Tail method calls, can(), and pre-currying

6 views
Skip to first unread message

Brent 'Dax' Royal-Gordon

unread,
Jul 20, 2005, 9:44:42 PM7/20/05
to Perl 6 Language List
<brentdax> Is there a Perl 6 tail call syntax, and if so is it
implemented in Pugs?
<autrijus> &sub.goto(...);
<autrijus> and yes.
<brentdax> Oh...are tail method calls possible?
<autrijus> tail method calls. hrmph.

I have a few methods where I'd like to perform tail calls into another
object's methods. If I were calling one of my own methods, I'd
probably use &meth.goto($?SELF, *@args) as Autrijus suggested before,
but these are calls into another object, based on its runtime class.

As far as I can tell, the easiest way to do this in Perl 6 is thus:

$obj.can('meth').goto($obj, *@args);

Besides the fact that this isn't possible in current Pugs (which seems
to lack a can() method), it has several other problems: it's too long,
the method name is being treated as a string, the object is included
twice, it will fail silently if $obj doesn't have a `meth` method, and
so on.

One suggestion was a tweak of `can`'s definition: instead of returning
a reference to the method, it returns one with the invocant already
curried into it. Thus, the above becomes this:

$obj.can('meth').goto(*@args);

While quite a bit better, this still has many of the problems I
mentioned before. My recommendation is thus:

$obj.\meth.goto(*@args);

The .\meth takes a precurried reference to the `meth` method (throwing
an appropriate tantrum if `meth` doesn't exist), which can then be
treated like any other subroutine reference, in this case being
invoked as a tail call.

Of course, this adds *another* piece of syntax to an already large
language, so I'm not sure if it's a good idea.

Am I missing something? How do you think a tail method call should be
performed?

--
Brent 'Dax' Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker

Adriano Ferreira

unread,
Jul 21, 2005, 8:59:57 AM7/21/05
to Perl 6 Language List, br...@brentdax.com
On 7/20/05, Brent 'Dax' Royal-Gordon <bren...@gmail.com> wrote:
> <brentdax> Is there a Perl 6 tail call syntax,

> One suggestion was a tweak of `can`'s definition: instead of returning


> a reference to the method, it returns one with the invocant already
> curried into it. Thus, the above becomes this:

> Am I missing something? How do you think a tail method call should be
> performed?

I can understand the convenience of turning a method into a subroutine
by currying the object. Syntactical support for this seems cool too.
But, can someone remind me why there is the need for an explicit tail
call syntax? It has to do with some oddity of Perl in some situations
that prevents the code generator to infer that should be a a tail
call? I am thinking about how tail calls are handled in languages like
Scheme or Lua. In these,

sub f ( $a ) {
return g($a);
}

urges for (and compiles to) a tail call with no need for explicit
marks by the programmer. Obviously, in Perl, there are some issues
with the calling context that should be propagated to the callee.

Also getting tail method calls right is an immediate win for the issue
of implementing delegation. Am I right?

Regards,
Adriano.

Adriano Ferreira

unread,
Jul 21, 2005, 10:58:41 AM7/21/05
to Perl 6 Language List
Larry said:
> So I guess I agree that .tailcall is probably just a bad synonym for "return".

But is there any other case where we need an explicit tail call with "goto"?

And about a way to curry a method with its receiver to a sub, is there
a shorthand?

Thanks,
Adriano.

Larry Wall

unread,
Jul 21, 2005, 10:51:03 AM7/21/05
to Perl 6 Language List
On Thu, Jul 21, 2005 at 09:59:57AM -0300, Adriano Ferreira wrote:
: I can understand the convenience of turning a method into a subroutine

: by currying the object. Syntactical support for this seems cool too.
: But, can someone remind me why there is the need for an explicit tail
: call syntax? It has to do with some oddity of Perl in some situations
: that prevents the code generator to infer that should be a a tail
: call? I am thinking about how tail calls are handled in languages like
: Scheme or Lua. In these,
:
: sub f ( $a ) {
: return g($a);
: }
:
: urges for (and compiles to) a tail call with no need for explicit
: marks by the programmer. Obviously, in Perl, there are some issues
: with the calling context that should be propagated to the callee.

Though, arguably, g is probably more interested in the context of f in
this case, so automatic tailcall optimization is not necessarily throwing
away any information that the return would not have to pass down to
g() anyway. So I guess I agree that .tailcall is probably just a bad
synonym for "return".

: Also getting tail method calls right is an immediate win for the issue


: of implementing delegation. Am I right?

Yes, presuming the delegator doesn't want to capture control again after
the delegation. But delegation is just syntactic sugar anyway, so
if you want control back you should just write it that way explicitly
and the tailcall disappears.

Larry

Larry Wall

unread,
Jul 21, 2005, 8:51:59 PM7/21/05
to Perl 6 Language List
On Thu, Jul 21, 2005 at 11:58:41AM -0300, Adriano Ferreira wrote:
: Larry said:
: > So I guess I agree that .tailcall is probably just a bad synonym for "return".
:
: But is there any other case where we need an explicit tail call with "goto"?

I suppose that depends on whether the tail-call optimization is
general enough to work indirectly at run time.

: And about a way to curry a method with its receiver to a sub, is there
: a shorthand?

$sub = &ThatClass::meth.assuming($obj);

is the shortest thing that specifies the other class.

$sub = &meth.assuming($obj);

should work if the method would be selected by MMD. I'd think a lot of
these cases are actually covered by currying the class to have an
implicit invocant, turning it into a module. Other than that, there's
always something like:

$sub = -> *@args { $obj.meth(@args) };

which presumably can optimize the tailcall away. Possibly

$sub = { $obj.meth(@_) };

could be forced to recognize that @_ is the slurpy arg to the closure.

Larry

Brent 'Dax' Royal-Gordon

unread,
Jul 22, 2005, 10:04:24 AM7/22/05
to Adriano Ferreira, Perl 6 Language List
On 21/07/05, Adriano Ferreira <a.r.fe...@gmail.com> wrote:
> But is there any other case where we need an explicit tail call with "goto"?

When the callee uses `caller

Larry Wall

unread,
Jul 22, 2005, 11:24:47 AM7/22/05
to Perl 6 Language List
On Fri, Jul 22, 2005 at 07:04:24AM -0700, Brent 'Dax' Royal-Gordon wrote:
: On 21/07/05, Adriano Ferreira <a.r.fe...@gmail.com> wrote:
: > But is there any other case where we need an explicit tail call with "goto"?
:
: When the callee uses `caller

Which we may not know, especially if we're tail-calling into something that
hasn't been compiled yet. But I think the default should be to assume that
the callee doesn't use caller, and then maybe have some trait or pragma that
overrides that default if we want to pessimize. In any event, many uses
of caller probably want to skip the middleman anyway, and even more uses
of "want".

It's the debugger that wishes the tail-call optimization didn't exist...

Larry

Reply all
Reply to author
Forward
0 new messages