Live data from Hacker News

No safe efficient ways to do three-way string comparisons in Go

go101.org

141–150 of 154 posts

Re: No safe efficient ways to do three-way string comparisons in Go

#141

Earlier quoted context omitted.

I'm not that good at it either, but I think that the runtime.memequal call is coming from the if a == b test, and that it is the if a test that is being replaced with a call to runtime.cmpstring . If so, then I guess there's still a redundant call to runtime.memequal inserted by the compiler. It's hard to imagine any of this matters at all, in practice, which is probably why the go authors haven't bothered addressing…

Thanks! Never thought == could be a simple buffer comparison (after a length check, I guess). I thought locale and things being Unicode would make that harder.

Ah, this confuses everyone: strings in Golang are really just read-only byte slices. They can contain Unicode, but they don't have to, and the == operator just does a byte comparison.

Re: No safe efficient ways to do three-way string comparisons in Go

#142

Earlier quoted context omitted.

The comment is confusing, but the idea seems to be that instead of calling this function, you should inline the code - that is, just write the comparisons yourself. You don't need a function call. I guess this is for stylistic reasons, but I don't know why anyone would feel strongly about doing it one way or the other.

Go doesn't have many features of other languages. There are several competing goals, including keeping the language small, not hiding complexity, etc. Manually writing the three-way comparison fits in with these goals. If slices were comparable then I'd wager that bytes.Compare would not exist.

Even if the compiler had good optimization of three way compares, this would be useful for passing to a higher order function. Say a function that allows you to specify how strings should be ordered.

Re: No safe efficient ways to do three-way string comparisons in Go

#143

> Basically no one should use strings.Compare Others have already talked about the performance aspect but I'm just baffled at the comment basically saying nobody should use this function anyway. I expect the need for 3-way compares isn't that uncommon, why tell people not to use it? It's great to have this idea that the compiler should optimize all comparison situations but a) it doesn't yet and b) people still want…

> you still end up with tons of code duplication if people followed the advice.

Code duplication is the go way

Re: No safe efficient ways to do three-way string comparisons in Go

#144

Earlier quoted context omitted.

Assuming you normalized the strings before.

Why would that matter, if you only want some well-defined order?

Because with (Unicode) strings, "\u006e\u0303" is defined to be equal to "\u00f1", for example. If you'd do bytewise comparison, as the above comment suggested, you may not reach the same result ¯\_(ツ)_/¯

Re: No safe efficient ways to do three-way string comparisons in Go

#145
post #63

Earlier quoted context omitted.

I seem to recall one of go’s creators snapped back at a similar question about code duplication with “what’s the matter, are your fingers broken?” I think that sums up the philosophy, though maybe not as well as “Nothing was achieved here”, which I would like to translate into Latin and get on some stickers.

Quoted post unavailable.

Since we've asked you many times to stop posting flamebait and you're still doing it, I've banned the account. It's not what this site is for, and it destroys what it is for.

If you don't want to be banned, you're welcome to email hn@ycombinator.com and give us reason to believe that you'll follow the rules in the future. They're here: https://news.ycombinator.com/newsguidelines.html.

Re: No safe efficient ways to do three-way string comparisons in Go

#146

This is just Go's philosophy of "we're delivering a language for bad programmers, we know what's best for them".

They're allowing devs to resist foolish performance pressure. This is a language for good developers, built by good designers.

Re: No safe efficient ways to do three-way string comparisons in Go

#147
post #114

Earlier quoted context omitted.

But of course the real solution is to use a strong and composable type for your comparison result, rather than remove the entire thing because you originally designed the API wrong.

I like how Rust does it with the `Ordering` type and associated combinators: https://doc.rust-lang.org/stable/std/cmp/enum.Ordering.html For two values `x` and `y` of the same type with fields `a` and `b`, this lets you compare on `a` first and then on `b` by writing ``` x.a.cmp(&y.a).then(x.b.cmp(&y.b)) ```

Not bad but I think python's way - using tuples is cleaner

  (x.a, x.b) 
btw you can format as code by indenting two spaces.

Re: No safe efficient ways to do three-way string comparisons in Go

#148
post #29
post #19

I’d argue that any string comparison which does not take into account collation is inherently broken. Even in the pure ASCII English-language case, a naïve comparison on values won’t give desirable results since abc123 will come before abc99 even though a reader would expect otherwise. Just because we’ve tolerated crappy string sorting for sixty years doesn’t mean we should continue to do so.

For some applications (eg sticking stuff in an ordered data structure), you just need any consistent ordering, but don't care too much about exactly which one.

Then in that case, treat the string as an array of bytes.

Re: No safe efficient ways to do three-way string comparisons in Go

#149

Earlier quoted context omitted.

Why would that matter, if you only want some well-defined order?

Because with (Unicode) strings, "\u006e\u0303" is defined to be equal to "\u00f1", for example. If you'd do bytewise comparison, as the above comment suggested, you may not reach the same result ¯\_(ツ)_/¯

Whether those two strings are or are not equivalent depends on the context. If we're assuming (as the GP did) a very generic context where we simply want to store arbitrary strings in a sorted data structure, then there is no reason to assume they are supposed to be interpreted as Unicode.

For a simple example, perhaps this is a list of strings that require Unicode normalization to be properly interpreted as human text that you are storing into a TreeMap for efficient retrieval. When you are adding "\u00f1" to the list, you wouldn't want the collection to say that it's already there because it already had "\u006e\u0303".

Re: No safe efficient ways to do three-way string comparisons in Go

#150
post #41

The optimal version does seem to exist here (per the comment too): https://github.com/golang/go/blob/d28bf6c9a2ea9b992796738d03... So the goal was to intentionally nerf Compare() to discourage code the golang authors considered less clear. I'm not sure bad performance is really discouraging usage though, it just penalizes folks that use stdlib. I wonder if they'd accept a PR to switch to runtime.cmpstring today?

It actually used to call this, but was changed in 2015: https://github.com/golang/go/commit/fd4dc91a96518fdbb47781f9... I'm not entire sure if I see the problem or follow why just using runtime·cmpstring is such a bad thing; doesn't seem that "overengineered" to me.

> The function is here ONLY for symmetry with package bytes.

> This function should be used ONLY if it makes code clearer.

> It is not here for performance. Remove any performance benefit.

Insane troll logic, pure and simple.

Post reply on HN