ビットパーティーに遅れてが、私はそれを周りいじるしてきたあなただけの中置演算子を作成するために、演算子オーバーロードを使用することができますpythonのように(ただし、もう少し作業が必要です)、構文はになります。
最初に、すばやく汚れたコピーを貼り付けてInfixで再生します:
class Infix def initialize*a,&b;raise'arguments size mismatch'if a.length<0||a.length>3;raise'both method and b passed'if a.length!=0&&b;raise'no arguments passed'if a.length==0&&!b;@m=a.length>0? a[0].class==Symbol ? method(a[0]):a[0]:b;if a.length==3;@c=a[1];@s=a[2]end end;def|o;[email protected];o.class==Infix ? self:@m.(@s,o)else;raise'missing first operand'end end;def coerce o;[Infix.new(@m,true,o),self]end;def v o;Infix.new(@m,true,o)end end;[NilClass,FalseClass,TrueClass,Object,Array].each{|c|c.prepend Module.new{def|o;o.class==Infix ? o.v(self):super end}};def Infix*a,&b;Infix.new *a,&b end
#
[OK]を
ステップ1:Infix
クラスを作成
class Infix
def initialize *args, &block
raise 'error: arguments size mismatch' if args.length < 0 or args.length > 3
raise 'error: both method and block passed' if args.length != 0 and block
raise 'error: no arguments passed' if args.length == 0 and not block
@method = args.length > 0 ? args[0].class == Symbol ? method(args[0]) : args[0] : block
if args.length == 3; @coerced = args[1]; @stored_operand = args[2] end
end
def | other
if @coerced
other.class == Infix ? self : @method.call(@stored_operand, other)
else
raise 'error: missing first operand'
end
end
def coerce other
[Infix.new(@method, true, other), self]
end
def convert other
Infix.new(@method, true, other)
end
end
ステップ2:|
方法と3つの特別な場合(true
を持っていないすべてのクラスを修正し、false
、nil
)(注:ここに任意のクラスを追加することができます。これはおそらく正常に動作します)
[ NilClass, FalseClass, TrueClass,
Float, Symbol, String, Rational,
Complex, Hash, Array, Range, Regexp
].each {|c| c.prepend Module.new {
def | other
other.class == Infix ? other.convert(self) : super
end}}
ステップ3:それらを使用する(間隔は関係ありません)::5のいずれかの方法
# Lambda
pow = Infix.new -> (x, y) {x ** y}
# Block
mod = Infix.new {|x, y| x % y}
# Proc
avg = Infix.new Proc.new {|x, y| (x + y)/2.0}
# Defining a method on the spot (the method stays)
pick = Infix.new def pick_method x, y
[x, y][rand 2]
end
# Based on an existing method
def diff_method x, y
(x - y).abs
end
diff = Infix.new :diff_method
ステップ4であなたの演算子を定義
2 |pow| 3 # => 8
9|mod|4 # => 1
3| avg |6 # => 4.5
0 | pick | 1 # => 0 or 1 (randomly chosen)
あなたもちょっとみかんカレーことができます。 を(これは最初のオペランドでのみ機能します)
diff_from_3 = 3 |diff
diff_from_3| 2 # => 1
diff_from_3| 4 # => 1
diff_from_3| -3 # => 6
この小さな方法では、 .new
を使用せずに挿入辞(または実際に任意のオブジェクト):
def Infix *args, &block
Infix.new *args, &block
end
pow = Infix -> (x, y) {x ** y} # and so on
すべてのことを行うに残って、これは
P.S.を助けた
希望のモジュールでそれを包むありますあなたが優先としたい任意の他の組み合わせのためにa **op** b
、方向性のためにa <<op>> b
、a -op- b
、a >op> b
とa <op<b
のようなものを持っている事業者とおよそマックが、論理演算子(|
、&&
との最初のオペランドとしてtrue
、false
とnil
を使用する際に注意することができます、not
など)を返します。
たとえば、訂正しないとfalse |equivalent_of_or| 5 # => true
となります。私はルビーの例を見つけることができませんが、私はいずれかを記述しようとしたではない認める
# pp prints both inputs
pp = Infix -> (x, y) {"x: #{x}\ny: #{y}\n\n"}
[ true, false, nil, 0, 3, -5, 1.5, -3.7, :e, :'3%4s', 'to',
/no/, /(?: [^A-g7-9]\s)(\w{2,3})*?/,
Rational(3), Rational(-9.5), Complex(1), Complex(0.2, -4.6),
{}, {e: 4, :u => 'h', 12 => [2, 3]},
[], [5, 't', :o, 2.2, -Rational(3)], (1..2), (7...9)
].each {|i| puts i.class; puts i |pp| i}
:
最後に、第1および第2のオペランドの両方として、すべての組み込みクラスの例束を確認するために、これを実行します私の側のコードはまだ – kamaradclimber
これは_parser_の機能なので不可能です。 – mudasobwa