2010-12-02 2 views
0

Ich weiß über Object#tap, die einen Wert nimmt und diesen Wert zurückgibt. Aber gibt es eine Methode, die einen Block nimmt und den vom Block ausgewerteten Wert zurückgibt?Gibt es eine Ruby-Methode, die nur den Wert eines Blocks zurückgibt?

Zu meinen Code in this answer (die komplizierter als das Snippet unten) zu verbessern, würde Ich mag

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

, ändern, die "A", in

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 

Antwort

2

wiederholt hat, was Sie suchen ist im Wesentlichen das Äquivalent von let in Lisp oder OCaml - etwas, mit dem Sie einen Wert vorübergehend an einen Bezeichner binden können, ohne eine neue Variable in den größeren Bereich einzuführen. Es gibt nichts, was Sie so etwas mit dieser Syntax in Ruby machen könnte. Die äquivalente Rubin wäre:

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

Sie könnten natürlich schreiben Sie einfach eine Methode, wie:

def let(*values) 
    yield *values 
end 
+0

Ist es möglich, setzt ' 'A'' in der Nähe von Anfang an, anstatt am Ende? –

0

Ich denke, man es mit Fasern lösen könnten. Etwas wie:

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})}" 

wird in Folge:

result: 1 
result: 5 
result: 2 
Verwandte Themen