1,143 karma · joined January 10, 2012
Software Developer in Washington, DC
[ my public key: https://keybase.io/cstrahan; my proof: https://keybase.io/cstrahan/sigs/yV0wzDolQldJ9GSMuflLE9_PIggrsCf9jzIQPUHqzKE ]
Depends on motherboard, but: I had a top of the line, very well reviewed gaming mobo, and I’d hear a buzzing noise over the speakers depending on what the computer was doing. Moving the mouse? Distinct buzz as a function of speed. Compiling the Linux kernel? Distinct buzzing. Etc. this happened under both Windows and Linux, so I don’t think it was a software issue.
Having an external DAC allows you to keep the audio signal very, very far away from the rest of the electronics, which completely solved the problem for me. I went with a Focusrite Scarlett 2i2 for about $200, connected to my two JBL 305 speakers — it’s been great. It wasn’t in my initial plans, but I later took advantage of the XLR microphone input to set up a Shure SM7B microphone (wasn’t quite enough gain, so I added a TritonAudio FetHead preamplifier and a DBX 286s for de-essing/eq/etc — very happy with the setup now).
So, FWIW, I’m a big fan of external USB DACs.
No, they said they couldn’t see the utility in what he was doing, which is very different than being told that his solution is unsatisfactory.
I have had countless interviews where I’ve been told that they don’t see where I’m going with something, and when I’m finished they admit (after some time processing) that they are impressed that I came up with such an elegant, simple solution. When asked what they had in mind, it turns out they (initially) thought the optimal solution was some contrived, overly complicated thing. If I let everyone’s interjections derail me, I’d never get through most interviews.
Think: have you ever seen a candidate give a crazy, overly complicated solution in an interview? Yes? Well, such interviewees (the ones that write 100+ line Fibonacci functions that look like they might be doing some memoization, but if you squint it turns out they aren’t even using the memo table they constructed) go on to be become interviewers — it shouldn’t be a surprise that many interviewers unintentionally throw candidates curveballs by expressing incredulity in the face of a non-shitty solution. If something is truly a hard “no”, then a “no” must be said — expecting the candidate to guess what’s going through the interviewers head is ridiculous.
That wasn’t part of the criteria. If that’s something they wanted to assess, they should have told him “no” when he asked if it would be alright to encode the rules in the types.
Maybe you have an issue with the interview, rather than the interviewee?
There are applications where hashes are used as identifiers, where it would be impossible to use the original data to resolve possible collisions. One example would be in RTTI (Run Time Type Information), when you want to check if two objects (of unknown-at-compile-time type) are instances of the same type. The only performant way to achieve this is if the compiler emits each type’s RTTI with a unique integer key to efficiently compare against, and this key must be unique across all object files and shared objects. In practice, this is done using hashing. If there is a collision, then the program behavior is undefined, so it is ideal to minimize probability of collision. You can see this issue in the Rust compiler project where there is ongoing discussion about how to handle this hashing, trying to balance compiler speed and collision likeliness:
https://github.com/rust-lang/rust/issues/129014
Another scenario would be like what Backtrace does: a hash is used to identify certain classes of errors in application code. The cost of analyzing each error is quite high (you have to load objects into memory, source maps (if available), perform symbolification, etc), so comparing any two errors every time you want to perform any metrics or retrieve associated data (like issue tracker identifiers) would reduce the performance to a point that any such application would be too slow to be useful. So a lot of thought was given to producing fast, non-cryptographic hashes (these hashes aren’t shared across tenants, and no customer is going to go out of their way to work out initialization parameters so they can be their own adversary) with a known likely hood of collision. You can read about the hash (UMASH) here:
https://engineering.backtrace.io/2020-08-24-umash-fast-enoug...
I don’t know how I can help you understand the utility of analogies (you recognized the rhetoric as such, yet simultaneously seem stuck on the fact that analogies don’t establish a literal connection). However, I’m not sure if that’s actually the problem, or if you’re feigning confusion in attempt to offend me. Granted, it would seem an odd choice for you to claim incompetence as part of an attempted insult.
Regardless, I’d be happy to help you in any way I can.
It is indeed a play on the saying “Nobody ever got fired for buying IBM”. What wasn’t explained, though, is the meaning behind the expression. It’s an expression used to mock use of the bandwagon fallacy and a general lack of critical thought in the decision process.
If you’re responsible for choosing a vendor, the easy out is to pick one of the largest vendors available: if it’s what everyone else is doing, then you can waive away any personal accountability for any resulting failures by claiming that “it’s what everyone else is doing, so it must have been the right choice, and therefore the failure that occurred must have been inherent to the problem domain, rather than something that could have been avoided if I personally chose better”.
The phrase now gets used to mock such bandwagon behaviors: a CTO completely unfamiliar with Kubernetes, yet choosing it “because everyone else is using it”; an engineer picking a serialization format based on popularity while never having read the spec; etc.
The article isn’t suggesting that anyone actually be fired. It is, however, critical of people choosing JSON due to familiarity/popularity, without any critical thought involved in choice (and bandwagon fallacy does not count as critical thought).
If you look at the statistics, you’ll find that casual, condomless sex is very common. Despite the risks of STI transmission, it often pans out okay: most STIs are readily curable, while HIV has a low transmission rate amongst heterosexual couples (about 0.08% to 0.2% per sexual act) while PrEP is pretty common for homosexual men, and HSV has fairly low odds of transmission outside of an active outbreak (annual odds of transmission amongst couples: about 11–17% for couples with a male source partner and 3–4% with a female partner). Consequently, many people who have casual, condomless sex with many, many partners will end up just fine.
Is it reckless? Well, the connotation of “reckless” is fairly negative, and I don’t see why I should get to judge what two consenting adults decide is an acceptable risk vs reward for themselves (at least, so long as I’m not involved).
However, when we pivot back to the domain of software/engineering: when software design choices are made via bandwagon fallacy, claiming that “it usually works out okay”, I do find that to be reckless. You may be fine with such a carefree approach, but it isn’t really fair to other engineers, users, and stake holders.
It’s not that I believe JSON (or similarly pitfall-laden technology) should be strictly avoided, but rather that the risks and failure modes should be given serious consideration, rather than minimized or outright dismissed. In terms of the STI analogy, it’s perfectly reasonable for two individuals to be aware of the risks, and depending on their appetite for said risk, agree upon the inclusive/exclusive nature of their relationship, as well as whether they exchange test results; what would be ridiculous is to pretend that the risk of infection is zero.
There would be zero value in the article minimizing the design flaws (and resulting footguns) in JSON. The insistence that the article should do so is about as bizarre as someone responding to an article on safer sex by insisting that the article be amended with a note that “… but raw-dogging strangers isn’t too risky anyway, so, like, YOLO”.
Is it that you are generally opposed to critical response? And if so, do you see the irony in you critically responding to another critical response?
I’m guessing you navigated to the https://mise.jdx.dev/environments.html page and saw the TOML syntax (which looks an awful lot like INI), and confused yourself.
Mise (like a lot of software) uses TOML as the format for its config files (as opposed to something like JSON). Mise reads that config, to automatically export environment variables on a per directory tree basis.
When the docs refer to environment variables, they very literally do mean environment variables. The values of which are taken from a format that resembles INI, as you have noticed.
I think you’re greatly overstating the problem, at least insofar as it relates to this tool.
For example, Python has its prefix (where packages are installed) baked into its installation. pip, ux, poetry — whatever — are going to install python packages there.
This tool is unconcerned with package installation — it is only concerned with getting the interpreters installed and managing which one is on your $PATH.
There’s literally nothing to leak.
And regarding “wraping existing tools” as proof of some shortcoming in mise (and/or similar) — if they reinvented the wheel, that’s where things could leak. And separation of concerns is a good thing.
I ran into this last week — I wanted to install the neovim text editor from the official binary distribution, but because the project’s CI distro has a more recent glibc installed, the executable would fail to run on Ubuntu 18.04.
There are plenty of great details spelled out here, in case you aren’t familiar with this kind of thing: https://stackoverflow.com/questions/57749127/how-can-i-speci...
I don’t see where they said (or implied) that.
How does “that isn’t plagiarism” imply “I can copy it with impunity”? Copyright infringement is still a thing.
Have you conflated plagiarism with copyright infringement? Neither implies the other. You can plagiarize without committing copyright infringement, and you can violate copyright without plagiarism.
> Description > > A vulnerability was found in D-Link DNS-320, DNS-320LW, DNS-325 and DNS-340L up to 20241028. It has been declared as critical. Affected by this vulnerability is the function cgi_user_add of the file /cgi-bin/account_mgr.cgi?cmd=cgi_user_add. The manipulation of the argument name leads to os command injection. The attack can be launched remotely. The complexity of an attack is rather high. The exploitation appears to be difficult. The exploit has been disclosed to the public and may be used.
The "The exploitation appears to be difficult" bit, AFAICT, is solely based on the presumption that most users won't put their NAS on the internet.
First heard about it was from the "Low Level" channel on YouTube -- https://www.youtube.com/watch?v=-vpGswuYVg8 -- the bug/vulnerability is pretty embarrassing. And D-Link's approach of "scrap your old purchase, buy a replacement model" is pretty insulting.
Probably going to avoid D-Link products where I can.
I cobbled together a little tool at my previous job that would capture a full trace of all process fork+exec and file opens, which would then present all of these events in the usual tracing UI (like you'd get when view a trace of a single program with Tracy[1] or Perfetto[2]).
We had a massive monorepo built with bazel and a heap of shell, and it wasn't clear which part of our code base was responsible for generating some mis-generated file. This tool gave me the whole inter-process call stack, complete with arguments and environment variables, letting me quickly find where and how to fix the problem.
It's such a nice tool to have that it kinda blows my mind that no one has openly published anything like it. By leveraging eBPF on Linux, the same UI could be used on both macOS and Linux. If I had more time and energy, I'd do it myself.
Same with Bakugan, Monsuno, Yu-Gi-Oh, Card Fight!! Vanguard, Future Card Buddyfight, Shadowverse, etc.
I don't really see what the problem is. If Nintendo was just a little less out of touch with what their fan base wanted, they could be raking in (even more) cash. But instead of doing that, they waste their resources getting butthurt over the silliest things, like people posting game play videos of humorous single player ROM hacks of games no longer being sold (they have successfully removed more YouTube videos like this than I count by sending DMCA take downs -- its ridiculous). More focus on innovating and less focus on litigation would do them (and their fan base) well.
It's not Palworld's fault that Nintendo et al choose to release horribly unoptimized, not fun Pokemon games (like Pokemon Scarlet and Violet). I think it's great that a competitor in the monster-capture game genre is providing an actually fun game, because despite the enormity of the Pokemon fan base and the massive financial incentive to deliver a compelling game to them, clearly Nintendo either can't or simply won't do it.
Why the HELL would you need objects and object oriented programming? Wherever you do foo.blah(), you could just do foo_class__do_blah(obj)… so what do objects really grant you that you can’t do with basic procedural programming?
Why do you need Python’s function decorators? You can just manually copy and paste whatever logic you need into each and every function, instead of decorating them.
Why have an iterator protocol? Every datum can have it’s own bespoke way of iteration that you simply have to memorize on a case by case basis (and can not be abstracted over in any common way), why make everything conform to the same interface?
Why have anonymous functions that can close over their lexical scope (what people usually refer to as “closures”)? Consider:
let x = 0;
let inc = () => x++;
You could just write: function inc(bindings) { return bindings.x++; }
And then remember to pass along bindings whenever you need to call inc. Besides, that’s more or less what’s going on behind the scenes.I could keep going.
We have these facilities not because they are essential (go program in assembler, and you’ll see how few programming techniques and concepts your processor actually cares about), but because they are nice to have. They are nice to have because they provide us tools for abstraction, so by solving the general case, you solve a host of concrete cases.
Lenses let you abstract over data traversal and projection.
Maybe you don’t appreciate that, and that’s fine. There are C programmers who don’t mind writing 100 different hash tables for different keys and elements. If you are a Python/TS developer, I’m pretty sure you’d find that surprising — if you want a dictionary/hashtable, you just use a dict and call it done — you wouldn’t go build a new dictionary class for each and every key-type/value-type pair.
Different people have different tolerances for the drudgery of solving the same problem for the 100th time.
However: while I don’t understand why someone would choose vanilla ice cream if they’re given the option of chocolate, I wouldn’t act flabbergasted in such a scenario. Why would I? Why should I expect my desires to be the same as everyone else’s?
The only reason I can think of that someone would express shock at someone choosing vanilla over chocolate is if they think that the preference for vanilla indicates something is fundamentally wrong them. Or in other words: being a condescending bigot.
That’s kinda how you’re coming off.
In the event that you were actually asking in good faith: if you like to broaden your skills so you can finish programming work faster, I’d recommend reading up on lenses. If you don’t care about that, that’s fine too, but I’d recommend against expressing shock at the fact that others do care about these types of things.
I don't think anyone (j-pb included) is saying anything to the contrary.
Here's what you wrote:
>> rusts type system is strong enough to build extremely powerful zerocopy serialization
> Unclear what you mean, but other than syn and quote you don't have a way to reflect and do code gen, outside of build script. Which also use it.
But your response doesn't logically follow from the text you quoted (so I figured you weren't familiar with zero copy). This isn't j-pb saying that Rust's type system could be used to forgo proc-macros -- j-pb isn't saying anything about proc-macros in the text you quoted.
To be clear, these two points from j-pb's original comment are two separate, orthogonal issues:
> - rusts type system is strong enough to build extremely powerful zerocopy serialization, but people don't explore that space because of serde
> - macros and especially proc-macros in Rust are horrible, and are only feasible because of the syn crate
> Unclear what you mean, but other than syn and quote you don't have a way to reflect and do code gen, outside of build script. Which also use it.
> Note there are alternative like mini serde and nano serde, but no library for type reflection.
Reflection/comptime/codegen are all orthogonal to zero copy (de)serialization.
To briefly(ish) describe zero copy by way of comparison, consider JSON: there's no way to parse a JSON object into your language's data structures without (among other things) copying any strings you come across (rather than directly borrowing a slice of the original buffer). Why not? Consider escapes: you must first unescape the string, which entails a new allocation. But this doesn't stop at strings: if you have an array, you must first parse that array (usually accumulating a copy of the elements in a Vec<Object> or similar, which in turn means that the whole array was effectively copied), rather than providing a "cursor" into the original buffer. Parsing JSON requires traversing the entire buffer and copying everything you come across.
Protocol buffers works much the same way: because structures are variable length (and in fact, scalars are too -- integers are stored as base 128 varints), if you want the Nth element of an array, you have no choice but to parse all the proceeding elements (rather than nudging a cursor's offset by N×sizeof(Elem) -- you can't do that because the size of any element is unknown until after you've parsed it). Because you want O(1) indexing after parsing, the logical implication is that whenever you parse a protobuf message, the protobuf library parses (and copies) the entire thing, and any array/repeated field ends up as a new array allocation in your language (e.g. Vec<Elem>).
Contrast with something like flatbuffers or Cap'n Proto: the code generated from your schema file gives you structures that (more or less) have two fields: a reference to a buffer, and an offset into that buffer. When you do something like person.age(), the offset of the age field (which is constant) is added to the offset of this person record, and that combined offset if used to index into the buffer (something like buffer.read_u32(offset)). Using a library like this gives you performance similar to what you'd have dereferencing array indices and struct fields in plain old data types in your language of choice. You don't pay in memory and processor time parsing everything up front, you only pay for the scalar memory reads you actually use (and a little bit of quasi-pointer chasing, not unlike what would happen with native structs).
Put another way: a zero copy (de)serialization protocol is one where the on-disk format is the same as the (readily usable) in-memory format. This rules out things like string escaping (just store the original bytes), variable sized records/integers, variable length arrays stored inline with records (otherwise that would make records themselves variable length), storing pointers in records (because those pointers will be meaningless when read from disk; instead: store offsets), etc.
You can read more about zero copy as it relates to Rust here:
https://manishearth.github.io/blog/2022/08/03/zero-copy-1-no...
Here's the Wikipedia article:
https://en.wikipedia.org/wiki/Zero-copy
Examples of zero copy (de)serialization libraries:
Maybe you didn’t follow the thread close enough — the complaint isn’t that funding Firefox is counterproductive, but that shoveling dollars to a non-Firefox product does nothing to help Firefox compete against Chrome/Chromium, which is kinda hard to argue against, no?
https://www.jetbrains.com/guide/pytest/tutorials/visual_pyte...
I believe the idea is that those identifiers are semantically related: that fixture decorator inspects the formal parameter names so that it can pass the appropriate arguments to each test when the tests are run. A sufficiently smart IDE and/or language server would thus know that these identifiers are related, and performing a rename on one instance would thus rename all of the others.
And maybe you were being facetious, but an IDE is an “Integrated Development Environment”.
Edit: Yep. Took all of 60 seconds to find what I’m looking for, as I type this from my phone while sitting in my throne room: https://docs.pytest.org/en/6.2.x/fixture.html
See the “Fixtures can request other fixtures” section, which describes the scenario from TFA.
And this post describes the PyCharm support for refactoring fixtures: https://www.jetbrains.com/guide/pytest/tutorials/visual_pyte...
I think you forgot how this thread got started:
> If you’re on macOS, then Orbstack is a nice alternative to Docker Desktop
We’re talking about running OCI (“Docker compatible”) images. The page you just linked to makes it apparent that you are talking about something orthogonal: OrbStack’s “machines” feature (https://docs.orbstack.dev/machines/).
The original topic is that OrbStack’s support for Docker containers is fast (implied: faster than Docker for Desktop), which cannot be explained by the lack of a VM, as both use a Linux VM to run one or more Docker containers.
https://docs.orbstack.dev/architecture
> OrbStack uses a lightweight Linux virtual machine with a shared kernel to minimize overhead and save resources, similar to WSL 2 (Windows Subsystem for Linux).
You probably are looking for a different word, rather than “indifferent”. Indifference is a property of the observer/subject, not the observed/object. For example, if I don’t care about sports, I might say that I’m indifferent to the outcome of the game my friends are watching.
Perhaps “mediocre” is what you’re looking for?
There’s a difference between obstinately refusing to learn the basics of a thing, versus taking issue with there being a bunch of self-inflicted hoops one must jump through to use a thing.
All other things being equal, I doubt you could put up with a car that required an elaborate 10 minute start up procedure, wherein any mistake pulling a dozen levers, cranking a bazillion knobs, and poking innumerable buttons could result in the engine exploding. If any such car entered the market, approximately zero people would put up with the headache — though I concede that some would likely love such a car, and proudly take the stance that “anyone that doesn’t like it isn’t a real driver”.
The difference is intrinsic vs extrinsic complexity.
When I program, I want to spend as much of my time working on solving the core problem, and as little time doing anything else — whether that’s wrangling unintuitive and poorly documented CLI tools, working around wonky, flaky third party APIs, etc. The value one generates is purely in solving the problem they set out to solve; all of the other hoops they jump through is the cost of doing business. I don’t see how you can fault someone for avoiding tools that (in their estimation) reduces their value to expense ratio.