Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

Greenspun's Tenth Rule

Name: Anonymous 2014-04-25 11:23


#include <stdio.h>
#include <stdlib.h>

void *apply(void *callee, int argc, void *argv) {
void **as = (void**)argv;
void *(*f)(void *a,...) = (void *(*)(void *a, ...))callee;

switch(argc) {
case 0: return ((void* (*)())f)();
case 1: return f(as[0]);
case 2: return f(as[0], as[1]);
case 3: return f(as[0], as[1], as[2]);
case 4: return f(as[0], as[1], as[2], as[3]);
default:
printf("apply: number of arguments limit reached\n");
abort();
}
}

int main(int argc, char **argv) {
char *as[] = {"hello %s\n" , "world"};
apply(printf, 2, as);
return 0;
}

Name: Anonymous 2014-04-25 12:38

>>1
If you want to remove the hard limit on the number of arguments passed, check out

http://man7.org/linux/man-pages/man3/stdarg.3.html

Name: Anonymous 2014-04-25 12:42

>>2
Greenspunth's tenth rule demands a half-assed and buggy implementation.

Name: Anonymous 2014-04-25 12:48

>>3
It's an abstraction over something that is easy to do in assembly. It's more of a macro abstraction layer than an implementation of anything.

Name: Anonymous 2014-04-25 13:31

you'll cowards don't even eval

#include <stdio.h>
#include <stdlib.h>

typedef struct datum datum;
struct datum {
enum {ATOM, STR, SEXP, QUOTE, NIL} tag;
union {
char *str;
datum *sexp;
};
};

void *apply(void *callee, int argc, void *argv) {
void **as = (void**)argv;
void *(*f)(void *a,...) = (void *(*)(void *a, ...))callee;

switch(argc) {
case 0: return ((void* (*)())f)();
case 1: return f(as[0]);
case 2: return f(as[0], as[1]);
case 3: return f(as[0], as[1], as[2]);
case 4: return f(as[0], as[1], as[2], as[3]);
case 5: return f(as[0], as[1], as[2], as[3], as[4]);
case 6: return f(as[0], as[1], as[2], as[3], as[4], as[5]);
case 7: return f(as[0], as[1], as[2], as[3], as[4], as[5], as[6]);
default:
printf("apply: number of arguments limit reached\n");
abort();
}
}

void *eval(datum *sexp) {
void *val[8];
int i;

switch(sexp->tag) {
case ATOM:
if(!strcmp(sexp->str, "printf")) {
return printf;
}
else { puts("PROGRAMMER ERRROR"); exit(-1); }
case STR:
return sexp->str;
case QUOTE:
return sexp->sexp;
case NIL:
return sexp;
case SEXP:
{
datum *list = sexp->sexp;
for(i = 0; list[i].tag != NIL; i++) {
val[i] = eval(list+i);
}
apply(*val, i-1, val+1);
}
}
}

int main(int argc, char **argv) {
datum as[] = { { .tag = ATOM, .str = "printf" }, { .tag = STR, .str = "hello %s\n" }, { .tag = STR, .str = "world" }, { .tag = NIL } };
datum apple = { .tag = SEXP, .sexp = as };

eval(&apple);
return 0;
}

Name: Anonymous 2014-04-25 14:29

Code is fine except for a minor detail: You have to use void *() for the type of callee in apply. You can't cast a function pointer to a void pointer. They don't even need to be the same size.

>>5 is impressive!

Name: Anonymous 2014-04-25 14:30

>>1
void *callee
READ DA FUGIN STANDARD

>>5
void *(*f)(void *a,...) = (void *(*)(void *a, ...))callee;

return printf
READ DA STANDARD YA STACKBOY

Name: 6 2014-04-25 14:31

Need to add some macros to make this more Lispy, >>5 -san

Name: Anonymous 2014-04-25 14:32

>>7
You can cast to void *() and call it with an indeterminate number of arguments just fine. Anyway, currying, man.

Name: Anonymous 2014-04-25 14:33

>>6,9
I meant void (*)()

Name: Anonymous 2014-04-25 15:49

>>9
you can't cast a void * to a function pointer, that was my point

Name: Anonymous 2014-04-25 16:23

>>11
No, you can't cast a void* to a function pointer.

Name: Anonymous 2014-04-25 16:27

MUH PDP-10

Name: Anonymous 2014-04-25 16:33

