For the best experience on desktop, install the Chrome extension to track your reading on news.ycombinator.com
Hacker Newsnew | past | comments | ask | show | jobs | submit | history | more Cushman's commentsregister

I’m not vegan so it’s none of my business, but: Sure! if you’re not eating processed foods, and you don’t want to spend hours a day cooking, everyone needs supplements.

Don’t forget that our salt and our flour and our milk and — “raw ingredients” — are supplemented by default with micros the standard diet is deficient in.

If the standard diet was vegan, there’d be taurine in the lentils and we’d be saying a meat-and-dairy diet is impossible without “supplements”.


Which kinds of food are supplemented by default varies from country to country.

While table salt is supplemented by default with iodine almost everywhere, flour and milk are supplemented by default only in a few countries and I consider that this is a very good thing and that they should not have been supplemented by default anywhere.

This forced supplementation is stupid, because it will not achieve an appropriate daily intake, except for a few people who happen to eat a certain amount of floor and milk, while for all the others it will be either too much or too little.

The right way to help the poor is to subsidize the price of vitamins and essential minerals, not to waste them by adding them to a certain kind of food, so that everyone who eats something else will not get them.

And the argument that the government should supplement some food ingredients because people have become too stupid to eat what they should, is even more ridiculous. Even supposing that modern people have become more helpless than their ancestors, so they would not be able to identify or catch anything edible when left alone in a forest, that does not mean that they should not be able to at least have the survival skill of buying the right food from a supermarket.

If it is believed that most people are not capable even of doing that, then they should be educated instead of hoping that the solution is that the state should feed them with food ingredients whose composition they no longer understand.

There certainly are few things more important for any human to know, than how to choose what to eat, in order to not die and to remain healthy.


Okay! I’m not here to tell anyone what to eat, so all I can say is I don’t have an opinion on that.


Do you have any source on that?


> I can’t imagine anyone buying a $3000 headset for “videoconferencing” as the killer feature.

Believe it. "Social presence"[0], the feeling of actually being in the room with another human being, is a very real phenomenon. Its influences are things like gaze following, head movements, hand gestures-- things flatscreen video chat has not and likely will never be able to capture veridically. Its impacts are things like empathy, affinity, trust-- things you very much care about when money is at stake.

To be excessively glib, social presence is why deals are still being won by the firmer handshake, not the better term sheet.

Can Apple deliver this today? Who knows. No one's done it outside of a lab before. But if they can, this isn't competing with video chat-- it's competing with airplanes. And if they can, $3000 is an unbeatable price.

[0] https://en.wikipedia.org/wiki/Social_presence_theory


Apple can’t even do realistic gesture tracking with their memojis on their highest end iOS devices. It’s appallingly bad and can pretty much only do a dozen or so expressions and with lag. I highly doubt their ability to do this in a more serious setting.

There’s enough issues in video conferencing today with audio codec compression and video buffering and Bluetooth issues - I would not want to add an entirely virtual layer on top of that. “Can you hear me?” will be replaced by “are you angry?” when it mistranslates a facial expression. Miscommunication over digital medium (text) is already a huge issue.


I just tried it on iPhone 14 Pro Max. There is no lag at all. Also I am not sure what exactly is appallingly bad? It's pretty good. If you are expecting Pixar quality gestures then that's on you


...and don't forget the benefit of having your persona represented as a Memoji -- you don't have to waste your morning prettying your self up. Hygiene, of course, keep doing that. But what if you didn't have to even concern yourself if your hair is unkempt or you're just wearing the sweatshirt you slept in.

Time savings given back to people is worth something.


> No one's done it outside of a lab before.

Depends on the person. There are many videos [1] where people report that feeling of social presence e.g. whilst working in a virtual cafe.

Question now is whether Apple/Meta can bring that feeling to everyone.

[1] https://www.youtube.com/watch?v=KAA9hBwnQKQ


Indeed, and to clarify, it's not a binary feeling for anyone-- IRC is better than email, FaceTime is better than the telephone. VRChat is state of the art on prosumer hardware, but it's not competitive with the boardroom. Yet.


Today? No. Tomorrow? Maybe.

I think it will be an expensive luxury for another while, but commonplace in a decade or so.


Will there be a chapter on this element?

It’s always been unclear to me how much a Martian civilization would improve humanity’s odds of surviving Seveneves, what with humans being involved and all. I think it’s the article of faith I’ve seen the least substantive critique of— maybe because it’s so depressing to think critically about.


I would say quite a bit, as it implies substantial space infra being in place. Still not pretty, but at least you would avoid things like cramming 20 kamikaze welders in space suits inside a Proton fairing per lunch to turn ISS to a space arch.

BTW, on this note I can recommend The Ring of Charon[0] and its follow-up books. In this case, its Earth suddenly vanishing due to some ancient alien technology being activated by mistake. The book then follows the consequences for the advanced but still partially Earth dependent space habitats in the Solar system as well as people on Earth figuring out WTH their planet has ended up and why.

[0] https://en.wikipedia.org/wiki/The_Ring_of_Charon


This is a great point, but I think it goes towards the cost-benefit analysis. The relevant comparison isn’t a sophonically-suppressed humanity which is never inspired again, but rather Maciej’s new age of exploration— a humanity very much conquering local space and reaching to the stars, just not with their own fleshy pestilent mitts.

The open question I have is does a planetary colony help per se, once the technical problems have been solved on an emergency basis, and what’s left are social problems which are far too late to cure?


Cool! Y’all, this is obviously an RPC interface, but the point is that `import { onNewTodo } from './CreateTodo.telefunc.js'` is not, as written, an RPC. That transform, with seamless type support et cetera, is what makes this interesting. (If you think it’s interesting.)

I think it’s interesting; I experimented with a higher-magic version of this a couple of years ago. (It had continuations to support returning callbacks, could preserve object identity, and could lift inline anonymous functions to the server with some amount of intelligence.) My goal was to make the RPCs as close as possible to local async functions, which was really fun when it was working.

My experience was that for the simplest use cases, the ergonomics were unbeatable. Just drop a `@remote` tag into your TodoMVC frontend, and there’s your TodoMVC backend. But as soon as I had to look under the hood (for something as simple as caching behavior), the “just a function” interface was a distraction and I found myself wishing for a more conventional RPC interface.

