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

proposal: constraints: rename package to "of" #50348

Closed
panyox opened this issue Dec 26, 2021 · 42 comments
Closed

proposal: constraints: rename package to "of" #50348

panyox opened this issue Dec 26, 2021 · 42 comments

Comments

@panyox
Copy link

panyox commented Dec 26, 2021

snippet code

func Abs[V of.Number](v V) V{...}

func Sum[K comparable, V of.Number](m map[K]V) V {...}

it is simple and smooth to type the word "of" better then "constraints"

@gopherbot gopherbot added this to the Proposal milestone Dec 26, 2021
@davecheney
Copy link
Contributor

davecheney commented Dec 26, 2021

There seems to be a pattern; the strings package contains symbols that relate to strings, the bytes package contains symbols that relate to slices of bytes, so the of package contains symbols related to, uh, prepositions?

But seriously, if you think it reads better, you can rename the import thusly

import of “constraints”

@robpike
Copy link
Contributor

robpike commented Dec 26, 2021

Too bad any is taken because any.Integer or any.Comparable reads nicely.

@seankhliao seankhliao changed the title proposal: Should the "constraints" package named "of" is better proposal: rename the "constraints" package to "of" Dec 26, 2021
@fzipp
Copy link
Contributor

fzipp commented Dec 26, 2021

My suggestion was is, because it contains the essence of types (lat. esse = to be): is.Integer, is.Comparable, is.Ordered.

@robpike
Copy link
Contributor

robpike commented Dec 26, 2021

Bikeshed entry number 4:some: some.Integer.

I do agree with the implication of the original comment that 'constraints' feels cumbersome.

@zephyrtronium
Copy link
Contributor

The name of the package was brought up (as @fzipp mentioned) in discussion, and @rsc marked it as resolved. I agree "constraints" is quite long, but I don't see what's changed.

@panyox
Copy link
Author

panyox commented Dec 27, 2021

definitely agree, "constraints" is cumbersome, hope the go team make some change in the future

@zigo101
Copy link

zigo101 commented Dec 27, 2021

Is it a good idea to make them all pre-declared?

@ianlancetaylor
Copy link
Member

Is it a good idea to make them all pre-declared?

Not in my opinion. It's possible to write these in the language (which is a good thing), so there is no reason to predeclare them.

@earthboundkid
Copy link
Contributor

My vote at the time of the discussion was types, but sadly, it seems the 🚢 has sailed.

@cristaloleg
Copy link

anyof ? 👀 anyof.Number, anyof.Ordered.

@Warmbellycat
Copy link

import isA “constraints”

isA.Number
isA.Ordered

@zhuah
Copy link

zhuah commented Dec 29, 2021

how about std? i like this, short, means standard but not builtin.
like cpp and rust, they also has a std namespace or crate.

@zhuah
Copy link

zhuah commented Dec 29, 2021

maybe someday we will adds some types like Optional[T] and Result[T, E], these types will have their own methods,
then which package should them be added in? constraints or types or just builtin, etc..

@mvdan
Copy link
Member

mvdan commented Dec 29, 2021

@zhuah std is already taken; see: go list std

@bitfield
Copy link

if you think it reads better, you can rename the import thusly

Dave is pleased to joke, but you absolutely shouldn't do that.

@seanmrnda
Copy link

definitely agree, "constraints" is cumbersome, hope the go team make some change in the future

just use an alias

@zhuah
Copy link

zhuah commented Dec 31, 2021

@mvdan thank you for clarification, i almost forgot it.

@ianlancetaylor
Copy link
Member

I think it's worth considering that in my experience so far the most commonly used identifier in the package currently named "constraints" is Ordered. of.Ordered doesn't read very well to me. Of the names suggested above and at #47319 (comment) the only plausible alternative I see to date is "is".

@mvdan
Copy link
Member

mvdan commented Dec 31, 2021

If we want to avoid the ambiguity of import "is", we could also consider import "constraints/is".

@dotaheor
Copy link

dotaheor commented Jan 1, 2022

I prefer import . "constraints".

func Abs[V Number](v V) V{...}

func Sum[K comparable, V Number](m map[K]V) V {...}

@smasher164
Copy link
Member

On their own, the package names any, of, and some don't indicate any meaning. It's only after seeing them in conjunction with .Number that their meaning is apparent. constraints may be cumbersome to type, but both for documentation/package discovery and reading someone else's code, it's a lot clearer.

@fzipp
Copy link
Contributor

fzipp commented Jan 1, 2022

On their own, the package names any, of, and some don't indicate any meaning. It's only after seeing them in conjunction with .Number that their meaning is apparent.

From the Go blog on package names:

"A package name and its contents' names are coupled, since client code uses them together. When designing a package, take the client’s point of view."

Take sort.Interface as an example. Here the type name Interface by itself doesn't mean a lot. Only the combination of both the package name and the type name creates the meaning.

constraints may be cumbersome to type, but both for documentation/package discovery and reading someone else's code, it's a lot clearer.

Re readability: Reading the package name constraints in a piece of code like [T constraints.Ordered] doesn't add any information. Of course it's a constraint, because it's used in the constraint position. If anything, its dominating lengthiness distracts from the more important rest.

Re documentation/discovery: Every package has a short description that is displayed in the package overview https://pkg.go.dev/std and in the documentation of the package itself. This is discoverable via search engines and Ctrl+F.

There is no shame in short package names if they are expected to be used a lot. The popular string formatting package was named fmt, not format or formatting, which would be "clearer" if explicitness was the only guiding principle.

@zigo101
Copy link

zigo101 commented Jan 2, 2022

Code cleanness is a big advantage of Go. We should not forget this.

@smasher164
Copy link
Member

smasher164 commented Jan 3, 2022

@fzipp

Take sort.Interface as an example.

Okay, but here we have the opposite situation. Interface is a symbol defined in the package sort, while of/any/is are package names themselves. Apart from dot imports (which are mostly discouraged), Interface can't be referenced without some qualifier.

Also, sort actually conveys meaning. In fact, all of the examples you gave convey the purpose of the package. I agree there is some grey area for short package names that are used a lot, but I think of/any/is are just far too vague.

@mibk
Copy link
Contributor

mibk commented Jan 4, 2022

These are my bikeshed entries:

  • ofkind.Integer
  • only.Integer

Too bad any is taken because any.Integer or any.Comparable reads nicely.

In addition to the name "constraints" being cumbersome I also think
it's unfortunte that the constraint comparable is a builtin type
while other "general" constraints are not. I would lean towards
either making all the constraints builtin (which might resolve this
issue, albeit by polluting the global space), or moving comparable
(despite its "magical" properties) to package constraints.

@rsc
Copy link
Contributor

rsc commented Jan 5, 2022

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@rsc rsc changed the title proposal: rename the "constraints" package to "of" proposal: constraints: rename package to "of" Jan 5, 2022
@gavingroovygrover
Copy link

There's always "curbs", which is 6 runes shorter.
Is "curb" a synonym of "constraint"?
The spec would needing changing too e.g. "A curb is a constraint on ..."

@rsc
Copy link
Contributor

rsc commented Jan 12, 2022

We added this to the proposal minutes to see if any new information came in since the previous discussion. It looks like there has not been.

The reasons for constraints at this point are:

  1. We already discussed this and ended at constraints.
  2. "constraints.Integer" is clear for readers even if a little long-winded for writers, and we expect that there will be many more people reading generic signatures than writing them.
  3. Words like "is" or "of" are a bit more cute than we usually aim for. People mention "fmt", but "fmt" is clearly short for "format", whereas "is" can be interpreted in many ways. There is a third-party testing package named "is", for example, supporting that there's nothing fundamentally "genericsy" about "is".
  4. "constraint" is also the term used throughout the spec definition for generics. Having the package name match the feature has discoverability benefits.

@earthboundkid
Copy link
Contributor

I think the thing we want to know is “how annoying is it in practice that signatures with ‘constraints’ will be rather long?” Fortunately, if the answer turns out to be “very” we can just use an import alias in the short term and introduce a new package in the long term, so it’s not an irrevocable decision.

