Context
The german the native web. YouTube Channel hosts a weekly coding challenge for their "Coding Circle" members. It's usually some short task that you can solve in 10-15min and the real value is in the solution videos, which explain the core concepts in depth and often teach you some basics in computer science. Especially if you don't have a "traditional" CS background, stuff like this can be very valuable and the way Golo explains, is IMO really great. If you understand german, it's definitely worth taking a look at the channel and maybe even checking out my live stream with them (also in german).
The Challenge
The challenge is based on the lisp cons concept, which is a function, that holds a pair of data provided as parameters.
A JS implementation of cons
could look like this:
jsconst cons = (a, b) => (f) => f(a,b);
If the above is not completely clear to you, I have a more detailed explanation here.
Step by Step explanation
Rewrite more readable
Let's unwrap this first and for this I'll rewrite it more readable:
jsconst cons = (a, b) => { return (f) => { return f(a, b); }; };
Now let's got through it step by step.
Define a function
First we have a function which takes two parameters a
and b
.
jsconst cons = (a, b) => { return (f) => { return f(a, b); }; };
Return a function
This function returns a function itself, which takes one parameter f
.
jsconst cons = (a, b) => { return (f) => { return f(a, b); }; };
Call the parameter
This parameter f
is itself a function, which get's called with a
and b
.
jsconst cons = (a, b) => { return (f) => { return f(a, b); }; };
Example usage
This is how you could use example:
jsconst pair = cons(3, 4); // pair is now a function returned by cons // let's create a function, which adds two parameters const add = (a, b) => a + b; // call pair with add as a parameter const result = pair(add); // we don't call add, but pass it along console.log(result); // Prints 7 (3+4)
Now back to the challenge.
Car and Cdr
car
and cdr
are two functions closely related to cons
, as they are meant to access the first (car
) and second (cdr
) element of a cons pair. The task is to implement these functions.
The clean solution
I'll just dump the more or less clean solution here, since I don't think they are that interesting and very self explanatory.
Car
jsconst car = (a, _) => a;
Cdr
jsconst cdr = (_, b) => b;
Let's get golfing...
Cdr
I'll start with cdr
, since there's less to do.
jsconst cdr = (_, b) => b; // 24 chars
Remove whitespace:
jsconst cdr=(_,b)=>b; // 19 chars
Use shorter variable declaration:
jslet cdr=(_,b)=>b; // 17 chars
Trust ASI:
jslet cdr=(_,b)=>b // 16 chars
Turn to the dark side, by not declaring your vars:
We need the semicolon on one side, since ASI might be problematic.
jscdr=(_,b)=>b; // 13 chars
But this is a version that will not run in strict contexts like modules, so we'll keep the 16 char version.
Car
jsconst car = (a, _) => a;
Apply all the above from cdr
:
jslet car=(a,_)=>a // 16 chars
Remove unused parameters:
jslet car=(a)=>a // 14 chars
And also the parentheses:
jslet car=a=>a // 12 chars
The dark side would even go further down
jscar=a=>a; // 9 chars
Combining both
We can do even more when doing both by using ,
declarations:
jsconst car = (a, _) => a; const cdr = (_, b) => b;
Short versions:
jslet car=a=>a let cdr=(_,b)=>b
Use ,
:
jslet car=a=>a,cdr=(_,b)=>b // 25 chars
And turn it dark:
jscar=a=>a;cdr=(_,b)=>b; // 22 chars
So in the end the solution for both is shorter than each was on their own in the "clean" version.
By the way, this is the type of thing a minifier would do to your code, to safe bandwidth to your clients.
If you find an even shorter solution, make sure to ping me somewhere and let me know. I love these kind of things.
In case you don't know about Code Golfing, it's trying to write the shortest version of a program. The resulting code is nearly always unreadable, unmaintainable and should never be used in production, but it's often a nice challenge to use stuff you normally wouldn't use and to deepen your knowledge in a language.