ruby – 传递给新方法时do..end块会发生什么?

我有两个例子:

第一:

class SomeClass
  attr_accessor :some_var
  def initialize
    @some_var = 42
    yield self if block_given?
  end
end

p some_instance = SomeClass.new
another_instance = SomeClass.new do |s|
  s.some_var = "foobar"
end

p another_instance

结果:

#<SomeClass:0x007fcdda047270 @some_var=42>
#<SomeClass:0x007fcdda047130 @some_var="foobar">
[Finished in 0.1s]

第二:

class SomeClass
  attr_accessor :some_var
  def initialize
    @some_var = 42
    yield self if block_given?
  end
end

p some_instance = SomeClass.new
p another_instance = SomeClass.new do |s|
  s.some_var = "foobar"
end

p another_instance

结果:

#<SomeClass:0x007fdd3f0131e0 @some_var=42>
#<SomeClass:0x007fdd3f0130a0 @some_var=42>
#<SomeClass:0x007fdd3f0130a0 @some_var=42>
[Finished in 0.1s]

我期待得到:

#<SomeClass:0x007fdd3f0131e0 @some_var=42>
#<SomeClass:0x007fcdda047130 @some_var=42>
#<SomeClass:0x007fcdda047130 @some_var="foobar">
[Finished in 0.1s]

我知道赋值比do … end块更贪婪.并且这些curlies比赋值更贪婪,如下所示:

第三:

p yet_another_instance = SomeClass.new { |s| s.some_var = "foobar" }
p yet_another_instance 

结果:

#<SomeClass:0x007f9a420529c0 @some_var="foobar">
#<SomeClass:0x007f9a420529c0 @some_var="foobar">

但是第二个例子中的do … end块会发生什么?它不会被运行吗?

编辑:

接受@ max_pleaner的建议:)似乎Ruby完全忽略了它:

class SomeClass
  attr_accessor :some_var
  def initialize
    @some_var = 42
    yield self if block_given?
  end
end

p some_instance = SomeClass.new
p another_instance = SomeClass.new do |s|
  puts "cats and dogs?"
  s.some_var = "foobar"
end

p another_instance

结果:

#<SomeClass:0x007fd01f96f130 @some_var=42>
#<SomeClass:0x007fd01f96eff0 @some_var=42>
#<SomeClass:0x007fd01f96eff0 @some_var=42>
[Finished in 0.1s]

所以现在我很好奇,在什么条件下Ruby完全忽略了一个块?有没有关于这种情况的文件?

编辑:

见接受的答案

class SomeClass
  attr_accessor :some_var
  def initialize
    @some_var = 42
    yield self if block_given?
  end
end

p some_instance = SomeClass.new
p (another_instance = SomeClass.new do |s|
  puts "cats and dogs?"
  s.some_var = "foobar"
end)

p another_instance

结果:

#<SomeClass:0x007fcc6a043060 @some_var=42>
cats and dogs?
#<SomeClass:0x007fcc6a042f20 @some_var="foobar">
#<SomeClass:0x007fcc6a042f20 @some_var="foobar">
[Finished in 0.1s]

最佳答案 由于{…}和开始…结束的优先级不同而产生混淆,并且您不使用括号使其显式化.表达方式

p another_instance = SomeClass.new do |s|
  puts "cats and dogs?"
  s.some_var = "foobar"
end

被解释为

p(another_instance = SomeClass.new) do |s|
  puts "cats and dogs?"
  s.some_var = "foobar"
end

所以块传递给#p,而不是SomeClass #new.您可以明确强制执行其他订单:

p(another_instance = SomeClass.new do |s|
  puts "cats and dogs?"
  s.some_var = "foobar"
end)

这将以您期望的方式执行块.

点赞