Hacker Newsnew | past | comments | ask | show | jobs | submit | Twey's commentslogin

Regular reminder: the ‘lines of code’ metric is a liability not an asset. The best engineer is not the one who can produce the most lines of code in a day but the one who can ship the feature with the fewest lines (and prepare the system to receive the next feature with few lines, too).

> Language doesn’t matter anymore: Python, Go, Rust, Node. But system design hasn’t changed.

I keep seeing this claim, and it's incoherent. Programming languages are the languages we use to express system design, and just like Sapir–Whorf in natural languages they admit, emphasize, or force consideration of different concerns in the design process. If we did get to the point where those languages ‘don't matter any more’ it would just be because modern tooling allows us to express ourselves at a higher level than these languages were designed for — but then whatever higher-level language you're using to express yourself matters instead (and matters more than ever: the higher-level you go the more inaccuracies compound).

Programming languages are designed for humans, not for computers.


Health is not a perk but an inelastic demand: a threat to withhold health is a threat of physical harm, and a negotiation in which one party's physical health is on the line is quantitatively but not qualitatively different from a negotiation held with a gun to that party's head.

I do not understand your statement, maybe you can elaborate. If you are saying there should be a public option for healthcare, I happen to agree. Then we can have the standard discussions on how the government ought to raise funds for it. If you are saying that by negotiating terms of employment, any employer is intrinsically engaged in violence, that stance is pretty out there.

If those terms include the potential for predictable harms like lack of healthcare or housing if an agreement isn't reached, then yes, I think that is indeed an engagement in violence.

Now I'm not saying that the employer is necessarily morally culpable here — I'm sure most employers would like nothing more than to not have to worry about their employees' healthcare, and certainly I doubt many people enjoy having the ability to take it away. But it doesn't change the fact that it's impossible to have a real negotiation when inelastic demands are (potentially) unmet. Someone under threat of losing health insurance or housing is negotiating under duress, contrary to the comment I replied to.


Under this principle no human has ever been able to consent to anything in the history of the world. Certainly 99.99% of humans.

This would also imply that the best thing ethically is not to give people goods in exchange for labor because the simple act of interaction with them puts their housing and food needs under your responsibility.


No human can _100%_ consent to anything (… probably: free will is tricky). Coercion is a continuum, not a binary.

I don't really think that companies (or other parties in trades) bear moral responsibility for this inherently — a company that accepted every job applicant to try to meet their inelastic demands wouldn't last long, so the company itself is also under some duress even if it might like to. Trying to assign blame for complex distributed problems isn't really that simple. Your example in particular is a trolley problem, and I (personally) don't believe that pulling the lever makes you more culpable than deliberately choosing not to pull the lever.

But regardless of your chosen ethics, my point is pragmatic — while it's not correct to say that people take jobs only because they are under duress, it's also not correct to base arguments on them acting on their own free will based on their personal preferences. UBI experiments show significant changes in employee behaviour when inelastic demands are guaranteed to be met and negotiations pertain only to elastic quantities.


There can be labor monopsonies but it is not a rule; I promise you that the key employees at a SaaS startup tend to have plenty of options.

This effect is very much not limited to monopolies, though it's certainly easiest to see there. There's no step change from monopoly to competitive marketplace though. If you believe it's the company's moral duty to provide e.g. healthcare then in a non-monopoly situation that culpability is divided, though not abrogated (and beware the bystander effect!). From the employee's perspective, the spectre of physical harm is a bit further off, but it will still colour negotiations.

It's especially insufficient to generalize the working of the entire system from an example of a market in which employees currently have enough power to not really have to worry about the prospect of physical harm because it would be disadvantageous to the employers to cause it. Even if we take the current state of the SaaS startup market as reliable (which it isn't) the original argument was not limited to SaaS startup employees, and in other industries (including ones that are a bit down the pyramid from the SaaS companies) things are a lot less rosy for employees.


A sole consumer of labor is a monopsony, not a monopoly (that would be a union). At any rate, the point is that there are many many employment negotiations that no reasonable person would agree to amount to duress. This is a counterexample to the idea that any negotiation of employment involves duress. I don't need to disprove the existence of any coercive employment. But SaaS companies are especially relevant since pg specializes in showing people how to become billionaires through SaaS. If earning a billion dollars implies some measure of coercion we should be able to find that in a SaaS startup.

