【问题标题】:Is there a ruby method that just returns the value of a block?是否有一个 ruby​​ 方法只返回一个块的值?
【发布时间】:2010-12-02 23:39:49
【问题描述】:

我知道Object#tap,它接受一个值并返回该值。但是有没有一种方法可以接受一个块并返回该块评估的值?

为了改进我在this answer 中的代码(比下面的sn-p 更复杂),我想更改

deck.index("A").tap {|index| 
  STDERR.puts "Result of indexing for #{"A".inspect} is #{index.inspect}"
}

,其中有 "A" 重复,进入

def my_method(*args)
  yield *args
end

deck = ['A', 'B', 'C']
my_method("A") {|value| deck.index(value).tap {|index|
  STDERR.puts "Result of indexing for #{value.inspect} is #{index.inspect}"
} }
# Result of indexing for "A" is 0
# => 0

【问题讨论】:

    标签: ruby block


    【解决方案1】:

    您要查找的内容本质上等同于 Lisp 或 OCaml 中的 let — 允许您临时将值绑定到标识符,而无需将新变量引入更大的范围。没有任何东西可以让您在 Ruby 中使用该语法做这样的事情。等效的 Ruby 将是:

    lambda {|value| deck.index(value).tap {|index|
      STDERR.puts "Result of indexing for #{value.inspect} is #{index.inspect}"
    } }.call 'A'
    

    你当然可以写一个类似的方法:

    def let(*values) 
      yield *values 
    end
    

    【讨论】:

    • 是否可以将'A' 放在开头而不是结尾?
    【解决方案2】:

    我认为你可以用纤维解决它。比如:

    def myfiber
        block = lambda{nil}
        loop{ block = Fiber.yield(block.call) } 
    end
    f = Fiber.new {myfiber }
    f.resume
    
    puts "result: #{f.resume(lambda{1})}"
    puts "result: #{f.resume(lambda{5})}"
    puts "result: #{f.resume(lambda{2})}"
    

    将导致:

    result: 1
    result: 5
    result: 2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-05
      • 2015-01-01
      • 2012-01-01
      • 2021-09-21
      • 2015-10-21
      • 2017-02-21
      • 1970-01-01
      相关资源
      最近更新 更多