我正在尝试编写一个简单的DSL(针对Redis),我想定义[] + =我自己
我有
def []=(key,val)
@redis.zadd(@name,val,key)
end
我想定义
def []+=(key,val)
@redis.zincrby(@name,val,key)
end
但我的理解是Ruby提供了“[] + =”运算符自动赋予[] =
有没有办法克服这种行为 显然我不想要这个,因为我不能,比如说,在管道模式下运行它
答案 0 :(得分: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
...
答案 1 :(得分: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."
您必须创建一个单独的方法。