u/CAD1997
CAD1997
CAD1997
Eeriely similar logic was used to argue that the insurrection clause doesn't apply to the presidency. I can absolutely see a case taking (or being delayed) long enough that an election happens before the case is resolved, and then at that point we need to abide by the people's will, right?
CAD1997
On the other hand, Windows' dedication to forwards compatibility (how you can transparently compile an application on Windows 11 for an older Windows release) is bonkers. Compiling for an older version of your operating system is a form of cross compilation; that takes significant work to get working seamlessly and often breaks in subtle ways.
Also, FWIW, glibc isn't against being able to target older GLIBs while using a newer glibc. They just don't have anyone willing to do it for free nor anyone willing to fund that work.
CAD1997
Using distro versions of libraries also means that you don't know which version(s) of the library you need to test with. There's a reason so many apps use electron instead of the native webview: the app now only has to test with the one bundled version of chromium that it ships with. I don't have to handle support requests from a user who has a subtly broken version of some dependency that only gets surfaced by my app.
All dynamic libraries is a workable solution when your dependency set is limited to "is present by default on all reasonable desktop distros," sure. But I want to be able to use other libraries as well, because if there's a solution out there I'd rather use it than reimplement it (or worse, copy paste it into my code). And that's not even getting to the idea that as a library author I only want to worry about maintaining API stability (and in a more expressive language than C), not ABI stability as well.
CAD1997
or guaranteed provided versions
And we're back to the initial point again: Linux is a kernel and a set of conventionally provided OSS libraries; what you get guaranteed on a *-linux-gnu target (yeah, GNU/Linux, I know) is quite minimal compared to a "full fat" OS like Windows or macOS. This is great for server applications — why should your server have code for a desktop environment when it doesn't even have a screen? But it means "optional" libraries are required to do much that's relevant. So your options are to develop against multiple distro targets (Debian, Fedora, Arch, …), waiting for a motivated user to show up and map your program dependencies to other distros (hope the versions you picked are also available there, or their port will fail and you could get flamed), or you could just do what everyone does on Windows and macOS and bundle any nonstandard dependencies. Plus, shipping a flatpak doesn't prevent motivated users from coming in and creating a build replacing unnecessarily bundled libraries with the system one for whichever distro of their choice.
The control that you want is why Linux won the Unix wars; that's a fact. But I'd also argue that the same ability to swap whatever components around is why Linux won't reach a significant audience of desktop installs. The median end-user doesn't want to choose between tens of distros, let alone be a sysadmin; they want to install "the" operating system and be able to expect that when they click the "download" link in the browser for the software they want that it'll work on their system without any further configuration. They want to interact with the software (and updates of) that they want and installed, not all of the "random" middleware they never asked for. Bundling is a better UX for the median user.
CAD1997
As a note, verifying package signatures is only helpful if the package signature is fetched from a different source than the package itself. If they find from the same source, a compromised package could simply also update the package signature.
CAD1997
… There's no recursion in the matrix version of fn fib. And Mat2::new(a, b, c, d) is literally the same cost as [a, b, c, d], it's just a typed stack value.
CAD1997
Mat::pow is O(log n)ish. powf is O(1) for any useful model; even a perfectly rounded result can be computed in a bounded maximum number of machine steps.
CAD1997
This looks like Rust, and with any of the common Rust linalg crates Mat2::pow isn't going to do any dynamic heap allocation, as it's using a fixed size (array-backed) matrix.
CAD1997
In what way are Samsung Wallet and Apple Pay more secure than Google Wallet? I was under the impression that all three tap-to-pay providers do basically the same thing. I could understand a benefit of not exposing your CC number to any Google services if you've never bought anything from Google, but I have. For better or worse I pay for a Google Workspace subscription so my custom domain email can avoid dealing with SMTP discrimination.
CAD1997
Rust's async syntax lends itself very well to giant multilevel wakeup-based polling state machines, yes. This isn't particularly a bad thing; it allows us to write such with code using usual structured control flow despite all the yield/resume points and ownership concerns. These, at least when used deliberately, are the method with the least resource overhead.
Completion based systems are possible to set up efficiently, if a little clunky due to async's lazy nature. Submit a task to the reactor, then spawn your continuation task already waiting on its completion.
What's messy is that because Rust is a systems language, you have to write code in the form that runs on the execution stack. The straightforward way of doing completion callbacks will grow the stack infinitely. Trampolining continuation frames greatly complicates ownership patterns. Rust makes you choose what costs you want to pay.
All the suggestions I've seen for how Rust could've done async better fall into one of two camps, or a combination of both:
- complaints about decisions made by runtimes, not by the language and standard library; or
- require tight integration between the language and the async execution runtime, where Rust explicitly does not want to go.
I could see a systems-level language that bundles an integrated micro runtime that integrates deeply with the language doing a better job than Rust at async. But that's not what Rust is trying to be.
CAD1997
I think it's worth bringing up again that we have "named arguments at home", e.g. f(Width(w), Height(h)). The problem with doing that kind of strong newtyping everywhere is that callers need to have those types imported for the call site to look even remotely reasonable, and very generic names like that can easily conflict between libraries.
Which brings me back to the idea that the solution that would feel the most at-home in Rust would be some form of context-dependent name resolution. Yes, uttering that phrase gives me aftershocks from C++ ADL rules (foo(obj) for ns::Obj obj looks for ns::foo in addition to ::foo and local using scope), but Swift's .EnumVariant syntax has shown that if it has a visible difference from usual name lookup that it can be quite nice to read and write in practice.
CAD1997
In Swift API conventional style, it absolutely is; the public name is often a kind of preposition, with the prototypical example being
func sendMessage(_ msg: Message, from sender: User, to receiver: User)
(sendMessage(_:from:to:)) and invoked as
sendMessage(msg, from: alice, to: bob)
Very roughly speaking, "parameter and argument name are the same identifying noun" and "parameter name is a preposition and argument name is a noun" are about equally common, in my experience. One other common shape is label typeName: TypeName for a single argument of a type that's clear how it is treated in context but labelling is good for the caller. Then unnamed arguments are a bit less common than either kind of named argument are.
Keep in mind also that the largest surface of Swift API out there is the projected Apple OS APIs from Objective C++, which were the original to use this proposition heavy argument naming style for their message passing APIs.
If named arguments are a late addition to a language and API style wasn't designed with their ubiquity in mind, then renaming is relatively uncommon. But if it's there from the beginning and API style was built with their use in mind, renaming becomes a common desire worth the sugar.
In Rust I think it'd get used about as much as pattern destructuring arguments, i.e. absolutely loved where it makes sense and mostly overlooked otherwise.
CAD1997
Hi, that author of the Store proposal is me, ask me whatever clarifying questions you want :3
Seconding u/nyanarchism here — once we can use implementable trait aliases and supertrait autoimpl, the Allocator fits perfectly into the storage hierarchy. Even with a full store trait hierarchy, we want a trait for the semantics of Allocator, because it's actually quite useful of a property to request that storage handles are just pointers to the allocated memory with all the usual properties.
CAD1997
There's an argument to be made that the default is a "type erased" allocator in that Global is (roughly speaking) dyn GlobalAlloc. The virtualization for a general-purpose "infallible" allocator is dominated by the actual allocation cost. But custom allocators are the case where the overhead might be noticable, as non-general-purpose allocators may be used.
But I think that might actually be talking about C++ std::allocator<T> (typed allocation) versus C++ std::pmr::polymorphic_allocator (which has untyped allocation). I personally think C++ std::pmr was an overreaction to the problems with std::allocator<T> style typed allocation APIs, and it definitely would not be a good fit for Rust, since swapping two containers with nonequal pmr allocators in C++ is just UB.
CAD1997
For the splat, you still need to write a trampoline function that takes a generic argument and calls the method. You can do it today with passing a tuple. So #[rustc_splat] really is just turning min((1, 2, 3)) into min(1, 2, 3).
The caveat being that because the double parens are awkward, a case that does have something like this is likely today to just not write the trampoline and tell users to write the method call form instead.
CAD1997
The main reported issue: https://github.com/rust-lang/rust/issues/123470
I might be misremembering the well-nested case.
CAD1997
A small bit of history: the original double-panic protection didn't allow well-nested unwinding like this; a panic inside f would abort with the "panicked while panicking" message.
Now on Itanium EH machines (ie Linux) we don't look at thread::panicking() to determine if it's a recursive unwind anymore. Instead, we directly integrate with the two-phase lookup to know if the unwind has a landing pad, aborting if not.
Last I checked, this means Windows doesn't print the "panicked while panicking" message anymore, since SEH unwinds just don't support nested unwinding at all, even with well-nested catch frames. Whoops 😬
CAD1997
This one is actually fully justified — 🇺🇸 is 🇺 🇸 (without a space in-between). That the characters have come into use independently of the flag sequences is mostly an accident.
CAD1997
My take on a more playable version:
Surveillance State {W}{U}{B}
Enchantment
If a player would scry one or more cards, they surveil that many cards instead.
{T}: Surveil 1 twice.
“If our empire is to prosper, we must cull the weak from our lands” — unnamed monarch
WotC might prefer printing “{T}: Surveil 2,” but I love the flavorful temptation in effectively choosing how aggressive the surveillance is between the effect as “mill 1 then surveil 1” vs the weaker “look at the top card of your library. (Twice.)”
CAD1997
There are other peculiarities and assumptions baked into the typed syntax tree, such as "this syntax node has only one way to parse it that is the same in every context the syntax node shows up in". syn attempts to make things non_exhaustive as it makes sense, but some things you just don't think are going to change end up changing due to some intersection of functionality you didn't think about yet.
That, plus syn was originally released before #[non_exhaustive] was a thing, and often times with syntax tree manipulation there isn't a good fallback implementation to use when manipulating a non exhaustive syntax tree node.
CAD1997
The happy version is she's your ex-girlfriend because you're married now. Somehow I doubt that, though…
CAD1997
That's the one where every operation returns its input isn't it
CAD1997
No, that's a monologue. A monocule is a highly contagious illness usually caused by the Epstein-Barr virus.
CAD1997
(monopoly is only one seller. monopsony is the word for only one buyer. generally discussed in the context of some employer being the only buyer of labor. but in practice people call it a monopoly because that's the word people will recognize as meaning "controls all of" even if the controller is on the other side of the money/service trade.)
I've always held that the CVSS system is kind of broken for libraries. "Someone could misuse this" isn't a critical vulnerability unless someone did misuse it. It's still good to patch first and check if you were exposed to the theoretical vulnerability after, but asserting that you definitely are vulnerable unless you patch isn't helpful to anyone (except maybe someone attempting a supply-chain attack).