Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EXPERIMENT] pluggable keyword API #13199

Open
p5pRT opened this issue Aug 25, 2013 · 22 comments
Open

[EXPERIMENT] pluggable keyword API #13199

p5pRT opened this issue Aug 25, 2013 · 22 comments
Labels
experiment ticket tracking an active experiment

Comments

@p5pRT
Copy link

p5pRT commented Aug 25, 2013

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

Searchable as RT119455$

@p5pRT
Copy link
Author

p5pRT commented Aug 25, 2013

From @rjbs

perl 5.12.0 introduced the "pluggable keyword" API. Although perlexperiment
has mostly excluded experimental APIs, pluggable keywords have a higher level
of general interest and use already.

We should determine acceptance criteria, then track them.

(Subordinate bugs can be hung off this one.)

See also the original(?) ticket for pluggable keywords, [perl #70263]

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Aug 25, 2013

From zefram@fysh.org

Ricardo SIGNES wrote​:

perl 5.12.0 introduced the "pluggable keyword" API. Although perlexperiment
has mostly excluded experimental APIs, pluggable keywords have a higher level
of general interest and use already.

That API turned out to be a poor design, and we should ultimately remove
it. A much better design for the same job is the per-sub parser hook,
as implemented by Devel​::CallParser. I'd like to put the call-parser
hook into the core and then remove the keyword plugin API. It has to
be in that order, because Devel​::CallParser is currently implemented
via the keyword plugin mechanism.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Aug 25, 2013

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

@p5pRT
Copy link
Author

p5pRT commented Aug 25, 2013

From @mauke

On 25.08.2013 11​:31, Zefram wrote​:

Ricardo SIGNES wrote​:

perl 5.12.0 introduced the "pluggable keyword" API. Although perlexperiment
has mostly excluded experimental APIs, pluggable keywords have a higher level
of general interest and use already.

That API turned out to be a poor design, and we should ultimately remove
it. A much better design for the same job is the per-sub parser hook,
as implemented by Devel​::CallParser. I'd like to put the call-parser
hook into the core and then remove the keyword plugin API. It has to
be in that order, because Devel​::CallParser is currently implemented
via the keyword plugin mechanism.

Devel​::CallParser solves a different problem. I can only use it to
implement custom argument syntax for subroutines, but what I actually
want is custom keywords.

For example​: if I want to reimplement 'sub', I need to accept a bareword
(subroutine name) followed by a block (subroutine body). None of the
parse_args_* functions can be used for this.

Assuming I can do this manually by bypassing D​:CP and calling perl's
lexer/parser functions directly, I still have to return an argument
list. This isn't needed because all the effects I want happen at
runtime, but the API insists on constructing a sub call.

Finally, the whole thing won't be a statement by itself, so the user
will need to add a ';'.

I'm thinking of this​:

  sub mysub {}
  # ... somehow use Devel​::CallParser to attach custom parsing code
  # to mysub ...

  mysub plus {
  return $_[0] + $_[1];
  }; # <- semicolon required

  # compiled as​:
  # BEGIN { *plus = sub { return $_[0] + $_[1] }; }
  # # ^ define &plus during call parsing
  # &mysub();
  # # ^ dummy call constructed by D​:CP

Also, this would make something like

  my $wtf = mysub foo { return 42; };

valid syntax. (Equivalent to​:

  BEGIN { *foo = sub { return 42; }; }
  my $wtf = &mysub();

)

All of this is unlike the 'sub' builtin, which can be approximated very
well using a pluggable keyword.

In short​: If I haven't misunderstood how D​:CP works, then the pluggable
keyword API may be a poor design but D​:CP simply doesn't do the same job.

(And I still want the KEYWORD_PLUGIN_NOOP patch to go in because it
would make Keyword​::Simple much more powerful.)

--
Lukas Mai <plokinom@​gmail.com>

@p5pRT
Copy link
Author

p5pRT commented Aug 25, 2013

From zefram@fysh.org

Lukas Mai wrote​:

Devel​::CallParser solves a different problem. I can only use it to
implement custom argument syntax for subroutines, but what I actually
want is custom keywords.

The breakthrough that led to Devel​::CallParser is the understanding that
there's no need for such a distinction, and in fact that we're better
off without one. Keyword-led syntax and subroutine calls both begin
the same way, with a bareword that identifies the type of construction
that is to follow. Keywords and subroutine names are semantically
active in the same situations. So it doesn't make sense to treat
them as two separate namespaces. Better to have one namespace, with
the metaobject to which the name refers determining all the behaviour.
Of the two namespaces we already have, the one that is more manipulable
is the subroutine namespace.

For example​: if I want to reimplement 'sub', I need to accept a bareword
(subroutine name) followed by a block (subroutine body). None of the
parse_args_* functions can be used for this.

That's orthogonal to how the namespace is managed. You need those
parsing routines regardless of how your plugged-in parser got invoked.
parse_args_*() don't cover your needs, but the core's parse_block()
does the sub body. parse_block() can be perfectly well called from a
D​:CP-managed sub arg parser. The possibility of calling parsing code
other than the standard argument parsers is the point of D​:CP.

                            I still have to return an argument

list. This isn't needed because all the effects I want happen at
runtime, but the API insists on constructing a sub call.

When using D​:CP for this sort of thing, you'll also want to use
Devel​::CallChecker to turn the sub calling ops into something
other than a sub call. See Memoize​::Lift, for example, which turns
lift(some_arbitrary_expr()) into a compile-time constant, requiring
modification of both stages.

It's sane to argue that the eventual API should make it easier than
this to generate a completely custom op sequence from a custom parser.
I think there is some use in keeping the two-phase structure, because
this potentially allows use of the op customisation from code that builds
ops directly rather than using the parser. This is always possible for
things that use only Devel​::CallChecker​: one can build the entersub op
tree manually, and the check phase replaces it with the custom ops just
as if the sub call had been parsed normally. But where such a split is
really not convenient (as in Memoize​::Lift, which actually does all the
constant lifting in the parse phase), a call checker that just throws
away the entersub wrapper and yields the parameter's op tree (M​:L's
myck_entersub_lift minus the const op type check) could be supplied by
the core for convenience.

