From: Daniel Brockman Date: 2005-06-30T08:20:27+09:00 Subject: Re: iterators and block arguments "Adam P. Jenkins" writes: > Daniel Brockman wrote: > >> 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. > > Not true at all. An OO language just has to support the concept of > a bound method reference. For example, in Python: > > # Here's an unbound method of the "file" class: > >>> file.write > > >>> In Ruby, IO.instance_method :write #=> # > # Here's a bound method > >>> sys.stdout.write > In Ruby, $stdout.method :write > # Here's how you can use a bound method reference > >>> w=sys.stdout.write > >>> w("Hello\n") > Hello > >>> In Ruby, w = $stdout.method :write w["Hello\n"] # or w.call "Hello\n" > The assignment to "w" creates a bound method reference, that not > only knows what method it refers to, but which object to send the > method call to. C# implements a similar concept, and there's no > fundamental reason that any OO language couldn't. Indeed, and Ruby does precisely this. > So I don't agree at all that OO and functional paradigms don't mix > in this regard. I think you missed the point. You originally suggested we have this foo.each print be equivalent to this: foo.each { |x| print x } Note how print is a ``global function,'' rather than a method on x. This is what I objected to, my point being that --- Ruby being a deeply object-oriented language --- it would be more natural for foo.each print to mean foo.each { |x| print.bind(x).call } Of course, as I said, a more useful form would be foo.each :print for foo.each { |x| x.__send__ :print } (I believe it's more common to invoke a method on each element of a collection than it is to give each element to a unary function.) >>>> 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. > > I'm just having an theoretical "could have been" discussion. I'm not > suggesting there's any practical way to change things at this point. I'm also having a mostly theoretical discussion. The above statement was not meant to criticize you. I said, ``unfortunately, you can't redefine `each', but look, you can define your own method in the following useful way.'' (But you cut that part out when quoting me.) >>> 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? > > Hey now, that's an unnecessary low blow. I apologize. I thought the above paraghaph looked like a pointless rant about how ``it would be better if it didn't suck.'' But I think I see where you are going with the analogy now: blocks are primitives and procs are Objects, and we should get rid of the primitives and stick to Objects unless it hurts performance? Simply put, you think that the yield keyword should be abolished along with the concept of ``block parameters'' --- right? So foo { ... } would be a method call with one regular parameter, and foo { ... }, { ... } would simply be a method call with two regular parameters. I don't think this is an insane proposal. But what about this syntax? foo { ... }.bar { ... } I don't think these alternatives are very attractive: (foo { ... }).bar { ... } foo({ ... }).bar { ... } Honest question: What are some use cases for multiple blocks? (Please don't tell me you want `if' to be a method.) [...] > When I first started programming in Ruby, I didn't understand why it > had separate concepts for blocks and closures, Please use one of the terms `lambda', `proc', or possibly `function' unless there is a specific reason to limit discussion to closures. def moomin foo = lambda { |x| x * 2 + 1 } lambda { |x| 7 / foo.call x } end bar = moomin Here, `foo' and `bar' are both lambdas, but only `bar' is a closure. > but I figured maybe it would become apparent after using it for a > while. One guess I made was that maybe the first version of Ruby > only had block/yield, and when it became apparent that blocks were > too limited, procs were added as a more general mechanism, but > block/yield had to stay for backward compatibility. After using > Ruby at work for several months now, I've come to the conclusion > that there is no good reason for the distinction at the language > level, though at an implementation level, I have seen it mentioned > that yield operates faster than Proc#call. I'd still be interested > though in hearing if there is another rationale for the distinction. Actually, the more I think about it, the more reasonable it seems. People, help: Why do we need blocks to be so damn special? -- Daniel Brockman