(I think that might be why you tend to see this sort of magic more in the context of a full framework (such as Meteor), where all the typical use cases can be answered robustly. If you’re building your thing out of modules, cleverer abstractions usually mean more work overall to integrate everything and boring is better.)


Joel Spolsky had an ancient article titled "Three Wrong Ideas From Computer Science" (2000): https://www.joelonsoftware.com/2000/08/22/three-wrong-ideas-... Some parts of this don't hold up that well.

But it has a section titled "Network Transparency" that talks about when transparency of fails. And he calls out three things that make network calls fundamentally different:

1. Availability. It's possible that your network "function" will be impossible to call for some amount of time.

2. Latency. The round-trip latency of RPC calls is extremely high, which affects API design in major ways. Typically, you wind up wanting to perform multiple queries or multiple operations per round-trip.

3. Reliability. Network calls may fail in many more ways than local calls.

And these are all issues that have defeated many "transparent" RPC systems in the past. Once your application spreads across multiple machines that interact, then you need to accept you're building a distributed system. And "REST versus RPC" is relatively unimportant compared to the other issues you'll face.


> he calls out three things that make network calls fundamentally different:

Joel Spolsky was not the originator of these ideas; their most famous form comes from about 1994, as written by L Peter Deutsch:

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


To JS developers' credit, writing modern JS in many ways already is like writing a distributed system.

Even if you stay fully client-side, you have bits of code that are running in different parts of the browser and you have to marshal data back and forth between them. Many web API functions are really RPC calls into a different browser process.

JS has has primitives like channels, promises or async/await to deal with those.

At least there might be some ways how you could use those as as building blocks for an RPC system which lets you handle the three problems better.


The client-server relationship is distributed but the intra-browser stuff is just async IPC. Writing robust clients against remote APIs requires considerations around retries, failover, idempotency and read/write consistency. It seems to me that distributed patterns in pure client code are thin on the ground and limited to things like CQRS and Sagas.


It's not like, it is a distributed system.

With PWAs web apps can and do work offline or work limited network. There's a whole series of problems this is useful for.


Web RPC protocols are not trying to replace local function calls though. They're trying to replace remote API calls (REST, GraphQL etc.). And all remote protocols have to solve problems like availability, latency, and reliability. Those problems remain. This is trying to solve a different problem with different trade-offs.

The problem it solves is unnecessary protocol noise and the trade-off is tight coupling between frontend and backend code. I think it's obvious that the trade-off makes sense for small projects and MVPs: most changes require touching both ends and typically the team isn't differentiated between backend and frontend anyway.

But even with large projects that have to cater to many clients, a tightly-coupled RPC system can solve problems like overfetching and underfetching as a straightforward method for implementing the BFF pattern[1].

[1] https://medium.com/mobilepeople/backend-for-frontend-pattern...


Exactly.

Telefunc is about replacing generic endpoints (RESTful/GraphQL APIs) with tailored endpoints (RPC).

That's why the trade-off is simpler architecture (generic endpoints are often an unnecessary abstraction) VS decoupling (tailored endpoints require the frontend and backend to be deployed in-sync).

In the long term I foresee RPC to be also used for very large teams. I've ideas around this, stay tuned. I can even see companies like Netflix ditching GraphQL for RPC, although this won't happen any time soon.

In the meantime, RPC is a natural fit for small/medium sized teams that want to ship today instead of spending weeks setting up GraphQL.


Every generation keeps trying rpc and learns its lesson…eventually.

On windows it was DCom, then COM+ then remoting the WCF then who knows I lost track.

Rest APIs are simple and easily debuggable, magic remote api layers are not.

That’s why REST is still prevalent even in websockets had better better performance parameters (and in my testing it did have performance advantages) yet 7 years after my testing hire many sites are running websockets?


For lots of APIs this is somewhat true. However, I recently took a deep dive into "REST" and realized that for many APIs, you really have to contort how you think in order to make it fit into that model.

It generally works for retrieving data (with caveats...), but I found that when modifying data on the server, with restricted transformations that don't necessarily map 1-1 with the data on the server, it feels like forcing a square peg into a round hole. I tend to think of verbs in that case, which starts to look like RPC.

("REST" is in quotes because the REST model proposed by Fielding (ie, with HATEOAS) looks almost nothing like "REST" in practice).


If Telefunc is bug-free (which I intend to be the case), then you won't need to debug Telefunc itself.

For error tracking, Telefunc has hooks for that.

For debugging user-land, you can `console.log()` just like you would with normal functions.

Do you see a concrete use case where this wouldn't suffice?


> If Telefunc is bug-free (which I intend to be the case), then you won't need to debug Telefunc itself.

And if no one crashes, you don't need airbags.

If I'm being blunt, reality doesn't give a shit what you think. It's better to design with the assumption there are bugs so that _WHEN_ it happens, the users are up a creek without a paddle.

These sorts of implicit assumptions are how painful software is made.


Software can be verified to be correct, stupidity of others is unavoidable.


Did someone solve the halting problem while I wasn't looking?


No, but somebody created type checking, linting and testing.

Not sure what's up with the CS people and their halting problem. In the industry we've solved (as in developed ways to deal with) the problem of verification decades ago.

Also, debuggers. Nobody said the verification can't be done by a human.


verifying software is correct implies solving the halting problem.

What you mean is "no known bugs", so may be use those words instead. "verification of correctness" has a specific meaning in our industry.

yeah yeah, I get it, those stupid CS people and their P=NP talk. Don't they know you can obviously verify correctness without verifying it for all possible inputs? What next, you can't prove a negative such as absence of bugs?!?


> verifying software is correct implies solving the halting problem.

No, producing a program that can verify that all correct programs are correct implies solving the halting problem.

Verifying a particular piece of software is correct just implies you've proved that one piece correct. (And probably wasted your time dicking around with it only to find that the actual issue was in software you treated as 'outside' of the software you were verifying...)


What you're describing is the programming version of approximation. It's understood that it has a margin of error due to the approximation.

What you're claiming here is that if you check enough inputs you've proven it correct, and what I'm telling you is that's not the case.

The fact is, nothing has been proven, the wording on the webpage itself is more honest (no known bugs and a suite of automated tests).

