Ich versuche, Ruby 1.9.1 für eine eingebettete Skriptsprache zu verwenden, damit "Endbenutzer" -Code in einen Ruby-Block geschrieben wird. Ein Problem dabei ist, dass ich möchte, dass die Benutzer das Schlüsselwort 'return' in den Blöcken verwenden können, damit sie sich nicht um implizite Rückgabewerte kümmern müssen. In diesem Sinne möchte ich Folgendes tun können:
def thing(*args, &block)
value = block.call
puts "value=#{value}"
end
thing {
return 6 * 7
}
Wenn ich im obigen Beispiel 'return' verwende, erhalte ich einen LocalJumpError. Mir ist bewusst, dass dies daran liegt, dass der fragliche Block ein Proc und kein Lambda ist. Der Code funktioniert, wenn ich 'return' entferne, aber ich würde es wirklich vorziehen, in diesem Szenario 'return' verwenden zu können. Ist das möglich? Ich habe versucht, den Block in ein Lambda umzuwandeln, aber das Ergebnis ist das gleiche.
quelle
Antworten:
Verwenden Sie einfach
next
in diesem Zusammenhang:return
kehrt immer von der Methode zurück, aber wenn Sie dieses Snippet in irb testen, haben Sie keine Methode, deshalb haben SieLocalJumpError
break
Gibt den Wert vom Block zurück und beendet den Aufruf. Wenn Ihr Block vonyield
oder aufgerufen wurde.call
, wird auchbreak
dieser Iterator unterbrochennext
Gibt den Wert vom Block zurück und beendet den Aufruf. Wenn Ihr Block vonyield
oder aufgerufen wurde.call
, wirdnext
der Wert an die Zeile zurückgegeben, inyield
der er aufgerufen wurdequelle
In Ruby ist das nicht möglich.
Das
return
Schlüsselwort wird im aktuellen Kontext immer von der Methode oder dem Lambda zurückgegeben. In Blöcken wird von der Methode zurückgekehrt, in der der Abschluss definiert wurde . Es kann nicht veranlasst werden, von der aufrufenden Methode oder dem Lambda zurückzukehren.Die Rubyspec zeigt, dass dies tatsächlich das richtige Verhalten für Ruby ist (zwar keine echte Implementierung, aber volle Kompatibilität mit C Ruby):
quelle
Sie sehen es aus der falschen Sicht. Dies ist eine Ausgabe von
thing
, nicht das Lambda.quelle
Wo wird etwas aufgerufen? Bist du in einer Klasse?
Sie können Folgendes in Betracht ziehen:
quelle
Ich hatte das gleiche Problem beim Schreiben eines DSL für ein Webframework in Ruby ... (das Webframework Anorexic wird rocken!) ...
Trotzdem habe ich mich in die Rubin-Interna vertieft und mit dem LocalJumpError, der zurückgegeben wurde, wenn ein Proc return zurückgibt, eine einfache Lösung gefunden.
Die if-Anweisung im Rettungssegment könnte wahrscheinlich ungefähr so aussehen:
Aber für mich ist es Neuland, also bleibe ich bei dem, was ich bisher getestet habe.
quelle
Ich glaube, dies ist trotz der Nachteile die richtige Antwort:
Dieser Hack ermöglicht es Benutzern, die Rückgabe in ihren Prozessen ohne Konsequenzen zu verwenden, das Selbst bleibt erhalten usw.
Der Vorteil der Verwendung von Thread besteht darin, dass Sie in einigen Fällen den LocalJumpError nicht erhalten - und die Rückgabe an der unerwartetsten Stelle erfolgt (neben einer Methode der obersten Ebene, bei der der Rest des Körpers unerwartet übersprungen wird).
Der Hauptnachteil ist der potenzielle Overhead (Sie können den Thread + Join durch den ersetzen,
yield
wenn dies in Ihrem Szenario ausreicht).quelle
Ich habe einen Weg gefunden, aber es geht darum, eine Methode als Zwischenschritt zu definieren:
quelle