include Math
a = (:to_s).to_proc
puts a[123]
は"123"になるのに
b = (:sin).to_proc
puts b[1]
はエラーになります。
in `[]': private method `sin' called for 1:Fixnum (NoMethodError)
b=->x{sin(x)} 以外でsinをProc型にする簡単な記法はないでしょうか?
以下のようにProcの代わりにMethodではダメでしょうか?
b = Math.method(:sin) # => #<Method: Math.sin> b[123] # => -0.45990349068959124
ruby 2.0.0p195 (2013-05-14) [i386-mswin32_100]
QSはWindows7です。
でProcと表示されますよ。
>でProcと表示されますよ。
確かにそうですが、
p b[1.0]を実行すると
NoMethodError: undefined method `sin' for 1.0:Float
とエラーになります。
例えばsin定義を補えば実行可能なので。
include Math
class Fixnum
def sin
Math.sin self
end
end
b = (:sin).to_proc
p b[1] # 0.8414709848078965
p 1.sin # 0.8414709848078965
しかし使用する関数を毎回追記するのは大変ですね。
こんな感じのことがやってみたいのです。
a = Math.method(:sin)
b = ->x,y{x[y]}
p b[a,1.0] #=> 0.8414709848078965
a = (:sin).to_proc # => #<Proc:0x007f96b9121d10>
a[Math, 123] # => -0.45990349068959124
この感じからすると、aがProc、bがレシーバー、cが引数だとして強引に変換すると
a[b, c] は b.a(c) に相当する感じでしょうか。
なので a[123] は 123.a になり、a[Math, 123] は Math.a(123) になる、と。
よくよく調べてみると:
http://doc.ruby-lang.org/ja/1.9.3/class/Symbol.html#I_TO_PROC
>>
生成される Proc オブジェクトを呼びだす(Proc#call)と、 その第一引数の self という名前のメソッドを 残りの引数を渡して呼びだされます。
<<
ということなので、Symbol#to_procによって生成したProcをcallすると第1引数がレシーバーとして使われるのは仕様のようですね。
proc {} や Proc.new でProcを生成した場合、生成した時点でのselfがレシーバーとしてProcに固定される(言い方が変?)のでProc#callに渡された引数はすべてProcに渡る(レシーバーを明示する必要がない)けど、Symbol#to_procは完全にレシーバーから切り離された状態になるためProc#callの際には引数にレシーバーが必要、という感じでしょうか(まだはっきりとは理解できていない)。
>a = (:sin).to_proc # => #<Proc:0x007f96b9121d10>
>a[Math, 123] # => -0.45990349068959124
これはさすがに冗長な気がします。a[sin,123]とかa[:sin,123]とできると楽しそうですが。
http://melborne.github.io/2011/01/24/Ruby/
上記で「Rubyにおいてorとandは予約語なのでそのままの形では引数として渡すことができない。ここではこの問題を回避するため、orとandをMethodオブジェクト化して渡している。」
というのがあるので Math.method(:sin)というのが一番簡単なのかも知れませんね。
>|ruby|
class Array
def any_true
reduce method(:or), false
end
def all_true
reduce method(:and), true
end
private
def or(a,b)
a or b
end
def and(a,b)
a and b
end
end
||<
それって send のような気がします。
>||
a = Math
a[:sin, 123] # => NoMethodError
class Object; def [](*args); __send__(*args); end; end
a[:sin, 123] # => -0.45990349068959124
||<