To verify a program is correct is a much stronger claim than what is even on the website. And that requires restricting the input or solving the halting problem.


Generic endpoits are a design smell. Junior devs making Junior dev problems because someone who's been coding for 10 minutes wrote a series on api design on Medium.

See the backend for front end pattern.

Debuggabilty wins.


Interestingly there was some research around the latency issue, trying to automatically rewrite the client code so that remote calls are batched together. (This was done in Java where rewriting the .class file was tractable): https://www.doc.ic.ac.uk/~phjk/Publications/CommunicationRes...


Availability and reliability can be handled similarly by thinking about classes of failure modes. Most RPC frameworks have error codes that are too fine grained (see HTTP and it’s cousin REST).

Latency is actually mostly solvable with something like cap’n’proto that pipelines the promises so that you can have a normal looking composable functions without the latency cost.

Joel Spolsky advice is usually fine but it’s important to understand his commentary tends to be about what ideas are in vogue / dominant at the time of the post and tend to have a more limited perspective (vs listening to researchers in the field actively investigating the problems and investing in ways to find solutions).

For example, we have an explicit class that manages RPC calls so that at the call site it looks like a regular function. But since it’s I/O it returns an async so it makes it clear that it’s I/O (which you have to do with non NodeJS JavaScript). Additionally, it returns a promise of a Result object type just like any other failable call which you have to handle properly. Works pretty well (although in retrospect I’m now wishing we had used structured clone instead of JSON to send messages around).


Sorry, but this post just shows a lack of experience in dealing with distributed systems. Joel was bang on the money about the problems of disguising network interactions in applications.

Async vs Sync is not enough. Network partitions have multiple failure modes depending on a range of factors, but one of the most pernicious is the “undetectable cloud break”, an invisible break between two routers. Having a well defined “api” that is the clear “we are communicating over the network here” makes it much easier to reason about and handle these issues.

There is an enormous difference between “this I/O call failed” and “this I/O call took 10 minutes to fail”.


vlovich123 built Cloudflare's R2, I think he has some experience with distributed systems.

The RPC debate is confused because the two sides of the debate have different ideas of what RPC is. The anti-RPC crowd is arguing about RPC systems from the 80's, which tried to make RPC look exactly like a local function call, including blocking until the call was complete. The pro-RPC crowd is mostly speaking from experience using modern RPC systems which do not do this; they use asynchronous callback APIs, have some mechanism for reporting network errors, etc. Modern RPC systems are called RPC because they encourage you to organize your network API conceptually into something like function calls, but they certainly do try to hide the fact that there is a network here that can fail in all the ways networks fail.


I don't see why automatically converting functions to RPC APIs is incompatible with a clear "we are communicating over the network". Just put all the RPC functions in their own `network` namespace or whatever.


One counterpoint to that is that this works very well in Erlang (and Elixir) and has done so for 30+ year. Well, I might be cheating a little bit with my definition of "so" :)

I'll agree with you that it's not a trivial change, far from it. You need switching your mindset from local to remote, from procedures to agent messages, from exceptions to non-local error-handling, but it remains quite simple and readable.

I feel that Telefunc is bringing developers a good chunk of the way towards that goal. And, who know, maybe there is another simple model that is not exactly agents, and that would also work nicely.


> Most RPC frameworks have error codes that are too fine grained (see HTTP and it’s cousin REST).

Are HTTP and its cousin REST examples of RPC frameworks? I don’t think so, and I may have misunderstood your point. But if you do consider them to be RPC, can you explain your reasoning?

Despite drawbacks here and there, I do have appreciation for RPC, e.g. JSON-RPC is widely used in the distributed/decentralized tech space I work in. It’s fairly well-specified and well-suited for a variety of use cases:

https://www.jsonrpc.org/specification


Not the GP, but I would definitely consider REST a layer in a RPC framework.


> I would definitely consider REST a layer in a RPC framework.

A beef patty is not a hamburger without the bun, pickles and condiments.


The distinction that it has to look like a normal function call is unhelpful. To me RPC and IPC are synonymous (which I get isn’t the Wikipedia definition). I lump them all together as “distributed communication”. The actual problems I think about are:

* semantics of what the request / response looks like and how failures communicate

* how are the APIs composed? Not the local function call, but the functionality calling the API implies (see cap’n’proto’s page on composable remote APIs - it’s really brilliant).

* can you communicate across programming languages?

* how is ownership of remote resources managed?

* how is routing / dispatch of API calls managed?

For example “fetch” in JS land looks a hell of a lot to me like a normal function call to me. And I certainly then wrapped it with easier to read APIs that looked more normal and handled routing and error handling for me. The main difference with HTTP is that RPC systems traditionally autogenerate a bunch of code for you. But in HTTP land you now have efforts like OpenAPI to do similar things. So HTTP isn’t RPC but the autogenerated code from a description of the API makes it RPC? That gets you into the ship of Theseus paradox which isn’t helpful. At what amount of wrapping it with local functional calls does distributed API calls transform into RPC?

To me it turns out that async / sync is a key distinction and the original sin of RPC in the 80s. It’s also why I view the coloring problem as a good thing (at least given where the tech stack is today). Making functions that may be doing I/O stand out and needing thought is a good thing. The problem with many RPC/IPC mechanisms from the 80s is they tried to make the code seem synchronous not that it looks like a function call. But I haven’t seen any RPC systems where async vs sync is the distinguishing characteristic (eg cap’n’proto and fetch are both async).

To me, HTTP, REST, SOAP, COM, gRPC, cap’n’proto, JSON-RPC, XPC, Mach etc all try to solve the same problem of distributed communication and processing, just by making different trade offs.

HTTP tried to standardize RPC semantics but you can clearly see it’s optimized particularly around static document retrieval and typical browser tasks. I’ll buy that static document retrieval need not be classified as a remote API but there’s a lot of non static document retrieval that’s layered on the same semantics that is proper API calls (notably REST) tries to get everything to conform to that so that middleware has some convention and you get browser interop. It works surprisingly well because a good majority of apps are CRUD and don’t need anything more.

JSON-RPC tries to solve routing/dispatch to be more automated if I recall correctly because REST is such a cluster (look at all the routing libraries which to me are an anti pattern). + JSON-RPC is particularly easy in JS which is usually the language on one side of the transaction.

