Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[perl #40955] [BUG] :anon .subs aren't anchored to a namespace

4 views
Skip to first unread message

Matt Diephouse

unread,
Nov 20, 2006, 3:34:02 PM11/20/06
to bugs-bi...@rt.perl.org
# New Ticket Created by Matt Diephouse
# Please include the string: [perl #40955]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=40955 >


There are two different relations between namespaces and subroutines:
namespaces contain subroutines (they're looked up) and subroutines
are anchored to namespaces (they look other things up). An anonymous
subroutine should not be in a namespace, but it should still be
anchored to one.

:anon .subs in Parrot are not anchored to a namespace like they ought
to be. The following test case exposes it:

.namespace ['lib']
.sub main :main :anon
$P0 = new .ResizablePMCArray
$P0 = get_namespace $P0
$P0 = $P0.'name'()
$S0 = join "::", $P0
say $S0 # this should print "parrot::lib" but it prints "parrot"
.end

This bug is blocking Tcl.

--
Matt Diephouse

Matt Diephouse via RT

unread,
Nov 20, 2006, 5:04:55 PM11/20/06
to perl6-i...@perl.org
This issue was actually fixed in r15674 - before the ticket even made it through to the list.

--
Matt Diephouse


Allison Randal

unread,
Nov 21, 2006, 3:19:56 PM11/21/06
to perl6-i...@perl.org
Matt Diephouse (via RT) wrote:
>
> There are two different relations between namespaces and subroutines:
> namespaces contain subroutines (they're looked up) and subroutines
> are anchored to namespaces (they look other things up). An anonymous
> subroutine should not be in a namespace, but it should still be
> anchored to one.

From my perspective, :anon subs should be neither in a namespace nor
anchored to a namespace. They're completely namespaceless.

> :anon .subs in Parrot are not anchored to a namespace like they ought
> to be. The following test case exposes it:
>
> .namespace ['lib']
> .sub main :main :anon
> $P0 = new .ResizablePMCArray
> $P0 = get_namespace $P0
> $P0 = $P0.'name'()
> $S0 = join "::", $P0
> say $S0 # this should print "parrot::lib" but it prints "parrot"
> .end

Combined with your comments in the IRC meeting today, I think what
you're onto is a new feature, orthogonal to :anon. Code examples of the
various use cases will help me define the behavior you're looking for.

Allison

Matt Diephouse

unread,
Nov 21, 2006, 3:45:41 PM11/21/06
to Allison Randal, perl6-i...@perl.org
Allison Randal <all...@perl.org> wrote:
> Matt Diephouse (via RT) wrote:
> >
> > There are two different relations between namespaces and subroutines:
> > namespaces contain subroutines (they're looked up) and subroutines
> > are anchored to namespaces (they look other things up). An anonymous
> > subroutine should not be in a namespace, but it should still be
> > anchored to one.
>
> From my perspective, :anon subs should be neither in a namespace nor
> anchored to a namespace. They're completely namespaceless.

Consider the following Perl 5 code:

package Test;
sub apply {
my $func = shift;
$func->(shift) while @_;
}
package Foo;
my $line = 0;
my $func = sub { print $line++, " ", shift(), "\n"; }
Test::apply($func, qw(a b c d)

That could be translated into PIR like so:

.namespace ['Test']
.sub apply
.param pmc func
.param pmc args :slurpy
.local pmc iter
iter = new .Iterator, args
loop:
unless iter goto done
$P0 = shift iter
func($P0)
goto loop
done:
.end
.namespace ['Foo']
.sub anon1 :anon
.param pmc elem
.local pmc line
line = get_global '$line'
print line
inc line
print " "
print elem
print "\n"
.end
.sub main :main :anon
.local pmc line
line = new .Integer
line = 0
set_global '$line', line
.const Sub func = 'anon1' # I think - but am not sure - that
this syntax is correct
$P0 = get_hll_global ['Test'], 'apply'
$P0(func, "a", "b", "c", "d")
.end

In this case, the :anon sub is not stored in a namespace. But a
namespace *is* attached to it. That is, it knows to look in ['Foo']
for the '$line' global. The bug that this ticket was exposing is that
Parrot was looking in the root HLL namespace for the '$line' global
instead of looking in ['Foo'].

I'm not sure I communicated this well in the original ticket.

This case is especially important for things like :main subs (the one
above is also :anon). Tcl relies on these when it compiles code to
PIR: we don't want every compilation to pollute our namespaces, so we
make these subs :anon. Fixing this in Parrot allowed me to fix some
bugs in Tcl.

> > :anon .subs in Parrot are not anchored to a namespace like they ought
> > to be. The following test case exposes it:
> >
> > .namespace ['lib']
> > .sub main :main :anon
> > $P0 = new .ResizablePMCArray
> > $P0 = get_namespace $P0
> > $P0 = $P0.'name'()
> > $S0 = join "::", $P0
> > say $S0 # this should print "parrot::lib" but it prints "parrot"
> > .end
>
> Combined with your comments in the IRC meeting today, I think what
> you're onto is a new feature, orthogonal to :anon. Code examples of the
> various use cases will help me define the behavior you're looking for.

This is the opposite of what I brought up on IRC today.

--
Matt Diephouse
http://matt.diephouse.com

Allison Randal

unread,
Nov 21, 2006, 5:09:37 PM11/21/06
to ma...@diephouse.com, perl6-i...@perl.org
Matt Diephouse wrote:
>
> Consider the following Perl 5 code:
>
> package Test;
> sub apply {
> my $func = shift;
> $func->(shift) while @_;
> }
> package Foo;
> my $line = 0;
> my $func = sub { print $line++, " ", shift(), "\n"; }
> Test::apply($func, qw(a b c d)
>
> That could be translated into PIR like so:
[...]

>
> In this case, the :anon sub is not stored in a namespace. But a
> namespace *is* attached to it. That is, it knows to look in ['Foo']
> for the '$line' global. The bug that this ticket was exposing is that
> Parrot was looking in the root HLL namespace for the '$line' global
> instead of looking in ['Foo'].

It could be written that way, but there's actually a good bit more going
on in the Perl 5 code than anchoring to a namespace. That anonymous code
block is defined in the dynamic context of its surrounding code, which
is why it has access to the lexical $line (note, not a global). It's a
closure. The namespace "anchoring" is a side-effect of being a closure,
not a fundamental characteristic of anonymous subs in general.

> This case is especially important for things like :main subs (the one
> above is also :anon). Tcl relies on these when it compiles code to
> PIR: we don't want every compilation to pollute our namespaces, so we
> make these subs :anon. Fixing this in Parrot allowed me to fix some
> bugs in Tcl.

This is why I need code examples. I need to understand the problem
you're solving before I can evaluate the solution you're proposing, see
how it fits into the overall architecture, or suggest alternatives.
(Let's take the discussion to a separate thread outside RT and just post
back the conclusion we come to.)

>> Combined with your comments in the IRC meeting today, I think what

>> you're onto is a new feature, orthogonal to :anon. [...]


>
> This is the opposite of what I brought up on IRC today.

Right, it's a grid of "stored in namespace" and "anchored to namespace",
and if you want to control both features independently, then it makes
the most sense to have them as two independent flags:

:anchor !:anchor
:anon 1 2
!:anon 3 4

Where (1) is your proposal here, (2) is how :anon currently works, (3)
is the default behavior for subs, and (4) is your proposal on IRC. (Just
an illustration.)

Allison

Ben Morrow

unread,
Nov 21, 2006, 11:30:51 PM11/21/06
to perl6-i...@perl.org

Quoth all...@perl.org (Allison Randal):

> Matt Diephouse wrote:
> >
> > Consider the following Perl 5 code:
> >
> > package Test;
> > sub apply {
> > my $func = shift;
> > $func->(shift) while @_;
> > }
> > package Foo;
> > my $line = 0;
> > my $func = sub { print $line++, " ", shift(), "\n"; }
> > Test::apply($func, qw(a b c d)
> >
> > That could be translated into PIR like so:
> [...]
> >
> > In this case, the :anon sub is not stored in a namespace. But a
> > namespace *is* attached to it. That is, it knows to look in ['Foo']
> > for the '$line' global. The bug that this ticket was exposing is that
> > Parrot was looking in the root HLL namespace for the '$line' global
> > instead of looking in ['Foo'].
>
> It could be written that way, but there's actually a good bit more going
> on in the Perl 5 code than anchoring to a namespace. That anonymous code
> block is defined in the dynamic context of its surrounding code, which
> is why it has access to the lexical $line (note, not a global). It's a
> closure. The namespace "anchoring" is a side-effect of being a closure,
> not a fundamental characteristic of anonymous subs in general.

...but that's just a braino on Matt's part, and his point still stands
for the code

package Test;

sub apply {
my $func = shift;
$func->(shift) while @_;
}

package Foo;
use vars qw/$line/; # can't use our as that also creates a lexical :(

$line = 0;
my $func = sub {
print $line++, ' ', shift(), "\n";
};

Test::apply($func, qw(a b c d));

In this case $func picks up $Foo::line rather than $Test::line or
$::line, even though it's anonymous.

Ben

--
Although few may originate a policy, we are all able to judge it.
Pericles of Athens, c.430 B.C.
benm...@tiscali.co.uk

Allison Randal

unread,
Nov 22, 2006, 11:37:26 PM11/22/06
to Ben Morrow, Perl 6 Internals
Ben Morrow wrote:
>
> ...but that's just a braino on Matt's part, and his point still stands
> for the code
>
> package Test;
>
> sub apply {
> my $func = shift;
> $func->(shift) while @_;
> }
>
> package Foo;
> use vars qw/$line/; # can't use our as that also creates a lexical :(
>
> $line = 0;
> my $func = sub {
> print $line++, ' ', shift(), "\n";
> };
>
> Test::apply($func, qw(a b c d));
>
> In this case $func picks up $Foo::line rather than $Test::line or
> $::line, even though it's anonymous.

It's still a closure. Perl 5 just isn't a good example here, since all
anonymous subs are closures.

Allison

0 new messages