Finally, the whole thing won't be a statement by itself, so the user
will need to add a ';'.

That's what the CALLPARSER_STATEMENT flag in the D​:CP API is for.
For example, see Scope​::Escape​::Sugar, which implements "block foo
{...}" being a complete statement, without semicolon. The code that
implements that form is a bit tricky to follow, I'm afraid, partly due
to also allowing "block(foo {...})" as an expression (not statement)
and partly due to some hackery to support parsing on Perls that don't
supply the parser callback interfaces.

In short​: If I haven't misunderstood how D​:CP works,

You have misunderstood much of D​:CP.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Aug 25, 2013

From @ikegami

On Sun, Aug 25, 2013 at 7​:32 AM, Lukas Mai <plokinom@​gmail.com> wrote​:

Devel​::CallParser solves a different problem. I can only use it to
implement custom argument syntax for subroutines, but what I actually
want is custom keywords.

For example​: if I want to reimplement 'sub', I need to accept a bareword
(subroutine name) followed by a block (subroutine body). None of the
parse_args_* functions can be used for this.

You should have a look at Syntax​::Feature​::Loop. That's pretty much exactly
what it does, and it does it using Devel​::CallParser.

(It actually provides C<< loop { ... } >>, but C<< mysub NAME { ... } >>
would be just as easy to implement.)

@p5pRT
Copy link
Author

p5pRT commented Aug 25, 2013

From @ikegami

On Sun, Aug 25, 2013 at 7​:32 AM, Lukas Mai <plokinom@​gmail.com> wrote​:

Finally, the whole thing won't be a statement by itself, so the user
will need to add a ';'.

That's not the case. For example, the aformentioned C<< loop BLOCK >> does
not require a trailing ";".

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From @mauke

On 25.08.2013 15​:09, Zefram wrote​:

Lukas Mai wrote​:

Devel​::CallParser solves a different problem. I can only use it to
implement custom argument syntax for subroutines, but what I actually
want is custom keywords.