COM solves all of the above and things like distributed ownership of resources, except it historically didn’t have a good security model (I don’t know it well enough to know what’s improved there but I don’t assume it’s stayed static since the 90s even if it hasn’t found traction outside Microsoft).

They all try to solve different parts of the problem or have different sets of tradeoffs, but to me it’s fundamentally the same problem. It’s the same reason I don’t view distributed systems as something that requires different machines, CPUs, processes or anything about geography. You can have distributed systems within one process, you can have it within processes on the same CPU, you can have it between CPUs on the same device, etc. Heck, to me even the kernel and user space form a distributed system with syscalls as a primitive RPC mechanism. JNI is a form of RPC too although you’ve seen traditional systems like gRPC supplant it even within process because it moves complexity out of the JNI layer into a simpler system with easier to follow rules.

Now you can sometimes makes simplifying assumptions to reduce complexity, reduce power usage etc. and not all distributed systems necessarily have the same sets of problems. But fundamentally to me it’s all the same problem space and why I don’t distinguish the terminology so much.


Yes, and that's why in Telefunc's world remote functions are called "telefunctions" to differentiate them from normal functions.

Telefunc doesn't try to completely abstract away the network: as you say, it's not possible to abstract away network latency and network failure. Telefunc is about creating network endpoints as easily as creating functions.


And you can just figure out a solution for these things as there is no one solution. There are many different tradeoffs needed based on the call.


> My experience was that for the simplest use cases, the ergonomics were unbeatable.

Exactly.

> the “just a function” interface was a distraction and I found myself wishing for a more conventional RPC interface.

For real-time use cases, I agree. I believe functions are the wrong abstraction here for real-time. I do plan to support real-time but using a "it's just variables" abstraction instead, see https://github.com/brillout/telefunc/issues/36.

> cleverer abstractions usually mean more work overall to integrate everything and boring is better.

Yes, Telefunc's downside is that it requires a transformer. The Vite and Webpack one are reliable and used in production (using `es-module-lexer` under the hood). The hope here is that, as Telefunc's popularity grows, more and more stacks are reliably supported. Also, there is a prototype using Telefunc without a transformer at all, which works but needs polishing.

> I experimented with a higher-magic version of this a couple of years ago.

Neat, curious, is it on GitHub?


> I think it’s interesting; I experimented with a higher-magic version of this a couple of years ago. (It had continuations to support returning callbacks, could preserve object identity, and could lift inline anonymous functions to the server with some amount of intelligence.) My goal was to make the RPCs as close as possible to local async functions, which was really fun when it was working.

That sounds familiar! We were doing all of that for Opalang arount 2009-2010 if I recall my calendar correctly. Were you there?


>It had continuations to support returning callbacks, could preserve object identity, and could lift inline anonymous functions to the server with some amount of intelligence.) My goal was to make the RPCs as close as possible to local async functions

Are you me? I made this as a fun project a while ago, and left it there gathering dust, but earlier this year it found new life in an AI application and it's delivering promising results.


I actually think this comparison is quite apt. Like those others, the science of linguistics has become heavily politicized in the US, most notably regarding the validity of AAVE as a first language.

Though I'd still argue linguistics has it worse. You don't really expect people in educated society to get into heated arguments with the 10-day weather forecast, or jump in to correct your "biology mistakes" while you're eating...


Spot on. Disdain for Ebonics is one of the last remaining ways in which it's considered acceptable in polite society to be blatantly racist.


Not to sincerely defend the claim that "the" "is" an adjective, but rather to dispute the general notion that grammar is "real": Here are some adjectives that fail your tests.

> The, theer, theest? The, more the, most the?

* Worstest? Most least?

> The shoe was red but most importantly, it was the. She had never before seen so the a shoe!

* The smallest shoe confused her. How could it be so smallest?!

> In the clearing was old a house with smoke rising from stone the chimney.

* Outside the wooden red house was a brick grey ancient barn.

The last one is especially interesting-- if you're a native English speaker, I'll wager that "brick ancient barn" sounds nearly as ungrammatical as "brick the barn", but it's a lot harder to explain why.

Edit: Some more decisive examples of that from replies, since some have rightly pointed out that "brick ancient barn" is semi-acceptable in context:

* "grain lone silo", "fish dry pond", "beef tasty stew", "laptop lost bag", "horse leather saddle" / "leather horse saddle" (both grammatical, but different meanings)


> Outside the wooden red house was a brick grey ancient barn.

native speakers of english will find that "red wooden house" is favored over "wooden red house", the same way the "big red dog" is favored over "red big dog".

There's an ordering to adjectives that has something to do with how important the adjective is to the identity or distinctiveness of the modified object.


The first two (worstest/most least, so smallest) are easily classified as wrong because "-est", "most", and "so" only apply to adjectives of positive degree rather than comparative or superlative. So to deny that grammar is "real" using these examples is to attack a strawman.


Oh, I get what you're saying-- so "the" must be a superlative adjective, right? Makes sense really, as it's the "most specific" article.


... no, quite the opposite. Since grammar has no reason to prefer large classification sets (generalization) to small (uniqueness), unlike descriptive linguistics, I'm perfectly happy to say that grammatically "the" is an article and leave it at that.


Actually there's an order you are supposed to apply things like that. Maybe someone came up with it after the fact, but there is a determinative way to make a list of adjectives sound right.


"brick grey ancient barn" is grammatically correct if you assume "brick grey" is a color, but of course that's probably not what it's supposed to mean.


Indeed! Although I'd argue that probably is what it's supposed to mean.

A "leather horse saddle" and a "horse leather saddle" are very different things, and no native English speaker would mix them up. You know which they mean.


What's your point?


That one is for horses, and the other is from horses.


As any fule kno


Time flies like an arrow. Fruit flies like a banana.


"Worstest" seems to be a morphological problem. "Most least" could be permissible, if somewhat exotic sounding, I think, if "least" is read with its adjectival meaning―"used in names of very small animals and plants, e.g., least shrew"―so eg. most least shrew. "So smallest" doesn't work with any other superlative ("most reddest") that I can imagine off the top of my head. And "brick ancient barn" is an unusual order but not ungrammatical, though it is interesting. (It sounds more like listing adjectives, ie. I'd read a larger pause after "brick" and stress on "ancient", than the other order. MATERIAL AGE NOUN seems to read awkwardly.)


