From: Daniel Brockman Date: 2005-06-30T03:10:16+09:00 Subject: iterators and block arguments (was: yield does not take a block) "Adam P. Jenkins" writes: > Eric Mahurin wrote: > >> "Adam P. Jenkins" wrote: >> >>> Rather I have to wrap print in a block: >>> >>> myArray.each { |elem| print elem } >>> >>> Wouldn't it have been cool to just be able to write: >>> >>> myArray.each print Due to the deeply object-oriented nature of Ruby, I think your semantics (call a global method with each element as argument) are neither very feasible nor very useful. >> The reason you can't is because a method name by itself calls >> the method instead of returning the method object. > > Ok, fair enough. I would still prefer just > > myArray.each :print Unfortunately, there is no straightforward way to redefine `each', since every class has its own implementation. But you can define another method for sending a message to each element in a collection. module Enumerable def each! message, *args, &block each { |x| x.__send__ message, *args, &block } end end I'm sorry I couldn't think of a better name than `each!'. >> If you had to put () to make the call and the method name by itself >> returned the method object (I would have preferred that), you could >> do this: [...] I just want to say that I'm really glad to be able to leave out the parentheses. I prefer array.compact! over array.compact!() any day. > Cool, I didn't know about that. Still, > > myArray.each &method(:print) > myArray.each {|e| print e } > > Not much advantage really. I have been toying with the idea of binding parameters automatically. The general case would be to bind all parameters to, e.g., @1, @2, @3, and so on. But the most useful case is the first parameter. What if a single lone snail referred to the first parameter? Then you could write the above as myArray.each { print @ } I know from experience that this can make people cry out ``hideous!'' and ``get away from our language, you subversive Perl advocate.'' It can also make people say ``hey, that makes a lot of sense.'' (For the record, I don't advocate Perl, per se, but I do recognize that it was designed by a real linguist with good ideas.) I don't think automatical currying or automatic method boxing or anything like that makes sense in Ruby. But I do think this ipv4s.collect! { IPv4Address[@] } publics = ipv4s.select { @.public? } privates = ipv4s.select { @.private? } loopbacks = ipv4s.select { @.loopback? } looks better than this ipv4s.collect! { |x| IPv4Address[x] } publics = ipv4s.select { |x| x.public? } privates = ipv4s.select { |x| x.private? } loopbacks = ipv4s.select { |x| x.loopback? } looks better than this ipv4s.collect! { |ip| IPv4Address[ip] } publics = ipv4s.select { |ip| ip.public? } privates = ipv4s.select { |ip| ip.private? } loopbacks = ipv4s.select { |ip| ip.loopback? } Those repetitive microscopically-scoped parameter names don't add any explanatory value or increased readability --- they're just clutter. > Obviously you can do what you need to do in the current Ruby > implementation, it's just annoying and inconsistent in the same way > that it's annoying in Java that you need to box or unbox primitive > types depending on the context. Even the Java 1.5 syntactic sugar > for autoboxing doesn't completely hide the distinction. Coming from > programming in functional languages, Ruby's distinction between > blocks, closures, and methods seems similarly unnecessary at a > language level, though like Java's primitive/Object distinction, > it's probably a useful compromise for runtime efficiency. It doesn't sound like you have anything concrete to contribute. No, Ruby is not Haskell --- so what? -- Daniel Brockman