Ich möchte eine Zeichenfolgenersetzung in einem for
Block mithilfe eines benannten Captures vornehmen . Ich habe erwartet, die Zahlen 1,2,3 als Ausgabe zu erhalten. Aber es ist Nil
für den ersten Lauf und dann 1 und 2 für den 2. und 3. Lauf. Wie verwende ich .subst
das Konstrukt korrekt in der Schleife? Ich sehe das gleiche Verhalten, wenn ich ein map
Konstrukt anstelle der for
Schleife verwende. Es funktioniert wie erwartet, wenn ich durch einen festen Zeichenfolgenwert ersetze.
for <a1 b2 c3> -> $var {
say $var;
say $var.subst(/.$<nr>=(\d)/, $<nr>); #.subst(/.$<nr>=(\d)/, 'X'); #OK
}
#`[
This is Rakudo version 2019.11 built on MoarVM version 2019.11
Output:
a1
Use of Nil in string context
in block at test3.pl6 line 3
b2
1
c3
2
]
raku
string-substitution
Valle Lukas
quelle
quelle
S///
manchmal zu verwenden. In diesem Fall könnten Sie tunS[.$<nr>=(\d)] = $<nr> given $var
Antworten:
TL; DR Verschiebung der Auswertung
$<nr>
bis nach Auswertung des Regex. @ JoKing ++ schlägt einen Weg vor . Eine andere Möglichkeit besteht darin, den Ersatz einfach mit Klammern ({$<nr>}
) zu umwickeln .Was passiert, wenn Ihr ursprünglicher Code aufruft?
subst
Bevor Raku versucht, die
subst
Routine aufzurufen , stellt er eine Liste von Argumenten zusammen, die an ihn übergeben werden sollen.Es gibt zwei Werte. Der erste ist eine Regex. Es ist nicht laufen . Der zweite Wert ist
$<nr>
. Es wird ausgewertet,Nil
weil zu Beginn eines Programms die aktuelle Übereinstimmungsobjektvariable an etwas gebunden ist, das ihren Wert beansprucht,Nil
und jeder Versuch, auf den Wert eines Schlüssels darin zuzugreifen,$<nr>
ebenfalls zurückgegeben wirdNil
. Zu diesem Zeitpunkt sind die Dinge also schon schief gelaufen, bevor siesubst
jemals gelaufen sind .Sobald Raku diese Liste von Argumenten zusammengestellt hat, versucht er aufzurufen
subst
. Es ist erfolgreich undsubst
läuft.Um das nächste Match zu erhalten, wird
subst
der Regex ausgeführt. Dadurch wird die aktuelle Übereinstimmungsobjektvariable aktualisiert$/
. Es ist jedoch zu spät, um den bereits übergebenen Substitutionswert zu ändernsubst
.Mit Match in der Hand wird als
subst
nächstes das Substitutionsargument betrachtet. Es findet esNil
und handelt entsprechend.Für den zweiten Aufruf
subst
,$<nr>
hat auf dem Wert aus dem aufgenommenen ersten Aufrufsubst
. Und so weiter.Zwei Möglichkeiten, die Bewertung von zu verschieben
$<nr>
@JoKing schlägt vor, die Verwendung von in Betracht zu ziehen
S///
. Dieses Konstrukt wertet zuerst den regulären Ausdruck (zwischen dem ersten Paar von/
s) und dann den Ersatz (zwischen dem letzten Paar von/
s) aus. (Das gleiche Prinzip gilt, wenn Sie andere gültigeS
Syntaxen wie verwendenS[...] = ...
.)Wenn Sie verwenden
subst
, stellt Raku, wie im vorherigen Abschnitt erläutert, die Argumentliste dafür zusammen, bevor Sie sie aufrufen. Es findet einen regulären Ausdruck (den es nicht ausführt) und einen Abschluss (den es auch nicht ausführt). Es versucht dann,subst
mit diesen Argumenten aufzurufen, und dies gelingt ihm.Als nächstes
subst
beginnt zu laufen. Es hat Code sowohl für das Match (eine Regex) als auch für die Substitution (ein Closure) erhalten.Es führt den regulären Ausdruck als Matching-Operation aus. Wenn der reguläre Ausdruck eine Übereinstimmung zurückgibt, wird
subst
der Abschluss ausgeführt und der zurückgegebene Wert als Ersetzung verwendet.Da wir also von der Übergabe
$<nr>
als nackter Wert, was bedeutete, dass er eingefroren wurdeNil
, zur Übergabe in einen Verschluss übergegangen sind, der seine Bewertung verschoben hat$/
, bis eine Übereinstimmung mit einem ausgefüllten<nr>
Eintrag festgelegt wurde, haben wir das Problem gelöst.Beachten Sie, dass dies nur funktioniert, weil derjenige, der entworfen / implementiert
subst
wurde, klug / nett genug war, um zuzulassen, dass sowohl die Übereinstimmungs- als auch die Substitutionsargumente Formen vonCode
(ein regulärer Ausdruck für die Übereinstimmung und ein gewöhnlicher Abschluss für die Substitution) sind, wenn ein Benutzer dies wünscht. Es führt dann zuerst das Match aus und führt dann nur dann den Substitutionsabschluss aus, wenn einer bestanden wurde, wobei das Ergebnis dieses letzteren Aufrufs als endgültige Substitution verwendet wird. Auf ähnliche WeiseS///
funktioniert , weil das nur entwickelt wurde , um den Austausch zu bewerten , nachdem er zunächst die Substitution ausgewertet wird .quelle