221 lines
3.7 KiB
C
221 lines
3.7 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
# define T double
|
|
# define Nil NULL
|
|
|
|
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
|
|
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
|
|
|
|
#define list(...) fromArray((T []){__VA_ARGS__}, NARGS(__VA_ARGS__))
|
|
#define lambda(expr, type, args...) ({ type __fn__ (args){ return expr; }__fn__; })
|
|
|
|
// List datatype
|
|
typedef struct listT {
|
|
T head;
|
|
struct listT* tail;
|
|
}* list;
|
|
|
|
|
|
// String type alias
|
|
typedef char* string;
|
|
|
|
|
|
// Prototypes
|
|
list pure(T x);
|
|
list cons(T x, list xs);
|
|
list snoc(T x, list xs);
|
|
|
|
list take(int k, list xs);
|
|
list drop(int k, list xs);
|
|
|
|
T index_(list xs, int k);
|
|
T head(list xs);
|
|
T last(list xs);
|
|
|
|
list head_(list xs);
|
|
list last_(list xs);
|
|
list tail(list xs);
|
|
list init(list xs);
|
|
|
|
int length(list xs);
|
|
|
|
list map(T (*f)(T), list xs);
|
|
|
|
string show(list xs);
|
|
string show_(list xs);
|
|
|
|
void putStrLn(string s);
|
|
void putStr(string s);
|
|
void print(list xs);
|
|
|
|
list fromArray (T* xs, int n);
|
|
T* toArray(list xs);
|
|
|
|
|
|
// Create singleton list
|
|
list pure(T x) {
|
|
list p = malloc(sizeof (struct listT));
|
|
p->head = x;
|
|
p->tail = Nil;
|
|
return p;
|
|
}
|
|
|
|
|
|
// Append an element before the list xs
|
|
list cons(T x, list xs) {
|
|
list p = malloc(sizeof (struct listT));
|
|
p->head = x;
|
|
p->tail = xs;
|
|
return p;
|
|
}
|
|
|
|
|
|
// Reverse of "cons": append after the list
|
|
list snoc(T x, list xs) {
|
|
list ys = last_(xs);
|
|
ys->tail = pure(x);
|
|
return xs;
|
|
}
|
|
|
|
|
|
// Take the first k elements of xs
|
|
list take(int k, list xs) {
|
|
if (k == 0)
|
|
return xs;
|
|
return cons(xs->head, take(k-1, xs->tail));
|
|
}
|
|
|
|
|
|
// Remove the first k elements of xs
|
|
list drop(int k, list xs) {
|
|
if (k == 0)
|
|
return xs;
|
|
return drop(k-1, xs->tail);
|
|
}
|
|
|
|
|
|
// Return the k-th element of the list xs
|
|
T index_(list xs, int k) {
|
|
if (k == 0)
|
|
return xs->head;
|
|
return drop(k-1, xs->tail)->head;
|
|
}
|
|
|
|
|
|
// Return the first element (head) of xs
|
|
T head(list xs) {
|
|
return xs->head;
|
|
}
|
|
|
|
|
|
// Return last element of the list
|
|
T last(list xs) {
|
|
return last_(xs)->head;
|
|
}
|
|
|
|
list last_(list xs) {
|
|
if (xs->tail == Nil)
|
|
return xs;
|
|
return last_(xs->tail);
|
|
}
|
|
|
|
|
|
// Return every element of xs but the last one
|
|
list init(list xs) {
|
|
if (xs->tail->tail == Nil)
|
|
return xs;
|
|
return init(xs->tail);
|
|
}
|
|
|
|
|
|
// Return xs "tail": everything after its first element
|
|
list tail(list xs) {
|
|
return xs->tail;
|
|
}
|
|
|
|
|
|
// Compute the length of a list
|
|
int length(list xs) {
|
|
if (xs->tail == Nil)
|
|
return 1;
|
|
return 1 + length(xs->tail);
|
|
}
|
|
|
|
|
|
// Apply the function f on every element of xs
|
|
list map(T (*f)(T), list xs) {
|
|
if (xs->tail == Nil)
|
|
return pure((*f)(xs->head));
|
|
return cons((*f)(xs->head), map(f, xs->tail));
|
|
}
|
|
|
|
|
|
// Convert a C array (given its size) into a list
|
|
list fromArray (T* xs, int n) {
|
|
if (n == 1)
|
|
return pure(*xs);
|
|
return cons(*xs, fromArray(xs+1, n-1));
|
|
}
|
|
|
|
|
|
// Convert a list into a standard C array
|
|
T* toArray(list xs) {
|
|
int n = length(xs);
|
|
T x, *p = malloc(n * sizeof(T));
|
|
|
|
for (int i=0; i<n; i++) {
|
|
x = head(xs);
|
|
xs = tail(xs);
|
|
*(p+i) = x;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
// Create a string representation of a list
|
|
string show(list xs) {
|
|
string rep = malloc(2 + 2*length(xs) * sizeof(T));
|
|
sprintf(rep, "[%s]", show_(xs));
|
|
return rep;
|
|
}
|
|
|
|
string show_(list xs) {
|
|
string rep = malloc(2*length(xs) * sizeof(T));
|
|
sprintf(rep, "%f", xs->head);
|
|
|
|
if (xs->tail == Nil)
|
|
return rep;
|
|
|
|
strcat(rep, ",");
|
|
return strcat(rep, show_(xs->tail));
|
|
}
|
|
|
|
|
|
// Print a string to stdout
|
|
void putStrLn(string s) {
|
|
printf("%s\n", s);
|
|
}
|
|
|
|
|
|
// Same as putStrLn without a terminating newline
|
|
void putStr(string s) {
|
|
printf("%s", s);
|
|
}
|
|
|
|
|
|
// Print a list to stdout
|
|
void print(list xs) {
|
|
putStrLn(show(xs));
|
|
}
|
|
|
|
|
|
int main() {
|
|
list x = list(1, 2, 3, 4);
|
|
float (*f)(float) = lambda(sin(2*x)/x, float, float x);
|
|
print(map(f, x));
|
|
}
|