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
.
When using parameters prefixed with ampersands, passing a block to a method results in a proc in the method's context. Procs behave like blocks, but they can be stored in a variable. Lambdas are procs that behave like methods, meaning they enforce arity and return as methods instead of in their parent scope.
Procs are objects, blocks are notA proc (notice the lowercase p) is an instance of the Proc class. This lets us call methods on it and assign it to variables. Procs can also return themselves. In contrast, a block is just part of the syntax of a method call.
The &block is a way of sending a piece of Ruby code in to a method and then evaluating that code in the scope of that method. In your example code above it means a partial named cart will be rendered in a div.
A Proc object is an encapsulation of a block of code, which can be stored in a local variable, passed to a method or another Proc, and can be called. Proc is an essential concept in Ruby and a core of its functional programming features.
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.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With