1. 35

    There’s really a problem with this blog post. I don’t know how it’s technically done but having to wait several seconds every time you display the tab is why almost nobody will read it.

    1. 20

      It is actually super-high-level web development. Kudos to @tedu for pulling it off.

      Pages are progressively enhanced using JavaScript if it is available. If it isn’t, users can still read the page. If JS is available, then UX is enhanced with a realtime loading indicator, much like the ten-pixel-bars top bars that are on many pages.

      After all, in this Third Age of JavaScript, we cannot simply trust the browser to render the page. We need to tell the user the progress of that.

      1. 14
        var delay = 100
        switch (progress) {
        	case 70:
        	case 73:
        	case 76:
        		delay = 250
        		progress += 3
        		break
        	case 79:
        		delay = 500
        		progress += 2
        		break
        	case 81:
        		progress += 14
        		break
        	default:
        		progress += 5
        		break
        }
        

        I have to give props for verisimilitude. And for teaching me where to find uBlock Origin’s “disable javascript on this page” function.

        1. 10

          I wouldn’t be surprised if @tedu spent a good twenty minutes fine tuning that for maximum annoyingness.

          1. 2

            You have more patience than me. It taught me where to find uBlock Origin’s domain-level blocklist.

          2. 9

            I’m sorta ok with progressive enhancement. What ground my gears was that it triggered every time the window (Chrome on Windows) regained focus. It made it really hard to find my place again in a page with lots of code.

            1. 19

              I mean, just so we’re all clear, it’s something between a joke and a protest statement, and what you’re complaining about is entirely the deliberate point: it’s a perfectly fine, instantly rendering webpage that’s being “progressively dehanced” by the presence of annoying JS.

              1. 4

                Wow… kids these days 😒

            2. 5

              Yeah, I love it. This “protest” is a nice compromise in comparison to sth like “Disable JS to enter the page”. It is annoying but still usable.

            3. 12

              The site loads almost instantaneously. Just disable JavaScript ;-)

              1. 11

                What’s really weird is all the markup appears to be there, and the loading is just for…giggles?

                1. 22

                  That sounds like something @tedu would do.

                2. 2

                  Well, @tedu also had a period with a self-signed certificate, the horror!

                  1. 2

                    When you have a self-signed certificate, you are expected to trust it on first use, and then the web browser remember it.

                    If the web browser remember the certificate of a website, noone, including a MitM possessing the key of a certificate trusted by your web browser, noone can tamper the connection anymore.

                    So you suddenly jump from a situation that looks suspicious security-wise, to one that can face the NSA kind of attack vector.

                    Of course, in the case of a MitM situation, your “accepted security exception” situation (self signed but trusted manually) would turn into a “green padlock” (certificate signed by the MitM) situation, and I doubt many will choose the “padlock with yellow cross” over the “padlock with green check mark”, even if icons barely have any accurate meaning on their own…

                    Simply wandering on an off-topic… Not actually meaning that Cloudflare should switch to self-signed right now… Oh, wait, Cloudflare are self-signing, they are their own trusted certificate authority…

                  2. 2

                    Just use links? ;)

                  1. 4

                    Canonical is taking risks by forcing snap onto his users. Two weeks ago, when an automatic chromium upgrade told me that chromium would switch to snap on my computer, didn’t let me the choice to refuse the new installation, and basically broke apt until I accept, I decided to change distribution. The reason I’m not on Ubuntu anymore and probably won’t be back is only this one: I don’t want to have such change forced on me. This isn’t the linux way.

                    1. 5

                      There are browsers for which !("a" == "a"[0]) evaluates to true ? How ? Which ones ?

                      1. 13

                        To answer how:

                        Accessing characters like "a"[0] was only added in ES5, originally you had to use "a".charAt(0).

                        If a browser does not support this way of accessing characters "a"[0] will be interpreted as trying to access a property with the name ‘0’ which does not exist on a string so it will evaluate to undefined.

                        To answer which ones:

                        Mostly older browsers that do not fully support ES5, I think IE took a really long time to support it.

                        1. 2

                          Thanks, I didn’t remember about the bracket access being added in ES5.

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

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

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

                                                    The article mentions a few old alternatives but not the more recent Zola which is very similar to Hugo but might have a more approachable templating language.

                                                    1. 5

                                                      The home page is clear on how smaller the files are but I’d like to see more about the costs (cpu, memory, code size) of encoding and decoding. Is there an article about that ? Does someone here have some answers ?

                                                      1. 4

                                                        Sounds pretty nice, but how well is this format supported?

                                                        1. 3

                                                          About not at all. No browser and no major tool apart ImageMagick.

                                                        1. 3

                                                          I’m trying for the 3rd time to learn Rust with the klabnik book and exercism.io’s exercises, and well, I really suck at it. Is it me or this language is really more difficult that it should be? My main languages are C, golang, php, python usually… I’m starting to believe I’m too old for learning.

                                                          1. 2

                                                            Is it me or this language is really more difficult that it should be?

                                                            More difficult that it should be is hard to answer. Some other attempts at new languages try to aim for easier to use concepts also ensuring the same safety but right now only rust can bring you both safety and performances.

                                                            Difficult ? Yes it is, especially if you learn rust at evenings while you spend your days on easier languages. But I think it’s worth it. If it’s any consolation: most developers found it really hard to learn until, progressively, it started to fall in place.

                                                            Suggestion: You should maybe start to use it without bothering learning it ? That’s what I did and I found it easier to learn by practicing and being corrected by the compiler (more usually the borrow checher).

                                                            1. 2

                                                              I had that same feeling of “Is it me or this language is really more difficult that it should be?” when I tried to learn Rust a few years ago. I see why a lot of people enjoy the language, but it wasn’t my cup of tea.

                                                              1. 2

                                                                Unfortunately it seems to take most people at least one time bouncing off of it, sometimes several as you have experienced… Rust’s type system borrows a lot of ideas from OCaml/F#, which are a pretty big change in the way of doing things from the language you’ve listed, so that might be one level of adjustment to get used to already. Then, between the type system, borrow checker, traits, iterators, generics, and so on there’s a lot of stuff going on in Rust, and most of it gets hidden by the type inference so that you don’t have to constantly bump into it. If you already know how it works.

                                                                What worked for me was two things: first, start by writing a program way simpler than you think you can handle; for me it was just Conway’s Life. Second, get in one of the various chat rooms of one kind or another, find the beginners channel, and ask for help as much as possible. A lot of Rust’s complexity is optional, but things like the standard library use a lot of it, so it’s common for new people to feel like they have to overdesign things.

                                                                1. 1

                                                                  I also tried, and “bounced” (even though I know many languages, and was very good at C++ some time ago). I tried the “start using it and learn as I go” approach, but got overwhelmed by nuance and kinda betrayed when trying to rely on error message hints, which showed up to be occasionally not working or self-contradictory (“You are doing A; maybe try B instead?”, then after doing B: “You are doing B; maybe try A instead?”). However I hope to try revisiting it in future, maybe more than once. I can’t count how many times I bounced off learning vim, but when I finally had to, I went on to love it. So, keeping fingers crossed for you!!!

                                                                  Also, one tutorial I found recently that I want to read, maybe you also will find it interesting, is about writing a roguelike game in Rust.

                                                                  1. 1

                                                                    I’ve been learning Rust too with the main book for about a month and a half, and it is a doozy. I have been doing every example in every chapter and tweaking to make sure I understand. That has helped. I started a project In Rust but I am realizing the value of working through the whole book, so I put that on hold for now.

                                                                  1. 8

                                                                    I didn’t understand the problem. Could someone explain?

                                                                    1. 4

                                                                      The problem is that some command line tools, like RipGrep, can have you typing out a command that is over 200 characters long. Having a small wrapper script for that can enable a lot of small gains, both in documenting how to use the tool, and making it less painful access more involved command parameters, since you don’t have to type them out so many times.

                                                                      This is a small productivity tip, not an earthshattering one, though I do find it moves some tools from “I use this occasionally” to “I can use this a lot more often”

                                                                      1. 1

                                                                        I still don’t get it. Competent shells support completion and some, like zsh, do fuzzy completion. It would be silly to manually type out 200 characters for a single command. You seem to be using windows though, so maybe this post is better tagged ‘windows’?

                                                                        1. 12

                                                                          No, I don’t think it’s specific to Windows (other than the fact that they are using batch scripts as their medium). Or 1995, for that matter, as another commenter cheekily suggested. I do this kind of thing all the time despite the fact that I use a “competent” shell (zsh with auto completions enabled). For example, just recently, I was hunting around trying to figure out how to grab an mp3 off a video off of YouTube. I do this very occasionally, so the command isn’t something I keep in my memory. So I just wrote youtube-dl-mp3.

                                                                          #!/bin/sh
                                                                          
                                                                          exec youtube-dl --extract-audio --audio-format mp3 "$@"
                                                                          

                                                                          The name means I’m likely to discover it when tab completing youtube-.

                                                                          1. 5

                                                                            Same for me. Shells make it easy to write small scripts that you can keep around like bookmarks. There’s no shame in finding it easier to remember/type the name of a short script you wrote for your need rather than remembering how a program works, even if it’s a well designed one.

                                                                            1. 3

                                                                              Now that I’ve picked it up as a pattern, I’d be more than keen on doing something similar on Linux when it makes sense to do so.

                                                                              1. 2

                                                                                I tend to do the same, except I keep these short scripts/commands in my notes rather than as standalone executable files (unless I need it often).

                                                                                1. 1

                                                                                  Speaking of “competent” shells, fish has abbreviations, so (e.g. in its example) gco can expand to git checkout. And functions and aliases (which also understand completion for the aliased command!) can be saved on-disk automatically. Fuzzy search also gives you the ability to just type mp3 and hit the up arrow until you get to this command in history.

                                                                                  Not to say “my favorite shell is better” - presumably zsh and other friends can do all of this too - just wanted to add other ways of doing this, for interested comment-readers.

                                                                                  1. 1

                                                                                    Nice yeah. If I’m understanding correctly, I believe my shell (zsh) has all of that too. Although it had to be configured. But it wasn’t too hard. Took about a day to set everything up.

                                                                                2. 3

                                                                                  This isn’t a Windows problem as much as a problem with people using cmd. It’s an antiquated shell that was never good to begin with. Now they refuse to use a modern shell like PowerShell. A more fitting tag would be “historical” and to reframe the article as “how we would do this we were in 1995”.

                                                                                  1. 4

                                                                                    It may sound funny to you, but I’ve actually started to warm up to using CMD a lot more. I’ve more or less had to use it, and batch scripts, at my current job, since we inherited a lot of code that uses batch scripts. One thing I like about CMD is is that it manages to be very low latency on Windows, where both PowerShell and mingw have a lot more latency around starting processes.

                                                                                    I realize this is a very different story on Linux and co, and there I usually end up using an alias or the like. But between this and and a jumplist, it makes working with CMD a whole lot less painful.

                                                                                    1. 1

                                                                                      Inheriting a lot of code is a valid reason to use the language, but I would still attempt to migrate to PowerShell if possible in that case as CMD is notorious for arcane incantations to accomplish things. It’s much easier to understand the program flow using PowerShell.

                                                                                      Regarding the startup time of PowerShell; I agree. It’s way too long to spin up a process when needed, but I just keep a terminal open at all times using ConEmu, so it’s always available at a hotkey.

                                                                                      Ultimately it’s up to you how you want to work. I just find CMD to be a difficult beast compared to POSH.

                                                                                      1. 2

                                                                                        So, when it gets to writing anythingore complicated than “start a program or two, maybe passing through some arguments”, then yeah, I prefer to write it in something other than batch. PowerShell works, currently I like Nim for that sort of thing.

                                                                                        This has proved a nice way to get quick responsiveness from a shell on Windows, and deal with complicated command invocations, without having to deal with the issues that mingw can have. As a bonus, you can get easy documentation for your uses cases of a particular command.

                                                                                    2. 1

                                                                                      What other systems use cmd apart from Windows?

                                                                                      (I realize DOS does)

                                                                                      1. 3

                                                                                        DOS uses COMMAND.COM, not CMD. CMD is used by ReactOS, OS/2, and Windows NT and later if I recall correctly. I get your point, but seriously using CMD is analogous to archaeology at this point…

                                                                              1. 2

                                                                                This solves a common issue I have on work machines, of deeply nested files and it being easy to lose context about file moves. The only thing I’m missing, is a way to drop the file path, relative to my current directory, of a file I select in broot. This may exist already, I just haven’t dug deep enough to find it yet.

                                                                                1. 2

                                                                                  Do you mean something like z?

                                                                                  1. 1

                                                                                    Similar yes, but combining the other capabilities of broot would be nice to utilize a single utility. Also, unlike z most of the time I don’t need to jump to the location of the file, but I need to do $something with it.

                                                                                  2. 1

                                                                                    What do you mean “drop the file path” ?

                                                                                    1. 2

                                                                                      Once I select (or focus) a file in broot and exit, it’d be nice if my current command line was populated with the relative path to the file I selected. For example

                                                                                      $ pwd
                                                                                      /home/kevin
                                                                                      $ br
                                                                                        [ selects file in broot with absolute path of /home/kevin/foo/bar/baz.txt ]
                                                                                      $ foo/bar/baz.txt
                                                                                      
                                                                                      1. 2

                                                                                        There’s a verb, :pp which outputs the absolute path. Just like with all verbs, you can define a shorcut (for example ctrl-p).

                                                                                        Does that solve your problem?

                                                                                        more on verbs: https://dystroy.org/broot/documentation/configuration/#verbs-shortcuts-and-keys

                                                                                        1. 1

                                                                                          I can make that work! Thanks! In a perfect world it’d place that path on the command line rather than just printing to stdout, but with something like xargs I can still work with this. Thanks for your work on broot!

                                                                                          1. 3

                                                                                            If you’re on zsh you can pop the path in with zle.

                                                                                            1. 2

                                                                                              I am. This is exactly what I was looking for, thanks!

                                                                                          2. 1

                                                                                            He’s asking for a way to get at just the relative path. In the example given, just foo/bar/baz.txt, and not the full /home/kevin/foo/bar/baz.txt.

                                                                                            1. 2

                                                                                              I could very easily add a verb for that, just like today’s :print_path, a :print_relative_path.

                                                                                              Please kbknapp post an issue or answer here if that’s what you want.

                                                                                    1. 8

                                                                                      broot author here. There’s also a discussion on HN but I’d be quite happy to answer questions here.

                                                                                      1. 4

                                                                                        Looks good. Some UX concerns:

                                                                                        • Behaviour of left and right arrow is completely unintuitive to me (I’d expect them to map to “go shallower” (parent dir) and “go deeper” (like Enter) respectively)
                                                                                          • I see that you commented elsewhere: “problem in using left and right arrow keys is that most people use them (even if rarely) for navigation inside the input field and broot always keeps this input file for filtering and commands” Perhaps one solution is to use left and right arrow for navigation when the input field is empty, and use them for cursor control when the input has contents.
                                                                                        • Esc in terminals often behaves such that the keystroke/keycode is not sent/executed until after a short delay (re: Alt, or Esc+key combos). Esc twice is often (always?) sent as one Esc keycode (in my experience)
                                                                                        • Backspace seems to be a workaround/alternate to Esc
                                                                                        • It’s surprising to me that Esc/Backspace from the original root(ish) dir causes broot to quit
                                                                                        • Having a fuzzy file find would be great, especially if you could use / to delimit dirs. e.g. searching for f/b/baz.rb would highlight ./foo/bar/baz.rb and ./fee/bur/baz.rb
                                                                                        1. 2

                                                                                          It’s surprising to me that Esc/Backspace from the original root(ish) dir causes broot to quit

                                                                                          I’ll probably change this. It’s mostly a remain of the initial version where I would very often just launch broot, stare at the tree, then quit having understood what the project looks like.

                                                                                          1. 2

                                                                                            Having a fuzzy file find would be great, especially if you could use / to delimit dirs. e.g. searching for f/b/baz.rb would highlight ./foo/bar/baz.rb and ./fee/bur/baz.rb

                                                                                            That’s a concern I have too. Not really an actual problem I have but there’s at least theoretically a weak point in the search. Still thinking about it.

                                                                                          2. 1

                                                                                            Could you answer this question? https://lobste.rs/s/ttsozh/broot_new_way_see_navigate_directory#c_ob4efc

                                                                                            Also, is there a way to make a no-color mode, and instead opt for just bold on matching text? My entire terminal setup is like this, where I don’t use colors anywhere, and opt for instead elegant spacing and bold text to achieve a clean, noise-free interface.

                                                                                            1. 4

                                                                                              You can configure your skin as you want, including colors, bold, italic: https://dystroy.org/broot/documentation/configuration/#colors

                                                                                          1. 3

                                                                                            I use fzf for directory and files traversal and ncdu for interactive disk usage. Broot takes a fantastic middle ground here. It would be cool if disk usage traversal was done using left and right arrow keys as are in ncdu. +1 for NixOS package.

                                                                                            1. 3

                                                                                              problem in using left and right arrow keys is that most people use them (even if rarely) for navigation inside the input field and broot always keeps this input file for filtering and commands

                                                                                            1. 16

                                                                                              I agree with the general thesis that data should be immutable by default. This is once of the things that I greatly appreciated in Haskell, coming imperative languages. However, I now like the approach of Rust’s borrows checker more. It permits easy mutability when necessary, often leading to more straightforward solutions and avoiding copying. But it resolves many of the problems with mutability in other languages. From the article:

                                                                                              If I pass my data to a function to have some computation performed, I expect that function to play nice and don’t change my data in the process. But if my data structures are mutable, how can I be sure they don’t?

                                                                                              Make functions take immutable references, e.g.:

                                                                                              fn frob(foo: &Foo) -> Bar
                                                                                              

                                                                                              However, if I actually want a function to modify a data structure, I do not have to jump through hoops:

                                                                                              fn frobber(foo: &mut Foo)
                                                                                              

                                                                                              What would happen if you had two threads operating on the same, shared data structure – one reading from it while the other mutates it? Best case scenario, your program blows up and execution stops.

                                                                                              This cannot happen in Rust, because the type system prevents mutable references to be shared between threads. The only way to permit mutation from different threads is to synchronize access. (This is all enforced through the Send and Sync traits.)

                                                                                              1. 8

                                                                                                Since I code in Rust, the whole “make data structures immutable” stance has suddenly been made empty to me.

                                                                                                Trying to make data structures immutable was a wrong take at the real problem.

                                                                                                1. 5

                                                                                                  IMHO total immutability makes sense in simpler, higher level and garbage-collected programming languages like Erlang or Elixir. Of course, immutability makes people life harder very often but it’s important to realize that a safe and concurrent immutable programming language don’t need a borrow checker and thus can be easier to learn.

                                                                                                  Also, this doesn’t work very well for some applications. In my experience immutability is really nice for the average web app (I mean a thing that queries databases and outputs HTML), but I would probably not choose Erlang for, let’s say, a video game.

                                                                                                2. 6

                                                                                                  I definitely have had a similar experience, but I feel like the key observation is that that the problem lies in limiting shared, mutable data. Most languages like Haskell, OCaml, Erlang etc. deals with it by limiting mutation of data. (Where did that idea start anyway, was it with original ML?) Rust does this too, but really deals with the problem more by limiting sharing of data. It’s a new and extremely powerful approach.

                                                                                                  That said, I feel like the old approach is still valid and useful at times. I spent a few weeks playing around with an Erlang/Akka-like actor system in Rust called axiom, and combining it with the im immutable data structure crate worked really, really well.

                                                                                                  1. 4

                                                                                                    I can highly recommend Bodil Stokkes Talk at RustFest Paris: https://www.youtube.com/watch?v=Gfe-JKn7G0I

                                                                                                    It goes into many reasons why immutable datastructures with structural sharing are useful beyond safety.

                                                                                                    1. 4

                                                                                                      I saw that talk live, it is great. That’s what inspired me to use im in the first place!

                                                                                                  2. 3

                                                                                                    Well, Rust is in a league of its own ;) I haven’t found the time to start learning Rust yet, but making concurrent programming safe with types sounds really interesting. It’s on my list of things to dive into, I just need to find time. Thanks for the input!

                                                                                                    I won’t start a big argue around immutable and mutable references, but the whole idea is that I want things to be immutable by default. If things are mutable by default, nothing more than conventions stops you from mutating, and that will eventually lead to errors. If things are immutable by default, you have to opt out of immutability, making it an explicit action. I am not necessarily against this, because as you say some situations demands a bit more pragmatism than pure immutability can provide.

                                                                                                    1. 9

                                                                                                      Just to sum it up, the stance of Rust is not that “mutability is evil” but “shared mutable access is evil”.

                                                                                                      1. 6

                                                                                                        I’m like a broken record on this board it would seem, but check out Idris. Way more powerful than even Haskell: your concurrent programms can to conform to arbitrary protocols that you write in the same language. Because types are first-class, they can be computed on the fly conditionally and used to statically confirm that several systems are coordinated in some complex way.

                                                                                                        1. 3

                                                                                                          Rust is absolutely immutable by default. If you want something to be mutable you have to mark it as such. However once you have marked it. Rust will then go a step further and ensure that no two threads can attempt to modify the mutable item at the same time. It also allows you to scope mutability to single functions or blocks which limits the number of code locations that something can be mutable.

                                                                                                      1. 2
                                                                                                        • Ubuntu because I’m too lazy to change
                                                                                                        • bash because I’m too lazy to change
                                                                                                        • terminator
                                                                                                        • neovim
                                                                                                        • chromium, chrome, firefox, brave
                                                                                                        • broot, ripgrep
                                                                                                        • thunderbird
                                                                                                        • IDEA (vi mode), unfortunately, because I still couldn’t remove java from my work
                                                                                                        • skype, unfortunately, because I’m remote and that’s the one which works with my colleagues
                                                                                                        • cargo
                                                                                                        1. 5

                                                                                                          I can’t remember who said it but I always liked the description of C as “universal assembly language”.

                                                                                                          I love C, I’d say 50% of the code I write is in C. The other 50% is in Python. I think, though I’m not sure, that it’s going to eventually be 50/50 Rust/Go. The future is coming.

                                                                                                          (Along with the occasional assembly language, of course. I’m interested to see what architectures we come up with as silicon real estate gets less expensive. Intel was banking on almost-operating-system-on-a-chip with iAPX 432, maybe we’ll get there eventually.)

                                                                                                          1. 5

                                                                                                            I can’t remember who said it but I always liked the description of C as “universal assembly language”.

                                                                                                            I’ve never really liked that, because it gives people some incredibly misguided ideas about how C works on modern compilers and CPU architectures.

                                                                                                            Essentially people naively assume that they can predict what C “naturally” compiles to, and claim this as an advantage of C, when in fact they’re just assuming they have a grasp of what the compiler and CPU are doing when both are frequently doing something else entirely that’s faster but happens to preserve the semantics.

                                                                                                            1. 7

                                                                                                              Look at Mr. I-Can-Afford-Something-Better-Than-A-PDP-11 over here.

                                                                                                              1. 1

                                                                                                                Hey, I’d love to be able to justify buying a working PDP-11. Found one for sale for about the price of a high-end laptop.

                                                                                                              2. 3

                                                                                                                Dont forget D, Nim, and Zig. Especially D given its maturity and compile speeds.

                                                                                                                1. 11

                                                                                                                  Don’t get me wrong, but I feel like D has been “almost there” for like 20 years now.

                                                                                                                  (Fun fact combining my love of computer science and the history of western religion: “Nim” was originally named “Nimrod”. Nimrod was “a mighty hunter before YHWH” (the tetragrammaton, there’s a lot to discuss there, along with the exact meaning of “before”) in Genesis. “Nimrod” became an insult in English when Bugs Bunny mockingly called Elmer Fudd “a mighty hunter” and a “Nimrod” in a cartoon in the 1950’s.)

                                                                                                                  1. 6

                                                                                                                    Re D. The licensing situation caused a lot of it. Now, they have a lot of features, a fast compiler, and a compiler for faster executable. Maybe it just needs a killer app or big company backing it.

                                                                                                                    Re Nim. I knew about Nimrod. I assumed the negative connotations were why they changed the name. I never checked, though.

                                                                                                                    1. 8

                                                                                                                      The licensing situation caused a lot of it.

                                                                                                                      RIP REBOL

                                                                                                                      1. 7

                                                                                                                        RIP REBOL

                                                                                                                        Fortunately, there is the Red programming language

                                                                                                                2. 2

                                                                                                                  I think, though I’m not sure, that it’s going to eventually be 50/50 Rust/Go

                                                                                                                  Both languages make a lot of sense and I can imagine smart companies having this kind of mix (with some JS or python added, probably). But it looks like a strange mix for a person in my opinion.

                                                                                                                  If you manage to maintain the ability and mindset to efficiently code in Rust (which is a real burden), is there really a reason to write anything in Go ? I don’t see one but I’d welcome your argument.

                                                                                                                  1. 1

                                                                                                                    If you manage to maintain the ability and mindset to efficiently code in Rust (which is a real burden), is there really a reason to write anything in Go ? I don’t see one but I’d welcome your argument.

                                                                                                                    Perhaps you are hoping for contributors who haven’t learned to live with the borrow checker. Perhaps your program is fairly simple, and you want to distribute cross-platform binaries (for cross-compilation, rust is better than C, but light years behind go)

                                                                                                                    1. 1

                                                                                                                      Depends on how well one knows/likes Go, really. I’m not good enough at it to think of it as replacing Python for quick-and-incremental tasks, but I could see where others might.

                                                                                                                    2. 1

                                                                                                                      I’d say 50% of the code I write is in C. The other 50% is in Python.

                                                                                                                      For me it’s 50% C and 50% Go. I like working with types too much.

                                                                                                                    1. 5

                                                                                                                      We know we have a problem with how fuzzy “systems programming” is defined and it’s only getting worse here.

                                                                                                                      Triplett broadly defines systems programming as “anything that isn’t an app.” It includes things like BIOS, firmware, boot loaders, operating systems kernels, embedded and similar types of low-level code, virtual machine implementations. Triplett also counts a web browser as a system software as it is more than “just an app,” they are actually “platforms for websites and web apps,” he says.

                                                                                                                      Browsers ? Then what about databases ? Libraries ? Frameworks ? Most of what people here are coding isn’t a final and complete user facing application. Is docker (notably written in go) systems programming ?

                                                                                                                      It seems we put in “systems programming” all the serious programming where consistent performances and reliability matter. Isn’t it time to drop or fix that notion ?

                                                                                                                      1. 4

                                                                                                                        It seems we put in “systems programming” all the serious programming where consistent performances and reliability matter.

                                                                                                                        Yep. This fuzziness caused problems for Go. The team making Go thought that “systems programming” meant building large, interconnected systems - i.e. distributed systems of servers. So they called Go a “systems programming” language. Then everyone complained at them for making it garbage collected. But garbage collection (especially a nice, low-latency GC) is a sensible choice for the sort of server programming that Go targets. Now they call Go the language of “cloud computing” (to which Rob Pike always adds, “What we used to call servers”) to try to avoid this confusion.

                                                                                                                        “Systems programming” always seems to mean, “The sort of programming that requires the features in my favorite language”.

                                                                                                                        1. 4

                                                                                                                          The type of garbage collection is important, too. Any type of garbage-collection is sensible for throughput oriented server programs. But for latency-oriented ones, you want incremental, small pause GCs. Otherwise, your tail-latency will be pretty bad. At work, we rewrote one of our servers from Java to C++ just for this issue.

                                                                                                                          1. 2

                                                                                                                            Absolutely! There are some low-latency GCs for the JVM too - Azul do a lot of that work - but Go is particularly good here. This is quite a nice talk about it: https://blog.golang.org/ismmkeynote

                                                                                                                            1. 2

                                                                                                                              Very apt observation. I am becoming increasingly aware that a lot of the patterns Rust programs use for situations where the borrow checker don’t cut it amount to runtime checking for memory safety. Tracing GC is just one way to do that runtime checking, with its own set of tradeoffs.

                                                                                                                        1. 1

                                                                                                                          Damn. I really did learn something. Most of us probably know some of them but there’s real lesser known content here, congrats.

                                                                                                                          1. 2

                                                                                                                            How are you picking up the next entries in your blog ? Are you taking suggestions ?

                                                                                                                            If so, may I hint about a tool that I’d like to have a little more exposed (I don’t think there’s been blog entries about it yet)? broot

                                                                                                                            Of course, as the author, I’m available for clarifications and discussions.

                                                                                                                            1. 2

                                                                                                                              Right now I’m picking new entries for the blog by looking through my ~/bin folder and trawling github. However this thread has given me a few new sites to look through for inspiration, and lobsters has shown me many tools from show tags in the past.

                                                                                                                              broot is already in my backlog actually! I have been using it on my personal machine since you posted it here a month or so ago. I appreciated your quick attention to the feature request I raised there too.

                                                                                                                            1. 16

                                                                                                                              I still don’t understand the backlash against “generics” (i.e. parametric polymorphism). If you’ve ever programmed in a dynamic language, then much of the code you’ve written in that language is generic, e.g. len() in python.

                                                                                                                              “generics” is just a language feature to bring this flexibility to statically-typed languages. What is complicated about this? Writing val length : 'a list -> int is simpler than writing val length_of_int_list : int list -> int and val length_of_string_list : string list -> int.

                                                                                                                              1. 20

                                                                                                                                My guess is that you probably haven’t used Go. In particular, len is actually polymorphic in Go, but only because it’s a builtin function. Go does have interfaces, which provide some limited ability to write generic code. The famous thing that they don’t support well are generic type safe data structures. But they can sometimes support generic algorithms, for example, sorting.

                                                                                                                                Either way, if you really, truly, don’t understand the backlash against generics and you want to, then there are a number of things out there explaining the draw backs. Russ Cox kind of kicked it all off with this blog post. You might reject his argument, which is fair, but you might at least understand it. ;-)

                                                                                                                                If you keep searching, folks (like Ian Lance Taylor) have made some fairly involved proposals for adding generics to the language, and IIRC, they include reasons why they didn’t move forward. See here for a starting point. Note the links at the bottom.

                                                                                                                                1. 6

                                                                                                                                  Oh, I didn’t understand it was a performance concern. My only Go experience was writing a fairly simple command line app. If the core team doesn’t accept a particular tradeoff between static and dynamic method dispatch, how did interfaces become part of the language?

                                                                                                                                  One option is to provide for both static and dynamic dispatch as language-level features, like Rust.

                                                                                                                                  1. 6

                                                                                                                                    I found the relevant portion from the generics proposal for you:

                                                                                                                                    Polymorphism in Go should be implementable both at compile time (by repeated specialized compilation, as in C++) and at run time, so that the decision about implementation strategy can be left as a decision for the compiler and treated like any other compiler optimization. This flexibility would address the generic dilemma we’ve discussed in the past.

                                                                                                                                    In other words, under this proposal, you wouldn’t get static vs dynamic dispatch as a language feature. Rather, it would be an implementation detail.

                                                                                                                                    1. 5

                                                                                                                                      One option is to provide for both static and dynamic dispatch as language-level features, like Rust.

                                                                                                                                      Yes. Read the Go 2 generics proposals for more on that point. (You may not like what you find.)

                                                                                                                                    2. 0

                                                                                                                                      Either way, if you really, truly, don’t understand the backlash against generics and you want to, then there are a number of things out there explaining the draw backs. Russ Cox kind of kicked it all off with this blog post. You might reject his argument, which is fair, but you might at least understand it.

                                                                                                                                      All he mentions is C++. I don’t think there’s any effort to benchmark generics, and I don’t think the algorithms involved in typechecking them are pathological. I really don’t see any fundamental problems with them, just complaints about C++ and C++ compilers.

                                                                                                                                      1. 6

                                                                                                                                        I provided other links. Go read them instead of trying to rehash everything with me, which I am absolutely not interested in doing because I don’t think you’re commenting in good faith.

                                                                                                                                    3. 9

                                                                                                                                      Generics bring complexity. People tend to over-abstract their code and to make it a lot less readable.

                                                                                                                                      1. 13

                                                                                                                                        Not using the right abstraction can also make your code harder to follow.

                                                                                                                                        In any case, not having a feature and then pretending that you only didn’t include the feature because of “bad” or “ivory tower” programmers is ridiculous and we can all see through the bullshit.

                                                                                                                                        1. 7

                                                                                                                                          No, it really is a feature. I can’t pretend I like it, because I’d rather have generics in Go, but I understand it and I’ll try to explain it:

                                                                                                                                          Go is designed around simplicity. Its whole design (minus the null pointer problem) helps you make simple, obvious and reliable codes. You don’t think much: you just build the thing the simple way. And reading the code of fellow programmers is easy too. You lose some power or elegance because of that but the programming flow is uninterrupted and remarkably quiet.

                                                                                                                                          Go is ideal for big teams because of that. You don’t have to dive into tricky modules and bugs are rarer and simpler than in most languages (with the possible exception of some concurrency problems).

                                                                                                                                          Not all languages share the same goal.

                                                                                                                                        2. 2

                                                                                                                                          This argument proves too much. Substitute generics<->functions.

                                                                                                                                        3. -1

                                                                                                                                          “Generics” in this context means C-style templates. You don’t need those in dynamic languages because you have a base class. You don’t need them in statically typed languages either where you can add a base class, but that’s not the world of C++ or Java.

                                                                                                                                          1. 1

                                                                                                                                            I’m not sure it has to do with inheritance. Dynamic languages allow for parametric polymorphism because values are boxed, and type errors are caught at runtime; you can write a function to append two lists, and as long you treat each element as a generic value (e.g not calling list_item.assumed_field), you’ve engaged in generic programming.

                                                                                                                                        1. 17

                                                                                                                                          There are only two real deficiencies with JSON, IMHO:

                                                                                                                                          • No standardized method of commenting
                                                                                                                                          • No multiline strings

                                                                                                                                          There are other problems, of course: no standardized date format, no standardized mechanism for including arbitrary binary data, no hexadecimal notation, etc….but really the two things mentioned above are the only true problems it has.

                                                                                                                                          (Again, IMHO.)

                                                                                                                                          1. 36

                                                                                                                                            I would argue failure to support a trailing comma is a serious defect in any format expected to support the addition of elements over time.

                                                                                                                                            To clarify, that’s maybe not a defect in json per se. If it’s just a serialization format, fine, whatever. But for the use case of tracking dependencies, configurations, etc., it’s bad. Choosing to use json for this is a defect.

                                                                                                                                            1. 7

                                                                                                                                              EDN’s use of whitespace as element seperators, is better than commas. https://learnxinyminutes.com/docs/edn/

                                                                                                                                              1. 6

                                                                                                                                                I heard an anecdote from someone who had to make a streaming json parser, and its performance was significantly hampered because it had to check for the trailing comma.

                                                                                                                                                1. 2

                                                                                                                                                  I have a “counter-dote”. https://github.com/stig/json-framework/blob/master/Classes/SBJson5StreamParserState.m implements a state machine for a streaming JSON parser that is not impaired at all by checking for trailing commas.

                                                                                                                                                  Admittedly I remember struggling with handling the trailing comma issue previous versions, before I adopted the state machine. Also, my parser is not the most performant—even for Objective-C.

                                                                                                                                                2. 2

                                                                                                                                                  Lack of trailing commas is also one of the things that irks me most about SQL…

                                                                                                                                                  1. 5

                                                                                                                                                    haha, so I was even going to suggest sql as an alternative to json for configs. Create an in memory sqlite database, then .load and .dump. What could be better than the ability to query your config? And it plays nice with version control because every line ends with a semicolon, not just some of them.

                                                                                                                                                    PRAGMA foreign_keys=OFF;
                                                                                                                                                    BEGIN TRANSACTION;
                                                                                                                                                    CREATE TABLE depends (name, version);
                                                                                                                                                    INSERT INTO depends VALUES('foo',7);
                                                                                                                                                    INSERT INTO depends VALUES('bar',3);
                                                                                                                                                    COMMIT;
                                                                                                                                                    

                                                                                                                                                    Plus you get atomic updates, rollback, etc. when doing a hot reload. Awesome, right? :)

                                                                                                                                                    1. 5

                                                                                                                                                      Yeah but as someone who deals with code or system configs first, and databases as an afterthought, SQL just seems so flimsy. Database setup is imperative more than declarative. Data insertion is the same. And the actual data types are terribly weak unless you go through a lot of work trying to enforce invariants.

                                                                                                                                                      I do know a lot of this is my own bias, because there seems a fairly large cognitive gap between “functional programming first” programmers such as myself where functions and structures come first and composing them should be easy, and “database-first” DBAs like some of my friends where sets of structures come first, functions seem a special case, and composition seems to have different rules… But it’s a hard gap for me to cross.

                                                                                                                                                      1. 4

                                                                                                                                                        And the actual data types are terribly weak unless you go through a lot of work trying to enforce invariants.

                                                                                                                                                        This is one point that I disagree with. If you’re primarily working with MySQL or SQLite, I guess it may be true, or if you’re thinking about SQL databases as filtered through a “least common denominator” database library, but types are pretty robust in most databases.

                                                                                                                                                        1. 2

                                                                                                                                                          SQL Server/TSQL is also strongly typed.

                                                                                                                                                          1. 1

                                                                                                                                                            Yeah, it’s things like that which find me always reaching for postgres over MySQL. <3

                                                                                                                                                            As I said, part of the problem is mine… I’m not actually very good with databases and so I tend to solve everything the most complicated and brute-force way. I’m trying to improve though, bit by bit.

                                                                                                                                                          2. 1

                                                                                                                                                            If you haven’t read The Third Manifesto you should. Made me fall in love with the relational model all over again

                                                                                                                                                          3. 1

                                                                                                                                                            Kinda like what slapd does, but I must say I’m not very fond of configuring it that way.

                                                                                                                                                      2. 15

                                                                                                                                                        Also it doesn’t let you round trip numbers correctly.

                                                                                                                                                        EDIT: To elaborate, you can’t store +/-Inf or Nan to them.

                                                                                                                                                        1. 6

                                                                                                                                                          This shortcoming is so important when you deal with complex number crushing applications that many libs add them, for example Google’s Gson. I even made a library to parse those numbers client-side (JSON.parseMore, this approach having the disadvantage that it isn’t as heavily optimized as the native JSON.parse of the most modern browsers, which is also, btw, why you can’t easily replace JSON by other formats like messagepack which would otherwise be faster to parse).

                                                                                                                                                          1. 2

                                                                                                                                                            With regards to parsing performance, an interesting approach is to piggyback on those highly optimized parsers. For example, the Transit format provides a richer set of builtin types and an extension mechanism (pretty much equivalent to EDN) but is encoded as JSON or MsgPack while in transit (I guess that’s the reason for the name). That way, serialization and deserialization profit from the host format’s optimized parser implementations.

                                                                                                                                                            1. 1

                                                                                                                                                              Transit is just a hack to enable use of native-code JSON parser for browser applications, because parsing EDN might be too slow with parser written in js.

                                                                                                                                                              It’s not even human-readable and of course is absolutely unusable for configs. We’re using it for React Native and I have to convert it to EDN every time I want to debug some output :(

                                                                                                                                                        2. 9

                                                                                                                                                          JSON5 addresses a lot of these issues.

                                                                                                                                                          1. 6

                                                                                                                                                            Ren has literals for most common types (dates, IP addresses, URLs, emails) built-in.

                                                                                                                                                            Another interesting approach, that is far more powerful (while still keeping it sane) is Dhall.

                                                                                                                                                            1. 2

                                                                                                                                                              Ren looks a lottle like REBOL, which is neat to me.

                                                                                                                                                              Dhall looks cool.

                                                                                                                                                              1. 6

                                                                                                                                                                Ren looks a lottle like REBOL, which is neat to me.

                                                                                                                                                                Oh, well, because it is to REBOL what JSON is to JavaScript :)

                                                                                                                                                                Dhall looks cool.

                                                                                                                                                                I’ve never personally used it extensively but I’ve heard people using it to also handle configuration updates (e.g. a Dhall function changing old config into new config) that are type-checked. Dhall functions are powerful but without Turing-completeness. In other words JSON and TOML are just variations on syntax preferences but ultimately they’re like each other, Dhall is something else.

                                                                                                                                                              2. 1

                                                                                                                                                                Dhall allow external url which looks like crazy from security standpoint

                                                                                                                                                                1. 1

                                                                                                                                                                  Yep, but you can add content digest to the URL (SHA sum).

                                                                                                                                                                  1. 1

                                                                                                                                                                    it is not by default, as such will not be always used and eventually become a security hole

                                                                                                                                                              3. 4

                                                                                                                                                                I do like hjson as an alternative to json nowadays. When I used toml with Cargo/rust, It seriously cost me some time to understand what “data structure” the toml file would be parsed into. I guess I still don’t firmly understand it.

                                                                                                                                                                1. 1
                                                                                                                                                                  • No streaming capability
                                                                                                                                                                  • No efficient encoding
                                                                                                                                                                  • Requires quotes escaping in strings (and consequently to parse every byte in every string to find a terminator)
                                                                                                                                                                  • No ability to skip ahead during decoding
                                                                                                                                                                  • No ability to store raw data

                                                                                                                                                                  People invented TLV for a reason https://en.wikipedia.org/wiki/Type-length-value

                                                                                                                                                                  ASN.1 DER: https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One#Example

                                                                                                                                                                  1. 1

                                                                                                                                                                    Since others have mentioned some alternatives, there’s always Lua. I use Lua as a configuration file format both for personal projects and for work. Comments, multi-line strings, ability to call functions (like the example one calling os.setlocale()) and trailing commas. Oh, don’t like commas? Replace them with semicolons if you wish.