>>13
/backplate getgoes/

Name: Anonymous 2014-04-25 16:46

>>12
NO U

Name: Anonymous 2014-04-25 17:20

someone implement C in LISP now

Name: Anonymous 2014-04-25 17:40

>>16
make your own thread!

Name: Anonymous 2014-04-25 21:12

Greenspun

Shalom!

Name: Anonymous 2014-04-26 1:17

>>12
POSIX requires that this be possible (e.g. for dlsym) even though DA STANDARD itself does not. So in practice you can assume this will work.

Name: Anonymous 2014-04-26 9:34

>>19
POSIX sucks they even forced CHAR_BIT to be 8 and added many useless and bad made functions. they could atleast make dlsym work like this

struct mydik
{
void (*f)(void);
};
struct mydik *shit = dlsym (a, b));
mydik->f ();

Name: Anonymous 2014-04-26 12:41

>>20
that would make soo many stack bois angerey

Name: Anonymous 2014-04-26 19:27

>>20
See >>13.

Anyway, it'd be easier to just have a void (*dlfunc(void *handle, const char *name))(); for code symbols.

Name: Anonymous 2014-04-26 20:34

>>22
Respect the standard faggot

Name: Anonymous 2014-04-26 20:57

why has no one taking this further? no lambda yet?

Name: Anonymous 2014-04-26 21:39

>>24
...

Name: Anonymous 2014-04-26 22:15

>>24
Variable capture is very difficult in C.

Name: L. A. Caluclus !jYCj6s4P.g 2014-04-27 2:03

char ** AINT COMPATIBLE WITH void **, YA CAST LIKE A FUKIN STAK BOI RETOID (void * CAN BE CONVERTED 2 A void ** WITHOUT VIOLATING DA STANDARD), CONVERTIN A POINTER 2 A FUNCTION TYPE 2 A POINTER 2 AN OBJECT TYPE HAS UNDEFINED BEHAVIOUR, CALLIN A int(const char *, ...) THROUGH A void *(*)(void *, ...) HAS UNDEFINED BEHAVIOUR, YA DONT KNO WAT abort DOES, YAINT HERD OF stderr, AND YAINT RED DA FUKIN STANDARD. DATS 4 DAM SURE.

Y DA FUK WUD U WANT TO DO FUNCTIONAL PROGRAMMING IN C ANYWAY, YA FUKIN DIKITA SADCOCK RETOID?

Name: Anonymous 2014-04-27 5:40

>>27
You can't be the original L. A. Calculus. He thought requiring CHAR_BIT == 8 was fine; punning function and data pointers is nothing next to that.

Name: Anonymous 2014-04-27 7:54

>>27
shut up, faggot

Name: Anonymous 2014-04-27 9:05

>>10
wrong!

Name: Anonymous 2014-04-27 10:08

>>5
exit(-1);
The only values that do not cause undefined behavior/implemetation defined behavior are 0, EXIT_SUCCESS and EXIT_FAILURE

Name: Anonymous 2014-04-27 10:48

>>27
hi lambda, this is offtopic but since I saw you I want to ask, what's the point of ptrdiff_t? why not size_t? it seems the same to me

Name: Anonymous 2014-04-27 10:56

>>32
ptrdiff_t has to be a signed integer.
really_large_unsigned_integer - really_low_unsigned integer = overflow when stored in a signed integer of the same width
In practice they're probably the same size on most platforms, since the only way you could get an overflow is by taking the difference of a pointer in kernel space (really high) and user space (really low), and that is not something that you'd ever need to do, but I see where da standed was going with it.

Name: Anonymous 2014-04-27 11:15

>>33
I though that ptrdiff_t was for subtracting pointers to the same object

Name: Anonymous 2014-04-27 11:36

>>34
You could also use it to compare two objects in a heap, two array indices, etc.
Like I said, not a problem on typical 32/64 bit OSes, but imagine a microcontroller or DSP with a 24 or even 16-bit address space. You could easily have an array or heap on such a platform whose length will not fit into a pointer-sized signed integer.

Name: Anonymous 2014-04-27 11:44

>>32-35
http://stackoverflow.com/a/7957001 (don't forget the comments)

Name: Anonymous 2016-10-24 19:00

>>19
Not everything with a C compiler is POSIX compliant.

Don't change these.
Name: Email:
Entire Thread Thread List