Comment by 9rx
2 days ago
That wouldn't explain C, then, which does not have sum types either.
All three languages do have enums (as it is normally defined), though. Go is only the odd one out by using a different keyword. As these programs were told to be written as carbon copies of each other, not to the idioms of each language, it is likely the author didn't take time to understand what features are available. No enum keyword was assumed to mean it doesn't exist at all, I guess.
C has numeric enums and tagged unions, which are sum types without any compile time safety. That’s idiomatic C.
Go doesn’t have any equivalent. How do you do stuff like this in Go, at all?
I’ve been programming for 30+ years. Long enough to know direct translations between languages are rarely beautiful. But I’m not an expert in Go. Maybe there’s some tricks I’m missing?
Here’s the problem, if you want to have a stab at it. The code in question defines a text editing operation as a list of editing components: Insert, Delete and Skip. When applying an editing operation, we start at the start of the document. Skip moves the cursor forward by some specified length. Insert inserts at the current position and delete deletes some number of characters at the position.
Eg:
Then there’s a whole bunch of functions with use operations - eg to apply them to a document, to compose them together and to do operational transform.
How would you model this in Go?
> C has numeric enums and tagged unions
C has unions, but they're not tagged. You can roll your own tagged unions, of course, but that's moving beyond it being a feature of the language.
> How would you model this in Go?
I'm committing the same earlier sin by trying to model it from the solution instead of the problem, so the actual best approach might be totally different, but at least in staying somewhat true to your code:
> C has unions, but they're not tagged. You can roll your own tagged unions, of course, but that's moving beyond it being a feature of the language.
This feels like a distinction without a real difference. Hand-rolled tagged unions are how lots of problems are approached in real, professional C. And I think they're the right tool here.
> the actual best approach might be totally different, but at least in staying somewhat true to your code: (...)
Thanks for having a stab at it. This is more or less what I ended up with in Go. As I said, I ended up needing about 50% more lines to accomplish the same thing in Go using this approach compared to the equivalent Typescript, rust and swift.
If anyone is curious, here's my C implementation: https://github.com/ottypes/libot
Swift: https://github.com/josephg/libot-swift
Rust: https://github.com/josephg/textot.rs
Typescript: https://github.com/ottypes/text-unicode
I wish I'd kept my Go implementation. I never uploaded it to github because I was unhappy with it, and I accidentally lost it somewhere along the way.
> the actual best approach might be totally different
Maybe. But honestly I doubt it. I think I accidentally chose a problem which happens to be an ideal use case for sum types. You'd probably need a different problem to show Go or C# in their best light.
But ... sum types are really amazing. Once you start using them, everything feels like a sum type. Programming without them feels like programming with one of your hands tied behind your back.
3 replies →