tags:

views:

404

answers:

4

I have a couple questions about Ruby's methods, procedures, and blocks that strike me as rather odd. They're not so much about syntax or function as the logic behind the decisions made.

Question 1:

Why is it that blocks can be passed to methods (e.g. each) but they cannot be assigned to a variable?

I know you can pass them around in procedures, i.e. p = Proc.new {...} (accessed with &p), but it doesn't make much sense to make the programmer go through these means.

Question 2:

Why is there a differentiation between methods and procedures?

For instance, I can accomplish the task of defining a function and calling that function in the following two ways:

def square(x)
    x**2
end

square(3)
=> 9

or

square = lambda {|x| x**2}
square.call(3)
=> 9

Why the differentiation? In Python for example both defining a function in the standard way and by square = lambda x: x**2 accomplish the same task of creating the function and assigning it to square.

+8  A: 

Question 1: Blocks are not objects, they are syntactic structures; this is why they cannot be assigned to a variable. This is a privilege reserved for objects.

Question 2: Methods are not objects, so they cannot receive messages. Inversely, procs and lambdas are objects, so they cannot be invoked like methods, but must receive a message that tells them to return a value on the basis of the parameters passed with the message.

Procs and Lambdas are objects, so they can receive the call message and be assigned to names. To summarize, it is being an object that makes procs and lambdas behave in ways you find odd. Methods and blocks are not objects and don't share that behavior.

Pinochle
Ruby claims everything is an object. Blocks should be objects in order to fit with that, and they can be passed as arguments, so they definitely act like objects in some ways.
Rusky
Blocks can be made to act like objects through creating an object to represent them, a proc or a lambda. Without that device, they are just syntactic structures.
Pinochle
There are block objects — that's the purpose of lambda {whatever}.
Chuck
Pinochle
This explanation makes sense, though I don't necessarily see the rational for these choices. Are these choices merely intended to honor the convention of the influential languages (i.e. smalltalk)?
David
The whole point of procs is to be able to have them persist in the lexical environment and pass them in to functions or methods as arguments. Blocks don't have that sort of independent "persistence" and are always attached to the statements where they are defined.
Pinochle
A: 

Because Ruby likes to add features haphazardly. Something like Lua or JavaScript combines those so that functions can be passed, stored in variables, etc. without the need for different types of functions.

Rusky
This answer is not helpful.
Chuck
It explains why. It gives examples of other ways things could have been done. How is that not helpful?
Rusky
It does not explain why. It's merely a slam against Ruby without any sort of factual basis — e.g., a quote from Yukihiro Matsumoto saying, "I like to add features haphazardly", or even an analysis of the history of the language showing that the features were indeed added haphazardly. It's the language equivalent of saying "Because their race is lazy and stupid." The actual explanation is probably somewhat more involved than this simple, prejudiced fairy tale.
Chuck
LOL; I assume this was meant to be ironic, coming from someone whose #1 SO answer tag is PHP. Very good.
Mike Woodhouse
+1  A: 

Methods are methods — that is, they're actions that an object can take in response to messages. They are not functions.

Blocks are closures — they're functions that close over the enclosing scope. They don't conceptually "belong to" a given object.

In some languages, methods are merely functions that are members of an object, but Ruby does not view them this way. Separating a method from its owning object is more akin to surgery than simple assignment. Ruby takes its object-orientation model from Smalltalk, the granddaddy of modern OO.

Chuck
+1  A: 

To some extent at least, methods are objects:

class ABC
  def some_method
  end
end
ABC.instance_method(:some_method) #=> #<UnboundMethod: ABC#some_method>

Further to that, there is a built-in class: Method, as documented here.

See also this: http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls

Haphazardly <bseg>, it does rather seem to bear out the everything-is-an-object thing. In this particular case, it just appears to take a little more digging to see.

(I really must make an effort to understand this better: I'm starting to think it's fundamental to getting a deeper understanding.)

Mike Woodhouse
Methods seem to take their objecthood from as instances of `Proc`. In the `ri` documentation for `Method`, the word 'method' is not used in the explanation, but 'proc' is. The two classes receive the same messages, but the difference is how they are invoked and in the fact that methods are defined within the namespace of another object, where procs need to receive the `call`method to be invoked and exist (persist, as I said before) independently of other objects.
Pinochle
Ahh, another difference... `Method` does not receive the `new` message, where `Proc` does. If methods are objects, they are not objects in a full sense ('full' meaning having all the characteristics we are used to seeing in objects).
Pinochle
That wikibooks link is helpful. Thanks.
David
Yes, that wikibooks link is very good.
Pinochle