2

クラスで結合Proc#*と分離Proc#+を定義しようとしています。Procレシーバーと引数のアリティが異なる場合、エラーが発生するはずです。それ以外の場合は、それぞれ結合/分離である proc オブジェクトを返す必要があります。次のように実装しました。

class Proc
  def * other
    raise ArgumentError, "Arity does not match" unless arity == other.arity
    ->(*args){call(*args) and other.call(*args)}
  end
  def + other
    raise ArgumentError, "Arity does not match" unless arity == other.arity
    ->(*args){call(*args) or other.call(*args)}
  end
end

これは単純なプロシージャでうまく機能します:

p = ->x{x % 2 == 0} * ->x{x % 3 == 0}
p.call(2) # => false
p.call(6) # => true

しかし、これらのメソッドの結果をさらに構築しようとすると、エラーが発生します。

q = p * ->x{x % 5 == 0}
# => Error, Arity does not match

これは、のアリティが->x{x % 5 == 0}is1であるのに対し、のアリティはp私の実装-1によるものであるためです。call(*args)

メソッドを作成して再帰的Proc#*に動作させる良い方法はありますか?Proc#+


定義からを削除するraise ...と機能しますが、アリティが異なるプロシージャが結合/分離されたときに、誤解を招くエラー メッセージが返されます。たとえば、raise ...上記の定義からパーツが削除されたとします。

p = ->x{x % 2 == 0} * ->x, y, z{x % 3 == 0}

その後Proc#*、エラーは発生しませんが、有効な proc オブジェクトが返されます。pただし、その一部は 1 つの引数を必要とし、別の部分は 3 つの引数を必要とするため、有効な方法で引数を渡す方法がありません。

p.call(2) # => error

を発生させ、次のようArgumentErrorに言います。

Wrong number of arguments

しかし、作成時に実際に発生した間違いはp、任意の数の引数で満たすことができず、エラー メッセージが誤解を招く可能性があります。そのため、raise ...チェックを追加しました。raise ...それを機能させる唯一の方法を削除していますか?

4

2 に答える 2

1

raise可変数の引数をとるプロシージャは有効に呼び出すことができますが、アリティ値が異なるため、おそらく削除する必要があると思います。例えば

p = ->(a) {} * (a, *args) {}
p.call(1)   # valid
p.call(1,2) # invalid

おそらく解決策は、返されたラムダ内のエラーメッセージを改善することでしょうか? 何かのようなもの

lambda(*args) do
  raise "wrong number of arguments for left lambda" if (arity < 0 && arity.abs - 1 <= args.size) || (arity > 0 && arity != args.size)
  # etc (not sure those cases are exactly right)
  call(*args) and other.call(*args)
end

parametersメソッドを使用する方が簡単な場合があります。これは、必須、オプション、およびスプラットのパラメーターを詳しく説明します。結果のラムダを呼び出すことができず、その場合に作成時にエラーをスローすることができないかどうかを簡単に確認できるようにする必要があります。

于 2013-10-08T23:22:18.943 に答える