If "brick ancient barn" is too plausible for you to get the full effect, try something with more diverse adjectives like "beef tasty stew" or "laptop lost bag".


You really do like fake examples. Can you point to a syntactician making the argument that the "beef" of "beef stew", or the "laptop" of "laptop bag", is an adjective? In any context I'm familiar with, that person would be laughed out of the room.


Fair point, apart from the invective. How do you feel about "hiking worn boots" or "mixed-breed adorable puppy"?


"Hiking boots" has the same problem -- the boots aren't themselves hiking, they're boots for use in hiking. That's another noun-noun compound.

"Mixed-breed puppy" is, to me, not such a clear case ("breed" is clearly originally a noun, but maybe this use is common enough to have converted). But you don't need to use spurious examples -- in another comment, you provided a very genuine one: "red" and "wooden" are both clearly adjectives, and their ordering cannot vary. This is a well-known example of a somewhat-but-not-entirely mysterious phenomenon in linguistics.

Here's a nice recent writeup of what I think is a related phenomenon: https://stancarey.wordpress.com/2015/04/28/cutthroat-compoun... . This one consists of the observation that words like "kickass" and "pickpocket" are suppressed (not illegal, but suppressed) in English because they conflict with our tendency toward right-headedness (that is, in any English compound, the "essence" of the compound should be found at the right end). Instead, we incline more to compounds like "bank robber" or "nose-thumbing" ("engage in a bit of nose-thumbing"). Someone else in this thread already mentioned that they see adjective ordering as a question of which adjectives are more essential to the whole.

My problem with your comments here is that you're making arguments based on obviously spurious tests unrelated to the claims you then try to follow (um, lead) with. It's analogous to saying "We need to stop celebrating Thanksgiving by eating turkey. Turkey perpetrated the Armenian genocide, genocide is bad and should be stopped, QED". Stick to honest examples, and you'll find the problems you're talking about are rather muted. Don't let your feeling that the problems are large, and you therefore need extremely malformed examples, lead you into choosing examples that are extremely malformed because they exhibit a completely different problem.


Well, yeah, I jumped in to defend the idea that the word "the" counts as an adjective. It seems vaguely possible that my argument is not backed by much besides bluster. (And of course the downvotes are my just reward.)

To the extent I'm arguing something non-disingenuous, it's just that language is best analyzed with a bit of a fuzzy lens, and words don't fit into neat boxes.

Take your claim that "hiking" is a noun: To me, it analyzes as an inflection of a verb ("hike") that can be used to indicate an action ("I was hiking"), the performer or target of an action ("I don't hate hiking, hiking hates me") or as a modifier for something else ("those crummy old worn-out tan leather gusseted hiking boots").

On what basis do you say that it is a noun? Specifically, when looking at the list "crummy old worn-out tan leather gusseted hiking", with modifiers lined up in order of significance, what about the word "hiking" jumps out at you as plainly different in use or meaning? "The boots aren't hiking, they're for hiking"? Clearly-- in this phrase, the word "hiking" means the boots are for hiking!

To me, the most intellectually honest thing is to see compound nouns as a sort of epicycle-style theory to explain why words in our non-modifier class are actually used as modifiers all the time, just according to a subtly different set of rules than applies to the modifier class. I don't think there's anything really wrong with that, since it explains things well enough and we might never have something like universal gravitation to set the record straight.

What I'm saying is, I don't think I have a problem.

Except, of course, when the "rules of grammar" are used as a proxy to cast minorities and lower-class people as unintelligent. That, I have a problem with, and it's quite a popular pastime in the English-speaking world. That's why I think it's important to think scientifically about the extent to which grammar is, and is not, a real thing. (Including, sometimes, hypothesizing things that don't make sense, just to see what happens.)


> Take your claim that "hiking" is a noun: To me, it analyzes as an inflection of a verb ("hike")

I wouldn't say you're wrong about this. However, I'd be much more willing to defend the idea that, as it appears here, "hiking" is a one-word noun phrase containing a verb form (and that compound nouns are formed NP-NP, not N-N). Traditional grammar has gifted us with a rich vocabulary of specialized terms for specialized syntactic functions, and the traditional term for a verb form which functions as a noun is "gerund". (Um, technically, infinitive forms can also function as nouns.)

I'll pause here to defend myself from an argument you haven't made: there are people who will say that "beef" in "beef stew" is an adjective simply because it modifies a noun. They're wrong. I say that a gerund really is a verb form acting as a noun. The difference is that I'm saying that gerunds can appear in basically all syntactic contexts that permit noun phrases, so the definition I'm using is syntactic (as appropriate for a syntactic term of art like "noun") rather than semantic. I'm not saying gerunds are nouns because they refer to objects -- I'm saying they're nouns because they can be the subjects of verbs (and otherwise appear where nouns appear). To me, the best analysis is just that noun phrases can be constructed from verb forms. Linking back to the subject at hand, I'd agree that "hiking", the word, is not a noun in the same way that "iron", the word, is one, but I am saying that this "hiking", as used in context, is just as much of a noun phrase as "this rusted iron" is.

> Specifically, when looking at the list "crummy old worn-out tan leather gusseted hiking", with modifiers lined up in order of significance, what about the word "hiking" jumps out at you as plainly different in use or meaning?

In all honesty, what jumps out at me is that all of the others are descriptions, while it would be odd to use "hiking" that way. For example, in a certain style of speech, you could see something like this:

    Get out and take your crummy, old, worn-out, leather, gusseted, boots with you.
(In actual rhetoric, the descriptors would probably be different.)

But it's completely impossible for the "hiking" of "hiking boots" to be delimited by commas (in speech, emphatic pauses) that way. If you did it, the meaning of "hiking" would change -- it would mean that the boots were out on a hike. This demonstrates that "hiking" is not a descriptor for "boots" -- rather, "hiking boots" is a single unit. (Yes, with internal structure.)

> To me, the most intellectually honest thing is to see compound nouns as a sort of epicycle-style theory to explain why words in our non-modifier class are actually used as modifiers all the time, just according to a subtly different set of rules than applies to the modifier class.

English is way more liberal with modifiers than that.

    He gave me his I'm-going-to-kill-you look.
