Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 527 forks source link

Wishlist: Overridable keywords #11869

Open p5pRT opened 12 years ago

p5pRT commented 12 years ago

Migrated from rt.perl.org#108286 (status was 'open')

Searchable as RT108286$

p5pRT commented 12 years ago

From @cpansprout

This touches on issues in tickets #84690\, #94480\, #96116\, #105924\, #105926 and #105928.

I have been thinking about this from time to time\, and I think I finally have all the edge cases worked out​:

Proposal


I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

Infix operators like ‘and’ will continue to be overridable only in non-infix positions. I.e.\, ‘use subs "and"; sub and () {} and and and’ will continue to parse as ‘&and && &and’\, as it currently does. Allowing overridable infix operators would be nice\, but is not part of this proposal. Maybe that can come later.

The keywords do\, require and glob are currently not overridable as keywords. Overrides cannot change their syntax\, but only their behaviour. In other words\, overrides of these keywords are actually callbacks\, rather than overrides.

I propose that whether overrides of those three keywords are actual keyword overrides depend on whether the ‘overrides’ feature is enabled in the scope where the subroutine is defined\, not where it is used. For XS functions\, I don’t know which way we should do it. We probably need a new XS keyword\, similar to PROTOTYPE.

I also propose that we add an :iter attribute\, that will allow custom subs to get the special defined() treatment that glob and readline get inside a while() condition. (while(glob "foo") is equivalent to while(defined(glob "foo")).)

All special-casing for parsing require VERSION should be removed from the tokenizer. ck_require can flag the op if it has a single unfolded numeric or vstring constant for its kidop. require VERSION should not delegate to a callback (‘override’) any more.

glob overrides should no longer be passed a second argument. The only code using the undocumented second argument anywhere on CPAN is in the core and can be changed.

\<> should continue to call glob and readline overrides automatically.

Reasoning


This should be in a feature feature\, because otherwise the existence of a length method will cause every subsequent use of length() in the same file to produce a warning.

do\, glob\, and require should be overridable based on the hints where the sub is defined\, not where the sub is used\, because otherwise this would violate existing subs’ expectations. Existing require subs expect to receive "Foo/Bar.pm" rather than "Foo​::Bar". A true override (with a * prototype) would leave it as "Foo​::Bar". Similarly for glob overrides​: an existing custom glob function might expect the automatic defined() in while(glob()).

The purpose of the :iter attribute is to avoid adding too many more hacks to fix bug #84690. It also allows true glob overrides to retain that feature.

Parsing of require VERSION is currently very screwy. It is not even consistent with itself. require also has the num/str bug\, in that it tries to decide based on the type of its operand whether it will be a version number or a file name. We cannot fix that bug unless we make require VERSION a *syntactic* special case. In that case require $version would no longer work (thank goodness!). That means that require overrides would no longer be able to do CORE​::require($_[0])\, unless we stop calling the override in the case of a version number. That would apply only to ‘callback-style’ overrides; i.e.\, the old kind. require overrides defined under ‘use feature "overrides"’ would be true overrides which would not go through the special parsing at all\, but would be required (i.e.\, allowed) to implement it themselves\, if at all.

My reason for putting require parsing in this ticket is that it is inextricably linked to the overrides feature. It’s hard to change one without the other.

The reason for eliminating the second argument to glob() (did you even know about it?) is that \<> will continue to call glob overrides\, and glob implementations that want to accept lists will still be expected to handle \<>’s calling convention.


Flags​:   category=wishlist   severity=low


Site configuration information for perl 5.15.6​:

Configured by sprout at Sat Dec 31 10​:12​:16 PST 2011.

Summary of my perl5 (revision 5 version 15 subversion 6) configuration​:   Local Commit​: b2635083831c8935c437465bbeb03aec8b599c01   Ancestor​: 407287f90891c4292ac8268e6566164f3992e28e   Platform​:   osname=darwin\, osvers=10.5.0\, archname=darwin-thread-multi-2level   uname='darwin pint.local 10.5.0 darwin kernel version 10.5.0​: fri nov 5 23​:20​:39 pdt 2010; root​:xnu-1504.9.17~1release_i386 i386 '   config_args='-de -Dusedevel -Duseithreads -DDEBUGGING -Dmad'   hint=recommended\, useposix=true\, d_sigaction=define   useithreads=define\, usemultiplicity=define   useperlio=define\, d_sfio=undef\, uselargefiles=define\, usesocks=undef   use64bitint=undef\, use64bitall=undef\, uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cc'\, ccflags ='-fno-common -DPERL_DARWIN -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'\,   optimize='-O3 -g'\,   cppflags='-fno-common -DPERL_DARWIN -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'   ccversion=''\, gccversion='4.2.1 (Apple Inc. build 5664)'\, gccosandvers=''   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8   alignbytes=8\, prototype=define   Linker and Libraries​:   ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc'\, ldflags =' -fstack-protector -L/usr/local/lib'   libpth=/usr/local/lib /usr/lib   libs=-ldbm -ldl -lm -lutil -lc   perllibs=-ldl -lm -lutil -lc   libc=\, so=dylib\, useshrplib=false\, libperl=libperl.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=bundle\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags=' '\, lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches​:  


@​INC for perl 5.15.6​:   /usr/local/lib/perl5/site_perl/5.15.6/darwin-thread-multi-2level   /usr/local/lib/perl5/site_perl/5.15.6   /usr/local/lib/perl5/5.15.6/darwin-thread-multi-2level   /usr/local/lib/perl5/5.15.6   /usr/local/lib/perl5/site_perl   .


Environment for perl 5.15.6​:   DYLD_LIBRARY_PATH (unset)   HOME=/Users/sprout   LANG=en_US.UTF-8   LANGUAGE (unset)   LD_LIBRARY_PATH (unset)   LOGDIR (unset)   PATH=/usr/bin​:/bin​:/usr/sbin​:/sbin​:/usr/local/bin​:/usr/X11/bin​:/usr/local/bin   PERL_BADLANG (unset)   SHELL=/bin/bash

p5pRT commented 12 years ago

From @sciurius

Father Chrysostomos (via RT) \perlbug\-followup@&#8203;perl\.org writes​:

I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

I'll bite... I think it's a good plan.

-- Johan

p5pRT commented 12 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 12 years ago

From @cpansprout

On Mon Jan 16 10​:35​:58 2012\, jv wrote​:

Father Chrysostomos (via RT) \perlbug\-followup@&#8203;perl\.org writes​:

I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

I'll bite... I think it's a good plan.

I plan to implement it for 5.18.

--

Father Chrysostomos

p5pRT commented 12 years ago

From [Unknown Contact. See original ticket]

On Mon Jan 16 10​:35​:58 2012\, jv wrote​:

Father Chrysostomos (via RT) \perlbug\-followup@&#8203;perl\.org writes​:

I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

I'll bite... I think it's a good plan.

I plan to implement it for 5.18.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @rjbs

* Father Chrysostomos via RT \perlbug\-comment@&#8203;perl\.org [2012-01-16T16​:28​:49]

I plan to implement it for 5.18.

I look forward to thinking more about it and poking at your work :)

-- rjbs

p5pRT commented 12 years ago

From @cpansprout

On Mon Jan 16 10​:35​:58 2012\, jv wrote​:

Father Chrysostomos (via RT) \perlbug\-followup@&#8203;perl\.org writes​:

I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

I'll bite... I think it's a good plan.

But there is one thing my plans did not address​: How should elsif and else work? If elsif is overridable like any other keyword\, then what happens in cases like this?

  use feature 'overrides';   use subs 'else';   sub else(&) { die }   if ($x) { }   else { }

Is else considered part of the if() statement\, such that the presence of if() causes else to be interpreted as the built-in keyword?

Or is else a keyword in its own right\, so the override kicks in\, compiling the above as

  if ($x) { }   &else(sub { });

?

If the former\, then is there any need for else and elsif to be considered keywords outside of their if() context?

--

Father Chrysostomos

p5pRT commented 12 years ago

From [Unknown Contact. See original ticket]

On Mon Jan 16 10​:35​:58 2012\, jv wrote​:

Father Chrysostomos (via RT) \perlbug\-followup@&#8203;perl\.org writes​:

I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

I'll bite... I think it's a good plan.

But there is one thing my plans did not address​: How should elsif and else work? If elsif is overridable like any other keyword\, then what happens in cases like this?

  use feature 'overrides';   use subs 'else';   sub else(&) { die }   if ($x) { }   else { }

Is else considered part of the if() statement\, such that the presence of if() causes else to be interpreted as the built-in keyword?

Or is else a keyword in its own right\, so the override kicks in\, compiling the above as

  if ($x) { }   &else(sub { });

?

If the former\, then is there any need for else and elsif to be considered keywords outside of their if() context?

--

Father Chrysostomos

p5pRT commented 12 years ago

From @sciurius

"Father Chrysostomos via RT" \perlbug\-comment@&#8203;perl\.org writes​:

But there is one thing my plans did not address​: How should elsif and else work? If elsif is overridable like any other keyword\, then what happens in cases like this?

Suggestion​: Do not allow if\, else\, elseif to be overridden independently but treat them as one set of keywords.

So you either override them all\, or none.

Does that make sense?

-- Johan

p5pRT commented 12 years ago

From j.imrie1@virginmedia.com

On 04/04/2012 19​:58\, Johan Vromans wrote​:

"Father Chrysostomos via RT"\perlbug\-comment@&#8203;perl\.org writes​:

But there is one thing my plans did not address​: How should elsif and else work? If elsif is overridable like any other keyword\, then what happens in cases like this? Suggestion​: Do not allow if\, else\, elseif to be overridden independently but treat them as one set of keywords.

So you either override them all\, or none.

Does that make sense?

-- Johan Opposing suggestion​: Allow overriding of if\, else and elsif to be overridden independently but make

CORE​::KEYWORD​::if etc. have the default semantics.

John

p5pRT commented 12 years ago

From @ikegami

On Sun\, Jan 15\, 2012 at 3​:51 PM\, Father Chrysostomos \< perlbug-followup@​perl.org> wrote​:

# New Ticket Created by Father Chrysostomos # Please include the string​: [perl #108286] # in the subject line of all future correspondence about this issue. # \<URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=108286 >

This touches on issues in tickets #84690\, #94480\, #96116\, #105924\, #105926 and #105928.

I have been thinking about this from time to time\, and I think I finally have all the edge cases worked out​:

Proposal --------

I propose that we make ‘use feature "overrides"’ allow all keywords to be overridden.

What do you mean by overriding a keyword? Do you mean a Perl-accessible version of PL_keyword_plugin (i.e. the keyword introduces your own grammar rule)? Do you mean the ability to pass them to "use subs"?

p5pRT commented 12 years ago

From @ikegami

On Wed\, Apr 4\, 2012 at 11​:50 AM\, Father Chrysostomos via RT \< perlbug-comment@​perl.org> wrote​:

But there is one thing my plans did not address​: How should elsif and else work?

If elsif is overridable like any other keyword\, then what happens in cases like this?

use feature 'overrides'; use subs 'else'; sub else(&) { die } if ($x) { } else { }

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

If by overriding a keyword you mean altering its syntax to something of the user's choice\, and if you want to change "else"'s syntax\, override "if" and "unless".

If by overriding a keyword you mean giving the ability to create functions with the same name\, and if you want create a sub called "else"\, the sub call can be disambiguated with a leading ";"\, or even "&" (although the latter disables prototypes).

- Eric

p5pRT commented 12 years ago

From @cpansprout

On Wed Apr 04 13​:53​:55 2012\, ikegami@​adaelis.com wrote​:

On Wed\, Apr 4\, 2012 at 11​:50 AM\, Father Chrysostomos via RT \< perlbug-comment@​perl.org> wrote​:

But there is one thing my plans did not address​: How should elsif and else work?

If elsif is overridable like any other keyword\, then what happens in cases like this?

use feature 'overrides'; use subs 'else'; sub else(&) { die } if ($x) { } else { }

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

If by overriding a keyword you mean altering its syntax to something of the user's choice\, and if you want to change "else"'s syntax\, override "if" and "unless".

If by overriding a keyword you mean giving the ability to create functions with the same name\,

That is what I mean.

and if you want create a sub called "else"\, the sub call can be disambiguated with a leading ";"\, or even "&" (although the latter disables prototypes).

Your suggestion sounds good to me.

--

Father Chrysostomos

p5pRT commented 12 years ago

From [Unknown Contact. See original ticket]

On Wed Apr 04 13​:53​:55 2012\, ikegami@​adaelis.com wrote​:

On Wed\, Apr 4\, 2012 at 11​:50 AM\, Father Chrysostomos via RT \< perlbug-comment@​perl.org> wrote​:

But there is one thing my plans did not address​: How should elsif and else work?

If elsif is overridable like any other keyword\, then what happens in cases like this?

use feature 'overrides'; use subs 'else'; sub else(&) { die } if ($x) { } else { }

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

If by overriding a keyword you mean altering its syntax to something of the user's choice\, and if you want to change "else"'s syntax\, override "if" and "unless".

If by overriding a keyword you mean giving the ability to create functions with the same name\,

That is what I mean.

and if you want create a sub called "else"\, the sub call can be disambiguated with a leading ";"\, or even "&" (although the latter disables prototypes).

