develooper Front page | perl.perl5.porters | Postings from June 2015

Re: For 5.24: suggested incompatible changes

Thread Previous | Thread Next
From:
Reini Urban
Date:
June 29, 2015 16:27
Subject:
Re: For 5.24: suggested incompatible changes
Message ID:
BE9858D3-7F2D-44C0-9C9E-4EE407D422E9@cpanel.net

> On Jun 28, 2015, at 4:06 PM, Aristotle Pagaltzis <pagaltzis@gmx.de> wrote:
> 
> * Zefram <zefram@fysh.org> [2015-06-27 13:40]:
>> it would be nice to reduce the massive confusion people have between
>> signatures and prototypes.
> 
> Maybe someday we can add a default warning for subs outside the scope of
> the signatures feature which use the shorthand non-:prototype() form of
> prototypes. (Years down the line from non-experimental signatures, if
> ever…)

I will release it later this year, hopefully. I have different tempo and skillset than p5p.
Works fine so far in most CPAN modules, but still need to test it with the cpanel codebase.

>> Generally, prototypes are quite unpopular, so making them happen by
>> default would go down badly. (I think their unpopularity is unfair: it
>> seems to stem from some backlash at them not being signatures.)
> 
> No. It stems from prototypes disabling list flattening, which is one of
> the most fundamental design choices of Perl 5. With prototypes that do
> anything, the otherwise largely pervasive principle that you can use
> @foo in place of ($foo, $bar) gets broken. So prototypes sit at odds
> with the rest of the language.

Agreed, converting to this particular prototype which disables list flattening
should of course not be done. To break everything you can always override
it with an explicit :prototype().

> Their involvement means you cannot understand a function call just by
> looking at it; you have to look up the prototype to understand how the
> call will parse and what values will be passed. More importantly, you
> can no longer *write* calls without knowing the prototype.

> The only prototypes I consider at all sane to use are () and (&@), and
> the latter isn’t sane so much as too useful to throw away entirely.

$ ; _ and * are also useful. most of the prototypes are useful, just for run-time
resolved methods we have the dilemma. yes.

>> It is indeed a priori silly that the () prototype is a prerequisite
>> for the built-in sub constant folding, but the constant folding
>> is semantically visible, so we can't go arbitrarily changing it.
>> An explicit :fold attribute might be a better way forward.

we have two ways to fold. fold to a fast CONSTSUB without entersub
and fold to a dummy XS call with returning the value immediately.

there’s no semantic visibility of those 3 variants, other than the required () proto or the usage of use constant pragma.
there’s no semantic distinction of constant folded to CONSTSUB, dummy_xs or not constant folded subs,
other than improved run-time performance and a different internal representation.

dropping the requirement to use the () seems 
1. fair, and 
2. even other prototypes should be allowed to fold
if those parameters are ignored in the body, when at compile-time the body folds to a constant sv.

the bigger problem is when to make the inlining decision, but there must not be semantic visibility neither. 
everything needs to be transparent

> Isn’t that what :const is?

for me yes. for you :const only works with anon subs yet.
for subs annotated with :const which cannot be constant folded, a parser error will be thrown.
but it will help in the case of side effects changing a lexically closed over variable, which we cannot detect yet.
only const expressions can be closed over.

i.e.
BEGIN {
            my $x = 79907;
            *RT_79908 = sub { $x };
            $x++;
}
print RT_79908(); # not inlined, prints 79908

BEGIN {
            my $x = 79907;
            *RT_79908 = sub () { $x };
            $x++;
}
print RT_79908(); # not inlined, warns about the wrong () and prints 79908

the case of an invisible side-effect in this block cannot be detected so far, so I stay with the wrong result.

BEGIN {
            my $x = 79907;
            *RT_79908 = sub :const { $x };
            $x++;
}
print RT_79908(); # inlined, warns about the ineffective $x++ and prints 79907
if the side-effect is invisible, the warning will be omitted, but the result will still be correct.

BEGIN {
            my $x :const = 79907; # turns the padsv into a const.
            *RT_79908 = sub :const { $x };
            $x++;
}
print RT_79908(); # inlined, but errors at the wrong $x++, would print 79907
here even the invisible side-effect will croak. that’s why we prefer :const all over.

BEGIN {
            my $x :const = 79907;
            *SUB = sub :const { $g + $x };
}
print SUB(); # dies, since $g is not a visible lexical in the body.


I only added :pure to annotate side-effect freeness, to help making decisions
for compile-time caching and inlining.


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About