提问人:David Wright 提问时间:8/29/2016 更新时间:8/29/2016 访问量:4507
如何在 Ruby 中通过引用传递?
How to pass by reference in Ruby?
问:
目前,我正在开发一个 Ruby 类,除其他外,它能够找到切换信号的周期持续时间。这通常相当简单,但我面临的一个问题是,显然 Ruby 按值传递所有参数。
在网上研究时,我发现了很多关于“按价值传递”和“按引用传递”实际上是什么的不同讨论,但没有实际的“如何”的讨论。来自C / C++背景,对我来说,这是编程/脚本语言的重要组成部分。Watcher
我写的类的相关部分如下所示。Watcher::watchToggling() 方法是我遇到的问题。作为参数,应该是对我正在测量其期间持续时间的值的引用。aVariable
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 中有什么方法可以通过引用传递吗?如果没有,有没有其他方法可以解决这个问题?
答:
10赞
Jörg W Mittag
8/29/2016
#1
Ruby 是严格按值传递的,这意味着调用方作用域中的引用是不可变的。显然,它们在作用域内是可变的,因为您毕竟可以分配给它们,但它们不会改变调用方的作用域。
a = 'foo'
def bar(b)
b = 'bar'
end
bar(a)
a
# => 'foo'
但请注意,即使引用不能:
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 中,唯一可能的突变是改变引用(通过赋值)或要求对象改变自身(通过调用它的方法)。
您可以从方法中返回更新的值,并让调用方将其分配给引用:
a = :foo
def bar(b)
:"#{a}bar"
end
c = bar(a)
c
# => :foobar
或者,您可以将不可变对象包装在一个可变对象中,并改变该可变包装器:
a = [:foo]
def bar(b)
b[0] = :bar
end
bar(a)
a
# => [:bar]
[这与上面的第二个示例确实是一回事。
但是,如果你不能改变任何东西,那么你就被困住了。
评论
0赞
Jörg W Mittag
8/29/2016
或者,你可以称之为“封装确实有效”。
0赞
David Wright
8/29/2016
怎么会这样?如果您无法控制数据的存储位置,我会说“工作”有点牵强。您期望如何在无法写入或读取某些地址的情况下访问控制器的寄存器?
下一个:Ruby 如何修改参数
评论