Your suggestion sounds good to me.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @cpansprout

On Wed Apr 04 13​:53​:55 2012\, ikegami@​adaelis.com wrote​:

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

In that case\, is there any reason why elsif needs to be a reserved word outside of that context?

I’m also trying to plan ahead with regard to adding all keywords to the CORE​:: namespace.

It should be possible in the future for the ‘if’ keyword to be implemented as a CV named &CORE​::if\, which has its own custom parser that eats the elsif and else keywords.

But it won’t make much sense for there to be a &CORE​::elsif subroutine. It would just be a stub that produces a syntax error when inlined. Maybe that does make sense. Then we could always change it later.

--

Father Chrysostomos

p5pRT commented 12 years ago

From [Unknown Contact. See original ticket]

On Wed Apr 04 13​:53​:55 2012\, ikegami@​adaelis.com wrote​:

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

In that case\, is there any reason why elsif needs to be a reserved word outside of that context?

I’m also trying to plan ahead with regard to adding all keywords to the CORE​:: namespace.

It should be possible in the future for the ‘if’ keyword to be implemented as a CV named &CORE​::if\, which has its own custom parser that eats the elsif and else keywords.

But it won’t make much sense for there to be a &CORE​::elsif subroutine. It would just be a stub that produces a syntax error when inlined. Maybe that does make sense. Then we could always change it later.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @ikegami

On Sun\, Apr 22\, 2012 at 1​:41 AM\, Father Chrysostomos via RT \< perlbug-comment@​perl.org> wrote​:

On Wed Apr 04 13​:53​:55 2012\, ikegami@​adaelis.com wrote​:

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

In that case\, is there any reason why elsif needs to be a reserved word outside of that context?

I was wondering that myself when I typed the above. We allow C\<\< sub if { }

\, so why not C\<\< sub elsif { } >>?

I'm not seeing the value of C\<\< elsif(); >> being a syntax error. The two reasons I can come up for continuing to be a syntax error are confusion avoidance and syntax error detection\, but neither reason is valid. We already allow C\<\< sub if { } >>\, and C\<\< elsif (...) { ... } >> would still be a syntax error if C\<\< elsif(...); >> isn't.

p5pRT commented 12 years ago

From @cpansprout

On Sun Apr 22 13​:25​:19 2012\, ikegami@​adaelis.com wrote​:

On Sun\, Apr 22\, 2012 at 1​:41 AM\, Father Chrysostomos via RT \< perlbug-comment@​perl.org> wrote​:

On Wed Apr 04 13​:53​:55 2012\, ikegami@​adaelis.com wrote​:

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

In that case\, is there any reason why elsif needs to be a reserved word outside of that context?

I was wondering that myself when I typed the above. We allow C\<\< sub if { }

\, so why not C\<\< sub elsif { } >>?

I'm not seeing the value of C\<\< elsif(); >> being a syntax error.

Allowing C\<\< sub elsif { } >> and having C\<\< elsif(); >> be a syntax error by default are not exclusive.

The real question is​: Without an imported override named elsif\, what should elsif(); do?

Another way of putting it​: Should there by a sub named CORE​::elsif that produces a syntax error when inlined? Or should there be no CORE​::elsif sub at all\, elsif only being treated as a keyword after if(){} or elsif{}?

I’m leaning toward the former right now\, as it avoids changing the behaviour unnecessarily.

The two reasons I can come up for continuing to be a syntax error are confusion avoidance and syntax error detection\, but neither reason is valid. We already allow C\<\< sub if { } >>\, and C\<\< elsif (...) { ... } >> would still be a syntax error if C\<\< elsif(...); >> isn't.

With custom call parsers\, elsif(){} could be valid syntax even with a sub named elsif :-).

--

Father Chrysostomos

p5pRT commented 12 years ago

From [Unknown Contact. See original ticket]

On Sun Apr 22 13​:25​:19 2012\, ikegami@​adaelis.com wrote​:

On Sun\, Apr 22\, 2012 at 1​:41 AM\, Father Chrysostomos via RT \< perlbug-comment@​perl.org> wrote​:

On Wed Apr 04 13​:53​:55 2012\, ikegami@​adaelis.com wrote​:

The builtin "if" should expect the following to follow it (ignoring whitespace)

"(" EXPR ")" BLOCK ( "elsif" "(" EXPR ")" BLOCK )* ( "else" BLOCK )?

None of those tokens should be overridable when parsing that rule (although EXPR and BLOCK may use overridden tokens).

In that case\, is there any reason why elsif needs to be a reserved word outside of that context?

I was wondering that myself when I typed the above. We allow C\<\< sub if { }

\, so why not C\<\< sub elsif { } >>?

I'm not seeing the value of C\<\< elsif(); >> being a syntax error.

Allowing C\<\< sub elsif { } >> and having C\<\< elsif(); >> be a syntax error by default are not exclusive.

The real question is​: Without an imported override named elsif\, what should elsif(); do?

Another way of putting it​: Should there by a sub named CORE​::elsif that produces a syntax error when inlined? Or should there be no CORE​::elsif sub at all\, elsif only being treated as a keyword after if(){} or elsif{}?

I’m leaning toward the former right now\, as it avoids changing the behaviour unnecessarily.

The two reasons I can come up for continuing to be a syntax error are confusion avoidance and syntax error detection\, but neither reason is valid. We already allow C\<\< sub if { } >>\, and C\<\< elsif (...) { ... } >> would still be a syntax error if C\<\< elsif(...); >> isn't.

With custom call parsers\, elsif(){} could be valid syntax even with a sub named elsif :-).

--

Father Chrysostomos

p5pRT commented 12 years ago

From @cpansprout

On Sun Jan 15 12​:51​:08 2012\, sprout wrote​:

I also propose that we add an :iter attribute\, that will allow custom subs to get the special defined() treatment that glob and readline get inside a while() condition. (while(glob "foo") is equivalent to while(defined(glob "foo")).)

Actually\, it’s equivalent to while(defined($_ = glob "foo")).

Interestingly\, while($x=\) did not get the special treatment until commit 4b161ae29769\, which I think was somewhere on the 5.004 maint branch.

Commit 4b161ae29769 also made while($x=each %foo) get wrapped in defined()\, but did not affect while(each %foo)\, which gets neither defined() nor $_=.

Was $_= omitted to avoid backward-compatibility problems\, or was it an oversight? Was it simply an oversight that defined() was omitted in that case?

The reason I ask is that it would be nice if we could make this all consistent\, but there may be good reasons why we cannot.

I also need to know how this will affect my :iter proposal. Based on the precedent set by ‘each’\, while($x=itersub) should become while(defined($x=itersub)). But what should happen for while(itersub)? Should it stay as it is (like each)? Should it become while(defined($_=itersub)) like readline? Or should we take a middle ground\, and make it while(defined(itersub))?

