experchange > perl

hymie! (07-09-19, 06:08 PM)
So I just had to debug a script, written long before I got here.

The problem turned out to be that the script had a user-defined function
named "reset" that was clashing with the built-in "reset" command.

sub reset()
{
...
...
}

So I renamed the function and everything is good now.

But my question is --

Is there a defined way that perl handles user functions named after built-
in commands? Is this undefined behavior?

In short ... did this ever work?

--hymie! hymie
Rainer Weikusat (07-09-19, 10:37 PM)
hymie! <hymie> writes:
[..]
> Is there a defined way that perl handles user functions named after built-
> in commands? Is this undefined behavior?
> In short ... did this ever work?


What's your idea of 'work'? 'reset' is a builtin. The Perl compiler
recognizes this and translates it into the corresponding op. Eg,

-------
sub reset {
return $_[0] + 43;
}

sub dosth
{
print(reset($_), "\n") for 0 .. 9;
}

dosth;
--------

compiles into

--------
main::dosth:
g <1> leavesub[1 ref] K/REFC,1 ->(end)
- <@> lineseq KP ->g
1 <;> nextstate(main 2 a.pl:8) v ->2
f <2> leaveloop K/2 ->g
6 <{> enteriter(next->c last->f redo->7) lKS/8 ->d
- <0> ex-pushmark s ->2
- <1> ex-list lK ->5
2 <0> pushmark s ->3
3 <$> const[IV 0] s ->4
4 <$> const[IV 9] s ->5
5 <#> gv[*_] s ->6
- <1> null K/1 ->f
e <|> and(other->7) K/1 ->f
d <0> iter s ->e
- <@> lineseq sK ->-
b <@> print vK ->c
7 <0> pushmark s ->8
9 <1> reset sK/1 ->a
- <1> ex-rv2sv sK/1 ->9
8 <#> gvsv[*_] s ->9
a <$> const[PV "\n"] s ->b
c <0> unstack s ->d
----------

hence, it won't call the function. As documented in perldoc CORE, a
compile-time override can be used to overload builtins. Another option
is to force a symbol table lookup, eg, by invoking the subroutine named
reset as method or via &.

-------
sub reset {
return $_[0] + 43;
}

sub dosth
{
print(&reset($_), "\n") for 0 .. 9;
}

dosth;
-------

compiles into

-------
main::dosth:
i <1> leavesub[1 ref] K/REFC,1 ->(end)
- <@> lineseq KP ->i
1 <;> nextstate(main 2 a.pl:8) v:{ ->2
h <2> leaveloop K/2 ->i
6 <{> enteriter(next->e last->h redo->7) lKS/8 ->f
- <0> ex-pushmark s ->2
- <1> ex-list lK ->5
2 <0> pushmark s ->3
3 <$> const[IV 0] s ->4
4 <$> const[IV 9] s ->5
5 <#> gv[*_] s ->6
- <1> null K/1 ->h
g <|> and(other->7) K/1 ->h
f <0> iter s ->g
- <@> lineseq sK ->-
d <@> print vK ->e
7 <0> pushmark s ->8
b <1> entersub[t3] lKS/TARG,AMPER,1 ->c
- <1> ex-list lK ->b
8 <0> pushmark s ->9
- <1> ex-rv2sv sKM/1 ->a
9 <#> gvsv[*_] s ->a
- <1> ex-rv2cv sK/8 ->-
a <#> gv[*reset] s ->b
c <$> const[PV "\n"] s ->d
e <0> unstack s ->f
--------

which does call the user-defined routine (invoking builtins via & is not
possible).
George Bouras (07-10-19, 01:30 AM)
Στις 9/7/2019 7:08 μ.μ., ο hymie! έγραψε:> So I just had to debug a
script, written long before I got here.
> The problem turned out to be that the script had a user-defined function
> named "reset" that was clashing with the built-in "reset" command.


#!/usr/bin/perl
use subs 'reset';

reset;
CORE::reset 'V';

sub reset :method {
print "I am the custom reset\n"
}
Eric Pozharski (07-10-19, 12:58 PM)
with <slrnqi9evg.o7u.hymie> hymie! wrote:

*SKIP*
> Is there a defined way that perl handles user functions named after
> built- in commands? Is this undefined behavior? In short ... did
> this ever work?


Yes. This is dark magic and it worked for years (so it will work for
years). Refer to 'perldoc perlsub', then grep for 'Overriding Built-in
Functions' for details.

Also:

% perl -we ' sub printf { die 42 }; printf "3.14\n"'
3.14
% perl -we ' sub printf { die 42 }; main::printf "3.14\n"'
42 at -e line 1.

But these are OO-enabled. Now watch this:

% perl -we ' sub reset { die 42 }; reset "3.14\n"'
Ambiguous call resolved as CORE::reset(), qualify as such or use & at -e line 1.

BTW it's a warning and not a failure. What brings in...

As they say over there on IRC: "use strict, use warnings, three-way
open". Always.
hymie! (07-10-19, 09:23 PM)
In our last episode, the evil Dr. Lacto had captured our hero,
Eric Pozharski <whynot>, who said:
> Refer to 'perldoc perlsub', then grep for 'Overriding Built-in
> Functions' for details.


Ah, thank you. I knew it was probably in there somewhere, if I could
figure out the correct term(s) to search for.

> Also:
> % perl -we ' sub reset { die 42 }; reset "3.14\n"'
> Ambiguous call resolved as CORE::reset(), qualify as such or use & at -e line 1.
> As they say over there on IRC: "use strict, use warnings, three-way
> open". Always.


My program looked like this:

[blah blah blah]
reset();
[blah blah blah]
reset();
[blah blah blah]

sub reset()
{
blah
blah
blah
}

I tried running perl -cw , and it said "syntax OK". I thought that was
(close to) the same thing as "use strict ; use warnings;" ... am I
mistaken?

--hymie! hymie
Eric Pozharski (07-11-19, 11:27 AM)
with <slrnqiceqd.usu.hymie> hymie! wrote:
> In our last episode, the evil Dr. Lacto had captured our hero,
> Eric Pozharski <whynot>, who said:


>> Refer to 'perldoc perlsub', then grep for 'Overriding Built-in
>> Functions' for details.

> Ah, thank you. I knew it was probably in there somewhere, if I could
> figure out the correct term(s) to search for.


Hooray! Usenet is victorious again! Google looses!!! But anyway,..

[..]
> blah
> blah
> }


This self-explanatory. Compiles meets calls to 'reset()' and resolves
them as CORE::reset, then comes re-definition,.. Which is just trown
away -- all calls are for CORE::reset, so main::reset can be safely
ignored.

Also (doing frowny face here), this 'sub reset() { ... }' -- don't do
that if you don't know what you are doing, ok? This '()' means empty
prototype, in this case it's ignored anyway. Yes, I remember, it's not
your code.

> I tried running perl -cw , and it said "syntax OK". I thought that
> was (close to) the same thing as "use strict ; use warnings;" ... am I
> mistaken?


Not exactly. '-w' is like 'use warnings' without option of 'no
warnings' for entire code including use()d and require()d modules.
Can't say about /**/lib/perl*/**/auto/*.so though. And '-w' doesn't
imply 'use strict' in any way.
Rainer Weikusat (07-11-19, 01:21 PM)
hymie! <hymie> writes:

[...]

[..]
> I tried running perl -cw , and it said "syntax OK". I thought that was
> (close to) the same thing as "use strict ; use warnings;" ... am I
> mistaken?


Should probably be

perl -cw -Mstrict

There's no de facto difference between that and 'use strict' with
regards to strictness. It just avoids pointless runtime checks when
running in "production mode".

The -w-switch is different, though: It applies to all code, not just
your code and it doesn't enable all kinds of dubious runtime checks,
usually about implicit type conversion someone strongly feels that
shouldn't ever happen. Usually, that's using undefined values as numeric
zero or empty strings.

Pointedly worded: You're supposed to use

use warnings;

because YOUR code is highly suspicious and deserves to be warned about
at any oppoertunity but not -w because the latter stops CPANers from
disabling warnings for their highly trustworthy code.
hymie! (07-11-19, 03:13 PM)
In our last episode, the evil Dr. Lacto had captured our hero,
Eric Pozharski <whynot>, who said:
> with <slrnqiceqd.usu.hymie> hymie! wrote:


> This self-explanatory. Compiles meets calls to 'reset()' and resolves
> them as CORE::reset, then comes re-definition,.. Which is just trown
> away -- all calls are for CORE::reset, so main::reset can be safely
> ignored.


Ah. I thought the compiler had to scan for subs first, to avoid
undefined subroutine or bare-word errors. TIL.

--hymie! hymie
Rainer Weikusat (07-11-19, 05:49 PM)
hymie! <hymie> writes:
> In our last episode, the evil Dr. Lacto had captured our hero,
> Eric Pozharski <whynot>, who said:
> Ah. I thought the compiler had to scan for subs first, to avoid
> undefined subroutine or bare-word errors. TIL.


That's not really possible because the subroutine associated with a glob
may change at runtime:

-------
print 1 + one() + two(), "\n";

sub one
{
my $r = rand();
*two = sub { $r };
2;
}
-------

Nothing is ever redefined in the code above and swapping the code and
the subroutine definition wouldn't change the outcome.

-------
sub reset
{
return 15;
}

print reset(), "\n";
--------

The subroutine defnition creates a subroutine associated with the glob
*main::reset. But as reset is a builtin, the following reset() doesn't
do a subroutine call which might find the reset subroutine, it's
translated into an invokation of op_reset. If one uses a subroutine
whose name is identical to a builtin but doesn't want to replace the
builtin reset, calls to the subroutine have to be made in a way which
forces a symbol table lookup, eg,

--------
sub reset {
return 15;
}

print main::reset() + main->reset + &reset, "\n";
---------
Eric Pozharski (07-12-19, 10:23 AM)
with <slrnqiedeu.301.hymie> hymie! wrote:
> In our last episode, the evil Dr. Lacto had captured our hero,
> Eric Pozharski <whynot>, who said:


*SKIP*
>> This self-explanatory. Compiles meets calls to 'reset()' and
>> resolves them as CORE::reset, then comes re-definition,.. Which is
>> just trown away -- all calls are for CORE::reset, so main::reset can
>> be safely ignored.

> Ah. I thought the compiler had to scan for subs first, to avoid
> undefined subroutine or bare-word errors. TIL.


Stick with this idea for a moment -- that smells static analysis. As
soon as you will see *why* static analysis is impossible for Perl your
powers will grow off limit.
gamo (07-12-19, 01:46 PM)
El 9/7/19 a las 18:08, hymie! escribi:
> The problem turned out to be that the script had a user-defined function
> named "reset" that was clashing with the built-in "reset" command.
> sub reset()
> {
> ...
> ...
> }
> So I renamed the function and everything is good now.


Good for you, respecting reserved words.

I only can suggest you english speakers advise on similar words:
init(), reinit(), renew(), even born().

But this is not the insight, brilliant responses you got.
Rainer Weikusat (07-12-19, 07:58 PM)
gamo <gamo> writes:
> El 9/7/19 a las 18:08, hymie! escribi:
> Good for you, respecting reserved words.
> I only can suggest you english speakers advise on similar words:
> init(), reinit(), renew(), even born().
> But this is not the insight, brilliant responses you got.


There aren't really reserved words in Perl: Built-in operators and
used-defined objects have separate namespaces. If Perl encounters a
bareword when expecting an operator, it basically makes a guess as to
what that's supposed to be. If its the name of a builtin, the builtin
will be used. Otherwise, a subroutine call is generated.
Similar Threads