← Back to context

Comment by josephg

2 days ago

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

> As I said, I ended up needing about 50% more lines to accomplish the same thing in Go

I'd be using Perl if that bothered me. But there is folly in trying to model from a solution instead of the problem. For example, maybe all you needed was:

    type OpType int
    const (
        OpTypeSkip OpType = iota
        OpTypeInsert
        OpTypeDelete
    )

    type OpComponent struct {
        Type OpType
        Int int
        Str string
    }

Or something else entirely. Without fully understanding the exact problem, it is hard to say what the right direction is, even where the direction you chose in other language is the right one for that language. What is certain is that you don't want to write code in language X as if it were language Y. That doesn't work in programming languages, just as it does not work in natural languages. Every language has their own rules and idioms that don't transfer to another. A new language means you realistically have to restart finding the solution from scratch.

> You'd probably need a different problem to show Go or C# in their best light.

That said, my profession sees me involved in working on a set of libraries in various languages, including Go and Typescript, that appear to be an awful lot like your example. And I can say from that experience that the Go version is much more pleasant to work on. It just works.

I'll agree with you all day every day that the Typescript version's types are much more desirable to read. It absolutely does a better job at modelling the domain. No question about it. But you only need to read it once to understand the model. When you have to fight everything else beyond that continually it is of little consolation how beautiful the type definitions are.

You're right, though, it all depends on what you find most important. No two programmers are ever going to ever agree on what to prioritize. You want short code, whereas I don't care. Likewise, you probably don't care about the things I care about. Different opinions is the spice of life, I suppose!

  • Yes I think I mentioned in another comment that that would be another way to code it up. It’s ugly in a different way to the interface approach. I haven’t written enough go to know which is the least bad.

    What are you “fighting all day” in typescript? That’s not my experience with TS at all.

    What are the virtues of go, that you’re so enamoured by? If we give up beauty and type safety, what do you get in trade?

    • I don't become enamoured by language. I really don't care if I have to zig or zag. I'll happily work in every language under the sun. It is no more interesting than trying to determine if Milwaukee or Mikita make a better drill. Who cares? Maybe you have to press a different button, but they both do the same thing in the end. As far as I'm concerned, It's all just 1s and 0s at the end of the day.

      However, I have found the Go variant of said project to be more pleasant because, as before, it just works. The full functionality of those libraries is fairly complex and it has had effectively no bugs. The Typescript version on the other hand... I am disenchanted by software that fails.

      Yeah, you can blame the people who have worked on it. Absolutely. A perfect programmer can program bug-free code in every language. But for all the hand-wringing about how complex types are supposed to magically save you from making mistakes that keeps getting trumped around here, I shared it as a fun anecdote to the opposite — that, under real-world conditions where you are likely to encounter programers that aren't perfect, Go actually excelled in a space that seems to reflect your example.

      But maybe it's not the greatest example to extol the virtues of a language. I don't know, but I am not going to start caring about one language over another anyway. I'm far more interested in producing great software. Which brand of drill was used to build that software matters not one bit to me. But to each their own. Different opinions is the spice of life, I suppose!