emn13
Both from a sheer numbers perspective and also from the perspective of qualitative differences between these audiences browsers are doing the right thing - prioritizing security in low-to-no-trust environments assuming low-to-no-competence administration.
It's also worth remembering that both of these specific organizations were instrumental in major, positive security shifts that eventually hit OS's too, including shorter-lived certs, limiting the point of CAs, adoption of TLS 1.3, and likely other things. If anything, they deserve _more_ trust than the OS distributors on this specific front, perhaps also because they don't share the OS distributor's incentive to prioritize stability for paying customers, which can be at odds at times with harsh, prompt security measures.
I also find that it's easy to spend like that, but also easy not to with little impact on productivity. At the current moment I'm stuck with rider + copilot (not ideal), but e.g. using GPT 6.1 luna is really, really cheap, and lots of tasks are quickly and decently dealt with even at lower reasoning levels, (added bonus of having low latency). And that model is so cheap, I can't see a hitting 1500$ at api prices realistically - not even close. But it also depends on the harness and codebase.
There are structural limitations (i.e. this implementation never looks at preceding context and sometimes that matters, nor does it understand other clues like punctuation or multi-word suffixes). Nevertheless, the accuracy is high enough that I'm not sure it'd be easy for a small model to beat it, especially not without considerably more work to make sure your inputs cover more context (which in principle the plain statistics approach could likely deal with too).
If the whole point of multi-layer networks is to deal with weirdly shaped, non-obvious manifolds in a very high-dimensional space, then this problem just doesn't look that difficult and perhaps does not need that mathematical finesse: just store the prototypical examples and you're pretty much there without anything fancier.
The real issue is one of timing and tech debt - higher quality software is cheaper and better, but... that's only over time. If you want that new software from scratch _now_, and don't have the time to set up a high quality development process, you can hack something together quickly. If the software is small enough, the person or LLM writing it smart enough, and while everything from requirements to code is still fresh in memory - that works pretty well! But that process scales poorly, and yet it's what we've as an industry done far too often, and at far too pervasive a scale.
So even though we know and have examples of how to design software better and more cheaply, actually getting to that situation isn't a simple question of trying harder; it's working entirely differently. And unfortunately, we build more and more of our software on the building blocks of the past, and many of those are themselves of low quality too; the more we do that, the more entrenched low quality becomes. As an end user that kind of isn't perceivable; it just means all software is a bit worse and more expensive, but as humanity, it's absurd how much effort we waste working around fairly trivial mistakes made in the past, typically by organizations that just had no incentives to care about future impacts especially on others.
While I get the instinct to prefer something over nothing as an end user it kind of is exactly that bad habit that got us into the mess we're in today. We don't build and throw away; we copy and tweak - so all the messes are inherited, kind of like a form of pollution.
Most quality defects I see are ultimately down to culture, not training and certainly not certification. Getting to excellent quality simply does not require great training nor rigorous certification, and I'm not even sure it really benefits from either all that much. But what it does require is a culture of chasing down all the avoidable risks, to fix not just the immediate bug, but also the process that allowed it to come to be, to pre-emptively look for whole classes of bugs or misfeatures seriously, and to always look deeper than for underlying causes or interactions (i.e. take the 5-why's game seriously).
It's perhaps almost a trope by this point, but it's still a great reminder and example - sqlite. About a month ago Richard Hipp, one of the primary authors, gave a great presentation "Reliability Lessons From SQLite" (https://youtu.be/V_qzqY1bb7I) - and notably, I'm not seeing even _echos_ of training and certification in their clearly world-class process. I don't think you can even seriously claim it's all that expensive, if you consider how tiny that team is, and yet how much they've achieved.
If larger organizations fail to achieve high quality - well, _why?_ It's not due to lack of training, certifications or smart people. Perhaps its intrinsic about larger for-profit corporations, but I suspect we could do better with better incentives, and a more serious attitude about dealing with mis-aligned incentives throughout our culture. Is it really a flaw for a corporation to prioritize short term cost reduction even over long term self-harm if that's what they're judged by? Is it a flaw for a profit seeking corporation to largely ignore costs their low quality imposes on others? Is it a flaw for a for-profit organization to take huge risks when the upside is unbounded but the downside is mere bankruptcy without any further liability?
I don't know how to solve these problems, and don't want to claim it's even remotely reasonable to throw out the capitalist baby with the corporate bathwater, but surely we can do better than the status quo even without a revolution. Misaligned incentives and tragedies of the commons aren't new issues, nor ones without potential mitigations. We're just choosing to ignore those inefficiencies, and have for decades. And at this point, even small changes in incentives might have truly wrenching consequences; the ingrained and by now deeply embedded carelessness in our huge software and other engineering stack is corroded at every level.
TLDR: I don't have the answer, but I'm pretty positive it's not an issue of cost, training or certification.
But the real problem with docs is that for MOST usecases, the audience and context of the readers matter HUGELY. Most docs are bad because we can't predict those. People waste ridiculous amounts of time writing docs that nobody reads or nobody needs based on hypotheses about the future that turn out to be false.
And _that_ is completely different when you're writing context-window documents. These aren't really documents describing any codebase or context within which the codebase exists in some timeless fashion, they're better understood as part of a _current_ plan for action on a acute, real concern. They're battle-tested the way docs only rarely are. And as a bonus, sure, they're retainable and might help for the next problem too, but that's not why they work; they work because they're useful in an almost testable way right away.
The exceptions to this pattern kind of prove the rule - people for years have done better at documenting isolatable dependencies, i.e. libraries - precisely because those happen to sit at boundaries where it's both easier to make decent predictions about future usage, and often also because those docs might have far larger readership, so it's more worth it to take the risk of having an incorrect hypothesis about the future wasting effort - the cost/benefit is skewed towards the benefit by sheer numbers and the kind of code it is.
Having said that, the dust hasn't settled on the best way to distill context like this. It's be a mistake to overanalyze the current situation and conclude that documentation is certain to be the long-term answer - it's definitely helpful now, but it's certainly conceivable that more automated and structured representations might emerge, or in forms better suited for machine consumption that look a little more alien to us than conventional docs.
As it is, it's just clearly misleading to people that haven't somehow figured out that it's not really a great test of multithreaded throughput.
For the first 8 threads or so, it's fine. Once you hit 20 or so it's questionable, or at least that's my impression.
It won't prevent all races, but it might help avoid mistakes in a few of em. And concurrency is such a pain; any such machine-checked guarantees are probably nice to have to those dealing with em - caveat being that I'm not such a person.
This doesn't exactly instill confidence in Apple's competence.
Whether or not the company in this case shares some or most of the blame with novice users - the analogy is not a great one.
I'm sure commercial incentives would lead issues that affect paying (hosted) customers to have better resolutions than those self-hosting, but that's not enough to explain this level of pain, especially not in issues that would affect paying customers just as much.
Whether it's the standards fault or the languages fault for following the standard in terms of preventing auto-vectorization is splitting hairs; the whole point of the standard is to have predictable and usually fairly low-error ways of performing these operations, which only works when the order of operations is defined. That very aim is the problem; to the extent the stardard is harmless when ordering guarrantees don't exist you're essentially applying some of those tricky -ffast-math suboptimizations.
But to be clear in any case: there are obviously cases whereby order-of-operations is relevant enough and accuracy altering reorderings are not valid. It's just that those are rare enough that for many of these features I'd much prefer that to be the opt-in behavior, not opt-out. There's absolutely nothing wrong with having a classic IEEE 754 mode and I expect it's an essentialy feature in some niche corner cases.
However, given the obviously huge application of massively parallel processors and algorithms that accept rounding errors (or sometimes conversely overly precise results!), clearly most software is willing to generally accept rounding errors to be able to run efficiently on modern chips. It just so happens that none of the computer languages that rely on mapping floats to IEEE 754 floats in a straitforward fashion are any good at that, which is seems like its a bad trade off.
There could be multiple types of floats instead; or code-local flags that delineate special sections that need precise ordering; or perhaps even expressions that clarify how much error the user is willing to accept and then just let the compiler do some but not all transformations; and perhaps even other solutions.
Not being able to auto-vectorize seems like a pretty critical bug given hardware trends that have been going on for decades now; on the other hand sacrificing platform-independent determinism isn't a trivial cost to pay either.
I'm not familiar with the details of OpenCL and CUDA on this front - do they have some way to guarrantee a specific order-of-operations such that code always has a predictable result on all platforms and nevertheless parallelizes well on a GPU?
Typescript's partial can however do more than that - required means you can practically express a type that cannot be instantiated partially (without absurd amounts of boilerplate anyhow), but if you do, you can't _also_ express that same type but partially initialized. There are lots of really boring everyday cases where partial initialization is very practical. Any code that collects various bits of required input but has the ability to set aside and express the intermediate state of that collection of data while it's being collected or in the event that you fail to complete wants something like partial.
E.g. if you're using the most common C# web platform, asp.net core, to map inputs into a typed object, you now are forced to either expression semantically required but not type-system required via some other path. Or, if you use C# required, you must choose between unsafe code that nevertheless allows access to objects that never had those properties initialized, or safe code but then you can't access any of the rest of the input either, which is annoying for error handling.
typescript's type system could on the other hand express the notion that all or even just some of those properties are missing; it's even pretty easy to express the notion of a mapped type wherein all of the _values_ are replaces by strings - or, say, by a result type. And flow-sensitive type analysis means that sometimes you don't even need any kind of extra type checks to "convert" from such a partial type into the fully initialized flavor; that's implicitly deduced simply because once all properties are statically known to be non-null, well, at that point in the code the object _is_ of the fully initialized type.
So yeah, C#'s nullability story is pretty decent really, but that doesn't mean it's perfect either. I think it's important to mention stuff like Partial because sometimes features like this are looked at without considering the context. Most of these features sound neat in isolation, but are also quite useless in isolation. The real value is in how it allows you to express and change programs whilst simultaneously avoiding programmer error. Having a bit of unsafe code here and there isn't the end of the world, nor is a bit of boilerplate. But if your language requires tons of it all over the place, well, then you're more likely to make stupid mistakes and less likely to have the compiler catch them. So how we deal with the intentional inflexibility of non-nullable reference types matters, at least, IMHO.
Also, this isn't intended to imply that typescript is "better". That has even more common holes that are also unfixable given where it came from and the essential nature of so much interop with type-unsafe JS, and a bunch of other challenges. But in order to mitigate those challenges TS implemented various features, and then we're able to talk about what those feature bring to the table and conversely how their absence affects other languages. Nor is "MOAR FEATURE" a free lunch; I'm sure anybody that's played with almost any language with heavy generics has experienced how complicated it can get. IIRC didn't somebody implement DOOM in the TS type system? I mean, when your error messages are literally demonic, understanding the code may take a while ;-).
I think it's pretty usuable now, but there is scarring. The solution would have been much nicer had it been around from day one; especially surrounding generics and constraints.
It's not _entirely_ sound, nor can it warn about most mistakes when those are in the "here-be-dragons" annotations in generic code.
The flow sensitive bit is quite nice, but not as powerful as in e.g. typescript, and sometimes the differences hurt.
It's got weird gotcha interactions with value-types, for instance but likely not limited to interaction with generics that aren't constrained to struct but _do_ allow nullable usage for ref types.
Support in reflection is present, but it's not a "real" type, and so everything works differently, and hence you'll see that code leveraging reflection that needs to deal with this kind of stuff tends to have special considerations for ref type vs. value-type nullabilty, and it often leaks out into API consumers too - not sure if that's just a practical limitation or a fundamental one, but it's very common anyhow.
There wasn't last I looked code that allowed runtime checking for incorrect nulls in non-nullable marked fields, which is particularly annoying if there's even an iota of not-yet annoted or incorrectly annotated code, including e.g. stuff like deserialization.
Related features like TS Partial<> are missing, and that means that expressing concepts like POCOs that are in the process of being initialized but aren't yet is a real pain; most code that does that in the wild is not typesafe.
Still, if you engage constructively and are willing to massage your patterns and habbits you can surely get like 99% type-checkable code, and that's still a really good help.
1. Flowsensitivity: It's a sure thing that in a dynamic language people use coding conventions that fit naturally to the runtime-checked nature of those types. That makes flow-sensitive typing really important.
2. Duck typing: dynamic languages and certainly ruby codebases I knew often use ducktyping. That works really well in something like typescript, including really simple features such as type-intersections and unions, but those features aren't present in C#.
3. Proof by survival: typescript is empirically a huge success. They're doing something right when it comes to retrospectively bolting on static types in a dynamic language. Almost certainly there are more things than I can think of off the top of my head.
Even though I prefer C# to typescript or ruby _personally_ for most tasks, I don't think it's perfect, nor is it likely a good crib-sheet for historically dynamic languages looking to add a bit of static typing - at least, IMHO.
Bit of a tangent, but there was a talk by anders hejlsberg as to why they're porting the TS compiler to Go (and implicitly not C#) - https://www.youtube.com/watch?v=10qowKUW82U - I think it's worth recognizing the kind of stuff that goes into these choices that's inevitably not obvious at first glance. It's not about the "best" lanugage in a vacuum, it's a about the best tool for _your_ job and _your_ team.
Quite plausibly they just didn't realize how rocky the start would be, or perhaps they valued that immediate strategic autonomy more in the short-term that we think, and willingly chose to take the hit to their reputation rather than wait.
Regardless, they had choices.
Recognizing the relevance of coherence and plausibility does not need to imply that other aspects are any less relevant. Redefining truth merely because coherence is important and sometimes misinterpreted is not at all reasonable.
Logically, a falsehood can validly be derived from assumptions when those assumptions are false. That simple reasoning step alone is sufficient to explain how a coherent-looking reasoning chain can result in incorrect conclusions. Also, there are other ways a coherent-looking reasoning chain can fail. What you're saying is just not a convincing argument that we need to redefine what truth is.
I can't imagine we're anywhere even close to the kind of perfection required not to need something like this - if it's even possible. Humans use all kinds of review and audit processes precisely because perfection is rarely attainable, and that might be fundamental.
Then again, it's been years since I used this kind of C, so maybe my instincts are rusty here (no rust-pun intended!)