3

(Redis に対して) 簡単な DSL を書こうとしていますが、 []+= 自分で定義したいと思います

私は持っている

def []=(key,val)
  @redis.zadd(@name,val,key)
end

そして私は定義したいと思います

def []+=(key,val)
  @redis.zincrby(@name,val,key)
end

しかし、私の理解では、Ruby は []= を自動的に与える "[]+=" 演算子を提供します。

この動作をオーバーライドする方法はありますか?明らかに、パイプライン モードでこれを実行できないため、これは望ましくありません。

4

2 に答える 2

6

いいえ、<operator>=Ruby では再定義できません。

実際の値にデリゲートするクラスに戻り値をラップして、非常に凝ってみることができます。このように、それらは実際の値のように動作しますが、たとえば+.

簡単な例を次に示します。

require 'delegate'
module Redis
  class Set
    class Value < SimpleDelegator
      def +(val)
        Increment.new(self, val)
      end
    end

    class Increment < SimpleDelegator
      attr_reader :increment
      def initialize(source, increment)
        super(source.__getobj__ + increment)
        @increment = increment
      end
    end

    def [](key)
      Value.new(@redis.not_sure_what(@name, key))
    end

    def []=(key,val)
      if val.is_a?(Increment)
        @redis.zincrby(@name,val.increment,key)
      else
        @redis.zadd(@name,val,key)
      end
    end
  end
end

これは単なる出発点です。たとえば、キーが同じであることを確認するなど、これよりも注意する必要があります。私の単純な例では、実際には...redis[:foo] = redis[:bar] + 1と同等ですredis[:foo] += 1

于 2012-06-15T22:26:13.407 に答える
2

いいえ。x[y] += zは正確に に展開されますx[y] = x[y] + z:

class << (object = Object.new)
  def [](key)
    puts "[#{key.inspect}]"
    key
  end

  def []=(key, value)
    puts "[#{key.inspect}] = #{value.inspect}"
    value
  end
end

# These are all equivalent
object['See?'] += " It's impossible."
object['See?'] = object['See?'] + " It's impossible."
object.[]=('See?', object.[]('See?').+(" It's impossible."))

# They all produce the same output:
# ["See?"]
# ["See?"] = "See? It's impossible."
# => "See? It's impossible."

別のメソッドを作成する必要があります。

于 2012-06-15T21:52:03.830 に答える