Also\, as long as ‘each’ follows its own rules\, how is one to override it with another iterator function\, while preserving exactly the same syntax?

Maybe in the end we need to let the iter sub itself decide\, and while() could call it with a special param\, or a package variable (like $AUTOLOAD)\, or *somehow* signal it to tell it that it is in a while().

--

Father Chrysostomos

p5pRT commented 12 years ago

From [Unknown Contact. See original ticket]

On Sun Jan 15 12​:51​:08 2012\, sprout wrote​:

I also propose that we add an :iter attribute\, that will allow custom subs to get the special defined() treatment that glob and readline get inside a while() condition. (while(glob "foo") is equivalent to while(defined(glob "foo")).)

Actually\, it’s equivalent to while(defined($_ = glob "foo")).

Interestingly\, while($x=\) did not get the special treatment until commit 4b161ae29769\, which I think was somewhere on the 5.004 maint branch.

Commit 4b161ae29769 also made while($x=each %foo) get wrapped in defined()\, but did not affect while(each %foo)\, which gets neither defined() nor $_=.

Was $_= omitted to avoid backward-compatibility problems\, or was it an oversight? Was it simply an oversight that defined() was omitted in that case?

The reason I ask is that it would be nice if we could make this all consistent\, but there may be good reasons why we cannot.

I also need to know how this will affect my :iter proposal. Based on the precedent set by ‘each’\, while($x=itersub) should become while(defined($x=itersub)). But what should happen for while(itersub)? Should it stay as it is (like each)? Should it become while(defined($_=itersub)) like readline? Or should we take a middle ground\, and make it while(defined(itersub))?

Also\, as long as ‘each’ follows its own rules\, how is one to override it with another iterator function\, while preserving exactly the same syntax?

Maybe in the end we need to let the iter sub itself decide\, and while() could call it with a special param\, or a package variable (like $AUTOLOAD)\, or *somehow* signal it to tell it that it is in a while().

--

Father Chrysostomos

p5pRT commented 12 years ago

From @ikegami

On Sun\, Apr 22\, 2012 at 4​:56 PM\, Father Chrysostomos via RT \< perlbug-comment@​perl.org> wrote​:

Another way of putting it​: Should there by a sub named CORE​::elsif that produces a syntax error when inlined? Or should there be no CORE​::elsif sub at all\, elsif only being treated as a keyword after if(){} or elsif{}?

I’m leaning toward the former right now\, as it avoids changing the behaviour unnecessarily.

Would you recommend this behaviour to someone else? Say someone introduces a C\<\< with ... in ... >> statement. Should they override C\<\< in >> so that C\<\< in(); >> is a syntax error?

It's going to be fun telling people that Perl goes out of its way to make C\<\< elsif(); >> a syntax error just so users can ask Perl not to make it a syntax error.

- Eric

p5pRT commented 12 years ago

From @ap

* Father Chrysostomos via RT \perlbug\-comment@&#8203;perl\.org [2012-04-22 23​:45]​:

I also need to know how this will affect my :iter proposal. Based on the precedent set by ‘each’\, while($x=itersub) should become while(defined($x=itersub)).

Should it?

There is a bit of a problem there\, isn’t it? The protocol with undef obviously makes sense for `each` as a hash key can never be undef. But when iterating arbitrarily (e.g. converting an array to an iter)\, undef becomes a valid value\, no?

So you cannot use it to abort iteration… unless you contrive something contorted like returning a scalarref to the real value on every successful iteration (thus turning undef in the data into \undef which is true) and then an undef once you are done.

But what should happen for while(itersub)? Should it stay as it is (like each)? Should it become while(defined($_=itersub)) like readline? Or should we take a middle ground\, and make it while(defined(itersub))?

I would tend to go with adding the $_ assignment by default\, including adding it to `while(each %foo)` retroactively\, if a scan of the CPAN shows this to be viable without breaking huge swathes of code. It seems the Perlish approach to take.

But\, extending its coverage to arbitrary user-defined function concerns me to some extent. As long as only `each`\, `glob`\, and `readline` get this treatment\, it is predictable what code will do. But if potentially any sub could get it\, then looking at

  while (foo $bar\, $baz) { ... }

without knowing the definition of `foo` will not tell whether this code will molest $_.

Also\, as long as ‘each’ follows its own rules\, how is one to override it with another iterator function\, while preserving exactly the same syntax?

Simple\, you have to ensure that your overridden `each` has the exact same semantics i.e. it can never return undef as part of the data. I see no problem here.

Maybe in the end we need to let the iter sub itself decide\, and while() could call it with a special param\, or a package variable (like $AUTOLOAD)\, or *somehow* signal it to tell it that it is in a while().

Please let’s not. I like this least of all options.

Regards\, -- Aristotle Pagaltzis // \<http​://plasmasturm.org/>

p5pRT commented 12 years ago

From @ap

* Aristotle Pagaltzis \pagaltzis@&#8203;gmx\.de [2012-04-23 12​:01]​:

The protocol with undef obviously makes sense for `each` as a hash key can never be undef. But when iterating arbitrarily (e.g. converting an array to an iter)\, undef becomes a valid value\, no?

So you cannot use it to abort iteration… unless you contrive something contorted like returning a scalarref to the real value on every successful iteration (thus turning undef in the data into \undef which is true) and then an undef once you are done.

Hmm. Now I am wondering how contrived that really is. I wonder if this could be baked into the protocol\, i.e. an :iter function returning any value other than undef or a reference would throw an exception.

Then unpacking a scalarref into $_ could be baked right into the `while` magic (returning other types of reference would be allowed but they would\, obviously\, not be automatically deref’d) and you could write Perlishly concise iterating loops at the price of a single backslash in your iterator functions.

Warning​: highly experimental. I am a long way from thinking through all the implications\, the automatic deref in particular may turn out to be a terrible idea in practice.

But if the pieces come together then I would be eager to prototype this somewhere to see how well it holds up.

If we could get a solid\, supported iteration mechanism right into core that would *rock*. E.g. I remember the struggles PSGI went through for lack of in-core iterators.

Regards\, -- Aristotle Pagaltzis // \<http​://plasmasturm.org/>

p5pRT commented 12 years ago

From @nwc10

On Sun\, Apr 22\, 2012 at 02​:43​:25PM -0700\, Father Chrysostomos via RT wrote​:

On Sun Jan 15 12​:51​:08 2012\, sprout wrote​:

I also propose that we add an :iter attribute\, that will allow custom subs to get the special defined() treatment that glob and readline get inside a while() condition. (while(glob "foo") is equivalent to while(defined(glob "foo")).)

