【问题标题】:How to "replace" number objects in-place in Ruby如何在 Ruby 中就地“替换”数字对象
【发布时间】:2013-03-11 23:57:16
【问题描述】:

我正在尝试调整 Ruby/Rails 函数中的变量。许多其他语言的标准内容。

在c中:

void change(int *io){
  *io = 1;
}

现在我们都知道 Ruby 是通过引用传递的(笑脸)。这段代码完美运行:

def tester()
  value = 'dave'
  test_replace(value)
  p value.to_s;
end

def test_replace(ioValue)
  ioValue.replace 'test'  
end

输出是“测试”。

所以问题是:固定数字没有替换方法。它们的传递方式与其他值不同。

所以我的问题是:我如何在 Ruby 中“io”一个“int”?

def tester()
  value = 10
  test_replace(value)
  p value.to_s;
end

def test_replace(ioValue)
  ioValue.replace 15  
end

哪个加注

10:Fixnum 的未定义方法 `replace'

【问题讨论】:

  • 不是真正的对象???它们就是我们所说的不可变的。
  • 请不要对这个例子发表评论。这个问题是 100% 人为设计的。价值传递的事情也已经在其他 SO 条目中解决了:)
  • 为什么会被否决?我的意思是说实话..通过引用传递是真实的吗?否决票让我很困惑。
  • 在您所说的意义上,Ruby 中没有传递引用。所有方法参数都是不可变的局部变量。如果它们碰巧指向一个对象,您可以调用该对象的方法。这些方法可以修改对象,但不能更改变量引用的对象。在 fixnums 的情况下,底层对象本身是不可变的,并且没有提供用于替换它的公共 API。
  • @daveatflow 是的,对象是通过引用传递的。但是,引用是不可变的值,因此如果引用的对象没有自变异方法,则无法更改它。

标签: ruby pass-by-reference


【解决方案1】:

@Linuxios 在他关于按值传递的解释中是正确的,但他的解决方法非常尴尬。用支持替换的SimpleDelegator 来装箱很容易:

class NumberBox < SimpleDelegator
  alias_method :replace, :__setobj__
  class <<self; alias_method :[], :new; end
end

def tester()
  value = NumberBox[10]
  test_replace(value)
  p value.to_s;
end

def test_replace(ioValue)
  ioValue.replace 15  
end

在上面value 的行为与它委托给的对象完全相同,在初始化时建立(使用::newNumberBox::[]),除了它还支持__setobj__ 方法及其绑定的别名replace一个新对象作为委托人。

【讨论】:

  • 不错的解决方案!我以前从未听说过 SimpleDelegator。 +1!
【解决方案2】:

实际上有两种方法可以做到这一点:

  1. 包裹在一个对象中
  2. 包装成一个数组
  3. 创建一个可变整数代理对象

选项二很简单,我不会举例。选项 1 如下所示:

class IntRef < BasicObject
  def initialize(i)
    @int = i
  end
  def replace(v)
    @int = v
  end
  def method_missing(name, *args, &block)
    @int.send(name, *args, &block)
  end
end

或选项三:代理对象!

class MutableInt < BasicObject
  def initialize(i)
    @int = i
  end
  def method_missing(name, *args, &block)
    v = @int.send(name, *args, &block)
    if(v.is_a?(::Fixnum))
      @int = v
      return self
    end
    v
  end
end

警告:任何,任何你对这个代理做的任何事情都会粘住并改变对象。小心。

【讨论】:

  • 那太丑了.. 但是有效... 唉,我希望其他人有不同的方法.. 我不想在函数之外编写代码来支持更改值。特别是因为我在几个地方都使用了这个值。谢谢:)
  • @daveatflow:抱歉,这是最好的方法。没有比这更好的方法了。
  • @daveatflow:实际上,等一下。我有个主意……(恶魔般的笑声):)。
  • @daveatflow:Ruby 中的 * 意味着与 C 中完全不同的东西。尽管 2 是最好的选择。
  • 是的.. 对不起,我就是这个意思.. 如果我尽可能地贴近我的心,它只会让我的代码更容易阅读
【解决方案3】:

现在我们都知道 Ruby 是通过引用传递的

相反,Ruby 只是按值传递。没有通过引用。与 Java、Python 等相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 2015-01-27
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    相关资源
    最近更新 更多