【问题标题】:How is a proc object preserved under `&`-`&` roundtrip?在 `&`-`&` 往返下如何保存 proc 对象?
【发布时间】:2016-05-07 00:15:55
【问题描述】:

当我在将数组传递给方法时使用* 分解数组,然后在方法中使用* 重构数组时,不会保留数组的标识:

a = []
a.object_id # => 69846339548760
def bar *a; a.object_id end
bar(*a) # => 69846339537540

但是,当我将 proc 传递给方法时使用 & 将其转换为块,然后在方法中使用 & 从块中重建 proc,proc 的身份似乎被保留:

pr = ->{}
pr.object_id # => 69846339666160
def foo ≺ pr.object_id end
foo(&pr) # => 69846339666160

proc 对象是如何保存的?转换成块的时候不会丢失吗?这是有保证的行为吗?

【问题讨论】:

  • 更多:def baz ; puts Proc.new.object_id end ; p = ->{} ; p.object_id #⇒ 9708320 ; baz &p ; #⇒ 9708320
  • @mudasobwa 这是由于特殊的语法约定。当您在方法中创建没有块的 proc 时,它指的是传递给方法的 proc。
  • 我知道了,谢谢。我的意思是Proc.new 实际上不是构造函数
  • @mudasobwa 现在我明白你的意思了。
  • Proc 实例不是不可变的吗?为什么当它作为参数传递给方法时要创建一个新实例?

标签: ruby proc


【解决方案1】:

Ruby VM 是一个堆栈机器。调用函数时,会将其所有参数(包括self)放入堆栈,然后调用。

数组 splat 的工作原理 - 它获取数组内容并将其放入堆栈,然后调用函数:

> puts RubyVM::InstructionSequence.compile("a = []; func *a").disasm
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] a          
0000 trace            1                                               (   1)
0002 newarray         0
0004 setlocal_OP__WC__0 2
0006 putself          
0007 getlocal_OP__WC__0 2
0009 splatarray       false
0011 opt_send_without_block <callinfo!mid:func, argc:1, ARGS_SPLAT|FCALL>
0013 leave  

当将proc作为一个块传递时,会发生类似的事情,但是ruby不必解包proc,它已经是一个proc了。

已添加: 根据 RubySpec 的 https://github.com/ruby/spec/blob/master/core/proc/block_pass_spec.rb

def revivify; Proc.new; end

it "remains the same object if re-vivified by the target method" do
  p = Proc.new {}
  p2 = revivify(&p)
  p.object_id.should == p2.object_id
  p.should == p2
end

这是某种标准化的行为,所以至少应该遵循 Rubinius 和 jRuby

【讨论】:

  • 那么这是否意味着这个问题的答案取决于您是否使用 MRI、JRuby、Rubinius 等?
  • @JoshRumbut ruby​​spec 定义了这种行为,所以应该是一样的
猜你喜欢
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
相关资源
最近更新 更多