W
Wilson
Hi all,
I recently came across the online video lectures of "The Structure and
Interpretation of Computer Programs". One of the examples, which I
found quite breath taking was their implementation of a pair system
(just two integers stored under one name) out of an anonymous
function.
They define a LISP function to create pairs (called cons), that
naturally takes two integers but returns a function which represents
the pair. They do this by constructing an anonymous function out of
the two parameters (using C style syntax):
cons (int a, int b) {
return lambda (int x) {
if (x==0) return a;
if (x==1) return b;
}
}
Where lambda is just saying "what follows is a function, but there's
no need to name it here". So we could write:
myPair = cons(12,15);
And myPair would then equate to:
myPair(int x) {
if (x==0) return 12;
if (x==1) return 15;
}
They then go on to define two functions to extract the two values,
each taking a function as a parameter and plugging in either 0 or 1:
/* Return the first value of the pair */
car(f){
return f(0);
}
/* Return the second value of the pair */
cdr(f){
return f(1);
}
They build a pair abstraction out of pure code, functional programming
exemplified! I found this very interesting because the system hides
the details of the myPair implementation, placing emphasis on the
interface of the pair object. All that is required of a pair is that
it returns the first value when passed 0, and the second value when
passed 1. The function could simply return the values like above, or
dive into an SQL database or retrieve the values over a network
connection or whatever, and it still behaves ostensibly like any other
pair.
I can imagine it being easily extensible in LISP (I don't know LISP at
all well). If pair represents a coordinate, then we could make 3D
coordinates by defining a function that takes a pair and returns a
function that again takes 1 argument, returning the 3rd coordinate if
the value is 2 or executing and returning the original pair function
with values of 0 or 1:
make3D(pair,int c) {
return lambda (int x) {
if (x==2) return c;
else return pair(x);
}
}
This new 3D point will still play nicely with 2D-aware existing code,
we just need a new function for extracting the 3rd coordinate, easy
enough.
Finally, pairs can have differing implementations but that are all
essentially functions, and thus can be grouped together as if they
were the same type in some sort of collection.
The system just seems to have an elegance about it. I've been thinking
about writing something like this in C, but having trouble getting my
head around it. The problem seems to be with associating the data with
the function: I find myself using structures with function pointers as
my pair implementation, and a malloc'd region to store the parameters
until execution. This is my code so far:
#include <stdio.h>
#include <stdlib.h>
/* Store data together with function pointer */
struct T_Pair {
int *data;
int (*fptr)(struct T_Pair *, int);
};
int simplePair(struct T_Pair *myData, int x){
return myData->data[x];
}
struct T_Pair cons(int a, int b) {
struct T_Pair pair;
pair.data = malloc(2*sizeof(int));
pair.data[0] = a;
pair.data[1] = b;
pair.fptr = simplePair;
return pair;
}
int car(struct T_Pair pair) {
return pair.fptr(&pair,0);
}
int cdr(struct T_Pair pair) {
return pair.fptr(&pair,1);
}
int main(void){
struct T_Pair test;
test = cons(5,4);
printf("First val = %d\n", car(test));
printf("Second val= %d\n", cdr(test));
}
It just doesn't feel right. Can anyone give me any ideas on how to
construct this more neatly, or is mirroring the LISP way just not do-
able in C? I can't find a way of representing my pairs as functions
without having some associated storage for it's values!
Any comments very welcome,
PA Wilson
I recently came across the online video lectures of "The Structure and
Interpretation of Computer Programs". One of the examples, which I
found quite breath taking was their implementation of a pair system
(just two integers stored under one name) out of an anonymous
function.
They define a LISP function to create pairs (called cons), that
naturally takes two integers but returns a function which represents
the pair. They do this by constructing an anonymous function out of
the two parameters (using C style syntax):
cons (int a, int b) {
return lambda (int x) {
if (x==0) return a;
if (x==1) return b;
}
}
Where lambda is just saying "what follows is a function, but there's
no need to name it here". So we could write:
myPair = cons(12,15);
And myPair would then equate to:
myPair(int x) {
if (x==0) return 12;
if (x==1) return 15;
}
They then go on to define two functions to extract the two values,
each taking a function as a parameter and plugging in either 0 or 1:
/* Return the first value of the pair */
car(f){
return f(0);
}
/* Return the second value of the pair */
cdr(f){
return f(1);
}
They build a pair abstraction out of pure code, functional programming
exemplified! I found this very interesting because the system hides
the details of the myPair implementation, placing emphasis on the
interface of the pair object. All that is required of a pair is that
it returns the first value when passed 0, and the second value when
passed 1. The function could simply return the values like above, or
dive into an SQL database or retrieve the values over a network
connection or whatever, and it still behaves ostensibly like any other
pair.
I can imagine it being easily extensible in LISP (I don't know LISP at
all well). If pair represents a coordinate, then we could make 3D
coordinates by defining a function that takes a pair and returns a
function that again takes 1 argument, returning the 3rd coordinate if
the value is 2 or executing and returning the original pair function
with values of 0 or 1:
make3D(pair,int c) {
return lambda (int x) {
if (x==2) return c;
else return pair(x);
}
}
This new 3D point will still play nicely with 2D-aware existing code,
we just need a new function for extracting the 3rd coordinate, easy
enough.
Finally, pairs can have differing implementations but that are all
essentially functions, and thus can be grouped together as if they
were the same type in some sort of collection.
The system just seems to have an elegance about it. I've been thinking
about writing something like this in C, but having trouble getting my
head around it. The problem seems to be with associating the data with
the function: I find myself using structures with function pointers as
my pair implementation, and a malloc'd region to store the parameters
until execution. This is my code so far:
#include <stdio.h>
#include <stdlib.h>
/* Store data together with function pointer */
struct T_Pair {
int *data;
int (*fptr)(struct T_Pair *, int);
};
int simplePair(struct T_Pair *myData, int x){
return myData->data[x];
}
struct T_Pair cons(int a, int b) {
struct T_Pair pair;
pair.data = malloc(2*sizeof(int));
pair.data[0] = a;
pair.data[1] = b;
pair.fptr = simplePair;
return pair;
}
int car(struct T_Pair pair) {
return pair.fptr(&pair,0);
}
int cdr(struct T_Pair pair) {
return pair.fptr(&pair,1);
}
int main(void){
struct T_Pair test;
test = cons(5,4);
printf("First val = %d\n", car(test));
printf("Second val= %d\n", cdr(test));
}
It just doesn't feel right. Can anyone give me any ideas on how to
construct this more neatly, or is mirroring the LISP way just not do-
able in C? I can't find a way of representing my pairs as functions
without having some associated storage for it's values!
Any comments very welcome,
PA Wilson