In Eloquent Ruby there’s a code example I don’t understand.
class Document
attr_accessor :save_listener
# most of the class omitted...
def on_save( &block )
@save_listener = block
end
def save( path )
File.open( path, 'w' ) { |f| f.print( @contents ) }
@save_listener.call( self, path ) if @save_listener
end
end
# usage
my_doc = Document.new( 'block based example', 'russ', '' )
my_doc.on_save do |doc|
puts "Hey, I've been saved!"
end
Why is it that @save_listener.call( self, path ) takes TWO arguments? The block that’s saved looks like it only has ONE parameter |doc|. Is this a typo in the book or is there something here I’m missing?
I even tried typing this code in and executing it and I found I can add as many parameters as I want and there wont be any errors. But I still don’t get why there are TWO parameters in this example.
This is due to a subtle difference between
ProcandLambda. When you create a newProcwith a block of code, you can pass as many arguments as you’d like to it when you call it. For instance:It is taking in those arguments but just not assigning them to any of the variables in your block.
However, a
Lambdacares about the number of arguments.The reason for this is because
Proc.callassigns the method’s arguments similar to parallel assignment of variables.However,
Lambdadoes not work like this.Lambdaacts more like a method call than a variable assignment.So, if you are worried about only allowing a certain number of arguments, use
Lambda. However, in this example, since there is a chance you can add a path to the block, aProcis best.