# New Ticket Created by  Peter du Marchie van Voorthuysen 
# Please include the string:  [perl #131887]
# in the subject line of all future correspondence about this issue. 
# <URL: https://rt.perl.org/Ticket/Display.html?id=131887 >

This is Rakudo version 2017.07 built on MoarVM version 2017.07
implementing Perl 6.c.

If the value of a Pair is a Scalar container, then the Pair can be
modified, e.g.

    > my $value = 0;
    > my $pair = number => $value;
    number => 0
    > $pair.value = 1; $pair;
    number => 1

Method freeze make the value of the Pair read-only, by removing it from its
Scalar container, and returns the value.

    > $pair.freeze;
    > $pair.value = 2;
    Cannot modify an immutable Int (1)
      in block <unit> at <unknown file> line 1

The problem is that freeze does more than that. It changes the object
identity as returned by WHICH as well:

    > $pair = number => $value;
    number => 1
    > $pair.WHICH;
    > $pair.freeze;
    > $pair.WHICH;

Now by itself having a 2-tuple that is identified by its two elements is a
nice feature (if it would be documented). But _changing_ the object
identity is not consistent with the behavior of other built-in Perl 6
classes and actually breaks the implementation of some of these classes.

For example, a SetHash represents a mutable set. The Set method returns a
_new_ object that is immutable:

    > $pair = number => $value;
    number => 1
    > my $set = SetHash.new($pair);
    SetHash.new(number => 1)
    > my $set2 = $set.Set;
    set(number => 1)
    > $set.WHICH;
    > $set2.WHICH;

But because freezing a Pair changes the identity of the _original_ object
it's possible to add a second instance of the _same_ Pair to the SetHash,
causing it to violate its contract:

    > $pair.freeze;
    > $set{$pair} = True;
    > my ($a, $b) = $set.keys;
    (number => 1 number => 1)
    > $a === $b;

I think it's clear that changing the identity of the original object is not
correct. So I propose to remove the undocumented behavior of the freeze
method that it changes the object identity.

Now I can imagine that at some implementation level there are benefits to
having a kind of Pair that is identified by its key _and_ value. I also
think it could be generally useful to have a class implementing a truly
immutable (2-)tuple that is identified by its elements. But that should be
a separate class and the Pair class should provide a method to create a
_new_ object of this class from a Pair object.

Reply via email to