1. 22
  1. 5

    There was hearty discussion of this post in the rust subreddit. https://www.reddit.com/r/rust/comments/8asb4i/dark_side_of_ergonomics/

    I particularly liked @burntsushi’s response, which begins like this:

    I feel like you’re missing the forest for the trees. In particular, you seem to be toting balance as a counter to absolutist arguments that I don’t think actually exist. e.g.,

    • ergonomics are good, but not at any cost
    • ergonomics is not the only thing
    • [ergonomic is not] the most important one

    I think you’d have a really hard time finding someone that would defend these principles. To me, that means you’ve built up a straw man.

    https://www.reddit.com/r/rust/comments/8asb4i/comment/dx1d32o

    1. 3

      As I see it, despite the wave of blog posts, Rust is still niche. Its usage is very small compared to the massively popular languages. I predict that unless Rust changes a lot and makes it easy for anyone to use, its usage will remain comparable to Haskell or Lisp usage: widely loved or desired language but too weird for mass adoption.

      Let’s see in five years how this plays out. Maybe I’ll be wrong.

      1. 11

        I don’t disagree and that makes me sad for what we as programmers ask for from our tools. I went through something like this a long time ago. I chose the “easy route” over the “difficult” one. I wish I hadn’t.

        In my case, I went with C over Ada because Ada frustrated me and it was hard to get it to compile. That my C programs were easy to compile but crashed all the time on me was never something that I saw as problematic until I gained a lot more experience.

        I wrote a bit about that a couple years back.

        https://www.monkeysnatchbanana.com/2016/02/22/learning-from-ada/

        1. 3

          Good write-up. That should be a submission instead. :)

          1. 4

            Thanks. Already submitted a couple years ago. Once from me is enough. If it ever reappears on lobste.rs, it will be because of someone else.

        2. 3

          I’d like to like Rust, but it seems a complex language.

          I’m not talking about the borrow checker, but the large number of features it proposes.

          There must be a way to get a good statically typed safe language that is simple… or not?

          1. 2

            Which features do you think can be removed without sacrificing safety while maintaining usability?

            1. 2

              What a wonderful and deep question!

              The honest answer is: I don’t know. :-)

              However I usually do not consider simple anything that qualify as syntactic sugar (eg macros). Generics are useful but increase the language complexity. Same goes for Traits or Closures.

              Note that I like each of these features.

              But I would like more a safe language where there is always one single obvious way to do each thing.

              1. 5

                But I would like more a safe language where there is always one single obvious way to do each thing.

                Have you used Rust in anger yet? It is not that far from this ideal. Certainly closer than a lot of other languages I have experience with, although I think perfection on this front isn’t really attainable.

                Macros are a good candidate to remove, in theory. But it’s a classic example of letting perfection be the enemy of good. Simple use of macros saves me a lot of annoyance, especially when writing tests. I’ve managed to stay away from more complex uses in all but one instance in my four years of working in Rust nearly daily. Not everyone has avoided them though.

                I don’t see how you could get a safe language with low level control without generics though. I can almost live happily without generics in a language like Go, but not Rust. Traits come right along with that as the implementation of useful generics (not the only choice, but you need something).

                I’m surprised to see you mention closures. They are as standard of a feature as they come.

                Keep in that Rust isn’t just after safe and static types here. We also want zero overhead abstractions. Combining all three creates a sharp knife that cuts through the design space.

                Note that I can’t actually answer my question. I am way too buried in Rust to have the requisite perspective. But. I can at least challenge others on it. :)

                1. 1

                  I can at least challenge others on it.

                  And you are welcome! I did not tried Rust on any real world project, so my opinion is pretty weak, based on general language considerations, reading the book and few toy programs (written before Rust 1.0).

                  Macros are a good candidate to remove, in theory. […] I’ve managed to stay away from more complex uses…

                  That’s a smell of a design issue: people should not need to pick “the good parts” of a language. ;-)

                  I don’t see how you could get a safe language with low level control without generics though. […]

                  By simple composition.

                  You might object that it’s boring and verbose, and you’re probably right.

                  But it make the language simpler.
                  Note that I’m not advocating the Go approach, which is another complex language, just with a different kind of complexity.

                  I’m surprised to see you mention closures.

                  Again, a cool feature on their own, but they further increase the language complexity.

                  And again, without them, programs will be more verbose.
                  But language’s verbosity might force the programmer to keep things simple and small.

                  We also want zero overhead abstractions.

                  And this is another thing I like about Rust. But, while I know nothing about language design (and it’s pretty out of my sphere of competences) my insight is that it could be simpler without sacrifying safety or zero overhead abstractions.

                  Note that such complexity is not for free: it locks the language to one single LLVM based implementation, that is hard to port to new hardware or new operating systems.

                  1. 4

                    That’s a smell of a design issue: people should not need to pick “the good parts” of a language. ;-)

                    I don’t think so. To be clear, that’s what I meant by letting perfect be the enemy of good. No design is perfect, just like no battle plan survives first contact with the enemy. Many uses of macros do paper over shortcomings in the expressivity of the type system, but fixing that requires more features, like higher kinded polymorphism or integer generics or specialization. I think you’d say all of those things are too complex. Some of those things are or will be coming to Rust, and macros have allowed, in certain circumstances, folks to solve problems that maybe they wouldn’t have otherwise.

                    By simple composition.

                    Note that Rust’s type system already favors composition today, in a way that works well with generics. (i.e., Rust does not have something like class inheritance.)

                    You might object that it’s boring and verbose, and you’re probably right.

                    But it make the language simpler.

                    Very strongly disagree, and my counter argument has nothing to do with “boring” or “verbose,” and everything to do with feasibility. A fundamental design proposition of Rust is that folks can build safe APIs that may or may not use unsafe internally. This is very common in the implementation of generic data structures like hash maps, btrees and growable arrays (vectors). If you didn’t have generics, I don’t know how you would build a single implementation that could be reused for data structures like that in a way that has zero overhead. Rebuilding those data structures isn’t practical, since getting the best performance possible requires unsafe code.

                    You can thumb your nose at this and just say these are symptoms of design flaws, sure, but removing generics would certainly not make using the language simpler. It would be much much harder and more complex. What would be more interesting is to suggest the removal of generics and also provide an idea on how to solve the problem of reusability. Because of the desire to limit the scope of unsafe, reusability is a critical aspect of writing code in Rust, because you really do not want to be re-litigating the implementation of unsafe code. It is much better to do it once, carefully audit it, and get as many others to use it as possible.

                    You might say that dealing with unsafe in this way is itself a flaw. And that the language should be able to permit more things safely. Maybe. But I think that’s an open question at this point, and almost certainly comes with extra type system expressivity, which may make things more complexity. But, that is certainly something Rust can improve on in the future. Nevertheless, it’s hard for me to see an alternative to the core design principle of building safe APIs over unsafe internals.

                    Note that such complexity is not for free: it locks the language to one single LLVM based implementation, that is hard to port to new hardware or new operating systems.

                    No it doesn’t?

                    Anyway, I guess this conversation has run its course. I’d definitely encourage you to keep thinking about concrete suggestions to make a different programming language that accomplishes what Rust does, but in a way that’s simpler. I can maybe imagine some tweaks here and there, but I think omitting some of the big picture features you’ve listed (without replacing them with something else) would be a serious mistake. The fact that you don’t want closures hints to me that we may have fundamentally different opinions that cannot be overcome.

                    1. 2

                      Wow! :-D

                      I think you have largerly overestimated my competence about language design tradeoffs!

                      But frankly, given the quality of your answer, I do not regret the misunderstanding. Thanks! ;-)

                      All you say is reasonable (and informative).
                      And despite being fluent in several different language, I’ve no real clue to propose alternatives. To me Rust feels complex. Not really difficult, just complex.

                      But (and sorry if I poke you more, hoping for an even greater response :-D), all the features I named can be defineds as (properly checked) syntactic sugar.

                      Whatever you can do with macro, generics and even closures, you can do manually. And whatever you can do manually, you can do by generating code.
                      The point is, actually, if you can write or generate boring and safe code.

                      I agree that without such syntactic sugar, some programming tasks become overly verbose.
                      And boring. But this might discourage complex programs, which is a Good Thing (TM).

                      Note that such complexity is not for free: it locks the language to one single LLVM based implementation, that is hard to port to new hardware or new operating systems.

                      No it doesn’t?

                      Do you mean that we have a Rust compiler not based on LLVM IR?

                      I missed that! What a great news!

                      1. 4

                        To me Rust feels complex. Not really difficult, just complex.

                        I see. I understand that, yes. I guess the thing that is more interesting to me is whether it is necessary complexity or incidental complexity. If it’s necessary, then great. We need to pick ourselves up by the bootstraps and find a way to teach people that complexity until it becomes easier to learn. If it’s incidental, then the design needs more work. Of course, all designs will have some amount of incidental complexity, but if there’s a huge area of the design space that Rust is missing, then it might be possible that there is in fact a lot of incidental complexity! Or perhaps changes in hardware in the future will alter the calculus we use today to decide things. It has certainly had an impact on C’s design trade offs.

                        And whatever you can do manually, you can do by generating code.

                        Note that generics are, to some extent, an interface to a code generation tool. It is through an automatic process called monomorphization, but that’s basically all it’s doing internally: code generating. There are other approaches to generics that languages like Java take that don’t necessarily require code generation, but they tend to have performance trade offs that would be unacceptable in a language like Rust.

                        Regardless, for Rust, I’m very skeptical that a simple code generation tool would be feasible in practice, but it is of course untested.

                        Do you mean that we have a Rust compiler not based on LLVM IR?

                        Note that you said that it “locks” the language to one single LLVM based implementation, but there is nothing about Rust that makes it true. A different statement that I might agree with is, “The complexity of the language makes it difficult to build alternative implementations.” :-)

                        With that said, there is actually a Rust compiler that doesn’t depend on LLVM called mrustc. I believe it compiles to C. It is obviously a work in progress, but IIRC, it has bootstrapped rustc itself, which makes it worth taking serious IMO. :-)

                        1. 2

                          And despite being fluent in several different language, I’ve no real clue to propose alternatives. To me Rust feels complex. Not really difficult, just complex.

                          Yeah, Rust is relatively complex. I like the language, and I get a huge amount of leverage out of it, but I think there are some things that could be simplified, combined, and made more powerful and general in a future incarnation of a systems language. But the bones of Rust is still far simpler than C++, and much saner than C, and it has a great ecosystem, so it’s the one I pick!

                          I’m putting my money where my mouth is by tinkering on some ideas for future langs, but don’t be expecting anything this decade! Building languages is hard, especially ones that try to tackle the domains that Rust works in.