development

Closures across languages

September 28, 2005 11:10:47.729

MemoRanda compares block syntax between Smalltalk and Ruby. While I think Smalltalk's is simpler, they are very, very similar.

Comments

in the eye of the beholder

[Isaac Gouy] September 28, 2005 12:06:15.000


Blocks and Closures in Ruby: A Conversation with Yukihiro Matsumoto, Part III

multiples?

[Alan Knight] September 28, 2005 12:22:18.000

Actually, seeing Ruby's block syntax was the point where I stopped considering Ruby very seriously. So, using the yield syntax, how do I pass two blocks to a method? And how do I make it use a block that's in an instance variable rather than in a parameter (e.g. SortedCollection).

questions for the Ruby list

[Isaac Gouy] September 28, 2005 13:30:43.000

[] September 28, 2005 14:19:59.000

Alan: it is possible to pass two (or more) blocks to a method in Ruby, but it's pretty ugly:

def i_take_two_blocks(proc1, proc2)
  proc1.call
  proc2.call
end

i_take_two_blocks(lambda { puts "Block 1" },
                  lambda { puts "Block 2" })
The syntax is not as clear because Ruby doesn't have keyword messages. But it is possible, but not using yield, only with Proc#call (which is like Smalltalk's BlockContext#value). And you'd set a block to a variable in the exact same way:
@square_block = lambda { |x| x * x }
puts @square_block.call(12) # ==> 144

2 blocks

[ Alan Knight] September 28, 2005 19:08:40.000

Ah, ok. So basically the yield syntax and the way the blocks are shown passed into the methods, are shortcuts for the more general form involving the more "convoluted" call and lambda.

[Vincent Foley] September 28, 2005 20:16:52.246

Yes, the advantage of yield (or having the ampersand before the last parameter in the parameter list) is that you can just tack the {} or do/end pair after the method. Just syntactic sugar.

yield

[ Michael Lucas-Smith] September 28, 2005 20:46:24.352

Comment by Michael Lucas-Smith

Yes, yield is a short cut, but it is actually different to blocks in ruby. The yield block's are not blockclosure's. You cannot "pass" them around. You're actually pointing off to an anonymous method not a closure. If you remember Resilient with its fake blocks for speed and memory? The Ruby yield block's are the same as that.

Fortunately, the Ruby guy's realised the value of having real block closures as well, so they let you make them from a yield block with methods like lambda and toProc.

Unfortunately, doing multiple blocks passed to a method in a keyword syntax sort of way is just plain.. hard. It doesn't "fit" as well as it does in Smalltalk. That said, the majority of protocols they use in Ruby only have one block and the yield fits really really well in to that.

If you look through Smalltalk, the most common uses of two block arguments exist to handle exception cases. For example, detect:ifNone: - in ruby, instead of raising an exception on "Not Found" they just return nil. keysAndValuesDo:, inject:into: are obviously lacking but they have ways of doing that too that isn't -too- bad.

But all in all, I left Ruby feeling that may be they'd compromised their future potential with this design decision.

[Vincent Foley] September 28, 2005 21:00:29.577

Michael: keysAndValuesDo: and inject:into: are pretty easy in Ruby, since those don't take multiple blocks:

hash_table.each { |k, v|
  puts "#{k} ->#{v}"
}

[1, 2, 3, 4, 5].inject(0) { |sum, x| sum += x }
And you're right, the block part in a method call is not an object.

 Share Tweet This
-->