Programming Perl sagt, dass overload::constant
Arbeiten auf Konstanten.
Alle Handler, die Sie für Integer und Float bereitstellen, werden aufgerufen, wenn der Perl-Tokener auf eine konstante Zahl stößt.
Wenn Sie anrufen m/$pattern/
, das ist keine Konstante. Es ist eine Variable.
($test, $name) = ChopPattern($test, '\nom');
Jetzt gibt es die '\nom'
eine Konstante, aber es ist eine Zeichenfolge. Verwandle das in eine qr//
und du wirst einen regulären Ausdruck haben, der eine Konstante enthält.
($test, my $name) = ChopPattern($test, qr'\nom');
Das Muster-Match in ChopPattern
gleich bleiben kann:
if($string =~ m/$pattern/) { ... }
Da es nun ein konstanter Teil in einem regulären Ausdruck ist, kann Perl rufen Sie Ihre convert
Überlastung und Ihre regex tun.
Lassen Sie uns dies in Aktion sehen. Denken Sie daran, dass Perl diese Ersetzung während der Kompilierung überlastet, wenn der Quellcode analysiert wird.
Betrachten Sie dieses Beispiel:
BEGIN {
overload::constant 'qr' => sub {
my $re = shift;
$re =~ s/\\nom/foobar/;
return $re;
};
}
sub match {
my ($t, $p) = @_;
$t =~ m/$p/;
}
match('some text', '\nom');
Es ist nicht wichtig, was der Code tut. Wenn wir es Deparse, bekommen wir diese Ausgabe:
$ perl -MO=Deparse scratch.pl
sub BEGIN {
use warnings;
use strict;
use feature 'say';
overload::constant('qr', sub {
my $re = shift();
$re =~ s/\\nom/foobar/;
return $re;
}
);
}
sub match {
use warnings;
use strict;
use feature 'say';
BEGIN {
$^H{'qr'} = 'CODE(0x147a048)';
}
my($t, $p) = @_;
$t =~ /$p/;
}
use warnings;
use strict;
use feature 'say';
BEGIN {
$^H{'qr'} = 'CODE(0x147a048)';
}
match 'some text', '\\nom'; # <-- here
Wir können sehen, dass der Handler installiert wurde, aber in der letzten Zeile im Funktionsaufruf gibt es den '\\nom'
String.
Wenn wir jetzt einen zitierten Ausdruck qr//
dort anstelle der Zeichenfolge verwenden, ändern sich die Dinge.
BEGIN {
overload::constant 'qr' => sub {
my $re = shift;
$re =~ s/\\nom/foobar/;
return $re;
};
}
sub match {
my ($t, $p) = @_;
$t =~ m/$p/;
}
match('some text', qr/\nom/);
Jetzt enthält das entartete Programm plötzlich foobar
. Die Regex wurde geändert.
$ perl -MO=Deparse scratch2.pl
sub BEGIN {
use warnings;
use strict;
use feature 'say';
overload::constant('qr', sub {
my $re = shift();
$re =~ s/\\nom/foobar/;
return $re;
}
);
}
sub match {
use warnings;
use strict;
use feature 'say';
BEGIN {
$^H{'qr'} = 'CODE(0x1e81048)';
}
my($t, $p) = @_;
$t =~ /$p/;
}
use warnings;
use strict;
use feature 'say';
BEGIN {
$^H{'qr'} = 'CODE(0x1e81048)';
}
match 'some text', qr/foobar/; # <-- here
Es tat, bevor der Code überhaupt ausgeführt wurde.
Wenn wir beide Programme mit -MO=Concise
ausführen, um zu sehen, was der Interpreter nach der Kompilierungszeit ausführen wird, erhalten wir einen weiteren Beweis, dass dieser Vorgang nur mit tatsächlichen Konstanten im Quellcode funktioniert und nicht dynamisch arbeiten kann.
$ perl -MO=Concise scratch.pl
8 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2529 scratch.pl:5950) v:%,R,*,&,{,x*,x&,x$,$,469762048 ->3
7 <1> entersub[t1] vKS/TARG,2 ->8
- <1> ex-list K ->7
3 <0> pushmark s ->4
4 <$> const(PV "some text") sM ->5 # <-- here
5 <$> const(PV "\\nom") sM ->6
- <1> ex-rv2cv sK/2 ->-
6 <$> gv(*match) s ->7
Und mit qr//
:
$ perl -MO=Concise scratch2.pl
8 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2529 scratch2.pl:5950) v:%,R,*,&,{,x*,x&,x$,$,469762048 ->3
7 <1> entersub[t1] vKS/TARG,2 ->8
- <1> ex-list K ->7
3 <0> pushmark s ->4
4 <$> const(PV "some text") sM ->5 # <-- here
5 </> qr(/"foobar"/) lM/RTIME ->6
- <1> ex-rv2cv sK/2 ->-
6 <$> gv(*match) s ->7
Ein paar Upvotes wert, da es mir nie in den Sinn gekommen ist, die Regex-Engine so zu überladen. – Sobrique
@Sobrique: Es ist möglich, aber es ist nicht eine sehr nette Sache zu tun. Fernwirkung und all das. – Borodin
Das hatte es vorher auch nicht gesehen. Zuerst dachte ich, sie hätten falsch verstanden was "Überladung" tut. Aber es ist eigentlich ziemlich logisch. Ich sehe einfach keinen Anwendungsfall dafür. Es ist verrückt. – simbabque