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