I agree that language requires a bit of a fuzzy lens. But grammar is very much a real thing.


I wager it's consensus that determines what sequence of words is considered "proper" or not. Personally I have very generous criteria for what a reasonable sentence is. Thought experiment: Reversed words of sequence the with but us for valid as count would that anything be to sentence valid a define.

When we're young we absorb language the way we experience it, in an informal and cultural way. I think in any attempt to categorize aspects of language this basic character has to be respected (which it is in linguistics, being fundamental to it, but which it isn't in e.g. English canon).

Accepting that one's language is actually a messy evolution-convolution of ancient languages is easier for some than others. :D


Wait, what exactly is wrong about the last one? It sounds odd, but not so incorrect, to me.


It is perfectly grammatical if "brick" is taken to be a verb.

Edit: this is in reference to "brick the barn". Grammatical if nonsensical. "Brick ancient barn" is of course weird and wrong unless you really want to emphasize that this is a brick ancient barn and not a wooden ancient barn like all the other ancient barns. The normal adjective order can be deviated from for emphasis. My point was that that didn't work when "the" was one of the "adjectives".

(I've been trying to fall asleep for hours so I make mistakes left and right -- I apologize for not being clear about the word list I referred to.)


Not to keep you up, but what's even cooler is that the degree to which you can deviate depends on the adjective's class, too. While I can sorta see "brick ancient barn" working, albeit with such heavy emphasis on "brick" that "ancient barn" turns into a bit of a compound, "grain lone silo" or "fish dry pond" don't sound grammatical to me at all. Maybe also because "grain silo" and "fish pond" are almost-notquite compounds?


That ship has sailed. It's 06:40 and the sun has been pouring through my windows for more than an hour :/ The part of my body that has synched up with the daylight refuses to listen to the part that needs sleep.

--

"Grain silo" and "fish pond" are exactly-precisely compound nouns. It's just that English refuses to accept that it's a Germanic language and instead puts on airs. Honest languages would of course never dream of inserting pretentious spaces between the constituent parts.

I actually thought of "stone chimney" as a compound noun instead of adjective + noun when I wrote it, precisely because I wanted to mock that and really hammer home the point. Unfortunately, the two look the same in English (but not in Danish) -- and I was tired -- so I didn't catch it and replace it with a better example.


> "Grain silo" and "fish pond" are exactly-precisely compound nouns.

Eeeh, not exactly in English. English does make some distinction between fully compounded words and noun phrases, especially in rules of production. In a newer phrase like "wind farm", you can swap in more or less any noun you like, even if it doesn't make a lot of sense: "mud farm", "rock farm", "hair farm"... there's some rule like "substance + farm = a farm that produces that substance". With a word like "bedroom", you can get "bathroom", but not so much "deskroom"; there's no general rule like "furniture + room = room where that furniture is found". The space (in cases where it's pronounced) is kinda your hint there.

Anyway... I still don't believe in grammar, but y'all have mounted a spirited defense of the traditional analysis. I'm sorry I tried to say everything's an adjective :)


English draws this distinction for gold, with gold (n) and golden (adj).


I actually meant: written in one word (stonechimney, a compound noun) or not (stone chimney, not a compound noun).


http://www.gingersoftware.com/content/grammar-rules/adjectiv...

Most people would be comfortable saying "ancient grey brick barn".


> As someone who has struggled with lifelong depression, I still didn't recognize anything familiar in his description of watching hours of television a day

Since I wrote elsewhere that I feel DFW's writing captures depression well, this might be a good place to clarify: I don't mean that his characters act the way I might act when I'm depressed, except maybe in caricature. I mean he writes in a way I might think about things when I'm depressed.

To put it another way, I don't agree with much of what he has to say, yet it resonates.


Maybe it's just me -- and I never met the man -- but I've never had someone convince me they understood what it's like to be terminally depressed as completely as the writing of DFW. It boggles my mind that someone could miss or misbelieve that.

The way that "This is Water" speech/pamphlet is brought up in particular horrifies me. Hindsight granted, it's always read to me as someone who, stuck in a deep, dark hole for so long, has given up on finding a way out. Blaming himself for being there in the first place. Standing so close to an answer, but unable to see it. And we know how the story ends.

It's a feeling I know well, and I'm routinely shocked how people without (I assume) first-hand experience with depression can completely ignore the darkness there, and see something banal or even encouraging.


I don't love the Kenyan College address as much as a lot of people do, but the idea that it's treacle, or a depressive's accounting of the tribulations of going to a grocery store (and one wonders: how can it be both?) seems like horseshit. To me, it seems like a pretty straightforward recapitulation of the ideas behind cognitive behavioral therapy, which Wallace probably had more than a passing familiarity with.


To answer your rhetorical: It can be both because depression makes boring things terrifying in a way non-depressed people find boring again. shrug

Anyway, I don't want to go too deeply into this, so I'll just say you're actually not far off from what I'm saying. What saddens me about "This is Water" is the fact that it's so close to something that might have been really helpful to him. He's talking about these daily experiences, and noticing how he's feeling. He feels bad. That's good; feeling bad helps.

And what he thinks next is... You have a choice of how to feel. Think about everyone who feels even worse. You can decide what you care about. Don't think of an elephant.

That isn't CBT, nor anything therapeutic-- that's depression, at its most pernicious and deadly.


I love the Kenyon address more than any other piece of writing I can think of. I don't read any particular complexity or symbolic meaning into it other than the seemingly revolutionary idea that all the people in the world with you are pursuing their own goals, and are harried by their own demons, and are basically doing the best they can in the circumstances they're in, so maybe you should be a little bit charitable to them, in your own mind, and by extension charitable to yourself.

The attitude taken toward that speech, and by extension toward that sentiment, by the smug asshole in TOA makes me almost fighting mad.


> I've never had someone convince me they understood what it's like to be terminally depressed as completely as the writing of DFW.

Just wanted to repeat that, because it's how I feel as well. It's why I consider his writing to be among the best I've ever read; not because of the hyper-literacy (although that's pretty fun too), but because of the level of insight effectively shared.


All of what you're saying is true, about the speed of real algorithms running on real hardware with real problem sizes.

But if you're talking about big-O, you are explicitly not talking about that. You're talking about how the speed of the algorithm hypothetically scales as some parameter tends to infinity.