The breakthrough that led to Devel​::CallParser is the understanding that
there's no need for such a distinction, and in fact that we're better
off without one. Keyword-led syntax and subroutine calls both begin
the same way, with a bareword that identifies the type of construction
that is to follow. Keywords and subroutine names are semantically
active in the same situations. So it doesn't make sense to treat
them as two separate namespaces. Better to have one namespace, with
the metaobject to which the name refers determining all the behaviour.
Of the two namespaces we already have, the one that is more manipulable
is the subroutine namespace.

For example​: if I want to reimplement 'sub', I need to accept a bareword
(subroutine name) followed by a block (subroutine body). None of the
parse_args_* functions can be used for this.

That's orthogonal to how the namespace is managed. You need those
parsing routines regardless of how your plugged-in parser got invoked.
parse_args_*() don't cover your needs, but the core's parse_block()
does the sub body. parse_block() can be perfectly well called from a
D​:CP-managed sub arg parser. The possibility of calling parsing code
other than the standard argument parsers is the point of D​:CP.

                            I still have to return an argument

list. This isn't needed because all the effects I want happen at
runtime, but the API insists on constructing a sub call.

When using D​:CP for this sort of thing, you'll also want to use
Devel​::CallChecker to turn the sub calling ops into something
other than a sub call. See Memoize​::Lift, for example, which turns
lift(some_arbitrary_expr()) into a compile-time constant, requiring
modification of both stages.

It's sane to argue that the eventual API should make it easier than
this to generate a completely custom op sequence from a custom parser.
I think there is some use in keeping the two-phase structure, because
this potentially allows use of the op customisation from code that builds
ops directly rather than using the parser. This is always possible for
things that use only Devel​::CallChecker​: one can build the entersub op
tree manually, and the check phase replaces it with the custom ops just
as if the sub call had been parsed normally. But where such a split is
really not convenient (as in Memoize​::Lift, which actually does all the
constant lifting in the parse phase), a call checker that just throws
away the entersub wrapper and yields the parameter's op tree (M​:L's
myck_entersub_lift minus the const op type check) could be supplied by
the core for convenience.

Finally, the whole thing won't be a statement by itself, so the user
will need to add a ';'.

That's what the CALLPARSER_STATEMENT flag in the D​:CP API is for.
For example, see Scope​::Escape​::Sugar, which implements "block foo
{...}" being a complete statement, without semicolon. The code that
implements that form is a bit tricky to follow, I'm afraid, partly due
to also allowing "block(foo {...})" as an expression (not statement)
and partly due to some hackery to support parsing on Perls that don't
supply the parser callback interfaces.

In short​: If I haven't misunderstood how D​:CP works,

You have misunderstood much of D​:CP.

Fair enough.

I've been thinking about creating a branch to convert
Function​::Parameters to D​:CP. I've hit two problems so far​:

1) There's no documentation that tells you how you actually integrate it
in a distribution. There's only this in the synopsis​:

# to generate header prior to XS compilation

perl -MDevel​::CallParser=callparser0_h \
  -e 'print callparser0_h' > callparser0.h
perl -MDevel​::CallParser=callparser1_h \
  -e 'print callparser1_h' > callparser1.h

What exactly is "prior"? Do I do this once and check the file in? Or is
this supposed to run as part of the build process (in which case, how do
I extend the Makefile to make it do that)? Or is this supposed to run at
configure time (in which case this code needs to go into Makefile.PL,
but then why is it presented in shell script form)?

2) Function​::Parameters is a lexical pragma. Does D​:CP provide lexical
exports? I don't see how to get the effect of lexically scoped keywords
with plain subs.

--
Lukas Mai <plokinom@​gmail.com>

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From @cpansprout

On Wed Aug 28 12​:53​:28 2013, plokinom@​gmail.com wrote​:

2) Function​::Parameters is a lexical pragma. Does D​:CP provide lexical
exports? I don't see how to get the effect of lexically scoped keywords
with plain subs.

You can use Lexical​::Var for that. Or use Perl’s own lexical sub
feature. See <http​://perl5.git.perl.org/perl.git/commitdiff/0be5d18d4f53>.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From @doy

