My stint with MongoDB was brief, but I too came away with a deeper appreciation of SQL bases. I feel it's a bit like a good type system: yes, there absolutely is an upfront cost, but over time it really does save you from stupid runtime problems. It's especially important when the bugs are in the data storage layer, because if a bug causes bad data to be written to your database, not only do you need to find and fix the bug, you also have to figure out how to deal with (possibly lots of) bad data.
Also, modern SQL is an incredibly powerful language. Good SQL can save you from lots of dumb data munging code if you know how to wield your database properly. Especially for analytical queries, but also more typical application code IMO.
I worked on an application implemented in SmallTalk for about two and a half years, and having the IDE be in the application was honestly a huge force multiplier, at least for the kind of complicated desktop application we were making. Basically, it made development extremely smooth because you always had the application at your fingertips and while developing no matter what kind of error happened it would trap into the debugger so you could see what was going on. No more remembering to set breakpoints or running under a debugger or anything; just write code, test and get dropped straight in the debugger if something goes awry. In some cases we could even fix the bug, and retry the failing operation in-flight. To stretch the Factorio metaphor beyond the breaking point, I would even say that the image-based nature helped there to be less mess, because you no longer have to care about the organization of your code in the source files: you edit methods and classes, but the on-disk organization of the bits and pieces is no longer a concern.
Where the image-based system does cause trouble is when you need to interact with stuff outside of SmallTalk. It basically doesn't play very well with others (in particular stateful stuff like database connections which can't straightforwardly be persisted when the image is saved and closed). But overall, I found developing in SmallTalk to be extremely productive, even in the antiquated implementation we were working with.
In my jurisdiction, damages from car crashes are strict liability, so you would in fact be legally liable. Limited to ~10 million USD for damages to objects, no limit for damages to persons. Of course the manufacturing defect would give you a credible claim against the manufacturer, but that's a separate matter. Which is why automotive liability insurance is mandatory.
Pseudo coordination is a fun phenomenon in Scandinavian. Lots of detail in NALS: https://tekstlab.uio.no/nals#/chapter/65 but an important difference with English is that the Scandinavian construction occurs with many more verbs in the first conjunct, not just _try_.
Apparently salmon was considered dubious in Japan as sushi. I forget the details, but I think something about freshwater fish being inappropriate for sushi due to the possibility of a parasite in the meat that only lived in fresh water, not salt. So salmon for sushi was apparently pushed hard in Japan by Norwegian authorities and the salmon industry, I think in the late 80s or the 90s?
The marks could be scouring marks from the wind, I think. From the description in the article, these fossils have basically been sandblasted out of their sandstone matrix over time, so if there's a dominant wind direction small irregularities in the fossil could probably quite easily develop into this kind of parallel markings.
Semi-relatedly, this is why I'm quite liberal about throwing errors while developing programs. During development it makes sure I'm reminded of my slipups when I inevitably forget some invariant that needed to be upheld, and then towards the end of the process any throws remaining are easily found and vetted. And in production, the closer to the source the error occurs the easier it is to fix; if you're especially unlucky, the error doesn't occur until after state has been persisted and read back, in which case you not only need to fix the bug but also have to figure out how to handle and/or remediate the bogus state written to your database.
Many people, when they say math, mean continuous math.
At work, my colleagues are almost entirely statisticians and actuaries, and I sometimes joke that my only math course at university was Calculus 1. I have of course done lots more math, but it’s all CS type stuff like logic and discrete structures like graphs and trees which is a very different world from continuous stuff.
I haven't used PBT much, but I did once get a lot of mileage out of it, which was when I was implementing a fairly gnarly edit-distance algorithm. In that case, I used PBT to check that the required properties of metric functions (d(x,x)=0, d(x,y)>0, d(x,y)=d(y,x), d(x,z) <= d(x,y)+d(y,z)) held for my implementation, which helped shake out a fair few stupid implementation mistakes.
I don’t think it’s a minor delay. In other places where gauge changes are necessary, I think it typically takes on the order of an hour or a few hours, so if you need a big logistics operation across the border from Sweden into Finland, that bottleneck is going to absolutely murder your throughput.
In GIS parlance, elevation is typically z coordinate. Which of x and y correspond to east-west and north-south varies from coordinate system to coordinate system, and is a bountiful source of stupid bugs (at least for me). But yeah, in 3D graphics z is usually distance from the camera I think.
And the continuum has two big groups: High and Low German (High and Low here being z-coordinates, High German dialects because they come from the more mountainous Southern areas and Low German from the lower-lying Northern parts). Modern day Standard German is a High German variant, whereas Dutch (and thus Afrikaans) are Low German.
So these are kind of fun to compare. At the high level they clearly all have the same purpose: in some cases it's socially useful to have the punishment for a crime simply be a statement of "person X did this thing". But the details vary a bit:
- It seems the Australian section 10 is handed out by the court, where the English and Norwegian options dispense with a trial entirely. It also looks like a Section 10 doesn't go in a person's criminal record, unlike the other two.
- It looks like the English caution requires an admission of guilt, while the Norwegian option is at the prosecutor's discretion within the rules of applicability of the procedure. Of course someone not demanding a trial when given this can be seen as an _implicit_ admission of guilt, but the legal nuance can probably be important.
- The English and Norwegian procedures are nominally also different in who makes the decision: the English procedure is handled by the police, while in Norway it's the prosecutor's office. But this is more a theoretical than practical difference I think, because the Norwegian prosecutor's office is organized differently than the English Crown Prosecution Service: here, the lowest levels of prosecutors are integrated into the police services they work with, so in practice I think it works out much the same.
Another example, not involving compound nouns: Norwegian criminal process distinguishes two levels of suspicion. The first level «mistenkt» (suspect) is basically the investigation noting down in their log «we think this guy might have done it», but the second level «siktet» (literally aimed at, no idea how to translate to English or even if an equivalent term exists) is a formal decision made by the prosecutor’s office. And importantly, the use of «tvangsmidler» (coercive instruments, like arrest, search, seizure and so on) requires there to be a siktelse and this status also triggers legal rights for the accused like the right to a defence attorney.
An example from my work: in Norwegian criminal law, the prosecutor can in some cases hand out what is called a «påtaleunnlatelse», which means something like «decision to not prosecute». This is a legal punishment in the sense that it goes on your criminal record, but no punishment beyond that is handed out. Basically, the prosecutor’s office can note down «we are convinced we can prove this was done, but have decided not to prosecute».
A special kind of this is the «prosessøkonomisk (process economical) påtaleunnlatelse» where in a large and complex case with many serious offences, some less serious can be non-prosecuted in this way to not spend eternity in the courtroom.
I worked on a case management system for a few years that dealt with Norwegian criminal law, and we did the same. Technical terms and conventional parts of method identifiers (like getFoo, setFoo, isFoo and such) were in English while the domain terminology was left in Norwegian. It looks a bit weird when you first encounter it, but honestly it was fine. Especially for a domain with as much emphasis on nuance and as many country specific details as the legal domain anything else would be a terrible idea IMO. Not only would it be really hard to translate many cases, it would probably make the code harder to understand and in some cases even cause misunderstandings.
That's the tyranny of Gödel incompleteness (or maybe Rice's theorem, or even both): useful formal systems can be either sound or complete. Rust makes the choice of being sound, with the price of course being that some valid operations not being expressible in the language. C of course works the other way around; all valid programs can be expressed, but there's no (general) way to distinguish invalid programs from valid programs.
For your concrete example of subdividing matrixes, that seems like it should be fairly straightforward in Rust too, if you convert your mutable reference to the data into a pointer, wrap your pointer arithmetic shenanigans in an unsafe block and add a comment at the top saying more or less "this is safe because the different subprograms are always operating on disjoint subsets of the data, and therefore no mutable aliasing can occur"?
The way I think about it is more or less in terms of how a C program would work: if you assume a heap allocated data structure, the owner is the piece of code that is responsible for freeing the allocation at the appropriate time. And a reference is just a pointer with some extra compile time metadata that lets the borrow checker prove that the reference doesn’t outlive the referent and that there’s no mutable aliasing.
Oh, but English does have a sarcasm marker! It's just not a word, instead it's typically marked by using non-standard pronunciation like creaky voice or lengthening vowels. The problem is of course that this stuff doesn't have an orthography, thus the use of stuff like /s online.
Classical Greek is well outside my field, but one of the things I love about SpecGram when it deals with things I do know, the jokes also have a kernel of truth to them. And in other classical languages I'm more familiar with, there is (IMO) an argument to be made that the texts should be translated more "orally" than they frequently are. There are probably many reasons for this, but I think one of them is that because they are Classical and Important there's a sense of reverence that makes us want to translate them Seriously(tm).
Of course you're entirely right that Greek particles are not some unfathomable mystery. The systematic study of Greek language goes back literal millenia, and the particles are well understood (unlike say Vedic Sanskrit particles).
To take an example from the post: in some cases a value was computed that could overflow, but it was not used because of a later overflow check. I think the optimizer would be fully within its rights to delete the code inside the overflow check, because the computation implicitly asserts that it won't overflow (since overflow is undefined). I think this is a more or less useful way of thinking around UB: any operation you put in your program implicitly asserts that the values are such that UB won't happen. For example, dereferencing a pointer implicitly means it cannot be NULL, because derefing NULL is UB, and anything downstream of that deref which checks for NULL can be deleted.
Single ownership and memory not being flat are separate points.
And I guess I'm imprecise saying pointers where I mean borrowed values, but my point is that a borrow is just a pointer with additional type checking. More formally: C pointers are a complete but unsound formal system, whereas Rust borrows are sound but incomplete. And every time I get in a fight with the borrow checker, it's because I'm doing something unsound, not because the system is incomplete.
I can think of three things off the top of my head:
- Rust doesn’t let you pretend that memory is a flat array of bytes
- Single ownership of data can be annoying in some cases
- The borrow checker pointing out that you’re trying to do something stupid with pointers (again) can be annoying
Of course, I’m of the opinion that the hassles are worth it, especially the borrow checker. Almost every time I have to fight the borrow checker, it’s because I haven’t thought properly about the pointers involved and tried to do something stupid.
Both are fine, IMO. In a context where array indexing is pointer plus offset, zero indexing makes a lot of sense, but in a higher level language either is fine. I worked in SmallTalk for a while, which is one indexed, and sometimes it made things easier and sometimes it was a bit inconvenient. It evens out in the end. Besides, in a high level language, manually futzing around with indexing is frequently a code smell; I feel you generally want to use higher level constructs in most cases.
In 2014 John Regehr and colleagues suggested what he called Friendly C[0], in an attempt to salvage C from UB. About bit more than a year later, he concluded that the project wasn't really feasible because people couldn't agree on the details of what Friendly C should be.[1]
In the second post, there's an interesting comment towards the end:
> Luckily there’s an easy away forward, which is to skip the step where we try to get consensus. Rather, an influential group such as the Android team could create a friendly C dialect and use it to build the C code (or at least the security-sensitive C code) in their project. My guess is that if they did a good job choosing the dialect, others would start to use it, and at some point it becomes important enough that the broader compiler community can start to help figure out how to better optimize Friendly C without breaking its guarantees, and maybe eventually the thing even gets standardized. There’s precedent for organizations providing friendly semantics; Microsoft, for example, provides stronger-than-specified semantics for volatile variables by default on platforms other than ARM.
I would argue that this has happened, but not quite in the way he expected. Google (and others) has chosen a way forward, but rather than somehow fixing C they have chosen Rust. And from what I see happening in the tech space, I think that trend is going to continue: love it or hate it, the future is most likely going to be Rust encroaching on C, with C increasinly being relegated to the "legacy" status like COBOL and Fortran. In the words of Ambassador Kosh: "The avalanche has already started. It is too late for the pebbles to vote."