In diesem Beispiellokale Variablen in den Blöcken
x = 1
foo = lambda do
x = 2
end
foo.call
foo den Wert von x ändern. Ist es möglich, den Wert von x zu verbergen, so dass es vor und nach dem Aufruf von proc gleich bleibt?
In diesem Beispiellokale Variablen in den Blöcken
x = 1
foo = lambda do
x = 2
end
foo.call
foo den Wert von x ändern. Ist es möglich, den Wert von x zu verbergen, so dass es vor und nach dem Aufruf von proc gleich bleibt?
Ich bin damit einverstanden, es ist nicht sehr googleable, wenn Sie nicht den genauen Begriff kennen. Hier gehen Sie:
x = 1
foo = lambda do
x = 2
end
foo.call
p x # => 2
x = 1
foo = lambda do |;x|
x = 2
end
foo.call
p x # => 1
Es ist seit Ruby 1.9 zur Verfügung, aber ich komme nicht über sie oft (wenn überhaupt). Es ist here beschrieben, und es ist "block lokale Variable" oder "Block-local Argument" genannt:
Sie können auch block lokale Argumente zu einem Block deklarieren mit ';' in der Blockargumentliste. Zuordnen zu einem Block-local Argument nicht überschreiben lokale Argumente außerhalb des Blocks in den Anwendungsbereich des Anrufers
@EliSadoff und @tadman einen sehr wichtigen Punkt in den Kommentaren machen.
Es gibt einen guten Grund, warum diese lokalen Blockvariablen nicht häufig verwendet werden: Es ist normalerweise keine gute Idee, eine äußere Variable in einem Block zu schattieren. Es könnte den Code schwerer lesbar machen, schwerer zu verstehen und schwieriger zu verwenden sein.
mit Rubin Blöcken, äußeren und Blockvariablen sind oft verwandt, aber nicht äquivalent:
filename
als äußere Variable, file
als Blockvariable mit IO.open
array
als äußere Variable, element
als Blockvariable mit Array#each
strings
als äußere Variable, string
als Blockvariable mit Array#map
Wenn Sie ein bound variable und x
bereits als äußere Variable verwendet wird, verwenden Sie einfach y
, i
, z
, m
, n
oder whatever
.
Nachdem das gesagt wurde, wird es im Allgemeinen als guter Stil angesehen, äußere Variablen in Blöcken nicht zu schattieren, selbst wenn es eine block-lokale Variable ist. –
Die '|; x |' Methode ist eine Lösung dafür, aber es ist sehr unregelmäßig und am besten zu vermeiden. Namen zu überschatten ist ein Problem, das vermieden werden sollte, nicht mit Tricks überflutet werden. Das ist wirklich als letztes Mittel für Situationen gedacht, in denen es keine andere Möglichkeit gibt. – tadman
Wow, wow, Ruby überrascht mich nie mit unbekannten Features. – akuhn
Blöcke sind keine Verschlüsse.
Um das Verhalten zu erreichen Sie suchen (einen Zugriff auf die äußerste Variable bekommen und es in wechselnden frei sein) könnte man wie folgt vorgehen:
x = 1
foo = ->(y = x) { puts y; y = 2; puts y }
foo.()
puts x
#⇒ 1
# 2
# 1
Es ist unklar, warum man nicht die verwenden können, Derselbe Name für die lokale Blockvariable.
foo = ->(x = x) { puts x; x = 2; puts x }
#⇒ # nil ?! WHY?
# 2
Ich würde die letztere als einen Fehler im Ruby-Interpreter betrachten.
Interessant, wie immer. Zumindest ist es konsistent mit dem anderen Feature/bug 'a = a # => nil, wenn 'a' undefiniert ist. Der Interpreter ist jedoch nett genug, um "Warnung: Zirkularargument-Referenz - x" zu sagen. –
@EricDuminil "Der Interpreter ist nett genug zu sagen 'Warnung: Zirkel Argument Referenz - X'" - beginnend mit 2.2 und wegen der meisten nicht verwandten [brechende Änderung] (https://bugs.ruby-lang.org/issues/10314) :) – mudasobwa
Haben Sie wirklich vor dem Posten gesucht?[Hier gehts] (http://stackoverflow.com/questions/16699595/how-to-use-truly-local-variables-in-ruby-proc-lambda) – 31piy
Ja, jedoch gibt es keine Antwort auf meine Frage. Ich kann nutzen ; um die Variable als lokal zu deklarieren, aber dann ist der Anfangswert nicht im Lambda sichtbar. Ich suchte nach etwas wie C++ - Blockverhalten. – Surfrider
Sie können 'x' im Lambda übergeben, wenn Sie Lambda als' foo = Lambda | y | deklarieren mach es. Auf diese Weise wird "y" nicht mit der äußeren Variablen "x" in Konflikt geraten. – 31piy