1. ホーム
  2. ruby

[解決済み] Rubyでパラメータとしてメソッドを渡す

2022-06-08 02:17:59

質問

私はRubyを少しばかりいじろうとしています。そこで私は、「集合知のプログラミング」という本の中のアルゴリズム(Pythonで提供されている)をRubyで実装しようとしています。

第8章で、著者はパラメータとしてメソッドaを渡します。これはPythonでは動作するようですが、Rubyでは動作しません。

私はここでメソッド

def gaussian(dist, sigma=10.0)
  foo
end

で、これを別のメソッドで呼び出したい場合

def weightedknn(data, vec1, k = 5, weightf = gaussian)
  foo
  weight = weightf(dist)
  foo
end

エラーばかり

ArgumentError: wrong number of arguments (0 for 1)

どのように解決するのですか?

procオブジェクトが必要です。

gaussian = Proc.new do |dist, *args|
  sigma = args.first || 10.0
  ...
end

def weightedknn(data, vec1, k = 5, weightf = gaussian)
  ...
  weight = weightf.call(dist)
  ...
end

ただ、このようなブロック宣言ではデフォルトの引数を設定できないことに注意してください。 ですから、スプラッタを使い、プロックコード自体でデフォルトを設定する必要があります。


あるいは、このすべての範囲によりますが、代わりにメソッド名を渡す方が簡単かもしれません。

def weightedknn(data, vec1, k = 5, weightf = :gaussian)
  ...
  weight = self.send(weightf)
  ...
end

この場合、コードの完全な塊を渡すのではなく、オブジェクトに定義されたメソッドを呼び出しているに過ぎません。 これをどのように構造化するかによって、次のように置き換える必要があるかもしれません。 self.sendobject_that_has_the_these_math_methods.send


最後になりますが、メソッドからブロックをぶら下げることができます。

def weightedknn(data, vec1, k = 5)
  ...
  weight = 
    if block_given?
      yield(dist)
    else
      gaussian.call(dist)
    end
  end
  ...
end

weightedknn(foo, bar) do |dist|
  # square the dist
  dist * dist
end

しかし、あなたはここでもっと再利用可能なコードの塊を望んでいるようです。