Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1
Ruby Foundations | 21

add_3.to_proc # => #<Proc:0x00024b08@-:6>
add_3.call(5) # => 8
# Method#[] is a handy synonym for Method#call.
add_3[5] # => 8

There are two ways to obtain an unbound method. We can callinstance_methodon
the class object:


add_unbound = Fixnum.instance_method(:+)
add_unbound # => #<UnboundMethod: Fixnum#+>

We can also unbind a method that has already been bound to an object:


add_unbound == 3.method(:+).unbind # => true
add_unbound.bind(3).call(5) # => 8

We can bind theUnboundMethod to any other object of the same class:


add_unbound.bind(15)[4] # => 19

However, the object we bind tomustbe an instance of the same class, or else we get
aTypeError:


add_unbound.bind(1.5)[4] # =>
# ~> -:16:in `bind': bind argument must be an instance of Fixnum (TypeError)
# ~> from -:16

We get this error because+is defined inFixnum; therefore, theUnboundMethodobject
we receive must be bound to an object that is akind_of?(Fixnum). Had the+method
been defined inNumeric(from which bothFixnumandFloatinherit), the preceding
code would have returned5.5.


Blocks to Procs and Procs to blocks


One downside to the current implementation of Ruby: blocks are not alwaysProcs,
and vice versa. Ordinary blocks (created withdo...endor{}) must be attached to a
method call, and are not automatically objects. For example, you cannot saycode_
block = { puts "abc" }. This is what theKernel#lambdaandProc.newfunctions are for:
converting blocks toProcs.*


block_1 = lambda { puts "abc" } # => #<Proc:0x00024914@-:20>
block_2 = Proc.new { puts "abc" } # => #<Proc:0x000246a8@-:21>

There is a slight difference betweenKernel#lambdaandProc.new. Returning from a
Proccreated withKernel#lambdareturns the given value to the calling function;
returning from aProccreated withProc.newattempts to returnfromthe calling func-
tion, raising aLocalJumpError if that is impossible. Here is an example:


def block_test
lambda_proc = lambda { return 3 }
proc_new_proc = Proc.new { return 4 }

*Kernel#proc is another name forKernel#lambda, but its usage is deprecated.

Free download pdf