Hacker News new | ask | show | jobs
by arturocamembert 372 days ago
left-pad even being a package is pretty funny, no? How many bytes got pumped across CDNs, proxies, build pipelines, etc. just to write a tiny utility function? I'm all for taking advantage of existing solutions, but I can't wrap my head around needing to pad a string and thinking "oh, I bet there's a package for that"
7 comments

I remember part of the discourse being that this was a much needed wake up call to web-devs for their relentless reliance on micro packages like left-pad. Part of it was the culture of publishing packages for the sake of popularity and github stars. Part of it were also devs insisting that implementing anything that could otherwise be installed through NPM was "reinventing the wheel". Today I work with a lot of devs who still prefer using micro packages, regardless of their simplicity, because to them it means "less maintenance". Go figure.
The package's original implementation[1] also seems like it would have resulted in O(n^2) operation rather than desired O(n).

[1] https://en.wikipedia.org/wiki/Npm_left-pad_incident

I don't see where the quadratic time complexity comes from. There's a single loop performing n operations in total, ie. O(n).
Extending strings is not a linear-time operation. Behind the scenes, the JS runtime allocates new memory for it. In the naive case, you start by allocating 1 byte, then when you append to it, you need 2 bytes. So you allocate a new string of 2 bytes, and copy the data in. Each new byte is a new allocation, and a new copy of the entire string. That's how it's quadratic.

In practice, memory allocators tend to double the size of an allocation like this, which is still quadratic.

In practice, JS runtimes also tend to use data structures like Ropes for strings to handle this sort of issue. That brings it down to linear time in practice (I think?)

In each loop prepending a single character could take O(m) (moving all m characters one to the right) so combined O(nm) where n is the number of padding characters and m is the total number of characters in the string.
Only when the underlying JS implementation does this naively. In reality JS implementations do a lot of optimizations which often can reduce the time complexity.
"The compiler will take care of it", funny, heard that one before, I'd profile it just to be on the safe side...
I didn't mean that. JS doesn't have any lower-level interface for handling memory, so such optimization has to be in the implementation. It should be quite obvious that relying on such optimization can be problematic.
The line `str = ch + str` is itself a linear-time operation, with time proportional to the length of the new string.

That linear-time operation is then additionally repeated `len` times

Really, what's the qualitative difference between reaching for a utility function that someone else already wrote within your project and reaching for a package that someone else already published within your ecosystem? They're obviously not the same thing but are they so far apart that you can't wrap your head around it wanting to treat them the same, given sufficiently advanced tooling?
The utility function just has to fit your use case, and can be easily refactored as it lives in a local context.

The package has to have a public API, meet millions of different people's use cases, and any change to the API will cause millions of man-hours of useless work... and yet if it's a poorly designed API, it might cause millions of sub-optimal programs.

Every project has a StringUtils file. But every project's StringUtils file is different.

Published packages in an ecosystem ought to be well-designed, with good performance, good APIs, good security. Packages that don't meet that bar ought to be kept out. npm is jarring because it let any old shit get published, despite there being long-standing package ecosystems in other languages with much better standards, that they could have copied from (CPAN, PyPi, RubyGems, Maven Central, NuGet Gallery, etc.)

The number of distinct entities in your supply chain and whether those developers are on your payroll.

As a business, each additional human or company you add to your supply chain represents additional risk that you're taking on. You can go some ways towards mitigating those risks—one of the most common is to sign a contract with them rather than doing business ad hoc—but the risk doesn't go away entirely. Given that additional risk for each additional downstream supplier, it's generally safer to use code written by someone who's already on your payroll than it is to use code written by someone you've never met and have no way of vetting.

Isn't it similar with AI now?

How many prompts can already be solved with a simple web query?

C&P but with extra steps

I'm pretty pessimistic about AI in general, but the quality of web query results has gone done so much I've resorted to asking an AI to get the short answer or the starting point that Google would have given me just a few years ago...
maximum code reuse flex, copy-paste is for losers.
The biggest reason for this is reuse between libraries - if you use 10 libraries, you don't want each of them to add its own leftpad. This is especially a problem if this happens in client code and you then send duplicate code to the browser.
Muh Unix way.