Sorry, misread you — but you can substitute ‘monopsony’ into my comment and I think it still holds.

This is a ‘no true Scotsman’ so I don't think I can really respond to it directly. But I'll point out that my claim is not that some contracts bargaining for safety of life and limb are a form of duress but that all inherently are (to some extent). Especially when the other party's BATNA is ‘no guarantee of safety’.


This is a strawman argument. It is of course mathematically possible to obtain a billion dollars (although notably much harder to do in a way that is liquid, but let's gloss over that). My somewhat more charitable reading of that claim (shared by other readers here, I see) is that ‘earn’ refers to moral desert. I'm not really a desert-oriented person but let me try to steelman it a bit:

In aristocracies we traditionally assume or imply that a person can deserve a certain wealth or power simply by being born into it. Capitalism, however, sells us the dream of the meritocracy: your (financial) success in life should depend not at all on factors of chance like birth or genetics but simply how much of yourself you choose to sell to the market.

At any point in time you have control of some tangible or intangible capital, including wealth, physical health, social connections, equipment, information, trained skills, et cetera. Some of these assets are gained by luck, e.g. accident of birth; some of them are gained by trading your time; and some of them are gained by spending another asset (whose origin reduces, recursively, to some combination of luck or time). At any point you can, assuming the market is appropriately liquid, spend some of these assets to get cash.

Some of these assets have force-multiplier effects on your future output in certain domains, from which exponentials naturally arise; but the time spent on them remains linear, and so, if we want to ignore inherited factors (the opportunity to spend the time on things without immediate feedback, say, or handed-down insight about which of these investments will produce the most value in the future, or access to the required tutors) the increase in earnings these things _merit_ has to remain linear as well. There is no way to compound your time and therefore, under an assumption of meritocracy, there is also no morally acceptable way to compound earnings, which I would assume is the point the politician is attempting to make. Under this worldview, any exponential compounding that occurs must, mathematically, be a result of systematically undervaluing the time of an exponential number of other people, since each person can only spend a linear amount of time.

In practice, of course, the assumption of meritocracy is simply wrong, and arguably the concept as a whole is internally incoherent (or at least I don't believe we've yet managed to articulate it coherently: we would have to settle the nature vs nurture debate and completely sever the value of a person's spent time from the accidents of their birth, if such a thing is even meaningful). But I think that's where the claim falls down, not in failing to understand the mathematics of exponentials.


> What is harder to find is the bridge between them, the part that connects understanding how async works to actually shipping with it.

There is actually already a tutorial at this level: Tokio has its ‘async in depth’ tutorial [1] that walks you through building a toy runtime and using it to run a future.

Not a complaint — you can never have too many tutorials, unless they're about monads — but just a pointer in case you hadn't seen it :)

[1]: https://tokio.rs/tokio/tutorial/async


Ah what a great little tutorial. Thanks for sharing that one.

It looks like rust async creates state machines similar to how Kotlin does it with so-called Continuations.


Yes I really think it should be better advertised!

The continuation model is the standard model of async programming and still perhaps the nicest semantically. Rust's big innovation is that futures are polled from the top, i.e. (potentially) advanced in an idempotent way whenever any of their relevant resources progresses, which is nicer for resource-conscious programming because it doesn't require that you capture the stack. It adds complexity over the continuation model from the programmer's point of view, but opens up async programming to a wider range of contexts in a way that is genuinely novel.


> I like my colours to have a bit more blue and green in them, so I skewed everything that direction. Colours like 222 look a tiny bit bluer / greener than you'd expect. It might be hard to see but trust me, it's true babe

Using a LUT to harmonize raw “working” colors is actually kind of genius. Interesting.

John Day talks about this a fair bit: what people want to do is naming of applications, in a way that makes it independent of addressing (i.e. where the application is running). DNS still names the machine — it's just a one-step abstracted machine addressing scheme, not an application naming scheme per se. Then we designed an ad-hoc protocol on top that associates applications with specific machine names (and port numbers): if you go to facebook.com:443 (a.k.a. https) you expect to find an instance of the Facebook application, not a webmail client or an SSH server.

This isn't how any of this was really supposed to work. Back in the day the application identifier was the _port number_, according to a big list maintained by ICANN. The idea was that you could go to a machine (identified by IP or more conveniently by DNS) and see if it was running an instance of the ‘Facebook’ application, i.e. you'd find Facebook not at facebook.com:https but at meta.com:facebook. The end goal was to eliminate the need for the former part at some point, and come up with a better way of looking up applications than distributing a list by email. Instead the application ID is now used for transport and the host name instead encodes application ID, which it was never meant for, and that's why we can't have nice things (like device mobility).


The concept of linting feels somehow inimical to Markdown, a language designed to progressively enhance existing plain-text formatting conventions.


> On the higher philosophical level, I wanted to avoid the cursed tower-of-abstractions trap that I felt quite sharply in C++.

Then you might want to avoid computers in general: C also sits on a tower of ‘imaginary’ abstractions (binary, gates, functions, allocation, virtual memory…). The computer itself is an abstraction, and sits on top of a teetering tower of other abstractions like electronics, physics, and (if you want to get philosophical about it) discrete objects.

> same bytes packaged differently become entirely different incompatible entities (like std::string vs std::vector<char> vs std::valarray<> etc)

The same bytes simply _are_ (in)compatible with different things depending on semantic context, and C++ is just surfacing that to you. A given slice of linear memory (which is an abstraction, of course) could be representing a heap or a string with the same bytes, and you'd better know which when using them — that information is not stored in the bytes themselves. Your choice is either to represent this in a way that the compiler can check for you, or encode that information in freeform human documentation about how to avoid the error cases that the compiler can no longer help you with.


https://en.wikipedia.org/wiki/Fundamental_theorem_of_softwar...

My point, more or less. Of course, a heap is different from append-only array, on higher level. On lower level, these are bit strings. Which is handy, if you can send it over the network with exactly the same function, for example.


But my bitstring representation of a heap may not be your bitstring representation of the same heap. Neither C nor C++ makes enough guarantees about the representation of the heap that you can assume that, so a higher-level ‘heap’ type that abstracts over the respective representations of my heap and your heap is inevitable, and not something to be scared of. Of course you can reasonably ask for a language in which the representation of a heap is uniform across hardware, but it will come with some performance penalties.

Everything on the computer can be _represented as_ a bit string. But it's important not to confuse that fact with everything on the computer _being_ a bit string. The bit string is only a ‘name’ to represent the thing in conversation between people who share an understanding of what that representation should represent.


In the same vein Wasm is also an option that might be more suited to this kind of thing thanks to the higher-level ABI (/components).


Even the _design_ of languages is a generational project. There are open problems in the PL space that we know need to be fixed but we have no idea how. Once you've got the ‘core ideas’ of the language in some papers somewhere (and proofs that they're coherent, which is usually the meat of the process) it's a pretty quick step to get a toy implementation, but then the path to an implementation that is usable for day-to-day work (especially if performance is important) can take decades, and the path to adoption after that can easily take between 5 and 20 more years.

Then people figure out the thing about your core ideas that gets in the way when writing the kinds of real-world programs they want to write and you get to go back to the drawing board for the next language idea :)

As an example of the kind of time scales involved, linear logic was introduced in 1987. Linear (well, affine) types made it into Rust 1.0 in 2015, which IMO is the first time substructural types have made it to a ‘mainstream’ (albeit still far from ubiquitous) language. And that's a very straightforward language feature that doesn't really challenge the dominant imperative/functional hybrid paradigm or have any inherent effect on performance (since it's ‘just’ a type system feature).

IMHO the next big thing up (assuming LLMs and other AI advancements don't throw everything off-kilter) is probably effect systems, introduced in ~2013, for which we can linearly extrapolate a time frame of about 2041!

But maybe not — one exciting thing that's been happening is that (as Jonathan Blow noted) with the growth of lower-level substrates like LLVM the work to go from a toy to a working and performant language has decreased significantly.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: