Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 有没有办法重新定义[]=+;红宝石色_Ruby_Redis_Metaprogramming - Fatal编程技术网

Ruby 有没有办法重新定义[]=+;红宝石色

Ruby 有没有办法重新定义[]=+;红宝石色,ruby,redis,metaprogramming,Ruby,Redis,Metaprogramming,我正在尝试编写一个简单的DSL(针对Redis),我想定义[]+=我自己 我有 def []=(key,val) @redis.zadd(@name,val,key) end 我想定义一下 def []+=(key,val) @redis.zincrby(@name,val,key) end 但我的理解是Ruby自动提供了“[]+=”操作符= 有没有办法克服这种行为 显然,我不想要这个,因为我不能,比如说,在管道模式下运行这个x[y]+=z精确扩展为x[y]=x[y]+z: clas

我正在尝试编写一个简单的DSL(针对Redis),我想定义[]+=我自己

我有

def []=(key,val)
  @redis.zadd(@name,val,key)
end
我想定义一下

def []+=(key,val)
  @redis.zincrby(@name,val,key)
end
但我的理解是Ruby自动提供了“[]+=”操作符=

有没有办法克服这种行为
显然,我不想要这个,因为我不能,比如说,在管道模式下运行这个
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."
class“看到了吗?这是不可能的。”
您必须创建一个单独的方法。

不,
=
不能在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模块
类集
类值

这只是一个起点。您必须更加小心,例如检查密钥是否相同。在我简单的例子中,
redis[:foo]=redis[:bar]+1
实际上相当于
redis[:foo]+=1

虽然结论是正确的,但这段代码并不表明这是不可能的。也就是说,它不排除特殊的
[]+=
运算符语法或
+=
的绑定规则。为了“证明”这一点,我们只需要证明这些“特殊”操作符/绑定没有在适用的Ruby规范中定义。(祝你好运找到一个正式的Ruby规范!:-/)@pst:ISO规范早就被正式批准了。@pst,看到Ruby语言放弃参考实现而支持它,真是太好了。我当然想在我的回答中提及这一点;如此多的C问题都以这种方式得到了优雅的回答。不幸的是,我没有副本。:)@pst:一般来说,RubySpec是一个值得一看的地方。所有的实现都运行它,所有的实现都为它做出贡献。ISO规范旨在由所有现有Ruby实现实现,包括MRI(只能运行1.8)和YARV(只能运行1.9),因此,它只指定1.8和1.9的交集。事实上,它只指定了1.8和1.9交集的一个非常小的子集,特别是标准库完全缺失,核心库缺失很多,甚至语言也不完整。这是一个“Ruby的最小有用子集”。@pst是可用的。+1(因为它很有趣),但我通常建议不要使用这种方法。。。因为增加了系统的复杂性(以及所需的知识)可能不值得这么做。我同意,与操作员打交道是不好的。这会使调试和维护变得非常困难。