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
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
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
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
...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
It's still a closure. Perl 5 just isn't a good example here, since all
anonymous subs are closures.
Allison