Ask HN: What piece of code/codebase blew your mind when you saw it?
(define (odd? x)
(cond
[(zero? x) #f]
[else (even? (sub1 x))]))
(define (even? x) (cond
[(zero? x) #t]
[else (odd? (sub1 x))]))(define (odd? x)
(cond
[(zero? x) #f]
[else (even? (sub1 x))]))
(define (even? x) (cond
[(zero? x) #t]
[else (odd? (sub1 x))])) send(to, from, count)
register short *to, *from;
register count;
{
register n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}Always love blog posts that cite Knuth.
Then I read it was about loop unrolling, and suddenly it clicked.
arr[index] is equivalent to index[arr]
This works because arr points to the memory location of the zeroth index of the array and index is the offset from that memory location. Since addition is commutative so too is the array notation.
edit: fixed escaped asterisks :-)
Contestants in the International Obfuscated C Code Contest will (and probably already have) find delightful ways to use and abuse this syntactical curiosity.
[0] My one-track mind always wants to jump to pirate jokes.
EDIT: If you like to explore this area, I highly recommend "Expert C Programming - Deep C Secrets" (get the pun? There's a fish on the cover...) by Peter Van Der Linden. It's pretty old (it talks about DOS memory models, among other things), but it is a fun deep dive into the murky corners of C. I wish there was an updated version and/or books covering other languages in that style.
The OCCC is where I learned about this in the first place!
Surely it counts as useful if it could be used to confuse The Enemy. ;)
This is up there for me or there's also that amazing recursive template class for n-dimentional vectorspaces written by Tim Sweeney. I can't find the page anymore but there is reference to it in the archive https://www.flipcode.com/archives/Unrolling_Loops_With_Meta-...
In addition to just the basic loop-unrolling (which I'm pretty sure you usually don't need to do by hand with modern compilers), it works really well when you need to jump into the middle of a pattern. Like if you're sieving primes in a wheel-factorized array.
[1] https://github.com/patricksjackson/primes-cpp/blob/master/pr...
// Here we're only checking possible primes after wheel-factorization
switch ((p.second/num)%30) do {
case 1: target->set(n); n+=num*6;
case 7: target->set(n); n+=num*4;
case 11: target->set(n); n+=num*2;
case 13: target->set(n); n+=num*4;
case 17: target->set(n); n+=num*2;
case 19: target->set(n); n+=num*4;
case 23: target->set(n); n+=num*6;
case 29: target->set(n); n+=num*2;
} while(n <= high - range.first);*to++ = *from++;
https://medium.com/hard-mode/the-legendary-fast-inverse-squa...
also love the story behind it.
https://github.com/mame/quine-relay
(HN thread: https://news.ycombinator.com/item?id=6048761)
https://www.shadertoy.com/view/MdB3Dw
Well, the code itself is simple GLSL. The math is (and I have not verified this) not that complex either, as I believe it's all about integrating the raytracing equation for a moving sphere over the time variable. I guess what I find most impressive is just the fact that it works and that someone even thought of doing that. I also think this is currently the only example of this method being used anywhere, and it might mostly stay that way because the method might not be super generalisable.
Also you may like Marble Marcher made by Code Parade, it's a game that uses a similar approach to rendering: https://youtu.be/9U0XVdvQwAI
In all of the samples there is some iteration constant you can adjust. Take this below a certain threshold and things get really interesting. You can almost reason about how it's all working mathematically by plugging in different iteration counts.
In fact so much of what is on shadertoy looks very familiar to video game 'game physics' programmers because a lot of it is related to collision detection. See the Orange book on real-time collision detection (Christer Ericson) for a lot of good code.
My mind was blown that I could read Apollo 11 source code. It was additionally blown that it included comments like, "# TEMPORARY, I HOPE HOPE HOPE"
https://github.com/chrislgarry/Apollo-11/blob/a13539c7c5c482...
That same week, I had a chat with a friend who at the time was dabbling in audio processing, and we tried to understand how lowpass and hipass filters worked. When we did understand it, I realized they worked basically the same as the image processing operations, just with a temporal aspect to it.
I learned a lot about FIR filters by trying to do room audio correction on my own. That was where the latency tradeoff made itself apparent to me in a very obvious way.
Reading it in a textbook is one thing, seeing/hearing live signals pass through your own filters is another. I think audio lends itself better to experimentation. You can actually construct passive filters and validate your assumptions with live equipment and not spend a dime. You likely already have all of the required gear in your office, short of some spare inductors, capacitors, etc.
Image DSP work can be done entirely on a MacBook on an airplane, but I have personally found the added dimensionality to be less intuitive than with a time-domain signal.
Not to be "that guy" but any linear, translation-invariant operator can be written that way. This is the essence of harmonic analysis.
DSP was easily the most impactful coursework I ever took at university. It applies literally everywhere. Information theory is at the heart of it all, and once you start to see how it all fits together, entire realms of possibilities open their doors to you. In our course we did a lot of image and audio work to help demonstrate that this concept applies to any domain. Discrete/continuous time domain, Some array of bytes on disk, doesn't really matter. You just need some rational way to quantize & sample your data.
Also, as you get into control theory... more matrices! You can use state space representation (a matrix) to represent the entire valid control space of an N-dimensional system (albeit one that is LTI and where N < infinity).
You can read it for free online on his website here: https://www.dspguide.com/ or get a physical copy here https://www.amazon.com/Digital-Signal-Processing-Practical-S...
https://www.amazon.com/Signal-Processing-First-James-McClell...
I don't think this is considered a fantastic book. The professor was simply amazing.
Finally understanding what a negative frequency really meant was an interesting shift in thought.
[1]: https://en.wikipedia.org/wiki/Linear_canonical_transformatio...
My answer would be the jQuery code base, back in the day when that was popular. At the time I didn’t know a whole lot about Javascript or the DOM. I remember it feeling like the kind of code you could just read top to bottom and it was almost like reading a novel. Really well-organized, well-commented, and effective. I don’t know if it’s still like that, but at the time it was transformative for me.
- https://en.wikipedia.org/wiki/Tower_of_Hanoi#Recursive_imple...
I remeber thinking "where's the rest of the code? It surely can't be just those lines!"
My mind is always blown by the tiny demoscene demos.
This is not true with a good compiler that does, e.g., tail call optimization, or is it?
Even in languages where TCO is supported, it's usually not safe to rely on from an engineer's perspective because there is usually no way to reliably assert that TCO is actually applied to any given function.
And again, when they teach recursion in school, they don't normally tell you that it can be unsafe unless your compiler happens to apply TCO or your language explicitly supports tail recursion.
A lot of languages do support TCO. For example, Scala (used by Twitter), OCaml (used by Jane Street for everything, used as the host language for Coq, originally used to implement the Rust compiler), Kotlin, Haskell, Clojure, Lua (used as an embedded language in many places), Elixir, Perl. Not necessarily your popular bread and butter languages but definitely used in production and available if necessary.
Your point that it is generally difficult to know whether TCO is applied is also well-taken. But in OCaml, you can annotate the recursive function call with `[@tailcall]` to verify that the compiler performs TCO.[1] Likewise, you can annotate your functions in Scala.[2] In languages without such annotations, one can get a sense by memory profiling (possibly not emphasized enough in those intro CS courses).
[1] https://v2.ocaml.org/manual/tail_mod_cons.html
[2] https://www.scala-lang.org/api/2.12.1/scala/annotation/tailr...
For modern computers/tablets I have never experienced an issue. Granted, what really matters is your data/recursion level, but even hundreds of recursive calls are not a problem for most applications.
Recursive solutions are usually so much easier to understand than stack/array based looping solutions that they are my go to for things like tree traversals or searching.
A very subjective statement. Yes, your data matters. Also, the scale and security model/trust boundary of your application matters.
Some actual problems with recursion based algorithms:
* They will break unexpectedly as you scale them up.
* They are not memory efficient, so you won't be able to process much in parallel if your data is non-trivial.
* They can make your service trivially DoSable, so now you have to worry about either sanitizing your input or monitoring your stack instead of just timeouts/rate limits.
I've lost track of the number of times I've had to tweak JVM settings, write up security issues, or just straight up tell people things won't work because an academic researcher decided to implement an algorithm with recursion, and then engineers were asked to productize it.
Quick backstory: a feature of Ruby (that you tend to either love or hate) is that you do not need to use parentheses to call a function.
if you have a function like so
def prefix_hello(name)
"hello, #{name}!"
end
you can call it like this prefix_hello "fred"
=> "hello, fred!"
After learning about some of the spiritual ancestors of Ruby (like Smalltalk), message passing, learning everything is just an object and function calls are just messages being sent to objects, a lot of things clicked immediately for me. It was kind of a mind blown moment.Take the `+` (add) symbol in `5 + 3` - in essence, it's just a regular method that is literally caled `def +(number)`, which belongs to the int/number object.
In laymans terms this code is saying, hey object (number) '5', call your + method with '3' as the argument.
You can simulate this in an `irb` shell:
irb(main):001:0> x = 10
=> 10
irb(main):002:0> x.send(:+, 10)
=> 20
It's all right there! `objectA.send(methodName, arg, arg, arg)`Then you realize that this is true of many languages, Python included (__add__)... but I do think Ruby does this in a particularly, ahem, eloquent way that really impressed me.
This moment in my career/learning was almost like a springboard/catalyst and unlocked a lot of additional learning down the road, like getting involved with Erlang and Lisp/Clojure.
Before warching Casey program, it had not occurred to me you could sit down with a compiler and write an entire video game from scratch.
Then, I found out Jonathan Blow sat down and wrote his own compiler, followed by an engine, and now has a game in flight.
It's a truly incredible what these guys (and their teams) get done.
N(|+\)\1 1
I'm not sure where I first saw this snippet (maybe in the Kona documentation) but it stuck with me enough that I was able to recreate it from memory.Last time I checked (a couple of months ago) there wasn't even a formal language spec yet.
I'm working on trying to reach their level (it is reachable) but I sometimes feel like I started with a handicap of comfort from modern OSs and tools
Specifically, Roller Coaster Tycoon, hand-written in x86 assembler by Chris Sawyer.
Edit: guess I could just download it and disassemble ;)
What impresses me though are old Atari games that were implemented in hardware without a microprocessor.
https://justine.lol/ape.html https://github.com/jart/cosmopolitan
It went its own way on a lot of things compared to GNU projects and achieved an enormous level of success for 10-15 years despite some really weird decisions. And even the "wrong" decisions, with hindsight, stemmed from a clear desire to keep creative control and a small codebase. I'd rather read well-documented "bad" code any day of the week.
Since then I've felt a bit of rebellion against standard practice is often a valuable if it's 100% aligned with the goal of your project - reinventing a wheel, ignoring portability, picking a weird language, a new storage format, that kind of thing.
For an engineer it's so easy to get sucked into assuming you should make standard, well-supported, well-understood choices that you suppress your more creative & judgmental instincts.
If you tried something like c = (('d','e','f'),('g','h')) and then a,b = zip(*c) you'd get a = ('d','g') and b = ('e','h'). The 'f' that was originally at c[0][2] is dropped so you can't zip back to the original value of c, unless that's how inverses work for this scenario and my math is rusty.
counter = 1
do highest priority stuff
case counter
when 1, 3, 5, 7, 9, 11, 13, 15
do high priority stuff
when 2, 6, 10, 14
do medium priority stuff
when 4, 12
do low priority stuff
when 8
do lowest priority stuff (1st half)
when 16
do lowest priority stuff (2nd half)
end
counter++
if counter > 16
counter = 1
end
This was called on a timer interrupt.I was like "what the heck does this do?" followed by "that sure reminds me of binary trees" and finally "whoa! cool!"
Especially where the guide explains how tail-call optimization works, my mind was blown.
https://github.com/kanaka/mal/blob/master/process/guide.md#s...
Studying the project changed the way I understand code. Since then I've created my own little Lisps in about three or four versions/languages. Next I'd like to write one in WebAssembly Text format, which is already in a Lisp-shaped syntax.
You'll note that we were busting that clean separation between tokeniser and parser. Yup, sometimes it's hard to DWIM and still stay in your lane.
Just checked and, thanks to the hard work of far smarter people than myself, the whole thing has been refactored and now the better code has better comments. Progress is wonderful! (I couldn't find the weighted guess, so maybe they found a way to work around it)
And, it learned more each time you ran it - even more crazy! It was only when I looked at the source code and realized that it was using self-modifying code that I went, "Wait a minute - THAT'S A THING?"
I had so many of those moments. The very first was realizing you could use an iterator variable to do other things within the loop. That's the exact moment when programming clicked for me. My perception of it changed from being a glorified way to write out steps (like a hair-washing algorithm on a shampoo bottle) to realizing it could be very expressive and flexible.
Other than that, I remember my mind was blown a few times while watching Jim Weirich's presentation on functional programming all those years ago (https://www.youtube.com/watch?v=FITJMJjASUs).
[0] - https://learn.microsoft.com/en-us/archive/blogs/patrick_duss...
I've got several short-lived applications that are extremely latency sensitive and would work flawlessly this way.
It's like trying to enter a house by demolishing it and rebuilding it around you instead of opening the door and walking in.
That said - you're right that it's still slower than constant time
9 is 1 digit, takes 9 steps.
99 is 2 digits, takes 99 steps.
999 is 3 digits, takes 999 steps.
An input d decimal digits long takes O(10^d) steps.
The runtime is exponential in the "size of the input", because the size of the input is usually taken to be the length of the binary or decimal representation of the number rather than the magnitude of the number.
import Data.List (sortBy)
minimum :: Ord a => [a] -> a
minimum = head . sortBy compare
`sortBy` is O(n log n). But `head` only needs the first element which can be found in linear time. So `sortBy` does not compute the rest and `minimum` is O(n).Amazing that someone can write correct, fast code like that.
"The formulae... defeated me completely; I had never seen anything in the least like them before. A single look at them is enough to show that they could only have been written by a mathematician of the highest class. They must be true because, if they were not true, no one would have the imagination to invent them."
I like it because it's so clearly coded - there are no crazy syntax tricks or hacks - it's just obviously the right way to write it. And yet it is compact, elegant and non-obvious if you are writing it yourself.
I used that trick for years until the virus scanners shut down that sort of activity. Sigh. This is why we can't have nice things.
And in just a couple of lines, excuse my quickie untested code:
#include <stdio.h>
#include <stdint.h>
// 5-bit maximal LSFR taps to get pseudo-random sequence of 31 unique numbers in range 1-31
// 0x12, 0x14, 0x17, 0x1B, 0x1D, 0x1E, 0x18, 0x17
int main(int c, char **v) {
uint8_t taps = 0x17; // could be any of the taps above
uint8_t seed = 0x7; // start, could be 1-31
uint8_t lfsr = seed;
do {
printf("%d\n", lfsr);
lfsr = (lfsr & 1)
? (lfsr >> 1) ^ taps
: (lfsr >> 1);
} while ( lfsr != seed );
return 0;
} x ^= y;
y ^= x;
x ^= y;
Check if the number is even: x & 1 == 0I was so surprised, since I had learned the other way first that it is actually easier to teach functional approaches with teenagers.
arr.map(x => x2) was abundantly clearer than
const newArr = [] for(let i, i < arr.length, i++) { newArr.push(arr[i]2) }
And to be perfectly honest, I might have goofed the for loop.
Yeah, you did! It should have used semi-colons. (And HN has lost the carets …)
And I agree completely with you.
And to be perfectly honest, I might have goofed the for loop.
You did, the commas must be semicolons :)
I can't tell you how much time I spent chasing a bug when it was a date that was passed by reference.
Rather than trying to keep track, I just return copies of arrays and objects and it's way easier.
Even a simple
``` function yeppers(input) => ({...input, x: 7}) ```
(An overly simple example)
has made things smoother.
Ok… it’s Footgun prone and callback hell is real.
But I still try to obtain that in other more boring language.
- https://blog.mikemccandless.com/2011/03/lucenes-fuzzyquery-i... - https://www.youtube.com/watch?v=4AbcvHKX8Ow
(Levenshtein distances are used as a measure between fuzzy/misspelled matches, and was ironically misspelled initially - https://lucene.apache.org/core/7_4_0/suggest/org/apache/luce...)
Fortran IV code, thousands of lines, no functions, only GOTOs jumping everywhere randomly. Mostly one or two letter variables, lots of GOTOs that turned out to be loops, with lots more jumping into the middle of them and jumping out of them into other loops. No documentation, I was supposed to modularize it. Failed.
But it successfully calculated thermodynamic properties for engineering designs, so go figure.
I'm pretty sure that if something of the sort had occurred to me before I came across it, I would have thought "that'll never work" and moved on without taking it seriously.
(define (cons x y) (lambda (m) (m x y)))
(define (car z) (z (lambda (p q) p)))
(define (cdr z) (z (lambda (p q) q)))
This implements cons-style linked lists in terms of only functions. In other words lists need not be the fundamental construct of a Lisp/Scheme—you can use functions instead.However, it's rare for that feeling to obtain just by programming in a language. One language that (so far) has consistently had that feeling even when simply programming in it is Dyalog APL.
To think that it's so expressive that naming things is often unnecessary, the name being the function itself.... It feels like I'm playing with raw essence.
+/÷≢ is the classic example, of course. That's four characters -- the "tally" character at the end tends to render wrong in browsers, but I assure you it really is only one character. Four characters! What is the name of the function? Either "Mean", or "Average", one of which is four characters itself, and the other longer. Of course, you could just say, "Avg", but why bother?
And this contains in itself another example. +/ being "Sum", which is longer. And "Product" is an even higher contrast: ×/
This language also has the added mind-blowing feature where the glyphs are often visually related when they are functionally related.
So "Scan" is \. Therefore, "Running Sum" aka "Plus Scan" is +\. Likewise "Running Product" aka "Multiply Scan" is -- you guessed it! -- ×\.
And there is so much more. I've been doing APL for a while now (IDR if it's a full year yet or not, but it's getting close I think), and it keeps blowing my mind over and over again. It's gotten to the point where when writing APL I feel like I'm just spelling out my thoughts for the most part. I've never gotten that feeling in any other language, and it's a mind-blowing feeling.
def to_minutes(df, col):
df[col] = df[col].dt.minutes
return df
(
pd
.read_csv('data.csv')
.assign(dur=df.finish-df.start)
.pipe(to_minutes, col='dur')
.query('dur < 30')
.sort_values(by='dur')
.pipe(
seaborn.relplot,
x='dur',
y='distance',
hue='city'
)
)
It's a simple snippet but the code structure is clever in many ways. The enclosure of the whole expression, starting with pd, into () makes it possible to split method chaining into multiple lines without backslashes and start each line with ".". Now we can treat DataFrame methods similarly to verbs from dplyr data grammar and "." similarly to %>% operator. Its now easy to rearrange, add and delete whole lines without thinking if we forgot to add "." to the line above or below. Everything is immutable, no side effects, it's safe to copy the code in a new notebook cell and tweak it a little without worrying about tens of temporary df2_copy1 variables. The .pipe method allows to avoid "df = df[...]" junk, to reuse code fragments and even to use plotting libraries in ggplot fashion. If the chain becomes huge, just put it in a function and apply in to df using pipe method, etc... I wonder if it's possible to add memorization to pipe method to avoid recalculating the whole construction every time when rerunning the cell during debugging.Winner of 2001 IOCCC:
I was a self-taught programmer as a teenager so there was a lot of theory and mental models I was missing. I viewed code as something static I wrote into an editor and later interpreted (QBasic) or compiled and ran (C).
Learning about function pointers in C was transformational. I started thinking about code as data that can be called and passed around and even changed at runtime and suddenly things like cooperative multi tasking made sense to me.
The regex itself: https://metacpan.org/dist/PPR/source/lib/PPR.pm#L65
Documentation: https://metacpan.org/pod/PPR
> IOCCC Flight Simulator runs on Unix-like systems with X Windows. As per contest rules, it is in the public domain.
https://blog.aerojockey.com/post/iocccsim
Oh, and the code is shaped as a plane. Pretty awesome.
It's a library to read/write java class files. The core at that time would fit into 2 java files.
It was a reader and a writer built around a visitor pattern. At that time apache bcel was also big, a library to build in-memory class file representations which you would then manipulate. ASM allowed you to do many transformation without ever holding the whole file in memory.
ASM also had an in-memory representation as an add-on. It was all nicely layered and the core was just a marvelous small piece of code, with incredible low memory consumption.
https://en.wikibooks.org/wiki/Haskell/Continuation_passing_s...
Here is SPJ giving a talk on them: https://www.youtube.com/watch?v=k-QwBL9Dia0
So, that.
There was a lot of code, about 1.5 million lines over two version of Oracle, which included a bunch of applications as well as the RDMS.
awk '!seen[$0]++'
I know it seems trivial, but back then, it seemed everybody talked about it, there was that coursera course about driving car, the self promotion of towarddatascience.com, video on youtube... but not a single line of code which made sense.
I mean : "Shut the fuck up and show me the actual code !".
I finally found it on github.
I was like : https://www.youtube.com/watch?v=xYHJRhRym1U
#include <stdint.h>
#include <stdio.h>
int main()
{
//the following code should be self-explanatory
int format = 684837;
uint64_t freqs[16] = {4557704611105873944,6293041952211349568,7232032755832676440,9836271091686599272,11342418091143829394,7666925796986299039,8289648};
uint64_t phases[16] = {2745812699376323861,4477710776532278558,4107622644641439798,4062343665106426382,4257685111635071841,2598073413584315427,1713226};
uint64_t composite[32] = {0};
int i = 0;
unsigned char frequency = i[(char*)(freqs)];
unsigned char phase = i[(char*)(phases)];
while (frequency > 0){
for (int j=phase;j<2048;j+=frequency){
(j/64)[composite] |= ((uint64_t)1 << j%64);
}
frequency = (i%64)[(char*)(freqs+i/64)];
phase = (i%64)[(char*)(phases+i/64)];
i++;
}
printf((char*)&format, composite);
return 0;
}On the less functional side, Linux linked lists are super smart.
Years later I could tell my colleagues how a device driver/plugin actually worked (before COM/etc) just with this.
Class.ancestors.include?(Object)
Object.ancestors.include?(Class)
Class.is_a?(Object)
Object.is_a?(Class)
It's beautiful. primes = filterPrime [2..]
where filterPrime (p:xs) = p : filterPrime [x | x <- xs, x `mod` p /= 0]Instead you should use the Sieve of Eratosthenes algorithm. Unfortunately this algorithm is easier to implement in an imperative, eager fashion than in a lazy, functional fashion.
See the paper "The Genuine Sieve of Eratosthenes" for more details: https://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
primes = 2 : filter isPrime [3..]
isPrime x = all (\p -> x `mod` p /= 0) $ takeWhile (\p -> p * p <= x) primes
primes is a list of prime numbers. It is defined as number 2 and numbers 3,4,5... for which isPrime is True.isPrime is a function that checks that x is a prime number by taking numbers whose squares don't exceed x from... primes list... and then making sure they all divide x with a reminder.
It only works because isPrime never touches an unevaluated element of primes list. Otherwise, the program would loop.
λ(λ1 (1((λ1 1)(λλλ1(λλ1)((λ4 4 1((λ1 1)(λ2(1 1))))(λλλλ1 3(2(6 4)))))(λλλ4(1 3)))))(λλ1(λλ2)2)
[1] https://tromp.github.io/cl/cl.htmlUntil this job I hadn't realized how blessed I had been in my career to work at companies that took software development seriously. I can safely say that every instance of "bad code" I had run into previous to this one was really nothing.
I'm not sure how much longer I'll stay here tbh. The place is toxic for a variety of reasons not just the software.
(define (cons x y) (lambda (m) (m x y)))
(define (car z) (z (lambda (p q) p)))
(define (cdr z) (z (lambda (p q) q)))
Then if you really want to go down the rabbit hole, there's SKI, which is lambda calculus without a lambda operator, just 3 named, curried functions(S, K and I, but I is techically definable in terms of S and K). Any function that can be expressed in lambda calculus can be expressed in terms of calling these various functions with eachother as arguments.
Assuming LAMBDA is automatically curried, to save myself some typing:
(define (k x y)
x)
(define (s x y z)
((x z) (y z)))
(define (i x)
x)
Alternatively, I can be defined as follows: (define i (s k k))
SKI is implemented in the Unlambda esolang, with some additional functions defined for IO and convenienceIf variable environments are implemented as hash tables, you're just making a pair out of a hash table. In other words, it's basically equivalent to:
function cons(x, y) {
return { "first": x, "second": y };
}
function car(x) { return x["first"]; }
function cdr(x) { return x["second"]; } (a, b) = (b, a);I'm a total .NET noob, but this attempt in Compiler Explorer shows it not using the xor trick.
https://godbolt.org/z/jhzqxEKzT
Maybe I need some extra compiler flags or something.
If the compiler had decided to put two locals located already in registers, and had the swap in a branch, like so:
if (foo()) {
bar();
(a, b) = (b, a);
}
Then the registers might get swapped with an xchg instruction or something, I don’t know. The compiler’s goal is to have pipelined execution be as fast as possible, so there’s no way it’s going to use bit-mangling operations that would get in the way of that.It better not. The CLR trick introduces a data dependency that slows down the code on modern CPUs.
Compilers sometimes also can compile this down to zero instructions. Nothing says the variable-to-register mapping has to be constant in a single function.
But I guess what really happened is that when you come up writing assembly code at a low level it's a lot more obvious when you've been neck deep in bits, shifts, and logic ops all day.
I still believe in data-dictionaries to drive CRUD instead of crap like C#/Java "annotations" on model classes, but our current tools and languages are not TOP-friendly. I'm convinced TOP is the future, I just don't know when. Some say "you lose type checking", but relational integrity can do much the same thing if set up right. I do personal TOP R&D, but the job is too big for 1 hobbyist.
If you want to call it O(1), by the same approach you could call any finite algorithm O(1).
type Cantor = Natural -> Bit
search :: (Cantor -> Bool) -> Maybe Cantor
that returns in finite time if its argument does.Source: https://math.andrej.com/2007/09/28/seemingly-impossible-func...
function gcd(a,b){ return b ? gcd(b, a%b) : a; }If A is less than B it calls itself with the terms reversed.
I'm a slow learner.
[1] https://www.cs.tufts.edu/~nr/cs257/archive/richard-bird/sudo...
template <typename T>
class Foo {};
class Bar : public Foo<Bar> { ... };
https://en.cppreference.com/w/cpp/language/crtpNow, if it had been declared int, I would probably have been on the lookout for it using something other than 1 or 0 as an error condition, but why bother to explicitly invent a BOOL type and then abuse it that way?
https://matt.might.net/articles/a-normalization/
I've got a fairly good grasp on recursion, but it took some effort to get a mental model of what was going on (k is what to do with the inside thing), because it's doing both recursion and continuation passing at the same time. It feels like a technique that could come in handy someday.
Not code/codebase, but I also want to mention the transform behind bzip:
https://www.hpl.hp.com/techreports/Compaq-DEC/SRC-RR-124.pdf
I understand how it works, but it seems magical that you can sort all of the rotations, take the last column, and still be able to recover the original text.
Anyway, one of the modules had a piece of code that was checking what was in a mailbox, and the name of that function was literally "butWhatIsItThatThereIsInThatMailbox()".
For another project I used Laravel to make a website, and they needed to add a feature after it went to production but I was not working there anymore. I later learned that they just did a "mysql_connect" and ran their query directly in the view's template because they didn't know how to use the framework to make a DB query and pass the data to the view.
And they had HUGE clients that everyone has heard of.
So yeah, mind blowing.
http://scihi.org/ivan-sutherland-computer-graphics/
Ph.D. thesis: - https://dspace.mit.edu/handle/1721.1/14979 (1963 original), - https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-574.{html,pd... (2003 electronic edition)
I was put in charge of the company's email program. This was in 1987-8.
It was a single file, with over 100 KLoC of 1970s-vintage FORTRAN IV code.
Not one single comment.
Variables written like INTEGER A1, for a buffer index.
No subroutines.
GOTOs galore.
That was some trauma that convinced me to write good, structured, well-documented code, from then on.
https://github.com/woodrush/lisp-in-life
Run it in your browser here. Definitely worth zooming all the way in to get a sense of scale.
There's a long-standing TC39 proposal to add it to JS. It's interesting to read it to see examples of the aforementioned differences.
```ocaml
type point = { x: float; y: float};;
let euclidean a a' =
let xd = (a'.x -. a.x) in
let yd = (a'.y -. a.y) in
sqrt ((xd*.xd) +. (yd*.yd))
;;
let is_in_unit_circle x =
x <= 1.
let quadsolve iterations hits =
((4. *. hits) /. Float.of_int iterations)
let estimate iters =
let origin = { x = 0.; y = 0. } in
Array.init iters (fun _ -> { x = (Random.float 1.); y = (Random.float 1.) })
|> Array.map (euclidean origin)
|> Array.map is_in_unit_circle
|> Array.fold_left (fun x y -> if y then x +. 1. else x ) 0.
|> quadsolve iters
;;```
utop # estimate 1000000;;
- : float = 3.141432
Edit: formattingI'd been programming for quite a while at that point, though mostly it was self-taught or procedural/OOP things I had learned in school.
That made a lot of impacts on how I thought about programming; basically until tha point I had never encountered functional programming, and boop it pushed me off a big ol' cliff.
The basic Haskell function definition,
factorial 0 = 1
factorial n = n * factorial (n - 1)Frankly, it still does. Low-mid level graphics code is incredible wizardry.
append([], L, L).
append([H|T], L2, [H|L3]) :- append(T, L2, L3).
Such that the computation can be run in any direction? Where it will produce the result of appending two lists, or the prefixes and suffixes of a list if the result (third parameter) is known, and so on?> a transducer is recognizing that the signature of foldl splits
> type Transducer a b = forall r. (r -> b -> r) -> (r -> a -> r)
> they compose like lenses
The guy is a literal genius, I hope to forget half the stuff he knows.
Also Fabrice Bellard (ffmpeg/qemu) and Inigo Quilez.
made me realize how much knobs are there in writing a data to bytes encoding function.. you get to pick a trade off between readability, ease of implementation (in other language), encoding speed, encoding output size, and more.
And I feel I’ve worked on that codebase …
1. The entry does not contain any words
2. The entry contains knowledge that can be easily understood
3. The knowledge inside the entry cannot be transliterated into words (even here)
The entry: https://scp-wiki.wikidot.com/scp-2521
Prior to the rewrite it had a bunch of global state and someone on the team I contracted on had decided to use it anyway but patch things up so it could work with multiple edit panes in the same UI.
I once worked with an old Perl greybeard, he had written some kind of code that could parse an almost impossible large set of string formats that a large collection of automated systems produced except they all had some sort of non-standard/non-guaranteed formatting or semantics. Little bits and pieces (some semi-atomic bits) of them were semi-reliable, but the aggregate strings were just a huge mess, things came in all kinds of orders, had unreliable separators (if any) some things came in backwards, some forwards, and so on.
You might imagine them to be things like IP addresses that sometimes had system names attached, sometimes locations, sometimes, no address, sometimes the address was separated by dots or commas, sometimes, pieces of equipment were listed. All legacy of decades of people slowly accruing bits and pieces of the larger system and naming things for local convenience rather for global understanding. As the systems rolled up these strings would sometimes get concatenated in different ways and in different orders.
His code looked like total gibberish, a library of a bunch of code that sort of looked like Perl but also sort of looked like a custom rule language, it had something like 1200 rules in it based on the kinds of "atomics" he'd observed. The rules were sort of pieces of regexes, and then a string with embedded functions in it.
And then some bizarre code elsewhere I also didn't get at first.
It turned out the code was clever way of writing a meta program that would assemble new code on the fly that was capable of processing every possible string format -- potentially billions of them. At the core of the code was simple lexer that atomized the strings based on a few heuristics (nonstandard of course), and then would apply the rules to each lexical piece.
It turns out the rules were regexes that emitted code snippets on match. The snippets were often templated to take pieces of the atomic bits and the regex would parse the atom and put the pieces into the snippet.
There was some simple logic to assemble all of the emitted code into a "program" that when eval()'d would generate an output object that had all of the components of the original string, but also decoded, enriched, normalized, and ready for downstream work.
In the rare case an "atom" was encountered the system didn't have a "rule" for, it would throw an error and dump the string out to a file where he'd take a look at it, and in about 30 seconds slap in a new "rule" to handle the case forever more.
The entire codebase was maybe the rules and a couple hundred more lines of code -- maybe 1400-1500 lines. Written in a few weeks, processing tens of millions of strings per day, silent and forgotten in the bowels of some giant enterprise automation system.
It, running on a Pentium II or III of some kind, had replaced a rack of Sun Pizza boxes, and an old codebase setup by a consulting company that went down or garbled the processing of the strings at least once a week and required two full-time people to keep running. When the company had a downturn they laid off that team and in a fit of desperation the greybeard had come up with this little monster -- the beauty of which was under 5 minutes of maintenance per week to check logged errors and write a new rule if needed.
edit ahh here's the video https://youtu.be/r-A78RgMhZU
https://github.com/elixir-lang/elixir/blob/main/lib/elixir/l...