Skip to content

Commit 44d0647

Browse files
authored
Merge pull request #68 from haarg/ampersand-method-calls
PPC0033: method-like calls to lexical subs
2 parents a0de141 + 2f3bd6a commit 44d0647

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Allow calling subs using method-like syntax
2+
3+
## Preamble
4+
5+
Author: Graham Knop <[email protected]>
6+
ID: 0033
7+
Status: Implemented
8+
9+
## Abstract
10+
11+
Add a syntax for calling lexical methods that is similar to the existing
12+
method syntax, rather than needing to call them like subs. The new syntax
13+
`$object->&method(@args)` would be equivalent to sub call to `method`, but
14+
using a syntax closer to method calls.
15+
16+
## Motivation
17+
18+
When using a lexical sub inside an object class, the subs must be called as
19+
`method($object, @args)`. This works, but for many people, this feels wrong
20+
as a way to call something thought of as a private method. This has resulted
21+
in some people using syntax like `$object->${\&method}(@args)`, or continuing
22+
to use code refs stored in a lexical variable (`$object->$method(@args)`).
23+
24+
## Rationale
25+
26+
`$object->method(@args)` always does a method lookup, ignoring the local
27+
context. Changing this would result in a lot of broken code. Changing this
28+
only for new code (via feature or other lexical effect) would introduce
29+
confusion and would also require some new (or pessimised) syntax to allow
30+
the previous behavior.
31+
32+
`$object->&method(@args)` would be an unambiguous way to call the `method` in
33+
the current scope, whether a lexical or package sub.
34+
35+
A truly private method does not need to do any lookup via `@ISA`, so being
36+
equivalent to a sub call makes sense.
37+
38+
This also would pair well with
39+
[PPC0021](ppc0021-optional-chaining-operator.md) to allow optional sub calls
40+
as part of a chain.
41+
42+
## Specification
43+
44+
`$object->&method(@args)` would behave exactly the same as `&method($object,
45+
@args)`. `method` would be searched for in the current lexical scope. If not
46+
found, it would be looked up in the current package. If still not found, the
47+
current package's `AUTOLOAD` would be called. If `AUTOLOAD` does not exist, an
48+
error would be issued. The call would ignore prototypes, just as traditional
49+
method calls and `&subroutine()` calls do.
50+
51+
Methods defined using the `class` syntax would also be callable using this
52+
syntax.
53+
54+
## Backwards Compatibility
55+
56+
The syntax `->&word` is currently a syntax error, so no backwards
57+
compatibility issues are forseen.
58+
59+
## Security Implications
60+
61+
As this is purely a syntax feature that is currently a syntax error, no
62+
security implications are forseen.
63+
64+
## Examples
65+
66+
```perl
67+
use v5.36;
68+
69+
package Foo {
70+
sub new ($class) {
71+
return bless {
72+
field => 5,
73+
}, $class;
74+
}
75+
76+
my sub private ($self) {
77+
return $self->{field};
78+
}
79+
80+
sub _old_school_private ($self) {
81+
return $self->{field};
82+
}
83+
84+
sub public ($self) {
85+
86+
# call via lexical method is allowed
87+
say "my field: " . $self->&private;
88+
# exactly equivalent to:
89+
say "my field: " . private($self);
90+
91+
92+
# can also be used to call package methods. But won't look up via @ISA
93+
say "my field: " . $self->&_old_school_private;
94+
# exactly equivalent to:
95+
say "my field: " . _old_school_private($self);
96+
}
97+
}
98+
99+
my $foo = Foo->new;
100+
$foo->public;
101+
102+
# this is an error, as there is no sub named "private" in scope
103+
$foo->&private;
104+
105+
# this is also an error, as "public" does not exist in the current scope
106+
$foo->&public;
107+
```
108+
109+
## Prototype Implementation
110+
111+
* [Object::Pad::LexicalMethods](https://metacpan.org/pod/Object::Pad::LexicalMethods)
112+
implements lexical methods and `->&` method calls for
113+
[Object::Pad](https://metacpan.org/pod/Object::Pad).
114+
115+
## Future Scope
116+
117+
Lexical methods (`my method foo`) are not currently supported under the
118+
`class` syntax. If they were added, `->&method` would be the preferred way to
119+
call them.
120+
121+
## Rejected Ideas
122+
123+
Allowing `$object->method` to call lexical subs would break existing code and
124+
would interfere with the ability to call the actual method. Perl doesn't know
125+
what type `$object` is, so it can't know when it is appropriate to do method
126+
lookup and when to call a local sub. Using a different syntax at the call site
127+
avoids these issues.
128+
129+
## Open Issues
130+
131+
None currently.
132+
133+
## Copyright
134+
135+
Copyright (C) 2025, Graham Knop
136+
137+
This document and code and documentation within it may be used, redistributed
138+
and/or modified under the same terms as Perl itself.

0 commit comments

Comments
 (0)