[PUGS] Bugs

3 views
Skip to first unread message

Stevan Little

unread,
Mar 2, 2005, 3:17:03 PM3/2/05
to perl6-c...@perl.org
Autrijus & Co.

I have managed to track down two different bugs/issues with PUGS. I
explain them here in detail with examples, and todo_* tests for them
are included in the following test files:
t/op/shift.t
t/op/pop.t
t/op/push.t
t/op/unshift.t

Note that these issues may not be related to these operators at all. I
think the first issue is probably related to how the AST gets
evaluated, and the second issue might be a problem with the Array/List
type itself (or it could be these operators (push, unshift)). Either
way, my Haskell skills are very weak at this point, so I will leave the
real bug tracking to the more lambda inclined.

- Steve

1) It seems that when functions are inlined as arguments to another
function, they will be evaluated twice.

Here is some simple code to illustrate this:
pugs -e 'my @l = (1, 2, 3); my $a = shift(@l); say $a'
prints:
1
and this code:
pugs -e 'my @l = (1, 2, 3); say shift(@l);'
also prints:
1
but this code:
pugs -e 'my @l = (1, 2, 3); say shift(@l); say shift(@l);'
should print
1
2
but it actually prints:
1
3
This issue is illustrated in the t/op/shift.t and t/op/pop.t test file,
as the same issue will come up with inlined pop(@list) as well.

2) I have also found an oddity with push(), which is documented in
t/op/push.t, but I am describing here in more detail.

This code:
pugs -e 'my @l; push @l, 10; say join ", ", @l; say +@l;'
Produces the following output:
, 10
2

Note the leading comma. It seems that if the @l array is not
initialized, then the first element is occupied by an undef value, and
the first push will go into the second slot. I tried changing the way I
write push()

pugs -e 'my @l; push @l, (10); say join ", ", @l;'
pugs -e 'my @l; push(@l, 10); say join ", ", @l;'

NOTE: @l.push(10) is currently a syntax error

But all three versions produce the same 2 element list. However, if the
@l array is initialized (even as an empty array), then the issue
disappears.

The following code:
pugs -e 'my @l = (); push(@l, 10); say join ", ", @l; say +@l;'
Produces the following output:
10
1

The same issue comes up with unshift() as well. The following code:
pugs -e 'my @l; unshift @l, 42; say join ", ", @l; say +@l;'
Produces the following output (note the extra comma):
42,
2
And then if the @l array is initialized:
pugs -e 'my @l = (); unshift @l, 42; say join ", ", @l; say +@l;'
Produces the following output:
42
1

Autrijus Tang

unread,
Mar 4, 2005, 11:04:16 AM3/4/05
to Stevan Little, perl6-c...@perl.org
On Wed, Mar 02, 2005 at 03:17:03PM -0500, Stevan Little wrote:
> I have managed to track down two different bugs/issues with PUGS. I
> explain them here in detail with examples, and todo_* tests for them
> are included in the following test files:
> t/op/shift.t
> t/op/pop.t
> t/op/push.t
> t/op/unshift.t

The double evaluation bug has been fixed today. It was result of a
misunderstanding of the role of $_ when the subroutine body does
not mention $_, but makes use of slurpy arrays (as is the default with
@*_), and has no invocants when actually used; in that case $_ is
probably best undefined (or bound to the first non-invocant argument?
Can we get a ruling?); I have stopped evaluation for $_ in that case for
now, which solves the double evaluation bug.

Thanks,
/Autrijus/

Larry Wall

unread,
Mar 4, 2005, 10:22:38 PM3/4/05
to perl6-c...@perl.org
On Sat, Mar 05, 2005 at 12:04:16AM +0800, Autrijus Tang wrote:
: The double evaluation bug has been fixed today. It was result of a

: misunderstanding of the role of $_ when the subroutine body does
: not mention $_, but makes use of slurpy arrays (as is the default with
: @*_), and has no invocants when actually used; in that case $_ is
: probably best undefined (or bound to the first non-invocant argument?
: Can we get a ruling?);

For a real "sub", it should probably default to undefined. It's when
we start dealing with internal blocks that we start having to play
games with defaulting to the outer scope's $_. Pointy subs are a gray
area, but the consensus seems to be that they should always topicalize
their first argument (again defaulting to the outer $_ if no actual
argument is passed). So they fall more into the block category than
the sub category.

I'm not sure what distinction you're making when you talk about a sub
that "has no invocants when actually used". Unless a sub is declared
"multi" or "method", it never really has any invocants, and if it's
a multi or a method, it always does. Or is this some fudging based
on the fact that we're trying to blur the distinction between multis
and ordinary methods for single invocants? In any case, something
declared with a non-multi "sub" should act very close to what Perl 5
does with an ordinary sub declaration. (Except for the fact that we're
forcing $_ to be lexical, and parameters are no longer rw by default,
and we can now have lexically scoped subs that hide more global subs,
and probably several other things I'm forgetting...)

Anyway, some code examples might help to keep me from rambling on here
about things you already probably know... :-)

Larry

Reply all
Reply to author
Forward
0 new messages