On Wed, Aug 28, 2013 at 02​:14​:14PM -0700, Father Chrysostomos via RT wrote​:

On Wed Aug 28 12​:53​:28 2013, plokinom@​gmail.com wrote​:

2) Function​::Parameters is a lexical pragma. Does D​:CP provide lexical
exports? I don't see how to get the effect of lexically scoped keywords
with plain subs.

You can use Lexical​::Var for that. Or use Perl’s own lexical sub
feature. See <http​://perl5.git.perl.org/perl.git/commitdiff/0be5d18d4f53>.

This actually doesn't work yet, because prototypes aren't parsed on
lexical subs (and Devel​::CallParser hooks into the prototype parsing
mechanism). I think this was reported somewhere, but I can't remember
where at the moment.

-doy

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From zefram@fysh.org

Lukas Mai wrote​:

1) There's no documentation that tells you how you actually integrate it
in a distribution.

Yeah. That bit's tricky. ExtUtils​::CBuilder really isn't set up to
get the linking right on Windows.

What exactly is "prior"? Do I do this once and check the file in? Or is
this supposed to run as part of the build process

You generate the header during the build process. The header is specific
to a particular Perl version.

                                             \(in which case\, how do

I extend the Makefile to make it do that)?

That's between you and ExtUtils​::MakeMaker. I've never done it that way;
I use Module​::Build.

                                      Or is this supposed to run at

configure time

You can if you like, but then D​:CP would be a configure_requires.

2) Function​::Parameters is a lexical pragma. Does D​:CP provide lexical
exports?

No, D​:CP does not address exporting. It just attaches magic to a
subroutine object, and you export that by whatever means you like.

For a while I thought lexical exporting was the way forward.
But actually, whether lexical scoping is desired is more a feature
of the *im*porting module, the one that owns the affected namespaces.
And we've got a huge base of existing modules that follow the established
protocol of exporting to the calling package. We're not going to get
pervasive lexical scoping implemented from the exporting side.

I therefore wrote Lexical​::Import, which interfaces to a standard
export-to-package module and puts the exported items into the lexical
namespace. It uses Lexical​::Var underneath to implement the lexical
scoping. This includes lexical scoping of subroutine names, even though
"my" doesn't offer such a facility.

(If you have a backcompat requirement to lexically export from a
particular module, you can do it by using Lexical​::Var directly from
the "import" method. I suggest that you shouldn't lexically export,
in general, if you don't have such an established API to maintain.
I actually switched Scope​::Escape​::Sugar incompatibly from lexical
exporting in 0.000 to package exporting in 0.001.)

So you see my recommended mechanism involves composing a bunch of modules
that concentrate on small parts of the job. D​:CP to hook parsing;
cv_set_call_checker to hook op generation; Exporter to publish the magic
subroutine; and Lexical​::Import to import it into a lexical scope.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From @doy

On Wed, Aug 28, 2013 at 10​:24​:43PM +0100, Zefram wrote​:

Lukas Mai wrote​:

1) There's no documentation that tells you how you actually integrate it
in a distribution.

Yeah. That bit's tricky. ExtUtils​::CBuilder really isn't set up to
get the linking right on Windows.

What exactly is "prior"? Do I do this once and check the file in? Or is
this supposed to run as part of the build process

You generate the header during the build process. The header is specific
to a particular Perl version.

                                             \(in which case\, how do

I extend the Makefile to make it do that)?

That's between you and ExtUtils​::MakeMaker. I've never done it that way;
I use Module​::Build.

                                      Or is this supposed to run at

configure time

You can if you like, but then D​:CP would be a configure_requires.

Parse​::Keyword has an example of a build process that works on Windows,
using EUMM (via Dist​::Zilla, but that shouldn't be relevant, you can
just look at the generated Makefile.PL if you want to ignore that).

-doy

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From @cpansprout

On Wed Aug 28 14​:17​:43 2013, doy@​tozt.net wrote​:

On Wed, Aug 28, 2013 at 02​:14​:14PM -0700, Father Chrysostomos via RT
wrote​:

