Qual è la differenza tra $ / e $ ¢ in regex?


11

Come indica il titolo, qual è la differenza tra $/e ? Sembrano avere sempre lo stesso valore:

my $text = "Hello world";

$text ~~ /(\w+) { say $/.raku } (\w+)/;
$text ~~ /(\w+) { say $¢.raku } (\w+)/;

Entrambi producono oggetti Match con gli stessi valori. Qual è la logica nell'usare l'uno sull'altro?

Risposte:


11

La variabile si $/riferisce alla corrispondenza più recente mentre la variabile si riferisce alla corrispondenza più recente più recente. Nella maggior parte delle regex di base come sopra, può essere la stessa cosa. Ma come si può vedere dall'output del .rakumetodo, gli Matchoggetti possono contenere altri Matchoggetti (questo è ciò che si ottiene quando si utilizza $<foo>o $1per le acquisizioni).

Supponiamo invece di avere la seguente regex con una cattura quantificata

/ ab (cd { say $¢.from, " ", $¢.to } ) + /

E se funzionasse vedrebbe il seguente output se ci abbinassimo a "abcdcdcd":

0 2
0 4
0 6

Ma se passiamo dall'uso a $/, otteniamo un risultato diverso:

2 2
4 4
6 6

(Il motivo per cui .tosembra essere un po 'spento è che —e-- .posnon vengono aggiornati fino alla fine del blocco di acquisizione.)

In altre parole, farà sempre riferimento a quello che sarà il tuo oggetto di corrispondenza finale (ovvero, $final = $text ~~ $regex) in modo da poter attraversare un albero di acquisizione complesso all'interno del regex esattamente come faresti dopo aver terminato la corrispondenza completa Quindi nell'esempio sopra, potresti semplicemente fare $¢[0]riferimento alla prima partita, $¢[1]alla seconda, ecc.

All'interno di un blocco di codice regex, $/farà riferimento alla corrispondenza più immediata. Nel caso sopra, questa è la partita all'interno ( )e non saprà delle altre partite, né l'inizio originale della corrispondenza: solo l'inizio del ( )blocco. Quindi dai una regex più complessa:

/ a $<foo>=(b $<bar>=(c)+ )+ d /

Possiamo accedere in qualsiasi momento usando $ ¢ tutti i footoken dicendo $¢<foo>. Possiamo accedere ai bartoken di un dato foousando $¢<foo>[0]<bar>. Se inseriamo un blocco di codice all'interno foodell'acquisizione, sarà in grado di accedere ai bartoken utilizzando $<bar>o $/<bar>, ma non sarà in grado di accedere ad altri foo.


1
Ohhh! Ho interpretato il documento "La principale differenza tra $/e è ambito: quest'ultimo ha solo un valore all'interno della regex", il che significa che era semplicemente una traccia rudimentale, così come Cursorè. Quando ho letto la tua risposta ho pensato che $*TOPavrei creato il possibile miglioramento? sezione della mia risposta alla comunicazione degli addebiti "Perché / come è necessaria una variabile aggiuntiva per abbinare il carattere arbitrario ripetuto ai gruppi di cattura?". Ma i miei tentativi di sostituzione $*TOPcon falliti. Capisci il mio punto in quella risposta? Puoi farlo funzionare?
Raiph,

Raiph: Quindi, nelle grammatiche, si rinnova per ogni token, quindi dovresti dire $*TOP := $¢nel TOPtoken, ma questo non elimina la necessità del $*TOPvar ovviamente. Sono d'accordo che sarebbe fantastico poter fare riferimento alle partite di alto livello. Il problema è, in definitiva, ancora quello che identifichi: quando le corrispondenze posizionale / hash vengono inviate all'oggetto partita. Quando si utilizza - che è per-token - i risultati per definizione verranno pubblicati non appena { }si incontra il blocco che lo racchiude .
user0721090601

La cosa interessante per me è che nello sviluppo Binex, non ho trovato peggio dal punto di vista computazionale pubblicare i risultati delle partite immediatamente dopo averli incontrati. Alla fine della giornata, stai spingendo / saltando in un elenco / hash memorizzato nella cache, oppure stai spingendo / saltando in un elenco / hash della corrispondenza. Tuttavia, potrebbe esserci una sorta di accelerazione interna che non sono a conoscenza dell'utilizzo per LTM, che è probabilmente al centro di esso ( { }termina un token ai fini di LTM, quindi è più probabile che venga eseguito / testato rispetto a il resto del token in un |raggruppamento)
user0721090601

Ahhh. Ero saltato alla conclusione che era dinamico e rimasi sorpreso quando non funzionava. Ma il centesimo ora è caduto sul fatto che è lessicale, come avrei potuto immaginare dato il tuo uso della parola "più esterno", ed è, come spieghi, stabilito all'inizio di ogni regola.
Raiph,

Quindi, all'inizio di una regola, viene creato un nuovo oggetto di corrispondenza che registra la posizione del cursore del motore corrispondente nella stringa di input originale, ma è altrimenti vuoto. (Giusto?) Quindi e $/sono legati allo stesso oggetto, vale a dire questo nuovo oggetto match, che registrerà ciò che questa regola corrisponde e acquisisce mentre procede. Quindi, man mano che la corrispondenza avanza, rimane legato a questo oggetto di corrispondenza generale, mentre $/viene rimbalzato ogni volta che viene creato un nuovo oggetto di corrispondenza, quindi corrisponde sempre, come dici tu, all'ultimo oggetto di corrispondenza. Giusto?
Raiph,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.