To wit, O(n) doesn't mean "this algorithm takes kn time to run for a given n", it means "this algorithm's runtime for all n > c for is bounded above by nk for some c and k".

Sound like a analytic club that's rarely accurate to real-world performance? Yup, that's big-O :)


Right, so I'm asserting that the parameter usually called for in big-O analysis of hash table operations is the wrong one since it measures the lookup complexity and not the hashing complexity, which is usually O(n). And this results in meaningless complexity analysis which gives you things like "Insert is O(1) on Average but O(n) Worst Case or Θ(n)".

This analysis is using the hash table length as the parameter under consideration, but that's silly, because most of the complexity of hash-tables is in the hashing which (depending on the hash function) usually has a known complexity of O(n). Where n is the length of the input string.

This is far more important in hash table complexity analysis than table size because this part of the operation dominates runtime.

You can also do multi-paramter big-O analysis. O(mn) is a thing for example, with two differently sized parameters, both of which contribute to the complexity of the algorithm and can't be dismissed.

So charitably, if you need to provide a big-O for say, hash table inserts, it's reasonable to say O(mn) where m is the length of the table and n is the length of the input string, but it's not necessary since table length usually has little contribution to the complexity of the algorithm...hence why people keep saying inserts are O(1) on average, because table length isn't much of a determinant in hash table operation complexity. Just like big-O hides constants, we can hide parameters that are dominated by another. O(1) is doing this backwards.

