Есть ли метод ruby, который просто возвращает значение блока? - PullRequest
0 голосов
/ 03 декабря 2010

Я знаю о Object#tap, который принимает значение и возвращает это значение.Но есть ли метод, который принимает блок и возвращает значение, оцененное блоком?

Чтобы улучшить мой код в этот ответ (что более сложно, чем приведенный ниже фрагмент), я 'я хотел бы изменить

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

Ответы [ 2 ]

2 голосов
/ 03 декабря 2010

То, что вы ищете, по сути эквивалентно let в Lisp или OCaml - то, что позволяет вам временно привязать значение к идентификатору, не вводя новую переменную в большую область видимости. Нет ничего, что позволяло бы вам делать такие вещи с этим синтаксисом в 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
0 голосов
/ 03 декабря 2010

Я думаю, вы могли бы решить это с помощью волокон.Что-то вроде:

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
...