|
|
 |
 |
 |
 |
Ruby Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
Replacement idiom for "list_or_nil.to_a"?
Many scripting languages, including Ruby, will "do nothing gracefully" when asked to iterate through an empty list. That is, they iterate NO times. However, many Ruby methods do not return empty lists when nothing is found. Instead, they return nil. This means that idioms such as: list_or_nil.each do |value| ... end will fail. As a workaround, I've been using this idiom: list_or_nil.to_a.each do |value| ... end However, I gather that this will soon be deprecated: http://www.megasolutions.net/ruby/to_a-68350.aspx This page suggests putting the list in brackets: [list_or_nil] but this doesn't solve MY problem: >> list_or_nil=nil => nil >> [list_or_nil] => [nil] because the loop will now run once with the value nil. I really dislike having to wrap the iteration block in an "if" block: if list_or_nil list_or_nil.each do |value| ... end end and this is only marginally better: list_or_nil.each do |value| ... end if list_or_nil I suppose I could define my own to_a method for nil, but that seems a bit questionable, as well. So, is there a Better Way To Do It? -r -- http://www.cfcl.com/rdm Rich Morin http://www.cfcl.com/rdm/resume r@cfcl.com http://www.cfcl.com/rdm/weblog +1 650-873-7841 Technical editing and writing, programming, and web development
> list_or_nil.each do |value| > ... > end
If you really want the extra loop in each just to find out that nothing has to be done, you could also do: (list_or_nil || []).each do |value| ... end
On 25/05/07, Rich Morin <r@cfcl.com> wrote: > I suppose I could define my own to_a method for nil, > but that seems a bit questionable, as well. So, is > there a Better Way To Do It?
If you're going to get a list or nil then I find it nice to wrap it in the Kernel#Array() method. It will convert a nil to a an empty array but will leave an array untouched: irb(main):001:0> Array(nil) => [] irb(main):002:0> Array([1,2,3]) => [1, 2, 3] Farrel
On 25.05.2007 12:13, Rich Morin wrote:
> Many scripting languages, including Ruby, will "do nothing > gracefully" when asked to iterate through an empty list. > That is, they iterate NO times. > However, many Ruby methods do not return empty lists when > nothing is found. Instead, they return nil. This means > that idioms such as: > list_or_nil.each do |value| > ... > end > will fail. As a workaround, I've been using this idiom: > list_or_nil.to_a.each do |value| > ... > end > However, I gather that this will soon be deprecated: > http://www.megasolutions.net/ruby/to_a-68350.aspx > This page suggests putting the list in brackets: > [list_or_nil] > but this doesn't solve MY problem: > >> list_or_nil=nil > => nil > >> [list_or_nil] > => [nil] > because the loop will now run once with the value nil. > I really dislike having to wrap the iteration block in > an "if" block: > if list_or_nil > list_or_nil.each do |value| > ... > end > end > and this is only marginally better: > list_or_nil.each do |value| > ... > end if list_or_nil > I suppose I could define my own to_a method for nil, > but that seems a bit questionable, as well. So, is > there a Better Way To Do It?
Probably. How do you like list_or_nil and list_or_nil.each do |x| ... end Or irb(main):001:0> class NilClass irb(main):002:1> def each; self; end irb(main):003:1> include Enumerable irb(main):004:1> end => NilClass irb(main):005:0> nil.each {|x| puts x} => nil irb(main):006:0> ? Kind regards robert
Rich Morin wrote: > will fail. As a workaround, I've been using this idiom: > list_or_nil.to_a.each do |value| > ... > end > However, I gather that this will soon be deprecated:
Object#to_a will be deprecated but not nil.to_a, so the idiom you have above works just fine. It will break if list_or_nil is a non-array non-nil value but I think that's as it should be. Daniel
On 5/25/07, Robert Klemme <shortcut@googlemail.com> wrote: > irb(main):001:0> class NilClass > irb(main):002:1> def each; self; end > irb(main):003:1> include Enumerable > irb(main):004:1> end > => NilClass > irb(main):005:0> nil.each {|x| puts x} > => nil > irb(main):006:0>
That hack will also make nil.to_a => []. -- Chris Carter concentrationstudios.com brynmawrcs.com
On May 25, 8:05 am, "Chris Carter" <cdcar@gmail.com> wrote: > On 5/25/07, Robert Klemme <shortcut @googlemail.com> wrote: > > irb(main):001:0> class NilClass > > irb(main):002:1> def each; self; end > > irb(main):003:1> include Enumerable > > irb(main):004:1> end > > => NilClass > > irb(main):005:0> nil.each {|x| puts x} > > => nil > > irb(main):006:0> > That hack will also make nil.to_a => [].
If the code will be reusable, that's a little too risky. It would be interesting however for an object to exist, say Void. Something like: class Void def method_missing(*args) void end end def void $void ||= Void.new end (list_or_nil || void).each { |x| p x } Though, a core implementation of Void would be much more efficient b/c it would not need to even bother with method_missing, and just know to return void and move on. Hmmm... actually this has been discussed in another context before (Hash lookup) as Null. Looks like another good reason for it. T.
Thanks for the suggestions! Here's a summary, with comments: > foo.to_a.each {|value| ... }
This is what I was using. It's nice to know that it's not going away, after all. > foo.to_a.each {|value| ... } if foo
This moves the "if" clause away from the iteration, which might make it harder to see. Also, it evaluates foo twice (could duplicate side-effects if foo is a method or be a performance issue id evaluating foo is expensive). > foo and foo.each {|value| ... }
A bit wordy and obscure. Also, it evaluates foo twice. > class NilClass > def each; self; end > include Enumerable > end > foo.each {|value| ... }
This shortens the usage code, but I don't like playing with the definition of NilClass. Specifically, this might confuse a human reader or get in the way of code that already expects the current behavior. > (foo || []).each {|value| ... }
This smells like line-noise, but is otherwise quite adequate. > (foo || VOID).each {|value| ... } > (foo || void).each {|value| ... }
Aside from the line-noise issue, these seem similar to me. Both require the use of a supplementary definition, however, which the reader might have to loop up. > Array(foo).each {|value| ... }
This seems like an improvement, from a clarity standpoint. My preference, at this point, is for either: > foo.to_a.each {|value| ... } > Array(foo).each {|value| ... }
I think I prefer the latter, from a clarity standpoint. Also, the fact that to_a is being deprecated in other contexts might confuse some readers. If foo is a BIG array, there might be performance differences between these two, but I'm loathe to second-guess interpreter implementation issues of this sort... -r -- http://www.cfcl.com/rdm Rich Morin http://www.cfcl.com/rdm/resume r@cfcl.com http://www.cfcl.com/rdm/weblog +1 650-873-7841 Technical editing and writing, programming, and web development
On 25.05.2007 18:23, Rich Morin wrote:
> Thanks for the suggestions! Here's a summary, with comments: >> foo.to_a.each {|value| ... } > This is what I was using. It's nice to know that it's not > going away, after all. >> foo.to_a.each {|value| ... } if foo > This moves the "if" clause away from the iteration, which > might make it harder to see. Also, it evaluates foo twice > (could duplicate side-effects if foo is a method or be a > performance issue id evaluating foo is expensive). >> foo and foo.each {|value| ... } > A bit wordy and obscure. Also, it evaluates foo twice.
This is an issue only if foo is a method that does a complex calculation.
>> class NilClass >> def each; self; end >> include Enumerable >> end >> foo.each {|value| ... } > This shortens the usage code, but I don't like playing with > the definition of NilClass. Specifically, this might confuse > a human reader or get in the way of code that already expects > the current behavior. >> (foo || []).each {|value| ... } > This smells like line-noise, but is otherwise quite adequate. >> (foo || VOID).each {|value| ... } >> (foo || void).each {|value| ... } > Aside from the line-noise issue, these seem similar to me. > Both require the use of a supplementary definition, however, > which the reader might have to loop up. >> Array(foo).each {|value| ... } > This seems like an improvement, from a clarity standpoint. > My preference, at this point, is for either: >> foo.to_a.each {|value| ... }
This might create another object which might impose a performance hit. >> Array(foo).each {|value| ... } > I think I prefer the latter, from a clarity standpoint. Also, > the fact that to_a is being deprecated in other contexts might > confuse some readers. > If foo is a BIG array, there might be performance differences > between these two, but I'm loathe to second-guess interpreter > implementation issues of this sort...
There will likely be a performance hit if foo is something different than an array because then it will have to be converted to an array. Kind regards robert
On May 25, 12:23 pm, Rich Morin <r@cfcl.com> wrote:
> Thanks for the suggestions! Here's a summary, with comments: > > foo.to_a.each {|value| ... } > This is what I was using. It's nice to know that it's not > going away, after all. > > foo.to_a.each {|value| ... } if foo > This moves the "if" clause away from the iteration, which > might make it harder to see. Also, it evaluates foo twice > (could duplicate side-effects if foo is a method or be a > performance issue id evaluating foo is expensive). > > foo and foo.each {|value| ... } > A bit wordy and obscure. Also, it evaluates foo twice. > > class NilClass > > def each; self; end > > include Enumerable > > end > > foo.each {|value| ... } > This shortens the usage code, but I don't like playing with > the definition of NilClass. Specifically, this might confuse > a human reader or get in the way of code that already expects > the current behavior. > > (foo || []).each {|value| ... }
A very common idiom in Ruby however. > This smells like line-noise, but is otherwise quite adequate. > > (foo || VOID).each {|value| ... } > > (foo || void).each {|value| ... } > Aside from the line-noise issue, these seem similar to me. > Both require the use of a supplementary definition, however, > which the reader might have to loop up.
This is a hypothetical. The significant advantage of "void" would come from a core implementation which would be much more efficient than []. (A "void" object would also have some other good uses however. hint hint matz ;) T.
list_or_nil.each do |value| unless list_or_nil.nil? -- Anbal Rojas http://www.rubycorner.com http://www.hasmanydvelopers.com On May 25, 6:13 am, Rich Morin <r@cfcl.com> wrote:
> Many scripting languages, including Ruby, will "do nothing > gracefully" when asked to iterate through an empty list. > That is, they iterate NO times. > However, many Ruby methods do not return empty lists when > nothing is found. Instead, they return nil. This means > that idioms such as: > list_or_nil.each do |value| > ... > end > will fail. As a workaround, I've been using this idiom: > list_or_nil.to_a.each do |value| > ... > end > However, I gather that this will soon be deprecated: > http://www.megasolutions.net/ruby/to_a-68350.aspx > This page suggests putting the list in brackets: > [list_or_nil] > but this doesn't solve MY problem: > >> list_or_nil=nil > => nil > >> [list_or_nil] > => [nil] > because the loop will now run once with the value nil. > I really dislike having to wrap the iteration block in > an "if" block: > if list_or_nil > list_or_nil.each do |value| > ... > end > end > and this is only marginally better: > list_or_nil.each do |value| > ... > end if list_or_nil > I suppose I could define my own to_a method for nil, > but that seems a bit questionable, as well. So, is > there a Better Way To Do It? > -r > --http://www.cfcl.com/rdm Rich Morinhttp://www.cfcl.com/rdm/resume r@cfcl.comhttp://www.cfcl.com/rdm/weblog +1 650-873-7841 > Technical editing and writing, programming, and web development
|
 |
 |
 |
 |
|