Block in Ruby compared to Smalltalk
Asked Answered
C

3

11

What does block in Ruby mean? It looks similar with Smalltalk, but you can't send messages to it.

For example, in smalltalk:

[:x | x + 3] value: 3

returns 6. But in ruby:

{|x| x + 3}.call 3

will cause SyntaxError.

Well, you can pass messages to lambda in ruby, though:

irb(main):025:0> ->(x){x+3}.call 3
=> 6

So in Ruby, block is not a block, but lambda is a block? Is this true? I mean, are there any differences between ruby lambda and smalltalk block? If this is true, then what is a ruby block?

Update:

From the comment and answer below, together with some googling, I guess I have more understanding of Ruby block. In Ruby, usually a piece of code evaluates an value, and every value is an object. But, block doesn't evaluate an value. So it's not an object. Instead it can act as part of an object. For example, in {|x| x + 3} can act as a part of the object proc {|x| x + 3 }.

But it did confuse me. In smalltalk, almost every expression can be divided into objects (binding to variables are exceptions). It seems in Ruby, there are more exceptions.

Crinkleroot answered 6/6, 2010 at 10:42 Comment(2)
I believe you're missing a yield. I'm not super knowledgable on blocks though..Aalesund
Thanks for pointing to yield. I found this related question: #764634Crinkleroot
R
15

First and the most important thing that Ruby block isn't: an object. It is a syntactic construct, and also obviously has an equivalent implementation - but it is not an object, and thus can't receive messages. Which makes your example of

{|x| x + 3}.call 3

ungrammatical. Lambdas, procs - those are objects that wrap a block, and have a call method which executes the block.

Thus, a block is simply a piece of code which can be passed to a method, outside the argument list - no more, no less. If you pass it to Proc.new constructor, for example, it will wrap it and give you an object you can handle:

Proc.new {|x| x + 3}.call 3
Roussillon answered 6/6, 2010 at 10:57 Comment(4)
I thought mistakenly that Ruby block is some object we pass to the method as its argument. Thanks for clarifying it.Crinkleroot
So if I understand correctly it also mean that when you pass a ruby block as parameter to a method the VM somehow wrap it into a Proc.new?Curd
I don't know the innards, but I do believe that is incorrect - unless you make it so with the & mark. Implicit block (no wrapping): def yield3; yield 3; end; yield3() {|x|puts x}; - Explicit proc (no block passed): def callprocwith3(func); func.call(3); end; callprocwith3(Proc.new {|x|puts x}) - Converted to proc (wrapping a block): def callblockwith3(&func); func.call(3); end; callblockwith3() {|x|puts x}; - all do roughly the same thing, but the way you handle it is different. I could have left off the empty parens (), but this way it's clearer what is an argument and what isn't.Roussillon
@Curd No, you cannot pass a ruby block as a parameter to a method. And Ruby will report an error instead of converting the block to a Proc instance automatically. It's strange. But in Ruby, block is not an object. And you can not pass it to a method as an argument. I think it's better to avoid the words "send a block", because you cannot "send" it (as in the sense of sending an object). Consider blocks as some kind of keywords or syntax sugar to associate a piece of code with something else. At least this consideration makes my brain more comfortable.Crinkleroot
C
1

A precision:

I would even say that in smalltalk even binding is made up with object. Think of the MethodContext. What you are actually doing is to store the object in the MethodContext. So

a := Object new

Can be rewrite in:

thisContext at: 1 put: Object new.

But obviously you wont write it this way since you need to know were are the temps variable.

Curd answered 7/6, 2010 at 8:34 Comment(0)
H
1

A block in Smalltalk is an anonymous object. Syntactically, it is delimited by a [ ... ] pair.

When evaluated, it will return the last expression evaluated within itself, and there are lots of methods in its protocol.

Here are the Class comments for Blocks from a Smalltalk (in this instance, Dolphin Smalltalk 6.03 Community Edition)

"Blocks encapsulate a sequence of statements to be performed at a later time. Blocks may capture (or "close over") runtime state, such as the values of temporary variables, from the enclosing lexical scope at the point where they are created. When evaluated a block executes as if in the lexical scope in which it was defined, except that blocks may have arguments that are bound at the time of evaluation. Blocks may be passed as arguments with messages to other objects and evaluated by those objects when appropriate, and thus form a very powerful and generic "pluggability" mechanism that is a core feature which provides much of the power of Smalltalk".

By contrast, a block in Ruby is simply a parameter string. It's syntactically delimited by a { ... } pair, but it has no methods of its own.

Hellion answered 13/11, 2015 at 2:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.