Threads for nil

  1. 5

    I don’t know what it is, but I always really enjoy these problems and am more motivated to do them than any other programming challenge sites. Going to try to do them all in Elixir this year, and challenge myself a bit with Prolog if there are some that seem to lend themselves to it.

    1. 7

      As shameful as it is to admit, for me the Christmas stuff really helps out. Even though the story is relatively barebones, imagining the silliness of the circumstances, and getting to write variable names like elfCookieLoad makes it so much more fun for me than dry algorithms exercises, even when day 5-6 onwards starts to ramp up towards basically the same kinds of problems.

      1.  

        You may have meant to respond to this comment.

    1. 7

      I noticed a weird trend where the check for if something is undefined happens after the undefined behavior. Intuitively it makes sense to me that this is insufficient so I’m wondering why this failure is so common? For example here the overflow check happens after the overflow already happened.

      1. 4

        I don’t usually do that, but in my case there were 2 reasons:

        • the initial intention when writing it wasn’t protecting against overflow/UB but simply protecting against the computation going outbound for the dereference
        • the assignment needed to be done early because I was targeting a codebase with some ancient C convention on variable declaration required to be before any code; and since I had the form where I wanted to bail out early instead of opening a scope, I had to declare it early:
        int x = ...
        if (...)
            return -1
        // x can not be declared here
        return f(x)
        
        1. 9

          Not trying to be critical, but it shouldn’t be news that you can’t check for a UB condition after it’s happened. I’ve seen so many cases where people run into similar problems, or problems related to the type-punning rules. Usually the thought process is something along the lines of:

          ok, so I know this is supposed to have undefined behavior. But the variable will still have some value, so I can check if the value is in the correct range and so avoid issues that way…

          No, you can’t. This is what undefined behaviour means. All bets are off; if it’s hit, it is a bug in the code, full-stop, and no checking afterwards can fix it because the behaviour from that point (*note1) on is totally undefined. Maybe it seems to work in some cases. It doesn’t matter; use a different compiler, or a later version of the same compiler, and all of a sudden it could stop “working”.

          Don’t think of the C compiler as some sort of glorified high-level assembler. It’s way more sophisticated than that. There are rules you have to follow, if you are using any of the modern compilers. You don’t have to like it (and there are even switches available that will give behaviour that you want, but that’s not standard C any more) but it is the case. You must not ever invoke undefined behaviour.

          Note 1: Actually, I believe the whole program behaviour is undefined if the program exhibits undefined behaviour at any point. So technically, even things that were supposed to happen before the UB might not happen or might happen differently.

          1. 5

            You are technically correct, but I’m sure you understand that the consequences of such a policy means that pushed to the extreme we could have the situation where a 100k LoC codebase has a single little bug deep down somewhere, then crashing or executing random code straight at startup is an acceptable behavior.

            The cost of a single mistake is very high, that’s the main point I’m trying to make.

            1. 9

              What’s the alternative? If the compiler can’t optimise around code that hasn’t been executed yet having UB, then the opportunities for useful optimisation become near non-existent.

              The compiler is not doing anything unreasonable here: every step, in isolation, is desirable and valid. If the end result feels unreasonable, then that’s either (a) a problem with the language spec being insufficiently relaxed about what it considers to be UB or (b) a problem with insufficient tooling (or, in the case of a language like Rust, built-in compiler checks) to catch issues like this.

              To point the finger at the compiler is a very hard sell indeed because there’s no specific thing to point at that it’s doing wrong.

              1. 9

                It might be reasonable not to do the optimization. The alternative in rust is to actually define the behavior of wrapping, which would be equivalent to using -fwrapv in C. Sure we loose some optim, but is it worth it? I’m starting to believe so.

                1. 10

                  Yes, I agree: but that’s a problem with the language spec, not the compiler. The language spec should just say ‘overflow has wrapping semantics’. You’ll lose some opportunities for optimisation and compatibility with a lot of older of obscure platforms (some platforms have arithmetic instructions that don’t wrap on overflow, and this is one of the big reasons that the C spec leaves overflow undefined!), but this is enough of a footgun that I think it’s a worthwhile tradeoff in the year of our lord 2022.

                  But again, this isn’t GCC’s fault: this is the fault of the language spec and the compromises that went into its creation. Don’t like it? Time to get a new language (this isn’t me trying to be gatekeepy: horrid footgun shit like this is a big reason I moved to Rust and never looked back).

                  1. 6

                    Not saying it’s GCC fault, but just because a spec did a mistake doesn’t mean GCC should be braindead about it: it holds a responsibility for all the software in C out there. Nothing forces GCC to do dangerous optimizations; it can still follow the specs by not honoring this part. GCC serves the user, not the specs; the question becomes: do users want this kind of optimization and assume its consequences by default?

                    1. 3

                      Where’s the mistake? Integer overflow being undefined is a feature, not a bug. There are platforms where the behaviour of overflow is implementation defined, entirely unpredictable, or just straight up UB at a hardware level, leaving the machine in a totally invalid state. C is designed to target bizarre and unusual architectures like these, and so having integer overflow be undefined is a huge boon to the language’s portability without sacrificing (and even improving, in many cases) performance.

                      If you’re just going to do language spec revisionism and claim that ‘the spec is wrong’ or something, then I think it’s clear that C’s not the language for you. Heck, it’s definitely not the language for me: I aggressively avoid touching the thing nowadays.

                      1. 3

                        I am sure there is, so please name one.

                        1. 3

                          Many GPUs have saturating semantics on overflow. Other architectures emulate small integers with large integers, meaning that overflow results in unobservable ‘extra bits’. Changing the standard to make integer overflow always wrap would make writing C for these architectures extremely difficult without significant performance ramifications.

                          If reducing portability is fine with you, then so be it: but that’s not what C is for: it’s supposed to be the lowest common denominator of a vast array of architectures, and it does this quite effectively in no small part because it leaves things like integer overflow undefined.

                        2. 3

                          There are platforms where the behaviour of overflow is implementation defined, entirely unpredictable, or just straight up UB at a hardware level, leaving the machine in a totally invalid state.

                          Can you name one such platform? That is still used after Y2K?

                          Also note that the spirit of UB in 1989 was almost certainly a compatibility thing. I doubt the standard committee anticipated anything other than -fwrapv on regular 2’s complement processors. And it’s only later that compiler writers realised that they could interpret “UB” in a way that in this particular case was most probably against the spirit of it.

                      2. 2

                        Yes, I agree: but that’s a problem with the language spec, not the compiler.

                        Compiler writers are on the standard committee…

                        1. 1

                          I dont think defining the behaviour of overflow is desirable: programmers want overflow to happen in very rare cases and defining its behaviour now means tools cannot distinguish between overflow the programmer wanted/expected and accidental overflow (the vast majority of cases in my experience).

                          We currently can write sanitizers around overflow because its undefined, if we had defined it as wrapping the sanitizers could only say “well its wrapping, but I guess you wanted that, right ?”

                          AFAIU rust traps on overflow in debug, and defines it as wrapping in release, I believe this is mostly because they decided undefined behaviour in safe code was unacceptable, so they went with defined but very likely wrong in release.

                        2. 4

                          You lose far fewer optimisations in a language that is not C. Unfortunately, in C, it is a very common idiom to use int as the type for a loop induction variable. Having to reason about wrapping breaks a lot of the analyses that feed vectorisation. In C++ or Rust, you typically use iterations, rather than raw indexes, and these iterations will use an unsigned type by default. Operating over the domain of positive integers with wrap to zero is much simpler than operating over the domain of signed integers with overflow wrapping to a large negative number and so the C++ and Rust versions of these loops are easier to vectorise. In C, using something like size_t as the type of the induction variable will often generate better code.

                          1. 2

                            Then… how about renouncing these optimisations, and tell everyone to update their code to use size_t so it is fast again? Because I sure resent compiler writers for having introduced critical vulnerabilities, and tell everyone to fix their programs so they are safe again…

                            I mean, sometimes the hoops I have to jump through… libsodium and Monocypher for instance can’t use arithmetic left shifts on signed integers at all. Instead of x << 26 we need to write x * (1<<26), and hope the compiler will be smart enough to generate a simple shift (thankfully it is). Reason being, left shifting negative integers is straight up undefined. No ifs, no buts, it’s undefined even when the result would stay within range.

                            1. 3

                              Then… how about renouncing these optimisations

                              That’s what PCC does. It renounces all of these optimisations and, as a result, generates much slower code. OpenBSD tried to use it for a while, but even they couldn’t put up with the poor performance (and OpenBSD generally favours security over performance). The market has shown time and time again that a C compiler that generates fast code will always be chosen over one that generates more predictable code for undefined behaviour.

                              It’s not like there aren’t alternative compilers that do what you claim to want, it’s just that no one (including you) actually wants to pay the performance cost of using them.

                              1. 3

                                The market has shown time and time again that a C compiler that generates fast code will always be chosen over one that generates more predictable code for undefined behaviour.

                                Gosh, I think our mutual employer provides a strong counter-example. The incentives of a standalone compiler vendor are very different to a vendor that uses the compiler to compile billions of lines of its own production code. Our compiler adds new security features at the expense of performance continually, and internal code is required to use them. IMHO these end up at the opposite absurd end of the spectrum, like default-initializing stack variables to ensure the undefined behavior on access becomes implementation defined, stack overflow buffer checks, etc. In addition to performance vs. security, there’s also a stronger emphasis on compatibility vs. performance; updating the compiler in a way that would defeat large numbers of existing security checks would come under a lot of scrutiny.

                                1. 2

                                  I thought about MSVC’s interpretation of volatile as a counter example here (it treats it as the equivalent of sequentially consistent atomic, because that’s what a lot of internal legacy code assumed). But then I thought of all of the third-party project switching to using clang on Windows, including things like Chrome and, by extension, all Electron apps and realised that it wasn’t such a counter example after all. For a long time, MSVC was the only compiler that could fully parse the Windows headers, which gave it a big advantage in the market, now that clang can do the same, that’s eroding (I believe clang can now parse all of the Windows source code, but it can’t correctly codgen some large chunks and doesn’t generate code that is the shape expected by some auditing tools).

                                  Alias analysis is another place where MSVC avoids taking advantage of undefined behaviour. Apple pushed for making -fstrict-aliasing the default and fixed (or encouraged others to fix) a huge amount of open source and third-party code, giving around 5% better performance across the entire system. MSVC does not take advantage of type-based alias analysis because doing so would break a lot of existing code that relies on UB. This is also pushing people who have code that does not depend on illegal type punning to use clang and get more performance.

                                  Note that I am talking specifically about interpreting the standard with respect to UB to enable optimisations here. I see security flags such as /GUARD, stack canaries, InitAll, and so on as a different category, for three reasons:

                                  • They are opt in, so you can ignore them for places where you know you’re sandboxing your program or where it isn’t operating on untrusted data.
                                  • They make certain behaviour well defined, which makes it easier to reason about your source code. Not taking advantage of UB does not have this property: your program still depends on UB and may still behave in unexpected ways and your performance is now harder to reason about because it will vary hugely depending on whether, post inlining, you have enough hints in your source for the compiler to prove that the condition will not trigger.
                                  • They, in general, don’t impede other optimisations. For example, InitAll combines with stead store elimination and typically can be elided by this optimisation (and Shayne did some great work to improve this). /GUARD is applied very late in the pipeline (I worked on the LLVM implementation of this so that we could have CFG for Rust and Objective-C), and so inlining and devirtualisation can significantly reduce the number of places where you need the check (MSVC has some very impressive profile-guided devirtualisation support, which helps a lot here). In contrast, things like not assuming that integer addition results in a larger number have a big knock-on effect on other optimisations.
                                2. 1

                                  Well, there is renouncing a class of optimisations, and defining a class of behaviours. I don’t think those are the same. Which one PCC was trying? Did it define integer overflow and pointer aliasing etc. or did it disable dangerous looking optimisations altogether?

                                  it’s just that no one (including you) actually wants to pay the performance cost of using them.

                                  I put myself in a situation where I can actually cop out of that one: I tend to write libraries, not applications, and I ship source code. This means I have no control over the compilation flags, and I’m forced to assume the worst case and stick to strictly conforming code. Otherwise I would try some of them (most notably -fwrapv) and measure the impact on performance. I believe I would accept any overhead below 5%. But you’re right, there is a threshold beyond which I’d just try to be more careful. I don’t know for sure which threshold this is though.

                                  1. 1

                                    I tend to write libraries, not applications, and I ship source code. This means I have no control over the compilation flags

                                    How’s that? Libraries would still come shipped with a build system to produce (shared) objects, right?

                                    1. 1

                                      Libraries would still come shipped with a build system to produce (shared) objects, right?

                                      Not when this library is literally one C source file with its header, with zero dependency, and used on obscure embedded targets that don’t even have a standard library and I don’t know of anyway.

                                      I do ship with a Makefile, but many people don’t even use it. And even if they did, they control $CFLAGS.

                                      1. 1

                                        Ouch, that’s not an enviable situation to be in :S

                                        Too bad you can’t enforce some of those semantics using #pragma or something.

                                        1. 1

                                          Well, then again, I did it on purpose: sticking to standard C99 with zero dependency is how people ended up using it in those contexts. My work is used on a previously underserved niche, that’s a win.

                                          And in practice, I did one error of any consequence, and it was a logic bug, not anything to do with C’s UB. I did have a couple UB, but none ended up amounting to anything. (There again, it helps that my library does zero heap allocation.)

                        3. 6

                          Yes, that is exactly the by-design consequence of C UB. A single UB anywhere deep in your code could convert your computer into a giant whale or a potted plant.

                          1. 4

                            Yes. Writing code in C is a minefield, and I think people who write code in this language need to be aware of that.

                        4. 3

                          the assignment needed to be done early because I was targeting a codebase with some ancient C convention on variable declaration required to be before any code

                          If this is referring to C89 style, then you can declare a variable without assigning it:

                          int x;
                          if (...) { return -1; }
                          x = 123;
                          
                          1. 3

                            Yeah but I don’t like that for 2 reasons:

                            • 2 lines instead of 1
                            • I can’t do const int x = … anymore (and I like to use const everywhere because it helps the developer mental model about non-mutability expectations)
                        5. 4

                          Good observation. In C/C++ you are intended to check for valid preconditions before you perform an operation that relies on them. In Python and many others, there is a pervasive “look before you leap” idiom because there is no undefined behavior, either it behaves correctly or throws an exception, i.e. every operation is checked beforehand. Could be from an influx of folks into C/C++ from those languages.

                          For those who don’t understand, C/C++ does it this way because specifying “undefined behavior” allows you to assume that preconditions are valid without having to recheck them on every call, allowing the programmer to be more efficient with the CPU.

                          1. 3

                            In Python and many others, there is a pervasive “look before you leap” idiom because there is no undefined behavior, either it behaves correctly or throws an exception, i.e. every operation is checked beforehand.

                            I think “look before you leap” (LBYL) is the opposite of what you’re trying to describe. I’ve usually heard that described as “easier to ask forgiveness than permission” (EAFP).

                            1. 1

                              My mistake, I meant “leap before you look”

                          2. 1

                            Note that the order of operations doesn’t matter for UB. UB is not an event that happens. Instead, “UB can’t happen” is an assumption that the compiler is free to make, and then move or delete code under that assumption. Mere existence of any UB anywhere in your program, even in dead code that is never executed, is a license to kill for a C compiler.

                            1. 1

                              even in dead code that is never executed, is a license to kill for a C compiler.

                              No, unless you mean that it’s a license to remove the dead code (which the compiler can do anyway).

                              If code that would have undefined behaviour when executed is never executed, then it does not trigger the undefined behaviour (by definition).

                              1. 1

                                Whole-function analysis can have an effect that seems like UB going back in time. For example, the compiler may analyze range of possible values of a variable by checking its every use and spotting 2 / x somewhere. Division by 0 is UB, so it can assume x != 0 and change or delete code earlier in the function based on this assumption, even if the code doesn’t have a chance to reach the 2 / x expression.

                                1. 2

                                  For example, the compiler may analyze range of possible values of a variable by checking its every use and spotting 1 / x somewhere, and then assume x != 0 and change or delete code based on that earlier in the function, even before execution has a chance to reach the 1 / x.

                                  Yep, but if that 1 / x is in dead code it can’t affect assumptions that the compiler will make for live code. And if the 1 / x is in a particular execution path then the compiler can’t use it to make assumptions about a different path.

                                  As an example, for:

                                  if (x == 0) {
                                      printf("x is zero!\n");    
                                  }
                                  
                                  if (x == 1) {
                                      printf("1/x = %d\n", 1 / x);
                                  }
                                  

                                  … the compiler will not remove the x == 0 check based on division that occurs in the x == 1 branch. Similarly, if such a division appears in dead code, it can’t possibly affect a live execution path.

                                  So:

                                  even in dead code that is never executed, is a license to kill for a C compiler.

                                  No.

                                  (Edit, based on your edits): In addition:

                                  Division by 0 is UB, so it can assume x != 0 and change or delete code earlier in the function based on this assumption,

                                  Yes, if it is guaranteed that from the earlier code the 2 / x division must be subsequently reached, otherwise no.

                                  even if the code doesn’t have a chance to reach the 2 / x expression.

                                  No. As per above example, the compiler cannot assume that because something is true on some particular execution path it is true on all paths.

                                  If what you were claiming was true, it would be impossible/useless to perform null checks in code. Consider:

                                  if (p != NULL) {
                                      *p = 0;
                                  }
                                  

                                  If the compiler can assume that p is not NULL based on the fact that a store to *p exists, it can remove the NULL check, converting the above to just:

                                  *p = 0;
                                  

                                  This is clearly different and will (for example) crash if p happens to be NULL. But a compiler can’t and won’t make that change: https://godbolt.org/z/hzbhqdW1h

                                  On the other hand if there is a store that appears unconditionally on the same execution path it can and will remove the check, eg.

                                  *p = 0;
                                  if (p != NULL) {
                                      printf("p is not null!");
                                  }
                                  

                                  … for which both gcc and clang will remove the check (making the call to printf unconditional): https://godbolt.org/z/zr9hc7315

                                  As it happens, neither compiler will remove the check in the case where the store (*p = 0) is moved after the if block, but it would be valid for them to do so.

                            2. 1

                              I think this is the core of the issue and why people are getting so fired up.

                              If you assume that integer operations are sent to the CPU in tact, and the CPU was made in the last 30 years, then checking for overflow after the fact is a single compare.

                              If you have to check for the potential for overflow beforehand, the comparison is much more involved. I was curious what it actually looks like and stumbled onto this which implements it in four compares (and three boolean evaluations.)

                              At some level, this whole conversation becomes a disagreement about the nature of bounds checking. If you assume bounds checking does not exist (or can be compiled away!) then you can exploit UB to optimize signed arithmetic to improve performance. If you assume bounds checking needs to exist, that UB exploit is a huge negative because it forces much more pessimism to put the bounds check back, making performance worse.

                              Then we end up with compiler builtins to perform signed arithmetic deterministically. This is odd because the UB optimization assumes that if the language spec doesn’t require something it’s not needed in an implementation, but the existence of the builtin suggests otherwise. The UB optimization assumes that there’s no value in having a predictable implementation defined behavior, but the builtin is a predictable implementation defined behavior.

                              1. 1

                                It’s the observation that most of the time overflow is a bug. If you wanted overflow semantics, you should have asked for it specifically. This is how e.g. Zig works.

                                1. 1

                                  Avoiding the overflow requires a bounds check. I interpreted your earlier question being about why these bounds checks often create an overflow in order to perform the check (which is not a bug, it’s integral to the check.) There’s no standards compliant way to request overflow semantics specifically, so that option doesn’t really exist, and doing the check without an overflow is gross.

                                  If the standard had provided a mechanism to request overflow semantics via different syntax, we probably wouldn’t have such intense discussion.

                                  1. 1

                                    I agree, not having a checked add or a two’s complement add is definitely a hole in the standard and should be fixed.

                            1. 14

                              Gleam is my favorite language that I haven’t actually tried yet (but I will as soon as I get home from my traveling).

                              I read the language tour on my phone one evening, and the next evening I was reading and understanding source code. That’s how approachable the language is!

                              use is interesting because it’s a fairly complex feature, but it opens up so many options (as shown in the link). At first I was skeptical, but I think I agree. It’s worth the added complexity.

                              To give two examples of where Gleam has made (imo) interesting design decisions to keep the language simple:

                              • There is no Option[T], only Result[T, E]. If you don’t want an error, just use Result[T, Nil]. Is it more typing? Sure, but now you only have one type instead of two.
                              • A type (think struct) can have multiple constructors, each with their own fields. This means they effectively double as enums. Have a look at the docs, they explain it better than I can.

                              Anyway, congrats Louis! Very inspiring work :-)

                              1. 4

                                A type (think struct) can have multiple constructors, each with their own fields. This means they effectively double as enums. Have a look at the docs, they explain it better than I can.

                                This sounds like it’s taken straight from Haskell. (Not a criticism, just background.)

                                1. 4

                                  One could do worse things then take inspiration from Haskell!

                                  I did not know this. :-)

                                  1. 4

                                    It’s not specifically inspired by Haskell, it was mostly inspired by Erlang. I didn’t realise that Haskell had the same feature but now I read the documentation it seems very similar. Cool stuff!

                                    1. 3

                                      I mean, Gleam does belong to the ML family of languages IMO, so we may as well say the feature is inspired by Standard ML! /s

                                      1. 1

                                        In what sense does it relate to ml?

                                        1. 6

                                          Some examples of “ML-like” features include…

                                          • Sum types as a primary data modeling tool, in some cases even displacing records for small-ish data structures

                                          • First-class functions and some use of recursion, often used to constrain and thereby elucidate control flow. This is sometimes in lieu of imperative-/procedural-style constructs such as…

                                            • If/else statements (not if/else expressions)
                                            • Switch/case statements (not if/else expressions)
                                            • Goto, which has basically been a strawman against this style of programming for the past decade or so
                                            • Defer, which though it allows code to be written out-of-order, still introduces a discrete procedural “step” to computation

                                            In languages like Javascript and Gleam, this extends to the use of a syntactic construct you may know as a callback function.

                                          • Type inference (usually Damas–Hindley–Milner type inference)

                                          • Other idioms that, like the above, help to obviate and/or discourage the use of global state in implementations as they scale

                                          There are plenty of ML-like languages for different runtimes, including a few that are used for systems programming.† Languages often described as “ML-like” include…

                                          • Scala, ‘an ML for the JVM
                                          • F#, ‘an ML for the CLR
                                          • Elm, which also takes some inspiration from Haskell while not going quite as far with the generics, apparently for sake of error message readability
                                          • Facebook’s Reason, which is sometimes even called ReasonML for clarity
                                          • Rust, one of the only systems programming languages to have this distinction. Check for the features above if you don’t believe me!

                                          Haskell is explicitly inspired by ML, but is often considered its own category due to the radical departures it makes in the directions of a) purely functional programming and b) requiring (in most cases) the use of monads to represent effects in the type system.


                                          My educated guess: This is largely because the core syntax and feature-set is relatively well understood at this point. As such syntactic sugar is rarely necessary in order to express intent directly in efficient code. This is unlike in “dynamic” languages such as Python, Ruby, and Elixir, which tend to make liberal use of metaprogramming in order to make the syntax more directly express intent. This can often make it unclear what is actually happening to make a given piece of code run.

                                          1. 3

                                            I find it interesting that nothing on that list is inherent to functional languages. All these sweet goodies might as well exist in an imperative language, but outside of Rust, they don’t.

                                            I’m still sad Go completely missed the boat on that one.

                                            1. 1

                                              Yup. Maybe someday we’ll have an approach in between those of Go and Rust; that’s some of what I’m looking to Gleam for, even if it’s not primarily a systems programming language.† In the meantime, we have the sometimes-insightful, sometimes-regressive minimalism of Go; and the sometimes-insightful, sometimes-overwhelming maximalism of Rust.


                                              † It is my broad understanding that the BEAM VM—on which I expect most* Gleam code will run—helps concurrent applications scale by denying granular control of threaded execution. This can be thought of as vaguely similar to the Go runtime’s decision to have a blessed implementation of cooperative multitasking, namely goroutines. In contrast, the Erlang ecosystem benefits from having a blessed provider and model (respectively) for all concurrent computation, thanks to the OTP supervision tree combined with the actor model of concurrent computation. It takes power away from the developer, but to the benefit of the system at large. Boy, is it ever exciting that we might actually have a statically-typed language built atop that excellent multitasking infrastructure!

                                              1. 1

                                                From my PoV Go and Rust are incomparable since Go is a GC’d language and Rust is a non-GC’d language. So on this basis Gleam, too, can never compete with Rust but is for sure a strong contender in the space Go plays in.

                                                1. 1

                                                  If all that matters is the engine that runs your code, the sure. If a project is performance-sensitive, then its options for reasonable programming language are constrained anyway IMO. When I compare these languages, I have their developer experience in mind. At least, relative to how much performance they leave on the table.

                                              2. 1

                                                It honestly depends what one even means by “functional language” lots of ML and ML-like things exist which are not particularly functional including possibly: SML, OCaml, Swift, Scala, Kotlin, Haxe

                                                1. 2

                                                  What’s not-functional about SML, OCaml, and Scala? Are you perhaps comparing them to the purely functional Haskell?

                                                  1. 1

                                                    What’s functional about them? Every language I listed is equally functional and not-functional depending how you use it. They’re all ML variants after all.

                                              3. 2

                                                Facebook’s Reason, which is sometimes even called ReasonML for clarity

                                                Credit where credit is due: Reason is a syntax extension for OCaml. It’s not a whole cloth creation by Facebook.

                                              4. 3

                                                I think it is an ML language in every way, although we moved away from the traditional ML syntax in the end.

                                      1. 2

                                        Huh. Do-notation but adapted to callbacks. Fascinating. Loved the examples, too. Excited to see what this opens up!

                                        1. 5

                                          I highly recommend watching Guy Steele’s Growing a Language for the counter-argument.

                                          The pertinent question is: where do you want to develop new behavior? In the compiler, or in library code? I assert that compiler features are inherently more risky, and much harder to write.

                                          1. 3

                                            Perhaps there’s an apt analogy to be made between the friction involved with changing the compiler from underneath the code written for it, and changing words in a closed linguistic class from under a spoken language’s speakers. Changes at the foundation level seem to shake things up for people’s thought process (how they grok syntax, how they think about their programs) more so than adding sugar at the top of the stack.

                                            I think it’s just one of the challenges of designing any formal method of human expression, let alone programming languages: the goalposts are always shifting, but no one wants to update the rulebook. So they just invent a new sport instead. It’s a silly dance we do, but there may be no good way around it. Just one area of many where we “elegance”-loving coders perhaps need to tolerate some amount of inevitable inelegance.

                                          1. 18

                                            It would be good in general if people were more aware of the political considerations of choosing a TLD and the dangers they might pose to a registration.

                                            I’ve seen people using .dev and .app a lot, it’s worth considering these are Google-controlled TLDs. What really rubbed me the wrong way about these TLDs is Google’s decision to make HSTS mandatory for the entire TLD, forcing HTTPS for any website using them. I’m sure some people will consider this a feature but for Google to arbitrarily impose this policy on an entire TLD felt off to me. No telling what they’ll do in the future.

                                            1. 12

                                              .app and .dev aren’t comparable to ccTLDs like .sh and .up, however. gTLDs like .app and .dev have to stick to ICANN policies; ccTLDs don’t, and you’re at the mercy of the registry and national law for the country in question.

                                              1. 11

                                                I was actually just discussing this fact with someone, but interestingly, we were discussing it as a positive, not a negative.

                                                All of the newTLDs are under ICANN’s dominion, and have to play by ICANN’s rules, so they don’t provide independence from ICANN’s influence. Whereas the CCTLDs are essentially unconditional handouts which ICANN can’t exert influence over. So there’s a tradeoff here depending on whom you distrust more: ICANN, or the specific country whose TLD you’ve chosen.

                                              2. 10

                                                HSTS preload for the entire TLD is brilliant idea, and I think every TLD going forward should have it.

                                                Defaulting to insecure HTTP URLs is a legacy problem that creates a hole in web’s security (it doesn’t matter whats on insecure-HTTP sites, their mere existence is an entry point for MITM attacks against browser traffic). TOFU HSTS is only a partial band-aid, and per-domain preload list is not scalable.

                                                1. 1

                                                  Does HTTPS really count as TOFU? Every cert is ultimately checked against a known list of CAs.

                                                  1. 4

                                                    The Trust-On-First-Use aspect is that HSTS is remembered by the browser only after the browser has loaded the site once; this leaves first-time visitors willing to connect over unencrypted HTTP.

                                                    (Well, except for the per-domain preload list mentioned by kornel.)

                                                    1. 2

                                                      Sure, but HSTS is strictly a hint that HTTPS is supported, and browsers should use that instead, right? There is no actual trust there, because the TLS certificate is still authenticated as normal.

                                                      Compare this to SSH, which actually is TOFU in most cases.

                                                      1. 3

                                                        Not quite - HSTS prevents connection over plaintext HTTP and prevents users from creating exceptions to ignore invalid certificates. It does more than be a hint, it changes how the browser works for that domain going forward. The TOFU part is that it won’t apply to a user’s first connection - they could still connect over plaintext HTTP, which means that a suitably positioned attacker could respond on the server’s behalf with messages that don’t include the HSTS header (if the attacker is fast enough). This works even if the site itself isn’t serving anything over HTTP or redirects immediately to HTTPS.

                                                        Calling it TOFU is admittedly a bit of a semantic stretch as I’m not sure what the specific act of trust is (arguably HSTS tells your browser to be less trustful), but the security properties are similar in that it only has the desired effect if the initial connection is trustworthy.

                                                        1. 1

                                                          Okay, I see the point about first-time connections, but that wouldn’t change regardless of the presence or absence of HSTS. So why single that header out? It seems to me that having HSTS is strictly better than not having one.

                                                          1. 2

                                                            The discussion was about HSTS preload which avoids the first connection problem just explained by pre-populating HSTS enforcement settings for specific domains directly in the browser distribution, so there is no risk of that first connection hijack scenario because the browser acts as if it had already received the header even if it had never actually connected before.

                                                            Normally this is something you would opt-in to and request for your own domain after you registered it, if desired… but Google preloaded HSTS for the entire TLDs in question, so you don’t have the option to make the decision yourself. If you register a domain under that TLD then Chrome will effectively refuse to ever connect via http to anything under that domain (and to my knowledge every other major browser uses the preload list from Chrome.)

                                                            It’s this lack of choice that has some people upset, though it seems somewhat overblown, as Google was always very upfront that this was a requirement, so it shouldn’t have been a surprise to anyone. There is also some real concern that there’s a conflict of interest in Google’s being effectively in total control of both the TLDs and the preload list for all browsers.

                                                            1. 1

                                                              The discussion was about HSTS preload which avoids the first connection problem just explained by pre-populating HSTS enforcement settings for specific domains directly in the browser distribution, so there is no risk of that first connection hijack scenario because the browser acts as if it had already received the header even if it had never actually connected before

                                                              Ahh, THIS is the context I was missing here. In which case, @kornel’s original comment about this being a non-scalable bandaid solution is correct IMO. It’s a useful mitigation, but probably only Google could realistically do it like this.

                                                              I think the more annoying thing about .dev is that a bunch of local development dns systems like puma-dev and pow used .dev and then Google took it away and made us all change our dev environments.

                                                              1. 2

                                                                I think the more annoying thing about .dev is that a bunch of local development dns systems like puma-dev and pow used .dev and then Google took it away and made us all change our dev environments.

                                                                That seems unfortunate, but a not terribly surprising consequence of ignoring the names that were specifically reserved for this purpose and making up their own thing instead.

                                                    2. 1

                                                      I mean user typing “site.example.com” URL in their browser’s address bar. If the URL isn’t in the HSTS preload list, then it is assumed to be HTTP URL and HTTPS upgrade is like TOFU (the first use is vulnerable to HTTPS-stripping). There are also plenty of http:// links on the web that haven’t been changed to https://, because HTTP->HTTPS redirects keep them working seamlessly, but they’re also a weak link if not HSTS-ed.

                                                  2. 5

                                                    uh! I chose .app (unaware, stupid me) for a software project that discarded the Go toolchain for this very reason. Have to reconsider, thx!

                                                    1. 3

                                                      I have no idea where to even start to research this stuff. I use .dev in my websites but I didn’t know it was controlled by Google. I legitimately thought these all are controlled by some central entity.

                                                      1. 2

                                                        I have no idea where to even start to research this stuff.

                                                        It is not really that hard. You can start with https://en.wikipedia.org/wiki/.dev

                                                        If you are going to rent a property (domain names) for your www home and if you are going to let your content live in that home for many years it pays off to research this stuff about where you are renting the property from.

                                                        1. 1

                                                          .test is untainted.

                                                          1. 6

                                                            Huh? There’s no registrar for .test, it’s just for private test/debug domains.

                                                      1. 4

                                                        Link to the playlist without auto-starting the first video: https://www.youtube.com/playlist?list=PLqj39LCvnOWbmaPrkGCAzFMC_FYZUkmSr

                                                        1. 8

                                                          Flagged as off-topic. There’s nothing technical to discuss here and the void will be filled with pot-shots at vague statements.

                                                          1. 1

                                                            Understood. I personally believe that matters regarding open source sustainability do have a home here on Lobsters, but I also know that not everyone feels the same. Thank you for explaining your reasoning.

                                                          1. 24

                                                            To preserve the community aspect of Gitea we are experimenting with creating a decentralized autonomous organization where contributors would receive benefits based on their participation such as from code, documentation, translations, and perhaps even assisting individual community members with support questions.

                                                            The worrying part…

                                                            1. 10

                                                              An enhanced enterprise version

                                                              is the worrying part for me as well. Does that mean those enhancements are proprietary?

                                                              1. 5

                                                                I heard a rumor that they’re not actually intending to launch their own coinscam and that the way it was announced it came across differently from the actual intention but I don’t have a reliable source to back that up yet. It’s reasonable to be concerned about this but I wouldn’t write them off yet.

                                                                1. 12

                                                                  This was the reply I got: https://twitter.com/giteaio/status/1585297381926793216

                                                                  1. We don’t plan on selling crypto or creating some shitcoin
                                                                  2. the DAO was mentioned as a possible way to ensure public and transparent community governance, but I believe it is possible to do that without cryptocurrency (still investigating if that is indeed possible, but… wanted to be upfront with areas we were exploring.)

                                                                  (Although I’ve since noticed that have at least one sponsor who is blockchain-related which is also bad.)

                                                                  1. 6

                                                                    Allegedly, that sponsor made a one-time donation a good couple of years ago, and has not done so since, so it’s listed for historical reasons only.

                                                                2. 2

                                                                  Yeah, that probably means gitea is going to have to go in the bin for me. Which is a shame because I was quite liking it as a self-hosted solution.

                                                                  1. 4

                                                                    How so ? They haven’t actually done anything you can blame them for, they’re just trying to find ideas for something that hasn’t been completely solved. How about you help them finding better ones ?!

                                                                    1. 7

                                                                      They haven’t actually done anything you can blame them for

                                                                      “gitea is going to have to go in the bin for me” … if they implement a blockchain-based DAO. Apologies, I thought that was implicit but I could have made it explicit.

                                                                  2. 1

                                                                    Look, this is inevitable. However it is worrying in the sense that it matters how it is implemented, ethereum is not a real solution … these matters are too serious to just roll with whatever is around.

                                                                    As an aside; I wonder what happened to mathematics… people are content with a theorem prover thing sitting on top of a massive amount of proprietary foundations?!

                                                                    Mathematics is only convincing if you can trace the argument down to the axioms. Obviously the proofs stand on their own so technically you don’t need to run the theorem prover to be sure that it is correct, however, people build these theorem provers so that they can trust the verdict it provides.. and we will be heading into the future on this foundation?! It’s laughable and from my point of view it is because the free software world has not established a proper negotiation position; which is exactly what risk assessments and credit systems will give us.

                                                                    1. 1

                                                                      Agreed. I do think this is preferable to an SSPL-like solution. Ultimately, I suppose there is no effective way to take back from the greedy without being greedy yourself.

                                                                      Funny enough, I had to stop myself from tagging the story under merkle-trees, since I anticipated that the short paragraph you quoted would become a big part of the discussion.

                                                                      1. 2

                                                                        I mean, Git is literally a Merkle tree, so the tag should be appropriate? I do understand why we can’t call programming hacking and cryptography crypto any more, but still…

                                                                        1. 2

                                                                          The linked article isn’t about Git, it’s about an organization that’s providing VCS as a service, and how it’s planning to fund itself in the future.

                                                                        2. 2

                                                                          Ultimately, I suppose there is no effective way to take back from the greedy without being greedy yourself.

                                                                          That sounds like an easy justification for a lot of things.

                                                                          1. 1

                                                                            Wasn’t meant as a justification so much as an observation. I personally think the best response to greed is… nothing. Call it out and move on. Two wrongs don’t make a right.

                                                                        3. 1

                                                                          Why is that worrying? That if you write a lot of code you’ll get more privileges? Is there a concern about state actors breaking gitea through the front door?

                                                                          1. 10

                                                                            It’s worrying because “decentralized autonomous organization” usually means some crypto-currency-related thing. That means the project will get flooded by cryptobros who want to use the project as leverage to (a) legitimise crypto-currency, (b) financially exploit each other, or (c) both, rather than contributing to the project itself.

                                                                            1. 1

                                                                              Ah, thanks for explaining! I didn’t catch the connection between the terms used and cryptocurrency stuff.

                                                                        1. 10

                                                                          Gleam seems like a really cool language! I really like the design of Elixir, but I would love something statically typed. Something with first-class concurrency like Go, without the corner cases, and with functional programming creature comforts like ADTs to allow for composable error handling. The BEAM seems to me like the most mature platform for concurrent & distributed programs, and being ML-like gives you much of the rest “for free”. Perhaps I’m misunderstanding what Gleam is at present, but I think the language has a lot of promise.

                                                                          That being said, I’m not entirely sure what the roadmap is. I’ve looked through the website a couple times, and noticed the docs were somewhat incomplete and there weren’t yet a lot of facilities for creating & using generic types.

                                                                          Is assistance with evolving the language design welcome? Alternatively, is there a roadmap somewhere to guide a prospective contributor to high-priority issues or good first issues?

                                                                          1. 3

                                                                            Hello! Thanks for the support!

                                                                            Perhaps I’m misunderstanding what Gleam is at present, but I think the language has a lot of promise.

                                                                            Yes, I think you have an idea of the goals :)

                                                                            That being said, I’m not entirely sure what the roadmap is.

                                                                            The planned additions can be found in the issue tracker. We’re low on time so there’s not lots of detail in the tickets (most the discussion happens in Discord) but if anything catches your eye I’m happy to add extra info to specific tickets.

                                                                            Tickets that are good to start with have been labelled as such, and more will be added in future.

                                                                            Is assistance with evolving the language design welcome?

                                                                            Drop by the Discord and get involved! That said the language has matured somewhat and there’s not going to be any large changes in future.

                                                                            1. 3

                                                                              I’m “excited from afar” about Gleam, and it seems like maybe it’s mature enough for me to begin exploring. I haven’t used a BEAM language–besides networked services, what other use cases is Gleam a good fit for? I don’t think I’ve seen many CLI tools implemented in a BEAM language, for example. Even within the context of networked services, does just using Gleam pretty much get me all of the supervisor tree / reliability goodness that I hear about with Erlang, or do I need to opt into some framework? And if I use Gleam, will I effectively have to learn Erlang and/or Elixir? How much interop is there in the ecosystem, and how much is the user exposed to it?

                                                                              1. 5

                                                                                I haven’t used a BEAM language–besides networked services, what other use cases is Gleam a good fit for? I don’t think I’ve seen many CLI tools implemented in a BEAM language, for example.

                                                                                It’s a general purpose programming language with a virtual machine and a garbage collector, so all sorts really. I use it mostly for web services and little CLI tools that I use personally. I also have some frontend SPAs and widgets written in Gleam compiled to JavaScript.

                                                                                If I were to make CLI tools that I wanted to ship to users I would probably compile the Gleam to JavaScript and bundle it into one file. It’s a bit easier to distribute it like that then to ask people to install the Erlang virtual machine.

                                                                                Even within the context of networked services, does just using Gleam pretty much get me all of the supervisor tree / reliability goodness that I hear about with Erlang, or do I need to opt into some framework?

                                                                                The Erlang framework that offers these properties is called OTP and you can use it from Gleam like any other BEAM language. We’ve got our own version called gleam_otp which is statically typed.

                                                                                Most the time when writing web applications and such you can largely ignore it and the web server, database client, etc will all be written using the framework, giving you those properties.

                                                                                And if I use Gleam, will I effectively have to learn Erlang and/or Elixir? How much interop is there in the ecosystem, and how much is the user exposed to it?

                                                                                You don’t have to, but if you’re looking to use libraries we don’t have binding for it’ll help to learn some Erlang. Some Gleam users have never written any Erlang, others do a lot of it as they bring new APIs to Gleam. It largely depends on what you’re looking to do currently while the ecosystem is younger.

                                                                                1. 2

                                                                                  This is great news. Really excited that it sounds like a lot of the networked services ecosystem leverages OTP already (rather than it being more niche). Personally, I’d prefer to have self-contained binaries for CLI tools, but that’s not much of a big deal–I can probably use Go or similar if that’s really important to me. I’ll play around with it soon. 👍

                                                                          1. 35

                                                                            This seems to miss the big issue of: some of those threads would not exist somewhere else. It’s one thing to complain about the interface which is a twitter problem. But “stop writing twitter threads” effectively means “I don’t like this so much, others shouldn’t have the chance to experience it at all”.

                                                                            There are people like foone and swiftonsecurity who could possibly write somewhere else but won’t change for $reasons and the medium works for them so you can only choose to not engage.

                                                                            1. 6

                                                                              This is a good point. However, I would point there are a lot of blogging platforms that offer free accounts; and creating your own blog is not that complicated. I wish Internet Service Providers still had the same mentality as back in the days, when (at least in France) they would offer an FTP with some disk space where you could host your (static or dynamic) website. This is how the whole blogging thing took off in the late 90s/early 2000s.

                                                                              1. 25

                                                                                It’s not about the availability of blogging platforms, but the way the medium works in the moment for some. For example see https://nitter.net/Foone/status/1066547670477488128

                                                                                1. 3

                                                                                  Foone’s threads are delightful and I find them very easy to read. ❤️

                                                                                  I wish Twitter had a couple of extra features like a button to jump to the top of the current thread and an easy way to see all the replies to an individual tweet inside a thread.

                                                                                  1. 2

                                                                                    Interesting challenge for the fediverse: make a server where people like foone can jot out tiny posts in a thread, but readers can view it as an unadorned stream-of-consciousness post (no replies, no ads).

                                                                                    1. 3

                                                                                      Interesting idea, but I’d be sceptical that it works. A stream of consciousness, written bite-sized and then glued together, reads like a rough draft. Some form of visual separation needs to be applied to make the readers aware that they are not reading a polished product.

                                                                                      1. 1

                                                                                        I hear you, but I recall being forced to read “The Old Man and the Sea” at school, and many automatically-reconstituted tw––r threads have been at least as coherent and interesting as that. :)

                                                                                    2. 1

                                                                                      I sure hope Foone doesn’t find out about this thread, they have a very low opinion on people bashing their tweets as it is.

                                                                                      1. 1

                                                                                        Right - it closely models just talking about it in something like IRC, without the friction.

                                                                                      2. 6

                                                                                        Even if those blogging platforms were magically even easier to use than Twitter, it would still be close to meaningless because Twitter has the eyeballs.

                                                                                        (To be clear, I share your preferences but it’s a pointless battle to fight unless you can solve the real forces that drive why things are the way they are.)

                                                                                        1. 1

                                                                                          My periodic reminder to any uninitiated readers that there is a name for this phenomenon: a network effect.

                                                                                      3. 3

                                                                                        some of those threads would not exist somewhere else

                                                                                        What is your thesis here? That free Twitter accounts are easier to create than free Wordpress, Substack, or $your_favorite_blogging_platform accounts?

                                                                                        Or is it that content authored as Twitter threads would not otherwise exist because authors are already logged into Twitter, rendering it the easiest place to author one’s thoughts?

                                                                                        I can see some ways in which your argument is correct, and many in which it can be dismissed.


                                                                                        Good ideas deserve a better reading experience than twitter threads. In addition to a better reading experience, alternative platforms – e.g. writing text/markdown in a Gist – are a significantly better authoring experience. URLs to better reading experiences can be cross-posted to Twitter to gain access to the “eyeballs” on Twitter.

                                                                                        1. 3

                                                                                          Swiftonsecurity used to post on a blog and it was great! I really miss those days.

                                                                                          1. 3

                                                                                            People write to be read. For better or worse, there are a lot more readers on Twitter than other, better platforms. Ergo, threads.

                                                                                            1. 1

                                                                                              I made abundantly clear in my comment that I understand the concept of optimizing for one’s readers. Ergo, give readers a better reading experience, not threads.

                                                                                              1. 2

                                                                                                I do not like the threads, but people seem to like “lots of readers - threads” more than “a well designed reading experience - readers”.

                                                                                            2. 2

                                                                                              The second one (see the explanation I linked for example) + twitter is its own kind of medium. Where else can you effortlessly link to / embed other bits of content the same way, continue a post from years ago while bringing only the new part into focus, post both a one line comment and a multi-page story without either looking out of place. I think SwiftOnSecurity basically mastered the medium - if that content existed somewhere else, it would change. The form of Twitter threads shapes the content itself.

                                                                                              1. 2

                                                                                                Foone, for one, has said that the twitter format is what enables them to post. That flow of think, then type in a very short burst, then hit “post” works especially well for their brain, and if they needed to write a blog in order to post they would not do it and would feel bad about all the unfinished blog posts in their backlog.

                                                                                                Looking at the number of unfinished blog posts in my own backlog, I understand a little bit where they’re coming from.

                                                                                                So when I see a twitter thread, even though I very much don’t enjoy reading it in that format, I just use one of the alternative twitter frontends to roll it together and read it that way. Because I suspect that Foone is not alone, and some stuff only exists because it can go out with very low friction like it can on twitter. And it’s interesting enough that I’d rather see it published in a format I don’t like than see it sit unpublished in someone’s backlog and never learn about it.

                                                                                                1. 1

                                                                                                  I think it’s self evident that if writers aren’t able to write with certain tools, then they can and should use the tools that work for them. If Twitter threads allow them to write most effectively – great; they should use Twitter threads.

                                                                                                  In my opinion, this discussion began not about those people, but about the readers who have to endure the reading experience that twitter threads mandate. I think it’s important to finish that conversation before having one about author UX.

                                                                                                  Obviously the clickbatey title lacks nuance, but if one were inclined to rewrite it, it might read “Please stop writing Twitter threads if you can help it”.

                                                                                                  1. 2

                                                                                                    I would actually push a small step further: we should start with the assumption that authors have considered alternatives, and found them lacking for some reason.

                                                                                                    It obviously never hurts to ask nicely, but the assumption that people don’t know twitter sucks to read and if we just tell them about it, they’ll instantly see the wisdom of maintaining their own site or otherwise altering their workflow, can seem more than a bit condescending.

                                                                                                    The discussion began about the readers, to be sure. But you mentioned the authoring experience and that made me think of Foone’s comments. The reading experience would be worse if authors stopped publishing.

                                                                                                    (With that said, I hope everyone who can stand to moves right off twitter. I don’t enjoy reading there, especially since the attempts to make me log in just to read have gotten more and more aggressive lately.)

                                                                                              1. 4

                                                                                                Excellent find! I especially loved the riveting breakdown of the process by which they found the offending app. No one should have to deal with this kind of stuff from lazy, non-communicative developers; but since we are, it’s amazing the kind of detective work some devs are able to pull off.

                                                                                              1. 1

                                                                                                This isn’t quite the setup I picture regarding a “static html website” (since it requires a backend and a database running on the web server), but it’s an interesting approach to turn a normally database backed feature into a static one

                                                                                                1. 1

                                                                                                  static =/= files. Static means not dynamic, i.e., no content is generated on-the-fly.

                                                                                                1. 4

                                                                                                  Sadly, in industry many people are forced to work in languages with a weak type system, such as Haskell.

                                                                                                  This is a joke, right? I’m genuinely confused.

                                                                                                  1. 7

                                                                                                    It’s a joke, but the joke is funny because Agda’s type system is much stronger than Haskell’s.

                                                                                                    1. 2

                                                                                                      Ok, that’s what I was thinking. Glad it wasn’t just me who thought that 😅

                                                                                                  1. 8

                                                                                                    After reading this I thought that it would be better if it were an extension that did this without having to click a button and for websites other than twitter. I decided to search and found https://addons.mozilla.org/en-US/firefox/addon/redirector/?utm_source=addons.mozilla.org&utm_medium=referral&utm_content=search

                                                                                                    1. 13

                                                                                                      I prefer bookmarklets for a few reasons:

                                                                                                      Compatibility

                                                                                                      Bookmarklets work on all devices. Deskop, iOS and Android.

                                                                                                      Security

                                                                                                      I can easily read and understand the code.

                                                                                                      Flexibility

                                                                                                      They are easy to change. For example in this one, I will probably update the array of nitter instances regularly.

                                                                                                      Usability

                                                                                                      I can organize them just like my other bookmarks.

                                                                                                      Sharing

                                                                                                      Sharing a bookmark is as easy as copy/pasting a line of text

                                                                                                      1. 8

                                                                                                        For what it’s worth, I really like bookmarklets for the security reasons alone. I know they they aren’t running any code until I click on them (unlike extensions). It’s much easier to check that nothing nefarious is going on behind the scenes. Even the simplest extensions have multiple files of boilerplate code, and they can be updated remotely. I hate to think what would happen if the developer’s account got compromised for any of the popular extensions.

                                                                                                        Unfortunately, it seems like Chrome on Android doesn’t support bookmarklets – or at least fails on ones imported from my desktop.

                                                                                                        1. 7

                                                                                                          Extensions are updated remotely without user interaction? That is another scary aspect.

                                                                                                          For me, the bookmarklet works fine on Chrome on Android. I have to use it from the address bar though. I named it “t2n” and when I am on a Twitter page, I type “t2n” into my address bar. Now from the list of suggestions I click on the bookmarklet and it works.

                                                                                                          1. 8

                                                                                                            Bookmarklets can’t get sold to a hostile data-collecting advertising company while you weren’t paying attention.

                                                                                                        2. 2

                                                                                                          Yeah these are good points. Have you also see Fraidycat which has slightly different aims?

                                                                                                          1. 1

                                                                                                            This looks awesome! I’ve been looking for something similar for a while. Thank you for sharing :)

                                                                                                          2. 2

                                                                                                            that’s fair but i personally find extensions more convenient 🤷

                                                                                                            1. 2

                                                                                                              Problem with using a redirect extension is:

                                                                                                              • It doesn’t always redirect
                                                                                                              • Often, the nitter instance is throttled so you have to disable the extension
                                                                                                              1. 2

                                                                                                                redirection via an extension sometimes just doesn’t work? not all that surprising I guess.

                                                                                                                an extension could pick a random instance just like the bookmarklet though

                                                                                                            2. 1

                                                                                                              I’d did not know bookmarklets worked on iOS. That’s pretty rad!

                                                                                                            3. 4

                                                                                                              This is the extension I use https://libredirect.github.io/

                                                                                                              1. 1

                                                                                                                Privacy Redirect is similar. Found some alternatives I didn’t know about in there.

                                                                                                              1. 25

                                                                                                                Their source code is in a git repo, but as a set of patches against releases, which makes contributing to them hard. This is particularly odd given their complaints about the Thunderbird workflow.

                                                                                                                I’d love to see something a bit more explicit about why they feel the need to maintain a fork rather than working with upstream. There are some hints, but a lot of them could be interpreted as ‘we’re a bunch of people that no one wants to work with who are convinced that we’re always right’.

                                                                                                                None of their bug fixes are particularly compelling for me. The things I’d like to see from Thunderbird are:

                                                                                                                • Not periodically freezing on Windows.
                                                                                                                • Never performing destructive operations in response to a key press without a modifier held, so that if it steals focus while I’m typing (ideally, for it not to ever do this) then I don’t do some mailbox manipulation operations and have to figure out how to do them (Apple’s Mail.app on macOS has an undo button for all of these operations and the undo menu tells you what you’re undoing).
                                                                                                                1. 5

                                                                                                                  There is some context about their need to maintain a fork, a link at the bottom of the FAQ. It looks like this is the outcome of some conflict?

                                                                                                                  1. 22

                                                                                                                    Heh, wow he even publishes the e-mails from the Thunderbird Council containing the accusations against him (not sure he comes out looking as good as he may think he does there). Tl;dr, he was temporarily banned from participation in Thunderbird for being abrasive, broke the conditions of said ban, then got banned permanently from the entire Mozilla community. He now blames cancel culture.

                                                                                                                    1. 4

                                                                                                                      Source: https://betterbird.eu/faq/moz-governance.pdf if you scroll down to the attached Email

                                                                                                                      I think the patch-based approach is very brittle. And I’m not sure what to think of such accusations, which are directly related and affecting the project.

                                                                                                                1. 6

                                                                                                                  Isn’t unencrypted SNI also an issue for VPNs?

                                                                                                                  1. 4

                                                                                                                    Yeah and this paper suggests that “only around 1.5%–2.25% of domains on the Internet have ESNI supported” and that “ Cloudflare […] is the only Internet company supporting ESNI to the best of our knowledge”

                                                                                                                    1. 1

                                                                                                                      Cloudflare […] is the only Internet company supporting ESNI to the best of our knowledge

                                                                                                                      Where do they support this? Is it in their function as a DNS / hosting provider for other people’s domains?

                                                                                                                      1. 4

                                                                                                                        ESNI

                                                                                                                        Cloudflare is MitMaaS for their DDoS protection. That’s where it’d come into play.

                                                                                                                        1. 1

                                                                                                                          Ah, I see. Weird. So then, the main subject of contemplation for me: these people couldn’t find a single actual hosting provider that supports ESNI? Or were they just not looking hard enough?

                                                                                                                          1. 2

                                                                                                                            check for yourself, it’s easy enough to query for TXT records on _esni.$DOMAIN.$TLD names. In fact, it looks like even _esni.cloudflare.com no longer returns a TXT record. Additionally, ESNI firefox has fully deprecated it, so we’re very much in a liminal state in between ESNI and ECH.

                                                                                                                    2. 4

                                                                                                                      In the trace we collected for that VPN leak / analysis video, only a tiny fraction (a few percent IIRC) of the requests were using Encrypted Client Hello.

                                                                                                                    1. 3

                                                                                                                      When I see a new language like this, that’s high-level-ish but doesn’t have safety guarantees, I think to myself, “When would I use this and not Zig?”

                                                                                                                      Explanation: In my opinion, Zig’s design does an excellent job at ensuring its features are orthogonal, and it stays really simple—heck, even generics are written similar to how functions are! Another niche language meeting those criteria would have to do a lot to compete with Zig’s excellently designed C interop and bit-twiddling creature comforts.

                                                                                                                      The only thing I can think of is method calling syntax, which is necessary for the object-oriented style of dispatching on the first argument’s type. But who knows, maybe there are other aspects of polymorphism that Zig is missing. Or… maybe even Zig is too low-level for some people. Maybe what people really want is Java without the JVM; or to look at it another way, the monolith that is C++, but without the leftover cruft from C.

                                                                                                                      1. 3

                                                                                                                        Alumina author here - the C++ comparison is spot on. C++ used to be my favourite language by far and I used to wish for a language that would be as elegant and powerful but without all the arcane syntax from C and the header files approach.

                                                                                                                        Then Rust came along which scratched that itch almost perfectly and had additional things that I didn’t even know I wanted (e.g. memory safety and enums), but gung-ho bit fiddling can be fun. Rust is far more restrictive in what you can do in unsafe blocks and many things are UB that would be perfectly legal in C.

                                                                                                                        1. 1

                                                                                                                          Ah, got it. Zero-cost abstractions as a singular focus. Very cool!

                                                                                                                          1. 3

                                                                                                                            Yeah, this was definitely a big focus.

                                                                                                                            A random bit of trivia: I was actually surprised at how much of zero-costness I was able to get for free by targeting C as the backend. For example this function uses iterators and closures and results in ~900 lines of generated C code with a ton of small helper functions.

                                                                                                                            #[export]
                                                                                                                            fn sum_of_mod_n(upper: u64, modulo: u64) -> u64 {
                                                                                                                                (1u64..=upper)
                                                                                                                                    .filter(|=modulo, n: u64| -> bool { n % modulo == 0 })
                                                                                                                                    .map(|n: u64| -> u64 { n * n })
                                                                                                                                    .sum()
                                                                                                                            }
                                                                                                                            

                                                                                                                            But the C compiler is still able to optimize this into a very straightforward loop with no overhead.

                                                                                                                            https://godbolt.org/z/4reY43GzP

                                                                                                                      1. 2

                                                                                                                        This looks like a logic error:

                                                                                                                        if (mask & (WGPUColorWriteMask_Alpha|WGPUColorWriteMask_Blue)) {
                                                                                                                            // alpha and blue are set..
                                                                                                                        }
                                                                                                                        

                                                                                                                        Shouldn’t it be this?

                                                                                                                        if ((mask & WGPUColorWriteMask_Alpha) && (mask & WGPUColorWriteMask_Blue)) {
                                                                                                                            // alpha and blue are set..
                                                                                                                        }
                                                                                                                        
                                                                                                                        1. 2

                                                                                                                          No, because that requires that both flags are set. The equivalent condition to s & (A|B), which works no different, would be (s & A) || (s & B).

                                                                                                                          Notice the commonality in how the bitmasks are joined: always with some form of the disjunctive (“or”) operator, either bitwise | or boolean ||. In any case, the bitmask A or B must be applied to the operand s using the & bitwise “and” operator: s & A, s & B, s & (A|B).

                                                                                                                          The equivalent operation to your “correction” (s & A) && (s & B), using the technique of joining the bitmasks first, would be s & (A|B) == A|B. This checks that all of the bits are set, rather than that any of the bits are set.

                                                                                                                          Edit: I got confused 😅 You are right: the original code tests whether either alpha or blue is set. My initial comment above would have been applicable if the commented-out text had read, “// alpha OR blue is set..”. I think that’s as good a case as any for “tagged” bit-fields over “untagged” bit-masks.

                                                                                                                          Note for any lurkers who have read this far and are rather confused: You may want to read up on how bitmasks are used.

                                                                                                                          1. 2

                                                                                                                            Which makes either the comment or the code wrong. The comment says “and” not “or”. @smaddox was matching the code to the comment

                                                                                                                          2. 2

                                                                                                                            As others have pointed out, the comment is a bit misleading. But if you want to check if both are set, this would work:

                                                                                                                            if (mask & (WGPUColorWriteMask_Alpha | WGPUColorWriteMask_Blue) == (WGPUColorWriteMaskAlpha | WGPUColorWriteMask_Blue))
                                                                                                                            {
                                                                                                                                // alpha and blue are set ...
                                                                                                                            }
                                                                                                                            
                                                                                                                            1. 1

                                                                                                                              Wouldn’t the | operator join the two bit masks together to create a new intermediate with both bits set? It’s a matter of A == (B|C) versus (A==B) && (A==C) at this point.

                                                                                                                              1. 3

                                                                                                                                It does, but you get “or” instead of “and”. If either bit is set, the result is not zero.

                                                                                                                                1. 2

                                                                                                                                  Correction: (A == B) && (A == C) is always false (0) when B != C, due to the transitive property of strict equality. You probably meant (A & B) && (A & C). See my other comment.

                                                                                                                              1. 3

                                                                                                                                Great language! It seems to fix pretty much all issues I had with Elm.

                                                                                                                                Why are function parameters separated by commas, but arguments separated by spaces? That feels inconsistent.

                                                                                                                                1. 1

                                                                                                                                  Currying. It makes the syntax for curried function application more consistent.

                                                                                                                                  1. 7

                                                                                                                                    But according to the FAQ, Roc doesn’t have currying…