On Wed Aug 28 12​:53​:28 2013, plokinom@​gmail.com wrote​:

2) Function​::Parameters is a lexical pragma. Does D​:CP provide
lexical
exports? I don't see how to get the effect of lexically scoped
keywords
with plain subs.

You can use Lexical​::Var for that. Or use Perl’s own lexical sub
feature. See
<http​://perl5.git.perl.org/perl.git/commitdiff/0be5d18d4f53>.

This actually doesn't work yet, because prototypes aren't parsed on
lexical subs (and Devel​::CallParser hooks into the prototype parsing
mechanism). I think this was reported somewhere, but I can't remember
where at the moment.

I think you are confusing call parsers and call checkers; I could be wrong.

I believe 5.18.1 addressed the latter​:

=item *

Lexical constants (C<my sub a() { 42 }>) no longer crash when inlined.

=item *

Parameter prototypes attached to lexical subroutines are now respected when
compiling sub calls without parentheses. Previously, the prototypes were
honoured only for calls I<with> parentheses. [RT #116735]

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From @doy

On Wed, Aug 28, 2013 at 03​:28​:22PM -0700, Father Chrysostomos via RT wrote​:

On Wed Aug 28 14​:17​:43 2013, doy@​tozt.net wrote​:

On Wed, Aug 28, 2013 at 02​:14​:14PM -0700, Father Chrysostomos via RT
wrote​:

On Wed Aug 28 12​:53​:28 2013, plokinom@​gmail.com wrote​:

2) Function​::Parameters is a lexical pragma. Does D​:CP provide
lexical
exports? I don't see how to get the effect of lexically scoped
keywords
with plain subs.

You can use Lexical​::Var for that. Or use Perl’s own lexical sub
feature. See
<http​://perl5.git.perl.org/perl.git/commitdiff/0be5d18d4f53>.

This actually doesn't work yet, because prototypes aren't parsed on
lexical subs (and Devel​::CallParser hooks into the prototype parsing
mechanism). I think this was reported somewhere, but I can't remember
where at the moment.

I think you are confusing call parsers and call checkers; I could be wrong.

I believe 5.18.1 addressed the latter​:

=item *

Lexical constants (C<my sub a() { 42 }>) no longer crash when inlined.

=item *

Parameter prototypes attached to lexical subroutines are now respected when
compiling sub calls without parentheses. Previously, the prototypes were
honoured only for calls I<with> parentheses. [RT #116735]

Prototypes do work now, but Devel​::CallParser still doesn't seem to. I'm
not sure what exactly the issue is.

-doy

@p5pRT
Copy link
Author

p5pRT commented Aug 28, 2013

From @cpansprout

On Wed Aug 28 15​:46​:25 2013, doy@​tozt.net wrote​:

On Wed, Aug 28, 2013 at 03​:28​:22PM -0700, Father Chrysostomos via RT
wrote​:

On Wed Aug 28 14​:17​:43 2013, doy@​tozt.net wrote​:

On Wed, Aug 28, 2013 at 02​:14​:14PM -0700, Father Chrysostomos via
RT
wrote​:

On Wed Aug 28 12​:53​:28 2013, plokinom@​gmail.com wrote​:

2) Function​::Parameters is a lexical pragma. Does D​:CP provide
lexical
exports? I don't see how to get the effect of lexically scoped
keywords
with plain subs.

You can use Lexical​::Var for that. Or use Perl’s own lexical
sub
feature. See
<http​://perl5.git.perl.org/perl.git/commitdiff/0be5d18d4f53>.

This actually doesn't work yet, because prototypes aren't parsed
on
lexical subs (and Devel​::CallParser hooks into the prototype
parsing
mechanism). I think this was reported somewhere, but I can't
remember
where at the moment.

I think you are confusing call parsers and call checkers; I could be
wrong.

I believe 5.18.1 addressed the latter​:

=item *

Lexical constants (C<my sub a() { 42 }>) no longer crash when
inlined.

=item *