Actually\, it's equivalent to while(defined($_ = glob "foo")).

Interestingly\, while($x=\) did not get the special treatment until commit 4b161ae29769\, which I think was somewhere on the 5.004 maint branch.

Commit 4b161ae29769 also made while($x=each %foo) get wrapped in defined()\, but did not affect while(each %foo)\, which gets neither defined() nor $_=.

Was $_= omitted to avoid backward-compatibility problems\, or was it an oversight? Was it simply an oversight that defined() was omitted in that case?

I think that $_ = being ommitted on while(each %foo) is not an oversight at that time.

That commit you quote gets me back to this message from Larry​:

  As usual\, when there are long arguments\, there are good arguments for both   sides (mixed in with the chaff). In this case\, let's make  
  while ($x = \)  
  equivalent to  
  while (defined($x = \))  
  (But nothing more complicated than an assignment should assume defined().)

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1998-04/msg00133.html

Nick Ing-Simmons asks for a clarification​:

  Thanks Larry - that is what the patch I posted does.  
  But it also does the same for C\\, C\ and C\ -   i.e. the same cases that solicit the warning in 5.004 is extending   the defined insertion to those cases desirable?   (glob and readdir seem to make sense\, I am less sure about each).

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1998-04/msg00182.html

(it's clarified in a later message that Nick I-S hadn't realised that each in *scalar* context returns the keys\, so it's an analogous iterator which can't return undef for any entry)

In turn\, the "RULING" dates back to this thread/request​:

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1998-03/msg01630.html

which also generates a massive thread\, of which this message is probably most insightful​:

  Pray tell how you can tell that the code is broken without comments in the   code explaining what they expected it to do. while ($x = \<>) is legal   code and works as documented. It does not use the idiom of while (\<>).  
  You can't just say "this code is broken" about while ($x = \<>) *in all   cases* without more context to indicate the expected behaviour.

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1998-03/msg01966.html

in turn that seems to be a reaction to these warnings added in 5.004

$ ./perl -lwe 'while ($a = each %a) {}' Value of each() operator can be "0"; test with defined() at -e line 1.

[strictly as far as git has it\, most this commit​:

commit a60067777be62ee91d1318f9ae26d9ed713245de Author​: Perl 5 Porters \perl5\-porters@&#8203;africa\.nicoh\.com Date​: Wed Jan 1 08​:59​:00 1997 +1200

  [inseparable changes from patch from perl5.003_17 to perl5.003_18]  
  CORE LANGUAGE CHANGES  
...

  Subject​: Warn on '{if\,while} ($x = X)' where X is glob\, readdir\, or \   From​: Chip Salzenberg \chip@&#8203;atlantic\.net   Files​: op.c pod/perldiag.pod

...

as determined by

.../bisect.pl --end perl-5.004 -lwe 'BEGIN {$SIG{__WARN__} = sub {++$b}}; while ($a = \<>) {++$a}; exit $b' \</dev/null

and the each warning in this commit​:

commit 68dc074516a6859e3424b48d1647bcb08b1a1a7d Author​: Perl 5 Porters \perl5\-porters@&#8203;africa\.nicoh\.com Date​: Sun Mar 9 11​:57​:19 1997 +1200   [inseparable changes from match from perl-5.003_93 to perl-5.003_94]

...

  Subject​: Warn on C\<while ($x = each %y) {}>   From​: Chip Salzenberg \chip@&#8203;perl\.com   Files​: op.c pod/perldiag.pod

as determined by

.../bisect.pl --end perl-5.004 -lwe 'BEGIN {$SIG{__WARN__} = sub {++$b}}; while ($a = each %a) {}; exit $b'

]

The rational for the former commit is detailed in the thread starting here​:

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/9612/msg02125.html

the latter in these messages

http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1997-03/msg01263.html http​://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1997-03/msg01302.html

The intent of the changes appears to be to retain the 5.003 and earlier behaviour on what gets assigned for each construction\, but change the loop behaviour to terminate on undefined rather than simply falsehood for the common simple cases​:

  while (OP ...)

and

  while ($var = OP ...)

The mail archives from 1997 are fascinating. Lots of messages. Lots of design discussions\, not always helpful. And some of the same unanswered questions as today.

Nicholas Clark

p5pRT commented 12 years ago

From dcmertens.perl@gmail.com

Can someone point me to the discussion where it was decided that overriding if() was a good idea? It seems to have sprung out of nowhere in this discussion. I skimmed through the related tickets but only saw discussion of glob(). Did I miss it?

Thanks! David

-- "Debugging is twice as hard as writing the code in the first place.   Therefore\, if you write the code as cleverly as possible\, you are\,   by definition\, not smart enough to debug it." -- Brian Kernighan

p5pRT commented 12 years ago

From @cpansprout

On Mon Apr 23 14​:20​:09 2012\, dcmertens.perl@​gmail.com wrote​:

Can someone point me to the discussion where it was decided that overriding if() was a good idea? It seems to have sprung out of nowhere in this discussion. I skimmed through the related tickets but only saw discussion of glob(). Did I miss it?

Overriding if() and being *able* to override if() are two different things.

Anyone who overrides if() is probably asking for trouble.

But it would be nice to override length() and vec(). Where do we draw the line? Or\, rather\, why do we need to draw a line? Instead of debating over every keyword about whether it should be overridable\, let’s just make them all overridable\, allowing smarter people to do things we haven’t thought of.

I only brought up if() in particular because it can have elsif attached to it\, and we need to figure out how things are going to fit together.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @cpansprout

On Mon Apr 23 14​:03​:27 2012\, nicholas wrote​:

The intent of the changes appears to be to retain the 5.003 and earlier behaviour on what gets assigned for each construction\, but change the loop behaviour to terminate on undefined rather than simply falsehood for the common simple cases​:

while \(OP \.\.\.\)

and

while \($var = OP \.\.\.\)

Except that while($var = each %h) implies defined()\, but while(each %h) does not. So something got screwed up. :-)

--

Father Chrysostomos

p5pRT commented 12 years ago

From @cpansprout

Χριστὸς ἀνέστη!

On Mon Apr 23 03​:03​:36 2012\, aristotle wrote​:

* Aristotle Pagaltzis \pagaltzis@&#8203;gmx\.de [2012-04-23 12​:01]​:

The protocol with undef obviously makes sense for `each` as a hash key can never be undef. But when iterating arbitrarily (e.g. converting an array to an iter)\, undef becomes a valid value\, no?

So you cannot use it to abort iteration… unless you contrive something contorted like returning a scalarref to the real value on every successful iteration (thus turning undef in the data into \undef which is true) and then an undef once you are done.

