They say I write Ruby like Perl

Hi all,

I wrote some hierarchy handling classes in Node.rb
(Node.rb), and I’ve
been
told I write Ruby in Perl style. In future software, what could I do to
write
in a more Ruby-like fashion?

Thanks

SteveT

Steve L.
Author:

On Wednesday 07 December 2005 09:13 pm, Steve L. wrote:

Hi all,

I wrote some hierarchy handling classes in Node.rb
(Node.rb), and I’ve been
told I write Ruby in Perl style. In future software, what could I do to
write in a more Ruby-like fashion?

Thanks

SteveT

Whoops, the actual code is here:
http://www.troubleshooters.com/projects/Node.rb/downloads/0.02/Node.rb,
with
test progarm here:
http://www.troubleshooters.com/projects/Node.rb/downloads/0.02/testnode_parse.rb
and test data here:
http://www.troubleshooters.com/projects/Node.rb/downloads/0.02/test.otl

./testnode_parse < test.otl | less

Thanks

SteveT

Steve L.

[email protected]

On Dec 7, 2005, at 9:13 PM, Steve L. wrote:

Well with merely skimming your code, I would suggest replacing
camelCase method names with underscore_style ones. Other than that,
it doesn’t seem too perlish to me, I don’t see a mess of $'s anyway, :wink:

Hi –

On Thu, 8 Dec 2005, Steve L. wrote:

Hi all,

I wrote some hierarchy handling classes in Node.rb
(Node.rb), and I’ve been
told I write Ruby in Perl style. In future software, what could I do to write
in a more Ruby-like fashion?

