1. 12

    I feel like he doesn’t address some questions properly.

    • when asked about rust and linear types, he says he tried to do that fifteen years ago, but with a purely linear implementation (where you pass a unique pointer to the callee, and it returns it to you when it’s done). That’s not quite as convenient as what rust does with borrowing and affine types.
    • maybe C++ proposed “epochs” are different than rust editions, I don’t know; but his rambling about not being able to use tooling from older epochs in newer ones is exactly the problem rust editions address. The whole point is to be able to deprecate things or change some parts of the language in newer editions, while being able to interoperate with old code!! So your legacy codebase of 3Mloc still works, but you can use a stricter, more modern language in new code. The compilers must be able to understand new and old epochs and have them interoperate, of course; in practice it means they should unsugar both old and new constructs to a similar IR.
    • the whole thing about people not using the STL, as far as I know, is because the STL’s API, not implementation, prevents it from being efficient. So when he says people should just stick to the STL interfaces when redoing their thing is flawed from the start. Alternative standard libraries and hashtables and whatnot are faster because they are not compatible with the STL. 🤷
    1. 32

      A long time ago I was a huge fan of a certain programmer¹ who had a lot of technical prowess and put TONS of angry rants that I thought were funny in their code. Bashing other tech companies’ engineers in a funny way while writing awesome code seemed to be a great thing to aspire to. One day I decided to contribute a one-line patch to this programmer’s side project which was on their self-hosted git instance. Not wanting to go through the annoying process of setting up git to work with gmail for a one-line patch, I just typed the diff into what I thought was a decent and friendly email. I received no response and forgot about it.

      A few months later the programmer, not realizing (or caring) that I followed them on twitter wrote a pointed angry rant about idiots who could only use github and not send in a properly formatted git patch. This was followed by a tweet asking a question about the thing my patch aimed to fix, meaning that the previous rant was almost certainly about me. Suddenly, all the programmer’s funny angry rants weren’t so funny anymore, and just made this programmer seem like… a jerk. They are now the CEO of a successful startup. Am I going to apply to work for them? Probably not. Am I going to use their product were I to need its features? Maybe, but with hesitation.

      The whole reason I’m telling this story is to remind people that it’s possible to be opinionated without being a jerk, and that it’s bad to celebrate when people voice good opinions in a jerk-like way². The programmer in question could have emailed me back asking for a properly formatted git patch, privately complained to their friends, or expressed their frustration on twitter in a way that wasn’t mean. I think the last part is the most important – rants have their place to vent frustration (and clearly Drew is very frustrated) or even change people’s minds, but have a different tone entirely when one of the core aspects of a rant is “I am smarter and more ethical than these other people.”

      I hope Drew’s concerns get addressed, but I also hope he is able to voice them more constructively in the future.

      ¹ Left unnamed, but not @ddevault

      ² See Linux Torvalds, for example

      1. 15

        Not to pile on, but this is the reason I unfollowed Drew on fosstodon. How angry rants become very pointed and are sometimes on the brink of harassment.

        1. 4

          I didn’t even had to do that, he blocked me after insulting me. I still like to read his posts, but more for the spectacle than for objective opinions, really.

        2. 4

          rants have their place to vent frustration (and clearly Drew is very frustrated)

          I think this is key. Drew seems to be generally angry and frustrated with the state of the world, technology, ethics of technologists, etc. And he’s right to be angry, a lot of stuff sucks! Anger can be a good/useful emotion, if it drives you to change shitty situations instead of accepting them, and that’s something I admire about Drew, his refusal to take the status quo for granted and his ability to follow through on groundbreaking projects. (I’m rooting for Sourcehut because it isn’t a clone of Github, it has a different philosophy and design goals, whereas many open source products look like inferior knockoffs of some proprietary progenitor.) Maybe he wouldn’t be making the kind of software+projects he does if he weren’t so angry. But, like most things, anger can be toxic when taken to extremes or misdirected, and it can drive people away.

          Whenever I introduce one of Drew’s projects like Sourcehut to my friends/colleagues, or forward a post of his, I have to add the disclaimer that Drew is kind of a dick, even though I tend to agree with him on many things. At some point his anger may do more damage to his projects by preventing people from using or contributing to them than whatever motivational benefits his anger provides to his personal productivity.

          1. 4

            One of the effects of having some of my own posts being posted on sites like Reddit and Hacker News a few times is that I’ve become a lot more careful in how I comment on other people’s posts. In general, I strive to write anything public as if the author of the post would actually read it. In quite a few cases, they probably do.

            It’s easy to think you’re oh-so-witty-and-funny with your snarky sarcastic takes or whatever; but in reality it’s usually not, especially not over the internet.

            I’ll readily admit I don’t always succeed at this though; but I try. I sometimes rant a bit to my friends or girlfriend in private, which has the same frustration-venting effect and doesn’t upset anyone. Just because someone is wrong, or because you strongly disagree with them, isn’t a reason to be a jerk to them.

          1. 7

            I think this is the first explanation that kinda makes sense and shows very well how the module system works.

            One thing I’m still wondering is: Why does it work this way?

            I’m using Rust since a while and I still haven’t seen any benefits of Rust’s module system over more “traditional” ones. Rust’s is just more complicated and that’s pretty much it, from my point of view.

            1. 5

              What even is a “traditional” module system? There are vast differences between Python’s module system, Java’s module system, JavaScript’s dozen unofficial module systems, Go’s module system, C’s module system and C++‘s two module systems. It’s not obvious to me that this is a “solved” problem with one “traditional” solution which everyone uses.

              1. 2

                Let’s pick an average one from Java/C#, i. e. where there is direct relationship between file path, file name, the file’s package/namespace declaration and the type contained in that file.

                Might be the case that Rust’s approach feels familiar if everything one knew was how C header files work, but I would have expected that people building Rust’s module system had stronger requirements than “slightly better than C header files”.

                1. 8

                  Let’s pick an average one from Java/C#, i. e. where there is direct relationship between file path, file name, the file’s package/namespace declaration and the type contained in that file.

                  I can’t speak much to Java, but for C# this is absolutely not the case, both in theory and practice. A given source file may have multiple classes, a given class may be split across multiple source files (a feature usually reserved for UI related code), a given assembly may expose types in multiple namespaces, a given namespace may have multiple assemblies that comprise it. Assemblies exist in a flat namespace, while they can have .s in their names it doesn’t have much or anything to do with their location in the filesystem relative to each other.

                  Actual C# source code does not refer to assemblies at all generally.

                  1. 1

                    Why Java/C#, instead of node.js or python or the new C++ module system or Go or something new? The Java solution probably makes sense if you know Java, but I don’t think Java developers are even the main target audience, given that Rust is mainly developed as an alternative to C++.

                    1. 7

                      C++ modules are basically its designers saying “whatever we can manage to do, after 30 years of bad decisions”, so I wouldn’t consider it to have many worthwhile design lessons that are applicable outside C++.

                      I think Java/C# are interesting design points, because they had the requirements that the main way of distributing the artifacts could not require recompilation/linking/etc. unlike Rust or Go.

                      It works reasonably well, the artifacts are rather small compared to other languages, and compatibility is well-understood.

                      I think that’s a reasonable starting point from which one can ask “why has Rust all this complexity, that doesn’t seem to buy me anything, while having to satisfy less requirements than Java?”.

                2. 4

                  Most of the answers to why in the rust module system are “to avoid whole-program recompilations or dependency cycles”.

                  1. 4

                    I don’t see the complexity, really. Modules mostly map to files (if you keep things simple), like in python; except you replace __mod__.py or whatever is it with mod.rs. You can also nest modules in other modules, giving you easy namespacing. I have a hard time imagining a simpler system that would still be reasonably expressive (i.e. not “one class per file” like java, or no namespacing at all like C).

                    1. 2

                      To me, the benefits are:

                      • It’s self-describing and doesn’t require scanning the file system. Lack of implicitly-discovered files means you can define modules conditionally (without module-specific features in the language). Stray files from botched git merges or editor backups don’t get included accidentally.

                      • It is simple. People get confused because it’s different from other module systems, but by itself the rule of mod defines a scoped item the same way as fn, struct, and enum do” makes a lot of sense. In other languages modules/packages are a meta-language on top of the language, often with their own syntax and rules. In Rust mod and struct are both “items” that behave similarly in many ways.

                      • pub use is very neat for designing your library’s public API separate from your library’s internal structure (e.g. I may want to have one widget per file for my convenience, but for user it’d be silly to import library::widgets::foo::Foo. I can make it library::FooWidget or library::widgets::Foo.) What is also cool about it is that it’s a design pattern that comes from a logical combination of two features (pub and use), rather than being a special-case export feature.

                      1. 1

                        It’s self-describing

                        Having to hand-craft the public API because the library’s structure has no bearing on it – I believe that’s the opposite of self-describing.

                        doesn’t require scanning the file system

                        Agreed, though there are other approaches that do this just as well.

                        you can define modules conditionally

                        I think there are better approaches for that. Rust’s approach tends to result in #ifdef’ed files all other the place.

                        In my experience, for instance Scala’s approach of having a directory tree with “shared source” and then having “conditional sources” in a separate directory tree (controlled by the build system) is much cleaner and easier to understand.

                        It is simple

                        I wouldn’t say that. The structure of the source does not reflect the API exposed, I’d say that’s rather unintuitive.

                        And having to make decisions between pub mod foo and pub use self::foo::{...} is not great either.

                        I may want to have one widget per file, but for user it’d be silly to import …

                        I guess this is where we disagree – I don’t think this benefit (to library authors) is worth the costs (to library consumers) that creating choice and adding flexibility create.

                        (I’d rather have the “inconvenience” of having to write some things in the same file, than having to wonder where things are every time I read a library by someone else.)

                        1. 2

                          It’s self-describing in the sense that the source code describes the crate structure, not an external build system or the filesystem.

                          The structure of the source does not reflect the API exposed, I’d say that’s rather unintuitive.

                          Users never access files of libraries, only the public API, so there’s nothing to be confused about.

                          And for contributors, it’s not a problem to find what is where, because the source code contains the mod and use declarations which are sort-of like waypoints or table of contents for navigating the source.

                          1. 1

                            It’s self-describing in the sense that the source code describes the crate structure, not an external build system or the filesystem.

                            Other approaches also do this, just without the additional indirection Rust affords.

                            Users never access files of libraries, only the public API, so there’s nothing to be confused about.

                            I have found it more productive (given the state of crate documentation and rust docs in particular) to simply read the source, instead of hunting for documentation that may or may not exist at some unknown place.

                            1. 1

                              instead of hunting for documentation that may or may not exist at some unknown place

                              docs.rs/<name of a crate>

                              If something isn’t there, run cargo doc --open from the source to get the same.

                              1. 1

                                That’s not what I meant – my problem is that many times the documentation just hasn’t been written, or is missing crucial aspects.

                                1. 1

                                  For that I recommend clicking [src] links in rustdoc output, which take you straight to relevant implementation.

                                  1. 1

                                    Yes, that’s basically my recommendation – skip the docs, just read the source.

                    1. 2

                      I should have posted a link to https://groups.google.com/g/golang-nuts/c/7t-Q2vt60J8/m/daacBE2tBQAJ that expands the first post in the thread and makes reading easier. Can a moderator please update the post link to this URL?

                      1. 5

                        it seems to require a google account to read… too bad

                        1. 2

                          This one doesn’t require a google account (taken from HN):

                          https://groups.google.com/forum/?_escaped_fragment_=topic/golang-nuts/7t-Q2vt60J8

                      1. 42

                        Why are these kinds of articles almost always predicated on the authors being completely unaware of Option/Result types?

                        It’s the old “beating down the exception strawman” – that no one is even interested in defending.

                        (I wonder what happens to all these similar articles when Go gets generics and people start using Option/Result types?)

                        1. 16

                          The author does give lip service to Option/Result types:

                          EDIT: Exceptions are definitely not the only way other languages deal with errors. Rust, for example, has a good compromise of using option types and pattern matching to find error conditions, leveraging some nice syntactic sugar to achieve similar results.

                          But in a way that suggests they’re something he’s heard of, rather than personally used. If you’re already used to working with ADTs that contain errors, I can’t imagine finding Go’s system of basically mandatory 2-tuple return types for all error-prone functions to be ergonomic.

                          1. 12

                            Agreed. Plus all the fun in figuring out whether you actually need to handle the value and error case, because the signature doesn’t tell.

                          2. 8

                            As someone who was an adamant gopher for like 7 years. Rust’s Option and Result types changed the way I see programming, especially once I fully grokked that Result is basically a monad.

                            1. 4

                              Same, although I had that realization when encountering the equivalents of those types in Haskell, rather than Rust. A lot of what I like about Rust is that it’s a mainstream language (more mainstream than Haskell in any case) that lets you easily define and use ADTs.

                            2. 11

                              It’s the old “beating down the exception strawman” – that no one is even interested in defending.

                              I dunno, having used Go as my main development language for eight years now, I encounter people defending exceptions far, far more often than people advocating for option types.

                              1. 5

                                Isn’t it that, at this point in time, most people familiar with option types for errors are developing in Rust and not really in the Go world anymore ?

                                Somebody coming from a language with exceptions to Go might say he prefers his old way. And there probably aren’t, today, many people coming from Rust to Go.

                                1. 6

                                  sure, I think there aren’t many people coming from Rust to Go, that’s … kinda my point? soc is mad that the article is not written specifically for him, and is instead written for an audience that is more representative of who the author is actually encountering. The idea that exceptions are a straw-man nobody is defending is … honestly a little ridiculous. People defend exceptions all the time. The majority of programmers work in JS, Python, Java, C#, and PHP, all of which have error-handling semantics built around exceptions. A lot of those programmers really do make arguments defending exceptions. Few of them read lobste.rs for recreation. And you know, the few that DO read lobste.rs for recreation need articles like this to learn about things they haven’t encountered yet.

                                  I also find it so hilarious that someone flagged my prior comment as “incorrect”. I described my lived experience and someone flagged it as “incorrect”. lol

                                  In reality, most people just code because it’s a job. This article is not written for people looking to find self-actualization in a type system.

                                  1. 3

                                    I also find it so hilarious that someone flagged my prior comment as “incorrect”. I described my lived experience and someone flagged it as “incorrect”. lol

                                    Looks like all my comments on this thread have received at least one flag.

                                    I don’t know what it is about Go that induces such rage in some people, it’s completely fine (even reasonable!) to not like Go, but Go threads have a tendency to turn in to dumpster fires in a way that I don’t see in other languages (including PHP and JavaScript).

                                    1. 1

                                      I don’t know what it is about Go that induces such rage in some people

                                      classism.

                                2. -10

                                  I’d assume that people with higher language quality standards usually don’t intermingle with Go devs.

                                  Communicating with Go devs certainly forced me to reevaluate the minimal amount of knowledge I assumed to be absolutely necessary to be a functioning programmer.

                                  1. 15

                                    Communicating with Go devs certainly forced me to reevaluate the minimal amount of knowledge I assumed to be absolutely necessary to be a functioning programmer.

                                    Dude, what the fuck? This has no place here.

                                    1. -4

                                      I don’t think you need to get emotional over this.

                                      I reported my experience, just like other people have in this thread.

                                      1. 1

                                        I did not downvote your comment, because I did not get emotional over it. What happened here I think is that people read “Go devs” and instinctually took your rather laconic criticism of the technology to be criticism of the members (i.e., themselves) belonging to the said group.

                                        It is easy to become a target of put-down by aggravated members of any group if you are not vigilant with your words.

                                    2. 5

                                      “Enable fresh graduates to contribute effectively” was a core design goal for the language.

                                      It’s not surprising, then, that there’s no shortage of beginners to be found there.

                                      1. 4

                                        In my experience/interactions there are actually comparatively few new programmings in Go; much of the documentation and resources also tend to be aimed more at people who already know how to program in another language, I’ve seen quite a few people complain about the lack of entry-level jobs, the community is not always very welcome to beginners, etc. Generally speaking, I wouldn’t recommend it as a first language.

                                        This is just my subjective impression; I don’t have any numbers to back this up and could be wrong.

                                      2. 5

                                        The Rob Pike quote (which seems to have come from this talk: https://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/From-Parallel-to-Concurrent ) was:

                                        “The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.”

                                        And this left a bad taste in my mouth when I read it originally. Either Rob Pike is right about the sorts of people he needed to optimize for when creating Go, implying that Google hires fresh out of college aren’t skilled enough programmers to deal with things like ADTs; or Rob Pike was wrong about who he was optimizing for and made a language that deliberately limits the tools you have to write correct and concise software because he mistakenly thought those tools were too hard for people to use.

                                        1. 5

                                          Agreed.

                                          It really feels like Go creators think nothing of value was invented/discovered since they left Bell labs.

                                          Also, using one of their team members as the language mascot is kinda weird.

                                          1. 5

                                            Also, using one of their team members as the language mascot is kinda weird.

                                            Huh? The Go Gopher was based on one of their team members?

                                          2. 3

                                            the fact that you find that quote upsetting is rooted in either class dysphoria or class chauvinism. One can only find that statement upsetting under one of the following two conditions:

                                            • class chauvinism: you think that programming should be reserved for an intellectual elite, and that opening programming to the labor class is a form of class betrayal by an intellectual elite. What you reject is not the design or implementation of Go itself, but the goals that the Go team has laid out when attempting to create the language. That is, the frustration is with the very goal of creating a programming language that can be used by the unwashed masses because programming should be reserved for the privileged.

                                            • class dysphoria: you reject the idea that the majority of software is written by a labor class, and that you are a member of that labor class. You are upset by the phrase “to use them to build good software”. This is only upsetting to you if you don’t accept your position that as a person selling their labor to make a living, your employer is interested in leveraging your labor to serve a business goal, and not because you are in some way special beyond the output of your labor. A person that digs holes for a living would not be bothered by the phrase “to use them to dig a hole”, because they understand the nature of the exchange being made; they understand that they are being used to accomplish somebody else’s goal in exchange for cash.

                                            Both of these cases are rooted in hatred of the labor class, because both of these cases are rooted in the idea that members of a laboring class are without dignity. If you are a member of a labor class with an awareness of the fact that you are a member of the labor class and you feel solidarity with the laboring class, Go’s goals seem perfectly reasonable. I like Go because I think it helps me perform my role as a laborer creating software as part of a collective effort. As a manager and team lead, I enjoy that it makes onboarding programmers to a new codebase very easy, and that it makes it easy for my developers to write mutually-intelligible code.

                                            If I were rich, I would not write Go for myself for enjoyment unless I was doing so expressly with the goal to turn what I was building into a business, and for the code to be passed on to future wage-earning programmers. Go is not, from my perspective as a person who has been writing Go since 2011, a great tool for writing beautiful, expressive poetry; it is a great tool for building information-processing machines that will actually be used.

                                            Go is designed by a corporation to pursue the goals of that corporation. It says as much on the tin. It is hard to argue that Go is unsuccessful at its own goals of being a programming language with which a large labor class can construct stable software. Go is tremendously successful at fulfilling those goals, and its success causes one to deal with issues of socioeconomic class. If you have never thought about class, this can be disturbing, as it lays naked the reality of classism in society, and one’s place within that system.

                                            1. 8

                                              I don’t like Go because it was designed for the average programmer or a contempt of them, I don’t like it because it’s a paternalistic and reactionary language that assumes the average programmer is too stupid to handle after anything that wasn’t status quo in 1995.

                                              The average programmer might not have a CS degree, but you don’t need a CS degree to have sum types and pattern matching make error handling less error prone, making their lives (and everyone else’s) easier. Go rejects this premise, because worse is better and Bell Labs got it right - dooming us all to deal with the sharp edges we keep getting cut on.

                                              1. 0

                                                “I’m too smart to program with something that dumb people can program with”

                                                1. 8

                                                  It’s not a matter of elitism, it’s a matter of being a dumb person (I’ll admit this - a lot in CS makes my eyes glaze over, I see so many people that are smarter than me), I want smart tools to help me be a more productive programmer, instead of struggling with common mistakes or writing menial boilerplate. I hate that there’s so many new ideas on the horizon, but they remain out of touch in the distance to the average programmer. As an industry, we should be bringing making new ideas and tools more accessible, instead of worshipping what has been already done poorly.

                                                  I’m smart enough to know we could have things so much better, but not smart enough to do it by myself.

                                                  1. 3

                                                    I hate that there’s so many new ideas on the horizon, but they remain out of touch in the distance to the average programmer.

                                                    I dunno, that doesn’t really resonate with me all that much because I don’t feel like anyone is discouraging me from learning those things. You can use Rust or Haskell or Lisp or whatever, all of that stuff is freely available to you. Nobody is creating barriers to using or exploring those things.

                                                    As an industry, we should be bringing making new ideas and tools more accessible, instead of worshipping what has been already done poorly.

                                                    On the one hand, I sorta think that’s what Go does. Structural typing, CSP, and getting rid of exceptions are pretty major changes from the C++/Java/C# model. Go was designed specifically to deprecate C++ and Java at Google. Go is just supposed to be a better Java. It really seems to succeed at that.

                                                    On the other hand, I think you’ve twice conflated “new ideas” with “good ideas”. A lot of new ideas are actually bad ideas. Inheritance was a new idea once. Turns out it’s bad. Go isn’t trying to have a lot of ideas or a lot of new ideas.

                                                    As for sum types specifically (which is both a good idea and an old idea): if you look at the long arc of the language, one of the driving principles is orthogonality. Each part of the language is expected to have as little overlap as possible with the other existing parts of the language. There is a large surface area of overlap between sum types with pattern matching and interface types with type switching. I’m not saying those are the same things; they are not the same things. Add sum types, cool! They’re useful! But you now have two mechanisms for looking at a value and switching on its type that can be checked at compile time. The design philosophy of Go attempts to reduce instances where different aspects of the language have that much overlap. A major thing that pattern matching does is enforce that the match be exhaustive, and the fact that type switches aren’t exhaustive is a huge source of sneaky and annoying bugs. Type switches will never be exhaustive because, for example, the number of possible types implementing interface{} is innumerable. As it turns out, this is a huge bummer both in theory and in practice.

                                                    I’ve been programming Go since r59; before Go 1.0. The discussion about sum types has been around since then. The open proposal to add sum types to the language has many links to past discussions. https://github.com/golang/go/issues/19412

                                                    Practically speaking, there is exactly one place where I really wish I could say (T | error), and that’s when managing unreliable procedures over channels. If you have to fan out an operation to N goroutines, but that operation can fail such that you collect all the errors and all the values on a single channel, you wind up having to create an ad-hoc product type every time you do that for the channel, and that’s really damned annoying.

                                                    1. 5

                                                      It’s sad that this kind of insightful comment is buried under a comment that’s flagged to invisibility…

                                                      1. 2

                                                        it also got flagged lol

                                                2. 1

                                                  This sounds reasonable, and I completely understand this perspective.

                                                  As a counter-point, I rather like this approach as it allows me to focus on what I’m doing and not the language; I’ve rather taken a liking to the “dumb” approach in Go (Stockholm syndrome? Perhaps 🙃)

                                                  I’ve also programmed a lot with Ruby in the past, and even after several years there were still corner cases and surprises in the language. Don’t get me wrong, I still like Ruby (actually, I miss programming in Ruby, it’s a fun language) but that approach does come with some downsides. Perhaps Go will be “obsolete” in 10 or 20 years when newer languages such as Rust, Zig, or some other have matured and stabilized a bit more (although I’m not sure if I will ever truly like Rust, since some design elements don’t particularly jibe with me, but I’d have to program more in it to be sure).

                                              2. 2

                                                Go is a language designed for software engineering in the large. At scale, there are no good or bad programmers, there are only average programmers, by definition. So it’s appropriate for a language to cater to that invariant. If you’re not programming at scale this design decision makes less sense for you and that’s fine, one tool doesn’t need to be all things to all people.

                                                1. 1

                                                  -1 incorrect

                                                  I’m pretty sure I’ve attracted my first Hater! Boggles the mind.

                                                2. 1

                                                  What alternative do you think is worse?

                                                  I think the first one is the correct one, and Pike and the team that created Go knew exactly what kind of language that Google needed - seeing as they worked there, and presumably had talked to a number of stakeholders in the company.

                                                  “FizzBuzz” is a meme for a reason. A lot of people with CS degrees literally cannot program. Presumably Google is big enough and prestigious enough to filter those out, but that doesn’t mean the rest is automatically fluent in Haskell or something.

                                                3. 4

                                                  yes all programming languages exist on a single dimension of performance called “quality”, that’s definitely how the industry works 👍

                                              3. 6

                                                It’s the old “beating down the exception strawman” – that no one is even interested in defending.

                                                It’s not a straw man when a large percentage of competing languages actually do use exceptions. There are very few mainstream languages that use Option/Result types. Actually, I think Swift might be the only one? And maybe Rust, but I’d argue that’s probably not a mainstream language, not yet anyway.

                                                1. 9

                                                  Isn’t it a problem in Go culture that it is content in comparing itself with mainstream languages from an earlier century instead of actively investigating what can be done in contemporary non-mainstream languages?

                                                  This attitude often leads to solving the wrong problem.

                                                  1. 2

                                                    That sounds about right. Go is not designed to break any new ground in computer science or language design, but rather to implement concepts that have been proven to work in various languages and are well understood. I think there is value in this: it gives a stable, reliable, and boring language, which may not be optimal in all respects, but it doesn’t have a lot of “sharp edges” and idiomatic Go code from 10 years ago is quite similar to Go code today. Especially if you want to write an application intended to be maintained for a long period of time (>10 years) then the Go approach can give you some good advantages, I think.

                                                    I think there’s a lot of value in the more experimental approach in e.g. Rust too, by the way. Not all languages need to be the same.

                                                    Either way, I personally wouldn’t call this a “problem”, just a design ethic.

                                                    1. 6

                                                      That sounds about right. Go is not designed to break any new ground in computer science or language design, but rather to implement concepts that have been proven to work in various languages and are well understood.

                                                      Haskell and OCaml have both been around since the 90s, and those are just the two most obvious examples I could come up with of languages that have been used a fair amount in production and which also provide ADTs. So I’m not sure how your assertion makes sense.

                                                      1. 9

                                                        Seconded. The “experimental” part of Rust is the borrow checker, the rest (a bit of type inference, sum types/enums, match) is extremely well known and robust stuff that has been around for > 40 years. Go ignores a lot of well known things, not just new ground.

                                                        1. 1

                                                          And both are also functional programming languages that most people struggle with and see quite little real-world use in the industry.

                                                          1. 2

                                                            Both languages are used extensively in production and have been for a long time, regardless of how their usage compares to C or Java or what-have-you. And ADTs are quite well understood at this point, and Maybe/Option types specifically even moreso; we’re not talking about these languages’ learning curves here. Maybe/Option has been introduced (badly) into Java, for example, and is present in Kotlin, Scala, Rust, etc. So I don’t see how your comment here contradicts my original point.

                                                            1. 2

                                                              We could argue at length on what is and isn’t “well understood” and “widely used”; but it’s not a binary thing, it’s a scale. And it’s also not completely objective either and there is quite some subjectivity involved.

                                                              Go has a very conservative take, which certainly isn’t perfect and you do miss out on some things, but as mentioned I think there is value in this approach too. YMMV.

                                                    2. 0

                                                      I don’t really feel like defending the 90ies poor error handling approach against a language from the 60ies. ¯\_(ツ)_/¯

                                                      The people who care have moved on from such inferior approaches, and those who are still stuck in the last century can’t be helped anyway.

                                                  1. 3

                                                    I’m currently porting/modernizing an old (Palm OS) app of mine (ninerpaint) to modern platforms with Rust, using the sdl2 crate. Any chance that I can hook Egui to that (was rolling my own UI framework but quickly realiized that I am not a masochist)?

                                                    1. 1

                                                      Not the author of the crate, but it says it can display anywhere where it can get events (sdl2) and print triangles (the openGL context in sdl2?). I’d say it’s doable?

                                                      1. 1

                                                        Check out iced, you can definitely hook it to anything, it’s very modular.

                                                      1. 11

                                                        It’s addressed in the article, but for those who don’t know “colorblind” in this context refers to a blog post: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ which discusses how async/await/promises/callbacks all bifuricate the library ecosystem of a language.

                                                        I remember when rust switched from green threads to no runtime, folks basically asked for zig’s behaviour and were told it was infeasible. (See comment here: https://lobste.rs/s/bfsxsl/ocaml_4_03_will_if_all_goes_well_support#c_whrcmk )

                                                        I would be very interested in understanding what constraints of rust don’t apply to zig or what the rust folks got wrong. Is it just that it was a runtime vs compile-time switch?

                                                        1. 7

                                                          It took years for rust developers to find Pin<T> and develop safe promises, along with async/await around them, support for which became stable less than a year ago. I can imagine why it was not obvious that this was possible, back in 2015.

                                                          1. 15

                                                            Rust also has compile-time proven safety, which is an incredible accomplishment, but also limits the design of the language. Meanwhile Zig’s safety is not required to be perfect, and some safety features are runtime checks. So Zig as a language has more design options than Rust does when it comes to getting “creative” with functions and memory layout.

                                                            1. 3

                                                              Definitely agree. Rust is tackling a hard problem and it pushes some (non-accidental) complexity into the language. The reward is less debugging at runtime. Some safety can still be pushed back to runtime, though, e.g. in RefCell.

                                                              I think both Zig and Rust have their place, and both have decent answers to async now; they cater to different aesthetics/sensibilities, is all.

                                                        1. 1

                                                          So what does it offer that “pick one” doesn’t offer?

                                                          In particular, given the ietf Core-WG impetus behind Cbor and Yang, why didn’t you just go with that?

                                                          1. 3

                                                            I explained the CBOR comparison briefly in the article here:

                                                            CBOR: ruled out for similar reasons: too much extensibility, and the schema is encoded into the message. Has the advantage of a specification, but the disadvantage of that spec being 54 pages long.

                                                            It’s too complex, which leads to incomplete and poor quality implementations, and it has too much extensibility, leading to perpetual maintenance and churn. And because it encodes the schema into the message, it ends up with longer messages, and the priority of BARE is small message lengths.

                                                            I explain the rationale for not selecting a handful of alternatives in this article, it should give you enough of an idea of my thought process to explain the rationale for not selecting others as well.

                                                            1. 4

                                                              it encodes the schema into the message.

                                                              Hmm, not quite true, like self-describing maybe, like JSON you can take a blob of CBOR, and convert it to something you can eye ball it, but a schema is a slightly different beast.

                                                              One of the things that I feel is quite compelling about where Core-WG is going, is you can optionally encode a sid into your msg, which will allow you to look up the Yang schema in the appropriate registry. ie. Not only self-describing ala JSON, but self-documenting.

                                                              ps: You xkcd reference is slightly out… you have taken 16 competing standards to 17!

                                                              Ah well, as they say in the classics… “Standards are such a Good thing. Everybody wants their own one!”

                                                              1. 1

                                                                Still - it’s encoding extra data into the message to describe its schema. BARE aims to make the message as small as reasonably possible while still being 8-bit aligned. That, combined with the other reasons I explained, rules out CBOR.

                                                                1. 2

                                                                  My only comment is….

                                                                  When a disease has many treatments….

                                                                  It has no cure.

                                                                  1. 1

                                                                    You could make an IDL for code-generation that relies on CBOR or msgpack as the concrete encoding. A msgpack array of values is probably as compact an encoding for a struct as BARE’s.

                                                                    Msgpack is arguably very simple; even Redis embeds it, and Antirez is not known for making complicated architectural choices. It just lacks a well supported IDL to help (de)serialize.

                                                            1. 10

                                                              You guys are fast :) I published an announcement an hour ago which gives more context and design insights:

                                                              https://drewdevault.com/2020/06/21/BARE-message-encoding.html

                                                              1. 9

                                                                Before you commit to reinventing Capn Proto, including copying the schema language, I want to let you know that the Capn Proto build tools do not mandate using a C++ API, nor using the libkj event loop. The process for writing new plugins is documented, but since you’re using existing languages, you could use capnpy for Python, capnproto2 for Go, or capnp for Rust, none of which use the C++ API. Instead, Capn Proto’s compiler is designed to come apart into subprocesses naturally, with each subprocess using Capn Proto itself to request schema compilation. The bootstrapping phase takes effort, but it is possible and people have already done a lot of the hard work already for many popular languages.

                                                                I also would wonder whether you’re prepared to take on the security burden. Capn Proto’s upstream maintainers set an extremely high bar, and their vulnerability writeups have garnered serious praise for their quality and depth.

                                                                Finally, although it is not mandatory, Capn Proto defines a custom compression algorithm, “packing”, intended specifically to address your concern that fixed-width and aligned data types are wasteful. The authors also recommend LZ4 or zlib for when packing isn’t sufficient.

                                                                In summary, I think that your:

                                                                $ go run git.sr.ht/~sircmpwn/go-bare/cmd/gen -p models schema.bare models/gen.go
                                                                

                                                                Could be:

                                                                $ capnp compile -I$GOPATH/src/zombiezen.com/go/capnproto2/std -ogo schema.capnp > models/gen.go
                                                                

                                                                With the package information included in the Capn Proto schema file.

                                                                1. 6

                                                                  Like I said in the article, I did evaluate Cap’n Proto, and concluded it was not the right fit.

                                                                  Before you commit to reinventing Capn Proto, including copying the schema language

                                                                  The schema language is not copied from Cap’n Proto, and frankly I don’t understand how you would make this assumption. The two schema languages are very different. Unless you mean the idea of having a schema language at all, in which case you are clearly ignorant of the alternatives and their history.

                                                                  I want to let you know that the Capn Proto build tools do not mandate using a C++ API

                                                                  C++ is, in fact, required:

                                                                  $ capnp compile -I$GOPATH/src/zombiezen.com/go/capnproto2/std -ogo schema.capnp > models/gen.go here -^

                                                                  I don’t evaluate technology in a vacuum. The total complexity of the implementation, including code I didn’t have to write myself, is part of my evaluation. There is no attempt at a specification or any motions to support third-party implementations from Cap’n Proto.

                                                                  The bootstrapping phase takes effort

                                                                  It seems that the typical amount of effort required to make a complete BARE implementation is 3-5 days. I also looked at the C++ frontend for Cap’n Proto: 3,153 lines of support code for C++. The entire Go implemenation of BARE is 3,629 lines of code, including marshaling & unmarshaling, parsing, code generation, exhaustive tests, example code, and generated code, and it has no external dependencies (well, getopt for the generator CLI, and a assertion framework for the tests).

                                                                  I also would wonder whether you’re prepared to take on the security burden. Capn Proto’s upstream maintainers set an extremely high bar, and their vulnerability writeups have garnered serious praise for their quality and depth.

                                                                  I find it ironic that the security vulnerability you use as an example is the result of C++ programmers doing C++ programmer things, namely over-use of templates (any use of templates being an over-use), and works in favor of my argument that Cap’n Proto’s programming culture is symptomatic of the broken culture that values tools like C++. An ounce of prevention is worth a pound of cure, and in BARE’s case both the spec and implementation are 10x simpler - and simpler always means more secure.

                                                                  Finally, although it is not mandatory, Capn Proto defines a custom compression algorithm

                                                                  This also argues against you. The message encoding should have nothing to do with compression, this just increases the complexity of both the specification and implementation (by the way, I keep refering to “the specification”, but in reality such a thing doesn’t exist - this fact also works against Cap’n Proto’s favor). The specification cannot be “complete”, either - the compression techniques will become obsolete over time, and the specification will have to be revised to accomodate.

                                                                  In general, BARE messages tend to have the same entropy as the underlying information they represent, because the BARE encoding is barely more than the literal data directly copied to the message. Unlike Cap’n Proto, which has alignment and fixed message size wasting space (this is done in exchange for performance, unless you’re decompressing the messages, in which case the performance improvement is totally lost), BARE messages stand to save very little from encoding-aware compression. For this and other reasons besides, compression is out of scope for BARE. Instead, you should feed BARE messages to your favorite compression algorithm yourself, such as zstd, and you will get results comparible to compressing the underlying information.

                                                                  Not having compression in-scope simplifies the implementation and specification. Reckless lack of consideration for scope is a major problem which ruled out many of the alternatives I explored before working on BARE.

                                                                  1. 2

                                                                    Your evaluation can be quoted in full, as it is barely a paragraph, with only half of its fragments qualifying as sentences:

                                                                    Cap’n Proto: fixed width, alignment, and so on — good for performance, bad for message size. Too complex. RPC support is also undesirable for this use-case. I also passionately hate C++ and I cannot in good faith consider something which makes it their primary target.

                                                                    BARE is not simpler; feel free to define a metric before revisiting that point. RPC support is optional. We’ve covered everything else.

                                                                    Some of your statements are either wrong or questionable:

                                                                    The two schema languages are very different.

                                                                    Really? All of these declarative schema languages look very similar to me. Which one were you trying to reinvent?

                                                                    There is no attempt at a specification or any motions to support third-party implementations from Cap’n Proto.

                                                                    Baldly contradicted, and I will continue to link to evidence as needed.

                                                                    in BARE’s case both the spec and implementation are 10x simpler

                                                                    This needs a metric.

                                                                    I, too, passionately hate C++. And yet, somehow, nobody really cares about my feelings. Capn Proto does not make C++ the primary target, nor does it mandate the C++ API. You are pointing at a subprocess invoked via shell, which is a common linguafranca across many different languages. There is no C++ linkage, no C++ name mangling, and no C++ templates. The reference implementation makes only one request, and it is a polite one: For interoperability, use the same struct offsets every time, and preferably use exactly the same algorithm as the original.

                                                                    Capn Proto has a complete encoding specification. Only the struct offsets are computed, but they are not necessary for deserializing a message, only for interpreting it according to certain names and schemata. Indeed, when I bootstrapped Capn Proto support for Monte, I started by writing a deserializer for unnamed buffers and messages, and only later added in support for schemata.

                                                                    On a more personal note, attacks and rudeness like:

                                                                    frankly I don’t understand how you would make this assumption

                                                                    in which case you are clearly ignorant of the alternatives and their history

                                                                    Are how you maintain your reputation for toxicity. I don’t believe in moderating people unkind, but I do think that you could stand to look at your words and how you escalated this conversation.

                                                                    1. 8

                                                                      Your evaluation can be quoted in full, as it is barely a paragraph, with only half of its fragments qualifying as sentences

                                                                      Yes, because it’s sharing a list of bullet points with 4 other alternatives in an article whose purpose isn’t to provide a detailed critique of Cap’n Proto.

                                                                      BARE is not simpler; feel free to define a metric before revisiting that point. RPC support is optional.

                                                                      Everything is optional, I could just choose not to use a subset of either system’s primitives and call it “less complicated”. Your argument doesn’t make any sense. A complete, conformant implementation of BARE is simpler than one of Cap’n Proto. Here’s one metric: the encoding spec you linked to is 3,908 words. The BARE spec is 1,430, and the BARE spec also includes a grammar for the schema DSL.

                                                                      Really? All of these declarative schema languages look very similar to me. Which one were you trying to reinvent?

                                                                      Give me a break. What they have in common appears to be the enum keyword, convention of PascalCase for user-defined types, the use of “:” to separate field names from types, and the use of braces “{ }” for structs. There are dozens of other languages that we share all of these traits with. In every other respect they are quite different:

                                                                      • BARE allows you to make any kind of user-defined type, not just structs
                                                                      • Cap’n Proto has explicit field offsets, BARE lacks them
                                                                      • Cap’n Proto has semicolons, BARE lacks them
                                                                      • Cap’n Proto has semicolons, BARE lacks them
                                                                      • BARE has a different syntax for arrays (lists in cap’n terms)
                                                                      • BARE has fixed arrays, maps, and first-class tagged union types, and syntax for each
                                                                      • Cap’n Proto has default values, and BARE’s DSL can’t describe values at all
                                                                      • Cap’n Proto has the concept of groups, which BARE lacks
                                                                      • BARE has no RPC and therefore no syntax for it

                                                                      I find your acusation of copying the schema completely unfounded and extremely rude.

                                                                      There is no attempt at a specification or any motions to support third-party implementations from Cap’n Proto.

                                                                      Baldly contradicted, and I will continue to link to evidence as needed.

                                                                      I will correct myself: there is a specification of the encoding. There is no specification of the DSL. There is documentation, but documentation is not a specification.

                                                                      They support third-party integrations, not implementations. This is an important difference.

                                                                      in BARE’s case both the spec and implementation are 10x simpler

                                                                      This needs a metric.

                                                                      See my first comment for the implementation size and this comment for the spec size.

                                                                      You are pointing at a subprocess invoked via shell

                                                                      A subprocess written in C++. This puts C++ in your dependency tree. Just because you don’t link to it with the C++ ABI doesn’t mean it’s not a dependency. There are multiple ways to skin^Wdepend on a cat.

                                                                      On a more personal note, attacks and rudeness like:

                                                                      frankly I don’t understand how you would make this assumption

                                                                      in which case you are clearly ignorant of the alternatives and their history

                                                                      Are how you maintain your reputation for toxicity. I don’t believe in moderating people unkind, but I do think that you could stand to look at your words and how you escalated this conversation.

                                                                      The use of the word “frankly” and using ignorance to explain unfounded arguments is not rude. Telling me that I am maintaining a reputation for toxicity, however, is extremely rude. You are disparaging my work and my character with baseless arguments and false comparisons.

                                                                      We get it, I don’t like your sacred cow. It is entirely possible for me to have evaluated it and determined it did not meet my needs, and also valid for me to determine that I simply don’t like it, and also valid to conclude that the idea is poorly realized by its implementation. In this case I came to all of these conclusions. The fact of the matter is that your protocol is not perfectly suited to all use-cases and neither is your implementation, and you aren’t entitled to praise for it.

                                                                      1. 3

                                                                        You’re kind of being rude here. Also, if you know that the metric hasn’t been defined then how did you decide that BARE is not more simple?

                                                                        1. 7

                                                                          They both are, in my opinion. I’d really prefer not see conversations in this tone on lobste.rs (speaking for myself only, of course).

                                                                          1. 4

                                                                            Dunno. I think @ddevault is just defending their post… Doesn’t seem particularly rude to me

                                                                          2. 2

                                                                            I’m trying. I am not a nice person and it’s been nearly a decade of trying to have conversations with the author. But sure, I do not mind receiving the unkind vote. This isn’t the first time that a basic technical discussion has been horribly derailed by their attitude, and not the first time that I’ve been told that I’m part of the problem because I refuse to go along with their framing.

                                                                            I did not claim that Capn Proto is simpler than BARE. I instead rejected the idea that there is a natural and obvious metric by which to claim that one is simpler than the other. This is a frustrating ambiguity in English; the word “not” can mean three different things and there is no way to disambiguate other than to write an explanatory paragraph.

                                                                            No suitable metric is given. One metric, lines of code, is used; however, lines of code between two different host and target languages are apples-to-oranges. To make it apples-to-apples, the comparison would have to be either between BARE and Capn Proto complete stacks in a single language (presumably C++), or between two Capn Proto implementations in two different languages. Either way, the appropriate comparison hasn’t been drawn.

                                                                      2. 1

                                                                        I think the appeal of BARE is that it has a low threshold of entry (like json, msgpack, etc.) for anyone willing to write a code-generator for it. On the one hand, capnproto’s schema language seems cleaner and more expressive; the problem is that the whole encoding format, albeit efficient, is very complex in the name of allowing zero-copy access. There should be room for a language like BARE, more or less in the same niche protobuf occupies currently (fast and binary but not insanely complicated).

                                                                        Sadly it looks like BARE will not get sum types/general tagged unions, and cannot represent them (except for option). I got fed up in this thread and failed to keep as civil a tone as I wished I had, but anti-intellectualism irritates me.

                                                                        1. -4

                                                                          BARE has sum types aka tagged unions. What it does not have is zero-bit types, which often change the way you use tagged unions. After an hour of back and forth it became apparent that c-cube lacks the “intellectual” capacity to understand this difference.

                                                                          1. 6

                                                                            And, this is the main reason I actively avoid working on any of the projects he’s involved in. “Feedback is welcome”, the page says, apparently until it gets annoying or the author has to deal with someone stubborn who has a different way of looking at the world, at which point you get called a moron in public.

                                                                            1. 4

                                                                              The back and forth made me sad and annoyed too. I think the terminology is confusing and ambiguous, because we have different ideas on what “sum types” precisely entails and could not find the words to carry the difference over short messages.

                                                                              The “anti-intellectualism” was also not civil, but so are the straight insults towards functional programming and people who like it.

                                                                              1. 0

                                                                                Your “different” idea on what “sum types” precisely entails is not just different, but factually incorrect. You approached the discussion with a flawed understanding of the type system you espouse and made incorrect assumptions about the limitations of BARE’s type system. This is the main source of frustration. I appreciate that you were willing to evaluate the specification and share your feedback, but you do not fully understand the problem that you are trying to communicate about.

                                                                                Regardless, after more thought to the potential use-cases and the best implementation approach, I have added a void type to the specification, which should enable the types you want to construct with BARE messages.

                                                                        2. 3

                                                                          The choice on schema upgrade is interesting (or strange). That means when upgrading to MessageV2, you need to write a manual translation between MessageV1 and MessageV2?

                                                                          What about incremental updates (schema evolution, i.e. adding and remove fields in a struct)? Protobuf and Flatbuffers both provides an evoution path for these while it seems BARE and Cap’n’Proto elected (not exactly sure about BARE story other than your compatibility section, but definitely Cap’n’Proto) to not support this.

                                                                          1. 1

                                                                            What about incremental updates (schema evolution, i.e. adding and remove fields in a struct)?

                                                                            The length is not encoded into a BARE message, so there’s no way to determine when one message stops and the next begins without knowing the schema of the message in advance. If you append fields, you won’t be able to tell that they’re not part of the next message.

                                                                            But, nothing is stopping you from adding your own length to messages, either through context (Content-Length) or explicitly adding a length prefix before reading out the struct (the Go implementation provides tools you can use to read primitives yourself for things like this, and I would hope that other languages would do so). So if you prefer that approach, then by all means. Another alternate approach could express a version out of band, like X-Message-Version.

                                                                            The tagged union versioning approach works in all contexts in which BARE messages work, so it’s recommended as a universal solution. But if you prefer a different option, you’re welcome to establish the necessary context to support it out-of-band and go with that.

                                                                            1. 1

                                                                              Thanks. Yeah, read the doc a bit more and realized that the struct just a concatenation of underlying fields. Unlike Protobuf or Flatbuffers, it doesn’t carry any offsets, therefore, adding / removing fields requires either having a brand-new type in the union types, or some other means (depending on the language) to carry the old schema somewhere (out-of-band).

                                                                              It is interesting to observe how these are solved. I am more comfortable with the built-in approach by Protobuf / Flatbuffers but I think different solutions fit different usage cases and having additional redirection may be undesirable for many cases.

                                                                        1. 4

                                                                          So, to close the loop, should we expect a RPC system (wire format + interface declaration format) on top of that BARE encoding? :^)

                                                                          1. 2

                                                                            Previous discussions of gemini highlight a different approach to the web bloat problem: instead of trying to define a subset of html no one will agree on, just define a new, simple protocol that is limited in scope on purpose. The faq even has a section on why it’s not a subset of html.

                                                                            1. 0

                                                                              As someone who is in V’s Discord every day being constantly blown away at the progress being made, I am shocked at the level of dishonesty that this strangely anti-V hit piece achieves.

                                                                              In particular, the degree of cherry-picking (and often then still misrepresenting) a few facts in order to make V appear in the worst possible light is truly breathtaking.

                                                                              She cites vlang.io saying

                                                                              V can be bootstrapped in under a second by compiling its code translated to C with a simple

                                                                              cc v.c

                                                                              No libraries or dependencies needed.

                                                                              then argues against it, preposterously, by saying in part,

                                                                              Git is a dependency, which means perl is a dependency, which means a shell is a dependency, which means glibc is a dependency, which means that a lot of other things (including posix threads) are also dependencies. …

                                                                              Downloading a .c source file requires git? Does this person know what a “dependency” is? Should JavaScript developers include depending upon the laws of physics in package.json?

                                                                              Amusingly, the documentation still claims that memory management is both a work in progress and has perfect accuracy for cleaning up things at compile time.

                                                                              No, the documentation correctly says that memory management is a work in progress, and also that, once completed, will clean up after itself in much the way that Rust does.

                                                                              An Honest Depiction of Progress

                                                                              Here are the combined release notes from all of the V releases since December:

                                                                              Release 0.1.23:

                                                                              - [Direct x64 machine code generation](https://github.com/vlang/v/issues/2849). Hello world being built in 3 milliseconds.
                                                                              - Bare metal support via the `-freestanding` flag, allowing to build programs without linking to libc.
                                                                              - Prebuilt V packages for Linux, macOS, and Windows.
                                                                              - `string.index()` now returns `?int` instead of `int/-1`.
                                                                              - Lots of fixes in Generics.
                                                                              - vweb framework for developing web applications is back.
                                                                              - Vorum, the forum/blogging software written in V/vweb, can now be compiled and has been added to CI.
                                                                              - REPL, `v up` have been split up into separate applications to keep the core V compiler small.
                                                                              - V now enforces short enum syntax (`.green` instead of `Color.green`) when it's enough.
                                                                              - V UI for macOS.
                                                                              - Interfaces have been rewritten. `[]interface` support.
                                                                              - `os.cp()` for copying files and directores.
                                                                              - Additional compile-time flags: `$if clang, msvc, mingw, x32, x64, big_endian, little_endian {`.
                                                                              - All C functions now have to be declared, all missing C functions have been defined.
                                                                              - Global variables (only with the `--enable-globals` flag) for low level applications like kernels and drivers.
                                                                              - Nothing can be cast to bool (previously code like `if bool(1) {` worked.
                                                                              - `<<` and `>>` now work with all integer types.
                                                                              - V detects Cygwin and shows an error. (V supports Windows natively)
                                                                              - Improved type checking of some operators (`%, |, &` etc).
                                                                              - Windows 7 support.
                                                                              - `println(true)` now prints `true` instead of `1`.
                                                                              - `os.exec()` now uses `CreateProcess` on Windows.
                                                                              - fast.vlang.io website for monitoring the performance of V after every commit.
                                                                              - On Windows Visual Studio is now used automatically if GCC is not installed.
                                                                              - vfmt!
                                                                              - Lots of cleaning up in the compiler code.
                                                                              - Multi-level pointers in unsafe code (`****int`).
                                                                              - MSVC backtrace.
                                                                              - `$if os {` blocks are now skipped on a different OS.
                                                                              - C string literals (`c'hello'`).
                                                                              - AlpineLinux/musl fixes + added to CI.
                                                                              - Inline assembly.
                                                                              - Clipboard module (Windows, macOS, X).
                                                                              - `foo()?` syntax for error propagation.
                                                                              - Docs have been migrated from HTML to `doc/docs.md`.
                                                                              - `eventbus` module.
                                                                              - Haiku OS support.
                                                                              - `malloc/free` on bare metal.
                                                                              - `utf8` helper functions (`to_lower()`, `to_upper()`, etc).
                                                                              - Optimization of `for c in str {`.
                                                                              - `string/array.left/right/slice/substr` were removed (`[a..b]` slicing syntax should be used instead).
                                                                              

                                                                              Release 0.1.24:

                                                                              - A new parser/generator built on top of an AST that simplifies code greatly and allows to implement new
                                                                                backends much faster.
                                                                              - Sum types (`type Expr = IfExpr | MatchExpr | IntegerLiteral`).
                                                                              - B-tree map (sped up the V compiler by ~10%).
                                                                              - `v fmt -w`.
                                                                              - The entire code base has been formatted with vfmt.
                                                                              - Generic structs.
                                                                              - SDL module.
                                                                              - Arrays of pointers.
                                                                              - os: `is_link()`, `is_dir()`, `exists()`.
                                                                              - Ranging through fixed size arrays.
                                                                              - Lots of fixes in ORM and vweb.
                                                                              - The first tutorial: [building a simple web application with vweb](https://github.com/vlang/v/blob/master/tutorials/building-a-simple-web-blog-with-vweb.md).
                                                                              - Match expressions now must be exhaustive.
                                                                              - freestanding: `malloc()`/`free()`.
                                                                              - `++` is now required instead of `+= 1` for consistency.
                                                                              - Interpolated strings now allow function calls: `println('val = $get_val()')`.
                                                                              - `string.replace_each([])` for an efficient replacement of multiple values.
                                                                              - More utf8 helper functions.
                                                                              - `-prealloc` option for block allocations.
                                                                              - `type` aliases.
                                                                              - Running `v` with an unknown command will result in an error.
                                                                              - `atof` implementation in pure V.
                                                                              - Enums can now have negative values.
                                                                              - New `filepath` module.
                                                                              - `math.factorial`.
                                                                              - `ftp` module.
                                                                              - New syntax for casting: `val as Type`.
                                                                              - Fewer libc functions used (soon V will have no dependency on libc).
                                                                              

                                                                              Release 0.1.27:

                                                                              - `vfmt` has been re-written from scratch using the new AST parser. It's much faster, cleaner, and can format
                                                                              files with compilation errors.
                                                                              - `strconv`, `sprintf`, and `printf` in native V, without any libc calls.
                                                                              - Interfaces are now a lot more stable and have all expected features.
                                                                              - Lots of x64 backend improvements: function calls, if expressions, for loops, local variables.
                                                                              - `map()` and `filter()` methods can now be chained.
                                                                              - New `[]int{cap:cap, len:len}` syntax for initializing array length and capacity.
                                                                              - New `is` keyword for checking the type of sum types and interfaces.
                                                                              - `as` can now be used to cast interfaces and sum types.
                                                                              - Profiling with `-profile`. Prints a nice table with detailed information about every single function call:
                                                                              number of calls, average time per call, total time per function.
                                                                              - `import(xxx)` syntax has been removed in favor of `import xxx` for simplicity and greppability.
                                                                              - Lots of fixes and improvements in the type checker.
                                                                              - `time.StopWatch`
                                                                              - `dl` module for dynamic loading.
                                                                              - Automatic `str()` method generation for every single type, including all arrays and fixed size arrays.
                                                                              - Short struct initialization syntax for imitating named function args: `foo(bar:0, baz:1)`.
                                                                              - New operator `!in`.
                                                                              - Performance improvements in critical parts of the builtin data structures (array, map).
                                                                              - High order functions improvements (functions can now be returned etc).
                                                                              - Anonymous functions that can be defined inside other functions.
                                                                              - Built-in JSON module is back.
                                                                              - Closures.
                                                                              - Lots and lots of new tests added, including output tests that test error messages.
                                                                              - Multiple errors are now printed, the compiler no longer stops after the first error.
                                                                              - The new JS backend using the AST parser (almost complete).
                                                                              - Variadic functions.
                                                                              - `net.websocket` module (early stage).
                                                                              - `vlib` is now memory leak free, lots of `autofree` improvements.
                                                                              - Simplified and cleaned up `cmd/v`, `v.builder`.
                                                                              - V UI was updated to work with the new backend.
                                                                              

                                                                              After she COMPLETELY ignores the MASSIVE progress mademore than 3000 commits worth from a brilliant and fiercely dedicated team – and judges the current state of V based exclusively on misunderstandings, nitpicks, and on its memory management status after acknowledging that it’s not done yet and that the language is in an alpha state, she snarkily ends with:

                                                                              Overall, V looks like it is making about as much progress as I had figured it would.

                                                                              This is almost as bad as the quote she ended with in her previous post on V:

                                                                              Don’t ever, ever try to lie to the Internet, because they will catch you. …


                                                                              Honesty, Please!

                                                                              If you want to know how well V is actually progressing, try it yourself, check out the Discord, look on GitHub, but whatever you do, do not focus on ignorant, dishonest, cherry-picked commentary from haters; that doesn’t serve anyone well, and is incredibly unfair to those who are pouring themselves into this important project.


                                                                              The Brilliance of V

                                                                              After my 11 years of programming, including 9.5 of programming in Go (which is the most similar language to V), I consider V to easily be the best-designed programming language that exists.

                                                                              Yes, it’s learned a lot from Go and C, and maybe Lisp people prefer Lisp, but V successfully combines the simplicity of Go, the programmer ergonomics of Python, the speed C, and almost as many safety guarantees as Rust (once V has finished implementing these latter aspects, of course!).

                                                                              What I thought would take the V team 5 years to implement has taken less than 1 year. Alex (V’s creator) thought it would take even less time, and now he’s being unfairly raked over the coals for setting extremely ambitious timelines while the same naysayers and bullies ignore everything that has been done.


                                                                              V Resources

                                                                              Website (including code examples): https://vlang.io/

                                                                              GitHub: https://github.com/vlang/v

                                                                              Wiki page explaining why C is used as in intermediate representation rather than LLVM (another brilliant move that allows V to build on the shoulders of giants and avoid reinventing the wheel in order to bootstrap a new language, but a move that is misunderstood and absurdly used to argue against V for doing things differently/better): https://github.com/vlang/v/wiki/On-the-benefits-of-using-C-as-a-language-backend

                                                                              1. 25

                                                                                I understand that you have strong feelings for your language of choice. Nonetheless, language designers are not entitled to a community, nor are they entitled to shelter from criticism. Indeed, one of the most important parts of programming language design is rejecting new languages based on showstoppingly-unacceptable design choices.

                                                                                V does not offer any compelling design choices. Its advertised features can be sorted into libraries, compiler/toolchain offerings, and roughly the level of safety advertised in the 80s when memory-safety was still controversial. Just like Go, V has not learned many lessons, and refuses to offer programmers a more interesting way to express themselves. Even if V were literally Go but better, this would be sufficient to damn it.

                                                                                I understand that you might not like it when people point out that the release dates keep slipping; I think it’s curious that you are willing to link to V’s wiki and source code, but not to bumping release dates.

                                                                                As a language designer, I think that it is important to not advertise what you don’t yet have written. Monte has had one release, a developer preview, and we are intending to complete another iteration of bootstrapping before even considering another release. We know that almost every feature that typical end users will want is not yet written, and so we are not loudly advertising our offering as usable for everyday general-purpose programming, regardless of how much everyday general-purpose programming I or anybody else actually achieves with it.

                                                                                I consider V to easily be the best-designed programming language that exists.

                                                                                What’s your favorite ML? I have lately played with OCaml. There are entire universes of language designs which I suspect that you have yet to explore.

                                                                                1. -4

                                                                                  Just like Go, V has not learned many lessons, and refuses to offer programmers a more interesting way to express themselves.

                                                                                  FP diehards will never understand why Go has been so wildly successful – and V will be even more successful than Go.

                                                                                  V is like Go but fixes all ~10 things wrong with it, providing a lot more flexibility due to its generic functions, generic structs, generic channels (still in the works), sum types, and TypeScript-style interfaces (also still partially in the works).

                                                                                  Plus there’s the raw speed factor; V is translated to C before being compiled to machine code, cleverly piggybacking on decades of speed optimizations made by gcc/clang/tcc/etc.

                                                                                  The simplicity of Go or Python + almost as much safety as Rust + almost exactly as much speed as C + a flexible type system + familiar syntax == a winning combination, I insist!

                                                                                  1. 16

                                                                                    The simplicity of Go or Python + almost as much safety as Rust + almost exactly as much speed as C + a flexible type system + familiar syntax == a winning combination, I insist!

                                                                                    Except all of these are “some time in the future”, and widely incompatible with one another. There’s nothing to support any of these claims. What’s the design for “almost as much safety as rust” (without GC, of course)? The whole thing only just got an AST, and we’re supposed to believe it’s going to be revolutionary? There’s been a lot of grand promises with release dates being pushed back repeatedly, but nothing specific about how the promises will actually be achieved. Making a good language is hard, it takes years (if not decades), and you can’t just magically make something both simple, fast, safe, gc-free, etc. in a field where it’s known that some tradeoffs are inevitable.

                                                                                    1. -3

                                                                                      Except all of these are “some time in the future”, and widely incompatible with one another.

                                                                                      Nope, totally wrong. The simplicity is there, the speed is there, the flexible type system is there, and the familiar syntax is there. A safe subset of C is generated then compiled but not all the safety guarantees are implemented yet.

                                                                                      There’s been a lot of grand promises with release dates being pushed back repeatedly

                                                                                      V is the first software project in history to be finished later than originally intended ;-).

                                                                                      The whole thing only just got an AST

                                                                                      Completely false; V has always had an AST. The AST-related thing that’s new is representing the generated C code as an AST before outputting it.

                                                                                      … you can’t just magically make something both simple, fast, safe, gc-free, etc. in a field where it’s known that some tradeoffs are inevitable.

                                                                                      The big “a-ha” moment for me was this: I now realize that I had falsely assumed that just because prior languages took certain trade-offs that it was impossible to check all these boxes at once. But I was wrong.

                                                                                      The only inherent tension between any of the things I listed is between simplicity and flexibility. But as I said in the comment you’re replying to,

                                                                                      V is like Go but fixes all ~10 things wrong with it, providing a lot more flexibility due to its generic functions, generic structs, generic channels (still in the works), sum types, and TypeScript-style interfaces (also still partially in the works).

                                                                                      The limiting factor is not some innate impossibility of making a language that is simple, fast, and safe. The limiting factor is creativity. But V has learned much from Go, Rust, Python, and other languages, and has unique insights of its own (like its error handling!).

                                                                                      New things are, in fact, possible… and spelled out in detail on the website and in the docs, in this case. See for yourself: https://github.com/vlang/v/blob/master/doc/docs.md .

                                                                                      1. 9

                                                                                        the flexible type system is there

                                                                                        hydraz below convincingly demonstrated that if function calls have generic types, type is not checked at all(!) in current V. How can you say type system is “there”? I guess it is “there” in terms of code generation, but if you are not checking types, saying type system is there is at best deceptive.

                                                                                        1. -4

                                                                                          How can you say type system is “there”?

                                                                                          …because there are types you can define and instantiate and do all the usual things that programming languages let you do with types…

                                                                                          hydraz said,

                                                                                          type errors for parameters in functions with a slapped on them are still silently ignored…

                                                                                          Silently ignored? If you use a generic type in a way that’s invalid then the program won’t compile (yes, during the C -> machine code step).

                                                                                          1. 9

                                                                                            I think you need to read my comments - and indeed, the compiler code that I linked - again. V has roughly no type system at all. The function, foo, that I wrote, isn’t generic!

                                                                                            • It does have a <T>, but there’s nothing to infer that T from (This should be a type error. It isn’t)
                                                                                            • It takes a string, but I can give it an int, and this should be an error, but the compiler has code specifically for silently ignoring these errors.
                                                                                        2. 8

                                                                                          spelled out in detail

                                                                                          Let’s see memory management: there’s no explanation, just claims there are (or will be, it’s wip after all) no leaks, no gc, not refcounting, but also no manual memory management (it’s hardly leak free, after all, even in rust). What magic justifies that? Is there just no dynamic allocation? Otherwise I’d like to see the papers and subsequent Turing award for solving memory management once and for all.

                                                                                          As for the deadlines: the author of V has made ridiculous deadlines so many times, for no good reason (why promise something in a few weeks or months instead of just waiting for it to be polished?!). It’s not like open source projects are tied to pointy haired boss deadlines.

                                                                                      2. 13

                                                                                        Interestingly, I’m not an “FP diehard”; I come from an object-based tribe, and I work on object-based designs.

                                                                                        None of the listed improvements to V over Go are related to what makes Go bad; I have a thread from last year exploring the worst of Go’s flaws. In short, the problem isn’t even an upper limit on abilities, but a lower limit on how much code is required to do even the bare minimum, and a surprising lack of safety in common situations.

                                                                                        As the original post author and several others have repeatedly indicated throughout current and past discussion about V, the speed claims simply aren’t being substantiated in an open and reproducible configuration which the community can examine and test themselves. Simply changing the host language does not grant speed, unfortunately, because of interpretative overhead, and the only cure is putting effort into the compiler.

                                                                                        At the same time, it is toolchains and not languages that are fast, and so any novel speed improvements in V should be explicable to the rest of us. For example, in Monte, we use nanopass design and ANF style, originally explored in Scheme. We have a JIT in the Smalltalk/Java tradition, using an off-the-shelf toolkit, RPython.

                                                                                        As an aside, I would imagine that V would be able to more efficiently take advantage of GCC/LLVM/etc. by picking just one backend, and emitting code just for that backend. This would be due to C’s relatively poor guarantees about how memory will be used.

                                                                                        1. 5

                                                                                          V is translated to C before being compiled to machine code

                                                                                          That, right there, is enough for me to question any safety guarantee V offers (and I like C).

                                                                                          1. 4

                                                                                            Nim compiles to C and it’s garbage collected. I believe the reasons they do that are runtime reach and whole program optimization.

                                                                                            If you can statically guarantee safety it shouldn’t be a problem. (However, its not necessarily a trivial thing to suggest.)

                                                                                            1. 3

                                                                                              ATS compiles to C too, if I understand it correctly. And there have been Haskell compilers that compiled to C too and many other programming languages that provide some aspects of safety that the underlying C language, like the machine code, do not provide.

                                                                                              1. 4

                                                                                                Why does using C as an intermediate language in the compilation process necessarily imply that a language’s safety guarantees are bad? Compilers that compile to some kind of bytecode - like rustc compiling to LLVM bitcode, or JVM langauges’ compilers compiling to JVM bytecode - are perfectly capable of being safe, even though they output code in an unsafe language (which may or may not be the final compilation output - it is (I think) in the JVM case, but LLVM bitcode is further transformed into machine-specific machine code). I don’t see why C should be any different in this respect.

                                                                                                1. 3

                                                                                                  I don’t know the guarantees of LLVM or JVM, but at the language level, C has a ton of unspecified and undefined behaviors. Skipping the dangers around pointers and arrays, you still have the following undefined behavior as outlined in the C standard:

                                                                                                  • shifting an integer by a negative value
                                                                                                  • shifting an integer more than its size in bits
                                                                                                  • left shifting a negative value
                                                                                                  • signed integer representation (sign-magnitude, 1s complement, 2s complement [1])
                                                                                                  • (quoting from the C99 standard for this one): Whether certain operators can generate negative zeros and whether a negative zero becomes a normal zero when stored in an object
                                                                                                  • signed integer trap representations
                                                                                                  • signed integer wrap sematics
                                                                                                  • padding value
                                                                                                  • padding in general
                                                                                                  • reading a union member that wasn’t the last one written to

                                                                                                  Now, it seems that V is targeting GCC/clang, but even so, you’ll get differences in behavior across different architectures, specifically with shifting (some architectures will mask the shift count, some won’t). When I see “safety” as applied to a computer language, I would expect these issues will be spelled out as to what to expect.

                                                                                                  [1] In my research, there aren’t many systems in use today that are not 2s complement. They are:

                                                                                                  • Unisys 1100/2200
                                                                                                  • Unisys ClearPath A
                                                                                                  • IBM 700/7000 series

                                                                                                  I know one of the Unisys systems is still be produced today and has a C compiler (which one, I don’t recall, I think the 1100/2200).

                                                                                                  1. 2

                                                                                                    you do realize that source code gets compiled to machine code, which is not safe by definition.

                                                                                                    The generated C code doesn’t use any of these, and doesn’t have to.

                                                                                                    1. 3

                                                                                                      Then what’s your definition of “safe” then? There is way less that’s undefined in assembly than in C. Give me an architecture, and I can look up what it does for the above list. The reason C has so much undefined behavior is precisely because it runs on many architectures and the designers of C didn’t want to favor one over the other. Different languages can make different trade offs .

                                                                                              2. 5

                                                                                                FP diehards will never understand why Go has been so wildly successful – and V will be even more successful than Go.

                                                                                                Do you? Go succeeded because it was created and backed by veteran Bell Labs people and Google, to solve existing problems. I’m not talking about marketing only, but also the level of sophistication and simplicity those people were able to bring in.

                                                                                                It also succeeded because it didn’t promise anything it didn’t deliver.

                                                                                                1. -4

                                                                                                  Yes. I spotted Go as great technology in November of 2010. Go is simple and fairly powerful considering that simplicity.

                                                                                                  The original version of V was written in Go, V has learned many lessons from Go, both from its strengths that V builds on and the weaknesses it shores up with generic functions, generic structs, sum types, and more.

                                                                                            2. 14

                                                                                              I’d be interested in seeing what kind of these “lots of fixes in Generics are”, because as far as I can tell from reading the compiler source code, type errors for parameters in functions with a <T> slapped on them are still silently ignored…

                                                                                                if !c.check_types(typ, arg.typ) {
                                                                                                  // str method, allow type with str method if fn arg is string
                                                                                                  if arg_typ_sym.kind == .string && typ_sym.has_method('str') {
                                                                                                    // note: str method can return anything. will just explode in the C compiler -- hydraz
                                                                                                    continue
                                                                                                  }
                                                                                                  if typ_sym.kind == .void && arg_typ_sym.kind == .string {
                                                                                                    continue
                                                                                                  }
                                                                                                  if f.is_generic {
                                                                                                    // ignore errors in functions with a <T> -- hydraz
                                                                                                    continue
                                                                                                  }
                                                                                                  if typ_sym.kind == .array_fixed {
                                                                                                  }
                                                                                              

                                                                                              Try this code:

                                                                                              fn  foo<T>(y string) int {
                                                                                                return 0
                                                                                              }
                                                                                              
                                                                                              fn main() {
                                                                                                foo(123)
                                                                                              }
                                                                                              
                                                                                              1. -4

                                                                                                You had foo take a string then passed in an int :-)

                                                                                                EDIT: This works, for example:

                                                                                                fn foo<T>(y string) int {
                                                                                                  return 0
                                                                                                }
                                                                                                
                                                                                                fn main() {
                                                                                                  println(foo<int>('hi'))
                                                                                                }
                                                                                                
                                                                                                1. 22

                                                                                                  … Yes, that’s my point. I passed an int to a string parameter, and the V compiler didn’t give a type error: the C compiler did.

                                                                                                  % make
                                                                                                  cd ./vc && git clean -xf && git pull --quiet
                                                                                                  cd /var/tmp/tcc && git clean -xf && git pull --quiet
                                                                                                  cc  -g -std=gnu11 -w -o v ./vc/v.c  -lm -lpthread
                                                                                                  ./v self
                                                                                                  V self compiling ...
                                                                                                  make modules
                                                                                                  make[1]: Entering directory '/home/abby/Projects/v'
                                                                                                  #./v build module vlib/builtin > /dev/null
                                                                                                  #./v build module vlib/strings > /dev/null
                                                                                                  #./v build module vlib/strconv > /dev/null
                                                                                                  make[1]: Leaving directory '/home/abby/Projects/v'
                                                                                                  V has been successfully built
                                                                                                  V 0.1.27 b806fff
                                                                                                  
                                                                                                  % ./v test.v
                                                                                                  ==================
                                                                                                  /home/abby/.cache/v/test.tmp.c: In function ‘main’:
                                                                                                  /home/abby/.cache/v/test.tmp.c:9476:2: error: implicit declaration of function ‘foo’ [-Werror=implicit-function-declaration]
                                                                                                   9476 |  foo(123);
                                                                                                        |  ^~~
                                                                                                  /home/abby/.cache/v/test.tmp.c: In function ‘vcalloc’:
                                                                                                  /home/abby/.cache/v/test.tmp.c:4597:1: warning: control reaches end of non-void function [-Wreturn-type]
                                                                                                   4597 | }
                                                                                                        | ^
                                                                                                  /home/abby/.cache/v/test.tmp.c: In function ‘byte_is_white’:
                                                                                                  /home/abby/.cache/v/test.tmp.c:7227:1: warning: control reaches end of non-void function [-Wreturn-type]
                                                                                                   7227 | }
                                                                                                        | ^
                                                                                                  ...
                                                                                                  ==================
                                                                                                  (Use `v -cg` to print the entire error message)
                                                                                                  
                                                                                                  builder error: 
                                                                                                  ==================
                                                                                                  C error. This should never happen.
                                                                                                  
                                                                                              2. 17

                                                                                                Author of the post here, let me see if I can try to clear some things up.

                                                                                                She cites vlang.io saying

                                                                                                V can be bootstrapped in under a second by compiling its code translated to C with a simple

                                                                                                cc v.c

                                                                                                No libraries or dependencies needed.

                                                                                                then argues against it, preposterously, by saying in part,

                                                                                                Git is a dependency, which means perl is a dependency, which means a shell is a dependency, which means glibc is a dependency, which means that a lot of other things (including posix threads) are also dependencies. …

                                                                                                Downloading a .c source file requires git? Does this person know what a “dependency” is? Should JavaScript developers include depending upon the laws of physics in package.json?

                                                                                                Okay I was being a bit unfair, but if we look at the makefile we see that it has the following dependencies:

                                                                                                • make (which depends on perl, glibc, autotools and all that nonsense)
                                                                                                • git (which depends on perl (even at runtime), glibc, autotools and all that nonsense)
                                                                                                • gcc (which depends on perl, glibc, autotools, automake, autoconf and more libraries than I care to list right now)

                                                                                                So if you want to be completely honest, even if you cut out the make and git steps (which i care about as someone who builds packages for linux boxes using the unmodified build system as much as possible so I can maintain whatever shred of sanity I have left), it still depends on a C compiler to get bootstrapped. This is a dependency. Then you have to download the bootstrap file from somewhere, which requires dependencies in terms of root certificates and the compiler to bootstrap with (not to mention the server that hosts the bootstrap file both existing and serving the right file back). Given that V in its current form requires you to download files from the internet in order to build it, mathematically it cannot be dependency free (this actually precludes it from being packageable in NixOS, because NixOS doesn’t allow package builds to access the network, all of the tarball/assets need to be explicitly fetched outside the build with fetchgit, fetchurl and similar). Pedantically, requiring someone to have an internet connection is a dependency.

                                                                                                Pedantically, the v binary lists the following dynamically linked dependencies when using lld(1):

                                                                                                $ ldd ./v
                                                                                                        linux-vdso.so.1 (0x00007fff2d044000)
                                                                                                        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2fb3e4c000)
                                                                                                        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2fb3a5b000)
                                                                                                        /lib64/ld-linux-x86-64.so.2 (0x00007f2fb4345000)
                                                                                                

                                                                                                If the binary was truly dependency-free, the ldd output would look something like this:

                                                                                                $ ldd $HOME/bin/dhall
                                                                                                        not a dynamic executable
                                                                                                

                                                                                                This leads me to assume that the v binary has dependencies that the runtime system will need to provide, otherwise the program will not be able to be loaded by the Linux kernel and executed. Binaries produced by v have similar limitations:

                                                                                                $ ldd ./hello
                                                                                                        linux-vdso.so.1 (0x00007ffdfdff2000)
                                                                                                        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fed25771000)
                                                                                                        /lib64/ld-linux-x86-64.so.2 (0x00007fed25d88000)
                                                                                                

                                                                                                Additionally, I am banned from the V discord and GitHub. The V programming language has censored a neuro-diverse trans woman from being able to contribute to the project in any capacity. I would love to be able to contribute to things at least to make the documentation and website not filled with misleading statements, but I cannot. This is why I ask other people to make issues for me in my posts.

                                                                                                I realize things might look snarky when the article is viewed from a certain worldview/lens, but there is a total scalar lack of snark intended in that article when it was written. If you cannot realize that, then I am sorry that my intended tone didn’t have the effect I wanted and I will use this feedback to further refine my writing ability.

                                                                                                Direct x64 machine code generation

                                                                                                In my testing I was unable to get this working on my Ubuntu server. It still used gcc.

                                                                                                1. 8

                                                                                                  You ended your piece (which utterly trashes V) by saying

                                                                                                  Overall, V looks like it is making about as much progress as I had figured it would.

                                                                                                  I criticized your snark, and you replied with

                                                                                                  I realize things might look snarky when the article is viewed from a certain worldview/lens, but there is a total scalar lack of snark intended in that article when it was written.

                                                                                                  Do you really expect anyone to believe that?

                                                                                                  Additionally, I am banned from the V discord and GitHub. The V programming language has censored a neuro-diverse trans woman from being able to contribute to the project in any capacity.

                                                                                                  Do you really think that’s why you were banned? Does Alex even know you’re trans? You don’t think you were banned for your vicious and misleading attacks on this project?

                                                                                                  1. 5

                                                                                                    You’re just ignoring the points she made here, and keep talking besides her and banging on about the article.

                                                                                                    1. 6

                                                                                                      @cadey didn’t say they were banned for who they are, they just stated they were X and were banned.

                                                                                                      You don’t think you were banned for your vicious and misleading attacks on this project?

                                                                                                      If my memory serves me right, @cadey was banned because of their disagreements with V, such as those voiced in this and the previous (https://christine.website/blog/v-vvork-in-progress-2020-01-03) blog post. I could be wrong. Also “vicious” is being overly dramatic and frankly not productive.

                                                                                                      1. 4

                                                                                                        @cadey didn’t say they were banned for who they are, they just stated they were X and were banned.

                                                                                                        Then why bring it up?

                                                                                                        If my memory serves me right, @cadey was banned because of their disagreements with V, … . I could be wrong.

                                                                                                        Is that actually true?

                                                                                                        Also “vicious” is being overly dramatic …

                                                                                                        It doesn’t sound like you’re paying very close attention… Two other people criticized her for bullying in this very thread before I even got here. If you read my comments here then I’d hope you would change your mind about how unfairly harsh she has been to Alex, to his project, and to the V team.

                                                                                                        Consider starting here: https://lobste.rs/s/nfjifq/v_update_june_2020#c_vuofat

                                                                                                        1. 22

                                                                                                          You almost never comment except in V threads.

                                                                                                          Further, many of those comments seem to be today, in last year’s thread.

                                                                                                          Please just let this be. Flag the submission if you must and move on.

                                                                                                          1. 6

                                                                                                            I have removed the post as of this commit. In a few minutes the article will be gone, but a tombstone of the former article will remain.

                                                                                                            1. 19

                                                                                                              I don’t think you did anything wrong by posting it, I don’t think you made any mistakes, and I enjoyed reading it. Not saying this to convince you to put the essay back; I just know that I personally feel awful when I get really harsh criticism, even when I don’t respect or care about the person giving it. So wanted to provide a bit of positivity to balance it out ツ

                                                                                                            2. 8

                                                                                                              Then why bring it up?

                                                                                                              I can’t answer that question. While I’m not sure what the benefit is of bringing it up, I don’t see the harm either; it was pretty clear from the comment they were not saying they were banned because of who they are.

                                                                                                              Is that actually true?

                                                                                                              Feel free to show otherwise. I can’t, because I’m not the person who banned @cadey; nor am I in contact with them.

                                                                                                              It doesn’t sound like you’re paying very close attention

                                                                                                              Please do not make such assumptions. It’s unproductive starting an argument as such, as well as factually incorrect.

                                                                                                              Two other people criticized her for bullying in this very thread before I even got here.

                                                                                                              Only one person said it’s starting to look like bullying (https://lobste.rs/s/nfjifq/v_update_june_2020#c_cdxvwk). Other comments mentioning “bullying” either state they are not sure, or don’t see it as bullying. I don’t see anybody else mentioning this is bullying. Am I perhaps overlooking something?

                                                                                                              If you read my comments here then I’d hope you would change your mind about how unfairly harsh she has been to Alex, to his project, and to the V team.

                                                                                                              I agree the tone in the blog post is not the most productive. While some parts of the post are a bit pedantic, overall I think it’s not unfairly harsh. V made many big claims both before and after its release. Here are just a few examples:

                                                                                                              • https://github.com/vlang/v/issues/35
                                                                                                              • Translating C++ to V, which now has the note “TODO: translating C to V will be available in V 0.3. C++ to V will be available later this year.”
                                                                                                              • Claiming V has pure functions when they can still have side-effects. “Pure” has a well defined meaning. If you mean “pure but with IO”, then call it something else; otherwise it’s just misleading. This was brought up in this issue, which was closed, but I can’t find any mention of this in the docs here.
                                                                                                              • Various claims about certain components not having dependencies, only to have dependencies; despite the website advertising “Compiles to native binaries without any dependencies”
                                                                                                              • Advertising “V is written in V and compiles itself in under a second.”, when according to https://fast.vlang.io/ compiling V with optimisations (if I’m reading the table correctly) takes over one second most of the time.

                                                                                                              There is a lot more from past discussions (e.g. those on Hacker News), so I suggest taking a look at those.

                                                                                                              With that all said, I really do hope V succeeds and wish the authors the best of luck. But the authors really need to make sure that what they advertise is actually implemented as advertised, or make it very clear what the current state is. Don’t go around saying “We support X” followed by “oh by the way we’ll release that end of this year”.

                                                                                                    1. 4

                                                                                                      I’ve written some Go and some Rust. I feel like I usually enjoy Rust more, though I struggle to explain why.

                                                                                                      I think, for Rust, I find the error handling really ergonomic. Using ? in a function that does a bunch of things that can fail is just so much nicer than having every other line be a if err == nil { return err }. I also find it easier to follow how references work in Rust, oddly enough maybe. And using modules through Cargo is just so nice, while Go modules is kind of a messy hack in comparison. Oh and the macros are just so nice too.

                                                                                                      But on Go’s side, Go concurrency is really awesome and smooth, especially compared to the half-complete hacks that are tokio and the Rust async system. Did I mention how nice the built-in channels are, and how a bunch of places in the standard lib use them? And easy cross-compilation is pretty nice too. And you gotta love that massive standard library. And I suppose not having to wrestle with complex too-clever generic hierarchies is nice sometimes too.

                                                                                                      1. 15

                                                                                                        But on Go’s side, Go concurrency is really awesome and smooth

                                                                                                        Concurrency is an area I feel Go really lets the programmer down. There is a simple rule for safe concurrent programming: No object should be both mutable and shared between concurrent execution contexts at the same time. Rust is not perfect here, but it uses the unique ownership model and the send trait to explicitly transfer ownership between threads so you can pass mutable objects around, and the sync trait for safe-to-share things. The only safe things to share in safe rust are immutable objects. You can make other things adopt the sync trait if you’re willing to write unsafe Rust, but at least you’re signposted that here be dragons. For example, the ARC trait in Rust (for atomic reference counting), which gives you a load of read-only shared references to an object and the ability to create a mutable reference if there are no other outstanding references.

                                                                                                        In contrast, when I send an object down a channel in Go, I still have a pointer to it. The type system gives me nothing to help avoid accidentally aliasing an object between two threads. To make things worse, the Go memory model is relaxed consistency atomic, so you’re basically screwed if you do this. To make things even worse, core bits of the language semantics rely on the programmer not doing this. For example, if you have a slice that is in an object that is shared between two goroutines, both can racily update it. The slice contains a base and a length and so you can see tearing: the length from one slice and the base from another. Now you can copy it, dereference it and read or write past the end of an array. This is without using anything in the unsafe package: you can violate memory safety (let alone type safety) purely in ‘safe’ Go, without doing anything that the language helps you avoid.

                                                                                                        I wrote a book about Go for people who know other languages. It didn’t sell very well, in part because it ended up being a long description of things that Go does worse than other languages.

                                                                                                        1. 2

                                                                                                          That’s a worthwhile point. I haven’t been bitten by the ability to write to Go object that have already been sent down a channel yet, but I haven’t worked on any large-scale long-term Go projects. I’ve found it straightforward enough to just not use objects after sending. But then, the reason why we build these fancy type systems with such constraints is that even the best developers have proved to be not very good at consistently obeying these limits on large-scale projects.

                                                                                                          I’m hoping that the Rust issues with async and tokio are more like teething pains for new tech than a fundamental issue, and that eventually, it will have concurrency tools that are both as ergonomic as Go’s and use Rust’s thread safety rules.

                                                                                                          1. 4

                                                                                                            I’ve found it straightforward enough to just not use objects after sending.

                                                                                                            This is easy if the object is not aliased, but that requires you to have the discipline of linear ownership before you get near the point that sends the object, or to only ever send objects allocated near the sending point. Again, the Go type system doesn’t help at all here, it lets you create arbitrary object graphs with N pointers to an object and then send the object. The (safe) Rust type system doesn’t let you create arbitrary object graphs and then gives strong guarantees on what is safe to send. The Verona type system is explicitly designed to allow you to create arbitrary (mutable or immutable) object graphs and send them safely.

                                                                                                        2. 15

                                                                                                          side-note: i think it’s a bit off-topic (and meme-y, rust strike force, etc. :) to compare to rust when the article only speaks of go :)

                                                                                                          Using ? in a function that does a bunch of things that can fail is just so much nicer than having every other line be a if err == nil { return err }.

                                                                                                          i really like the explicit error handling in go and that there usually is only one control flow (if we ignore “recover”). i guess that’s my favorite go-feature: i don’t have to think hard about things when i read them. it’s a bit verbose, but that’s a trade-off i’m happy to make.

                                                                                                          1. 7

                                                                                                            i really like the explicit error handling in go

                                                                                                            I would argue that Go’s model of error handling is a lot less explicit than Rust’s - even if Go’s is more verbose and perhaps visually noticeable, Rust forces you to handle errors in a way that Go doesn’t.

                                                                                                            1. 1

                                                                                                              I have just read up un rusts error handling, it seems to be rather simila, except that return types and errors are put together as “result”: https://doc.rust-lang.org/book/ch09-00-error-handling.html

                                                                                                              my two cents: i like that i’m not forced to do things in go, but missing error handling sticks out as it is unusual to just drop errors.

                                                                                                              1. 4

                                                                                                                Well since it’s a result, you have to manually unwrap it before you can access the value, and that forces you to handle the error. In Go, you can forget to check err for nil, and unless err goes unused in that scope, you’ll end up using the zero value instead of handling the error.

                                                                                                                1. 1

                                                                                                                  i like that i’m not forced to do things in go, but missing error handling sticks out as it is unusual to just drop errors

                                                                                                                  The thing is, while it may be unusual in Go, it’s impossible to “just drop errors” in Rust. It’s easy to unwrap them explicitly if needed, but that’s exactly my point: it’s very explicit.

                                                                                                              2. 3

                                                                                                                The explicit error handling is Very Visible, and thus it sticks out like a sore thumb when it’s missing. This usually results in better code quality in my experience.

                                                                                                                1. 2

                                                                                                                  It did occur to me that it may come off like that :D It’s harder to make interesting statements about a language without comparing it to its peers.

                                                                                                                  IMO, Rust and Go being rather different languages with different trade-offs that are competing for about the same space almost invites comparisons between them. Kind of like how temping it is to write comparisons between Ruby, Python, and Javascript.

                                                                                                                  1. 1

                                                                                                                    I think Swift fits in quite well in-between. Automatic reference counting, so little need to babysit lifetimes, while using a powerful ML-like type system in modernised C-like syntax.

                                                                                                                2. 8

                                                                                                                  And using modules through Cargo is just so nice, while Go modules is kind of a messy hack in comparison.

                                                                                                                  I have always found Rust’s module system completely impenetrable. I just can’t build a mental model of it that works for me. I always end up just putting keywords and super:: or whatever in front in various combinations until it happens to work. It reminds me of how I tried to get C programmes to compile when I was a little kid: put more and more & or * in front of expressions until it works.

                                                                                                                  And of course they changed in Rust 2018 as well which makes it all the more confusing.

                                                                                                                  1. 3

                                                                                                                    Yeah, I’ve had the same experience. Everything else about Cargo is really nice, but modules appear to be needlessly complicated. I have since been told that they are complicated because they allow you to move your files around in whatever crazy way you prefer without having to update imports. Personally I don’t think this is a sane design decision. Move your files, find/replace, move on.

                                                                                                                    1. 2

                                                                                                                      And of course they changed in Rust 2018 as well which makes it all the more confusing.

                                                                                                                      One of the things they changed in Rust 2018, FYI, was the module system, in order to make it a lot more straightforward. Have you had the same problem since Rust 2018 came out?

                                                                                                                    2. 6

                                                                                                                      For me Go is the continuation of C with some added features like CSP. Rust is/was heavily influenced by the ML type of languages which is extremely nice. I think ML group is superior in my ways to the C group. ADTs are the most trivial example why.

                                                                                                                      1. 3

                                                                                                                        I generally agree. I like ML languages in theory and Rust in particular, but Rust and Go aren’t in the same ballpark with respect to developer productivity. Rust goes to impressive lengths to make statically-managed memory user-friendly, but it’s not possible to compete with GC. It needs to make up the difference in other areas, and it does make up some of the difference in areas like error handling (?, enums, macros, etc and this is still improving all the time), IDE support (rust-analyzer has been amazing for me so far), and compiler error messages, but it’s not yet enough to get into a competitive range IMO. That said, Rust progresses at a remarkable pace, so perhaps we will see it get there in the next few years. For now, however, I like programming in Rust–it satisfies my innate preference to spend more time building something that is really fast, really abstract, and really correct–but when I need to do quality work in a short time frame in real world projects, I still reach for Go.

                                                                                                                        1. 9

                                                                                                                          To me Go seems like a big wasted opportunity. If they’d only taken ML as a core language instead of a weird C+gc hybrid, it would be as simple (or simpler) as it is, but much cleaner, without nil or the multi-return hack. Sum types and simple parametric polymorphism would be amazing with channels. All they had to do was to wrap that in the same good toolchain with fast compilation and static linking.

                                                                                                                          1. 2

                                                                                                                            Yeah, I’ve often expressed that I’d like a Go+ML-type-system or a Rust-lite (Rust with GC instead of ownership). I get a lot of “Use OCaml!” or “Use F#”, but these miss the mark for a lot of reasons, but especially the syntax, tooling, and ecosystem. That said, I really believe we overemphasize language features and under-emphasize operational concerns like tooling, ecosystem, runtime, etc. In that context, an ML type system or any other language feature is really just gravy (however, a cluster of incoherent language features is a very real impediment).

                                                                                                                            1. 1

                                                                                                                              Nothing is stopping anyone from doing that. I’d add that they make FFI to C, Go, or some other ecosystem as easy as Julia for the win. I recommend that for any new language to solve performance and bootstrapping problem.

                                                                                                                            2. 3

                                                                                                                              Then, you have languages like D that compile as fast as Go, run faster with LLVM, have a GC, and recently an optional borrow checker. Contracts, too. You get super productivity followed by as much speed or safety as you’re willing to put in effort for.

                                                                                                                              Go is a lot easier to learn, though. The battle-tested, standard libraries and help available on the Internet would probably be superior, too.

                                                                                                                              1. 3

                                                                                                                                I hear a lot of good things about D and Nim and a few others, but for production use case, support, ecosystem, developer marketshare, tooling, etc are all important. We use a lot of AWS services, and a lot of their SDKs are Python/JS/Go/Java/dotnet exclusively and other communities have to roll their own. My outsider perspective is that D and Nim aren’t “production ready” in the sense that they lack this sort of broad support and ecosystem maturity, and that’s not a requirement I can easily shrug off.

                                                                                                                                1. 2

                                                                                                                                  I absolutely agree. Unless easy to handroll, those kind of things far outweigh advantages in language design. It’s what I was hinting at in 2nd paragraph.

                                                                                                                                  It’s also why it’s wise for new languages to plug into existing ecosystems. Clojure on Java being best example.

                                                                                                                        1. 23

                                                                                                                          10 selling points, no downside, that’s fishy. No mention of the lack of static typing, for example. No mention of Kotlin or Scala. That sounds like someone who’s a bit too enthusiastic to acknowledge the shortcomings that any tool has.

                                                                                                                          1. 11

                                                                                                                            The lack of static typing as a downside is, and will always be, subjective. As Rich Hickey famously says, “What’s true of every bug? 1) it passed your unit tests 2) it passed the type checker.”

                                                                                                                            Spec, as a structural testing mechanism, is I believe generally understood to be a preferable alternative to static typing, not an afterthought bolted on to appease devs that demand static typing.

                                                                                                                            1. 10

                                                                                                                              I don’t understand what the quote is trying to say. “Every bug” is still fewer bugs if type bugs are ruled out by a type checker.

                                                                                                                              1. 3

                                                                                                                                My reading is that static typing isn’t a silver bullet. That’s an over simplification. See the video below for a bit more context surrounding that particular quote, and maybe some rationale behind clojure’s approach to typing and the role that Spec plays.

                                                                                                                                https://www.infoq.com/presentations/Simple-Made-Easy/

                                                                                                                              2. 5

                                                                                                                                It’s amusing to me that people accept this as a critique of static typing in general rather than a critique of certain hilariously-bad type systems like that of C or Java.

                                                                                                                                I am trying to think of the last time I encountered a bug in a piece of software written in a language with a not-terrible static type system, but … I can’t think of one.

                                                                                                                                1. 4

                                                                                                                                  Awesome. I’ll take your word for it. What is a language with a not-terrible type system? Haskell?

                                                                                                                                  1. 4

                                                                                                                                    Right.

                                                                                                                                    I mean obviously part of the reason I haven’t run into many bugs is that there just aren’t as many programs written using good type systems. Programs written in Haskell or OCaml or Elm still have bugs, but they only have certain classes of bugs. Just because you can’t get rid of every bug doesn’t mean it’s pointless to get rid of the ones you can, and Rich’s punchy quote seems to imply that this line of reasoning is invalid.

                                                                                                                                    1. 2

                                                                                                                                      I see what you’re saying. And I agree that, on the surface, that quote seems like it’s dumping on static typing entirely, but I don’t think that’s the case. In the talk in which Hickey drops that quote he expands a on it a bit, to a degree that my simply slapping it into a response doesn’t do justice. You’re the Leiningen guy, you know Clojure, you’re presumably familiar with the talk.

                                                                                                                                      My takeaway was that static typing, like unit tests, catches bugs. Certain classes of bugs (as you mention above). However, in some complex and complicated systems, those classes of bugs aren’t the primary concern. I’ve never worked in that kind of system, but I like what I’ve seen of clojure and I haven’t found this particular line of reasoning disagreeable.

                                                                                                                                      1. 4

                                                                                                                                        You’re the Leiningen guy, you know Clojure, you’re presumably familiar with the talk.

                                                                                                                                        Yep, I’ve seen the talk. It feels to me like he already decided he doesn’t like static typing because of bad experiences with Java and uses that experience to make straw-man arguments against all static type systems in general. I can imagine the existence of a system for which “bugs that no type system can catch” are the primary concern, but I’ve never encountered such a system myself. (I have worked with plenty of systems where the cost of the type system is higher than the benefit of squashing those bugs, but that’s a very different argument than Rich’s.)

                                                                                                                                        1. 3

                                                                                                                                          Yep, I’ve seen the talk. It feels to me like he already decided he doesn’t like static typing because of bad experiences with Java and uses that experience to make straw-man arguments against all static type systems in general

                                                                                                                                          There seems be at least some evidence that he knows Haskell pretty well, he just doesn’t really publicize it.

                                                                                                                                          I think it’d be really funny if he keynoted ICFP with a talk on algebraic effects and never mentions the talk ever again. Will never happen, but a guy can dream.

                                                                                                                                          1. 3

                                                                                                                                            I’m pretty skeptical that anyone who “knows Haskell pretty well” would produce the “Maybe Not” talk. More generally, my experience is that anyone willing to invest the time and energy into learning Haskell tends to be more tuned-in to the actual tradeoffs one makes when using the language, and it’s clear that his emotionally-framed talking points overlap very little with what actual Haskell programmers care or think about. Of course, it could be the case that he does know the language pretty well and simply talks about it like a frustrated novice to frame emotional talking points to appeal to his Clojure true-believers, but this seems far-fetched.

                                                                                                                                            1. 3

                                                                                                                                              IMO the “Maybe Not” talk gets more flak than it deserves. Function subtyping is a valid data representation and Maybe Int -> Int can be represented as a subtype of Int -> Maybe Int. Haskell chooses not to allow that representation, and it is a way in which the type system is arguable incomplete (in the “excludes valid programs” sense.)

                                                                                                                                              1. 4

                                                                                                                                                You’ll have to work hard to convince me that Rich Hickey was arguing on the level of critiquing the “function sub-typing” capabilities of Haskell’s type system vs. the more prosaic “static typing bad!” bullshit he falls back on again and again. Stated straightforwardly, his argument is basically “Maybe is bad because it means you will break the expectations of the caller when you need to introduce it to account for optionality.” And, I suppose it is in fact terrible when you don’t have a type-checker and depend on convention and discipline instead. So, Rich Hickey 1, static typing 0, I guess?

                                                                                                                                                As to “Maybe Not” getting more flak than it deserves…yeah, we’ll have to agree to disagree. (And I’ll note here I’m really surprised that you in particular are taking this position considering how often I see you on here deeply engaging with such a broad variety of academic computer science topics, without needing to use strawmen or appeal to emotion to argue a position.)

                                                                                                                                                For example, “Maybe/Either are not type system’s or/union type.” Okay. How do you even argue with that? I don’t even really understand what he’s trying to assert. Does he not believe the Curry-Howard correspondence is valid? For that matter, which type system? Will I get lambasted by the apologists for not understanding his super subtle point, yet again? Meh.

                                                                                                                                                Someone who was honestly and deeply engaged with the ideas he spends so much time critiquing wouldn’t be babbling nonsense like “you would use logic to do that, you wouldn’t need some icky category language to talk about return types” or “type system gook getting into spec”…god forbid!

                                                                                                                                                I’ll give him this though: Rich Hickey is doing a great job of convincing the people who already agree with him that static typing is bad.

                                                                                                                                                (Edited to fix some links and a quote)

                                                                                                                                                1. 3

                                                                                                                                                  As to “Maybe Not” getting more flak than it deserves…yeah, we’ll have to agree to disagree. (And I’ll note here I’m really surprised that you in particular are taking this position considering how often I see you on here deeply engaging with such a broad variety of academic computer science topics, without needing to use strawmen or appeal to emotion to argue a position.)

                                                                                                                                                  Thank you! I should note that just because I deeply engage with a lot of different CS topics doesn’t mean I won’t flail around like an idiot occasionally, or even often.

                                                                                                                                                  For example, “Maybe/Either are not type system’s or/union type.” Okay. How do you even argue with that? I don’t even really understand what he’s trying to assert. Does he not believe the Curry-Howard correspondence is valid? For that matter, which type system? Will I get lambasted by the apologists for not understanding his super subtle point, yet again? Meh.

                                                                                                                                                  Let me see if I can explain this in a less condescending way than the talk. Let’s take the type Maybe Int, which I’ll write here as Maybe(ℤ). From a set theory perspective, this type is the set {Just x | x ∈ ℤ} ∪ {Nothing}. There is an isomorphism from of the maybe type to the union type ℤ ∪ {Nothing}. Let’s call this latter type Opt(ℤ). Opt(ℤ) is a union type in a way that Maybe(ℤ) is not, because we have ℤ ⊆ Opt(ℤ) but not ℤ ⊆ Maybe(ℤ). 3 ∈ ℤ, 3 ∉ Maybe(ℤ). Again, we have Just 3 ∈ Maybe(ℤ), and an isomorphism that maps Just 3 ↦ 3, so in theory this isn’t a problem.

                                                                                                                                                  The problem is that Haskell’s type system makes design choices that makes that isomorphism not a valid substitution. In fact, I don’t think Haskell even has a way of represent Opt(ℤ), only its isomorphism. Which means that we can’t automatically translate between “functions that use Opt(ℤ)” and “functions that use Maybe(ℤ)”. Take the functions

                                                                                                                                                  foo :: Maybe Int -> Int
                                                                                                                                                  foo Nothing = 0
                                                                                                                                                  foo (Just x) = x*x
                                                                                                                                                  
                                                                                                                                                  -- I don't think this is possible in Haskell, just bear with me
                                                                                                                                                  bar :: Opt Int -> Int
                                                                                                                                                  foo Nothing = 0
                                                                                                                                                  foo x = x * x
                                                                                                                                                  

                                                                                                                                                  Is map foo [1..10] type-safe? Not in Haskell, because map foo has type [Maybe Int] -> [Int] and [1..10] has type [Int]. Is map bar [1..10] type-safe? In a type system that supported “proper” union types, arguably yes! ℤ ⊆ Opt(ℤ), so map bar is defined for all [Int]. So maybe types emulate useful aspects of union types but, in the Haskell type system, don’t have all the functionality you could encode in union types.

                                                                                                                                                  Now there are two common objections to this:

                                                                                                                                                  1. Haskell has very good reasons for doing things this way. This is 100% true. But it’s true because Haskell has a lot of goals with this type system and being able to encode this particular union type requires us to have proper function subtyping, which would absolutely be a nightmare to combine with everything else in Haskell. But nonetheless shows that Haskell is only exploring one part of the possible space of type systems, and there are valid things that it chooses not to represent. “Proper” union types are one of these things.
                                                                                                                                                  2. You can easily write a shim function to make map foo type safe. This is usually people’s objection to this talk. And most of the time you can do this. But this is just a form of emulation, not reproducing the core idea. It’s similar to how in OOP you can “emulate” higher-order functions with the strategy pattern. But it’s not a perfect replacement. For any given emulation I can probably construct a example where your emulation breaks down and you have to try something slightly different. Maybe it doesn’t work if I’m trying to compose a bunch of fmaps.

                                                                                                                                                  This is why I think the talk is underrated. There’s a lot of genuinely interesting ideas here, and I get the impression Rich Hickey has thought a lot of this stuff through, but I think it’s hampered him presenting this ideas to a general clojure audience and not a bunch of type-theory nerds.

                                                                                                                                                  1. 1

                                                                                                                                                    I don’t follow: map foo [1..10] wouldn’t even typecheck; it’s not even wrong to say it’s not typesafe (edit: and apologies if that’s what you meant, I don’t mean to beat you over the head with correct terminology, I just honestly didn’t get it). And while it’s well and fine that there’s an isomorphism between {Just x | x ∈ ℤ} and , it’s not clear to me what that buys you. You still have to check your values to ensure that you don’t have Nothing (or in the case of Clojure, nil), but in Haskell, because I have algebraic data types, I can build abstractions on top to eliminate boilerplate. Your Opt example doesn’t present as better or highlight the power of this isomorphism. Why do I even care that I can’t represent this isomorphism in Haskell? I’m afraid your post hasn’t clarified anything for me.

                                                                                                                                                    As far as the talk, I think that if he had some really interesting ideas to share, he’d be able to explain them to type theory nerds in the same talk he gives to his “core constituency.”

                                                                                                                                                    At this point, I have trouble considering the output of someone who, no matter how thoughtful they may be, has made it clear that they are hostile to certain ideas without justifying that hostility. There is plenty of criticism to be made of Haskell and type theory without taking on the stance he has taken, which is fundamentally “type theory and type systems and academic PLT is not worth your time to even consider, outside of this narrow range of topics.” If he was a random crank that’d be fine, but I think that because of his position, his presentations do real harm to Clojure programmers and anyone else who hears what he’s saying without having familiarity with the topics he dismisses, because it shuts them off to a world of ideas that has real utility even if it’s very much distinct from the approach he’s taken. It also poisons the well for those of us in the community who have spent serious time in these other worlds and who value them, which is a tremendous shame, because Rich Hickey does have a lot of great ideas and ways of presenting them intuitively. So regardless of how eloquently you may be able to translate from Rich Hickey-ese, what I object to fundamentally is his intellectual attitude, moreso than his ideas, many of which I agree with.

                                                                                                                                                    Thank you! I should note that just because I deeply engage with a lot of different CS topics doesn’t mean I won’t flail around like an idiot occasionally, or even often.

                                                                                                                                                    Well understood from personal experience. ;-)

                                                                                                                                                    1. 2

                                                                                                                                                      I don’t follow: map foo [1..10] wouldn’t even typecheck; it’s not even wrong to say it’s not typesafe (edit: and apologies if that’s what you meant, I don’t mean to beat you over the head with correct terminology, I just honestly didn’t get it).

                                                                                                                                                      That’s what I meant, it wouldn’t typecheck. Brain fart on my part.

                                                                                                                                                      And while it’s well and fine that there’s an isomorphism between {Just x | x ∈ ℤ} and ℤ, it’s not clear to me what that buys you. You still have to check your values to ensure that you don’t have Nothing (or in the case of Clojure, nil) … Your Opt example doesn’t present as better or highlight the power of this isomorphism.

                                                                                                                                                      Let’s try a different tack. So far we have

                                                                                                                                                      foo :: Maybe Int -> Int
                                                                                                                                                      bar :: Opt Int -> Int
                                                                                                                                                      

                                                                                                                                                      Now I give you three black-box functions:

                                                                                                                                                      aleph :: Int -> Maybe Int
                                                                                                                                                      beis :: Int -> Opt Int
                                                                                                                                                      gimmel :: Int -> Int
                                                                                                                                                      

                                                                                                                                                      foo aleph typechecks, as does bar beis. foo gimmel doesn’t typecheck. I think all three of those we can agree on. Here’s the question: what about bar gimmel? In Haskell that wouldn’t typecheck. However, we know that Int ⊆ Opt Int. gimmel’s codomain is a subset of bar’s domain. So bar must be defined for every possible output of gimmel, meaning that bar gimmel cannot cause a type error.

                                                                                                                                                      This means that because Haskell cannot represent this isomorphism, there exists functions that mathematically compose with each other but cannot be composed in Haskell.

                                                                                                                                                      Why do I even care that I can’t represent this isomorphism in Haskell?

                                                                                                                                                      Mostly this is a special case of function subtyping, which I don’t think Haskell supports at all? So if function subtyping makes your problem domain more elegant, it’d require workarounds here.

                                                                                                                                                      1. 1

                                                                                                                                                        To be clear I understood your point initially about function subtyping being a thing that maybe Haskell can’t represent, and I apologize for making you come up with multiple creative examples to try to illustrate the idea (but I appreciate it)!

                                                                                                                                                        So if function subtyping makes your problem domain more elegant, it’d require workarounds here.

                                                                                                                                                        What remains unclear for me–if we’re treating this as a proxy for Rich Hickey’s argument–is how this demonstrates the practical insufficiency of Maybe, which is his main pitch. I am happy to acknowledge that there are all kinds of limitations to Haskell’s type system, this is no surprise. What I don’t yet understand is why this is a problem wrt Maybe!

                                                                                                                                                        In any case, thank you for the thoughtful responses.

                                                                                                                                2. 3

                                                                                                                                  Static typing, in my uninformed opinion, is less about catching bugs than it is about enforcing invariants that, as your application grows, become the bones that keep some sort of “tensegrity” in your program.

                                                                                                                                  Without static typing your application is way more likely to collapse into a big ball of mud as it grows larger and none of the original engineers are working on it anymore. From this perspective I suppose the contract approach is largely similar in it’s anti-implosion effect.

                                                                                                                                  However, type theory offers a whole new approach to not only programming but also mathematics and I think there is a lot of benefit we still haven’t seen from developing this perspective further (something like datafun could be an interesting protobuf-esque “overlay language” for example).

                                                                                                                                  On the other hand, dynamic programming (I think) peaked with lisp, and clojure is a great example of that. A lightweight syntax that is good for small exploratory things has a lot of value and will always be useful for on the fly configuration. Doesn’t change that the underlying platform should probably be statically typed.

                                                                                                                                3. 6

                                                                                                                                  Static typing is mentioned in section 8 in regards to the spec library, and Scala is named in the Epilogue as a mature alternative.

                                                                                                                                  1. 3

                                                                                                                                    “In this article we have listed a number of features that positively separates Clojure from the rest.” well, seems like the author thinks they address scala as well as java in the article, even though it’s only named in the previous sentence.

                                                                                                                                    Spec is no alternative to static typing, as far as I know. Isn’t it just runtime checks, and possibly a test helper? Scala and kotlin both have decent (or even advanced) type systems. I think some of the points are also advantages over kotlin and scala (repl and simplicity/stability, respectively), but the choice is not as black and white as depicted in OP.

                                                                                                                                    1. 2

                                                                                                                                      Spec isn’t static, but it can provide much of the same functionality as a type system like Scala’s, just that it does so at runtime rather than compile time. In addition, it can be used to implement design-by-contract and dependent types and it can also generate samples of the specified data for use in testing. It’s not the same but it is an alternative.

                                                                                                                                  2. 6

                                                                                                                                    Yeah #8 and #9 (and arguably #7) really are just downsides that are framed as if they were upsides. “There’s no static typing, but here’s what you can do instead!” and “The startup time is really slow; here are some ways to work around that problem!”

                                                                                                                                    1. 2

                                                                                                                                      I read #9 as ‘by default, clojure is compiled, like java. But here’s a way to get instant(-ish) startup time, which is impossible with java.’

                                                                                                                                      1. 2

                                                                                                                                        Being compiled has nothing to do with how fast something starts; planck is compiled as well.

                                                                                                                                        1. 1

                                                                                                                                          clojure is compiled, like java

                                                                                                                                          That is, clojure’s startup time characteristics are similar to java’s.

                                                                                                                                          1. 2

                                                                                                                                            uh … no?

                                                                                                                                            Clojure code can’t run without loading the Clojure runtime, which is implemented as an enormous pile of Java bytecode. A “hello world” in Java only has to load a single bytecode file, whereas a comparable Clojure program will have to almost all of clojure.jar before it can even begin to do anything.

                                                                                                                                    2. 4

                                                                                                                                      That sounds like someone who’s a bit too enthusiastic to acknowledge the shortcomings that any tool has.

                                                                                                                                      Immediately after reading the article, I agreed with this comment. After re-reading it more critically, I think the issue isn’t that he is too enthusiastic, as much as that isn’t the point of this. Outside of the brief jab in the second to last sentence (“that positively separates Clojure from the rest”), to me this doesn’t read as a comparison between all the potential successors, just something aimed at getting people interested in trying Clojure.

                                                                                                                                      As someone who hasn’t written Clojure before, but really enjoys Lisp-based languages, I found it to be a helpful overview of the language. The fact that there are no negatives listed doesn’t deter me from believing the positives any more than if I was looking for a new computer and the specifications didn’t list out other companies that make a better product. It just makes me want to carry out his last sentence and see for myself:

                                                                                                                                      … the best way to learn Clojure is to actually use it.

                                                                                                                                      1. 5

                                                                                                                                        As a fan of static typing, I would not advertise Java’s implementation of it as a feature. More of an anti-feature. It doesn’t track whether or not a field or variable pointing at a reference type can be null or not. It doesn’t support algebraic data types.

                                                                                                                                        For contrast, I would advertise the static type systems in Kotlin and Scala as features.

                                                                                                                                        1. 2

                                                                                                                                          There is little difference between Java’s type system and Kotlin’s type system.

                                                                                                                                          1. 4

                                                                                                                                            Kotlin has literally the exact two features I just mentioned. Java does not.

                                                                                                                                            1. 1

                                                                                                                                              Yes, and those two features do little difference – so it’s weird saying “Java bad, Kotlin good”.

                                                                                                                                              1. 2

                                                                                                                                                Explicit nullability tracking is not a small deal. Never having to accidentally cause a NullPointerException again is liberating.

                                                                                                                                                ADTs mean you can implement everything in the “make wrong states unrepresentable” paper.

                                                                                                                                                1. 1

                                                                                                                                                  That’s a bit like saying “look how crazy fast this 486 is .. compared to a 386!”.

                                                                                                                                            2. 2

                                                                                                                                              Doesn’t Kotlin have algebraic data types and pattern matching?

                                                                                                                                              1. 1

                                                                                                                                                Yes, barely, and no.

                                                                                                                                        1. 3

                                                                                                                                          Just bought a wetsuit today and I hope to go and try wing-foiling for the first time in my life tomorrow! Been waiting and gearing up for this since autumn 😀

                                                                                                                                          Other than that I plan to try and record a presentation for the (online) NimConf 2020, the deadline is by end of week. I installed OBS Studio yesterday but I am super frustrated that I can’t find an app to display a draggable window showing a “facecam” on Windows OS :( I found a perfect-looking one called CamDesk but it seems to be broken on Win10 :( and I’d really like to be able to have a preview of my lovely face while recording, and also to be able to move it around interactively… the app is open-source (Visual Basic) on sourceforge, but I don’t know the relevant WinAPIs well enough to be able to try and fix it in time for the conf :/ I’ve seen some suggestions on the web to record 2 streams simultaneously by using -multi option, and that’s what I expect to fall back to, but I feel this will require me to waste much more effort & learning at postprocessing/mixing phase. Though maybe I’ll do a quick try on my Linux machine; who knows, maybe I’ll actually have some luck there? I’d be seriously impressed :) edit: Woohoo, so in the end a Linux-related search led me to an app named vokoscreen… which actually also works on Windows, and can display a nice facecam preview (^v^)/ awesomesauce, I am super happy now! :) :) and thank you good people of lobste.rs for helping me this time as a silent rubber ducky guru ;D

                                                                                                                                          More generally, this is hopefully my last week of semi-corona-related unemployment, I expect to start a new job next week (yay!)

                                                                                                                                          1. 1

                                                                                                                                            Oh, nimconf is online? When is it due to happen?

                                                                                                                                            1. 3

                                                                                                                                              Sat, Jun 20; start is currently proposed at 11am UTC, but I believe that part is not 100% confirmed yet.

                                                                                                                                              1. 1

                                                                                                                                                why, thank you. If it’s recorded I’ll probably watch in later, saturdays are not the best for me. :)

                                                                                                                                          1. 2

                                                                                                                                            I’ve been using this post to implement a parser in rust last night, and it works beautifully. Thanks for the amazing writeup.

                                                                                                                                            1. 13

                                                                                                                                              The best discussion platform I’ve ever used was bbcode forums. Easy to extend, easy to organize, easy to search, easy to use. We need a modern take on those.

                                                                                                                                              1. 6

                                                                                                                                                Forums are great but they’re very different to mailing lists, IMO. (Flat!!) forums are much better for meandering discussions and as a community hub. They’re much better for long-running threads. The osdev forums are a great example: each person can make their own thread for posting updates about their project, there are many threads that have run for years, etc.

                                                                                                                                                But you couldn’t use a phpBB-style forum to discuss patches or something, it just wouldn’t work.

                                                                                                                                                1. 2

                                                                                                                                                  you couldn’t use a phpBB-style forum to discuss patches or something

                                                                                                                                                  You don’t need to. Right tool for the job: to discuss patches, use Phabricator, GitLab, GitHub, etc. (Anything other than Gerrit.)

                                                                                                                                                  1. 1

                                                                                                                                                    The right tool for the job is a mailing list. Code forges are appallingly bad for discussing patches because none of them make it at all easy to suggest changes in the form of a simple patch.

                                                                                                                                                    1. 2

                                                                                                                                                      In GitHub PRs, I can just write:

                                                                                                                                                      ```suggestion

                                                                                                                                                      {my proposed change}

                                                                                                                                                      ```

                                                                                                                                                      And there’s then a button to apply the change (or add it to a batch to apply) right there as a new commit in the PR. CI then runs automatically, without needing anyone to check out the code locally. What is the mailing list workflow that is simpler than this?

                                                                                                                                                2. 5

                                                                                                                                                  Forums are considerably better. The thing is you could just as well us an email client to read and post to forum too. Forums have always been superior at presenting discussions compared to mailing list archives. There is certainly room for improvement (Discourse seems like a decent attempt), but when it comes to organizing and browsing past discussions, I’d take bbforum over Mailman.

                                                                                                                                                  1. 4

                                                                                                                                                    Discourse is the closest I have seen. A pig to host, though, and extension is via http api (your bot also needs hosting etc).

                                                                                                                                                    1. 3

                                                                                                                                                      Have you ever tried Zulip? The Lean prover community has one and it seems to suit them well (same for rust, these days). I like it a lot, best threading I’ve seen in any kind of messaging system, and it encourages longer form messages with embedded LaTeX and markdown.

                                                                                                                                                      1. 3

                                                                                                                                                        Couldn’t disagree more with you. Bbcode forums are some of the worst designed interfaces that have ever existed. There abdundance of completely useless user information:

                                                                                                                                                        john is user since 1992-11-11, has 20 144 posts, 44 reputation point, 5 thank yous and half of a screen signature banner of a gif leopard eating a linux penguin
                                                                                                                                                        message #1004 last edited by john 2020-06-08 20:14:55 UTC+6 South East Asian Pacific Time.
                                                                                                                                                        From Russia, Moscow
                                                                                                                                                        Offline

                                                                                                                                                        A whole 5 page thread of bbcode forums could fit in a single old.reddit screen.

                                                                                                                                                      1. 4

                                                                                                                                                        Small correction: the standard library now has an iterator type, Seq.t, and there is a compatibility package. So we’re now fully in the 21st century with both a result type and an iterator interface!

                                                                                                                                                          1. 1

                                                                                                                                                            I use feedbro too, but I’m a bit annoyed it doesn’t interoperate with firefox sync. Otherwise it’s really neat.

                                                                                                                                                          1. 6

                                                                                                                                                            Is Idris development aiming at getting “production ready” (for whatever that would mean to its author) at all, or remain a pure research vehicle?