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

Request to undeprecate Pair .freeze #5121

Open
librasteve opened this issue Dec 8, 2022 · 8 comments
Open

Request to undeprecate Pair .freeze #5121

librasteve opened this issue Dec 8, 2022 · 8 comments

Comments

@librasteve
Copy link

The Problem

Certain algorithms are easier to understand and maintain with the Pair .freeze method.

This is evident from a recent StackOverflow question.

Expected Behavior

My vote is to keep .freeze in the language (perhaps with another name)

Actual Behavior

.freeze is deprecated and scheduled for removal.

Environment

any

@lizmat
Copy link
Contributor

lizmat commented Dec 8, 2022

The reason for .freeze to be deprecated, is that it changed a non-value type into a value type, without changing the type.

If we're going to re-instate this behaviour, I'd rather see it as a sub-class of Pair, which would be pretty easy to do. Now we get to the matter of naming...

@jnthn
Copy link
Member

jnthn commented Dec 8, 2022

I was about to say "shouldn't it just return Enum, the immutable parent class of Pair"...but then noticed Pair has no such parent! Am I misremembering, or did it really disappear?

@lizmat
Copy link
Contributor

lizmat commented Dec 8, 2022

Enum is a compile time construct, and is basically a Map underneath with the keys exposed.

@2colours
Copy link
Contributor

2colours commented Dec 8, 2022

Yall were faster than me. Still, I'm gonna leave this here.

Raku/old-issue-tracker#5581
Raku/old-issue-tracker#6442

@jnthn
Copy link
Member

jnthn commented Dec 8, 2022

Nope, Enum really did exist as a Pair base class until 2232157; I remembered correctly. :-)

@2colours
Copy link
Contributor

2colours commented Dec 8, 2022

I think most of the hassle comes from the misdesign and/or miscommunication of what a Pair is and what it's meant for. Confer the smartmatching behavior as well.

Pair is, or at least was, no matter how funny this sounds, really an alias for a symbol, and therefore a value-typed key with any value or container bound to it. I really doubt the name or the semantics of Pair could change in the foreseeable future but we should at least try to communicate it clearly what it is and what it is not:

  • it is not a value-type in the first place, as lizmat pointed it out
  • it is not symmetrical regarding the two parts it holds, meaning that they have a hierarchic relation and they aren't interchangeable under the hood. The existence of antipair is highly misleading in this regard - definitely something that needs to be compensated for!
  • consequently, it is not a great fit for "first value, second value" two-element tuples, despite the fact it often lets you get away with this way of thinking (pretty sure I have also used it like that a number of times)
  • it is the type that backs up several "associate a variable to a name/key" features; most importantly named parameters and Hashes

One place where this education can take place is the documentation. It's good that there is an entry about an essential aspect of Pair behavior - however, rather ironically it advises the use of freeze. I think that topic can be extended, while also removing that advice. I would also definitely add a "note" to antipair that it de facto "freezes" the newly created Pair.

For freeze itself: I think the argument that it mutates the mutability of an "identifier type" was indeed strong enough for it to be removed. Another path could be to create a method that creates a new, "containerless" Pair, and therefore doesn't mangle with the existing instance at all.

@librasteve
Copy link
Author

Another path could be to create a method that creates a new, "containerless" Pair, and therefore doesn't mangle with the existing instance at all.

works for me, something like

method freeze( Pair:D: => Pair:D ) {
    self.key => self.value<>
}

@Mercerenies
Copy link

Mercerenies commented Dec 8, 2022

Hi there! Asker of the SO question linked in the title here. I have definitely learned a lot from reading this. It was not at all clear to me from the docs alone that Pair is a complex internal aliasing type. When I saw the Pair type, I had been treating it as a simple two-tuple that could be loaded into associative containers, not as a kludge but genuinely because I had no idea that was wrong.

In my mind, it's a bit of a shame that a generic word like Pair is used for something so complex, when in other languages it's a simple 2-tuple. If we were designing the language for the first time, I'd probably advocate for Pair being simple (and containerless) and for having a separate type that does what today's Pair does (maybe call it Kwarg or something, since it's the syntax used in named arguments). But obviously such renames are not going to happen at this stage.

Even in the absence of a significant name change, I think there does need to be a separate type. It seems I'm not the only one using Pair to mean "two things juxtaposed in an arbitrary context", so that leads me to conclude that there's a type missing from the standard library, namely a type that actually does capture that notion correctly.

And if there were two separate types, then some of the other misleading things can be moved over too. For instance, antipair on Pair could be deprecated, and this new hypothetical tuple type could get a real antipair that makes sense for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants