Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

:delete holes in Arrays get turned to Mus when coercing to List or Slip #6406

Closed
p6rt opened this issue Jul 23, 2017 · 9 comments
Closed

:delete holes in Arrays get turned to Mus when coercing to List or Slip #6406

p6rt opened this issue Jul 23, 2017 · 9 comments
Labels
LTA Less Than Awesome; typically an error message that could be better testneeded

Comments

@p6rt
Copy link

p6rt commented Jul 23, 2017

Migrated from rt.perl.org#131783 (status was 'resolved')

Searchable as RT131783$

@p6rt
Copy link
Author

p6rt commented Jul 23, 2017

From @zoffixznet

The current behaviour kinda makes sense when you squint at it, but today we had a user[^1]who was surprised by it, so I'm filing it as a ticket, if maybe there's some Better Way this can be done with.

When you :delete an element from the Array, you get nqp​::null stuffed into the position, which gets converted to `is default` value when you look it up again​:

  <Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a
  <camelia> rakudo-moar b14721​: OUTPUT​: «Array @​a = ["a", 42, "c"]␤»

However, if you now convert that Array to a Slip or a List, the hole is left as a bare Mu and doesn't get turned into a default value, which is lost​:

  <Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a.Slip
  <camelia> rakudo-moar b14721​: OUTPUT​: «slip("a", Mu, "c")␤»

  <Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a.List
  <camelia> rakudo-moar b14721​: OUTPUT​: «("a", Mu, "c")␤»

So it makes sense that without `is default` you don't get an `is default` value, but at the same time, Mu is not a great value to deal with...

[1] https://irclog.perlgeek.de/perl6/2017-07-22#i_14908846

@p6rt
Copy link
Author

p6rt commented Jul 23, 2017

From @zoffixznet

On Sat, 22 Jul 2017 18​:48​:38 -0700, cpan@​zoffix.com wrote​:

The current behaviour kinda makes sense when you squint at it, but
today we had a user[^1]who was surprised by it, so I'm filing it as a
ticket, if maybe there's some Better Way this can be done with.

When you :delete an element from the Array, you get nqp​::null stuffed
into the position, which gets converted to `is default` value when you
look it up again​:

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a
<camelia> rakudo-moar b14721​: OUTPUT​: «Array @​a = ["a", 42, "c"]␤»

However, if you now convert that Array to a Slip or a List, the hole
is left as a bare Mu and doesn't get turned into a default value,
which is lost​:

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a.Slip
<camelia> rakudo-moar b14721​: OUTPUT​: «slip("a", Mu, "c")␤»

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a.List
<camelia> rakudo-moar b14721​: OUTPUT​: «("a", Mu, "c")␤»