Parameter prototypes attached to lexical subroutines are now
respected when
compiling sub calls without parentheses. Previously, the prototypes
were
honoured only for calls I<with> parentheses. [RT #116735]

Prototypes do work now, but Devel​::CallParser still doesn't seem to.
I'm
not sure what exactly the issue is.

If you have a test case, could you file a separate bug?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2013

From @doy

On Wed, Aug 28, 2013 at 04​:40​:19PM -0700, Father Chrysostomos via RT wrote​:

Prototypes do work now, but Devel​::CallParser still doesn't seem to.
I'm not sure what exactly the issue is.

If you have a test case, could you file a separate bug?

I've boiled this down to a test case, but it's not really clear if it's
a bug in lexical subs or Devel​::CallParser itself. I can file a separate
bug if it's not just something that needs to be fixed in
Devel​::CallParser. The test case is attached.

-doy

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2013

From @doy

lexical-test.tar.gz

@p5pRT
Copy link
Author

p5pRT commented Sep 29, 2013

From @ikegami

On Wed, Aug 28, 2013 at 3​:52 PM, Lukas Mai <plokinom@​gmail.com> wrote​:

I've been thinking about creating a branch to convert
Function​::Parameters to D​:CP. I've hit two problems so far​:

1) There's no documentation that tells you how you actually integrate it
in a distribution. There's only this in the synopsis​:

[...]
2) Function​::Parameters is a lexical pragma. Does D​:CP provide lexical
exports? I don't see how to get the effect of lexically scoped keywords
with plain subs.

For both, take a look at Syntax​::Feature​::Loop. Feel free to ask me if you
have any questions.

@p5pRT
Copy link
Author

p5pRT commented Sep 29, 2013

From @mauke

On 29.09.2013 17​:46, Eric Brine wrote​:

On Wed, Aug 28, 2013 at 3​:52 PM, Lukas Mai <plokinom@​gmail.com
<mailto​:plokinom@​gmail.com>> wrote​:

I've been thinking about creating a branch to convert
Function&#8203;::Parameters to D&#8203;:CP\. I've hit two problems so far&#8203;:

1\) There's no documentation that tells you how you actually integrate it
in a distribution\. There's only this in the synopsis&#8203;:

\[\.\.\.\]
2\) Function&#8203;::Parameters is a lexical pragma\. Does D&#8203;:CP provide lexical
exports? I don't see how to get the effect of lexically scoped keywords
with plain subs\.

For both, take a look at Syntax​::Feature​::Loop. Feel free to ask me if
you have any questions.

I've given up on D​:CP for now. It simply doesn't provide the right
look-and-feel for keywords.

I've found a few weird things in Syntax​::Feature​::Loop, though​:

% perl -we 'use syntax "loop"; loop()'
syntax error at -e line 1, near "loop("
syntax error at -e line 1, near "()
"
Execution of -e aborted due to compilation errors.

That's not very helpful. (Also, why 2 syntax errors?)

% perl -we 'use syntax "loop"; &loop()'
Undefined subroutine &Syntax​::Feature​::Loop​::loop called at -e line 1.

Why is it trying to call Syntax​::Feature​::Loop​::loop instead of
main​::loop when that sub doesn't even exist?

% perl -we 'use syntax "loop"; sub loop {} &loop()'
Undefined subroutine &Syntax​::Feature​::Loop​::loop called at -e line 1.

That simply shouldn't happen. I have a perfectly fine &main​::loop right
there.

--
Lukas Mai <plokinom@​gmail.com>

@p5pRT
Copy link
Author

p5pRT commented Sep 30, 2013

From @ikegami

On Sun, Sep 29, 2013 at 4​:15 PM, Lukas Mai <plokinom@​gmail.com> wrote​:

On 29.09.2013 17​:46, Eric Brine wrote​:

On Wed, Aug 28, 2013 at 3​:52 PM, Lukas Mai <plokinom@​gmail.com
<mailto​:plokinom@​gmail.com>> wrote​:

I've been thinking about creating a branch to convert
Function&#8203;::Parameters to D&#8203;:CP\. I've hit two problems so far&#8203;:

1\) There's no documentation that tells you how you actually

integrate it

in a distribution\. There's only this in the synopsis&#8203;:

\[\.\.\.\]
2\) Function&#8203;::Parameters is a lexical pragma\. Does D&#8203;:CP provide

lexical

exports? I don't see how to get the effect of lexically scoped

keywords

with plain subs\.

For both, take a look at Syntax​::Feature​::Loop. Feel free to ask me if
you have any questions.

I've given up on D​:CP for now. It simply doesn't provide the right
look-and-feel for keywords.

I've found a few weird things in Syntax​::Feature​::Loop, though​:

% perl -we 'use syntax "loop"; loop()'
syntax error at -e line 1, near "loop("
syntax error at -e line 1, near "()
"
Execution of -e aborted due to compilation errors.

That's not very helpful. (Also, why 2 syntax errors?)

Not helpful? It's the exact same error message found elsewhere.

perl -e"for{}"
syntax error at -e line 1, near "for{"
Execution of -e aborted due to compilation errors.

In fact, the error is emitted by Perl itself. I'll look into why it's
giving two errors.

% perl -we 'use syntax "loop"; &loop()'
Undefined subroutine &Syntax​::Feature​::Loop​::loop called at -e line 1.

Why is it trying to call Syntax​::Feature​::Loop​::loop instead of
main​::loop when that sub doesn't even exist?

There's a difference between existing and being defined. While the sub
exists, it's not defined.

% perl -we 'use syntax "loop"; sub loop {} &loop()'
Undefined subroutine &Syntax​::Feature​::Loop​::loop called at -e line 1.

That simply shouldn't happen. I have a perfectly fine &main​::loop right
there.

Yes, but you said to use the one from S​::F​::L. Defining a sub doesn't
override keywords.

perl -E"sub for { } for('abc');"
syntax error at -e line 1, near ");"
Execution of -e aborted due to compilation errors.

perl -E"sub lc { 'b' } say lc 'a'"
a

@p5pRT
Copy link
Author

p5pRT commented Sep 30, 2013

From @ikegami

On Mon, Sep 30, 2013 at 9​:29 AM, Eric Brine <ikegami@​adaelis.com> wrote​:

On Sun, Sep 29, 2013 at 4​:15 PM, Lukas Mai <plokinom@​gmail.com> wrote​:

% perl -we 'use syntax "loop"; sub loop {} &loop()'

Undefined subroutine &Syntax​::Feature​::Loop​::loop called at -e line 1.

That simply shouldn't happen. I have a perfectly fine &main​::loop right
there.

Yes, but you said to use the one from S​::F​::L. Defining a sub doesn't
override keywords.

perl -E"sub for { } for('abc');"
syntax error at -e line 1, near ");"

Execution of -e aborted due to compilation errors.

perl -E"sub lc { 'b' } say lc 'a'"
a

ah, nevermind, I get your point here. I'll don't know if that's an issue
with Call​::DevelParser/Checker or with Lexical​::Sub. I'll find out. I would
expect something like​:

$ perl -Mfeature=lexical_subs -M-warnings=experimental -wE'my sub lc { "b"
} sub lc { "c" } say &lc("a")'
Subroutine lc redefined at -e line 1.
c

@p5pRT
Copy link
Author

p5pRT commented Oct 10, 2013

From @doy

On Sat, Sep 28, 2013 at 02​:51​:52PM -0400, Jesse Luehrs wrote​:

On Wed, Aug 28, 2013 at 04​:40​:19PM -0700, Father Chrysostomos via RT wrote​:

Prototypes do work now, but Devel​::CallParser still doesn't seem to.
I'm not sure what exactly the issue is.

If you have a test case, could you file a separate bug?

I've boiled this down to a test case, but it's not really clear if it's
a bug in lexical subs or Devel​::CallParser itself. I can file a separate
bug if it's not just something that needs to be fixed in
Devel​::CallParser. The test case is attached.

-doy

And reported as a bug against Devel​::CallParser here​:
https://rt.cpan.org/Ticket/Display.html?id=89370

-doy

@rjbs rjbs added experiment ticket tracking an active experiment and removed Severity Low labels Apr 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
experiment ticket tracking an active experiment
Projects
None yet
Development

No branches or pull requests

2 participants