[HN Gopher] 4B If Statements
___________________________________________________________________
4B If Statements
Author : r4um
Score : 1132 points
Date : 2023-12-28 06:11 UTC (16 hours ago)
(HTM) web link (andreasjhkarlsson.github.io)
(TXT) w3m dump (andreasjhkarlsson.github.io)
| lmm wrote:
| > Considering the computer has to read 40 GB of data from disk,
| map it to physical memory and then let the CPU has a rip of it
|
| No it doesn't? Maybe it needs to set up page tables for 40GB, but
| it doesn't need to read the parts you're not using into memory,
| that's part of the point of memory-mapping like this - it sets up
| a page fault handler to load the page into memory when accessed,
| rather than needing to do it all up-front.
| DHowett wrote:
| Given that the entire linear chain of comparisons (therefore,
| every instruction) needs to be evaluated for 2^32-1, it would
| indeed need to read and execute the entire 40GB file.
|
| The fact that it does so by faulting in each page before
| instructions in it can be executed doesn't materially avoid
| having to read every byte.
|
| Clearly the author should have checked the larger numbers first
| to prevent this (:
| Centigonal wrote:
| Software development needs to be driven by user needs.
| Clearly the best action in this scenario is to bundle in
| telemetry code that reports back which numbers are used with
| this program, assemble a ranking of the most frequently
| compared numbers in the real world, and use that to order the
| comparisons in v2 of the program.
| satiric wrote:
| Of course the modern "scaleable" solution is to ask ChatGPT
| if the number is even or odd, and then print ChatGPT's
| response.
| constantly wrote:
| Using selenium and chrome webdriver under the hood to do
| so, as well.
| chrismorgan wrote:
| It's worth noting that good compilers can actually do a
| version of this: it's called profile-guided optimisation
| <https://en.wikipedia.org/wiki/Profile-
| guided_optimization>. Not many projects use it, because
| it's generally a bit of a bother (build a special version,
| run your profiling, then build everything all over again),
| but Firefox gets good mileage out of it. My vague
| recollection is a typical sort of speedup of 5%.
| eviks wrote:
| Don't forget to remove the least used 1% of the numbers to
| make it leaner!
| lmm wrote:
| > Given that the entire linear chain of comparisons
| (therefore, every instruction) needs to be evaluated for
| 2^32-1, it would indeed need to read and execute the entire
| 40GB file.
|
| It does, but not step by step the way the part I quoted
| described - the reading from memory can be pipelined with the
| execution. (And it's an ideal access pattern - reading
| linearly once - so it wouldn't surprise me if other
| optimisations kicked in)
| slabity wrote:
| Did you ignore this part that came a bit before that?
|
| > I decided to map the file into the address space instead of
| reading all of it. By doing this, we can just pretend that the
| entire file is already in memory and let the poor OS deal with
| fitting a 40 GB blob into virtual memory.
|
| Why take a vaguely rhetorical statement and then complain it
| contradicts a more concretely accurate statement before it?
| lmm wrote:
| > Did you ignore this part that came a bit before that?
|
| No, just the opposite - I read that and that's exactly why
| I'm saying there was no need to read the whole thing into
| memory before starting to execute it.
|
| > Why take a vaguely rhetorical statement and then complain
| it contradicts a more concretely accurate statement before
| it?
|
| Because it's a contradiction in what they've written?
| rocqua wrote:
| The article doesn't state the entire program has to be read
| into memory before it starts executing. Instead the article
| states that during execution, for the highest inputs, the
| entire program needs to pass through memory for execution
| to finish.
| rocqua wrote:
| For the highest possible input, all of the program needs to be
| read into memory. Just not all of it at the same time.
|
| I guess technically most of the RET instructions are jumped
| over, and so they don't need to be in memory. But that isn't
| how cache-lines (let alone pages) work.
| satiric wrote:
| Surely any solution that claims to be performant would use a
| binary search, rather than looping through every number. Would be
| a little trickier to generate the code though.
|
| Edit: /s of course
| tarruda wrote:
| I wouldn't touch the generated ifs, but would generate a b-tree
| database which maps integers to the address of the generated
| code which has the desired "if" comparison. Then the C program
| starts by querying the b-tree for the address and just assigns
| that to "isEven" pointer.
|
| Hmm... Nevermind. A really smart way to solve this would be to
| store the result of the "isEven" computation directly on the
| b-tree, so the whole problem can be solved with a simple
| database query!
| neilv wrote:
| Make it a microservice in Kubernetes so that it scales.
| jiggawatts wrote:
| I wouldn't be surprised if there isn't at least one thing
| this insane at some FAANG.
|
| "We've got to scale the maths engine cluster to handle the
| load!"
| rplnt wrote:
| I mean, there's this
|
| https://www.npmjs.com/package/is-even
| vegardlarsen wrote:
| The actual implementation of this package is even better.
|
| https://github.com/i-voted-for-trump/is-
| even/blob/master/ind...
| tarruda wrote:
| What is even better is the fact that it has 200k weekly
| downloads. I thought this was supposed to be a troll
| package.
| doikor wrote:
| It is a troll package. Just a successful one.
| whaleofatw2022 wrote:
| Don't fall for the salesman's "it was a joke" play.
|
| Is-thirteen, now THAT is a troll package.
| chupapimunyenyo wrote:
| But why do people use this? Is this a dependency in some
| popular library?
| madarcho wrote:
| Well worth a quick trip to the source to see how it's
| implemented. After all, how would the author get around
| to packaging 4B if statements, like the OP?
| ezconnect wrote:
| He could package it to the size limit and range the
| numbers it could detect. Add a note to download
| particular package if the number is out of range of the
| package and that package is not installed.
| rplnt wrote:
| One package should probably handle range of one million.
| Now it's just 4000 packages to install. You wouldn't even
| notice that in an average js project.
| gorbachev wrote:
| Why stop there. Create an algorithm that distributes the
| calculation of each unique number to a different instance.
| Surely that would scale even better!
| ithkuil wrote:
| Or make an array with 2 billion uint64 entries all containing
| this constant:
|
| 0xC3C033C340C033
|
| Then cast the array as if it was a uint32_t* add the number
| you want to check, cast it again as a function pointer of a
| function returns a int and voila
|
| It should take 16G of space to encode but it should require
| only a single page fault to load from disk.
| uint64_t a[] = { [ 0 .. INT_MAX ] = 0xC3C033C340C033 } ;
| int is_even(uint32_t n) { return ((int
| (*)())((uint32_t *)a + n))(); }
|
| This uses a GCC extension. If you can't use that or if it
| doesn't work you can easily create an ELF object file that
| contains a data section with that number repeated 2 billion
| times.
|
| Explaination:
|
| That magic number is actually two 32-bit numbers juxtaposed:
|
| The first one is 0xC340C033, which encodes the following
| instructions: xor eax, eax ; 33 C0
| inc eax ; 40 ret ; C3
|
| This effectively returns 1 in the eax register (which is
| compatible with the C calling convention)
|
| The second number is similar but it doesn't include the "inc"
| instruction.
|
| When casting as a int array we end up with an array with
| alternating function bodies. At even positions we have
| functions that return 1 (true) and at odd positions it
| returns 0 (false)
|
| The interesting thing is each of those function bodies fit
| into a 32-bit number. A single jump to an arbitrary address
| would require larger array.
|
| Of course, it's silly to do this for even/odd but it can be
| useful to understand how this works.
|
| Go kids, build your own forths!
|
| (Disclaimer: I haven't tried out any of the above and typed
| this on my phone while walking in the woods, so I'd be
| surprised if it actually works without some touches, but the
| gist of the idea should work)
|
| Edit: fixes
| ithkuil wrote:
| .global a .data a: .fill
| 0x7FFFFFFF, 8, 0xC3C033C340C033
| glandium wrote:
| Or make a lookup table with bits. It'd only be 512MB of
| 0xaa or 0x55. (but wouldn't use ifs)
| diegocg wrote:
| Compilers will actually do these kind of tricks, I have seen
| them doing that for switch statements with a large number of
| cases.
| zeroCalories wrote:
| Why search? We know exactly where every number is. Use a jump
| table.
|
| While this example is obviously silly because loading a number
| into a register and performimg some operations on it is going
| to be faster than a cache miss from jumping into a massive
| table, the general technique can absolutely be applied in the
| real world.
| noobermin wrote:
| The thing is jump tables re absolutely used for this kind of
| thing, namely when the function doesn't have an easy closed
| form. It should be noted half of the joke is the fact he uses
| subsequent if statements in order to exhaustively check each
| number rather than a jump table.
| twic wrote:
| No, a binary search will defeat prefetching. A linear scan is
| cache-friendly and will be much faster up to a certain point.
| It's called mechanical sympathy, look it up.
| Hugsun wrote:
| Visionary genius Ross van der Gussom is my new favorite
| mythological creature.
| punnerud wrote:
| Think of Python as a way to script C, and skip most/all
| compiling. If your Python is slow, you are probably doing it
| wrong.
|
| Recommend reading this: https://cerfacs.fr/coop/fortran-vs-
| python
| IshKebab wrote:
| Not all Python is just a front-end to fast C code. That only
| really works with numerical computing of big tensors.
|
| Though I'd still agree - if your Python is slow you're doing
| it wrong - you shouldn't be using Python!
| punnerud wrote:
| If you switch away from Python, you are probably sub
| optimizing
| eru wrote:
| You can also call eg Rust or OCaml code from Python,
| doesn't have to be C.
| IshKebab wrote:
| Of course. When people talk about calling C from Python
| they really mean "a fast language".
| 7734128 wrote:
| I was a teaching assistant in a "data structures and
| algorithms" course where students could choose either Java or
| Python. Most of the labs were the same except that the
| treemap lab had to become a hashmap lab for the Python
| version because it was so excruciatingly slow.
| vitiral wrote:
| If you want to see C's _true_ scripting language, check out
| Lua.
|
| It can be embedded in your C application, unlike Python which
| is the other way around (Lua is like 80KiB, Python is several
| MiB).
| divbzero wrote:
| I ran a web search to figure out if "Ross van der Gussom" was
| some sort of inside joke. The top two search results were OP
| and the parent comment.
| mijoharas wrote:
| I assume a play on Guido van Rossum the creator of python but
| I'm unaware of any meaning deeper than that if that's what
| you're looking for.
| Hugsun wrote:
| It's just a funny misphrasing of his name.
| teaearlgraycold wrote:
| > Now, in a world where AI is replacing programmers by the
| minute, taking their jobs and revolutionizing the way we think
| about code
|
| I'm dumb. This is a joke right? At most I can say AI has
| revolutionized how I interface with documentation.
| ninepoints wrote:
| I would think that the title alone should indicate that this
| entire bit is satire.
| leosanchez wrote:
| > This is a joke right?
|
| I hope so. If not, it is a load of bullshit.
| coldtea wrote:
| That is a joke in the context of the post. Not so much a joke
| in general reality.
|
| For you, AI might have just revolutionized how you "interface
| with documentation", but a huge share of programmers in any
| company are already using AI, officially or unofficially as a
| coding assistant.
|
| And of course MS, IntelliJ and others are all having out
| products on this.
| speedgoose wrote:
| Would you spend a lot of time and money on contractors to do an
| often disappointing job, or ask a LLM to do a better job
| immediately?
| elzbardico wrote:
| GPT is a brilliant interface to github search and stack
| overflow. That's all. Most of the time I use it, like stack
| overflow, you need to double check if it is the idiomatic way
| of doing it, if it IS still the right way of doing stuff or
| even if the code is correct, not full of bugs or even if it is
| solving the right problem.
|
| It is like a helpful, but over-confident intern helping you
| with toil and research.
| midjji wrote:
| % is a surprisingly slow way to do so compared to x & 1.
| Cyph0n wrote:
| I'd assume any decent compiler would optimize a "% 2" (or any
| power of 2) into a bitwise op. Could be wrong though!
| constantly wrote:
| Easy enough to check with even the indecent compilers!
|
| https://godbolt.org/
| roetlich wrote:
| Tested it! In C: https://godbolt.org/z/7xTrhGasc GCC uses &1
| even using -O0. LLVM using -O0 still does the modulo, but at
| -O1 it does a clever &-2.
|
| And even C#: https://godbolt.org/z/5WPfT8e5G Does use the &-2
| strategy.
|
| Dart also uses and: https://godbolt.org/z/1437df4En
|
| So most of languages compiled to native binaries seem to do
| it. Languages like Ruby and Python don't seem to optimize
| this, which is hardly surprising. Ruby has a JIT now, and the
| JIT might do it.
|
| And I'm not sure what the haskell version does, can someone
| explain: https://godbolt.org/z/xPP4E1a6h ?
| tomsmeding wrote:
| If you change the code from "n `mod` n" to "n `mod` 2", and
| add "-O" as a compiler flag, you'll see an "and" with 1 pop
| up in the assembly.
|
| Without -O, what's happening is that "mod" is a method from
| the Integral type class (for the non-haskellers: read
| "interface"/"abstract class"), and thus the program just
| reads the corresponding field from the stafically allocated
| copy of the Integral dictionary for Int, and subsequently
| calls it. Of course one should just inline this known
| function call, and that's precisely what -O lets ghc do.
| roetlich wrote:
| Nice, thanks!
| teo_zero wrote:
| Can someone explain what's the &-2 method, and why it
| should be better than &1 ?
| roetlich wrote:
| In two's complement, -2 means all bit are 1, except for
| the lowest. 1 is all bits are zero, except for the
| lowest. So it's basically the same, just negated. If you
| look at the generated code, this is used to the opposite:
| Keep all bits, except the least significant.
|
| Btw, it's a lot simpler if you use only unsigned ints.
| Both GCC and clang add a couple more instructions to make
| it work with negative numbers. With unsigned ints, both
| gcc and clang generate this simple assembly code:
| is_even: mov eax, edi and
| eax, 1 ret
| Joker_vD wrote:
| And those additional instructions are there only because
| C modulo is defined to have the same sign as the dividend
| (so that e.g. -5 % 2 == -1 instead of 1). Had it been
| defined as being always positive, &1 would have been
| sufficient in all cases (that would also have the effect
| of making integer division round to negative infinity
| instead of zero which too can be implemented simply by
| >>1, for both signed and unsigned numbers).
| teo_zero wrote:
| Thank you, today I've learned something new.
|
| So the easiest answer to the original question (whether a
| number is even or odd) likely involves &1, not %2. Note
| taken.
| neonsunset wrote:
| Why "even C#"? Nowadays we often can trade blows with LLVM
| and GCC :)
| IAmLiterallyAB wrote:
| But that probably isn't the function you want, because that
| will return -1 if the input is negative.
|
| What you want to return is a boolean. And in that case the
| code generated is much simpler
| https://godbolt.org/z/5dq7MnrEx
| Cyph0n wrote:
| Thanks for trying this out! It's the same with Rust:
| https://godbolt.org/z/89z9rEz9a
| makapuf wrote:
| I once saw that the only thing writing &1 instead of %2 does
| is making your computer yawn
| kaetemi wrote:
| Lmao. The copyright headers.
| gitgud wrote:
| Didn't notice that, incredible
|
| > _Copyright 2023. All unauthorized distribution of this source
| code will be persecuted to the fullest extent of the law_
| Der_Einzige wrote:
| I was hoping that this would be about someone finally building an
| LLM out of a decision tree or decision tree derived technique
| (which ultimately boils down to nested if statements). Not sure
| why no one has tried it yet.
| OscarCunningham wrote:
| My understanding is that they are using increasingly small
| precision on the floats used by LLMs. So we just have to wait
| for them to reach 1-bit precision.
| matrix2596 wrote:
| its funny but the large language models can be seen as billions
| of if statements learnt from data
| iopq wrote:
| Not really, since they do a mathematical function over blocks
| and don't need a single if statement. They map learned data +
| input -> output as a pure function
| ryanlbrown wrote:
| ReLU is if-like since it only passes half of the input values
| with the other half becoming 0
| LargeTomato wrote:
| Is ML different than if statements? Yes.
|
| But is it reallllly different? No not so much.
| Joker_vD wrote:
| If your programming language of choice has no arrays (like most
| of the languages implemented in one of the many, many, many "How
| to write your own interpreter/simple compiler" tutorials out
| there) but supports variables, then you can use this technique to
| kinda implement them anyway, Okasaki-style: var
| arr0, arr1, arr2, arr3, arr4, ..., arr65535 : int;
| func get_arr(index: int): int { if index < 0 or index
| > 65535 { exit(); } if index < 32768 {
| if index < 16384 { if index < 8192 {
| ... if index < 2 {
| if index < 1 { return arr0;
| } else { return arr1;
| } } else {
| if index < 3 { return arr2;
| } else { return arr3;
| } } ...
| } else { ...
| } } else { ...
| } } else { ... }
| } proc set_arr(index: int, value: int) {
| if index < 0 or index > 65535 { exit(); } if index <
| 32768 { if index < 16384 { if
| index < 8192 { ...
| if index < 2 { if index < 1 {
| arr0 = value; } else {
| arr1 = value; }
| } else { if index < 3 {
| arr2 = value; } else {
| arr3 = value; }
| } ... }
| else { ... }
| } else { ... } }
| else { ... } }
|
| It even has O(log n) access time which is actually the same
| complexity as accessing a RAM by a pointer anyway! Just replicate
| this code for any array variable you need to simulate and pre-
| allocate enough of the memory, it's totally free with that .bss
| trick anyhow.
|
| So technically, languages without arrays are about as Turing-
| complete as those with limited-size pointers/array indices
| (funnily enough Brainfuck -- where the pointer is invisible to
| the progammer -- _actually_ is Turing-complete).
| anvuong wrote:
| That's because array, or even if/else statements are already
| higher-level abstraction. To be Turing complete you simply
| need: a memory that can be read from or written to, and the
| ability to "jump" or "move" to some memory location.
|
| Turing complete may sound big, but almost anything that can
| compute is Turing complete.
| Joker_vD wrote:
| You also need an unbounded storage. Technically, if you have
| unlimited-width integers then two variables is all you need,
| but most languages have limited-width integers which makes
| them finite-state automata.
| baq wrote:
| Technically all computers in our universe aren't, but we
| don't make a fuss about it. In theory they aren't complete,
| but in practice they are. Wonder if there's a theorem which
| links the maths with physics in an intuitive way.
| Thermodynamics sort of do, but entropy isn't that
| intuitive?
| Joker_vD wrote:
| You can have e.g. Python (lists and bignums)
| implementation that would acquire more and more storage
| as needed: first from the RAM, then from disk, then doing
| fancy cloud Memory-as-a-Service requests, then
| commissioning building more datacenters, then branching
| out to the other planets etc. until it runs into the
| finiteness of the universe, all the while providing the
| abstraction of lists and numbers that can grow without
| hard limit (although with growing access latency). The
| _practical_ limit is determined entirely by the things
| extraneous to the computation model itself.
|
| On the other hand, if you have e.g. C, then your program
| is _in principle_ can not have an array with indices
| larger than SIZE_MAX, period -- which is guaranteed to be
| a finite number. This limit is built into the C abstract
| machine. Trying to weasel out of it by using FILE I /O is
| hindered by the fact that ftell() has to return accurate
| results that must fit into long (now, if ftell() were
| unavailable, or were allowed to fail for large enough
| offsets, then fseek()/read()/write() could actually be
| used in an obvious way for simulating a tape without a
| hard limit on its size). So this computation model, while
| _practically_ Turing-complete, is not _theoretically_
| Turing-complete.
|
| So, my original point was that built-in support for
| arrays, while providing ergonomics and performance, does
| not really extend the computational capabilities of the
| language: the languages with finite-sized integers but
| without arrays can simulate finite-sized arrays just like
| so. And if your integers are unbounded then you can use
| e.g. Godel numbering to simulate unbounded arrays (again,
| with loss in ergonomics and performance).
| btdmaster wrote:
| Why two variables? Can't you always encode two arbitrary-
| width integers into one arbitrary-width integer?
|
| For example, using 0b0001 as a split character, to end up
| with the pseudocode left, right = memory.split('0001') and
| then encoding everything else without using any 0b0001
| pattern. It might be awfully complicated, but you can
| always use a fixed but arbitrarily large part of this
| arbitrary length integer as scratch space to implement this
| encoding.
|
| Edit: for an easier time, put one integer in all the even-
| indexed parts of the binary number, and the other in all
| the odd-indexed parts of the number.
| extheat wrote:
| Why would normal memory access be O(log n)? Seems to me jumping
| to a random address should be an O(1) operation. Would be
| pretty dumb if jumping to higher RAM addresses takes longer
| than jumping to lower RAM, excluding hardware things like
| different RAM sticks or page files.
| Jaxan wrote:
| > excluding hardware things like different RAM sticks or page
| files.
|
| Exactly this! Also as n grows you will need bigger address
| busses (or have serial communication).
| Athas wrote:
| It depends on your definitions and assumptions. Here 'n' is
| not the address, but the size of memory (or the largest
| possible/worst-case address). In the universe we inhabit, due
| to limitations on information density in a given volume[1],
| the worst-case random access time for a memory of size 'n'
| would be the cube root of 'n', because you need to transmit a
| signal at the speed of light between to points inside a
| sphere.
|
| Real computers tend not to be able to store their information
| in all three dimensions (I think I once saw an argument for
| why this is also theoretically not feasible), and in practice
| appear to have worst-case access times that are logarithmic.
| It's fundamentally for the same reason: the bigger your
| memory, the more distant will be the most remote (worst-case)
| part of it.
|
| Of course, in a single _specific_ desktop or server computer,
| changing the capacity of your RAM sticks will likely not
| affect worst case access speeds, because the speed limit is
| likely based on the _maximum capacity_ of the machine (a
| constant). So this kind of analysis is useful for pondering
| the ultimate limits of worst case memory accesses (and does
| also have some relevance huge computers), but in practice you
| will of course find that cache /locality effects are far more
| important for performance on real computers.
|
| [1]: Since information is energy and therefore mass, a
| sufficiently dense store of information would collapse into a
| singularity, and you better hope your pointer doesn't point
| into one of those.
| btdmaster wrote:
| There was an article that mentioned that cbrt(n) is worst-
| case array access, not constant time. They did some
| benchmarks across the CPU cache/RAM/SSD boundary to show
| this practically. I can't seem to find it though, where was
| it?
|
| Edit: found it,
| https://www.ilikebigbits.com/2014_04_21_myth_of_ram_1.html
| cushpush wrote:
| Fantastic use of meta-programming, and I like the benchmarking at
| the end, you have clarified much for the beginner and expert
| alike.
| adastra22 wrote:
| I enjoyed this more than I should have.
| charcircuit wrote:
| Here is a version with 0 if statements #include
| <stdio.h> #include <stdlib.h> int main(int argc,
| char** argv) { return printf(atoi(argv[1]) & 1 ?
| "odd" : "even") < 0; }
| brokensegue wrote:
| Still branches
| chrismorgan wrote:
| #include <stdio.h> #include <stdlib.h> int
| main(int argc, char** argv) { return
| printf(&"even\0odd"[(atoi(argv[1]) & 1) * 5]) < 0; }
| charcircuit wrote:
| Not always. Popular architectures like x86_64 and ARM have
| instructions for conditional moves. These instructions do not
| cause the processor to branch.
| winwang wrote:
| I'm surprised no one has chimed in on how the program is
| "processing" 40GB of instructions with only 800 MB/s * 10s of
| disk read.
|
| If I had to hazard a guess, there's some kind of smart caching
| going on at the OS level, but that would entail the benchmark of
| "n close to 2^32" not being run correctly.
|
| ...Or that the CPU is smart enough to jump millions of
| instructions ahead.
| treffer wrote:
| > my beefy gaming rig with a whopping 31.8 GB of memory
|
| So a rerun of the program should only need to load ~8GB if the
| filesystem caching is somewhat loop/scan resistant.
|
| My first thought was "probably the math is wrong", but looks
| like it adds up to something reasonable - especially as all
| numbers are rather vague / rounded (e.g. let it be 12s) and the
| number was just high, not absolute maximum.
| jeffreygoesto wrote:
| It mmaps the program, unused pages then only take a page table
| entry and are not loaded. The only page actually loaded is the
| one he directly jumps into. Neat trick.
| Liquid_Fire wrote:
| It's not jumping directly, it's executing sequentially,
| comparing against each consecutive number in sequence.
| jeffreygoesto wrote:
| You are right, my bad. Thanks for clarifying it.
| drewtato wrote:
| My guess is either compression or stuff lingering in RAM. The
| CPU can't be smart here since it doesn't know what any of the
| future ifs will be. It doesn't know they're in order, or
| unique, or even valid instructions. You could (theoretically;
| the OS probably wouldn't let you) replace an if with an
| infinite loop while the program is running.
| rocqua wrote:
| Could it be the branch predictor of the CPU somehow catching
| on to this? Perhaps something like 'the branch for input x is
| somewhere around base+10X.
| dist1ll wrote:
| > Perhaps something like 'the branch for input x is
| somewhere around base+10X.
|
| That's unlikely. Branch predictors are essentially hash
| tables that track statistics per branch. Since every branch
| is unique and only evaluated once, there's no chance for
| the BP to learn a sophisticated pattern. One thing that
| could be happening here is BP aliasing. Essentially all
| slots of the branch predictor are filled with entries
| saying "not taken".
|
| So it's likely the BP tells the speculative execution
| engine "never take a branch", and we're jumping as fast as
| possible to the end of the code. The hardware prefetcher
| can catch on to the streaming loads, which helps mask load
| latency. Per-core bandwidth usually bottlenecks around
| 6-20GB/s, depending on if it's a server/desktop system,
| DRAM latency, and microarchitecture (because that usually
| determines the degree of memory parallelism). So assuming
| most of the file is in the kernel's page cache, those
| numbers check out.
| umanwizard wrote:
| I doubt it, branch predictors just predict where one
| instruction branches to, not the result of executing many
| branches in a row.
|
| Even if they could, it wouldn't matter, as branch
| prediction just lets you start speculatively executing the
| right instruction sooner. The branches need to be fully
| resolved before the following instructions can actually be
| retired. (All instructions on x86 are retired in order).
| toxik wrote:
| It can't be the CPU since it is actually memory-mapped code,
| and the branch predictor surely cannot cause page faults and so
| cannot page in the next page of code.
|
| Truly curious. I guess the linear access pattern helps but 800
| MiB/s?
| dist1ll wrote:
| Very likely the majority of the file is paged in, and can be
| prefetched just fine. The author doesn't clear/disable the
| page cache.
| rzzzt wrote:
| There's also anticipatory paging, the OS can guess which pages
| will be requested the next time around.
| bob1029 wrote:
| I assume modern branch predictors are capable of picking up a
| trivial pattern like this.
| raegis wrote:
| This is one of the most entertaining articles I've ever read
| here. He should put the source code online so ChatGPT can "learn"
| from it.
| hoherd wrote:
| That would definitely violate his strict license:
| /* Copyright 2023. All unauthorized distribution of this source
| code will be persecuted to the fullest extent of
| the law*/
|
| And with such elegant code, who can blame him?
| kparaju wrote:
| OpenAI see.
|
| OpenAI ignore.
|
| OpenAI train.
| prossercj wrote:
| To what extent does the law allow persecution?
| Patient0 wrote:
| I feel like the whole article is an allegory of LLM development
| (as a critic would write it: devoting a stupendous amount of
| resources and 'training data' to 'memorize' the solution). I
| wonder if this was the author's intent?
| Semaphor wrote:
| Considering I expected it to be about LLMs from the title (I
| thought it would be an announcement of a new 4B model), I'm
| going with "probably" ;)
| idonotknowwhy wrote:
| Glad I'm not the only one who thought that lol
| jgilias wrote:
| Reading the headline I totally expected it to be about LLMs.
| oefrha wrote:
| This approach is perfect for the is-even npm package[1], with
| 196,023 weekly downloads, or the is-odd npm package[2], with
| 285,501 weekly downloads. Wouldn't it be cool if you type `npm
| install` and it starts downloading a 40GB is-even and a 40GB is-
| odd?
|
| [1] https://www.npmjs.com/package/is-even
|
| [2] https://www.npmjs.com/package/is-odd
| chrisandchris wrote:
| The funniest (or best part) about those two packages is that
| is-even has a dependency to is-odd and does just negate the
| output of is-odd.
| jl6 wrote:
| It's true, the great thing about clean, reusable, modular
| code like this is that you can compose both of these packages
| to make a is-even-or-odd package.
| lvncelot wrote:
| Well first you need to obviously build an OR package, part
| of your suite of logical operator packages, all depending
| on your battle-tested, high performance XOR package.
| wiseowise wrote:
| Groundbreaking!
| kparaju wrote:
| You joke... but https://www.npmjs.com/package/is-odd-or-
| even
| layer8 wrote:
| If would be even funnier if is-odd would simultaneously do
| the same thing in reverse.
| chrismorgan wrote:
| Actually it's not good enough there because JavaScript numbers
| are f64 rather than u32. Even if you only support the safe
| integer range (beyond which the answers become somewhat
| meaningless), that's 254, more than four million times as large
| as 232. Not sure how big the machine code would be, but I'm
| guessing it'll just add 4 bytes (40%) to each case, so you're
| up to something like 224 exibytes. And that's when you're being
| _lazy_ and skipping the last ten bits' worth. If you want to do
| it _properly_ , multiply by another thousand. Or maybe a little
| less, I haven't thought too deeply about NaN patterns. Or maybe
| just infinite if it supports bigints.
| deepsun wrote:
| But we can probably compress the data very well (e.g. "double
| delta" is always zero), and then decompress only needed
| parts.
| vineyardmike wrote:
| This still requires reading through it all in memory at run
| time. Maybe we can optimize it with a JIT -what if the
| package called the ChatGPT api to get the the python code
| that generates the machine code just for the number
| queried?
| Someone wrote:
| But you can create a self-modifying function that, 'for
| speed', adds each case when it is called.
|
| The initial function should start with checking for special
| cases NaN, infinities, 0 and -0, then do (may not be valid
| JavaScript) if((x++ === x) && (x--- === x))
| printf("even\n");
|
| to handle cases over 2^54 or below -2^54, then do
| isOdd = true neg = x pos = x while(true) {
| if(neg++ === 0) break; if(pos-- === 0) break;
| isOdd = !isOdd }
|
| to determine whether x is odd or even in isOdd. Doing the
| self-modification is left as an exercise.
|
| This is good defensive programming. It avoids doing a tricky
| division by 2.0 that might be buggy (I don't think
| https://en.wikipedia.org/wiki/Pentium_FDIV_bug was affected,
| but who knows what other FPUs do?)
| lvncelot wrote:
| It's always worth mentioning that those packages stem from the
| effort of one dedicated npm spammer[1] to weasel his way into
| as many node_modules directories as possible. There's also
| packages for ansi-colors (no, not one package for all colors,
| one package for _each_ color) and god knows what else. These
| then get jammed into any cli tool or other half-way sensible
| looking package, all referencing each other obviously - and any
| "real" project is just a single innocuous dependency away from
| having dozens of jonschlinkert packages.
|
| [1] https://www.npmjs.com/~jonschlinkert
| jevoten wrote:
| Achieving supply-chain security by controlling every link in
| the chain. This Jon is very noble.
| jbverschoor wrote:
| Packages should specify their entitlements.. network
| access, file access, executing system calls, being able to
| monkey patch things, accessing packages outside their own.
| vorticalbox wrote:
| Deno has a few of these by default an application has no
| access to the filesystem, env or network.
|
| You can allow only reading or only writing for files and
| you can also define what domains are allowed.
| jbverschoor wrote:
| Sure it's a huge step forward. But that's on an
| application level, which honestly I can do with sandbox-
| exec on macOS (see below).
|
| In Deno, all permissions would still propagate down to
| the dependencies. (version 1) (deny
| default) (allow file-read* (subpath
| "~/Downloads") ) (allow network-outbound
| (remote tcp "localhost:80") )
|
| or (version 1) (allow default)
| (deny network*)
|
| or # start an airgapped shell, and play
| around in there.. sandbox-exec -p "(version
| 1)(allow default)(deny network*)" bash
| smolder wrote:
| Realistically I think they long ago should have been banned
| from npm, with all submissions deleted.
| fmx wrote:
| When I first heard of the is-odd and is-even NPM packages I
| was sure they were a joke, yet there we are: 200K weekly
| downloads! _Publishing_ the packages may have been the effort
| of one spammer, but many developers obviously chose to _use_
| them - that 's the part that boggles my mind.
| lvncelot wrote:
| Well, look at one of the dependents:
| https://www.npmjs.com/package/handlebars-helpers -
| certainly a more useful npm package, but by the same
| author. Seldom do people actually type `npm install is-
| even` - there's just a jungle of transitive dependencies
| that can be traced back to one of jonschlinkert's many
| packages, which then circles back to something inane as
| `is-even` or `ansi-red`.
|
| I once ran a simple grep in some of my node projects - most
| of them had a jonschlinkert package in node_modules,
| certainly not through any (direct) choice of my own.
| spacechild1 wrote:
| Check out this very useful utility:
| https://github.com/mitsuhiko/is-jonschlinkert :)
| bryancoxwell wrote:
| I love the release notes:
|
| > It exists.
| password4321 wrote:
| Possibly related: https://github.com/SukkaW/nolyfill vs.
| ljharb and nodejs 4
| runarberg wrote:
| I recently came across this issue
| (https://github.com/import-js/eslint-plugin-
| import/issues/213... and https://github.com/import-
| js/eslint-plugin-import/issues/181...) and man that
| person has really found him self a hill.
|
| What is a bit worrying though is that he is an active
| member and contributor to TC-39. Meaning that this kind
| of community hostility is very much alive among the
| people who rule JavaScript.
| Ataraxic wrote:
| View their obstinance: https://github.com/nvm-
| sh/nvm/issues/794
|
| 8 years later and despite much support for the `.node-
| version` file.
|
| Someone else started using the .node-version file years
| ago, and because all open source packages won't form a
| committee to standardize this file, nvm will not support
| it.
|
| They have a lot of hills. JS Private Properties was
| another.
| wk_end wrote:
| Very often when I'm digging around GitHub Issues because
| of some bug or quirk or insanity in the JS ecosystem
| (which is often) I see someone spout the worst possible
| take - often being kind of a jerk about it - and when I
| look to see who's responsible, very very often, ljharb's
| name pops up. Often.
|
| Dogpiling on someone deep in an HN comments tree isn't
| exactly the classiest thing but...never having interacted
| with him myself, I've been harbouring this low-grade
| antipathy towards him - nothing unhealthy, just a groan
| whenever I see his name on GH - for years now, and it's
| cathartic and almost gratifying, given his prominence in
| the community, to feel seen like this. Thank you.
| runarberg wrote:
| I was doing some snooping around and found this earlier
| discussion https://news.ycombinator.com/item?id=37602923
| from September 2023 (234 points, 110 comments), which I
| had missed at the time, very related to this current
| subthread, and includes posts such as these
| (https://news.ycombinator.com/item?id=37604635).
|
| I think we as a community really need to have a
| conversation about ljharb and his role in the future of
| our industry. If he was only a library maintainer, that
| would be one thing, we could just move on, find
| workarounds, alternatives, etc. But his involvement in
| TC-39 makes him one of our rulers in a non-democratic
| structure. That makes this different.
| fmx wrote:
| I see, thanks. I guess that answers one question, but
| raises another: why have his packages depend on more of
| his packages? If his goal was to be included in as many
| node_modules directories as possible, and handlebars-
| helpers was already included what's the point of pulling
| in is-odd/is-even, too?
| ncruces wrote:
| Makes is-odd/is-even popular; many downloads; raises
| their (and his) profile.
| peteradio wrote:
| He could sell rights to the repos and disavow any
| knowledge of its maintenance while maintaining the link
| in his own repos. When those sold rights are used to
| commit some crime he has plausible deniability as anyone
| else but got a payday. If you try spinning off the
| subpackage just prior to a sale then it shows some sort
| of intent.
| umanwizard wrote:
| Is there any evidence that he has ever done anything like
| this, or that he plans to? Or is this just pure
| speculation?
| peteradio wrote:
| I didn't declare he's done this only that it is a
| vulnerability of depending on those packages.
| plufz wrote:
| Might be this from his GitHub bio "Several years ago,
| just before my 40th birthday, I switched careers from
| sales, marketing and consulting to learn how to program"
| Good way to get more eyeballs...
| fmx wrote:
| Ah yes, that actually explains a lot! Thanks.
| tshaddox wrote:
| Here we are all talking about him now!
| Levitz wrote:
| Would it be considered bad practice or in poor taste to
| make pull requests in projects with the sole objective of
| implementing is-even natively?
|
| Thinking of being the change I want to see in the world.
| verandaguy wrote:
| It's probably contextual but I'd say it's in poor taste
| to use them in the first place. Removing them is a net
| benefit imo.
| divbzero wrote:
| I did learn one new thing from browsing the is-odd source
| code: _Number.isSafeInteger(n)_ checks that _n_ falls
| within the [ _Number.MIN_SAFE_INTEGER_ ,
| _Number.MAX_SAFE_INTEGER_ ] interval. ...
| if (!Number.isSafeInteger(n)) { throw new
| Error('value exceeds maximum safe integer'); }
| ...
| brainzap wrote:
| the bigger joke is that programming language have no built
| in
| fifilura wrote:
| Huh? Did you miss the modulo operator?
| kristopolous wrote:
| It wouldn't have 200k downloads a week unless there was a
| large number of programmers who didn't know how to do it.
|
| I mean we're talking FizzBuzz secret sauce here. This
| must be total black magic for a catastrophic percentage
| of programmers
| RugnirViking wrote:
| A more catastrophic number of programmers a) dont know
| how dependencies work and b) think everyone else are
| idiots.
| kristopolous wrote:
| Perhaps, I solidly understand how dependencies work and
| in this case my observation is defensible
|
| Someone made the decision to use that and someone thought
| using stuff made by a person's who makes those kinds of
| decisions was a good idea and so on.
|
| You can git blame dependencies all the way down and
| research the parties involved. I've done it, built tools
| for it even.
|
| A stack of people who make bad decisions doesn't make
| good software.
| arzig wrote:
| I have not read the source but I had always assumed that
| this was the lovingly crafted effort of someone who is
| intimately familiar with the js standard making sure that
| some hypothetical expression like ![1] is neither odd nor
| even. Surely the idea that modulo is beyond developers is
| too horrifying to contemplate.
| fifilura wrote:
| Sad but true. For JavaScript these kind of functions can
| actually be useful because of all the quirks. If that was
| the GPs hint then I can understand.
| umanwizard wrote:
| Here you go: /*! * is-odd
| <https://github.com/jonschlinkert/is-odd> *
| * Copyright (c) 2015-2017, Jon Schlinkert. *
| Released under the MIT License. */
| 'use strict'; const isNumber =
| require('is-number'); module.exports =
| function isOdd(value) { const n =
| Math.abs(value); if (!isNumber(n)) {
| throw new TypeError('expected a number'); }
| if (!Number.isInteger(n)) { throw new
| Error('expected an integer'); } if
| (!Number.isSafeInteger(n)) { throw new
| Error('value exceeds maximum safe integer'); }
| return (n % 2) === 1; };
|
| It does some checking the `value` is an integer in the
| safe range, which doesn't even seem right to me. Why
| shouldn't you be able to call this on integers outside
| the save range?
| addaon wrote:
| All non-safe integers are even, yes?
| johnfn wrote:
| (10e15 + 1) % 2 === 0
| SkyBelow wrote:
| Given the lack of integers and my hesitancy to trust
| modulo for non-integer variables, I don't know if I would
| trust it. You would need to add some safety checks, but
| either you create an is_even/is_odd function that has
| safety checks, or you have to rely on developers adding
| in the checks anytime the number might have been in close
| proximity to a floating point number.
|
| Something as simple as this can end up being neither even
| or odd. (0.1 + 0.2) * 10
| charlieyu1 wrote:
| It is not just modulo, it also test for whether the input
| is a number or integer. It also has one dependency, is-
| number. And isOdd("3") returns true.
|
| Basically it helps dealing with all the typing problems
| of Javascript, and also fitting into functional
| programming paradigms.
| ownlife wrote:
| If you need to know if a number is even or odd then you
| should convert it to an int natively anyway.
| paulddraper wrote:
| Often the is-even package will be imported by another (less
| ridiculous) package of the same author.
| MyFirstSass wrote:
| Seriously fuck this dude leeching on the open source
| community.
|
| He's not even a technical guy but has a background i
| marketing and is directly trolling various Github issues :
|
| https://news.ycombinator.com/item?id=28661094
|
| I've always wondered why node-modules and npm required such
| an insane amount packages so quickly, and now i know why,
| people like him that use their 10.000 ridiculous packages to
| boost their career or do whatever self serving community
| destroying thing they can think off that day.
|
| There really should be a way to ban people doing this shit.
| yreg wrote:
| The author hasn't forced you to import their package.
| What's there to ban apart from maybe polluting the common
| namespace?
| posix86 wrote:
| It's more a statement about the community than him imo. Or
| maybe about what npm allows to be published. Nobody forced
| you to use is-odd, yet it's downloaded 200k a week, why?
| Because js' developer community doesn't know any better
| geodel wrote:
| Exactly right. Its clever way of deflecting blame that
| whole community should share by piling on this particular
| person.
| ycombobreaker wrote:
| This really sounds like victim-blaming. The community is
| vulnerable to somebody publishing asinine modules, which
| should be addressed. However, this individual is still
| the perpetrator.
| kardos wrote:
| A lot or these downloads may be CI systems running
| automatic tests.
| darkwater wrote:
| They clearly are, but this still means a not negligible
| amount of softwares have those packages in their
| dependencies.
| sam_bristow wrote:
| Maybe someone needs to do a website in the same spirit of
| https://youmightnotneedjquery.com except
| youmightnotneedjonschlinkert.
| bee_rider wrote:
| I mostly write in languages without package managers so it
| is possible that my expectations are just wrong, but is
| there no way of showing your dependency graph when using
| npm?
| christophilus wrote:
| Here are some popular ones. Now, in two of these cases,
| they can be dev-dependencies, but even there, it makes me
| angry, since all of those deps have to be downloaded to
| my machine, and can run any random code they want at
| _install_ time (which is why Node projects should always
| be run in some kind of sandbox).
|
| https://npm.anvaka.com/#/view/2d/jest
|
| https://npm.anvaka.com/#/view/2d/tailwind
|
| https://npm.anvaka.com/#/view/2d/aws-sdk
| throwitaway1123 wrote:
| > can run any random code they want at install time
| (which is why Node projects should always be run in some
| kind of sandbox).
|
| You can install with the --ignore-scripts flag. Or set
| the option globally in your npm config file.
| umanwizard wrote:
| Isn't the post you linked to about a different person?
| paulddraper wrote:
| > There really should be a way to ban people doing this
| shit.
|
| ???
|
| There is. It's called "doing nothing."
|
| It takes work to add a dependency to your project; they
| don't spring out of nothing.
| AussieWog93 wrote:
| This is the first time I'm hearing about this guy, but not
| sure why there's so much hate.
|
| It looks like he came from a non-technical background, and is
| trying to make the language more noob friendly.
|
| Compare the pair:
|
| if isEven(n) { }
|
| if (n % 2) == 0 { }
|
| I guarantee you my wife would have no idea what the second
| snippet even means.
| numpad0 wrote:
| if !(n & 1) {} // rightmost bit(LSB) is always `true` for
| odd integers
| extrememacaroni wrote:
| AussieWog93 should marry this guy instead.
| btdmaster wrote:
| For code golf purposes, ~n&1 works fine
| cperciva wrote:
| // FIXME: This breaks on negative numbers on ones-
| complement machines
| MrJohz wrote:
| There's an argument to be made for writing functions like
| `isEven` and using them instead of n%2. There's an argument
| that the JS standard library, or other comprehensive util
| libraries like Lodash or Underscore should include these
| functions.
|
| The problem here is introducing separate dependencies for
| each of these tiny functions. Dependencies are code that
| you haven't written, but are still your responsibility. For
| a lot of things, that's a good tradeoff: if you don't have
| the expertise in a specific area, or if you can offload
| work to a dependency that you trust, that's great. But for
| micro dependencies like this, it's usually a bad deal - you
| don't get anything in return (seriously, how hard is it to
| write your own isEven function?) but you have to rely on a
| third party to be secure, to not push anything accidentally
| broken, to not change the API, etc.
|
| (I think it's also worth pointing out that your wife is not
| a paid programmer. Software development should be
| accessible, but this isn't the only goal, and I think it's
| reasonable to assume that most programmers either
| understand the n%2 idiom, or know enough to be able to find
| help on the subject.)
| buttercraft wrote:
| The hate is deserved. This person lacks ethics.
| umanwizard wrote:
| It seems very uncharitable to describe someone as a "spammer"
| because their philosophy on the proper size of units of code
| reuse is different from yours.
| Y_Y wrote:
| It seems overly charitable to me to frame the dispute in
| those terms. You and I might differ as to the appropriate
| amount of vermouth in a martini or pineapple on a pizza and
| I won't worry much about it, within reason.
|
| There's a limit though! I think up to about 10% pineapple
| by weight is reasonable for a Hawaiian, if you choose 0 or
| 20% then we'll have no issue. If you went to 30% I don't
| think I could stop myself writing a libellous remark on hn.
| Anything about 50% and I would be morally forced to
| denounce you to the proper authorities. About 80% is where
| the nightmares begin.
| hex4def6 wrote:
| At a certain point, isn't it just grilled pineapple with
| pizza crumbs?
| pc86 wrote:
| Even if you think having a _dependency_ load `is_even()` is
| a good thing, surely you can see how it 's pretty hard to
| defend having a completely separate and nearly identical
| `is_odd()` rather than just `!is_even()`
| tentacleuno wrote:
| > It seems very uncharitable to describe someone as a
| "spammer" because their philosophy on the proper size of
| units of code reuse is different from yours.
|
| https://github.com/jonschlinkert/ansi-reset
|
| https://github.com/jonschlinkert/ansi-bold
|
| https://github.com/jonschlinkert/ansi-dim
|
| https://github.com/jonschlinkert/ansi-italic
|
| https://github.com/jonschlinkert/ansi-underline
|
| https://github.com/jonschlinkert/ansi-inverse
|
| https://github.com/jonschlinkert/ansi-hidden
|
| https://github.com/jonschlinkert/ansi-strikethrough
|
| https://github.com/jonschlinkert/ansi-black
|
| https://github.com/jonschlinkert/ansi-red
|
| https://github.com/jonschlinkert/ansi-green
|
| https://github.com/jonschlinkert/ansi-yellow
|
| https://github.com/jonschlinkert/ansi-blue
|
| https://github.com/jonschlinkert/ansi-magenta
|
| https://github.com/jonschlinkert/ansi-cyan
|
| https://github.com/jonschlinkert/ansi-white
|
| https://github.com/jonschlinkert/ansi-gray
|
| https://github.com/jonschlinkert/ansi-grey
|
| https://github.com/jonschlinkert/ansi-bgblack
|
| https://github.com/jonschlinkert/ansi-bgred
|
| https://github.com/jonschlinkert/ansi-bggreen
|
| https://github.com/jonschlinkert/ansi-bgyellow
|
| https://github.com/jonschlinkert/ansi-bgblue
|
| https://github.com/jonschlinkert/ansi-bgmagenta
|
| https://github.com/jonschlinkert/ansi-bgcyan
|
| https://github.com/jonschlinkert/ansi-bgwhite
| shp0ngle wrote:
| You may not like it, but this is what 10x performance looks
| like
| joenot443 wrote:
| > Several years ago, just before my 40th birthday, I switched
| careers from sales, marketing and consulting to learn how to
| program, with the goal of making the world a better place
| through code [1]
|
| It checks out, sales/consulting folks are pretty infamous for
| their tendency to abuse metrics. The metric here is npm
| downloads and Github stars.
|
| The strategy does mean that he's _technically_ not inaccurate
| in claiming this on his LinkedIn -
|
| > NASA, Microsoft, Google, AMEX, Target, IBM, Apple,
| Facebook, Airbus, Mercedes, Salesforce, and hundreds of
| thousands of other organizations depend on code I wrote to
| power their developer tools and consumer applications.
|
| I encountered this type a lot in college consulting groups,
| it's a little funny seeing one make their way to the OSS
| community.
|
| [1] https://github.com/jonschlinkert
| whaleofatw2022 wrote:
| Yeah but this might make him the Patient Zero for modern
| tech influencing and blogspam.
| galangalalgol wrote:
| Anyone know if this has spread to crates.io yet? I see
| plenty of name squatting, but I haven't run into real
| crates trying to insert themselves into everything.
| Namespaces are sorely needed, including some semi-
| official ones. candi::rand would be reasonable for
| candidates to enter std. Watching the battles over tokio
| getting into candi would be fun.
| jd24 wrote:
| > To date, I've created more than 1,000 open source
| projects
|
| This dude is counting each one as a project hahaha
| buttercraft wrote:
| It's the truth but not the whole truth
| jv22222 wrote:
| It reminds me of graffiti tagging!
| pc86 wrote:
| So what excuse do the people _installing these packages_
| have?
| mbb70 wrote:
| Another classic from jon is the venerable
| https://www.npmjs.com/package/isobject coming in at
| 30,000,000 weekly downloads for
|
| `function(val) { return val != null && typeof val ===
| 'object' && Array.isArray(val) === false; }`
|
| But honestly, having seen "TypeError: Cannot read properties
| of null" enough times, I give it a pass.
|
| https://npm-stat.com/charts.html?author=jonschlinkert paints
| a pretty crazy picture
| orenlindsey wrote:
| That's hilarious. The best part is that he didn't even try to
| make good packages (not that hard) but just took the lazy
| route.
| geodel wrote:
| Well one reason could be this software proverb: _Good
| programers are lazy programers._
| mkgeorge7 wrote:
| I'm relatively new to the world of node. Is there anything
| objectively wrong or should I say nefarious with that this
| Jon person is doing? I guess, what's the issue here, from
| your perspective, if he's creating package (that albeit are
| simple) but some _some_ amount of utility?
| lolc wrote:
| In my view it is objectively wrong to create trivial npm
| packages yes. If we look at the npm ecosystem as a commons,
| that person is polluting it. Of course you could say it's
| namespaced to one account, so what's the harm? In my view,
| plenty:
|
| - package searches will show these packages due to the
| inflated usage from transient deps.
|
| - installs are slower due to the package noise.
|
| - increased attack surface when they are used
|
| - cultural normalization of throwaway packages
|
| Probably more.
| johannes1234321 wrote:
| Each dependency causes work for any serious use. You got to
| check license, got to check for updates, risk supply chain
| attacks (package disappearing, package replaced with bad
| code, ...) etc. which causes longer term cost.
|
| In addition abstraction of trivial checks, makes it harder
| to see the limitations of said routine. How well does it
| work on numeric strings? How well on large numbers where
| float properties cause issues?
| Jasper_ wrote:
| My favorite is the existence of both
| https://github.com/jonschlinkert/ansi-gray and
| https://github.com/jonschlinkert/ansi-grey that do the exact
| same thing.
| johnfn wrote:
| It's weird to me that in every other comment thread on Hacker
| News, people say "good software should do one thing and do it
| well". And then the topic moves to NPM, and suddenly everyone
| loses their mind?
| lolc wrote:
| Haha ok do something substantial! It's implied.
| jrockway wrote:
| A little copying is better than a little dependency.
| throwitaway1123 wrote:
| This is part of the UNIX philosophy, but sometimes this
| gets taken way too far. There is of course the UNIX command
| "yes", which literally just prints the character "y" over
| and over again (to skip interactive prompts).
| ericbarrett wrote:
| GNU yes will actually repeat any string--the default is
| of course "y". So it's very handy for scripting, and not
| really as single-purpose as you'd think.
| throwitaway1123 wrote:
| Yeah it's definitely useful. Still a bash one liner
| though: function yes { while true; do
| echo "$1"; done }
| cyco130 wrote:
| But of course WebAssembly is the future. So we should
| reimplement it in WASM.
| christophilus wrote:
| Every time I see these packages mentioned, I'm reminded of an
| interview with Joe Armstrong. In it, he said, (paraphrasing
| from memory) "Wouldn't it be interesting if a language had a
| global, flat registry of functions that anyone could pull from
| and contribute to? That way, bugs are fixed in one place,
| there's less reinvention of the wheel, things get more correct
| over time, and programs just become a simple composition of
| standard functions."
|
| I may be misremembering his meaning, but I remember thinking it
| was an interesting idea. It wasn't obviously a terrible idea. I
| thought it would be like the Clojure standard library on
| steroids, especially if it was coordinated and vetted by a
| decent team.
|
| But alas, NPM has proven it otherwise.
| harperlee wrote:
| I don't think NPM has proven that idea infeasible, just that
| it may not be a good idea to depend on third-party content
| that may change under your feet, on such a fine-grained
| level.
|
| But have a look at the Unison language https://www.unison-
| lang.org/docs/the-big-idea/ , that has such global registry
| but addresses each function by a hash of its syntax tree, and
| thus sidesteps the issue.
| ncruces wrote:
| How are bugs "fixed in one place" that way?
|
| You either accept updates of third party packages, with
| little to no vetting of your own, and get fixes "for free"
| or... you don't.
|
| There's no middle ground: the only way to save effort is to
| trust others.
| MisterTea wrote:
| NPM is a worse idea than Joe's as Joe was talking about a
| single community vetted monorepo. Not a free for all of
| individual repos.
|
| With Joe's idea everything is up front and part of the
| language and not a bulletin board of packages near the
| checkout line at the git supermarket. This way simple stuff
| like isint() can make its way into the languages official
| standard library. This should eliminate the uncertainty of
| 3rd party packages maintained by a random number of
| individuals that can be taken down or tainted at any time.
| AQuantized wrote:
| To be fair, for all its pitfalls, NPM does provide a limited
| version of that idea to millions of codebases.
| divbzero wrote:
| NPM doesn't capture the full benefit of an open registry of
| functions because, while anyone can fork and create an
| alternative @christophilis/is-even or @divbzero/is-even,
| there is no good way for developers to pick the best version
| of is-even.
|
| Maybe if NPM required all package maintainers to use a
| namespace, the global is-even package name could resolve to
| the most-used fork.
|
| So for an import like: import isEven from
| 'is-even'
|
| You could install a specific fork: npm
| install --save @christophilus/is-even
|
| Or default to the most-used fork: npm install
| --save is-even
|
| In both cases, _package.json_ would only contain namespaced
| dependencies and _npm outdated_ could flag if a different
| fork is more commonly used.
| ksherlock wrote:
| This Joe Armstrong quote sums up NPM:
|
| "You wanted a banana but what you got was a gorilla holding
| the banana and the entire jungle."
|
| (originally on object oriented programming)
| mickael-kerjean wrote:
| I did a nullll package [1] whose only purpose is to export a
| null and takes 400MB in memory but somehow it got flagged in HN
| [2]. With 41 stars on github and 100% test coverage [3], it was
| clearly production ready.
|
| [1]: https://github.com/mickael-kerjean/nulll
|
| [2]: https://news.ycombinator.com/item?id=17072675
|
| [3]: https://github.com/mickael-
| kerjean/nulll/blob/master/test.js
| lvncelot wrote:
| That try-catch block[1] is a thing of beauty.
|
| [1] https://github.com/mickael-
| kerjean/nulll/blob/master/index.j...
| tiagod wrote:
| Shame it was flagged. Would've been handy for a project I was
| working on. Had to work around not having a performant null
| divbzero wrote:
| Amazingly, following "don't repeat yourself" in its purest
| form, is-even depends on is-odd: /*! *
| is-even <https://github.com/jonschlinkert/is-even> *
| * Copyright (c) 2015, 2017, Jon Schlinkert. * Released
| under the MIT License. */ 'use strict';
| var isOdd = require('is-odd'); module.exports =
| function isEven(i) { return !isOdd(i); };
| goalieca wrote:
| If this code runs on hundreds of millions of phones and
| computers, npm seems horrible for the environment! Not only
| because of runtime, but because we're talking so much just to
| host and serve these modules!
| asylteltine wrote:
| That's right. Npm and the entire node ecosystem is just
| terrible. Specifically because you can get a production
| ready package from even Google, and you know it's going to
| have some random useless package in the chain somewhere.
| fritzo wrote:
| These packages are performance art, and shall not be judged
| by efficiency metrics.
| darkwater wrote:
| I bet a dollar you started writing "performance" and then
| rewrote it as "efficiency" :)
| fritzo wrote:
| Good guess, but sorry :) You can pay at
| https://github.com/sponsors/fritzo?frequency=one-time
| jrpelkonen wrote:
| Implementing the comparisons by hand seems difficult and
| primitive. May I suggest introducing some helpful sub-packages
| and building the solution on top of those. For instance, is-odd
| would be implemented by using is-one, is-three, is-five, is-
| seven, etc.
| leeoniya wrote:
| and is-one should be implemented by negating is-two, is-
| three, and so forth
| paddy_m wrote:
| I read some text where a cheme was implemented such that
| numbers were `2 = 1+1`, `3 = 2+ 1`...
| jcparkyn wrote:
| Probably Peano numbers.
|
| https://wiki.haskell.org/Peano_numbers
| ta8903 wrote:
| >Succ Peano
|
| ...
| jbboehr wrote:
| Perhaps Nock:
|
| https://developers.urbit.org/reference/nock/definition
|
| > The reader might wonder how an interpreter whose only
| arithmetic operation is increment can ever be practical.
|
| > The short answer is that a Nock interpreter doesn't
| have to use the algorithm above. It just has to get the
| same result as the algorithm above.
| avinassh wrote:
| I did something similar six years ago called gg-flip for npm -
| https://github.com/avinassh/gg-flip
|
| It was submitted in HN too -
| https://news.ycombinator.com/item?id=16194932
| jgalt212 wrote:
| I'd fire someone who imported those packages.
| atleta wrote:
| I haven't heard about him but checking the source tree of our 2
| front-end apps and his 'is-number' package (which his is-odd
| depends on), seems to be imported by quite a few other
| packages.
|
| Now looking at the source, that package _may_ make sense if
| figuring out whether something is a number type in JS is really
| that cumbersome. (Though I 'd expect that there is a more
| generic package that covers the other built-in types as well.)
|
| Also since isNumber treats strings that can be converted to a
| number, a number, it can yield weird results since adding two
| strings will naturally just concatenate them. So e.g.:
| const a = '1'; isNumber(a); // returns true
| const b = a + a; // Now you have a string in b: '11'
|
| Of course, it's standard JS stupidity (and 2*a would be 2, and
| 1+'1' and '1'+1 would both be '11'), but then maybe stating
| that '1' is a number is not the right response. However, the
| package was downloaded 46 million times last week and that
| seems to be so low only because of Christmas. The previous
| weeks averaged around 70M. And most of these are dependencies,
| like in our projects, I'm sure.
| geodel wrote:
| Big fan of code reuse. Small packages providing single unique
| functionality is the way to program modern systems. It has to
| be right if bright minds in NPM / Rust community follow this
| approach.
| ape4 wrote:
| I was wondering what the code looked like...
| 'use strict'; const isNumber = require('is-
| number'); module.exports = function
| isOdd(value) { const n = Math.abs(value);
| if (!isNumber(n)) { throw new TypeError('expected a
| number'); } if (!Number.isInteger(n)) {
| throw new Error('expected an integer'); }
| if (!Number.isSafeInteger(n)) { throw new
| Error('value exceeds maximum safe integer'); }
| return (n % 2) === 1; };
| cchance wrote:
| I mean... when you look at it like that, at least it's got
| the error checking integrated as well... tho the fact it
| pulls in is-number is fucking hysterical lol
| kparaju wrote:
| even
| (https://www.npmjs.com/package/even?activeTab=dependencies)
| pulls is-even.
|
| is-even (https://www.npmjs.com/package/is-
| even?activeTab=dependencies) pulls is-odd.
|
| is-odd (https://www.npmjs.com/package/is-
| odd?activeTab=dependencies) pulls is-number.
|
| _sigh_
| jkrubin wrote:
| Theoretically only one 40gb file would be needed. AFAICT almost
| every odd number is not even (I cannot say "all" bc I have not
| checked every integer yet).
| blowski wrote:
| That's what unit tests are for, right?
| dfee wrote:
| The implementation of is-even is mind blowing (numbing?).
| 'use strict'; var isOdd = require('is-odd');
| module.exports = function isEven(i) { return
| !isOdd(i); };
|
| good thing it declares its dependencies properly!
| xorvoid wrote:
| Even better if it built-on-install by executing another script
| to generate everything (naturally using %) New nerd game:
| enshitification inverse golf.
| bryanlarsen wrote:
| That reminds me of my first program ever as an 11 year old. Not
| only did I not know about modulus, I didn't know about less than
| or greater than. The program picked bingo numbers. So there were
| 5 lines that looked something like `10 IF n=1 OR n=2 OR n=3 OR
| n=4 OR n=5 OR n=6 OR n=7 OR n=8 OR n=9 OR n=10 OR n=11 OR n=12 OR
| n=13 OR n=14 OR n=15 THEN l="B"`
| wenyuanyu wrote:
| better to keep "4 billion" in the title... I was confused with "4
| bytes" before open the link
| faizshah wrote:
| This metaprogramming reminds me of the post where they serialized
| data to ruby code to get around a slow XML parser:
| https://news.ycombinator.com/item?id=36311924
|
| I'm curious if anyone has found a serious application for
| metaprogramming large amounts of data in a high level language
| like this?
|
| So far the only application I have thought of was meta
| programming a series of api calls before executing them so the
| entire transaction can be replayed as a script.
| SCUSKU wrote:
| Somewhat pedantic here, but would the authors use of python to
| generate C code be considered metaprogramming as opposed to
| code generation? I thought metaprogramming typically involved
| writing code that can alter/augment itself, like new syntax.
|
| Personally, I have found a lot of use in code generation, for
| example using RTKQuery's codegen tool that accepts an OpenAPI
| schema and outputs a JS client.
| teo_zero wrote:
| I would argue that code generation _is_ a form of
| metaprogramming, no opposition here.
| Retr0id wrote:
| A while back I was reverse engineering a mobile game that used
| a completely custom serialization format for game data, most of
| it in one giant "config" blob several megabytes in size. I'd
| written a parser and serializer for it in Python, using custom
| classes to represent the various nested object types, but I
| didn't have a convenient way to explore and edit the data.
|
| So, I wrote some code to parse the giant blob and emit a python
| source file, consisting of a whole bunch of nested class
| constructors (with named parameters etc. making it quite
| readable), and a final function call to serialize the whole lot
| back into a blob. Now I could edit that source file and run it,
| and have my source-level edits reflected in the output blob
| (which I could subsequently feed back into the game engine to
| see the results of my changes).
| baq wrote:
| Note: this is essentially what the AWS CDK does.
|
| Yet another example that configures is code is configuration
| is code is...
| rented_mule wrote:
| I don't know if I'd go as far as calling it serious, but...
|
| I have a string of 150 individually addressable RGB LEDs on a
| fake tree in my living room. It's controlled by an ESP32
| (running ESPHome). I started generating little animations for
| different times of year (in the form of ESPHome light effects).
| I ran into a few problems:
|
| - The edit/compile/flash/debug cycle was painfully slow.
|
| - Expressing the animations in C++ sapped inspiration.
|
| - Some parts of the animations are more computationally
| intensive than others, so getting consistent "frame rates" was
| difficult.
|
| That "frame rates" bit made me realize these are just little
| videos with 150x1 pixel resolution. Now I write the animations
| in Python on my laptop and that code has two backends. One
| renders to the screen for quick iteration on the animations.
| The other plays one cycle through the loop of each animation
| and emits the results as C++ arrays and some variables (e.g.,
| name, desired frame rate, etc.). Then the only other C++ code
| needed is the logic for passing the array data to the LED
| library.
|
| There is no compression or anything else fancy. I can fit about
| a dozen animations with 100 to 200 frames each on a $4
| microcontroller with Wi-Fi. They start almost instantly when
| applying power, and they play at a very consistent frame rate.
| The highest I have tried is 60 fps and that is no problem.
| tda wrote:
| I quit iterating on my animations (led strip based bedlight
| with ESPHome/ESP32) due to the exact same frustrations (and
| that writing c++ in a yaml file is not really great). Care to
| share the code for your approach?
| Someone wrote:
| https://en.wikipedia.org/wiki/X_BitMap and
| https://en.wikipedia.org/wiki/X_PixMap come to mind, but they
| usually were written by an image editor, not by a program
| specifically written by the programmer who needed such code in
| their program.
| vitiral wrote:
| Protocall buffers are effectively code generation and are
| central to Google's tech stack. Does that count?
| notfed wrote:
| > modulus operation
|
| Isn't it normally called the modulo operation?
| eurekin wrote:
| Maybe it's a modulo operation squished together with the modus
| operandi, for laughs
| brcmthrowaway wrote:
| The skeleton of this post can make a good interview question
| brcmthrowaway wrote:
| Those APIs seem like fake pseudocode, until I realized... Windows
| glandium wrote:
| It's kind of ironic that the python generator script uses modulo.
| The author could have pushed it to the point of not using one.
|
| I'm tempted to write a followup doing even crazier things...
| eru wrote:
| Author should have perhaps bootstrapped a script that doesn't
| use modulo?
| layer8 wrote:
| Clearly the solution is to factor each number and to
| (recursively) test the parity of the sum of the factors. Since
| all prime numbers other than 2 are known to be odd, the parity
| test for the case of a single factor is easy. You only need to
| special-case 4 to avoid an infinite recursion.
| ryanjshaw wrote:
| I'm pretty sure that was an intentional joke. I do wish it'd
| have been a bitwise AND with 1.
| Retr0id wrote:
| > for the large number close to the 2^32 limit the result is
| still returned in around 10 seconds.
|
| This could be improved by arranging the if/else statements in a
| binary tree.
| elwell wrote:
| This is a great idea! Intuitively, I think it might make the
| program 3x size though?: first `if` for ==, then an `else if`
| for <, then `else` for >.
| vitiral wrote:
| it would be extremely humorous if it actually *reduced* the
| speed since it required loading so much more code.
| hansjorg wrote:
| Come to think of it, I'm sure there are other optimisations you
| could do as well.
| Scarblac wrote:
| It could also simply check the most common numbers first. We
| can spider the Internet and collect all usages of numbers, sort
| them, and find out what the optimal order is.
| Retr0id wrote:
| True - given probability weights, the optimal decision order
| would be a Huffman tree
| https://en.wikipedia.org/wiki/Huffman_coding
| Scarblac wrote:
| I don't think it would help, you'd still need the 4 billion if
| statements to decide whether to take the left or the right
| branch from the root.
| sltkr wrote:
| Yes but you would only need to visit 32 of them, so it would
| run much faster (around a hundred million times faster).
| Retr0id wrote:
| I think Scarblac's point is that using a > comparison would
| be cheating, and you'd have to do _that_ as a series of 4
| billion if /else statements too.
| sltkr wrote:
| Fair enough, comparisons are dangerously close to
| arithmetic and we can't have any of that.
| Subdivide8452 wrote:
| Can't you just test the last digit of main's arg and get the best
| of both worlds?
| projektfu wrote:
| "just"
|
| https://dohertyjf.medium.com/just-dont-say-just-4c3c4cde3ebb
|
| /s
| Subdivide8452 wrote:
| Ironically, I have no idea what you're implying with this
| reply. Should I drop the usage of the word 'just'? Isn't it
| clear what I'm saying?
| friedrich_zip wrote:
| This is amazing technology. You should sell it to AWS so they can
| offer an Enterprise-ready AWS EvenOrOdd API for everyone who does
| not know how to host the 40GB executable properly. With the power
| of the cloud this programme would be unstoppable
| MBCook wrote:
| It's just begging to be a Lambda function.
| BillyTheKing wrote:
| why though? this is exactly what databases have been invented
| for! One could simply store a mapping of numbers to their
| classifications as 'even' or 'odd' in an SQLite database. This
| approach has the added benefit of not requiring program updates
| whenever a number's classification changes from odd to even.
| Mattasher wrote:
| Databases still have to be maintained and updated. You're
| better off setting up an Ethereum contract with proper economic
| incentives for others to act as an oracle and return the proper
| answer at any given time.
| ep103 wrote:
| Anyone want to try to figure out the gas costs for deploying
| 30GB worth of smart contracts? xD
| twic wrote:
| AWS's Elastic Cloud Parity already provides this, and is far
| more scalable.
| layer8 wrote:
| Yes, this seems like the kind of thing that should be in
| Wikidata. Then you also don't have to keep the database locally
| and can simply do a quick HTTPS request. (The only problem
| might be if TLS itself needs an even/odd function, but it
| probably doesn't.)
| peteradio wrote:
| > The only problem might be if TLS itself needs an even/odd
| function, but it probably doesn't.
|
| Doesn't sound like its ready for cloud scale.
| mminer237 wrote:
| I like this option just because then it makes it easy for
| anyone to update the data when future changes arise.
| whoopdedo wrote:
| CREATE TABLE even_or_odd ( is_odd NUMBER(1);
| is_even NUMBER(1); is_zero NUMBER(1);
| is_one NUMBER(1); is_two NUMBER(1);
| is_three NUMBER(1); -- ... ); INSERT
| INTO even_or_odd (is_odd,is_one) VALUES (1,1); INSERT
| INTO even_or_odd (is_even,is_two) VALUES (1,1);
| ht85 wrote:
| A better design would look like this:
| CREATE TABLE numbers ( minus_four_billions_two_hund
| red_ninety_four_millions_nine_hundred_sixty_seven_thousands_t
| wo_hundred_ninety_six_is_even BOOLEAN, ...
| zero_is_even BOOLEAN, one_is_even BOOLEAN,
| two_is_even BOOLEAN, ... four_billions_tw
| o_hundred_ninety_four_millions_nine_hundred_sixty_seven_thous
| ands_two_hundred_ninety_six_is_even BOOLEAN )
|
| That design can store multiple versions of the data, making
| it more resilient to future changes in the even/odd property
| of numbers.
| huhtenberg wrote:
| Correct, but you'd certainly want to use an XML database.
|
| Not only it helps with portability of the data, it also keeps
| it in a human-friendly format should the need to inspect it by
| hand arise.
| ric2b wrote:
| XML is not web scale though, if you want to serve lots of
| users it has to be JSON in MongoDB.
| KETHERCORTEX wrote:
| Come on, we live in 2023 and we can achieve better performance.
| It should be parallelized with checks evenly distributed between
| GPU cores. Unless you think that efforts by NVIDIA and AMD should
| be wasted.
| NKosmatos wrote:
| I'm pleasantly surprised that nobody started the discussion on
| whether zero is odd or even ;-)
| https://en.wikipedia.org/wiki/Parity_of_zero
| eru wrote:
| I find it hard to understand how someone can be confused about
| that. But I dimly remember talking to people with this
| confusion in the past.
| contravariant wrote:
| It's apparently confusing enough that if you ban odd license
| number plates then the cops don't want to arrest anyone whose
| license plate ends in 0 because they're not sure if it is
| even or not. At least that was the case in Paris in 1977,
| when they alternated between odd/even license plates every
| day to limit the number of cars.
| eru wrote:
| Interesting. Do you have a source for that?
| Snarwin wrote:
| It looks like bans for odd/even license plates were used
| in Paris in 2014 [1] and 1997 [2], but not before then.
| However, a similar scheme was used to ration gasoline in
| the US during the 70s [3].
|
| The only source I can find for the claim about police
| confusion is the one cited by Wikipedia [4], whose
| reliability I'm inclined to doubt based on the 1997/1977
| discrepancy.
|
| [1] https://www.npr.org/sections/thetwo-
| way/2014/03/17/290849704...
|
| [2] https://www.wired.com/1997/09/paris-smog/
|
| [3] https://www.npr.org/sections/pictureshow/2012/11/10/1
| 6479229...
|
| [4] https://en.m.wikipedia.org/wiki/Odd%E2%80%93even_rati
| oning#D...
| eru wrote:
| Thanks!
| contravariant wrote:
| The wikipedia article matched my vague recollection of
| the event, but if they got the year wrong then it may as
| well just be a rumour at this point.
| travisjungroth wrote:
| Please don't take this as _defending_ this thinking. I'm just
| guessing at how someone could get to this confusion.
|
| I can see how you'd get there by thinking of numbers as a
| thing for counting. Even numbers give you piles of two
| without one left over. Zero fails the first condition since
| it gives you no piles at all. But it doesn't leave a pile of
| one, so it's not really odd, either.
|
| If you ever find yourself confused in this way about
| definitions consider: is this definition serving me? Could I
| adopt a different definition that's used by people really
| good at this sort of thing?
|
| (Zero is even because any integer n that can be formed by 2k
| for integer k is even, and that can be formed by 2k+1 is odd.
| 2x0=0)
| eru wrote:
| Yes, it all boils down to definitions. Definitions that
| have 0 as an even number work well in math.
|
| For most people's daily life, it doesn't really matter
| which category zero would fall under (as they never really
| eg consider dividing zero items evenly between people.) So
| their (implied) definitions can be all over the place.
| Joker_vD wrote:
| I am fairly certain I can split an empty pile into two
| empty piles, without a remainder.
| sbarre wrote:
| Hmmm by definition an empty pile is not a pile though, is
| it? So there's nothing to split?
|
| ;-)
| Joker_vD wrote:
| And an empty plate is not a plate, also by definition?
| Okay, sure.
| sbarre wrote:
| Ah I suppose if you see an "empty pile" as still a vessel
| with nothing on/in it, your point stands.
|
| But a plate is its own thing, in addition to what goes on
| it. A "full plate" is full of what? And a full plate is
| the plate plus whatever is on it, not just the stuff on
| it.
|
| I think of a "pile" of stuff as being it's own thing,
| that being the pile itself. An empty pile is the absence
| of the thing.
|
| That was my interpretation, but I see what you meant. :)
| royaltheartist wrote:
| well that's odd
| javajosh wrote:
| _> Even numbers give you piles of two without one left
| over. Zero fails the first condition since it gives you no
| piles at all. But it doesn't leave a pile of one, so it's
| not really odd, either._
|
| This definition does not naively extend to negative
| numbers, which are anti-piles of things. You are right, of
| course, about definitions serving their purpose. In this
| case maintaining the symmetry of alternation requires 0 to
| be even, and that argument could even be extended to
| negative numbers. (Of course other numbers, like the
| rationals and reals, are pure fiction and can safely be
| ignored negative or otherwise.)
| eru wrote:
| > (Of course other numbers, like the rationals and reals,
| are pure fiction and can safely be ignored negative or
| otherwise.)
|
| I think natural numbers are already pretty fictional.
|
| Btw, you might want to look into p-adic numbers.
| codeflo wrote:
| Your defense boils down to people having an insufficient
| understanding of zero as an ordinary number, and still
| clinging to the concept that zero means "nothing" or is
| otherwise magic.
|
| This hints at a failure of math education.
|
| As an analogy, many (usually, but not always, weaker)
| programmers still have magic ideas about booleans and
| comparison operators, and write nonsensical stuff like if
| (a == true). When you ask them, it's invariably that in
| their mind, there's mystic connection between comparison
| operators and if statements.
| travisjungroth wrote:
| > Your defense
|
| I _literally_ ... never mind.
| layer8 wrote:
| One might even say it's odd.
| latexr wrote:
| The thing that gave me pause the first time I thought about
| it (it was during a test so I couldn't ask or check) was that
| if zero is even, that means (despite numbers being infinite)
| there's one more even number than odd numbers.
|
| I also knew that 1 is not prime, even if logically it should
| be. Its definition specifically states a prime number needs
| to be greater than 1. So that means mathematics sometimes has
| exceptions for numbers inside a definition.
|
| Given that, it's not immediately obvious that zero would be
| even. It wouldn't be odd either, that was out of the
| questions, but it could be neither.
| raverbashing wrote:
| This is the kind of discussion that matters only for the very
| theoretical edge cases or for the pop-math inconsequential
| discussions
|
| 0 is even
|
| I mean, it is the first phrase on the linked fine article:
|
| > In mathematics, zero is an even number.
| Viliam1234 wrote:
| Is that article about the IEEE 754 positive zero, or negative
| zero, or both?
| Mountain_Skies wrote:
| When I was a junior developer fresh out of college, another
| junior and I noticed a bank sign with the temperature showing
| to be -0 degrees. We made a few comments about Two's
| Complement and felt a bit smug in our superiority over the
| manufacturer of the sign. Decades later I read an article
| about how -0 degrees is a standard in civil meteorology for
| "below freezing but rounded up to zero". Though it took a
| while to learn, it was a good lesson in making assumptions
| about standards in other domains.
| vitiral wrote:
| I particularly liked this bit
|
| > Not only is 0 divisible by 2, it is divisible by every power
| of 2, which is relevant to the binary numeral system used by
| computers. In this sense, 0 is the "most even" number of all.
|
| in the arena of even one-up-man-ship, zero wins.
| codeflo wrote:
| I always found it funny that this is printed as a reminder text
| on Magic the Gathering cards that care about even or odd
| values: https://scryfall.com/card/iko/88/extinction-
| event?utm_source...
|
| But thinking about it, I have no doubt that Wizards found out
| this confusion is somewhat widespread during playtesting, and
| printing a short reminder was an easy fix.
| quickthrower2 wrote:
| Home run! (First blog post blows up on HN)
| zimpenfish wrote:
| Weirdest bit is this, I think.
|
| > After all, IPv4 is still standing stronger than ever, 60 years
| after it was deemed deprecated due to so called "address
| exhaustion".
|
| IPv4: deprecated in 1963, 19 years before it was introduced.
| stanac wrote:
| The whole article is full of jokes.
|
| > the C programming language as it's by far the fastest
| language on the planet to this day (thanks to the visionary
| genius Dennis Richie)
|
| Which would be more or less true, but:
|
| > I decided to use the slowest language on the planet, Python
| (thanks to the visionary genius of Ross van der Gussom)
|
| > So I let the mighty snake do its work and after getting a cup
| of coffee and getting back to check on the program 48 hours
| later I was left with a beautiful c file
| junon wrote:
| It took me way too long to realize this was satire. It was a
| stressful read up until that point.
| keepamovin wrote:
| This was hilarious thank you. Many lols
| gverrilla wrote:
| First program I ever wrote was to bypass an anti-afk program in a
| game: it needed to click on a button which was x vs y pixels, and
| would appear on random positions on the screen every time. I
| manually inserted one line for each viable position using x-1 and
| y-1. In v2 I implemented a for loop which made the script go from
| tens of pages to not even a single full one - computer magic!
| (EasyUO language)
| ykonstant wrote:
| Although not quite as spectacular as that, here is some funny
| codegen in POSIX shell I wrote; `sh` doesn't have a `repeat`
| command, so I wrote a script to implement it without forcing any
| loops at all. Along the way I uncovered some interesting
| segfaults for most sh implementations (including, sadly, dash),
| which is the reason for the somewhat convoluted code. Have fun!
| #!/bin/sh # # Usage: repeat TIMES COMMAND #
| Repeat COMMAND a given number of TIMES.
| eval_full_quotes=' s/\\/\\\\/g ; s/\"/\\\"/g ;
| s/</\\</g ; s/>/\\>/g ; s/\$/\\\$/g ; s/\[/\\\[/g
| ; s/*/\\*/g ; s/?/\\?/g ; s/|/\\|/g ; s/&/\\&/g
| ; s/~/\\~/g ; s/=/\\=/g ; s/;/\\;/g ; s/ /\\ /g
| ; s/%/\\%/g ; s/`/\\`/g ; s/(/\\(/g ; s/)/\\)/g
| ; s/{/\\{/g ; s/}/\\}/g ; s/#/\\#/g ;
| s/'"'"'/\\'"'"'/g' errorx() { printf 'Error: %s\n'
| "${*:-"unknown error."}" >&2; exit 1; } _rep() {
| rep_times="$((2 * $1))" rep_string="$2" output=""
| while [ 0 -lt "${rep_times}" ]; do test 1 -eq
| "$(((rep_times /= 2) % 2))" && output="${output}${rep_string}"
| rep_string="${rep_string}${rep_string}" done
| printf '%s' "${output}" } {
| times="$1" shift test 0 -lt "${times}" ||
| errorx "First argument must be a positive integer." test 0
| -lt "$#" || errorx "No command given to repeat."
| repeat_command="$*" command_length="${#repeat_command}"
| max_arg="${ARG_MAX:-"$(getconf ARG_MAX)"}" if [
| "${max_arg}" -le "$((times * (command_length + 2)))" ]; then
| : "$(( block_size = max_arg / (20 * (command_length + 2))
| ))" : "$(( blocks = times / block_size +
| 1 ))" : "$(( remainder = (block_size +
| (times % block_size)) % block_size ))"
| eval_string="$(_rep "${block_size}" "${repeat_command}; " | sed
| -e "${eval_full_quotes}")" while [ 0 -lt
| "$((blocks -= 1))" ]; do eval eval "${eval_string}"
| done eval_string="$(_rep "${remainder}"
| "${repeat_command}; " | sed -e "${eval_full_quotes}")"
| eval eval "${eval_string}" else
| eval_string="$(_rep "${times}" "${repeat_command}; " | sed -e
| "${eval_full_quotes}")" eval eval "${eval_string}"
| fi } exit
| timrobinson333 wrote:
| I'm afraid I take issue with the phrase "amazingly performant". I
| would struggle to come up with another way of determining whether
| a number near 2^32 is even that takes anything like 10 seconds
| christophilus wrote:
| I'd bet this is slower: function isEven(n) {
| let arr = []; let sign = -1; for (let i =
| 0; i < Math.abs(n); ++i) { arr = [...arr, sign];
| sign *= -1; } return arr.length === 0 ||
| arr.reduce((a, b) => a + b) === 0; }
|
| But I'm not going to test it, because I'm doing productive
| things on my computer right now, and don't want to OOM.
|
| Sadly, the OP missed an opportunity to call his program
| "blazingly fast" [0].
|
| [0]
| https://www.youtube.com/results?search_query=primagen+blazin...
| furyofantares wrote:
| I wish I still had one of the earliest programs I wrote. It would
| have been 1996, I was 16, and I had a linear algebra book which
| had an appendix entry on computer graphics. I had taken a
| programming class the prior quarter.
|
| I got hooked writing a program to draw rotating wireframes of a
| few different shapes. I almost failed the class because I was so
| distracted by this.
|
| I didn't know about arrays yet. Every vertex was its own variable
| with a hardcoded default. Every entry in the rotation matrices
| was its own variable. The code to do matrix multiplication
| therefore didn't have loops, just a long list of calculations.
| Which had to be duplicated and adapted to every vertex.
|
| I did know about pointers, I had to draw to the screen after all,
| which was done by writing to memory starting at a known address.
| So at least I had loops rasterizing the lines between vertices.
|
| Which means I definitely had the concept of arrays and indexing
| into them, I just didn't know enough to make my own.
| sbarre wrote:
| Do you recall which shapes you created?
| furyofantares wrote:
| I remember there were 3, and that there was a cube and a
| pyramid. I can't recall the third. Maybe I did both a square
| pyramid and a triangular pyramid.
| phkahler wrote:
| Same. When I was 12ish trying to write a Pac-Man game in basic,
| I dreaded writing the logic for the 4 ghosts. I'd need separate
| code for the ghosts at (x1,y1)....(x4,y4) and said to my dad it
| would be cool if I could use xn and yn inside a for loop, but
| those are just 2 more variables. I wanted n to indicate which
| one. This seemed kind of weird, but it's what I _really really
| wanted_. He grabbed the little basic book and showed me that
| x(n) was actually a thing!
|
| I think back to this in discussions about teaching. Abstract
| concepts are best understood when the student has a legitimate
| need for them. You can explain something all day and have their
| eyes glaze over wondering why something is important, but if it
| solves a problem they have it will click in seconds or minutes.
| quirino wrote:
| When I started programming at 12-13 I had no idea loops or
| arrays existed and implemented an absolutely criminal Tic-
| Tac-Toe game.
|
| The same year me and a friend were studying for the national
| Informatics Olympiad and we were completely stumped when
| faced with a problem that required a list: "How do we know
| how many variables to declare if we don't know the N
| beforehand?".
|
| (The problem if anyone is interested:
| https://neps.academy/br/exercise/384. Given a list of up to
| 50k distinct numbers (with values up to 100k) and another
| list of 50k numbers that should be removed, print the
| resulting list. Time Limit: 1 second.)
| freetime2 wrote:
| When I first started coding, I thought loop structures were
| confusing and redundant when I could accomplish the same
| thing with GOTO. So that's how I implemented all my loops
| for _years_ until I eventually took a course and a teacher
| told me I was never to use GOTO again.
| dubi_steinkek wrote:
| This seems to be a somewhat common occurrence. When I was
| first learning programming with python I wanted multiple
| balls in a pong-like game, so after some googling I ended up
| writing something like `globals()["ball" + i]` until someone
| mentioned that arrays were a thing I could use for that.
| WJW wrote:
| This comes up pretty often in (well-designed) video games.
| Say you have colored doors that can only be opened by keys of
| the same color. If you put the blue key on the path to the
| blue door, then players will never learn that you need the
| color of the key to match the color of the door. But if you
| put the blue key on a side path and have the player encounter
| a blue door relatively early on, then they will encounter the
| door first and cannot progress until they find the key. The
| frustration at not being able to progress is much more
| effective at teaching the player about the "colored keys for
| colored doors" mechanic than any amount of explaining you
| could have done.
| Y_Y wrote:
| The obvious solution here is to use the lower part of the
| screen as working memory while drawing the upper part. By the
| time you get to the bottom you shouldn't have many calculations
| left anyway. This has the benefit of using fast gpu ram and is
| therefore cuda and very ai.
| adastra22 wrote:
| If only GPUs existed back then. This would have been very
| slow memory mapped video ram.
| almostnormal wrote:
| The first part of GWBasic I learned by asking someone for help
| was "chain", after having taught myself print, input, if, and
| goto from the documentation.
| canjobear wrote:
| I did something similar for my big middle school hit, a TI-83
| version of Snake. Every x and y position of every segment of
| the snake went into a separate variable. The snake could only
| get so long because TI-83 BASIC only gives you so many
| variables.
| ljm wrote:
| It reminds me of one of my earliest ventures into freelancing,
| where all I had was a tiny VPS that supported PHP. I had to
| process a large spreadsheet which had maybe 5/10k entries in
| it. Small potatoes these days, compared to that time in
| 2002/2003.
|
| I wasn't a computer scientist so I read the file in the dumbest
| way possible, but kept getting errors about memory usage and
| running out of space since I was looping within loops within
| loops. I went through it and added `$variable = null` at every
| opportunity. Lo and behold it worked.
| maxlin wrote:
| I'd be interested in seeing how this would have gone with a
| switch statement instead.
| reidrac wrote:
| Yep, I was thinking a switch statement may be better.
|
| I mean, if we don't take into account that implementing this is
| just a joke anyway :D
| majke wrote:
| In the blog post "Branch predictor: How many "if"s are too
| many?", I started with the same premise, but focused on branch
| predictor :P
|
| https://blog.cloudflare.com/branch-predictor
| bilinguliar wrote:
| It seems over-engineered to me. Why go through all the hustle of
| code generation? It can be solved with a simple "for loop":
| func isOdd(n int) bool { var odd bool for i := 0;
| i < n; i++ { odd = !odd } return odd
| }
|
| Playground link: https://go.dev/play/p/8TIfzGrdWDF
|
| I did not profile this one yet. But my intuition, and my industry
| experience, tell me that this is fast.
| javajosh wrote:
| You, sir, are a raging psychopath. You have found a local
| maxima of brevity and absurdity and I, for one, salute you.
| clarkdale wrote:
| You can improve this with tail recursion.
| YetAnotherNick wrote:
| It will iterate infinitely for n=infinite.
| WJW wrote:
| Is infinite even or odd?
| gpm wrote:
| I can confirm that the rust version of this one is fast:
| playground::isOdd: testq %rdi, %rdi setg %al
| andb %dil, %al retq
|
| (Click ... beside build to get assembly) https://play.rust-
| lang.org/?version=stable&mode=release&edit...
|
| Unfortunately the go playground doesn't seem to support
| emitting assembly?
| bilinguliar wrote:
| Shameless plug to claim Rust superiority!1
|
| No, Go playground can not do that :(
| jeroenhd wrote:
| https://godbolt.org/ supports emitting assembly for Go
| while Google's tools catch up!
| gpm wrote:
| Good point! Neither gc nor gccgo -O seem to figure this
| function out :(
|
| https://godbolt.org/z/eMv41nc6Y
|
| Proof, that you must use rust if you want blazingly fast
| execution of fearlessly pessimized code!
| bilinguliar wrote:
| This commands an issue in the Go repo!
| flakes wrote:
| A true production quality implementation should always use
| recursion. func isOdd(n int) bool {
| switch { case n == 0: return false
| case n > 0: return !isOdd(n-1) default:
| return !isOdd(n+1) } }
| make3 wrote:
| this is truely evil :)
| grishka wrote:
| This will cause a stack overflow. You can convert that into a
| loop and make your own stack on the heap if you need very
| deep recursion.
| oldsecondhand wrote:
| In a language with tail-call optimization, it won't.
| dmurray wrote:
| It will. The negations are only being applied on the way
| back up the call stack. The mutual recursion version in a
| sibling post can be made to work though.
| jeroenhd wrote:
| If you can keep the local variables down, a simple ulimit
| -s 60000000 should be able to get that stack limit nice and
| big!
|
| You may need to call setrlimit with an appropriate
| RLIMIT_STACK, but I think the FFI compatibility should be
| able to pull that off, right?
| someplaceguy wrote:
| > This will cause a stack overflow. You can convert that
| into a loop and make your own stack on the heap if you need
| very deep recursion.
|
| Doesn't Go allocate / extend stacks using dynamic
| allocation rather than having a static limit (e.g. like C)?
| myaccountonhn wrote:
| You can also use beautiful mutual recursion a la ocaml
| let rec isEven n = if n = 0 then true else
| isOdd (n-1) and isOdd n = not (isEven n)
| paulddraper wrote:
| FYI ES2015 added tail-call optimization, allowing JS to
| finally have an elegant isOdd function.
| webstrand wrote:
| Only Safari supports it, though
| stevefan1999 wrote:
| Why do people always got skill issue and can't learn to use
| proper modulo arithmetic? It seems like those "TikTok idiots"
| always get the limelight over this kind of silly thing
| usrbinbash wrote:
| > Running this gives us a nice 40 GB file which contains all 4.2
| billion comparisons needed to determine if any 32 bit number is
| even or odd!
|
| For some reason I am thinking of npm now ...
| foxhop wrote:
| performant != high performance he used it twice so I felt
| compelled to state this
| davidy123 wrote:
| What was really hurting me was all the literal strings "even" and
| "odd." I would have made them into constants. I guess then the
| next step would be to use constants for all the numbers.
| schaefer wrote:
| From the article:
|
| "Now, in a world where AI is replacing programmers by the minute,
| taking their jobs and revolutionizing the way we think about
| code, maybe we should..."
|
| Excuse me ?!?
|
| I get that job loss due to AI is a common fear. But is there any
| hard evidence that the job market is losing "a software
| engineering job a minute" to AI? That's 525600 jobs annually...
| depaulagu wrote:
| I think this is a joke
| schaefer wrote:
| Gotcha. I'll consider myself "swoooshed".
| kolinko wrote:
| He should've used regex for that.
| btdmaster wrote:
| Not as exciting as PCRE checking for primality, but:
| python -c 'import re;print(re.match(r"^(.*)\1$",abs(int(input("
| n=")))*"1")and"Even"or"Odd")'
| MPSimmons wrote:
| This is the kind of insanity I miss from the early internet.
| Excellent job. Thank you for this.
| tcgv wrote:
| > In fact, the above code is a perfect example of a time-memory
| tradeoff
|
| Not as much since the program will take increasingly more time to
| run as the input number gets higher. Checking if a 'small' number
| is even or odd will be pretty fast. Checking a 'large' number
| will be slow since it will go through all 'IFs' until it reaches
| the result.
|
| It's like O(M/2) average time complexity where 'M' is a constant,
| the program memory size (number of 'IFs' stored).
| vitiral wrote:
| I took it as a joke. The tradeoff is the programmer's time and
| memory, not the computer's
| phkahler wrote:
| Clearly they should have optimized using binary search. Use
| nested if-else statements 31 deep. This would require using a
| more sophisticated comparison like < less than instead of equals.
| You'd get a similar amount of code, but it would execute on
| O(logN) instead of O(N). That would surely be the mark of an
| expert. ;-)
| HeavyStorm wrote:
| Why did I waste my time reading this? Hahaha
| dorfsmay wrote:
| That work is amazing!
|
| Now before you laugh at the original meme and the use of AI
| chosing the wrong algorithm, read this:
|
| https://fosstodon.org/@gabrielesvelto/110592904713090347
|
| There is no proof AI was used, but:
|
| > Google's code was allocating 20000 variables in a single frame.
| winddude wrote:
| I to do lots of "researching" on social media.
| Racing0461 wrote:
| > ; add the next 2...2^32-1 comparisons here
|
| Chatgpt is getting so lazy these days.
| asylteltine wrote:
| The TikTok is fake. Obviously it was created to drive engagement.
| Everything you see on TikTok is there to manipulate your
| emotions.
| docfort wrote:
| So I honestly thought that this was going to be another LLM
| article, but using the venerable ReLU activation function instead
| of the usual. A ReLU is exactly an if statement when rendered in
| a decision tree (if less than 0, emit 0; otherwise, emit the
| input). Given the relative popularity of the 4B parameter models
| (any transformer is dominated by the number of parameters in good
| old fully-connected feedforward layers), you can perhaps describe
| such models as 4B if statements. I was disappointed that the
| author didn't go there as a means of parody.
| cchance wrote:
| Not gonna lie, i really thought he was gonna end it with... now
| lets try 64bit, and leave us hanging
| csours wrote:
| My biggest hope for code GPTs is replacing dependencies.
| pbw wrote:
| I like the engineering effort, but it's tainted by puerile
| comments like "visionary genius of Ross van der Gussom".
| kloch wrote:
| This seems dangerously close to spawning a new busy beaver type
| inefficient resource utilization game
| ashvardanian wrote:
| Jokes aside, lookup tables are a common technique to avoid costly
| operations. I was recently implementing one to avoid integer
| division. In my case I knew that the nominator and denominator
| were 8 bit unsigned integers, so I've replaced the division with
| 2 table lookups and 6 shifts and arithmetic operations [1]. The
| well known `libdivide` [2] does that for arbitrary 16, 32, and 64
| bit integers, and it has precomputed magic numbers and lookup
| tables for all 16-bit integers in the same repo.
|
| [1]:
| https://github.com/ashvardanian/StringZilla/blob/9f6ca3c6d3c...
| [2]: https://github.com/ridiculousfish/libdivide
| otteromkram wrote:
| I wish people would stop putting open curly braces on new lines.
| Makes it harder to read, IMHO.
| kazinator wrote:
| That looks like a program developed with TDD that has gone on too
| long without refactoring.
|
| The author probably has a billion individual tests that will all
| lose their value if it were to be simplified, since they would no
| longer correspond to special cases in the code.
| keitmo wrote:
| I'd like to see a fully distributed version. All you need is 4B
| hosts (IPV6 FTW) named N.domain.com (where N varies from 0 to
| 4B-1). The driver app sends N to the first host (0.domain.com).
| Each host compares the incoming N with their N.domain.com name;
| if they match, return the host's true/false value. If they don't
| match, forward the request to (N+1).domain.com and return the
| result.
| koromak wrote:
| Don't give Suckerpinch any ideas
| Someone wrote:
| _N+1_ may overflow; using _N-1_ is more robust.
|
| Also, I think this can easily be implemented; you don't need 4B
| hosts, just 4B DNS entries, and those, you can create with a
| single wildcard entry
| (https://en.wikipedia.org/wiki/Wildcard_DNS_record)
| LASR wrote:
| At 9, I tried to make a game that combined SimCity 2000 and
| Transport Tycoon Deluxe - my favs at the time. I used
| MFC(Windows) because my parents got me a big black book about it.
| My game was a simple train simulator with four trains. Each train
| moved turn by turn to its destination from its origin. Each train
| had to finish its move before the next train had a chance to
| move.
|
| I wrote it in C++ but didn't know much about managing the game's
| state or objects. But there was some fancy acceleration code in
| there.
|
| You "played" the game by modifying the hardcoded x,y coordinates
| in the code and admiring how the trains moved on screen.
|
| I thought real games used multi-threading to move each train at
| the same time. When I tried it, the game broke, probably because
| of UI updates from other threads.
|
| So I never quite built my game. But this project, with all its
| problems, got me into software development years later.
| 1vuio0pswjnm7 wrote:
| "Since I'm a great believer in performant code I decided to
| implement this in the C programming language as it's by far the
| fastest language on the planet to this day (thanks to the
| visionary genius Dennis Richie)."
|
| Fastest portable language. Assembler is faster.
| amai wrote:
| Reminds me of that guy who scrolled to the end of Excel:
| https://youtu.be/sF8k3zl70os
___________________________________________________________________
(page generated 2023-12-28 23:00 UTC)