For style things (avoiding camelCase for methods and local variables,
two-character indentation, etc.), you can look at (most of :slight_smile: the
Ruby code in the standard library. Also there’s a good style guide
at:
http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd=view;name=RubyCodingConvention
(not beyond dispute in every detail but very much in harmony with
traditional Ruby style).

Looking a bit at the code itself, I think there’s a certain amount of
verbosity that you could cut down on – and still be nice and clear
(which is an area where Ruby shines). For example, you have this:

def counttabs(s)
	answer = s.index(/[^\t]/)
	answer = 0 if not answer
	return answer
end

which could be:

def counttabs(s)
  s.index(/[^\t]/) || 0
end

(I’m not sure about the name – it’s not actually counting tabs – but
I’ll leave that to you :slight_smile: Of course there’s no imperative to make
things as short as they can be – but one thing I like about Ruby is
that one’s code tends to get more concise and to get more clear, as
one works on a project.

David


David A. Black
[email protected]

“Ruby for Rails”, forthcoming from Manning Publications, April 2006!

On 7-Dec-2005, at 9:23 PM, Steve L. wrote:

Thanks
Index of /projects/Node.rb/downloads/0.02/
test.otl

For:

def setAttributes(attribs) @attribs = attribs; end
def getAttributes() return @attribs; end
def hasAttributes() return @attribs != nil; end

You could use these (assuming you use @attributes as the instance
variable in place of @attribs)

attr_accessor :attributes
def has_attributes?
@attributes.empty?
end

and if you wanted to use a [] notation to access the attributes then
you could say

def []=(key, val)
@attributes[key] = v
end

def
@attributes[key]
end

Hope this helps,

Mike (Perl refugee)

Mike S. [email protected]
http://www.stok.co.uk/~mike/

The “`Stok’ disclaimers” apply.

On 12/7/05, Steve L. [email protected] wrote:

In future software, what could I do to write
in a more Ruby-like fashion?

This definitely doesn’t look like idiomatic Ruby, and here are a few
glaring things I can see:

  1. The general naming convention is lowercase with underscores for
    variables and methods. You have sort of a mix of “runitalltogether”
    variables, i.e. prevsibling, and then the CamelCase methods like
    insertSiblingAfterYou. Those should be prev_sibling and
    insert_sibling_after_you (though that last one is a bit too long.)

  2. Generally when initializing member variables from parameters in
    initialize, parallel assignment is used, i.e. “@name, @type, @value =
    name, type, value”.

  3. You have “class Node < Object”, which is redundant since classes
    subclass object by default:

irb(main):065:0> class Node;end
=> nil
irb(main):066:0> Node.superclass
=> Object

  1. There is not a single block used in your code. Ruby without blocks
    is like C++ without classes. In other words you can get by, but you
    lose A LOT of power and beautiful code. Most of the those loops could
    be iterators with blocks, especially this one:

for lineno in 1…lines.length
line = lines[lineno-1]

How about lines.each?

Ryan

Steve L. wrote:

SteveT
Thanks

SteveT

Steve L.
http://www.troubleshooters.com
[email protected]

Hi Steve,

Here are some quick pointers:

  • No need to subclass Object. All classes inherit from Object
    automatically
  • You don’t need most of the explict getters and setters. That’s what
    attr_accessor is for
  • Ditch the camel case
  • No need for semicolons
  • Rather than method names like “setParent”, use “parent=”.

Regards,

Dan

On Thu, 8 Dec 2005, Steve L. wrote:

Hi all,

I wrote some hierarchy handling classes in Node.rb
(Node.rb), and I’ve been
told I write Ruby in Perl style. In future software, what could I do to write
in a more Ruby-like fashion?

here are some thoughts:

 class Node < Object
         def initialize(nam, type, value)
                 super()
                 @name = nam
                 @type = type
                 @value = value
                 @attribs = {}
                 @parent = nil
                 @prevsibling = nil
                 @nextsibling = nil
                 @firstchild = nil
                 @lastchild = nil
         end

         attr_reader :name, :type, :value
         attr_writer :name, :type, :value
         attr_reader :parent, :prevsibling, :nextsibling, 

:firstchild, :lastchild

         def setAttributes(attribs) @attribs = attribs; end
         def getAttributes() return @attribs; end
         def hasAttributes() return @attribs != nil; end
         def setAttribute(key, value) @attribs[key] = value; end
         def getAttribute(key) return @attribs[key]; end
         def hasAttribute(key) return @attribs[key] != nil; end

i would condensed into

class Node

 ATTRIBUTES = %w(
   name type value attribs parent prevsibling nextsibling firstchild 

lastchild
).each{|a| attr_accessor a; alias_method “#{ a }?”, a}

 def initialize name, type, value, attribs = {}
   @name, @type, @value, @attribs = name, type, value, attribs
 end

don’t bother with access control - sometimes it’s needed (object
available on
the web) but sometimes it’s not. with it you are saying “my code has no
mistakes - you will not need access to these vars” by saying
‘read_only’. i’ve
probably fixed about 50 bugs in code where i had to subvert the access
control
by doing

obj.instance_var_set “@broken”, “fixed”

because of this kind of design. don’t use it where it’s not critical.

dont’ use get/set/has - use attr, attr=, attr?

     def setParent(parent)
             @parent = parent
             node = self
             while node.prevsibling
                     node = node.prevsibling
             end
             @parent.firstchild = node
             node = self
             while node.nextsibling
                     node = node.nextsibling
             end
             @parent.lastchild = node
             @parent
     end

could be

   def parent= parent
     parent.firstchild = oldest
     parent.lastchild = youngest
     @parent = parent
   end
   def oldest
     node = self
     node = node.prevsibling while node.prevsibling
     node
   end
   def youngest
     node = self
     node = node.nextsibling while node.nextsibling
     node
   end

which isn’t shorter - until the next time you write that code.

food for thought.

cheers.

-a

2005/12/8, Steve L. [email protected]:

Hi all,

I wrote some hierarchy handling classes in Node.rb
(Node.rb), and I’ve been
told I write Ruby in Perl style. In future software, what could I do to write
in a more Ruby-like fashion?

Hi Steve,

From the testing code, you have:

def rvExit(checker, level)
for i in 0…level
print “\t”
end
print checker.value
print “, Line “, checker.getAttribute(”_lineno”), “\n”
end

Which could be written as:

def reverse_exit(checker, level)
puts “#{”\t" * level}#{checker.value}, Line #{checker[:_line_number]}"
end

No need for the for loop, using print, getAttribute (use []= instead),
or appending a “\n” manually. And with all that saving, you can afford
to write out full method names!

Take a look at Test::Unit for running your tests:
http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/index.html

You could use it to automate all your tests, so you wouldn’t need
comments like “Change to b and watch what happens”.

Other things:

attr_reader :commentchar, :skipblanks
attr_writer :commentchar, :skipblanks

could be:

attr_accessor :comment_char, :skip_blanks

and:

def skipLine?(line)
regex_comment = Regexp.new(“^\s*” + @commentchar )
if @skipblanks and line =~ /^\s*$/
return true
elsif @commentchar and regex_comment.match(line)
return true
else
return false
end
end

could be:

def skip_line?(line)
return true if @skip_blanks and line =~ /^\s*$/
return @comment_char and /^\s*#{@comment_char}/.match(line)
end

You get the idea :slight_smile:

Good thread, thanks!

hth,
Douglas

Ryan L. [email protected] wrote:

CamelCase methods like insertSiblingAfterYou. Those should be
prev_sibling and insert_sibling_after_you (though that last
one is a bit too long.)

This recurring label “CamelCase” (or sometimes “camelCase”)
seems to come up a lot, and I can’t help thinking “camel” is
a reference to Perl… This is strange for me, as a veteran
Perl programmer.

I’ve always read/heard/been told that the preferred method of
naming variables in Perl a_var_name style. People who used
StudlyCaps or javaCaps were usually accused of having come from
either Visual Basic (or other Win32 tech) or Java, respectively.

Upon looking, I do see some Perl modules using StudlyCaps
(DirHandle, FileCache, ExtUtils, et al), but this is hardly more
prominent than Ruby’s MatchData, NilClass, FileTest, or
ObjectSpace.

I guess my comment is two-fold. One, can we really single out
Perl as the progenitor of this practice? And two, to state that
this naming scheme is not an endorsed practice for variable
names to my knowledge.

Cheers,
Tim H.

On Thursday 08 December 2005 01:37, Tim H. wrote:

Ryan L. [email protected] wrote:
This recurring label “CamelCase” (or sometimes “camelCase”)
seems to come up a lot, and I can’t help thinking “camel” is
a reference to Perl…

Why? CamelCase simply refers to the humps that appear in the middle of
words
when youUppercaseTheMiddleWord. At least that’s how I’ve always thought
of
it. I don’t think anyone’s pointing fingers at Perl. Hell, I came from
C++
and my first real Ruby code has all methods named in lowerCamelCase. -_-

Tim H. [email protected] wrote:

I guess my comment is two-fold. One, can we really single out
Perl as the progenitor of this practice? And two, to state
that this naming scheme is not an endorsed practice for
variable names to my knowledge.

Nor for method names.

Hell, I came from C++ and my first real Ruby code has all methods named in lowerCamelCase.

"There is no place in Ruby where lowerCamelCase is ever used. "
http://www.rubygarden.org/ruby?RubyStyleGuide

See Also slide 10 of Schroeder’s Ruby Course:

I Variables and methods should be written in snake_case
I Class Names should be written in CamelCase
I Constants should be written ALL_UPPERCASE

http://ruby.brian-schroeder.de/course/slides.pdf

CamelCase has been sporadically used since ancient times:

Camel case - Wikipedia

“CamelCase” is not explicitly mentioned in the style guide but the
examples show upper CamelCase for Class and Modules and lower case with
underscores at word boundaries for variables and methods:

http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd=view;name=RubyCodingConvention

On Thursday 08 December 2005 02:37 am, Tim H. wrote:
[clip]

This recurring label “CamelCase” (or sometimes “camelCase”)
seems to come up a lot, and I can’t help thinking “camel” is
a reference to Perl…

Hi Tim,

I had assumed it was called “CamelCase” because it had humps :slight_smile:

SteveT

Steve L.

[email protected]

Ryan L. wrote:

  1. The general naming convention is lowercase with underscores for
    variables and methods. You have sort of a mix of
    “runitalltogether” variables, i.e. prevsibling, and then the
    CamelCase methods like insertSiblingAfterYou. Those should be
    prev_sibling and insert_sibling_after_you (though that last one
    is a bit too long.)

Who says? Just a style/convention issue surely. Readability doesn’t
suffer, nor does execution.


Chris G.

Computers are only human.

Steve L. wrote on 12/8/2005 7:17 AM:

This recurring label “CamelCase” (or sometimes “camelCase”)
seems to come up a lot, and I can’t help thinking “camel” is
a reference to Perl…

I had assumed it was called “CamelCase” because it had humps :slight_smile:

the o’reilly “programming perl” book features a camel on the front.
just a guess :slight_smile:

On 12/8/05, Chris G. [email protected] wrote:

suffer, nor does execution.
Personally, I think readability does suffer. The wordier it gets, the
more I have to think. Why not a simple ‘append_sibling’?

Hi –

On Thu, 8 Dec 2005, Chris G. wrote:

suffer, nor does execution.
“Just”? :slight_smile: You’re right, though, in the sense that the parser
doesn’t enforce traditional style. You can write Ruby that looks like
lots of other languages. Then when you go back to those languages,
you can write variable names like_this because you now come from
Ruby…

Or just break the cycle and use the conventions of whatever language
you’re using when you’re using it :slight_smile:

David


David A. Black
[email protected]

“Ruby for Rails”, forthcoming from Manning Publications, April 2006!

I’d be interested to know why it is a language convention, and more
important why it is a lanaguage convention that from this thread it
seems rubyists vigorously insist upon? For those of us who were
“raised” with a language like Java (or as some on this list may say,
brain damaged ;-), lowerCamelCase seems more pleasing to the eye than
identifiers_with_underscores.