Hmm. Now I am wondering how contrived that really is. I wonder if this could be baked into the protocol\, i.e. an :iter function returning any value other than undef or a reference would throw an exception.

Then unpacking a scalarref into $_ could be baked right into the `while` magic (returning other types of reference would be allowed but they would\, obviously\, not be automatically deref’d) and you could write Perlishly concise iterating loops at the price of a single backslash in your iterator functions.

Warning​: highly experimental. I am a long way from thinking through all the implications\, the automatic deref in particular may turn out to be a terrible idea in practice.

This reference interface would make the sub practically unusable outside of a while loop.

But if the pieces come together then I would be eager to prototype this somewhere to see how well it holds up.

I’ve already been thinking about that. This would require hooking PL_check or something to intercept how while loops are compiled. And then\, to work with closures\, we would have to associate the attribute with the address of the op tree. I can already see how that could be accomplished\, without memory leaks\, using tied field hashes.

If we could get a solid\, supported iteration mechanism right into core that would *rock*.

But we may end up with too many variations that are all equally good\, but designed for different circumstances. Maybe in the end the core docs could recommend Sub​::Iter (or whatever name it gets)\, they way they do Unicode​::Casing.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @cpansprout

On Mon Apr 23 15​:19​:09 2012\, sprout wrote​:

I’ve already been thinking about that. This would require hooking PL_check or something to intercept how while loops are compiled. And then\, to work with closures\, we would have to associate the attribute with the address of the op tree. I can already see how that could be accomplished\, without memory leaks\, using tied field hashes.

In fact\, in the process of thinking about this and considering where the attribute could be stored\, I’ve noticed that cv_clone doesn’t copy magic\, which means that call checkers added in attribute handlers won’t apply to closures cloned therefrom. I think this is clearly a bug. But (and this question is aimed mostly at Zefram) would copying the magic be the best solution? Is there a standard way of copying magic already that cv_clone can use?

--

Father Chrysostomos

p5pRT commented 12 years ago

From dcmertens.perl@gmail.com

Got it. That makes sense. Stories about rope come to mind.

Thanks! David

On Mon\, Apr 23\, 2012 at 4​:55 PM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

On Mon Apr 23 14​:20​:09 2012\, dcmertens.perl@​gmail.com wrote​:

Can someone point me to the discussion where it was decided that overriding if() was a good idea? It seems to have sprung out of nowhere in this discussion. I skimmed through the related tickets but only saw discussion of glob(). Did I miss it?

Overriding if() and being *able* to override if() are two different things.

Anyone who overrides if() is probably asking for trouble.

But it would be nice to override length() and vec(). Where do we draw the line? Or\, rather\, why do we need to draw a line? Instead of debating over every keyword about whether it should be overridable\, let’s just make them all overridable\, allowing smarter people to do things we haven’t thought of.

I only brought up if() in particular because it can have elsif attached to it\, and we need to figure out how things are going to fit together.

--

Father Chrysostomos

--- via perlbug​: queue​: perl5 status​: open https://rt-archive.perl.org/perl5/Ticket/Display.html?id=108286

-- "Debugging is twice as hard as writing the code in the first place.   Therefore\, if you write the code as cleverly as possible\, you are\,   by definition\, not smart enough to debug it." -- Brian Kernighan

p5pRT commented 12 years ago

From @Leont

On Tue\, Apr 24\, 2012 at 12​:21 AM\, Father Chrysostomos via RT \perlbug\-followup@&#8203;perl\.org wrote​:

In fact\, in the process of thinking about this and considering where the attribute could be stored\, I’ve noticed that cv_clone doesn’t copy magic\, which means that call checkers added in attribute handlers won’t apply to closures cloned therefrom.  I think this is clearly a bug.  But (and this question is aimed mostly at Zefram) would copying the magic be the best solution?  Is there a standard way of copying magic already that cv_clone can use?

That's what mg_copy is for\, assuming the magic has a copy method implemented (I think it doesn't).

Leon

p5pRT commented 12 years ago

From @Leont

On Tue\, Apr 24\, 2012 at 12​:41 AM\, Leon Timmermans \fawaka@&#8203;gmail\.com wrote​:

That's what mg_copy is for\, assuming the magic has a copy method implemented (I think it doesn't).

No\, that's wrong. It's mg_dup. I hate how confusing those two names are.

Leon

p5pRT commented 12 years ago

From @cpansprout

On Mon Apr 23 15​:19​:09 2012\, sprout wrote​:

And then\, to work with closures\, we would have to associate the attribute with the address of the op tree. I can already see how that could be accomplished\, without memory leaks\, using tied field hashes.

That’s assuming that the prototype is never freed before the closure cloned from it.

Is that always the case?

As I understand it\, the closure references the subroutine outside of it. That subroutine’s op tree references the closure prototype. Is that right?

--

Father Chrysostomos

p5pRT commented 12 years ago

From @cpansprout

On Mon Apr 23 16​:26​:04 2012\, LeonT wrote​:

On Tue\, Apr 24\, 2012 at 12​:41 AM\, Leon Timmermans \fawaka@&#8203;gmail\.com wrote​:

That's what mg_copy is for\, assuming the magic has a copy method implemented (I think it doesn't).

No\, that's wrong. It's mg_dup. I hate how confusing those two names are.

I’ve just had a look at the code\, and I see that mg_dup is defined only under threads. So I don’t think it is what I want. And I think you were right the first time. So\, thank you.

What is the significance of the return value of mg_copy? It seems to be the number of magic structs copied. But it is always called in void context\, at least in core.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @nwc10

On Mon\, Apr 23\, 2012 at 03​:13​:39PM -0700\, Father Chrysostomos via RT wrote​:

On Mon Apr 23 14​:03​:27 2012\, nicholas wrote​:

The intent of the changes appears to be to retain the 5.003 and earlier behaviour on what gets assigned for each construction\, but change the loop behaviour to terminate on undefined rather than simply falsehood for the common simple cases​:

while \(OP \.\.\.\)

and

while \($var = OP \.\.\.\)

Except that while($var = each %h) implies defined()\, but while(each %h) does not. So something got screwed up. :-)

Yes. I *thought* that question was about while(each %h) [not] assigning to $_\, but I missed the [not] using defined.

Pretty sure that the intent was that the intent at the time was to change it to use defined. And I'd guess that it was missed because it's not the same opcode structure.

So that's a bug?

Nicholas Clark

p5pRT commented 12 years ago

From @sciurius

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org writes​:

Overriding if() and being *able* to override if() are two different things.

Indeed. But I remember long discussions on making changes to perl "just because we can".

Anyone who overrides if() is probably asking for trouble. But it would be nice to override length() and vec(). Where do we draw the line?