My guess is that O(1) is some weird cargo-culted remnant from some early work done on Hash tables as a generalization of Arrays, likely from when the hash functions were just modulus operations on integer keys or some other simple, fixed length hashing method that was easy to ignore (like the universal hash in Corman's "Introduction to Algorithms". But modern hash-tables can't make these assumptions and I, and quite a few other folks, think that this needs to be rethought.

Some examples (I don't agree with all of these, but I think it makes the point):

https://stackoverflow.com/questions/2771368/can-hash-tables-...

http://lemire.me/blog/archives/2009/08/18/do-hash-tables-wor...

> Sound like a analytic club that's rarely accurate to real-world performance? Yup, that's big-O

If your complexity analysis isn't measurable by real-world performance, it's likely that you aren't analyzing the correct parameters.


> And this results in meaningless complexity analysis which gives you things like "Insert is O(1) on Average but O(n) Worst Case or Θ(n)".

I dunno, that just sounds like a time complexity to me. Quick, what's the time complexity of quicksort?

> This analysis is using the hash table length as the parameter under consideration, but that's silly

I think you're just talking about something else, then? Sure, the analysis generally assumes a finite key size, and looks at performance as the table size increases. That's just pragmatism; people generally have a bounded key size and an unbounded amount of data.

If your complaint is that treating the key length as finite results in a complexity of O(1), then... that's the point. Treating the key length as finite results in a complexity of O(1).

Table size isn't much of a determinant. It isn't any of a determinant, on average. Only the key length matters. That conclusion is the whole point of this analysis.

> it's reasonable to say O(mn)

I'm confused if this is what you meant to write-- this is not an accurate complexity for a hash table insert because, as you have pointed out, a hash table insert doesn't depend on the table size. There should be no factor of m. Edit: Er, technically O(n) is in O(mn)? Is that your point? But O(mn) doesn't simplify to O(n) unless m is constant, which I don't think you're saying.

With respect to key size n and table size m, the average complexity should be O(n). If we let key size be finite relative to the size of the table, that gives us O(1). But if you don't like that, you can let key size grow to infinity and you're right back to O(n).

None of this is going to tell you if it's the right data structure to use, though.

> If your complexity analysis isn't measurable by real-world performance, it's likely that you aren't analyzing the correct parameters.

No, in this case you are looking at the correct parameters but using the wrong model. At least, I think; it's still not clear what you're trying to get done here where big-O is letting you down.


On a hash with a million elements, the O(n) hashing of a 10-char key is negligible.

Also, you have to make apples to apples comparisons. In this case, you're comparing the time to search against the number of elements, and that's it. If you want the time to hash AND search - as a function of n - then your analysis holds, but you can't then compare that against other datastructures that do not have an equivalent hash step.


This is mostly an issue with terms. Most (all?) of the operations we call constant-time, say, comparison, are technically logarithmic in the number of bits on real computers.

Since that's usually not relevant to big-O analysis, we can sidestep the issue by specifying what we're counting: rather than say that mergesort is in O((log n) log (log n)) time, we say it takes O(n log n) comparisons.

Whether you think of that as a theoretical computer with a constant-time comparison instruction or as a real computer with a commonsense (2^64) upper bound, the upshot is that we don't care. As long as what we're studying is sorting, not comparison, it will fall out of every algorithm, so the difference isn't important even in theory.

It's still an important thing to notice, though-- there are plenty of cases where you definitely do care about counting bits.

In more detail: http://cs.stackexchange.com/questions/1643/how-can-we-assume...


But those situations aren't the same -- comparison sorts take O(n log n) because it is expressed in terms of n, the number of elements, which is orthogonal to element size. Even if you did account for the max element value V, it would be constant with respect to that value. The full bound would then be n log(V) log n -- regardless of your choice of V, you don't affect the scaling with respect to n.

But for hashtables, what exactly are we studying that doesn't care about hash time? The whole reason that a hashtable is supposed to save time is that you locate the desired key's value by computing the location from the key itself. To whatever extent that computation requires more steps, that cannot itself be abstract away -- if only because a limitation on key size is a limitation on table size.


That example may have misfired-- perhaps consider that sorting an array of n elements requires addressing n elements, which requires arithmetic on words of log n bits, which are therefore log time operations. Limiting the size of each element won't help your complexity.

But we really don't care about that very much. In this case.

It's kind of described in that SO post I linked-- you can assume a constant-time hashing operation, but if that offends your conscience, assume an "integer RAM" model where arithmetic operations up to a certain word size w are constant time. Then you can observe that any reasonable w is inconsequential to your problem domain, and go back to treating hashing as a constant-time operation :)

The idea is that the fact that w increases at least as the log of n is shared by all computations modeled in integer RAM, so it's not a useful contribution to analysis at that scale. It's in the model, it's just not generally useful to the model. If you ever find yourself asking, is the bit width relevant? You can do some math and get a straight answer.

Of course real world algorithms often hash strings which complicates the analysis, but that's orthogonal, like my misstep earlier in implying the size of an element rather than the size of n. The mathematical sense in which hashing time must increase with the log of n is a fact of all algorithms that have ns.

I think your surprise at this just stems from wanting a rigorous definition for something that's more of a modeling tool, with different models to choose from. In real life, there's the time on the wall since you clicked "Run", and everything else is theorygramming.


You can't have it both ways: on the one hand, say that big-O is about arbitrarily large unrealizable values, but on the other hand make a bunch of exceptions for where things don't matter in practice, lest you be theory-gramming.

If you go the route that requires you to handle arbitrarily large tables, then computing a hash with a long enough value necessarily requires more steps, even if you assume all operations on length w integers are constant time -- because eventually your keys have to be larger than w, after which computing the hash increases in number of steps with the key size.

This is still different from the sorting problem. You can have a consistent computation model in which memory seek times are constant (even if unrealizable). That seems fundamentally different from a model where a hash computation is constant steps but also has arbitrarily long output.

The issue isn't whether the scaling of the hash computation matters in practice, but whether the big-O is properly O(1). And even if you did just care about "in practice" limitations, you're stuck with the problem of the hash computation taking longer than any realizable trie lookup would (as another poster mentioned is common), meaning that the O(1) claim misrepresents performance relative to another data structure.


Edit: Ugh, the old version of this post turned out really lectury, and I'm still working on my own intuitive understanding here, so I'm just gonna start over.

Basically-- you're not wrong. It's a quirk of analysis that a hash table is allowed to take the modulo (for example) of an arbitrarily large number, producing an arbitrarily large number, in "constant time", while a trie is not allowed to descend to an arbitrary depth in constant time.

But saying that such a thing is possible is a simplifying assumption that we make, in general, for non-numeric algorithms: arithmetic is O(1).

Of course, real programs cannot do this for arbitrarily large numbers. So if you are actually concerned with arbitrarily large numbers, you must do something else. Thus, other sorts of analysis which would give you a different number for hash table complexity. Yay!

And if you're having difficulty using the reported big-O value under the canonical model to compare algorithms which have very similar amortized performance in the real world, your problem is just that big-O is not for that thing you're doing.


Thanks for taking the time to revise and give a thorough and fair reply.

To give background, my main concern is with the exceptionalism: the defining (good) thing about STEM is that there's actual logic to the discipline, where if I forget an answer, I can re-derive it. It's not just a game of memorization and regurgitation.

But O(1) for hash lookup feels like the old soft-sciency "hey, you just have to memorize this". I don't have one consistent model that lets me derive bounds, and which produces O(1) for hash lookup and O(log n) for trie lookup. The other convention of constant seek times is unrealistic [2], but it's at least consistent. This isn't.

Rather, it's supposed to be a big-O table. If these were presented as "in-practice" bounds, with its own consistent logic about which resources are scarce relative to which, that would be a different story. Then I would have a consistent set of conventions that produce O(1); it wouldn't come off as "oh, we assume the rules don't apply here".

>But saying that such a thing is possible is a simplifying assumption that we make, in general, for non-numeric algorithms: arithmetic is O(1).

Where? Every treatment I've seen takes arithmetic as linear in the number of bits. [1] This is still consistent with O(n log n) for sorts because you can assume a bound on element size, and still only have constant factor overhead.

>Of course, real programs cannot do this for arbitrarily large numbers. So if you are actually concerned with arbitrarily large numbers, you must do something else. Thus, other sorts of analysis which would give you a different number for hash table complexity. Yay!

But (as above), the problem is it's not even clear what sort of problem class we were doing that let's you assume this particular thing can be bounded but others can't.

[1] https://en.wikipedia.org/wiki/Computational_complexity_of_ma...

[2] Pretty sure that in the physical universe, memory seek requires n^(1/3) because you have to cram it into a volume whose size increases with the cube of longest distance between addresses, and travel time is linear in distance.


> Where? Every treatment I've seen takes arithmetic as linear in the number of bits. [1] This is still consistent with O(n log n) for sorts because you can assume a bound on element size, and still only have constant factor overhead.

This is probably the only point of disagreement here. If I understand your critique of the O(1) result, it's that addressing n elements takes arithmetic (hashing) on numbers of log n bits.

ISTM that, assuming an integer RAM model, that same critique must apply to any input. A mere pointer into an array of n elements has log n bits, so just incrementing and testing the pointer can't be O(1), and even iterating that array can't be O(n).

It's still hard for me to see any reason why the one or two arithmetic operations in a for loop can be O(1), while the larger but still constant number used by a hash function can't.


>This is probably the only point of disagreement here. If I understand your critique of the O(1) result, it's that addressing n elements takes arithmetic (hashing) on numbers of log n bits.

It's not the addressing I object to -- this whole domain consistently assumes O(1) seek times. It's the computation of the hash itself. A hash function that, by supposition, minimizes collisions is going to have to avalanche the whole thing such that it has to perform a complex calculation -- not mere lookup -- that incorporates multiple combinations of the elements. The growth in cost is not from doing seeks over bigger ranges but from computation. You can no more assume away that growth than you can assume that md5 is just as expensive than SHA256.

>ISTM that, assuming an integer RAM model, that same critique must apply to any input. A mere pointer into an array of n elements has log n bits, so just incrementing and testing the pointer can't be O(1), and even iterating that array can't be O(n).

I never objected to this before but I've always disagreed: iterating needn't be log(n) because any such procedure can be optimized away to get the next element via either a) a seek, or b) incremeting a value, which is constant amortized (because bit rollover is exponentially rare).


Since we call cases where something that looks polynomial on the surface but actually performs in NP "pseudo-polynomial," does it makes sense to call the cases where something more or less takes constant time "pseudo-logarithmic?"


Well, there are terms linearithmic and quasilinear that already get some usage.

> https://en.wikipedia.org/wiki/Time_complexity#Quasilinear_ti...


Or maybe, since O(1) is in O(log n), you can cover your bases by just calling everything logarithmic regardless :)


Consider applying for YC's Summer 2026 batch! Applications are open till May 4

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

Search:

HN For You