programowania Perl mówi, że overload::constant
prace na stałe.
Wszelkie procedury obsługi podane dla liczby całkowitej i zmiennoprzecinkowej będą wywoływane za każdym razem, gdy tokenerator Perla napotka stałą liczbę.
Po wywołaniu m/$pattern/
nie jest to stała. To zmienna.
($test, $name) = ChopPattern($test, '\nom');
Teraz tam '\nom'
jest stała, ale jest to ciąg znaków. Zmień to w qr//
, a będziesz miał wyrażenie regularne, które zawiera stałą.
($test, my $name) = ChopPattern($test, qr'\nom');
Wzór meczu w ChopPattern
może pozostać taka sama:
if($string =~ m/$pattern/) { ... }
Bo teraz jest stałym elementem w wyrażeniu regularnym, Perl może zadzwonić do przeciążenia convert
i wykonać regex.
Zobaczmy to w akcji. Pamiętaj, że Perl robi to przeciążanie podstawienia podczas kompilacji, kiedy analizuje kod źródłowy.
Rozważmy następujący przykład:
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');
to nie jest ważne, co kod robi. Kiedy go deparse, otrzymujemy następujący wynik:
$ 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
Widzimy, że program obsługi został zainstalowany, ale w ostatniej linii w wywołaniu funkcji, istnieje ciąg '\\nom'
.
Teraz, jeśli używamy cytowanego wyrażenia qr//
, zamiast ciągów, rzeczy się zmieniają.
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/);
Teraz program deparowany zawiera nagle foobar
. Zmodyfikowano wyrażenie regularne.
$ 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
Zrobił to, zanim kod został uruchomiony.
Jeśli uruchomimy oba programy z -MO=Concise
, aby zobaczyć, co interpreter będzie działał po czasie kompilacji, otrzymamy kolejny dowód, że te rzeczy działają tylko na rzeczywistych stałych w kodzie źródłowym i nie mogą działać dynamicznie.
$ 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
I z 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
Warto kilka przegranych, ponieważ nigdy nie przyszło mi do głowy, że można przeciążać silnik regex w ten sposób. – Sobrique
@Sobrique: Jest to możliwe, ale nie jest to bardzo przyjemne. Akcja na odległość i tak dalej. – Borodin
Nie widział tego również wcześniej. Najpierw pomyślałem, że źle zrozumieli, co robi "przeciążenie". Ale jest to całkiem logiczne. Po prostu nie widzę dla niego przypadku użycia. To dziwaczne. – simbabque