如何在Ruby中通过引用传递? [英] How to pass by reference in Ruby?

查看:38
本文介绍了如何在Ruby中通过引用传递?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在 Ruby 中开发一个 Watcher 类,除其他外,它能够找到切换信号的周期持续时间.这通常相当简单,但我面临的一个问题是显然 Ruby 按值传递所有参数.在在线研究时,我发现了许多关于通过值传递"和通过引用传递"实际上是什么的不同讨论,但没有实际的如何".来自 C/C++ 背景,对我来说,这是编程/脚本语言的重要组成部分.

Currently I'm developing a Watcher class in Ruby, which, among other things, is able to find the period duration of a toggling signal. This is in general rather simple, but a problem I'm facing is that apparently Ruby passes all parameters by value. While researching online I found many different discussions about what "pass by value" and "pass by reference" actually is, but no actual "how to". Coming from a C/C++ background, for me this is an essential part of a programming/scripting language.

我写的类的相关部分如下所示.Watcher::watchToggling() 方法是我遇到的问题.作为参数,aVariable 应该是我测量周期持续时间的值的参考.

The relevant parts of the class that I wrote are shown below. The method Watcher::watchToggling() is the one I'm having trouble with. As a parameter, aVariable should be the reference to the value I'm measuring the period duration for.

class Watcher
  @done
  @timePeriod

  def reset()
    @done = false;
    @timePeriod = nil;
  end

  def watchToggling(aVariable, aTimeout=nil)
    oldState = aVariable;
    oldTime = 0;
    newTime = 0;

    timeout(aTimeout)do
      while(!@done)
        newState = aVariable;
        if(newState != oldState)
          if(newState == 1)
            # rising edge
            if(oldTime != 0)
              # there was already a rising edge before,
              # so we can calculate the period
              newTime = Time.now();
              @timePeriod = newTime - oldTime;
              @done = true;
            else
              # if there was no previous rising edge,
              # set the time of this one
              oldTime = Time.now();
            end
          end
          oldState = newState;
        end
      end
    end

    puts("Watcher: done.")
  end

  def isDone()
    return @done;
  end

  def getTimePeriod()
    return @timePeriod;
  end
end

在 ruby​​ 中有什么方法可以通过引用传递吗?如果没有,是否有替代方案可以解决这个问题?

Is there any way at all in ruby to pass by reference? And if not, are there alternatives that would solve this problem?

推荐答案

Ruby 是严格按值传递的,这意味着调用者范围内的引用是不可变的.显然它们在作用域内是可变的,因为你毕竟可以分配给它们,但它们不会改变调用者的作用域.

Ruby is strictly pass-by-value, which means references in the caller's scope are immutable. Obviously they are mutable within the scope, since you can assign to them after all, but they don't mutate the caller's scope.

a = 'foo'

def bar(b)
  b = 'bar'
end

bar(a)

a
# => 'foo'

但是请注意,即使引用不能,object 也可以改变:

Note, however, that the object can be mutated even if the reference cannot:

a = 'foo'

def bar(b)
  b << 'bar' # the only change: mutate the object instead of the reference
  b = 'baz'
end

bar(a)

a
# => 'foobar'

如果你传递的对象也是不可变的,那么你就无能为力了.Ruby 中唯一的变异可能性是改变引用(通过赋值)或要求一个对象改变自身(通过调用它的方法).

If the object you get passed is immutable, too, then there is nothing you can do. The only possibilities for mutation in Ruby are mutating the reference (by assignment) or asking an object to mutate itself (by calling methods on it).

您可以从您的方法返回一个更新的值,并让调用者将其分配给引用:

You can return an updated value from your method and have the caller assign that to the reference:

a = :foo

def bar(b)
  :"#{a}bar"
end

c = bar(a)

c
# => :foobar

或者您可以将不可变对象包装在一个可变对象中并改变该可变包装器:

Or you can wrap the immutable object in a mutable one and mutate that mutable wrapper:

a = [:foo]

def bar(b)
  b[0] = :bar
end

bar(a)

a
# => [:bar]

[这和上面的第二个例子是一样的.]

[This is really the same thing as the second example above.]

但如果你不能改变任何东西,那么你就会陷入困境.

But if you can't change anything, then you are stuck.

这篇关于如何在Ruby中通过引用传递?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