So it makes sense that without `is default` you don't get an `is
default` value, but at the same time, Mu is not a great value to deal
with...

[1] https://irclog.perlgeek.de/perl6/2017-07-22#i_14908846

And actually both .flat and .Seq do get `is default` value instead of Mu, so at the very least there's some inconsistency here​:

  <Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a.flat
  <camelia> rakudo-moar b14721​: OUTPUT​: «("a", 42, "c").Seq␤»
  <Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a.Seq
  <camelia> rakudo-moar b14721​: OUTPUT​: «("a", 42, "c").Seq␤»

@p6rt
Copy link
Author

p6rt commented Jul 23, 2017

From @AlexDaniel

Perhaps also worth noting that this applies to other holes as well, e.g. those created by extending an array​:

my @​a = 42; @​a[5] = 49; say |@​a # 42(Mu)(Mu)(Mu)(Mu)49

In fact, this the actual problem the user had.

On 2017-07-22 18​:52​:03, cpan@​zoffix.com wrote​:

On Sat, 22 Jul 2017 18​:48​:38 -0700, cpan@​zoffix.com wrote​:

The current behaviour kinda makes sense when you squint at it, but
today we had a user[^1]who was surprised by it, so I'm filing it as a
ticket, if maybe there's some Better Way this can be done with.

When you :delete an element from the Array, you get nqp​::null stuffed
into the position, which gets converted to `is default` value when
you
look it up again​:

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a
<camelia> rakudo-moar b14721​: OUTPUT​: «Array @​a = ["a", 42, "c"]␤»

However, if you now convert that Array to a Slip or a List, the hole
is left as a bare Mu and doesn't get turned into a default value,
which is lost​:

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a.Slip
<camelia> rakudo-moar b14721​: OUTPUT​: «slip("a", Mu, "c")␤»

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a.List
<camelia> rakudo-moar b14721​: OUTPUT​: «("a", Mu, "c")␤»

So it makes sense that without `is default` you don't get an `is
default` value, but at the same time, Mu is not a great value to deal
with...

[1] https://irclog.perlgeek.de/perl6/2017-07-22#i_14908846

And actually both .flat and .Seq do get `is default` value instead of
Mu, so at the very least there's some inconsistency here​:

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a.flat
<camelia> rakudo-moar b14721​: OUTPUT​: «("a", 42, "c").Seq␤»
<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete;
dd @​a.Seq
<camelia> rakudo-moar b14721​: OUTPUT​: «("a", 42, "c").Seq␤»

@p6rt
Copy link
Author

p6rt commented Jul 23, 2017

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Jul 23, 2017

From @lizmat

On 23 Jul 2017, at 03​:48, Zoffix Znet (via RT) <perl6-bugs-followup@​perl.org> wrote​:

# New Ticket Created by Zoffix Znet
# Please include the string​: [perl #​131783]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl6/Ticket/Display.html?id=131783 >

The current behaviour kinda makes sense when you squint at it, but today we had a user[^1]who was surprised by it, so I'm filing it as a ticket, if maybe there's some Better Way this can be done with.

When you :delete an element from the Array, you get nqp​::null stuffed into the position, which gets converted to `is default` value when you look it up again​:

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a
<camelia> rakudo-moar b14721​: OUTPUT​: «Array @​a = ["a", 42, "c"]␤»

However, if you now convert that Array to a Slip or a List, the hole is left as a bare Mu and doesn't get turned into a default value, which is lost​:

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a.Slip
<camelia> rakudo-moar b14721​: OUTPUT​: «slip("a", Mu, "c")␤»

<Zoffix__> m​: use nqp; my @​a is default(42) = <a b c>; @​a[1]​:delete; dd @​a.List
<camelia> rakudo-moar b14721​: OUTPUT​: «("a", Mu, "c")␤»

So it makes sense that without `is default` you don't get an `is default` value, but at the same time, Mu is not a great value to deal with...

[1] https://irclog.perlgeek.de/perl6/2017-07-22#i_14908846

The problem is really caused by the fact that an Array has a descriptor, which contains the default value and type information, and a List does not. And since a Slip isa List, we lose the descriptor when Slipping an Array.

The same issue appears with​:

  $ 6 'my @​a; @​a[2] = 42; dd (|@​a)[0] = 44; dd @​a'
  Cannot modify an immutable Str (Nil)

Which is because Slip is a List, it uses List.AT-POS, and that one doesn’t create a WHENCE with a container to be filled at a later time.

Which then goes back to​: what is the use case of Slipping an Array? When do you need that?

Perhaps slipping an Array should produce a warning?

@p6rt
Copy link
Author

p6rt commented Jul 23, 2017

From @smls

Which then goes back to​: what is the use case of Slipping an Array?

Same as slipping any other type of Iterable​: Fine-grained, elegant flattening and concatenating.

Compare​:

  my @​all = flat $first, @​rest;

  my @​all = $first, |@​rest;

When you *know* that $first is a Scalar and @​rest is an Array, those two do the same thing because `flat` doesn't descend into item containers.

But if those are, say, function parameters, then they can become bound to other things, e.g. the calling code could pass a List to `@​rest` which *doesn't* have its elements itemized, so the version with `flat` would destroy the elements' internal structure.

Even if that wasn't the case, I'd consider the `|` version more elegant than the `flat` version, because it denotes very clearly to the reader *where* exactly something is being flattened into the outer list.

because Slip is a List, it uses List.AT-POS, and that one
doesn’t create a WHENCE with a container to be filled at a later time.

Couldn't `@​array.Slip` be made to properly iterate @​array behind the scenes (the same way that `@​array.map` would iterate it), instead of reaching into @​array's guts and copying its elements in a way that misinterprets some of them?

@p6rt
Copy link
Author

p6rt commented Jul 24, 2017

From @lizmat

On 23 Jul 2017, at 22​:27, Sam S. via RT <perl6-bugs-followup@​perl.org> wrote​:

Which then goes back to​: what is the use case of Slipping an Array?

Same as slipping any other type of Iterable​: Fine-grained, elegant flattening and concatenating.

Compare​:

my @​all = flat $first, @​rest;

my @​all = $first, |@​rest;

When you *know* that $first is a Scalar and @​rest is an Array, those two do the same thing because `flat` doesn't descend into item containers.

But if those are, say, function parameters, then they can become bound to other things, e.g. the calling code could pass a List to `@​rest` which *doesn't* have its elements itemized, so the version with `flat` would destroy the elements' internal structure.

Even if that wasn't the case, I'd consider the `|` version more elegant than the `flat` version, because it denotes very clearly to the reader *where* exactly something is being flattened into the outer list.

because Slip is a List, it uses List.AT-POS, and that one
doesn’t create a WHENCE with a container to be filled at a later time.

Couldn't `@​array.Slip` be made to properly iterate @​array behind the scenes (the same way that `@​array.map` would iterate it), instead of reaching into @​array's guts and copying its elements in a way that misinterprets some of them?

Which is exactly what 12d7d5b48add8347eb119 does.

So fixed, and tests needed!

@p6rt
Copy link
Author

p6rt commented Oct 10, 2017

From @zoffixznet

On Mon, 24 Jul 2017 01​:54​:53 -0700, elizabeth wrote​:

On 23 Jul 2017, at 22​:27, Sam S. via RT <perl6-bugs-
followup@​perl.org> wrote​:

Which then goes back to​: what is the use case of Slipping an Array?

Same as slipping any other type of Iterable​: Fine-grained, elegant
flattening and concatenating.

Compare​:

my @​all = flat $first, @​rest;

my @​all = $first, |@​rest;

When you *know* that $first is a Scalar and @​rest is an Array, those
two do the same thing because `flat` doesn't descend into item
containers.

But if those are, say, function parameters, then they can become
bound to other things, e.g. the calling code could pass a List to
`@​rest` which *doesn't* have its elements itemized, so the version
with `flat` would destroy the elements' internal structure.

Even if that wasn't the case, I'd consider the `|` version more
elegant than the `flat` version, because it denotes very clearly to
the reader *where* exactly something is being flattened into the
outer list.

because Slip is a List, it uses List.AT-POS, and that one
doesn’t create a WHENCE with a container to be filled at a later
time.

Couldn't `@​array.Slip` be made to properly iterate @​array behind the
scenes (the same way that `@​array.map` would iterate it), instead of
reaching into @​array's guts and copying its elements in a way that
misinterprets some of them?

Which is exactly what 12d7d5b48add8347eb119 does.

So fixed, and tests needed!

Tests added in Raku/roast@24d5fcb486

However, the values for .List differ depending on how you access them. If you use iterator, you get a Mu for a hole, but if you use AT-POS you get a Nil..

  13​:04 Zoffix m​: (my @​a)[1] = Mu; my @​b is default(42) = @​a.List; say @​b
  13​:04 camelia rakudo-moar b8eda6​: OUTPUT​: «[(Mu) (Mu)]␤»
  13​:04 Zoffix m​: (my @​a)[1] = Mu; my @​b is default(42) = @​a.List[*]; say @​b
  13​:04 camelia rakudo-moar b8eda6​: OUTPUT​: «[42 (Mu)]␤»

I filed a separate ticket for that​: https://rt-archive.perl.org/perl6/Ticket/Display.html?id=132261

IRC​: https://irclog.perlgeek.de/perl6-dev/2017-10-10#i_15283224

@p6rt
Copy link
Author

p6rt commented Oct 10, 2017

@zoffixznet - Status changed from 'open' to 'resolved'

@p6rt p6rt closed this as completed Oct 10, 2017
@p6rt p6rt added LTA Less Than Awesome; typically an error message that could be better testneeded labels Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LTA Less Than Awesome; typically an error message that could be better testneeded
Projects
None yet
Development

No branches or pull requests

1 participant