@andig
Copy link
Contributor

andig commented Jan 12, 2022

Apart from having to type it the main drawback of long names is imho readbility when you have more then one or two parameters. It distracts people and leads to hard-to-read, long signatures.

@rsc
Copy link
Contributor

rsc commented Jan 12, 2022

Based on the discussion above, this proposal seems like a likely decline.
— rsc for the proposal review group

@andig
Copy link
Contributor

andig commented Jan 12, 2022

Not sure. Is got 19 thumbs up. Would that need a new proposal?

@seankhliao
Copy link
Member

Any renaming of constraints is covered in this proposal.

@robpike
Copy link
Contributor

robpike commented Jan 12, 2022

Point 1 is not itself enough, since the release has not happened yet, and we are in the phase of finalizing decisions. A decision can change. It's not a cost-free change, but it's doable.

Not sure about point 2. The word "constraints" is just so long and not, in package-name space, Go-like. Plus the impliciti analogy with "bytes" and "strings" is specious, since the package isn't about functions that operate on things, it's a set of type definitions to enable functions.

Point 3 is a reach, I think. Honestly I believe some of the shorter suggestions read very well. The pre-existence of a package in the open source world is not a problem: there are countless name collisions. Enabling them was part of the design of packages.

Point 4 is true, but is it critical?

Sorry to push on this, and I see the "likely decline", but I still feel "constraints" is an ugly name to put in a function definition. @carlmjohnson's point about frequency is a good one to consider.

@jimmyfrasche
Copy link
Member

If everyone aliases the import to something else, I would consider that more of a readability concern than having an import that's not immediately clear the first time you see it.

@ChrisHines
Copy link
Contributor

We have an example of how the length of constraints can contribute to the length of a generic function declaration in #47649.

func EqualFunc[M1 constraints.Map[K, V1], M2 constraints.Map[K, V2], K comparable, V1, V2 any](m1 m1, m2 M2, cmp func(V1, V2) bool) bool

I am not partial to any of the suggested names, but it seems to me constraints contributes too much to the length of this declaration compared to its semantic contribution. Compare it with:

func EqualFunc[M1 is.Map[K, V1], M2 is.Map[K, V2], K comparable, V1, V2 any](m1 m1, m2 M2, cmp func(V1, V2) bool) bool
func EqualFunc[M1 of.Map[K, V1], M2 of.Map[K, V2], K comparable, V1, V2 any](m1 m1, m2 M2, cmp func(V1, V2) bool) bool
func EqualFunc[M1 some.Map[K, V1], M2 some.Map[K, V2], K comparable, V1, V2 any](m1 m1, m2 M2, cmp func(V1, V2) bool) bool

Also compare with this layout I suggested in #47330 (reply in thread)

func EqualFunc[
    Map1 constraints.Map[K, V1],
    Map2 constraints.Map[K, V2],
    K comparable,
    V1, V2 any,
](m1 Map1, m2 Map2, cmp func(V1, V2) bool) bool

@ianlancetaylor
Copy link
Member

ianlancetaylor commented Jan 13, 2022

Note that thanks to #48424 there is no more constraints.Map. The declaration you mention is now written as

func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, cmp func(V1, V2) bool) bool

It's certainly true that constraints.Map, constraints.Slice and constraints.Chan could lead to very long function declarations, and that helped accept #48424 which removed them.

@jimmyfrasche
Copy link
Member

Even if those particular references are no longer valid those are still examples of a small number of uses of constraints inflating a signature considerably.

@ianlancetaylor
Copy link
Member

Honest question: can you point us to those examples? Thanks.

@jimmyfrasche
Copy link
Member

I meant that the examples using constraints.Map were examples where repeating constraints just 2-3 times in a signature is enough to make it quite large, especially if there are other parameters.

@rsc
Copy link
Contributor

rsc commented Jan 19, 2022

No change in consensus, so declined.
— rsc for the proposal review group

@marvinhosea

This comment was marked as off-topic.

@rsc rsc removed this from Proposals Jan 25, 2023
@golang golang locked and limited conversation to collaborators Oct 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests