Live data from Hacker News

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

go101.org

41–50 of 154 posts

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

#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?

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

#42
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.

I've been developing my own version string parser for a couple weeks now, in golang.

It's ridiculous to what lengths you have to go to understand which part of a string comes earlier or later.

Simple example: semantic versioning allows "1.2.3alpha" and also 1.2.3-beta", but which one comes first now...

- Is 1.2.3 > 1.2.3omega?

- Is 1.2.3 > 1.2.3beta?

- Is 1.2.3gamma > 1.2.3?

In the Linux world it gets even funnier cause they invented SONAME fields that reflect breaking API changes instead of forcing packages to comply with semantic versioning syntax. Oftentimes there is a package version of e.g. 0.4.7 that has an SONAME of 12.7 on the filesystem.

Add to that the ~prerelease suffix syntax in Debian based distros which are maintained downstream, and all the +buildid or .commithash or -revision123 suffixes and you've landed in string comparison hell.

When I started I would have never guessed that this is such a complex problem to solve in golang.

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

#43

Earlier quoted context omitted.

I don't blame the cute three way comparison at all for that problem. Converting number types incorrectly is an endemic problem, and using the right conversion would have made this work quite nicely.

What's the right conversion in this case? How to narrow down negative long to negative int without loosing a sign?

I don't know about Java or Go, but any time I've looked at a C compiler's output it's emitted pretty good assembly for "if (a>b) return 1; else if (a<b) return -1; else return 0;" kinds of input when optimization is on. As long as the type being compared is something the compiler can reason about (and/or has a peephole optimization for I guess).

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

#44

> 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…

Quoted post unavailable.

> it is designed to be friendly to enterprises who have to produce code

Our two person engineering team has found this to be the ultimate form of user-friendliness as our goal is to pragmatically deliver software.

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

#45

> 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…

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.

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

#46

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.

Yes, I mentioned that that's basically what it says. But why would you tell people to actively duplicate code? It's like "I don't get what this type of function does and have to look it up all the time, better to have everyone inline this so it's clearer". To be fair, I agree that seeing bad examples of its use shown by one of the other folks here, some could have been avoided by them being forced to inline, but funn…

I think manual three-way comparisons are very clear. But so is strings.Compare. For better or worse, copying code is a pretty normal thing to do in Go. See "A little copying is better than a little dependency." [0]

[0]: https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s&themeRef...

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

#47
post #38

So I think the strings.Compare should be implemented efficiently, to avoid breaking user expectations. Is Go forkable (for lack of a better word)? That's the only question that comes to mind when I read the article. You have the source code, and this shouldn't be a difficult change to make, so I think "fork-and-fix and see who follows along" should be the mentality to practice in this case.

No one will follow along. If you want to implement strings.Compare better, you can write a package and publish it for other folks to import. The function is not particularly special.

No one will follow along.

"The only sure path to failure is to not even try."

Or are you both implying the power of and supporting the massive monopoly that Google already has?

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

#48

Earlier quoted context omitted.

Quoted post unavailable.

> it is designed to be friendly to enterprises who have to produce code Our two person engineering team has found this to be the ultimate form of user-friendliness as our goal is to pragmatically deliver software.

I think what they're saying is that you need more code in Go, which is inherently unfriendly to developers, to produce an equivalent output in other languages. And to a certain extent that is true, but it disregards the intangible benefits of Go, such as it's balance between simplicity and the ability to make it perform.

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

#49

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.

What sticks out to me is the part saying "the compiler should be changed". It's weird enough that this isn't even a doc comment but a comment inside the function (making it harder for people using the function to notice), but even as someone who thinks the passive voice is often unfairly maligned, the phrasing immediately brings to mind the question "who should change the compiler?" Is the Go standard library not maintained by the same group of people as the compiler, or is this comment just a doubly obfuscated "TODO"?

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

#50
post #38

Earlier quoted context omitted.

No one will follow along. If you want to implement strings.Compare better, you can write a package and publish it for other folks to import. The function is not particularly special.

No one will follow along. "The only sure path to failure is to not even try." Or are you both implying the power of and supporting the massive monopoly that Google already has?

Encouraging people to use a different language entirely (Rust, whatever) is much much more likely to succeed than getting them to use some random Go fork.
Post reply on HN