1. 22

Just some loose unscientific thoughts about some programming languages. In this case for a tool I am (very slowly) chipping away at.

Don’t forget to let me know how wrong I am.

    1. 30

      I think classifying C as simplicity 5 / 5 is a bit odd, because it is superficially easy but then actually writing correct code is hard because you need to know the subtleties of it. No wonder there is a book called “Deep C secrets”. In this regard Java is much, much simpler because for the most part you don’t need to concern yourself too much about what the code will compile to, it will be sort of correct. There are a couple of weird and surprising gotchas but my impression is that it is overall way more manageable.

      Also the amount of tooling required to make C correct is anything but simple.

      Of course, all of these points are even more valid in C++.

      Also I think your praising Go with points that are just as valid for Python and Ruby, which you’re pretty much damning (“quite a large number of projects invested into it already, has been stable for years and probably isn’t going anywhere”).

      1. 6

        That’s a great point about C, you changed my mind on that one, even more damning for C++.

        With regard to python and ruby, you are very right, my brain sort of just registered it as a given, but I should have been more clear. I would bet much much more stuff runs on python or ruby than Go.

      2. 9

        I think classifying C as simplicity 5 / 5 is a bit odd, because it is superficially easy but then actually writing correct code is hard because you need to know the subtleties of it

        Simplicity and ease of use are two different things. You could envision an assembly language for a tiny risc with load & store and a handful of other instructions and that’d get you about as simple a turing complete language as one can imagine but it won’t be easy to write complex and correct software in it.

        Now, as for the subtleties of C, I feel like they’re a little overstated. They’re there, but you learn the stuff that matters in a weekend. The rest of Deep sea secrets is just an exposition of funny tricks you can do, if you’re into IOCCC and party tricks.

        Can’t really compare it to Java since I don’t know Java. But going by the spec and features, Java does not appear to be a simpler language.

        I definitely agree that C isn’t 5/5, but it’s fairly simple for a mainstream language.

        1. 8

          Now, as for the subtleties of C, I feel like they’re a little overstated. They’re there, but you learn the stuff that matters in a weekend.

          The ceaseless litany of security problems in C codebases is evidence that this is pretty demonstrably untrue.

          1. 4

            To be fair, security was on a different 0-5 scale so I would presume explicitly excluded from this one. Also, it scored a 0 on security, so I think the author agrees with you.

          2. 2

            I think it’s evidence that a lot of people write code very poorly and that there’s a lot of old C code. It is possible - easy, really - to write very secure C code. It requires you to use a ‘subset’ of the language, I guess, but it’s not difficult. Certainly if you argue that C++ is more secure than C then you’re admitting that the security of a language is not based on all of its features but on the features people use, given that all of C’s security issues exist in C++.

            1. 2

              I think it’s evidence that a lot of people write code very poorly and that there’s a lot of old C code. It is possible - easy, really - to write very secure C code. It requires you to use a ‘subset’ of the language, I guess, but it’s not difficult.

              Well, I mean, by all evidence it is difficult, because plenty of big and important and long-lived projects, with extremely good C programmers behind them, are deeply and critically insecure. At some point you can’t just blame poor craftsmen, at some point it is the fault of the tools.

        2. 1

          Also, if some language X is written in C, then I do not get that X can be simpler than C, as to have X running on your machine, you would need both a C compiler and a X engine/compiler.

        3. 1

          Plus, there’s tools that can check for funky stuff. KCC, the executable semantics for C, says it crashes when it detects undefined behavior during a compile. So, one idea I had was making sure all safer modules compile clean with it.

        4. 1

          Simplicity and ease of use are two different things.

          I agree with you here, unfortunately the article does not do a distinction between simplicity and ease of use. When it comes to simplicity, assembly is pretty simple, so are stack based languages like Forth, with C being someone in the middle ground. In this regard Java is not simple, agreed.

          When it comes to ease of use it is different, but one can also evaluate it in different contexts. Writing a C program that compiles is quite easy, writing correct C programs at scale is a very different matter. Maybe that’s another possible point of comparison: how well does a language scale from simple to complex tasks.

    2. 13

      You might find this interesting, it’s an attempt to predict bugs by language features. Unsuccessful, but still interesting enough for me to finish.

      http://deliberate-software.com/safety-rank-part-2/

      1. 5

        edit: Hey that is actually really cool and interesting, (the point about clojure is interesting too). It is also a pretty smart way to gather data in a situation where it is normally extremely hard to do so.

        Something I just read today too - less about bugs, but more about robustness

        http://joeduffyblog.com/2016/02/07/the-error-model/

        1. 3

          Thanks! Good link too.

          Speaking of which, I highly recommend learning Haskell. It’s a lot of work, but it’s really changed how I think about programing. I would absolutely go back and do it again. It really makes the easy things hard (tiny scripts) but the hard things easy. Very much worth learning in my mind.

      2. 1

        While Tail Call Optimization would certainly be nice to have in Go to improve performance, in practice it’s not a cause of defects because people just use iteration instead of recursion to accomplish the same thing. It doesn’t look as “nice” but you don’t get stack overflows.

        1. 1

          Arguably that could be said of all the things on that list. Every programming language community has idioms to best use the available feature set.

          Specifically for recursion, I was assuming that the mental shuffle to convert something from recursion (often more elegant and simple) to iteration would cause issues. Since the whole model doesn’t work very well, I clearly was wrong in multiple places, and this very well could be one.

          1. 5

            Specifically for recursion, I was assuming that the mental shuffle to convert something from recursion (often more elegant and simple) to iteration would cause issues.

            I could be wrong, but I suspect most developers find iterative algorithms more straightforward to write iteratively, not recursively, and consider writing them recursively a mental shuffle.

            It wouldn’t surprise me if comfort with recursive algorithms is a predictor of developer proficiency, though.

            1. 2

              You are probably right, but I’d guess now that is more because most developers work in languages that don’t support recursion. Originally, I was also going for the idea that it offers a way for the developer to make a mistake without realizing it. In this case, they don’t realize that recursion isn’t tail optimized, since the language allows it without warning. But since I have yet to see anyone use recursion unless they are used to languages with immutability (and even then they probably just use fold), it probably doesn’t come up much.

              As such, it probably makes sense to remove that item, which doesn’t change much, just slightly raises the “c-style” languages and lowers the “lisp-style”.

              1. 2

                but I’d guess now that is more because most developers work in languages that don’t support recursion.

                Most people think about problem solving in an iterative way. They’ll do this, then this, maybe this conditionally, and so on. Imperative. Iterative. Few people think of their problems in a recursive way without being taught to do so. That’s probably why most prefer iterative algorithms in programming languages.

                1. 3

                  To fully shave the yak, I’d argue this is entirely a product of how programmers are taught. Human thinking doesn’t map perfectly to either format. Recursion is just saying, “now do it again but with these new values”, and iteration requires mutations and “storing state”. Neither are intuitive - both need to be learned. No one starts off thinking in loops mutating state.

                  Considering most programmers learn in languages without safe recursion, most programmers have written way more iterative loops so are the most skilled with them. That’s all, and this isn’t a bad thing.

                  1. 3

                    They might not either be very intuitive. Yet, educational experience shows most students pick up iteration quickly but have a hard time with recursion. That’s people who are learning to program for the first time. That indicates imperative, iterative style is closer to people’s normal way of thinking or just more intuitive on average.

                    Glad we had this tangent, though, because I found an experimental study that took the analysis further than usual. I’ll submit it Saturday.

                  2. 1
                2. 2

                  I agree. And I think there’s a lot that just isn’t possible with that mindset.

          2. 3

            Specifically for recursion, I was assuming that the mental shuffle to convert something from recursion (often more elegant and simple) to iteration would cause issues.

            I think it really depends on the algorithm. To my understanding, mapping and filtering is a lot easier recursively, but reducing and invariants tend to be easier iteratively.

        2. 1

          I think I remember reading Russ Cox doesn’t like tail recursion because you lose the debug information in the stack traces.

          1. 2

            This is a big pet peeve of mine: because many languages use pointers in stack traces, you can’t see what the values were at that time. I think storing the value instead of just the pointers would be expensive, but it sure would be useful.

          2. 1

            What information would you lose?

            1. 2

              I think that in this example, you’d think that initial directly called final:

              def initial():
                  intermediate()
              
              def intermediate():
                  final_caller:
              
              def final():
                  throw "boom"
              

              This could make it extremely hard to debug if intermediate happened to modify state and it was the reason why final was failing.

              1. 1

                I think the call stack may be convenient for this purpose, but not necessary. I’m sure there are other (potentially better & more flexible) ways to trace program execution.

    3. 9

      In my experience Go has been pretty performant (of course not on C’s level), certainly more than 3.5/5. And I’d be curious to know why you gave it a 3/5 for simplicity. Taking all of C and not only it’s official standards into account it’s far easier to write Go than (safe, proper) C.

      One huge pet peeve of mine is a language with concurrency but no notion of immutability.

      AFAIK they are working on this for Go 2, but in the mean time, I’ve found that using channels instead of “classical” concurrency mechanisms has been a good workaround – and quite easy to use actually.

      1. 3

        Last I tested python was 100x slower than C, Go was about 2x and java was 1.5x . Not a detailed look really, and maybe things have changed since then.

        I marked go down on simplicity because sometimes things that should be simple are not. One example is forking (due to runtime threads), another is dropping user privileges (due to goroutines not mapping to OS threads.) . It depends what you are trying to do usually though.

        1. 3

          Keep in mind that there are at least two Go compilers: go and gccgo. They have different performance profiles. Gccgo is a GCC frontend. GCC has had built-in support for Go since version 4.6.

        2. 2

          The Java/Go performance disparities really seem to come down to the kind of task one is doing, as seen here – then again “real world” performance is another question…

          One example is forking (due to runtime threads), another is dropping user privileges (due to goroutines not mapping to OS threads.) . It depends what you are trying to do usually though.

          Ok, I understand your point – Go isn’t the best sysprog language that’s pretty uncontroversial. I was thinking of the number of concepts and (especially arbitrary) rules a language specified.

        3. 2

          For many web /API use cases Go is faster than Java but somewhat slower than C++

    4. 8

      Since I write python for a living I can testify that everything you said about it is spot on.

      With that said, I have since discovered D and I’m quickly falling in love with it. It seems to come naturally to me as a python programmer, but it’s much quicker and feels more powerful to me. Should you ever get the time, I’d like to hear your thoughts as well. It will obviously score pretty low in popularity contest.

      1. 2

        D is one of those languages I just never poked at. I have no idea why.

        1. 7

          You really should before committing to Rust. You might like it. It’s a C++ alternative with lots of features that still compiles really fast. They also have the BetterC mode as a C alternative. Aside from borrow checker, Rust’s main advantage over it will be the community that will crank out lots of libraries you might use or that might use your code. D’s community probably won’t achieve parity any time soon.

    5. 8

      You’re not wrong, OP.

      FWIW, Python and Ruby are 0/5 for fun for me. Most of the time they feel like they don’t really value my time. This is coming from someone who spent a significant amount of time in each language, and shipped many apps in different domains, from desktop to web to mobile.

      The problem is that the workflow always seems to devolve into “write/[test]/debug”, where debugging consumes lots of time. Most of it is sorting out errors that basic static analysis would catch immediately. The very thing that people love about these languages I despise: it is easy to simply re-run your programs over and over until you exorcise the bugs, but after being spoiled by ghcid, which tells me instantly if I have a type error after saving, there’s no comparison. There’s always going to be some amount of debugging, but I’ve become accustomed to front-loading that via a compiler and type system.

      1. 7

        FWIW, Python and Ruby are 0/5 for fun for me. Most of the time they feel like they don’t really value my time.

        Interesting. I write Python for a living, and have the point of view that it tends to value my time over basically everything else. There are tools like flake8 and pylint which you can run after saving (or integrate in your editor) that do some static analysis and catch quite a lot of bugs beforehand, so it’s not that bad.

        The type hinting features introduced in the recent versions of Python could also help a little, but at the same time I don’t think the type system will ever be close to what Haskell provides. It’ll take all the fun out. :)

        1. 4

          I think a lot of Python’s productivity boils down to its libraries being relatively well-designed and its straightforward syntax.

          Python’s type hints are a strange beast. They’re useful for documentation and metaprogramming, but they’re just sort of there because Python didn’t want to get left behind in the great Rediscovery of Static Typing.

      2. 3

        This just comes down to personal preference, IMO. I’ve been on both sides of the static-vs.-dynamic typing debate, and I think there’s an element of mathematics vs. engineering to it. Some people prefer tinkering; others prefer derivation. It all depends on what makes you tick.

        1. 2

          I’ve been tinkering happily for about 20 years or so before I got tired of it.

          Of course, there’s always going to be some tinkering on system boundaries. But your whole program? No thanks.

          1. 1

            I suppose static analysis is best for projects that scale.

    6. 8

      Some other factors to consider:

      1. Ease of using UTF-8 strings; I do not use OCaml much anymore, and this is one of the reasons. My brother’s name is Jérôme, not Jérôme.
      2. Ease of concurrency and parallelism; many (most?) programs start off sequential, and at some point, someone wants to extract more out of the machine by making the program parallel.
      3. Ease of error handling: I guess this is related to security, but if error handling is difficult or too verbose, there’s a very strong tendency to avoid doing it.
      4. Ease of extracting more performance: some languages offer good performance by default, but with C, C++, and Rust you can actually go and get more performance by optimizing your data structures for cache.
      1. 2

        That surprises me about OCaml since it was originally created in France.

        1. 6

          They use latin-1 which has all the accented letters we use in French (à, â, é, è, ê, ë, î, ï, ù, û, ç).

    7. 12

      This is a bit of a wild card, I am not experienced at all with haskell, but my impression is it may not be well suited to imperitive operations like read buffers from a stream and write buffers to a stateful database. I could be totally wrong or ignorant and would like to one day address my ignorance.

      These are things that I use Haskell for!! As Tackling the Awkward Squad says:

      In short, Haskell is the world’s finest imperative programming language.

      1. 3

        exactly the type of thing I love to read, thanks :)

      2. 1

        This PDF crashed my browser.

      3. -2

        Can you mark your PDF? Thanks.

      4. 0

        Why was my comment about marking PDFs downvoted?

        1. 0

          The article is an HTML page. There is not a PDF in sight. Why do you want to mark a PDF?

          1. 1

            It’s quite obviously a PDF. I honestly don’t know what you’re talking about.

    8. 9

      I’m surprised to see that Go rated only 3/5 for simplicity. It’s far simpler than modern Java! Just consider how few concepts it has and that they’re all orthogonal to each other so you need not learn about those you don’t use.

      1. 9

        And bus factor for Go should be 5/5. It’s used a bit everywhere at Google and by all kind of large projects outside, so it’s there to stay for many, many years.

        1. 10

          A corporate google mandate could also kill the whole project at any time if they invented something much better. It may not die immediately, but I’m pretty sure they could kill it far more easily than C could be killed. One problem is a scale of 1-5 doesn’t have good resolution :)

          1. 6

            I don’t see how a corporate Google mandate would kill off Go. I could see it removing Go’s google contributions, in the worst case, but the code is open source, and there are a lot of outside companies that use Go, and several of them have implemented other languages in it (at least 2 separate Lua implementations and 1 Lisp come to mind). and Go gets a decent amount of outside developers working on it.

            At this point, Go’s use outside of Google is enough to keep it going should Google suddenly lose interest in it. But given that Go is used a lot inside Google, to the point that there exists a cross compiler from Python to Go, a sudden loss of interest from Google would be a very unlikely event. Dart, a language that is far less popular, is still quite alive and kicking at Google, on the basis of their Ads team using it, even though it has had a much harder time getting adopted outside of Google.

            I don’t think Go is going anywhere soon. I’d personally give it a 4.5/5, if C is the 5/5.

          2. 1

            I very much agree. I am making plans on how to leave the Google ecosystem for emails. Last week they killed Google Inbox (announced plans to do so very soon), and I loved that product very much. I wouldn’t be surprised if Gmail gets killed too. And the same could happen to Go language.

            Inbox wasn’t a less-popular product by any means, and still it got killed.

      2. 1

        I may be accidentally judging on the fact that my old job used an outdated version of java to support the old code. Modern java must be a different story for some things.

    9. 5

      I would have loved if zig could just compile to more or less idiomatic C and give projects an escape hatch if things aren’t going well for zig development after all.

      I’ll never hedge my bets in this way. Maybe C should start compiling to idiomatic Zig and give projects an escape hatch for the impending doom of C :-)

      Also regarding simplicity - just yesterday in this stream I made an argument that Zig is actually a simpler, smaller language than C, because it removes 2 (anti-)features from C. For example the preprocessor. C is actually 2 languages which are unaware of each other whereas Zig is only one.

      1. 2

        I watched the whole stream :)

    10. 5

      I think by “popularity” you rather mean “ecosystem”. C is a very popular language, but if you want to build a web app, there is nearly no marketing, libraries and community support available. This also implies that it very much depends on what you want to build.

    11. 6

      Interesting. I’ll add the security score for C is unfair given, if subsets and tooling are used, it’s easier to write low-defect software in it than most other things. For instance, Astree Analyzer can prove code is free of the kinds of defects C programmers worry about the most. There’s quite a few open tools for C like KLEE and AFL that should knock out a lot of them in combination. Then, it’s one of only two languages (other is SML) that have certifying compiler to prevent it from adding vulnerabilities. There will be lots of false positives and refactoring using the static analyzers. If you don’t have them or don’t want false positives, then C’s safety drops way down to 0-1 given the high impact of failures.

      For Java, it’s security is nowhere near 5. First, its Trusted Computing Base is a combo of a VM and libraries full of unsafe code. You just rated that language at 2. JVM’s vulnerability track record was what one would expect. I kept Java off machines unless absolutely necessary since it was one of top threats. If memory safe, you can still get concurrency errors. There are tons of tools for catching those in Java, though. Even if concurrency safe, a non-low-level language leaves one problem: covert channels (aka secret leaks). It could leave them in memory that gets accessed by malicious or just leaky code later. Alternatively, it obscures the timing of your routines on secrets in ways that leak them. Altogether, Java is a terrible language for security even though it reduces vulnerabilities in the average case for apps written on top of it. It’s why safety-critical Java was usually a subset running on special, deterministic VM’s (example).

      Regarding C++ and OO, I just used structured programming with C++ during brief time I used it. Couldn’t you do that? I would understand if you just don’t like it. I ditched it quickly.

      Regarding Haskell, it’s popular in high-assurance systems, esp tooling for them. Hardware people use it, too. It has same weakness as Java of gap between high-level code and low-level representation causing potential issues. It’s better than Java at TCB quality, concurrency safety, and getting more out of type system. I’d recommend against it since you’re doing something crypto-related that you want high uptake and contributions for. Might have been nice for your compiler project, though. You still might find this paper interesting which assessed its properties for secure programming with a crypto algorithm used as case study.

      1. 2

        I definitely missed a productivity category. The safer C is, the slower work becomes - for some tools (perhaps even this tool) it is worth it to be extremely careful.

        1. 1

          That’s true.

    12. 3

      What we need […]

      What about “soft-features” like eco-system, compatibility, maintainability, testability … ? Those are very important for some of the use cases that that require that the program works reliable and should be definetly considered when choosing a language for a project.

      Edit: especially for a project that aims to be “highly reliable” on its homepage.

      1. 2

        Popularity and eco-system seem highly correlated.

        Not quite sure what you mean by compatibility, but if you mean operating systems, it is quite correlated with popularity.

        I didn’t quite rank maintainability, I think its possible to make a mess of pretty much any language, but it is a good question if some languages produce more maintainable code than others. Rust advertising fearless concurrency is essentially a maintainability issue.

        For testability I have some plans that I might write about later, but it is good to not choose something that paints you into a corner for sure.

        Reliability to me means thorough testing of error conditions and minimizing code in the fault kernel of a program. For this tool in particular this means the write path data takes should be small and tested (across all error paths). The choice of error model for a language does affect this quite a lot. http://joeduffyblog.com/2016/02/07/the-error-model/ .

        If I am totally honest, many languages don’t meet the quality standard (yet) either, which I sort of counted under ‘stability’ even if i didn’t mention it explicitly.

        1. 1

          I didn’t quite rank maintainability, I think it’s possible to make a mess of pretty much any language…

          I think this is in large part because languages that focus on correctness, often do so at the expense of difficult refactoring and daunting cognitive overhead. This manifests as a maintainability issue in actual projects, but the self-selecting nature of the maintainers means the issue is unconsciously swept under the rug.

          At the same time, few languages offer features specifically geared toward keeping code refactorable—let alone aim to be both correct and manageable (both on the screen and in the mind). One rare exception, an example of the latter, is Jon Blow’s Jai prototype.

    13. 3

      It’s a real shame that Nim is dismissed because of its bus factor + low popularity. Please help us get out of this catch-22 scenario. The fun and performance that the language offers really outweighs this.

      One problem is that if the creator lost interest the project would grind to a total halt, which may be a reason for the lack of adoption.

      While this is true the likelihood of it happening is low. The project has been going for a while now and the creator has not budged at all when it came to his passion for it.

      I’ve got a question for you as well: how did you evaluate the popularity of the languages? I’ve noticed that Nim has a score of 1 here, but Zig has a score of 2. I find that strange.

      1. 3

        I’ve noticed that Nim has a score of 1 here, but Zig has a score of 2. I find that strange.

        That seems like an oversight on my part - you are right, I will update the page with a note.

        I actually had the most fun writing Nim of any language recently - For other projects I would definitely use it.

    14. 3
      Python/Ruby
      • performance 0 / 5

      […]

      These languages are slow…

      The Cython project may give you some pause.

      Rust

      […]

      • fun 4 / 5

      Oh, just you wait… You’ll have a love/hate relationship with the borrow checker in no time. My impression is that Rust is very much still coming of age.

      Haskell

      […]

      • fun ? / 5

      …my impression is it may not be well suited to imperative operations like read buffers from a stream and write buffers to a stateful database. I could be totally wrong or ignorant and would like to one day address my ignorance.

      Same caveats as with Rust. But I think you’ll find Haskell’s state encapsulation isn’t all too bad once you get used to it. Plenty unfamiliar, for sure—but the modularity it provides is priceless. Especially for projects of the sort you’re embarking on.

      1. 5

        I played around with things like Cython, never found a way to make Python fast. The guys from Sentry did write some parts in Rust and then embedded it in python, that probably works. https://blog.sentry.io/2016/10/19/fixing-python-performance-with-rust.html

        1. 3

          What shortcomings did you find in Cython?

      2. 1

        Agreed, Haskell code is super easy to rewrite.

    15. 2

      Thank you for sharing this opinion. If taken as a one-stop judgement, it might cause a huge reaction and flame war all over the place. But taking it as an opinion is very pleasant to read.

      1. 3

        I tried to say something I like and something I dislike about each. I was a bit harsh on C++ but I can’t really hurt it. Overall there are things I like and dislike about most of the languages which hopefully came through.

    16. 1

      The levels of OO programming that is idiomatic C++ also bothers me at times. Sometimes a float is a float and doesn’t need 100 lines of class boilerplate to wrap it.

      I find it interesting how often I see people say this. Idiomatic C++ is not layers of OOP, it’s really a procedural language.

      Go: simplicity 3 / 5

      I think Go’s probably the simplest language on this list with the exception of C. I don’t see how it’s the same simplicity as Python, Ruby or Java.

    17. 1

      java has better performance than python? are you okay?

      1. 2

        https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/python.html

        According to this Java is at least 10 times faster on the majority of benchmarks. Java has a native JIT python doesn’t.

    18. 1

      One important factor I don’t recall seeing: availability. Tools like pandoc are not available on my non x86 machines, because Haskell is hard to get on them. The openjdk jvm isn’t even available on Musl on Void Linux, on x86. Golang is more available, rust is a pain to cross compile tooling for (last I tried), making it less available, and only C is available on absolutely every platform I care about.

    19. [Comment removed by author]