0

Eloquent Ruby には、理解できないコード例があります。

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

@save_listener.call( self, path )2 つの引数を取るのはなぜですか? 保存されたブロックには、パラメーターが 1 つしかないように見えます|doc|。これは本のタイプミスですか、それとも私が見逃しているものがありますか?

このコードを入力して実行してみましたが、必要な数のパラメーターを追加でき、エラーは発生しないことがわかりました。しかし、この例に 2 つのパラメーターがある理由がまだわかりません。

4

2 に答える 2

8

Procこれは、との微妙な違いによるものLambdaです。コードのブロックでnew を作成するProcと、呼び出すときに必要な数の引数を渡すことができます。例えば:

proc = Proc.new {|a,b| a + b}
proc.arity #=> 2 -- the number of arguments the Proc expects
proc.call(4,8) #=> 12
proc.call(4,8,15,16,23,42) #=> 12

これらの引数を取り込んでいますが、ブロック内の変数に割り当てていません。

ただし、 aLambdaは引数の数を気にします。

proc = lambda {|a,b| a + b}
proc.arity #=> 2
proc.call(4,8) #=> 12
proc.call(4,8,15,16,23,42) #=> ArgumentError: wrong number of arguments (6 for 2)

Proc.callこれは、 が変数の並列代入と同様にメソッドの引数を代入するためです。

num1, num2 = 1,2 #=> num1 is 1, num2 is 2
num1, num2 = 1  #=> num1 is 1, num2 is nil
num1, num2 = 1,2,3,4,5 #=> num1 is 1, num2 is 2 and the rest are discarded

ただし、Lambdaこのようには機能しません。Lambda変数の代入よりもメソッド呼び出しのように機能します。

したがって、特定の数の引数のみを許可することが心配な場合は、 を使用してLambdaください。ただし、この例では、ブロックにパスを追加できる可能性があるため、aProcが最適です。

于 2012-06-07T16:47:39.023 に答える
1

この例では役に立たないように見えますが、ブロックに必要な数の引数を渡すことができ、それらは無視されます。この場合、引数なしで呼び出すこともできます。

于 2012-06-07T15:53:30.207 に答える