I solved the following problem by trial and error, and still have not proper understanding of how i did that.
There is a function cons : const cons = (x, y) => f => f(x, y);
Cons store value to a variable pair : const pair = cons(5, 3);
Create two functions car and cdr which each of them gonna return a argument of each.
car(pair); // 5
cdr(pair); // 3
My solution:
const car = pair => pair((x, y) => x);
const cdr = pair => pair((x, y) => y);
const cons = (x, y) => f => f(x, y);
const pair = cons(5, 3);
const car = pair => pair((x, y) => x);
const cdr = pair => pair((x, y) => y);
const carTest = car(pair);
const cdrTest = cdr(pair);
console.dir(carTest);
console.dir(cdrTest);
It's very difficult to answer how you "did it", since you seem to have stumbled over the answer.
Cheating a bit by inventing a thought process that is never so linear when you don't already know the answer, one way to approach it is to first look closely at what cons
does:
const cons = (x, y) => (f => f(x, y))
It takes two things, (x, y)
, and then returns a function.
This function takes another function f
and returns the result of applying that function to the (x, y)
that cons
was given.
For car
, we want to extract the first element of such a pair.
To select the first element of (x, y)
, we can pass it to the function
const first = (x, y) => x
Since a pair is a thing that takes a function and applies that function to its elements, passing first
to a pair should select its first element:
(cons(3,5))(first)
is 3.
But the syntax is now "backwards", so we use another function to turn it around:
const car = p => p(first)
Substituting the definition of first
:
const car = p => p((x,y) => x)
The same process leads to cdr
.
To see exactly what's happening, you have
const pair = cons(5, 3);
Substitute the definition of cons
:
const pair = f => f(5, 3);
Apply car
to f => f(5,3)
and keep substituting:
(pair => pair((x, y) => x)) (f => f(5,3))
-->
(f => f(5,3)) ((x, y) => x))
-->
((x, y) => x)) (5,3)
--> 5