jweirich / one.net wrote:
> 
> Below I have abstracted some candidate "rules of thumb" for defining
> the Ruby Way.  They were all taken from responses to Joshua's request
> for help and based on a suggested change to his code.
> 
> NOTE: These are only *candidate* guidelines based on actual code
> improvement suggestions.  I did this to start a discussion, not to
> preemptively define the "Ruby Way".  In fact, I'm not sure *I* agree
> with all the suggestions below.  It is my hope that some good
> guidelines will be generated by consensus and discussion.
> 
> Ok, without further ado, here is a list of candidate guidelines ...

Thanks for the suggestions! Let's hope that this turns out to become a
lively discussion.
I'd really love to learn what the "Ruby Way" actually _is_ - in terms of
positive expressions.

> ----------------------------------------------------------------------
> I) Factor redundant code into a method

We should do this whatever the language, don't we?!

> ----------------------------------------------------------------------
> II) Use catch/throw for control structures, use rescue/raise for
>     communicating errors.
> 
>     ORIGINAL
>       class MyLoopExit < Exception; end
>       begin
>         loop do
>           # Note: prompt_and_read can raise MyLoopExit
>           first_name = prompt_and_read "First name"
>           last_name  = prompt_and_read "Last name"
>           phone      = prompt_and_read "Phone"
> 
>           myfile.puts first_name + "\t" + last_name + "\t" + phone
>       resure MyLoopExit
>       end
> 
>     BETTER
>       catch (:done) do
>         loop do
>           # Note: prompt_and_read can throw :done
>           first_name = prompt_and_read "First name"
>           last_name  = prompt_and_read "Last name"
>           phone      = prompt_and_read "Phone"
> 
>           myfile.puts first_name + "\t" + last_name + "\t" + phone
>         end
>       end

Well, that's interesting! (I didn't knew this is possible.) 
What would happen in case there's no :done in the caller?
The longer I think about it the more I like it.

-----   8< snip




> ----------------------------------------------------------------------
> IV) Take advantage of blocks to do automatic closing
> 
>     ORIGINAL
>         begin
>           myfile = File.open('phonespec.txt', 'a')
>           # ...
>         ensure
>           myfile.close
>         end        file = File.open
> 
>     BETTER
>         File.open('phonespec.txt', 'a') do |myfile|
>           # ...
>         end
> 

For 'line oriented input' i like IO.foreach:

IO.foreach( "somefile" ) { | line |
    # do something with line
}

Or "File.foreach" if you prefer that (see below).
"readlines" is a fine method, too.
In that case you don't need another degree of nesting to do 

myfile.each { | line |
    # do something with line
}	

or  

myfile.each do | line |
    # ...
end

BTW, which of these is more "Ruby wayish"?


> ----------------------------------------------------------------------
> V) Avoid Unnecessary Globals
> VI) Use true/false to represent booleans, not 1/0.
> VII) Use loop do ... end for infinite loops

I second that - what ever the language. 

> ----------------------------------------------------------------------
> VIII) Use File.open rather than IO.open or just plain open.
>       (Applies to readlines and other methods in File as well).
> 
>     ORIGINAL
>       open ("phonespec.txt")
>       # or
>       IO.open ("phonespec.txt")
> 
>     BETTER
>       File.open ("phonespec.txt")
>       loop do
>         # loop stuff ...
>       end

OK, but... what's the (pragmatic?) reason for this?


> --
> -- Jim Weirich     jweirich / one.net    http://w3.one.net/~jweirich
> ---------------------------------------------------------------------
> "Beware of bugs in the above code; I have only proved it correct,
> not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

I really like that citation! 


Happy rubying - in the "Ruby Way" whatever that is (but we'll find out)

Stephan