Precisely \<-- HERE. Functions like vec() and length() can be overridden\, but control keywords like if and when and while can not.

Writing it as if() doesn't make it similar to vec() or length().

Or\, rather\, why do we need to draw a line? Instead of debating over every keyword about whether it should be overridable\, ...

Drawing a line means there's a vast group of keywords (functions) that can be overridden\, a smaller group that can not\, and maybe a few dubious cases that need discussion. Doesn't sounds that hard to me.

...let’s just make them all overridable\, allowing smarter people to do things we haven’t thought of.

This would be okay if we can be 100% sure that changes like these do not introduce additional code complexity and other future maintenance problems. "Oh no\, we cannot remove this because we have once said that it would be possible and maybe there's someone on earth actually using it".

Let's be a bit careful.

-- Johan

p5pRT commented 12 years ago

From dcmertens.perl@gmail.com

On Apr 24\, 2012 3​:10 AM\, "Johan Vromans" \jvromans@&#8203;squirrel\.nl wrote​:

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org writes​:

Overriding if() and being *able* to override if() are two different things.

Indeed. But I remember long discussions on making changes to perl "just because we can".

Anyone who overrides if() is probably asking for trouble. But it would be nice to override length() and vec(). Where do we draw the line?

Precisely \<-- HERE. Functions like vec() and length() can be overridden\, but control keywords like if and when and while can not.

Writing it as if() doesn't make it similar to vec() or length().

Or\, rather\, why do we need to draw a line? Instead of debating over every keyword about whether it should be overridable\, ...

Drawing a line means there's a vast group of keywords (functions) that can be overridden\, a smaller group that can not\, and maybe a few dubious cases that need discussion. Doesn't sounds that hard to me.

...let’s just make them all overridable\, allowing smarter people to do things we haven’t thought of.

This would be okay if we can be 100% sure that changes like these do not introduce additional code complexity and other future maintenance problems. "Oh no\, we cannot remove this because we have once said that it would be possible and maybe there's someone on earth actually using it".

I\, for my part\, hope Perl is shipped on Mars rovers and space stations. However\, the rovers seem unlikely to download updates\, so I guess we can keep our focus on near-earth targets.

:-)

Let's be a bit careful.

-- Johan

p5pRT commented 12 years ago

From @iabyn

On Mon\, Apr 23\, 2012 at 06​:11​:22PM -0700\, Father Chrysostomos via RT wrote​:

On Mon Apr 23 15​:19​:09 2012\, sprout wrote​:

And then\, to work with closures\, we would have to associate the attribute with the address of the op tree. I can already see how that could be accomplished\, without memory leaks\, using tied field hashes.

That’s assuming that the prototype is never freed before the closure cloned from it.

As I understand it\, the closure references the subroutine outside of it. That subroutine’s op tree references the closure prototype. Is that right?

I think it likely that the prototype is never freed before the clone; the clone has a refcounted ptr to the outside sub (CvOUTSIDE)\, and the prototype lives in the pad of that outside sub (and so gets duped during thread creation).

-- "Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses\, not from some farcical aquatic ceremony."   -- Dennis\, "Monty Python and the Holy Grail"

p5pRT commented 12 years ago

From @doy

On Tue\, Apr 24\, 2012 at 10​:10​:16AM +0200\, Johan Vromans wrote​:

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org writes​:

Anyone who overrides if() is probably asking for trouble. But it would be nice to override length() and vec(). Where do we draw the line?

Precisely \<-- HERE. Functions like vec() and length() can be overridden\, but control keywords like if and when and while can not.

Writing it as if() doesn't make it similar to vec() or length().

The issue is that with the parser changes that have been happening recently (call_checker\, call_parser\, etc)\, there is getting to be less and less of a difference between these two cases (and ideally\, at some point in the future\, there won't be any difference at all). What about overriding something like map? The distinction isn't quite as clear as you seem to be implying.

-doy

p5pRT commented 12 years ago

From @cpansprout

On Tue Apr 24 01​:10​:59 2012\, jv wrote​:

Anyone who overrides if() is probably asking for trouble. But it would be nice to override length() and vec(). Where do we draw the line?

Precisely \<-- HERE. Functions like vec() and length() can be overridden\, but control keywords like if and when and while can not.

Writing it as if() doesn't make it similar to vec() or length().

Or\, rather\, why do we need to draw a line? Instead of debating over every keyword about whether it should be overridable\, ...

Drawing a line means there's a vast group of keywords (functions) that can be overridden\, a smaller group that can not\, and maybe a few dubious cases that need discussion. Doesn't sounds that hard to me.

OK\, so now we are debating about whether we should debate. :-)

How about ‘given’? I would love to be able to override it with something that actually works\, in which case I would need ‘when’ as well.

How about being able to override ‘if’ to make if(\<>) dwim? How about overriding ‘while’ to make a non-dwimmy do-what-I-say version? These\, of course\, don’t have to be global overrides.

Do you realise that Perl has three distinct override methods and one of them (PL_keyword_plugin) already allows ‘if’ to be overridden? Why should the other two (use subs and CORE​::GLOBAL) be left out?

...let’s just make them all overridable\, allowing smarter people to do things we haven’t thought of.

This would be okay if we can be 100% sure that changes like these do not introduce additional code complexity and other future maintenance problems. "Oh no\, we cannot remove this because we have once said that it would be possible and maybe there's someone on earth actually using it".

Let's be a bit careful.

I think about future backward-compatibility all the time. That’s why &CORE​::eof croaks with ‘&CORE​::eof cannot be called directly’. It’s not clear whether it should mean eof or eof() (the parentheses make a difference). And picking one behaviour over the other will cause backward-compatibility problems later if we invent a new way to express that difference using prototypes.

I’ve been thinking carefully about the implications of overriding things like ‘if’ and ‘for’. The fact is that they are already overridable\, though only via one overriding mechanism\, so there is no possibility for future compatibility problems\, as long as the overridability via CVs is limited to ‘use v5.16’ scopes.

@​UNIVERSAL​::ISA = CORE; print $_->ucfirst for "just another "\, "perl hacker\,\n";

--

Father Chrysostomos

p5pRT commented 12 years ago

From @cpansprout

On Tue Apr 24 08​:56​:47 2012\, sprout wrote​:

as long as the overridability via CVs is limited to ‘use v5.16’ scopes.

I mean v5.18/20/whatever.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @ikegami

On Tue\, Apr 24\, 2012 at 4​:10 AM\, Johan Vromans \jvromans@&#8203;squirrel\.nl wrote​:

Drawing a line means there's a vast group of keywords (functions) that can be overridden\, a smaller group that can not

Actually\, every keyword can be overridden by other mechanisms. For example\, feature​::qw_comments overrides qw\, which cannot currently be overridden using C\<\< use subs 'qw'; >>

