Wilson wrote:
> 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!
What you are trying to do is to implement two things in one: a tuple and a+, ld.