Threads for jado

  1. 10

    I just want to call out, I think the author isn’t talking about dynamic/static typing from the perspective of developing a regular application, but for program analysis.

    I think we’re going through a wave of static analysis, but dynamic analysis like the author is talking about will surely come back as we start to hit the limits of static analysis.

    For me, its not as important if the best tooling exists out there or not, but if I can write some tooling that’s good enough for me. I spent an afternoon a few weeks ago writing a svelte store inspector using Proxy, honestly I’m sure an extension exists that does it better, but I could write something that from the web console I could do stores.user = newUser or stores.user to update/see the existing value at runtime.

    Also something I’ve realized recently in the whole static/dynamic debate, I think we’re usually talking about the wrong thing (just if you have a type checker or not). TypeScript is still a dynamic language in the way that I care because the runtime is dynamic.


      dynamic analysis like the author is talking about will surely come back as we start to hit the limits of static analysis

      This sounds odd to me, as I would expect static analysis to have a higher upper bound than dynamic analysis. What are the limits of static analysis, and what approaches could we take to push dynamic analysis past them? It seems unbelievable that tools for Python could catch as many issues as fbinfer for example. And as we increase the abstraction power of our static types, such as with (liquid) refinement types, dependent types, effect types, etc., it looks like our ability to analyze statically typed languages is only increasing.

      TypeScript is still a dynamic language in the way that I care because the runtime is dynamic.

      Why do you care that the runtime is dynamic? What benefits do you gain from having your data boxed this way? If you want to extend types with new fields, or allow different kinds of structures that all share the same interface without requiring specification, we already have this in statically typed land with row polymorphism & structural typing / duck typing.


        I care that the runtime is dynamic so I can programmatically interact with/inspect the program at runtime, like I was describing with my svelte stores example.


          I’ve gone the dynamic route pretty far for this – having implemented a few runtimes that use that approach – and in my latest stint I ultimately found static types to actually be helpful for the inspection scenario since it gives you places to attach metadata about the shape of your data. For the run-time aspect I found that serializing the app state and then restarting it was way more resilient to code changes than running code in a current VM state (often the VM state becomes something that’s hard to reproduce). This definitely makes more sense if serialization is a core part of your app (which I’ve often found to be the case in my applications – games or tools).

          Bit of an old video but here’s a workflow demonstrating some of this: – directly links to a timestamp where I modify a data structure / metadata on some fields and you can see the results in the UI (while the state of the application remains, including undo / redo history). Earlier in the video at 0:47 you can see the app actually have a hard error due to array out of bounds, but after I fix that the app actually continues from the same point.

          But yeah I get all of this while also getting the static compile benefits of performance etc. in this case (it compiles to C++ and then to wasm. I enable more clang / llvm optimizations when I do a release build (takes longer)).

    1. 11

      I find music theory fascinating from a philosophical perspective because:

      • our perception of pitch, and of pleasing combinations of pitches, is mathematical. Our ears/brains experience pitches logarithmically and like small-integer ratios.
      • So music theory is basically simple applied math — integer ratios, modular arithmetic, logs base 2.
      • We expect that mathematical structures will fit together perfectly, because usually they do. When you prove a=b, then a is precisely equal to b, no slop, no rounding error.
      • But when you do the very fundamental exercise described in this article, which Pythagoras was probably not the first to try, you end up with a beautiful structure of 12 notes … but it doesn’t quite fit. By all rights it ought to be a perfect 12-pointed star with all its lovely symmetries, but the damn thing doesn’t close. And yet we use this star, this circle of fifths, as a foundational structure of music in nearly every human culture.
      • This problem has been bothering musicians, and causing real problems, for about 2,000 years. You couldn’t transpose pieces to a different key or play them on certain instruments. Composers couldn’t use certain intervals or harmonies because they sound like shit. In fact no matter what you do you can’t get all harmonies to sound right. Composers were literally engaging in flame wars and nearly coming to blows in 18th-century Europe over this.
      • Our current Western tuning is a kind of hack that’s very symmetrical — 12 equal steps of the 12th root of 2 — but which makes all intervals except octaves slightly wrong. The wrongness is small enough to ignore, and it turns out if you grow up with it the true integer-ratio intervals sound weird and wrong.

      Anyway. And it’s all based on this odd coincidence that (3/2)^12 is almost equal to 2^7. If that weren’t the case, music would be indescribably different.

      1. 2

        Jacob Collier does a great quick demo of how different the integer-ratio vs 12th-root-2 notes can sound:

        1. 2

          Rhythm is also fascinating! It is so syntactical

          1. 1

            I don’t think the circle of fifths is used outside western music. Can you explain why you say “nearly every human culture”?

            1. 3

              12 tone equal temperament (which the circle of fifths arises from) has been around for a couple thousand years and has influenced a plurality of non-westerners. Especially after the internet, our music tastes have started to converge across the world. There are of course non-western cultures that don’t use 12 tones and thus don’t have the same circle of fifths, but if you listen to the radio in Eastern Europe, South America, East Asia, etc (big first-world cultural hubs), you’ll find plenty of pop songs structured very similarly to American pop songs. Bad Bunny and Higher Brothers are some examples of converging music tastes imo.

              1. 1

                Sorry, I was being a bit lazy there. What’s universal is the use of simple pitch ratios as musical intervals. Every culture that has any sort of music has discovered & used pentatonic scales (or so I’ve read.)

            1. 3

              $school: Working on my grad research. I’m working in the Machine Learning Research Lab at NAU, researching surrogate functions for AUC maximization. I described a bit of this in my first cohost post. This week I need to build some experiments that show my algorithm is more efficient / accurate than the last paper for the particular surrogate I’m working on.

              I’m also in a computer graphics course, and the final project is building a raytracer. We’ve got 3d objects rendering with very basic light, and next week we need to do actual tracing of the rays we’re casting.

              $work: Our Minecraft modpack was used at Twitchcon in a Twitch Rivals event at the beginning of October, and we are continuing the event online throughout the month. There are a bunch of content creators (CaptainSparkles, AntVenom, etc) that are streaming the event live. The gamemode itself is a MOBA inside Minecraft, and the company I work for made the clientside component of it. I’m not working on any of the ingame features, so I only help on that when needed.

              Over the last couple months, I’ve completely rewritten how we write our mods. Our toolchain can target all versions of Minecraft and we can now write pretty complex JVM bytecode injections that can retarget themselves at runtime to account for the differences between Minecraft versions (field or method signatures can change a lot). There are some bugs I need to iron out this week.

              1. 6

                Any media with a comment section is going to have some form of social element, and I think all of these threads are fine. I use twitter / fediverse / orang site as link aggregators as well as lobsters, so occasional discussions of big shifts to neighboring platforms seems relevant. Especially when many of the authors who reach the front page here are switching from twitter to fediverse, cohost, etc. It feels like culture is a relevant tag for all of these since its description reads “Technical communities and culture”.

                1. 5

                  Kotlin is a lot more fun, but I still constantly deal with horrific, soul-sucking dependency management issues. We are using 4 different versions of Guava. Don’t get me started on actually deploying Java to Windows/macOS/Linux users.

                  1. 4

                    I feel like I never truly understand what I’m doing with Gradle, just copy/pasting until all the IntelliJ squiggles go away.

                    1. 2

                      I have to ask: is it the dependency management, and/or is the shitty software depended on?

                      1. 2

                        The best dependencies are ones that don’t change. I learned yesterday that Guava’s HostAndPort#getHostText was renamed to getHost for effectively 0 reason and, of course, we had code that we want to run with multiple Guava versions calling that method: a choice a dependency made turned into a NoSuchMethodError for me. Gradle is a good enough build tool that I can slap hacks where I need them.

                        I am very curious to know what dependency management for Elm is like, with their auto-updating-semver for packages. Sounds like it could go really well or really bad depending on how it’s implemented.

                        1. 2

                          There are good reasons to do simple renames of APIs (consistency being the big one). I really liked the way go handled this, with go fix tooling to do the substitution.

                          In Java, this kind of thing is much harder. If the class or method are not final then subclasses might override them, so renaming is more than a simple text substitution.

                      2. 2

                        friends don’t let friends use guava!

                        Whenever I have a chance I remove it from code-bases. apache-commons-* is usually good enough. guava is not worth all the grey hair it is causing.

                        1. 2

                          What’s wrong with using 4 different versions of Guava? It’s a waste of space, but what actual problems does it cause?

                          1. 3

                            Nothing intrinsically, the complexity comes from building modules we want to work with old code that could be using any one of these versions of that dependency. For some of these, we choose one version to build this module against and fix up NoSuchMethodErrors when we see them. Other cases we do more hacky things to ensure field/method access is checked at compile time. You’d effectively have the same issue in any other language + build system.

                            1. 1

                              guava is using semver, but they are using it to an extreme. Basically every release is a new major version, so anything goes. An API that worked in version 21 is gone in 22. There are very little or no guarantees. The thing is that the build tools assume that this is not the case. It is even more fun when you learn that sbt, gradle and maven all have different dependency resolution algorithms/order meaning things that work fine in one tool, breaks in another.

                              Simply put, having two libraries that depend on different versions of guava is a ticking time bomb and things may break or not. There are no guarantees.

                              While this is all probably okay w.r.t. semver, this is not what people expect from libraries that are basically used everywhere.

                              1. 1

                                If multiple versions of Guava is a “ticking time bomb” for sbt/gradle/maven, it seems to me (coming from Rust world, where multiple versions are common and well supported) it is sbt/gradle/maven that is broken, not Guava.

                                1. 1

                                  well, guava is by far the worst library in the eco-system with this behavior. Sure dep. resolution is problematic in java land, but there is something to be said about a library being backwards compatible and reliable.

                                  It is not good practice to behave in the way the guava devs are behaving. Aloso “fixing” java dep resolution everywhere is a lot harder than avoiding guava.

                                  edit: I want to add that rust had it easier because they could see what works and what does not when they build out their tool chain. In java things have grown organically and there is not one single blessed way of doing things. That makes them hard to compare imho

                          1. 11

                            I had a sort of out-of-body experience reading (skimming) this article, as I realized that it’s been long enough since I was involved in java/scala that I don’t remember any of it, don’t care to, and am happier now for it. I guess I’m lucky I don’t have PTSD over it.

                            1. 3

                              I am very jealous. I’ve been writing Java for far too long and am longing for the day I can jump ship and work with / on more exciting languages. I had been writing Java for 8 years when they finally added local variable type inference.

                              1. 1

                                tfw started working on a new project at work, started in 2020, that’s still built for Java 7

                            1. 2

                              For those wanting a more advanced Java decompiler, my recommendation is Quiltflower. It’s a fork (of a fork of a fork?) of JetBrains’ Fernflower decompiler with a lot of improvements to source readability. It (and Fabric’s fork) allow you to embed JavaDocs into the source as well with a little tinkering.

                              1. 32

                                I personally enjoy the way how Zig modules and macros are implemented. It feels very elegant to see existing language features being reused to achieve more functionality.

                                This is the biggest thing for me. In C & Rust, once you want to do something sufficiently complex with types, you have to break out into a “meta language” that runs somewhere in the middle of parsing. Control flow in these macro languages comes with different syntax and semantics. In Zig, these are the same thing. inline while works at comptime and runtime. Comptime reflection uses the same syntax! This made prototyping with complex type manipulation very quick compared to my experiences with C / Rust.

                                1. 2

                                  I am loving this font. I installed it as a joke but now it’s growing on me. I’m using it for the main text window in IntelliJ with Scientifica as the editor font, so the file viewer is a “smaller font” that looks about the same pixel size as Monocraft.

                                  1. 3

                                    always nice to see a scientifica user in the wild, glad you like it!

                                  1. 5

                                    This is not for CF to do. Plain and simple.

                                    1. 33

                                      Why? Seriously, I see this take everywhere, and I don’t get it. They’re a for-profit business; they feel their legal liability is higher than the profit they get from hosting KF. How could they explain any other decision to their shareholders?

                                      If you feel CloudFlare should provide services even when it is unprofitable to do so, then should be nationalized, or at least regulated as a utility.

                                      1. 11

                                        Why? Seriously, I see this take everywhere, and I don’t get it.

                                        In democracies we have three branches of government tha should be completely separated. The judiciary (courts), the executive (government) and the legislative (senate).

                                        In 2022 not being part of the facebook, google, twitter, tik-tok, instagram, whatsup or AWS or cloudflare can literally make or break a business, a social life (e.g. public services using Viber and WhatsUp to send messages),, e.g. picture a teenager being banned by instagram while the entire class virtually lives there, etc.

                                        The power of these private corporations to decide and act is effectively replacing the judiciary and executive branch of a modern democracy. Corporations have incentives that do not align with democracy, so they should not be allowed to act as branches of government.

                                        Another problem here is that the US government doesn’t wanna be involved - it’s clear nowadays. In politics every time gov makes a decision part of the electorate is hurt one way or another, so if they can avoid making a decision so much the better… Let corporations fend-off for themselves is what they’re probably thinking. The result is that now we have a precedent where ex-POTUS is banned from twitter, opposition leaders are banned from facebook and corporations might be banned from GCP or AWS on a whim or because a specific group is too vocal about it. The key part is realising that incentives alignment is coincidental, there is no oversight of any kind!

                                        What if it’s an BDSM or LGBTQ group next time? I mean, CloudFlare could decide to ban them because a far-right group was vocal on twitter, right? Questions like what is hatespeech online and which post can be taken seriously in a populated forum (e.g. Reddit) are not trivial questions in 2022 - we need a process that doesn’t depend on reddit’s board and democracies have such processes in place that are slow (unfortunately) and obsolete - we need to make sure they’re up-to-date… But replacing them with corporation can only bring misery and mistrust in the democratic process.

                                        1. 14

                                          What if it’s an BDSM or LGBTQ group next time? I mean, CloudFlare could decide to ban them because a far-right group was vocal on twitter, right?

                                          They already do this. Their DNS service blocks plenty of LGBTQ+ sites but not KF or the Daily Stormer. They already source their blocklists from right wing evangelical groups.

                                          1. 6

                                            Cite source, please. I had not heard this claim, and it seems like an extraordinary claim, which should warrant extraordinary evidence.

                                            1. 7

                                              I will admit and apologize that I can find the sources for the LGBTQ+ part, I took it on authority from some folks and can’t find a list myself. I do know that in the past they did have this issue (they have a blog post addressing it) and coupled with quite a few adult content block list being maintained by religious groups or “family focus” groups. I didn’t find it hard to believe, so sorry I can’t provide a list on that end.

                                              On the KF and DS front I personally confirmed both resolved just fine a couple days ago through KF no longer resolves when I checked today but DS still does. I will not provide a link to the site (I hope you can understand why) but it isn’t hard to find them (along with the claims I made) on twitter on some quite popular posts.

                                          2. 18

                                            What if it’s an BDSM or LGBTQ group next time?

                                            This is a slippery slope argument. Please, let’s not assume stopping nazis from committing murder will lead to websites we do like being kicked offline.

                                            Corporations have incentives that do not align with democracy [..] In politics every time gov makes a decision part of the electorate is hurt one way or another

                                            This is fear mongering. Somehow, all corporations and all government institutions are incapable of aligning with the views of the people. This story is literally CF aligning with the views of the people (albeit very late). There are obviously times were they are not aligned with the people, but movements like #DropKiwifarms exist to steer them back on course.

                                            The power of these private corporations to decide and act is effectively replacing the judiciary and executive branch of a modern democracy. […] they should not be allowed to act as branches of government

                                            They are not doing this. They’re a private corporation exercising their rights. You are saying corporations shouldn’t be allowed to “decide and act” without the government getting involved, but also saying we shouldn’t trust the government to make decisions because they’re also undemocratic. That’s a contradiction that I’ve seen many times when it comes to corporations disagreeing with conservative opinions.

                                            The result is that now we have a precedent where ex-POTUS is banned from twitter […] on a whim or because a specific group is too vocal about it

                                            He’s still stating on his own social media app that he won the election. He also spread lies about covid that had far reaching consequences. I’m sure most of us know a conspiracy theorist who would still be alive today had they been vaxxed or had they not listened to his lies. Twitter is completely within their rights to ban whoever the hell they want off their platform, just as Trump is allowed to make his own app to spew his lies on.

                                            1. 5

                                              What if it’s an BDSM or LGBTQ group next time? I mean, CloudFlare could decide to ban them because a far-right group was vocal on twitter, right?

                                              Companies, including CloudFlare on their service, do this all the time. It’s no gotchya, but something I’ve experienced myself. And guess what? It’s not gonna stop if we never pressure a company to drop an abusive evil site like KF.

                                              Fundamentally, I don’t trust CloudFlare or any other company saying they’re neutral, because never in my life have I found that to be followed up with action that isn’t biased against me and mine. Why the hell wouldn’t I use those levers against the people that want to hurt me, if I can’t get rid of them entirely?

                                              To be clear, I agree with your overall point. These companies should be either nationalized or broken up - but until they are, I absolutely do not trust them to be “neutral” when it comes to weird freak sex, or LGBTQ topics, or pagan communities, whether or not they use that excuse to defend harassment forums.

                                            2. 5

                                              So in your view a for-profit business does not have any other responsibility than to pursue that profit? What a strange take. Of course they have. They operate in a society. Their actions have a much broader effect on a lot more people than just the exhange of money between a few selected parties, so their responsibilities are broader too. Companies are bound to the same system of moral rules we’ve set up as much as every other party. Why would they be an exception?

                                              1. 5

                                                Should? No. But in fact, in the absence of regulation, that’s how it works. If CloudFlare wants their hands tied, they should get the government involved. If they’re a utility, they should be regulated like one.

                                              2. 3

                                                Seems like a pretty analogous situation to Hatreon being suspended by Visa.

                                            1. 13

                                              The list of issues present in this article boils down to “I don’t like their markdown spec” and “they’re closed source”, which I think are incredibly weak arguments.

                                              GitHub is a proprietary, trade-secret system that is not Free and Open Source Software (FOSS).

                                              (from the Software Freedom Conservancy post that was linked:)

                                              In the central irony, GitHub succeeded where SourceForge failed: they have convinced us to promote and even aid in the creation of a proprietary system that exploits FOSS.

                                              What is “exploiting FOSS”? How is GitHub exploiting FOSS by being closed source? None of the Freedoms granted by free software are prevented when using GitHub’s platform. I don’t understand why every commercial usage of free software is demonized to hell and back. Free software would be far less useful and prominent if it wasn’t for its ability to be used by businesses. Encouraging businesses to use (and lock-in to) FOSS is a better choice than completely segmenting the ecosystems. The proliferation of FOSS depends on commercial usage.

                                              1. 10

                                                i would imagine they are talking about GitHub Co-pilot and how they trained it on FOSS without respect for licenses, which absolutely is exploitive

                                                1. 4

                                                  All of my open source work is released under a BSD license, by my choice. How is it “exploitative” for GitHub to do something I’ve explicitly granted them permission to do? Even before I’d agreed to their terms of service, even before GitHub existed, I was perfectly content to offer code to the world under a permissive license and was already doing so.

                                                  1. 5

                                                    For BSD-licensed code, it’s fine. But Copilot is also trained on GPL-licensed code, which forbids proprietary software being derived from it.

                                                    1. 4

                                                      First of all, it’s relevant to point out that not all of us use copyleft licenses, and many people instead use permissive licenses which explicitly say we’re OK with this. Too many Copilot discussions, and “corporate exploitation of open source” discussions in general, are framed as if the entire community is using copyleft licenses when it is not at all the case.

                                                      And for Copilot versus the GPL, I expect nobody will ever bother trying to enforce, and if someone does it will simply be ruled in court that GitHub’s terms of service make it work. To lay it out as simply as possible, when putting code on GitHub you are making two license grants. One of those license grants is to the world at large via whatever you put in your LICENSE or license-indicator metadata, and the other license grant is specifically to GitHub, and is defined in GitHub’s terms of service. GitHub will almost certainly argue that the second license grant permits Copilot to do its thing, and if their legal team has done their jobs, the license grant in the terms of service will permit Copilot to do its thing.

                                                      This leaves only the possibility of someone uploading code for which they do not have sufficient rights to make the GitHub-terms-of-service license grant, but the terms also require that person to indemnify GitHub, so the person who ends up in a lot of legal pain is still not GitHub – it’s the person who uploaded the code without being able to grant the associated license to GitHub.

                                                  2. 3

                                                    I think I would encourage the use of using NNs trained on Free software. It’s creatively transforming the work to provide creativity and automation to others. That is the same reason I would encourage others to transform and spread Free software. I don’t think that’s exploitative to the authors of the original software.

                                                    As for other-licensed software, I don’t particularly care about their licenses, because I would prefer all software to be Free, so I don’t see GitHub “exploiting” other author’s work. It was clear in my test run of Copilot that it wasn’t copying some other author’s work verbatim, it was genuinely learning the patterns in my codebase. I don’t think patterns of code can or should be copyrighted anyway.

                                                    1. 6

                                                      For me, it’s not so much that GitHub’s efforts around Copilot and Codespaces are exploitative as they are one-way gates. They extract business value from open source software and lock it inside their ML models, managed cloud infrastructure, and proprietary APIs.

                                                      Yes, there’s almost certainly more open source code in the world because of GitHub’s efforts, but a whole lot of it is useless without proprietary services you can only rent, not buy, and certainly not fork and hack on yourself.

                                                      It’s a kinder, more self-aware Microsoft, but it is still Microsoft. Their playbook has always included being the foremost vendor of platforms and APIs that are “open” in the sense of being documented and accessible to developers, but not in the sense of having any choice of provider, terms, or implementation.

                                                      1. 2

                                                        They extract business value from open source software and lock it inside

                                                        But that’s what businesses do. They put in work to add value to their inputs, and then sell the outputs at a premium. How is this fundamentally different from going to a field to pick blueberries, cooking them into jam, and then locking the jam away inside jars to sell at the market? (Except that in this case GitHub didn’t even take away the blueberries.)

                                                        1. 3

                                                          The correct analogy would be the owner of the field telling you that you can pick blueberries, but everything you make from them must also be freely accessible.

                                                          1. 3

                                                            No, that would be the model of the original GPL. “I will give you this blueberry jam, but in exchange you must share the recipe whereby they were created.”

                                                            GitHub says, “cool, thanks, but no. I’m gonna take this jam and feed it into my jam-copier, then let people choose it as a flavor to mix in the jam I sell them at my farm stand next door to the community garden. The copier is my proprietary secret invention, though, so you can’t see inside and know how I extract and mix the flavors, and I’m not going to credit any of the cooks who contributed.”

                                                            1. 1

                                                              Well, here we run into the usual issue where intellectual property is trivially copyable while blueberries aren’t.

                                                              The more interesting point specific to Copilot is whether the neural net is a derivative work of the GPL’d code it was trained on. I don’t think it is — the amount of transformation that’s gone on is too high. If I’m allowed to read some GPL code to study how it works and then write my own code that does something similar (i.e. there’s no “clean-room” requirement the way there is with reverse engineering), I think that also allows for what Copilot is doing. Not because Copilot is intelligent, but because both involve similar degrees of transformation.

                                                      2. 1

                                                        Too lazy to find the source, but there was a lawyer that stated like generative art, it would likely be better for freedom if all generated code like this were required to be licensed as 0BSD–the CC0 of software.

                                                      3. 2

                                                        “I don’t like their markdown spec” and “they’re closed source”, which I think are incredibly weak arguments.

                                                        I’ll grant you the markdown spec bit, but the closed source argument is the single strongest argument possible in this space.

                                                        How on earth did the so much of open source community come to depend on a proprietary, closed-source system run by an organisation that has historically been one of the most antagonistic towards open source software?

                                                        1. 1

                                                          Github offered a superior product for no to low cost.

                                                          Their dominant position in Open Source development was built before they were acquired by Microsoft.

                                                          Not everyone involved in developing open source software cares about the philosophical underpinnings of Free Software, or are even aware of the rift between FS and Open Source/permissive licensing. Anyone choosing an MIT license for example should have any problem hosting it on a platform that doesn’t publish the code they use.

                                                          1. 2

                                                            Github offered a superior product for no to low cost.

                                                            … up-front.

                                                            Don’t get me wrong, I was an enthusiastic user and promoter of Github for years. It was so much better to use than Sourceforge in so many ways. My “how on earth” was more of a rhetorical hand-wringing than a serious question; I know exactly how, because I was there.

                                                            In hindsight, though, I believe it was a mistake.

                                                          2. 1

                                                            one of the most antagonistic towards open source software

                                                            I don’t see this being applicable to GitHub when they have enabled the development of so much open source software. I would love for GH to be open source, and I’m glad that free alternatives exist, but I don’t view the open source-ness of the platform I’m using to be a deciding factor. Especially when it’s relatively simple to jump off of GH. Git is still decentralized here - nothing is tying you to GH aside from logs of issues / PRs (which are also able to be migrated). Your core software and audience isn’t directly tied to the platform.

                                                            I empathize with the sentiment, but I’m not going to jump ship solely because they’re closed source. Otherwise, if I wanted to stay consistent, I wouldn’t use any software that was closed source. That would be a cool world to live in, but for now closed source software, in a lot of scenarios, is the best we have.

                                                            1. 2

                                                              I think he means Microsoft

                                                              1. 1

                                                                but for now closed source software, in a lot of scenarios, is the best we have.

                                                                Yes, that’s true, and I use a fair bit of it myself - from binary blobs on ARM systems to my Chromecasts attached to my TVs.

                                                                But those scenarios do not include software forges :)

                                                          1. 11

                                                            Here is the announcement on Reddit.

                                                            1. 9

                                                              There must be some kind of Completeness Theorem for language design that you can’t have a language that is consistent, concise, and free from unexpected edge cases at the same time.

                                                              1. 1

                                                                Does Lisp have unexpected edge cases? Brainfuck seems to fit all three, as do many other esolangs. Does practicality imply unexpected edge cases?

                                                                I’ve seen a lot of people say “complexity” can add holes / warts to a language, but I think in this case it was Rust’s decision to go all in on the ownership model. Pony, for example, chose differently, and it has a memory model that I find much easier to reason about. Deny capabilities like trn and iso express semantics that Rust can only emulate with ownership + unsafe.

                                                                1. 2

                                                                  Brainfuck seems to fit all three


                                                                  Does Lisp have unexpected edge cases?

                                                                  Here’s one I’ve seen multiple people stumble over: ‘nil’ is the bottom type, while ‘null’ is the type whose sole inhabitant is the symbol ‘nil’.

                                                              1. 7

                                                                I would start with a stop the world mark and sweep collector, no compacting, copying, or moving, couple it with tagged pointers to avoid churn of numbers, etc. Then when and if you find the stop the world pauses to be too much of a problem start looking at making it more complicated.

                                                                I am being serious here, that is how the JS engines worked for more than a decade (for spider monkey it could be two), and the GC pauses were essentially unnoticed. This was at a time when all active web pages were running from a single shared heap as well, and prior to the more aggressive NAN-boxing of modern engines so were taking more of an allocation hit during numeric heavy operations.

                                                                The need for small pause times is almost entirely as a result of modern JS being used to do a lot at a high frame rate, so historically fine pauses of potentially 20ms are no longer tenable.

                                                                I would ask very simply, why do you need the gc to be concurrent? “because other engines do it” is not a good answer. Making a concurrent GC is vastly more challenging than single threaded, as you are essentially taking on the complexity of incremental and generational GC.

                                                                portable, concurrent, short pause times > simple implementation > low memory usage > fast

                                                                As above, why do you want concurrent? the only reason for concurrent GC is performance, short pause times is related to fast, simple implementation is counter to concurrent, low memory usage means ref counting, as GC cost is proportional to how much of the heap is live - if your heap is filled with live objects you end up having to GC more frequently, and the GC takes longer because time to scan is proportional to how many live objects there are.

                                                                Why not a vanilla mark-sweep collector? That can have long pause times.

                                                                This is a problem that is in general way overblown. A long pause time requires a very large heap (pause time is proportional to live heap), generational GCs partially mitigate that at the cost of much higher memory usage, much more complexity, and still can have very large pause times when the heap gets large.

                                                                The only way to guarantee short pause times is to support incremental GC, which can be built with any of the standard mark/sweep, generational, copying, etc GCs because being incremental is independent of the tracing and collection strategy. It is also very hard to implement.

                                                                Mark/sweep collectors also easily extend to generational collection if you feel that your GC is suffering from scanning large amounts of long lived objects.

                                                                But again, JS engines uses stop the world GCs for years, in principle you can make a GC pause for a very large amount of time. In practice that doesn’t occur very often, Blocking the construction of a GC on the basis of a potential problem, or choosing a complex implementation over a simple one, is imo not a great choice.

                                                                Assuming a good design, your interface to your GC should not expose the actual implementation, so changing in future should not be more complex than implementing the complicated thing first. The only real problem is write barriers, but that’s a large part of the complexity of every GC other than mark sweep.

                                                                1. 1

                                                                  long pause times… a problem that is in general way overblown… if you find the stop the world pauses to be too much of a problem start looking at making it more complicated.

                                                                  Thank you for your long and detailed answer. It could be true that i am worrying too much about pauses. My worries are probably because in the distant past, I recall hearing about people’s bad experiences with Java GC pause times. Perhaps those experiences were just outliers.

                                                                  why do you need the gc to be concurrent?

                                                                  One goal of this language is to be suitable for writing programs with very large numbers of threads executing in parallel.

                                                                  your interface to your GC should not expose the actual implementation, so changing in future should not be more complex than implementing the complicated thing first

                                                                  Yes I agree, I am trying to future-proof the interface to the GC. This is one reason why I do not want to put off the implementation of an incremental GC until later, because I don’t want to miss a requirement for this interface (such as read or write barrriers) that may be needed for fancy GCs but not for simple ones. Here’s what I have so far, can you think of anything I should add to the following list? The runtime may need to be able to:

                                                                  • produce a list of the locations of any pointers within data, including in:
                                                                    • the registers
                                                                    • the stack
                                                                    • the heap
                                                                    • the globals
                                                                  • impose read barriers and write barriers
                                                                  • interrupt execution every now and execute GC code
                                                                  1. 1

                                                                    I recall hearing about people’s bad experiences with Java GC pause times

                                                                    In my experience long pause times are rarely a cause, they’re an effect of poor algorithmic / data structure choices. The specific GCs that are bundled with OpenJDK are are pretty well tuned, and the default (G1) is concurrent and generational.

                                                                1. 2

                                                                  I think this list is pretty bad and I’m pretty tempted to flag it as spam because low effort complaints about these terms appear so frequently.

                                                                  [Artificial Intelligence] now means “an algorithm pushed to production by a programmer who doesn’t understand it”

                                                                  This is dumb. If we’re not talking about Machine Learning, then you can usually understand how your AI makes decisions. Games are great examples of AI that is easy enough to reason about that you could trace the causes of every decision your AI makes.

                                                                  If we are talking about ML, “doesn’t understand it” is phrasing I’d like to see retired. We know how these things work. You might not be able to trace the cause of every decision an ML algorithm takes, but they are not magic black boxes. There are plenty of non-DL algorithms that you can write by hand in a little bit of Java/Go/your-favorite-lang that can exhibit pretty complex behavior (kNN is an example). Sometimes I think people forget that “buzzwords” have buzz for a reason.

                                                                  1. 1

                                                                    I agree that it’s bad, and I don’t think it should be here, but I’ve been told off for using the spam flag for that. My tactic in lieu of the “low quality” flag reason is to upvote everything else currently on the front page.

                                                                    1. 1

                                                                      Sadly I see too many posts on here that I think would get flagged to hell if “low quality” was an option.

                                                                  1. 3

                                                                    Acceptance rate (for suggestions visible for >750ms) 34%

                                                                    This is the most interesting number to me. 1/3 of all suggestions by the AI are accepted by the user! Even with how primitive these things are, they’re already generating good code. My quick sprint with GitHub Copilot showed me how it useful these things can be - it was autocompleting a lot of complex Kotlin code for me.

                                                                    1. 3

                                                                      they’re already generating good code.

                                                                      Because this test is on Google developers, I’ll grant that it is likely generating “good” code, but the statistic here is actually “accepted” code, which I might term “good enough.” There’s a key difference in those terms, especially when the minimum time for the suggestion to be on the screen is less than a second.

                                                                      As I consider what changes will happen to different professions as AI gets bigger (thinking as a tool to be used, not “the robots will take our jobs!”), I can’t help but think that the quality that is accepted will go down over time as the speed at which you can work goes up. People could become as used to programming suggestions as they are on GPS nowadays, leading to a decrease in people’s map reading ability.

                                                                      I wouldn’t be surprised where, in content creation specifically after reading the DALL-E threads here, or in programming, you’ll eventually see people advertising “hand crafted” content. “This Youtube channel is produced without ANY AI (woah, wow!)”. “This code was entirely generated by a real human, support your local programmer.” This could become the same sort of niche as buying a vase that wasn’t produced in a factory, with higher charges associated.

                                                                      I’m not against AI-based tools, the threads here the past few weeks have convinced me of a few really good ways they can be used. But much like air travel was glamorous and now is a cattle car with wings, I think the ability to accept things quickly and move on, letting you do more in the same amount of time, is going to lead to significant change for a few industries. Change isn’t bad.

                                                                    1. 3

                                                                      I like this tutorial by Andrej Bauer. I made a Rust implementation and experimented a little further with it.

                                                                      1. 25

                                                                        The pain in the author’s voice is disheartening.

                                                                        It was all worth it. … Or. That’s what I keep telling myself. Because it doesn’t feel like it was worth it. It feels like I wasted a lot of my life achieving something so ridiculously basic that it’s almost laughable.

                                                                        I wonder if their efforts would be better spent on a different language that is more welcoming to features many programmers consider basic in 2022. They also write:

                                                                        It has only just occurred to me now,

                                                                        that every single paper I have merged into C or C++ has been exclusively at the behest of other people and I have merged exactly 0 papers that have served my own needs.

                                                                        I need to be a lot more fucking selfish.

                                                                        C++26 and C2y/C3a era is gonna be on Demon Time. No more of this happy nice let’s-get-along shit.

                                                                        I hope “demon time” brings improvements to the C ABI, and I hope we can one day throw out the technical debt we’ve accumulated over the decades in exchange for new languages and new ABIs. Carbon looks really appealing, especially if they go the route of “your C++ is busted and you must change it to conform to our new practices/API/ABI”.

                                                                        1. 7

                                                                          I hope “demon time” brings improvements to the C ABI, and I hope we can one day throw out the technical debt we’ve accumulated over the decades in exchange for new languages and new ABIs.

                                                                          There are a lot of good changes in the most recent standard (I’m particularly pleased with the removal of K&R prototypes), and a lot of other good proposals on the table – but I don’t think that this is one of them.

                                                                          The C ABI things pointed out here are a non-problem. C already doesn’t guarantee ABI, and the healthy variety of libc implementations out there means that people tend to not rely on the ABI that deeply anyways.

                                                                          The C++ ABI issues involve a number of subtle properties that are effectively guaranteed by the standard, such as reference stability in the standard hash tables or std::string copying in regex. Adding new aliasing options doesn’t fix code that depends on this.

                                                                          The proposed solution makes things worse – it doesn’t consider changes to types, the interactions between returned types and different libraries, function pointers, and so on, and it has the effect of effectively baking in old ABIs in a way that needs to be maintained forever.

                                                                          It makes the ABI situation worse, not better.

                                                                          What we need is for people to get used to rebuilding their code, and possibly some standardized package management solutions around that. Whole builds need to learn to segregate by ABI for this to work.

                                                                          A cross ABI build is a cross compilation, and needs to be treated that way.

                                                                          (There has been talk in the C++ committee around package managers, and this is, in my opinion, the place to fix ABI.)

                                                                          1. 1

                                                                            Probably not on demon time, there are now new kids ready to do happy nice let’s-get-along shit. The question is, in which language.

                                                                            1. 1

                                                                              I wonder if their efforts would be better spent on a different language that is more welcoming to features many programmers consider basic in 2022.

                                                                              I know Go and Rust probably natively support this but it’s not very common. The two languages I’ve used in production where I’ve wanted this are Haskell (which requires Template Haskell) and Java/Kotlin (which can’t even get close except there are build tools which generate special class files with byte arrays).

                                                                              Not sure I’d call it “basic in 2022” but I wish it was.

                                                                            1. 4

                                                                              I’ve been watching this page and your posts in the r/PL discord, and I’m excited for the direction this is going in! I’ve got some notes / questions on what you have so far.

                                                                              Better ergonomics around borrowing would be nice too, though I’m not sure how to do that yet, I just hate that there’s no way to abstract over ownership and so we have Fn and FnMut and FnOnce. […] You can’t be generic over mutability and ownership, so for example you end up with iter(), into_iter(), and iter_mut().

                                                                              What would a function that is generic over mutability and/or ownership look like? What could you do with a param that you don’t know if you have mutable access to and don’t know if you own? Isn’t the explicitness the whole point of having these be separate pointer types? If Garnet had some way to reify the information then I think this could be useful, but I’d have to see some example implementations. Personally, I think the iter() trio has some bad names but the semantic difference is important, and I think it would be lost if that function was generic.

                                                                              Additionally, will Garnet implement lifetime tracking? One idea I can’t grok is how you can minimize Rust’s complexity without losing required language features. For example, to any C / Lua programmer, Higher-Rank Trait Bounds must seem like an absolute nightmare. Higher-Rank anything is dipping your toes into some meaty theory that “practical programmers” dislike. But without HRTB, there would be some functions with lifetimes that your language would be incapable of expressing. It seems to me that much of the complexity of Rust stems the intersection of traits and lifetimes.

                                                                              Again, this is kinda similar to Zig, but I want to avoid the problem where you don’t know whether the code will work before it’s actually instantiated.

                                                                              Zig does this for conditional compilation / comptime tree shaking. Since you’re going to need to compile some code that uses Linux’s ABI and some that uses Windows’ ABI, I think some conditional compilation is going to be required for a systems language. Rust uses build-time configuration flags (#[cfg(...)]) which, imo, is a hack. I think Zig’s approach is a lot simpler, even if it requires lazy resolution.

                                                                              Another thing to note here is testing - idiomatic Zig uses test {} blocks to ensure your code is actually being resolved.

                                                                              fn Vec(comptime len: comptime_int) type {
                                                                                  return struct {
                                                                                      const LEN = len;
                                                                                      // ...
                                                                              test "resolve Vec" {
                                                                                  _ = Vec(5);

                                                                              Tests can also be skipped on certain OSes (w/ something like return something.SkipTest?). This has the same functionality as Rust’s cfg, but doesn’t require obscure annotations on your functions. I prefer this method because it makes the language smaller.

                                                                              Rust’s trait orphan rules are annoying, but may be too hard to be worth trying to solve.

                                                                              I just wanted to note that Carbon decided to do the same thing here.

                                                                              Trying out QBE and Cranelift both seem reasonable choices, and writing a not-super-sophisticated backend that outputs many targets seems semi-reasonable.

                                                                              I wrote a toy language with an IR that translated to LLVM and CraneLift and it wasn’t too bad. CL’s API was pretty nice. One thing to note is CL uses extended basic blocks instead of phi nodes. I found that having my IR use EBB and compiling that to phi nodes for the LLVM backend was easier than turning basic blocks w/ phi nodes into EBB.

                                                                              1. 5

                                                                                I’ve been watching this page and your posts in the r/PL discord

                                                                                oh no

                                                                                What would a function that is generic over mutability and/or ownership look like?

                                                                                I don’t know yet, to be quite honest. I don’t think it would technically add any power to the language. But if you have something like, in Rust, fn iter(&self) -> impl Iterator<Item=&T> and fn iter_mut(&mut self) -> impl Iterator<Item=&mut T> and fn into_iter(self) -> impl Iterator<Item=T> then having three different methods really doesn’t get you much in terms of power either. The important information is that the ownership of the output T is the same as the ownership of the input self. What can you do with the param? Mostly just move and assign it, but sometimes that’s enough for the call-ee. The caller knows the ownership status of the self in question and so knows what it’s getting.

                                                                                As for what it will look like and how it will work, I’m open to suggestions. The above statement is literally about as far as I’ve gotten on it.

                                                                                Additionally, will Garnet implement lifetime tracking? …

                                                                                It will definitely track lifetimes, and I don’t actually think (anymore) I’ll be able to improve on Rust’s lifetimes that much, but it’s been a while since I visited this problem in depth. I agree that lifetimes + traits = complexity, but more of my work has been spent gnawing on the trait side of that equation than the lifetime side. Higher ranked trait bounds are a good example though, since I’ve been using Rust since the 1.0 release and I’ve had to write code that uses HRTB’s about twice, and both times I ended up refactoring my code so that I didn’t need it because it was such a pain in the ass to actually figure out. So is the cost of writing unsafe { ... instead of for<'a> ... really that big? Opinions will inevitably vary, but for the moment I’m leaning towards “no HRTB’s if possible”.

                                                                                … I think some conditional compilation is going to be required for a systems language. …

                                                                                It is, but I haven’t really figured out what form it would take. My thought for lack of anything better was “steal Rust’s system”, which usually gets you at least a half-decent default. I hadn’t considered using lazy type instantiation for the same sort of thing, it’s an interesting approach. Rust’s #[cfg(...)] blocks certainly have all the downsides of “well this works on my platform” that scares me about Zig’s type resolution, so… idk, might be worth looking into more.

                                                                                …idiomatic Zig uses test {} blocks to ensure your code is actually being resolved. … …but doesn’t require obscure annotations on your functions.

                                                                                From the outside I don’t see much to choose one over the other.

                                                                                Rust’s trait orphan rules are annoying, but may be too hard to be worth trying to solve. I just wanted to note that Carbon decided to do the same thing here.

                                                                                Actually, with ML modules, orphan rules go away because choosing implementations of your trait-ish things is explicit. The classic example of trait conflicts that I like is you have module A that provides type A.T and implements Hash on it, then you have module B that implements its own copy of the Hash trait on type A.T with a different hashing algorithm. Now whenever you get an A.T and pass it to something you don’t know whether it should use A’s implementation of Hash or B’s implementation of Hash

                                                                                This doesn’t happen with modules ‘cause it extracts the implementation from the type. Rust-style traits basically have a list of implementations of traits attached to each type, which is global. ML modules have a list of implementations of traits that are not attached to particular types, they live in your module namespace like any other value, so if your function is passed an A.T and wants to hash it then it also has to know what implementation its using. If something creates an Hashset<A.T, A.Hash> or whatever and passes it to a function that is using B.Hash then it won’t typecheck.

                                                                                The downside of this is that juggling this by hand instead of using the type as your namespace is kinda a pain in the ass. I have yet to make it particularly satisfactory. So, we will see. My most recent “this is what I want to be able to make compile” experiment is here, I think.

                                                                                I wrote a toy language with an IR that translated to LLVM and CraneLift and it wasn’t too bad.

                                                                                Good to know! Cranelift was a fair bit less mature when I started this project but I continue watching it with interest from time to time. The only downside right now, besides stability (which will be true for any compiler backend I expect), is that it’s intending to optimize for JIT use cases rather than AOT compilation. But maybe I’ll give it a go. I do slightly prefer EBB’s to phi nodes, though for now my attempts at writing an optimizing backend basically made me go “woah I need to learn more about control-flow and data-flow analysis” and back off a bit.

                                                                                1. 3

                                                                                  My thought for lack of anything better was “steal Rust’s system”, which usually gets you at least a half-decent default.

                                                                                  For a while now, I’ve been thinking that it would be nice to have a wiki that lists and compares implementations of programming language features for programming language designers. Anybody know if that already exists?

                                                                              1. 2

                                                                                As someone who isn’t very familiar with Zig, can you better define “smaller” vis a vis Rust and Zig? Feature set? Stdlib? Syntax?

                                                                                1. 27

                                                                                  Rust is three-five languages in a trench coat:

                                                                                  • imperative plain rust code: for x in [1, 2, 3] (with a subset for const)
                                                                                  • substitution-based macros: macro_rules! { /*this looks nothing like Rust*/} + proc-macros
                                                                                  • logical traits (impl X for Y where Z:T)

                                                                                  Zig is very uniformly just one imperative language.

                                                                                  This I think is the major reason why Zig feels smaller.

                                                                                  1. 8

                                                                                    Very true! I recently rewrote a packet struct generator I made a few years ago in Rust to Zig. The original implementation used heavy Rust macros to manipulate types, while the Zig implementation doesn’t require anything special because I can manipulate types as values. The comptime reflection is crazy cool, and felt more intuitive to me than building this pseudo-DSL for packet definitions.

                                                                                  2. 1

                                                                                    Along the lines of matklad’s comment, comparing both languages to C++ is also useful. C++ has

                                                                                    • the imperative language, with the addition of classes
                                                                                      • the compile-time constexpr subset
                                                                                    • the compile-time template language (which is famously turing complete, and people do weird things like write regex engines and parser generators at compile time, in a tortured syntax, with limited tools)

                                                                                    And if you look at what happened in C++ 14, 17, 20, and I think 23 – a lot of the “weight” is in the compile-time languages (constexpr and templates).

                                                                                    I think the language probably doubled in size during that period.


                                                                                    Features like coroutines rely on a lot on templates from what I remember, and lambdas interact with them, etc.

                                                                                    Now Rust has all of those things (constexpr / const contexts and templates / parameterized types), and it also has 2 different types of macros! And it’s getting bigger along the same lines.

                                                                                    I think the comptime feature of Zig can go a long way towards simplifying this situation. Admittedly I haven’t used it, but I have done lots of metaprogramming C++ with Python, so I know all the things I would use it for. (Anything that happens before main() and doesn’t depend on runtime values.)

                                                                                    For systems languages, the compile-time / runtime split is a bit like a “shadow language”


                                                                                    It could be justified, but it definitely makes the whole language bigger and introduces problems of composition.