- Eric

PS - Something to test​: What happens if one overrides C\ using the keyword plugin? Does it break C\?

p5pRT commented 12 years ago

From @sciurius

Jesse Luehrs \doy@&#8203;tozt\.net writes​:

What about overriding something like map? The distinction isn't quite as clear as you seem to be implying.

Despite its weird syntax\, map is just a function. No problem overriding.

But above all lies the question​: what for?

We know we *can* do it. I suggest not to do it. Okay\, throw away the distinction between if and other keywords\, np\, but add a fatal error if someone tries to override if and friends.

Now\, if someone can come up with a real good reason why overriding if would be beneficial to the Perl community\, *then* remove the error message.

One of the reasons Perl was conceived many years ago was to take away the burden from having to keep track of trivial things like arrays\, hashes\, memory management\, and so on. The Principle Of Least Surprise was still written with capitals.

Now the goal seems to have become to provide as many rope as possible to hang oneself.

-- Johan

p5pRT commented 12 years ago

From @doy

On Tue\, Apr 24\, 2012 at 08​:05​:21PM +0200\, Johan Vromans wrote​:

Jesse Luehrs \doy@&#8203;tozt\.net writes​:

What about overriding something like map? The distinction isn't quite as clear as you seem to be implying.

Despite its weird syntax\, map is just a function. No problem overriding.

But above all lies the question​: what for?

We know we *can* do it. I suggest not to do it. Okay\, throw away the distinction between if and other keywords\, np\, but add a fatal error if someone tries to override if and friends.

Now\, if someone can come up with a real good reason why overriding if would be beneficial to the Perl community\, *then* remove the error message.

I have on occasion wished for a more functional programming-style if statement​:

  my $foo = if ($foo->bar) { $bar } else { $baz };

It is a lot more readable than ?​: when the expressions get more complicated.

Looking at it from the other side\, I really don't understand what making an arbitrary distinction between keywords that are allowed to be overridden and keywords that aren't allowed to be overridden actually gains us. That is just extra arbitrary restrictions that have to be remembered\, which just adds complication. Why do you think this makes anything simpler?

-doy

p5pRT commented 12 years ago

From @sciurius

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org writes​:

How about ‘given’? I would love to be able to override it with something that actually works\, in which case I would need ‘when’ as well.

How about being able to override ‘if’ to make if(\<>) dwim? How about overriding ‘while’ to make a non-dwimmy do-what-I-say version? These\, of course\, don’t have to be global overrides.

My first reaction to this thread was​: override okay\, but then as a set of keywords. if\, else and elsif go together. given\, when etc likewise.

I can easily imagine a pragma that changes the behaviour of such a set of keywords.

But just overriding keywords like if independently... Yuck.

BTW\, for the if(\<>) dwim\, I'd consider overriding the readline function instead.

-- Johan

p5pRT commented 12 years ago

From @sciurius

[Quoting Jesse Luehrs\, on April 24 2012\, 13​:18\, in "Re​: [perl #108286] W"]

I have on occasion wished for a more functional programming-style if statement​:

my $foo = if ($foo->bar) { $bar } else { $baz };

It is a lot more readable than ?​: when the expressions get more complicated.

I definitely agree.

Looking at it from the other side\, I really don't understand what making an arbitrary distinction between keywords that are allowed to be overridden and keywords that aren't allowed to be overridden actually gains us. That is just extra arbitrary restrictions that have to be remembered\, which just adds complication. Why do you think this makes anything simpler?

Because\, as was remarked earlier in this thread\, overriding if() is asking for trouble.

But again -- overriding if\, else and elsif as a whole (cf. tie) would be feasible. Bot not as loose keywords.

I cannot imagine a sensible purpose to override else. Can you?

-- Johan

p5pRT commented 12 years ago

From @doy

On Tue\, Apr 24\, 2012 at 08​:39​:54PM +0200\, Johan Vromans wrote​:

[Quoting Jesse Luehrs\, on April 24 2012\, 13​:18\, in "Re​: [perl #108286] W"]

I have on occasion wished for a more functional programming-style if statement​:

my $foo = if ($foo->bar) { $bar } else { $baz };

It is a lot more readable than ?​: when the expressions get more complicated.

I definitely agree.

Looking at it from the other side\, I really don't understand what making an arbitrary distinction between keywords that are allowed to be overridden and keywords that aren't allowed to be overridden actually gains us. That is just extra arbitrary restrictions that have to be remembered\, which just adds complication. Why do you think this makes anything simpler?

Because\, as was remarked earlier in this thread\, overriding if() is asking for trouble.

But again -- overriding if\, else and elsif as a whole (cf. tie) would be feasible. Bot not as loose keywords.

I cannot imagine a sensible purpose to override else. Can you?

No\, I think that if() should be the overridable part\, with 'else' and 'elsif' just as much a part of the syntax as '{' or '}'.

-doy

p5pRT commented 12 years ago

From @doy

On Tue\, Apr 24\, 2012 at 08​:24​:40PM +0200\, Johan Vromans wrote​:

"Father Chrysostomos via RT" \perlbug\-followup@&#8203;perl\.org writes​:

How about ‘given’? I would love to be able to override it with something that actually works\, in which case I would need ‘when’ as well.

How about being able to override ‘if’ to make if(\<>) dwim? How about overriding ‘while’ to make a non-dwimmy do-what-I-say version? These\, of course\, don’t have to be global overrides.

My first reaction to this thread was​: override okay\, but then as a set of keywords. if\, else and elsif go together. given\, when etc likewise.

I can easily imagine a pragma that changes the behaviour of such a set of keywords.

But just overriding keywords like if independently... Yuck.

BTW\, for the if(\<>) dwim\, I'd consider overriding the readline function instead.

given/when are actually independent keywords - they are actually more like for/next/last/etc. (whether this is actually a good idea is debatable\, but that is how they work currently). Overriding elsif outside of the context of if() doesn't actually make any sense - elsif isn't (or shouldn't be\, anyway) a keyword on its own\, it is just a token that is an expected part of parsing an if statement.

-doy

p5pRT commented 12 years ago

From @sciurius

[Quoting Jesse Luehrs\, on April 24 2012\, 13​:49\, in "Re​: [perl #108286] W"]

I cannot imagine a sensible purpose to override else. Can you?

No\, I think that if() should be the overridable part\, with 'else' and 'elsif' just as much a part of the syntax as '{' or '}'.

Precisely.

May I bring up a different but related topic?

While writing Camel IV we noticed that several of the new features were very hard to document\, because the implementation had been focused mainly on technical aspects and not on usability. Are we learning from that experience? Or do we face the same disaster should we ever decide to write Camel V?

-- Johan