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

Maybe sort the output of the keys command #1025

Closed
krader1961 opened this issue May 13, 2020 · 9 comments
Closed

Maybe sort the output of the keys command #1025

krader1961 opened this issue May 13, 2020 · 9 comments
Labels

Comments

@krader1961
Copy link
Contributor

It would be nice if the output of keys was in a predictable order; i.e., sorted. Especially in an interactive context the current random order is somewhat annoying:

> keys $str:
▶ has-prefix~
▶ title~
▶ trim~
▶ contains~
▶ trim-suffix~
▶ index-any~
▶ trim-left~
▶ has-suffix~
▶ to-lower~
▶ last-index~
▶ to-title~
▶ contains-any~
▶ index~
▶ join~
▶ compare~
▶ trim-prefix~
▶ trim-space~
▶ count~
▶ to-upper~
▶ equal-fold~
▶ replace~
▶ split~
▶ trim-right~
@hanche
Copy link
Contributor

hanche commented May 14, 2020

⬥ keys $str: | to-lines | sort | all
⮕ compare~
⮕ contains-any~
⮕ contains~
⮕ count~
[… and so on …]

But of course you knew that already. I agree that having them sorted is nice to have, as this has been an irritant to me too. But unless this is literally a two line fix (it might be), I wouldn't give this a really high priority at present. For my own uses, I'll just turn the above into a function, possibly without the trailing all.

@zzamboni
Copy link
Contributor

I don't know any languages that offer any promises in the order of keys in a hash/dictionary. I agree this would be nice in an interactive context, but then it should be a feature of the editor. Particularly since sorting the output of the keys command would imply (as mentioned in the chat) coercing all keys to the same type. I personally find the ability to have arbitrary objects as keys useful sometimes.

@krader1961
Copy link
Contributor Author

I don't know any languages that offer any promises in the order of keys in a hash/dictionary.

That is true for hash based maps which is, as you note @zzamboni, a widely used implementation strategy. But there are tree based implementations that do guarantee the order of the keys. And some languages, such as Python, have had ordered dictionaries for a long time. Although, in the case of Python it wasn't the default behavior until very recently.

I personally find the ability to have arbitrary objects as keys useful sometimes.

Me too. I'm not proposing restricting keys to strings. I'm proposing requiring that the keys for a particular map be the same data type; whether that is string, float64, list, or something else. Regardless of the merits of having keys always sort the keys. Note that @hanche's example for sorting the keys only does "the right thing" for strings:

> m = [&(float64 11)=a &(float64 3)=c]
> keys $m | to-lines | sort
11
3

Since the keys are numbers I would expect the order to be 3, 11. Lists as keys also produce the wrong sorted order when coerced to strings:

> m = [&[1]=a &[1 2]=b &[1 1]=c]
> keys $m | to-lines | sort
[1 1]
[1 2]
[1]

@krader1961
Copy link
Contributor Author

There was an IM/Gitter discussion about this wherein @xiaq pointed out that preserving insertion order is often more useful than sorting the map's keys. Which is why Python's collections.OrderedDict exists and has recently become the default implementation for its dictionaries/maps. If Elvish static maps like the $str: namespace are constructed in a fashion where the keys are inserted in sorted order and iterating over the map preserves that order then this issue becomes moot. Other than any requisite documentation updates.

@krader1961
Copy link
Contributor Author

It would be okay if the output of keys was predictable but not necessarily sorted. Having the output of keys be based on insertion order would resolve this issue if maps like $str: had their content initialized with the keys sorted.

@krader1961
Copy link
Contributor Author

Regarding whether map keys should be homogenous this, from "When to release Elvish 1.0", seems relevant:

Static type system. A language without any kind of static type system is not likely to be future-proof. I have this vague idea that Elvish should have an optional structural type system much in the style of TypeScript, but there are many details to be figured out.

@xiaq xiaq added the maybe label Feb 28, 2022
@krader1961
Copy link
Contributor Author

Revisiting this I'm going to close this issue. It's now easy enough to do keys $str: | order. The order command builtin was added a few days after my previous comment. If someone can make a convincing argument that the default enumeration of map keys should be predicated on insertion order they should open a new issue. I still, however, feel that Elvish map keys should be homogenous. While that is clearly orthogonal to the original intent of this issue I'm still extremely bothered that examples like this are valid Elvish:

> var x = [&x=y &(num 0)=z &[a b]=why]
> pprint $x                                                                                                                                                        369 µs
[
 &(num 0)=	z
 &[
  a
  b
 ]=	why
 &x=	y
]

I'm still convinced that heterogenous key types should be disallowed. Note that I am not arguing for disallowing heterogenous value types.

@krader1961
Copy link
Contributor Author

Note that the order builtin requires the values to be homogenous:

> order [a [a]]
Exception: bad value: inputs to "compare" or "order" must be comparable values, but is uncomparable values

It's not obvious why maps should not include a similar restriction. Certainly the Go language, and pretty much all other languages, require maps to have a homogenous key type.

@krader1961
Copy link
Contributor Author

Closing again, because even though Elvish maps allow heterogenous key types that will rarely be true in practice. And if someone wants to use heterogenous key types they should be aware that order [(keys $map)] will fail (at least at this time). That inability to use the order command in that situation does not justify automatically ordering the output of keys since doing so could be accomplished by an equivalent modification to the order command to support heterogenous value types. Ultimately Elvish should either require map keys to be homogenous or the order command should be modified to support ordering heterogenous value types.

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

No branches or pull requests

4 participants