Hatena::Grouprubyist

Rubyをラクガク(正規表現編) RSSフィード

2006-06-22yield or call?

[]yieldとproc.callの違い yieldとproc.callの違い - Rubyをラクガク(正規表現編) を含むブックマーク はてなブックマーク - yieldとproc.callの違い - Rubyをラクガク(正規表現編) yieldとproc.callの違い - Rubyをラクガク(正規表現編) のブックマークコメント

昨日の続きから。というか、寝ぼけてました。ゴメンナサイ。pの使い方を間違ってる。式展開せずに使うべきだった。

def foo
        yield(1)
end

def bar
        yield(1,2)
end

foo{|p1,p2|
        p p1
        p p2
}

bar{|p1|
        p p1
}
1
nil
./method7.rb:14: warning: multiple values for a block parameter (2 for 1)
        from ./method7.rb:6
[1, 2]

fooメソッドのブロック引数にはp1=1,p2=nilが渡されている。barメソッドのブロック引数には[1,2]の配列が渡されている。昨日の最後の結果の"12"は[1,2].to_sの結果だった。ギャフン

yieldをProc.new.callに置換。

def foo
        Proc.new.call(1)
end

def bar
        Proc.new.call(1,2)
end

foo{|p1,p2|
        p p1
        p p2
}

bar{|p1|
        p p1
}
1
nil
./method8.rb:14: warning: multiple values for a block parameter (2 for 1)
        from ./method8.rb:6
[1, 2]

あれ?yieldの結果と変わらない…。fooはArgumentErrorがでることを期待したんだけど。Proc.new.callproc.callに変えてみる。

def foo
        proc.call(1)
end

def bar
        proc.call(1,2)
end

foo{|p1,p2|
        p p1
        p p2
}

bar{|p1|
        p p1
}
./method8.rb:2: warning: tried to create Proc object without a block
./method8.rb:9: wrong number of arguments (1 for 2) (ArgumentError)
        from ./method8.rb:9:in `call'
        from ./method8.rb:2:in `foo'
        from ./method8.rb:9

あ、怒られた。Proc.new.callproc.callは違うってことか。

Proc.new は、Proc#initialize が定義されていればオブジェクトの初期化のためにこれを呼び出します。このことを除けば、proc と同じです。

Rubyリファレンスマニュアル

とあるので、Proc#initializeを定義していなければprocと同じ振る舞いが期待できそうなんだけど…。ということで、Object#private_methodsを使ってみる。

def foo
        pr = Proc.new
        p pr.private_methods
        pr.call("foo")
end

foo{|arg|
        p arg
}
["getc", "initialize", "split", "rand", "fail", "putc", "gsub!", "String", "load", "exec", "sprintf", "iterator?", "proc", "catch"\
, "p", "sub", "syscall", "callcc", "test", "fork", "caller", "Array", "puts", "chop!", "format", "scan", "require", "block_given?"\
, "throw", "lambda", "warn", "gsub", "loop", "open", "initialize_copy", "singleton_method_added", "trap", "exit", "exit!", "gets",\
 "chomp!", "autoload", "system", "trace_var", "foo", "global_variables", "remove_instance_variable", "`", "chop", "printf", "Integ\
er", "singleton_method_removed", "abort", "readline", "eval", "sleep", "untrace_var", "local_variables", "select", "srand", "chomp\
", "raise", "print", "sub!", "Float", "method_missing", "singleton_method_undefined", "autoload?", "at_exit", "readlines", "set_tr\
ace_func"]
"foo"

う、たくさん表示されちゃったなぁ。Procのメソッドだけじゃなくて、Proc継承元(Object)のメソッドも含まれているみたい継承元のクラスのメソッドを引っ張ってきたくない場合は第1引数falseを指定するらしい。

p pr.private_methods(false)
[]
"foo"

う、また…。Proc#initializeは定義されていないように見えるけど、Proc.newprocの結果は違うという…。