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

(Tuis.) #1

22 | Chapter 1: Foundational Techniques


lambda_proc.call # => 3
proc_new_proc.call # =>

puts "Never reached"
end

block_test # => 4

The return statement inlambda_procreturns the value 3 from the lambda. Conversely,
the return statement inproc_new_procreturns from the calling function,block_test—
thus, the value 4 is returned fromblock_test. Theputsstatement is never executed,
because theproc_new_proc.call statement returns fromblock_test first.


Blocks can also be converted toProcs by passing them to a function, using&in the
function’s formal parameters:


def some_function(&b)
puts "Block is a #{b} and returns #{b.call}"
end

some_function { 6 + 3 }
# >> Block is a #<Proc:0x00025774@-:7> and returns 9

Conversely, you can also substitute aProc with& when a function expects a block:


add_3 = lambda {|x| x+3}
(1..5).map(&add_3) # => [4, 5, 6, 7, 8]

Closures


Closuresare created when a block orProcaccesses variables defined outside of its
scope. Even though the containing block may go out of scope, the variables are kept
around until the block orProcreferencing them goes out of scope. A simplistic exam-
ple, though not practically useful, demonstrates the idea:


def get_closure
data = [1, 2, 3]
lambda { data }
end
block = get_closure
block.call # => [1, 2, 3]

The anonymous function (thelambda) returned fromget_closurereferences the local
variable data, which is defined outside of its scope. As long as theblockvariable is in
scope, it will hold its own reference todata, and that instance ofdatawill not be
destroyed (even though theget_closurefunction returns). Note that each time
get_closure is called,data references a different variable (since it is function-local):


block = get_closure
block2 = get_closure

block.call.object_id # => 76200
block2.call.object_id # => 76170
Free download pdf