Ruby 从块返回值,而不从方法返回

Ruby 从块返回值,而不从方法返回,ruby,block,next,Ruby,Block,Next,我有一个类测试: class Test attr_accessor :data def initialize @data = [0, 1, 2, 3] end def map @data.map!{|i| i = yield i } end end 我试着像这样使用它: a = Test.new a.map{|i| if(i==2) i+=1 break i #<--- -This line is the focus el

我有一个类
测试

class Test 
  attr_accessor :data
  def initialize
    @data = [0, 1, 2, 3]
  end
  def map
    @data.map!{|i| i = yield i }
  end
end
我试着像这样使用它:

a = Test.new

a.map{|i|
  if(i==2)
    i+=1
    break i  #<--- -This line is the focus
  else
    1
  end
}

puts a.data
a=Test.new
a、 地图{i|
如果(i==2)
i+=1
你必须这样做:

a.map{ |i| (i % 2 == 0) ? i + 1 : i }
使用映射函数时,不更改“a”变量,如果要更改“a”变量,请执行以下操作:

a.map!{ |i| (i % 2 == 0) ? i + 1 : i }
“i”的新值是块返回的值,因此不要执行以下操作:

a.map{|i| i = 1 }
因为如果你这样做:

a.map{|i| i = 1; 5 }
结果将是:

 [5, 5, 5, 5]

我假设你问的是如何留下一个块并利用最后计算的值,而不是如何计算一组特定的数字;对于后者,可能有一个聪明的一行

像这样的怎么样:

class Test
  attr_accessor :data

  def initialize
    @data = [0, 1, 2, 3]
  end

  def modify
    @data.map! {|i| yield i }
  end
end

a = Test.new
a.modify do |i|
  break i if @done
  @done = i == 2
  @done ? (i + 1) : 1
end

puts a.data

另外一个想法-
#map
是Ruby中一个具有特定接口的重要方法。在您的示例中,您通过修改
Test
中的一个字段违反了接口。因此,我使用了名称
#modify

通常,您可以通过修改生成的值来解决这个问题。例如,如果数组由字符串而不是Fixnums组成:

class Test
  attr_accessor :data

  def initialize
    @data = %w{a b c d}
  end

  def map
    @data.map! { |i| yield i }
  end
end

a = Test.new
a.map do |i|
  if i == 'c'
    i.next!
    break
  else
    'b'
  end
end

p a.data   #=> ["b", "b", "d", "d"]
您的示例的问题是:

Fixnum对象具有立即值。这意味着当它们作为参数分配或传递时,将传递实际对象,而不是对该对象的引用。分配不会别名Fixnum对象。任何给定整数值实际上只有一个Fixnum对象实例


Fixnums不能在适当的位置进行更改,因此下块中的表达式
i+=1
不会影响上块中
i
的值。这就是为什么在您的示例中得到
2
,但在我的示例中得到
d

我认为他在询问如何在使用当前值而不是当前值时离开该块示例中提到的具体数值。非常感谢您的回答。您能澄清一下#map的作用吗?我想这差不多是它的作用吗?@Paul:根据它的调用方式,
#map
返回一个
数组
或一个
可枚举的
,而不修改调用它的对象。@Paul:我应该更正前面的注释——使其成为枚举器,而不一定是
可枚举的