1. 90

      In light of all of these problems, I’ll take my segfaults and buffer overflows

      but I won’t take your buffer overflows. I have spent enough time with emergency security patching RCEs left by C programmers who were “good enough” not to need a memory-safe language.

      1. 9

        “I have the best taxi service in town because my car is so fast! Yeah, it has no seat belts, but don’t worry — I’m a very safe driver.”

        1. 1

          This is a beautiful way to put that.

        2. 7

          I was thinking about this actually. I was pretty sure that those were security issues rather than just annoying. Maybe he doesn’t mean for the finished product? I hope that’s what he means.

          1. 3

            I’m sure he meant that, but it is still very unlikely that he or anyone else will iron out all segfaults and buffer overflows.

          2. -9

            So since PHP is memory-safe, it’s a good C replacement?

            1. 23

              Yes, if you have to choose between C and PHP, and both can do the job, you definitely should choose PHP, no question. The problem is that PHP often can’t do the job.

              1. 17

                That’s a very uncharitable interpretation. Brainfuck is also memory safe and is obviously not a good C replacement - obviously the only requirement isn’t memory safety.

                1. 3

                  Yes. I chose PHP because it’s an extreme case.

                  The point is: yes, Rust is safe, but the article explains why (besides memory safety) Rust isn’t a good C replacement. In other words: there are other programming languages that are better suited than Rust to replace C.

                  1. 5

                    I think everyone get’s your point, but it’s banal noise that pollutes the discussion, hence the downvotes, which are actually pretty rare here.

            1. 4

              C: 0.73 new features per year, measured by the number of bullet points in the C11 article on Wikipedia which summarizes the changes from C99, adjusted to account for the fact that C18 introduced no new features.

              adjusted to account for the fact that C18 introduced no new features.

              And that is why I love C. Yes, it has its problems (of which there are many), but it’s a much smaller, bounded set of problems. The devil I know. Many other languages are so large, I couldn’t even know all of the devils if I tried.

              1. 25

                The devil I know

                if the devil you know is an omnipotent being of unlimited power that generations of warriors have tried to fight and never succeeded because it’s just too powerful, then I would argue that it might be worth trying to chose a different evil to fight.

                Even in 2019 70% of security vulnerabilities are caused by memory-safety issues that would just not happen if the world wasn’t running on languages without memory-safety.

                1. 1

                  I don’t think being memory safe is enough for a programming language to be a good C replacement.

                  1. 18

                    No. It’s not enough. But IMHO it’s required.

                    1. 4

                      … a requirement that C, incidentally, does not fulfil. Now that memory-safe low-level languages have swum into our ken, C is no longer a good C replacement. ;-)


                      Edited to add a wink. I meant this no more seriously than pub talk – though I believe it has a kernel of truth, I phrased it that way mainly because it was fun to phrase it that way. There are many good reasons to use C, and and I also appreciate those. (And acknowledge that the joke does not acknowledge them.)

                      1. 3

                        that is my point.

                        1. 2

                          Hi, sorry, I spent a lot of time on my edit – everything below the line plus the smiley above it wasn’t there when you replied. Sorry to readers for making this look confusing.

                          It is indeed your point, and I agree with it.

                    2. 6

                      Nobody is arguing that it’s sufficient, but it is necessary.

                      If I were to develop a new language today, a language that was as unsafe as C but had lots of shiny new features like ADTs and a nice package manager and stuff, I’d never get traction. It would be ridiculous.

                      1. 1

                        I don’t know. PHP and C are still pretty popular. You just target those markets with selective enhancements of a language that fits their style closely. ;)

                    3. 1

                      Doesn’t web assembly allow unchanged C to be memory safe?

                      1. 2

                        Sort of, but not really. Unmanaged C isn’t allowed to escape the sandbox it’s assigned but there is still plenty of opportunities for undefined behavior. Process-level isolation in OSes provide similar guarantees. In the context of WebAssembly, even if the TLS stack were segregated into its own module it would do nothing to mitigate a Heartbleed-style vulnerability.

                        1. 2

                          There are other environments where the C standard is vague enough to allow for C to compile to a managed and safe environment. As the local AS/400 expert, C there compiles to managed bytecode, which is then compiled again by a trusted translator.

                          1. 1

                            I try to keep up with folks’ skills in case opportunities arise. Do you know both AS/400 and z/OS? Or just AS/400?

                            Also interested in you elaborating on it making C safer.

                            1. 3

                              No, z is a separate thing I don’t know much about.

                              Because C on AS/400 (or i, whatever IBM marketing calls it this week) is managed code, it does things like checking the validity of pointers to prevent things like buffer overflows. It does that by injecting hardware-enforced tagging. To prevent you from cheating it, the trusted translator is the only program allowed to generate native code. (AIX programs in the syscall emulator, however, can generate native code, but are then subject to normal Unix process boundaries and a kernel very paranoid about code running in a sandbox.) The tags are also used as capabilities to objects in the same address space, which it uses in place of a traditional filesystem.

                              1. 1

                                Thanks. That makes sense except for one thing: hardware-enforced tagging. I thought System/38’s hardware enforcement was taken out with things just type- or runtime-checked or something at firmware/software level. That’s at least how some folks were talking. Do you have any references that show what hardware checking the current systems use?

                                1. 1

                                  No, tags and capabilities are still there, contrary to rumours otherwise.

                                  The tagging apparatus on modern systems are undocumented and as a result I know little about them, but it’s definitely in the CPU, from what I’ve heard.

                                  1. 1

                                    Ok. So, I guess I gotta press POWER CPU experts at some point to figure it out or just look at the ISA references. Least I know there wasn’t something obvious I overlooked.

                                    EDIT: Just downloaded and searched the POWER ISA 3 PDF for capabilities and pointer to see what showed up. Nothing about this. They’re either wrong or it’s undocumented as they told you. If it’s still there, that’s a solid reason for building critical services on top of IBM i’s even if commodity stuff had same reliability. Security be higher. Still gotta harden them, of course.

                      2. 1

                        Sort of. It had a much larger set of problems than safe, system languages that compete with it. There’s less to know with them unless you choose to dance with the devil in a specific module. Some were more productive with faster debugging, too. So, it seems like C programmers force themselves to know and do more unnecessarily at least on language level.

                        Now, pragmatically, the ecosystem is so large and mature that using or at least outputing C might make sense in a lot of projects.

                      1. 4

                        Nvidia users

                        All proprietary graphics drivers are unsupported. This includes the Nvidia proprietary driver. The open source Nouveau driver is required instead. This is not going to change, don’t ask. Tip: buy your hardware with open source support in mind.

                        https://www.youtube.com/watch?v=iYWzMvlj2RQ

                          1. 1

                            The nouveau driver is utterly unusable in other DEs, at least on my hardware, does Sway make that not be the case?

                            https://bugs.launchpad.net/ubuntu/+source/gdm3/+bug/1796614 https://bugs.launchpad.net/ubuntu/+source/mutter/+bug/1796614

                            (Yes these were for Gnome 3, which was a total tire fire on my Alienware 17 R5. I’ve switched to KDE and love it. Last time I tried to run Sway it would have required a full build with all dependencies from source - not a small undertaking for a casual test attempt.)

                            1. 2

                              Yes, sway is less resource-intensive than, say, GNOME. However Nouveau is known not to work too well on some graphics card (please help them!), and sway can’t do a lot about this. That said, if KDE works, sway will probably work fine too.

                              1. 2

                                Would that I could.

                                When I filed those bugs, I actually tried pulling up the source code and wrapping my head around what was going on to offer assistance or even aid in debugging, but device drivers are an incredibly context heavy beast, and I just couldn’t do it.

                                Also, my C is about 20 years rusty.

                          1. 14

                            I like the design aesthetic well enough, but I often find it difficult to navigate between components of a given project. It really does feel like each part of the site is completely separate from the other. I assume design/UI/UX is reflecting architecture here?

                            For example, when I am on a git repo page, how do I get to the list archive or the tasks page for the same project? I have resorted to “manual url editing” to date, but every time I have to do that it tends to detract from the experience.

                            Example:

                            1. go here: https://git.sr.ht/~sircmpwn/scdoc
                            2. hover over lists and builds in the nav bar – realize those don’t do what you want. eyes roam around the page.
                            3. give up and edit the url bar and replace git with todo. yay. found the bugtracker. https://todo.sr.ht/~sircmpwn/scdoc
                            4. Edit url bar to see if there is a mailing list. replace todo with lists. Hmm. There isn’t one?
                            5. Remember something on the git page, so go back to it. Find a link in the bottom to public inbox, but that link is a mailto link (just part of the readme). It actually refers to a different list than expected.
                            6. Edit url bar to try to reconstruct the mailing list url based on the mailto link. http://lists.sr.ht/~sircmpwn/public-inbox
                            7. success! found the mailing list.
                            1. 3

                              Agreed, I was just annoyed by that this weekend. It would be nice if there were a higher level project abstraction to tie things together. Links in the README are an okay substitute, but require manual setup and are easily forgotten.

                              It’d also be nice if the “Create repo” page had options to create a bug tracker and mailing list automatically.

                              1. 4

                                This might not be as simple as one could think, as the sourcehut design is built on modularity: sr.ht might host all sourcehut services, but my understanding is that it might not always be the case, as sourcehut is a a-la-carte service.

                              2. 3

                                Yes, that’s a valid criticism. IIRC improvements to ease navigation between modules of the same project are planned. Soon™!

                              1. 7

                                git commit --amend is pretty handy to edit the last commit

                                1. 1

                                  I’ve got a similar alias to fix mistakes in the last commit using the same commit message:

                                  fixup = commit --amend -C HEAD
                                  
                                  1. 2

                                    In Mercurial, this is just hg amend or hg am (all Mercurial commands can be abbreviated to their shortest unique prefix). If you do want to edit the commit message, it’s hg amend --edit.

                                1. 2

                                  With much respect for Drew, who does amazing work with Sway - this is precisely the kind of thinking that keeps Linux on the desktop a fringe market with (in the grand scheme) very limited appeal.

                                  AMD has made great strides of late, but Nvidia still owns a very sizable portion of the market.

                                  Yes, everyone hates that Nvidia isn’t AMD and doesn’t open source their drivers, forcing LInux folks to interoperate with an ABI.

                                  Can we please, pretty please with sugar on top, get over ourselves for just a moment and recognize that for the teeming droves of PC owners with Nvidia hardware want to enjoy running Linux and have made the choice that utilizing a proprietary binary blob is a reasonable trade-off to make. Why not honor that choice?

                                  1. 2

                                    The main issue with the proprietary driver is that it’s using its own special EGLStreams API, whereas all other drivers use GBM.

                                    1. 3

                                      From the outside, this feels like a confusing mess.

                                      GBM has become the defacto standard for Wayland it would seem, but EGLStreams seems like a bona-fide specification.

                                      Do we have any sense of why it’s important enough for Nvidia to fight this fight and why someone can’t just write an abstraction layer that makes one talk to the other or some such and keep everybody happy?

                                  1. 4

                                    I agree somewhat with the conclusion, but not the argument.

                                    Ok, there’s no free software implementation to verify against - but so what? If it breaks, it breaks; It’s then on NVidia, or someone else who cares, to fix it. You could easily continue development with the general contract that you don’t have to test the EGLStreams support and, while I understand that developers will generally feel uneasy about the possibility that they are breaking things without being able to verify that they aren’t, it wouldn’t be that hard a pill to swallow. You’d quickly find out if the code was going to be properly maintained and if it wasn’t, you could rip it right back out. Then, the main argument is only that you’re likely wasting effort because you don’t think it will be maintained, but the fact that the code is submitted in the first place is somewhat evidence that someone cares enough that this code works.

                                    In my view, a much better technical argument is that supporting two different APIs, one of which is single-vendor, is a maintenance burden regardless of whether you have to test it - since you will still compile it regardless, and changes may break compilation due to the EGLStreams component, which then has to be resolved. In particular, this makes general changes to a higher level abstraction (which presumably exists as a layer over the two underlying implementations ie. EGLStreams and GBM) more costly.

                                    (I don’t know enough about the two APIs to make a technical judgement regarding which is better, but when it appears that neither API can be implemented in terms of the other I worry that they are both flawed).

                                    On the political side: I don’t think trying to force NVidia to use an API that they have persistently insisted is not suitable is really being on the right side of the argument. It’s reasonable to not expend effort supporting a proprietary API, but not to refuse to allow the vendor to provide their own support for that API. And if that, or part of it, comes in the form of closed source software, let the people who feel strongly enough about it choose the competitor who has the more open alternative (and let the problems caused by closed source components cause the frustration that they do; that’s the choice of the user). Would I (personally) prefer that NVidia release and support open-source drivers? Yes I would, but only because I’d rather have more options for hardware with open drivers, not because I begrudge NVidia their choice of providing closed drivers. The latter I solve easily by buying only AMD graphics cards (or using integrated Intel graphics. And yes there may be a few other options).

                                    And it’s all very well to offer to buy a competitor’s graphics card for “anyone who works on Linux graphics” but that is pretty meaningless for regular consumers who just want the graphics card that they bought to work as it should. If on some level NVidia seem to be trying to take steps to make that be the case then I don’t see why they should be discouraged.

                                    Ultimately, that leaves the maintenance burden issue, and I think that could easily be argued is a sufficient reason not to merge the code. But I personally think it’s the only valid reason, in this case.

                                    1. 4

                                      This. The wlroots people have an extreme stance against merging patches that they themselves won’t maintain / patches that could become dead code. I really don’t agree with them on that. Merge all the things, delete later if it’s abandoned by the original author. Linux merged the AMD Display Core after all, and no one outside of AMD is going to maintain it, and it’s fine. And here, it’s a much simpler, tiny patch.

                                      The conclusion… well… so there’s two goals – pressuring Nvidia into being a real open source citizen and making Wayland widely adopted. Pretty much everyone would like both to happen, but which to prioritize? I’m leaning towards the latter. I think getting desktop users off Xorg ASAP might be more important after all.

                                      1. 2

                                        Merge all the things, delete later if it’s abandoned by the original author.

                                        Even if it works for Linux, it might not work well for other projects like wlroots.

                                        First, Linux is a much older project, wlroots has much more breaking changes. Second, having code you don’t maintain in your tree makes it impossible to refactor code (or very expensive). Third, this code can prevent new features from being added. For instance, it’s not clear how EGLStreams can work with multi-GPU, direct scan-out and efficient screen capture.

                                        pressuring Nvidia into being a real open source citizen and making Wayland widely adopted

                                        I personally think it’s better to have a sane ecosystem. There will always be X11 users, it’s not harmful. Users should stay on X11 if they don’t want to switch to Wayland.

                                        1. 2

                                          having code you don’t maintain in your tree makes it impossible to refactor code (or very expensive)

                                          Not necessarily. If you have a well defined stable interface, and someone adds an implementation of that interface, it’s not going to be a huge problem.

                                          KWin is written in C++ and it seems like they have already planned for GBM alternatives — there was an abstract base class for various backends, right?

                                          can prevent new features from being added

                                          Usually not a big problem to only add features supported on one backend and not another one.

                                          Users should stay on X11 if they don’t want to switch to Wayland

                                          Sure, but

                                          • many do want, but nvidia + compositor authors made the choice for them
                                          • most casual users don’t care about protocols (but do care about the benefits like proper HiDPI and zero tearing) and the distro maintainers made the choice for them
                                          1. 1

                                            If you have a well defined stable interface, and someone adds an implementation of that interface, it’s not going to be a huge problem.

                                            If this were the case, how would there be any benefit to merging the implementation?

                                            1. 1

                                              Not like an external interface. They have an abstract class it seems.

                                              1. 1

                                                So either:

                                                • The interface of the abstract class is considered stable, in which case it could be exposed as an external interface and the NVidia implementation could remain external.
                                                • The interface of the abstract class is considered experimental, and will want to evolve as development continues, in which case having a bunch of untestable code tied to it is a burden on anyone trying to change it.
                                                1. 1

                                                  I think that’s a bit of a false dichotomy. The interface might be mostly stable - enough so that major changes aren’t expected and that ongoing development should be minimally impacted, but not necessarily enough that no minor changes will need to be made to implementations. Undoubtedly there will be some maintenance cost from incorporating a second implementation, but if that reduces overall development burden across what would otherwise be two separate trees, and if the functionality added is worth the cost - then incorporation seems the clear choice. (I’m not convinced this is necessarily the case here, as I noted above).

                                                  1. 1

                                                    I agree that there is some middle ground between the two in terms of interface stability, but somewhere you have to draw a line between merging vs. the implementation remaining external.

                                                    As long as changes to the interface are minor, it shouldn’t be difficult for the external implementation stay in sync, such that you rarely or never get an actual release where it doesn’t work.

                                                    The main benefit to having the implementation merged would be that developers could check their changes don’t break things, or fix minor breakages as they go. If the code isn’t testable, that benefit isn’t really there.

                                                    The problem with trying to reduce the ‘overall development burden’ in this way is that in doing so you shift some of the burden from a multi-billion dollar company to a much smaller group, many of whom are volunteers.

                                      2. 3

                                        If it breaks, it breaks; It’s then on NVidia, or someone else who cares, to fix it.

                                        No, it’s ultimately on the person/group distributing the software, not the original patch owner, to fix things. At least that’s where most of the pressure is. Good luck deferring responsibility in that case, when users do not understand the history/technical details.

                                        but the fact that the code is submitted in the first place is somewhat evidence that someone cares enough that this code works.

                                        Companies throw code over the wall all the time, and subject its maintenance to the whims of their current corporate agendas (which almost always change with the seasons).

                                        And it’s all very well to offer to buy a competitor’s graphics card for “anyone who works on Linux graphics” but that is pretty meaningless for regular consumers who just want the graphics card that they bought to work as it should.

                                        Regular consumers don’t work on Linux graphics. It seems like the author wants to encourage those who do work on Linux graphics to work on supporting devices from folks that are friendly towards Linux graphics.

                                        1. 2

                                          No, it’s ultimately on the person/group distributing the software, not the original patch owner, to fix things. At least that’s where most of the pressure is

                                          Yes, there might be some pressure in the sense that you get users complaining about things not working. But again, if the code isn’t maintained, you rip it out. And the pressure may well exist even if you don’t merge the code - “hey why is my NVidia card dog slow in KWin? Why doesn’t it support effects?” - in either case you have to try and pass the blame NVidia. Much easier to do that when you can say “they have a proprietary driver with a proprietary API, they provided support code for it but it is buggy” rather than “we don’t support that API”. From a user perspective, NVidia looks more to blame in the first case.

                                          Companies throw code over the wall all the time, and subject its maintenance to the whims of their current corporate agendas (which almost always change with the seasons).

                                          “We won’t accept code because you might not maintain it” is a terrible argument.

                                          Regular consumers don’t work on Linux graphics.

                                          That was my point. They still want their hardware to work.

                                          1. 2

                                            Hey thanks for the response.

                                            But again, if the code isn’t maintained, you rip it out.

                                            “We won’t accept code because you might not maintain it” is a terrible argument.

                                            Is it though? KWin has a lot of users (compared to many DE/community projects), so the impact of accepting something which could stop being maintained is greater. Why not require new contributors who want to submit API changes to demonstrate that they can maintain code when they say they would? Why is nvidia automatically a “trusted contributor” in this case? Accepting code, dealing with issues/bugs (even if you attempt to pass blame), and reverting it still takes a non-zero amount of man hours.

                                            1. 2
                                              “We won’t accept code because you might not maintain it” is a terrible argument.
                                              

                                              Is it though?

                                              Well - “companies throw code over the wall all the time, [and then don’t maintain it]” can just as easily be turned around: Companies hand over code all the time and go on to do a great job of maintaining it. But what actually is the impact of accepting this code, if it ceases to be maintained? I’d say, again, that you just have the option of ripping out the unmaintained code.

                                              Why not require new contributors who want to submit API changes to demonstrate that they can maintain code when they say they would?

                                              As I understand it, NVidia aren’t submitting API changes here. They’re submitting an alternative implementation of parts of KWin, presumably selectable at runtime (and hopefully possible to disable at compile time), which makes use of an alternative underlying API.

                                              The suggestion of asking them to maintain the necessary changes out-of-tree for a bit perhaps isn’t so bad (It wasn’t clear that this is what you were actually arguing for). I’d personally, in this situation, assuming I thought the code should be merged at all, prefer just merging it and hoping for the best; goodwill goes both ways (and I think the downsides are minimal risk/reward trade-off is generally favourable). But I’m not totally against an out-of-tree-maintainership test, conceptually; I just also happen to think it probably does make sense to reject the changes outright, in this case.

                                              As for NVidia automatically being a trusted contributor, I think it’d be unusual to ask any new contributor to maintain their changes out-of-tree, but if that’s a standard practice, then sure, ask NVidia to do it too. If you don’t do that as standard practice, but ask NVidia to do it (without having any particular reason to suspect they will be any worse than any other contributor), then you’re automatically making them an “untrusted contributor” which also seems unfair.

                                              Accepting code, dealing with issues/bugs (even if you attempt to pass blame), and reverting it still takes a non-zero amount of man hours.

                                              Agreed! - But it feels like you’re starting from a position that this is likely what will happen, and I don’t think that’s necessarily fair; if it wasn’t for the fact that we were talking about an API which only has a proprietary implementation, I don’t think this question would’ve come up. Or if it had, it would’ve been not so much about “will it be maintained” but “is it worth the burden of having extra code and additional abstraction necessary to support two APIs”, which I think is the legitimate question here.

                                        2. 2

                                          In my view, a much better technical argument is that supporting two different APIs, one of which is single-vendor, is a maintenance burden regardless of whether you have to test it - since you will still compile it regardless, and changes may break compilation due to the EGLStreams component, which then has to be resolved. In particular, this makes general changes to a higher level abstraction (which presumably exists as a layer over the two underlying implementations ie. EGLStreams and GBM) more costly.

                                          Exactly - THIS is an argument I can get behind. I have Nvidia hardware in my laptop. I don’t love that they use binary drivers, but forcing everyone to use a different API from the accepted standard is at the very least worthy of some discussion and debate.

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

                                                      Just wow. I can read a lot of things with a straight face, but the liberal use “no true Scotsman” combined with copious amounts of fanboyism really made me cringe hard.

                                                      Maybe it’s time to remind people that the things they put on the Internet are there forever and might cause embarrassment to their children and grand-children, especially articles like these.

                                                      Articles like these make me lose my hope that software development will ever rise above alchemy, superstition and wishful thinking during my lifetime.

                                                      1. 24

                                                        Agreed, you can substitute the name of some other programming language, and the content doesn’t really change.

                                                        The constraints imposed by the lack of generics (and other things FORTH lacks) breed creativity. If you’re fighting FORTH’s lack of generics trying to do something Your Way, you might want to step back and consider a solution to the problem which embraces the limitations of FORTH instead. Often when I do this the new solution is a much better design.

                                                        I try to hold myself to “if I’m going to complain, show examples of how to do better” so here we go.

                                                        I would prefer to see content like “Here’s a problem commonly solved with generics, and here’s one way to implement that same thing in Go”.

                                                        I would like to point out that Go does have generics for two three of the system types, list and array and map. One way to sort-of get generics is to wrap those system types inside whatever data structure you actually wanted to build. That is, you can build a generic tree datatype, but under the covers it’s actually some combination of list and array, and you still sort-of get the behavior of generics in other languages. To get more generic type signatures, you can declare types as “empty interface” which is roughly the “superclass of all values” and then most things will work. You will still have runtime errors if you try to cast a value from the “any” type to a type that doesn’t match, so you have to be very careful.

                                                        I guess a more thorough response would include code demonstrating the above, but I’m busy writing Python today. Does anyone already have handy examples of the above solutions?

                                                        (Bias statement: my favorite language is Haskell!)

                                                        (edited to add maps to the list of generic system types)

                                                        1. 13

                                                          Problem: implement a custom container data structure.

                                                          Solution:

                                                          “empty interface” which is roughly the “superclass of all values”

                                                          Conclusion: why have a static type system at all if you can’t even use it for typechecking the use of your container? :)

                                                          One way to sort-of get generics is to wrap those system types inside whatever data structure you actually wanted to build. That is, you can build a generic tree datatype, but under the covers it’s actually some combination of list and array, and you still sort-of get the behavior of generics in other languages

                                                          I’m not sure I understand. If you wanted to define a FancyThing<T> that consists of List<T> and Map<int, T>, you’d still need actual generics support to parameterize FancyThing and pass these types into the members’ types. Otherwise you can only instantiate the builtins with interface{}.

                                                          1. 7

                                                            Problem: implement a custom container data structure.

                                                            “Implement a custom container data structure” is never your problem. Problems are more like “serve web pages to users” or “crunch data from this database”.

                                                            1. 24

                                                              Yes, if you’re an application author, you have these problems, and Go is 100% made for you.

                                                              If you’re a library author, “implement a data structure” is your problem, and Go suuuucks for you.

                                                              1. 6

                                                                I don’t think that Go is really oriented towards writing libraries rather than writing applications. Sure, lots of people write libraries in Go (I have!), but the language itself feels like it’s meant to be used rather than abstracted with. That’s okay, I think.

                                                                1. 5

                                                                  Yes, it does. Remember the part where I said I’m okay with certain classes of problems being off the table?

                                                                  1. 11

                                                                    “I need a data structure for my application that is flexible enough for different frobz and widgets that has faster amortized access than go’s map, but I have to duplicate the code because the author of a red black tree library can’t do their job generically and safely.”

                                                                    1. 0

                                                                      Go has a way to do this called go generate. It adds an extra step to builds which is an ergonomic downside but on the other hand it doesn’t suffer from type erasure and the debugging messages are way way better than C++ templates.

                                                                      The author of your red black tree library can absolutely do their job generically and safely. They just don’t want to.

                                                                      1. -1

                                                                        Go generate is a way to invoke an external generator, isn’t it? So you’d have to make a generator that’s essentially a “TypeScript for Go”. TypeGo. LOL.

                                                                        1. 4

                                                                          First, go generate is intended§ to be run by the author of a package, not the client of it. The author of the package generates the required Go files and includes them in the package; the client does a regular go get or go build. Generation through go generate is not part of the build, just a tool for package authors. This avoids complicating the dependency analysis done by Go build.

                                                                          https://docs.google.com/document/d/1V03LUfjSADDooDMhe-_K59EgpTEm3V8uvQRuNMAEnjg/mobilebasic

                                                                          (In other words, an RB tree distributed like this is not intended usage)

                                                                          Also, plot twist: nothing forces a script run by go generate to actually generate anything.

                                                                    2. 6

                                                                      What an incredibly user-hostile attitude. You’re okay with penalizing library authors, precisely the people that contribute most to the community?

                                                                      1. 4

                                                                        A library-author-hostile attitude, you mean. And this is only a particular kind of library, e.g. the ones which implement some kind of generic data type. Many libraries don’t need to do this, and get by fine with just interfaces. It’s similar to the situation in C: everyone just implements their own data structures and that’s fine.

                                                                        1. -6

                                                                          It’s not a user-hostile attitude, because people that write data structure libraries aren’t actually users. They’re not actually solving real problems of any kind. They’re playing with themselves.

                                                                    3. 5

                                                                      “Implement a custom container data structure” is never your problem.

                                                                      I forget that gophers have such a crippled type system that they say stuff like this. In a sensible language such as Haskell, one might have

                                                                      data Day = Monday | Tuesday | ... | Sunday
                                                                      
                                                                      type Schedule = Map Day [String]
                                                                      

                                                                      Just because Go’s type system has so few interesting features that you don’t want to ever implement a custom container, doesn’t mean that’s the case for everyone.

                                                                      1. 3

                                                                        Quality snark!

                                                                        The limits of my language are the limits of my world

                                                                        1. -5

                                                                          It’s not quality snark, it’s obnoxious idiocy.

                                                                        2. 1
                                                                          type Day interface{}
                                                                          type Monday Day
                                                                          type Tuesday Day
                                                                          type Wednesday Day
                                                                          // ...
                                                                          type Sunday Day
                                                                          type Schedule map[Day]string
                                                                          
                                                                          1. 10
                                                                                    s := Schedule{}
                                                                            	var k interface{}
                                                                            	s[k] = "zoink"
                                                                            	var j Saturday
                                                                            	fmt.Println(s[j])
                                                                            

                                                                            What a safe way to write programs in 2019! All those silly academics with their type safety nonsense!

                                                                          2. -3

                                                                            It’s literally never your problem to implement a custom container data structure.

                                                                            You might need to do so if you want to solve an actual problem, in some languages, but you don’t in Go. That’s never the problem you need to solve in Go.

                                                                        3. 2

                                                                          You can cast the empty interface to a specific type at runtime, in the case that the code calling your FancyThing decided to choose the types you’re using. In my employer’s codebase I’ve seen lists and arrays of interface{} where the it’s expected that code using FancyThing will check the types before use.

                                                                          Go lang takes the Samurai Principle too far for my tastes, the cultural approach to runtime errors (the way I understand it) is that the program should immediately die. To me this implies that runtime errors should not be allowed outside of truly exceptional circumstances where the program cannot possibly continue. My take on that is, “don’t do runtime casting of any sort” so that kinda kills the idea of using the empty interface.

                                                                          I could easily be wrong, I’m certainly not an expert on idiomatic use of Go, though I have spent the last year or two working on a 50k line codebase for my employer. I would appreciate input/feedback from anyone with more understanding of idiomatic use of “die for any error” and “runtime casting of empty interface”.

                                                                          1. 3

                                                                            die for any error

                                                                            Huh? I remember that there’s a lot of passing errors around. But of course in an obnoxious explicit fashion:

                                                                            something, err := maybeDoSomething(x)
                                                                            if err != nil {
                                                                              return nil, err
                                                                            }
                                                                            

                                                                            And every call looks like this. So much simpler than Result/Either :D

                                                                            1. 0

                                                                              For many cases, you can do this, though:

                                                                              if err := x.doSomething(); err != nil {
                                                                                  return fmt.Errorf("error when calling x.doSomething: %v", err)
                                                                              }
                                                                              
                                                                              1. 5

                                                                                OK, so it’s slightly more compact… that doesn’t fix the underlying problem though.

                                                                                1. 3

                                                                                  That looks really side-effecty, as it doesn’t capture a return value :-) I personally find that even when my program is about ‘doing’ rather than computing, I still have a lot of pure functions in my program because I need to manipulate data before I can act on it – how is that in your experience? (Probably different! I expect we have different styles as well as domains!)

                                                                            2. -1

                                                                              Problem: implement a custom container data structure.

                                                                              That’s a problem almost nobody actually has, but ok. You could use code generation, which would give you the typechecks you were looking for. Don’t some “real generics” implementations essentially do this also?

                                                                              1. 6

                                                                                Surprisingly, I had this problem last week, I really needed a suffix (or prefix) tree that would return the count and value of keys that match a particular suffix. I ended up using strings.HasSuffix instead, but it’s going to make future maintainers sad when they read that code.

                                                                                1. -6

                                                                                  YAGNI

                                                                                2. 4

                                                                                  That’s a problem almost nobody actually has, but ok. You could use code generation, which would give you the typechecks you were looking for.

                                                                                  Plenty of people have this problem. Perhaps the reason people don’t do it more in Go has more to do with the fact that the type system is too weak to handle even simple algebraic sum types, so you just use e.g. integers to express what should be something else.

                                                                                  Don’t some “real generics” implementations essentially do this also?

                                                                                  Not really, at least during typechecking.

                                                                              2. 2

                                                                                Forth doesn’t lack generics - it just doesn’t have types…

                                                                                1. 1

                                                                                  After a few minutes searching, I found an article that’s much better than anything I could say about generics in Go: https://appliedgo.net/generics/

                                                                                  I completely forgot that Go interfaces are pretty much like Java interfaces (what I think of as typeclasses).

                                                                                  I will also point out that option 6 in the article I linked is exactly the C++ approach, use code generation to build a type-specific implementation at compile time.

                                                                                  I’ve not used reflection in Go, so no opinions here.

                                                                                  1. 1

                                                                                    I think you mean map & slice.

                                                                                    1. 1

                                                                                      From what I’ve read, arrays and slices are both generic, but slices are a reference-oriented layer on top of arrays. To me arrays and slices are pretty much different views/parts of the same data structure, what do you think?

                                                                                      The slice type is an abstraction built on top of Go’s array type, and so to understand slices we must first understand arrays.

                                                                                      That’s from this 2011 blog post: https://blog.golang.org/go-slices-usage-and-internals but it’s not 2011 anymore.

                                                                                      1. 9

                                                                                        Slices, arrays, channels, pointers and maps all support some limited form of polymorphic type-safe operations on them.

                                                                                        This discussion is a complete pit. I suggest you bow out while you can. Hell, this sub-thread’s parent comment is literally calling for the OP to be shamed by our descendants based simply on an opinion expressed about a programming language. The fact that nobody has called @soc out of this yet (ah, someone just did, yay) just shows how much all of us have been numbed to how ridiculous this conversation has gotten. The other side is almost as ridiculous too. Apparently implementing type safe reusable data structures isn’t actually a solution to anything.

                                                                                        1. 2

                                                                                          Yes, arrays are generic; it’s that they’re not used much in practice becuase slices are much more convenient. My main point was that you left out maps.

                                                                                          1. 1

                                                                                            Oh, good point! I’ll fix that!

                                                                                      2. -1

                                                                                        Correct, that quote does apply to more than just Go. So what? That doesn’t make it any less true.

                                                                                      3. 18

                                                                                        Your patronizing tone isn’t really contributing to the discussion.

                                                                                      1. 6

                                                                                        Why’d they switch from LibreSSL to OpenSSL? I don’t see any downsides to using LibreSSL, and the OpenBSD guys tend to do a better job with security stuff.

                                                                                        1. 8

                                                                                          http://lists.alpinelinux.org/alpine-devel/6308.html

                                                                                          and also https://news.ycombinator.com/item?id=19033634

                                                                                          tl;dr: compatibility issues with libressl, and openssl allegedly got their shit together

                                                                                          1. 4

                                                                                            Apparently OpenSSL has improved, and LibreSSL broke their ABI.

                                                                                            http://lists.alpinelinux.org/alpine-devel/6073.html

                                                                                            1. 1

                                                                                              Because libressl isn’t in their mission. Their mission is keeping a tiny system working, and adding packaging effort to be more secure at some point is not worth it.

                                                                                              Also libressl changed the openssl version constant, requiring more patching than had they not done so.

                                                                                              OpenSSL still doesn’t have their stuff together, but more software deals with their stuff and the inane version checks for features.

                                                                                            1. 17

                                                                                              Somebody needs to solve the mismatch between the value generated by free software and the inability to get paid. Programmers shouldn’t have to take a huge pay cut to work on libre software.

                                                                                              Having to ask for ‘donation’ is an insult to the dignity of a competent programmer who can otherwise get a very lucrative offer for his/her skills.

                                                                                              1. 11

                                                                                                I honestly think to a large degree this has been solved if we follow the example of SQLite. Rather than trying to reach out all all possibly users of SQLite, trying to get a monthly donation of like $1/$2/$5 from each user, they focus on the corporate users of the software and ask for significant investment for things that corporate users specifically care about and aren’t “donations”:

                                                                                                • Email Support: $1500 a year.
                                                                                                • Phone Support: $8000 a year base, for SLA response time goes up to $50,000.
                                                                                                • Consortium Membership: $85,000+
                                                                                                • Title/License: $6000
                                                                                                • AES Custom Version: $2000
                                                                                                • CEROD Custom Version: $2000
                                                                                                • ZIPVFS Custom Version: $4000
                                                                                                1. 3

                                                                                                  Note that this doesn’t work if the software isn’t going to be used by companies. For instance I have a hard time picturing a company pay for sway or aerc.

                                                                                                  1. 1

                                                                                                    Absolutely, stuff that is of no use to a corporation is harder to deal with this way. I would argue that at certain levels of corporate dependency, even niche products like text editors and diff tools can get widespread financial backing. I have seen both (text editors and diff tools) get major contributions in terms of cash from corporations.

                                                                                                2. 9

                                                                                                  Donations are difficult to justify by companies both legally and in terms of business. They also cannot guarantee any continuity to the recipient. Moreover, donations are inherently unfair to donors VS non-donors.

                                                                                                  Public funding has been invented exactly for this.

                                                                                                  1. 2

                                                                                                    Moreover, donations are inherently unfair to donors VS non-donors.

                                                                                                    Could you elaborate “fair” a little?

                                                                                                    I cannot settle on a definition of fairness around donations (esp. to develop open source software) that I, myself, would use in this situation, and so I would surely fail at assuming the definition intended in your comment.

                                                                                                    1. 4

                                                                                                      Forgive me for the platitude: If a company donates a lot and a competitor does not (while still benefiting from the same shared public good), the latter has an advantage. This little prisoner dilemma around donations encourage greed over cooperation. That’s why taxes are mandatory.

                                                                                                      1. 2

                                                                                                        If a company donates a lot and a competitor does not (while still benefiting from the same shared public good), the latter has an advantage.

                                                                                                        That sounds right but might not be. IBM backed Linux when Microsoft and SCO were going to patent sue everyone trying to use it. IBM both was donating labor to Linux and would counter-sue to keep it open. The result over time was IBM got massive benefit from Linux while proprietary offerings folded or went into legacy mode over time.

                                                                                                        I mean, IBM and Linux are both kind of unique. That success might not extrapolate. It might for companies who can stand to gain a lot from a community around their product. The community might be bigger if the company significantly invests in open source and community activities.

                                                                                                      2. 3

                                                                                                        I assume the rational is that open source code is a public good in the same way that clean water or science is. If you spend a lot of money making sure that your local river has clean water, or a lot of money to study physics then the benefits are shared by everybody but the costs were incurred by just you.

                                                                                                        “Fairness” in the context of shared resources generally means that the costs of providing the resource are shared by the users of the resource in proportion to the benefit those users each receive.

                                                                                                      3. 2

                                                                                                        I agree that public funding was meant to solve problems much like this, but that doesn’t make it an easy solution.

                                                                                                        There are thousands of new libraries created every day, which ones will you fund? How much money should you give Pixie Lang?

                                                                                                        The NSF gives grants to researchers who are motivated to publish papers, which journals will only accept if the papers reveal something new and important. If you give money to open source developers do they have any external motivation to produce useful things? What is preventing them from adding a million new features to OpenSSL rather than carefully auditing the code and fixing tricky bugs?

                                                                                                        If ruby is given enough public funding to hire 10 developers, won’t that make the developers who weren’t chosen feel like they’re not as important? Would they continue contributing as much as they have when they know somebody else is getting paid?

                                                                                                        Many open source projects have contributors from many different nations. Is the agency doing public funding okay with giving money to non-nationals?

                                                                                                        1. 2

                                                                                                          public funding was meant to solve problems much like this, but that doesn’t make it an easy solution

                                                                                                          It worked better than other alternatives during the last 100 years to develop phones, early computers, semiconductors, satellites, a lot of medicine, aeronautics, chemistry… Anything that does not have a short or medium-term return.

                                                                                                          Is the agency doing public funding okay with giving money to non-nationals?

                                                                                                          A lot of long-term scientific research is funded through global nongovernmental organizations.

                                                                                                      4. 6

                                                                                                        Not a great comfort to a libertarian, I’m sure - but for those who believe in government intervention, taxpayer-funded work on core infrastructure is an obvious way to share the load (since broadly speaking, society at large benefits from access to improved technology).

                                                                                                        IIRC at least one of the OpenSSL core team was funded - for years - off the German social security pension. RMS’s work at MIT was largely funded through the US government. DARPA paid for a ton of computing infrastructure.

                                                                                                        1. 4

                                                                                                          Who is this somebody who needs that?

                                                                                                          Describing your own desires as someone else’s needs is a cop-out.

                                                                                                          1. 1

                                                                                                            I discuss this a lot. It usually breaks the moment I bring in the notion that this somebody should probably be paid, at around, say, 10-20% if what the developers get.

                                                                                                          2. 1

                                                                                                            If the software is valuable, you can license it such that you can sell it for money.

                                                                                                            1. 6

                                                                                                              This is a pretty often mentioned, but not every FOSS software has a straight forward business model attached. For example, programming languages are far too remote from an actual product for people to actually invest in them on large scale. Yet, they certainly have huge value! If you see the struggle to get a widely used project as MRI funded…

                                                                                                              Sure, I could get my money by consulting in that programming language and being an expert in it, but there, the incentive is actually again to have other people developing it and just run around using their stuff.

                                                                                                              Also, not every programmer wants to become a salesperson or build end-user products.

                                                                                                              1. 3

                                                                                                                You can also license it freely and sell it for money. There’s no inherent contradiction in “commercial free software”. Indeed, sr.ht seems like it fits this category.

                                                                                                                1. 1

                                                                                                                  Great example (and congrats again) :)

                                                                                                                  In my experience, most such software is very hard to deploy for yourself (since the primary maintainer has no real reason to work on that aspect and nobody else tends to step up).

                                                                                                                  This is in no way a jab at your fantastic work - merely an observation of how this, like every funding structure, exerts a pull on the project funded.

                                                                                                                  1. 1

                                                                                                                    Congrats? For what? I’m not Drew.

                                                                                                                    1. 1

                                                                                                                      Huh, somehow I got my wires crossed, sorry.

                                                                                                                2. 1

                                                                                                                  I wonder if that’s true, and if not, why.

                                                                                                                  You’ve done it. And perhaps I have too (although one might tell my own story in different ways). But the people who manage to create functioning open source software from scratch have failed to earn real money from it with such frequency that I wonder whether there’s some blocker. That some personality trait that’s necessary to create that software also blocks generating income from the software.

                                                                                                                  1. 1

                                                                                                                    I absolutely believe this is the case, personality traits that draw people to open source software tend to push them away from the obvious avenues of income. I think they also fear angering their communities if they start to value corporate users over regular users. I think this fear is misguided, if regular users get much a much better product because of that corporate support, I believe they will be very understanding / support (ala sqlite).

                                                                                                                    1. 1

                                                                                                                      That some personality trait that’s necessary to create that software also blocks generating income from the software.

                                                                                                                      I don’t believe this is the case. FOSS comes out of a culture where many people could make their ends meet. Either by being employed by MIT or by having a paid day job.

                                                                                                                      It’s something our community - as a whole - could easily ignore and not build structure around. That’s falling on our feet now. Those structures will take years to build.