3 ms·
As much as I like Lisp and even pure functional languages (such as my own Fexl), I still like that old-school loopy, branchy, bracey, break-ish, drop-down to th
by fexl 17y ago
As much as I like Lisp and even pure functional languages (such as my own Fexl), I still like that old-school loopy, branchy, bracey, break-ish, drop-down to the iron, procedural feel of straight-up C and even Perl.
You won't get a language war from me, but there's a huge difference in "feel" between those two major language classes, and strangely, I kinda like both of them. Sure I can do some impressive reasoning in the functional realm, but even in the procedural realm I can do iron-clad reasoning and correctness-preserving transforms that (I hope) would make Dijkstra proud.
- arethuza 17y agoMaybe it was just me, but back in the day when I was paid to write Lisp I was pretty fond of the Common Lisp loop macro. So my Lisp code was pretty loopy...
- brazzy 17y agoIt's no coincidence they feel different. The Lisp family of languages was based on theoretical mathematical considerations (Lambda calculus), with implementation as an afterthought. The Fortran family of languages was based on the hardware's capabilities, with theoretical considerations like expressiveness as an afterthought. We are fortunate to have reached an age where we have CPU cycles and RAM to spare so that languages that were not designed with performance-related restrictions in mind are becoming practical for a wide variety of applications.
- fexl 17y agoI concur. Fexl can whip combinators around so fast it makes my head spin. But I still like writing C, even if it's only to write a Fexl interpreter. Consequently the whole purpose of Fexl is to be a thin functional "layer" on top of C. That way as a C programmer I can escape to functions to avoid all the gnarly horrors of memory management and such, and as a Fexl programmer I can escape to C to embrace the hard-edged bits and bytes. That way if you asked me whether I was writing the thing in C or in Fexl, I couldn't really give you a straight answer. ;)
- aaronblohowiak 17y agoOff-Topic: Can you do a fexl vs gambit scheme comparison? I am interested in the interleaving of functional programming and C
- fexl 17y agoSure, I'm reviewing the gambit code a bit. I'm really busy so I'll have to follow up later. Right off the bat I can tell you that Fexl's combinators aim to be written in readable C. I suppose the simplest combinator to show would be "I" (the identity function). In Fexl I have a file named "type_I.c" which says: #include "node.h" #include "type_I.h" static struct node *reduce(struct node *parent) { return parent->RIGHT; } static struct type type = { reduce, clear_pair }; struct node *make_I(void) { return make_pair(&type,0,0); } (Quick note: all node values are reference counted. Cycles are impossible, and unnecessary because of the wonderful Y combinator.) Speaking of Y combinator, here is "type_Y.c": #include "node.h" #include "type_app.h" #include "type_Y.h" static struct node *reduce(struct node *parent) { return make_app(parent->RIGHT,parent); } static struct type type = { reduce, clear_pair }; struct node *make_Y(void) { return make_pair(&type,0,0); } Those are easy. The most gnarly one is the S (fusion) combinator ... which ... oh well I might as well paste it in: #include "node.h" #include "type_app.h" #include "type_S.h" static struct node *reduce(struct node *parent) { if (0 == parent->LEFT->LEFT || 0 == parent->LEFT->LEFT->LEFT) { parent->type = parent->LEFT->type; return parent; } struct node *x = parent->LEFT->LEFT->RIGHT; struct node *y = parent->LEFT->RIGHT; struct node *z = parent->RIGHT; struct node *fun = make_app(x,z); struct node *arg = make_app(y,z); hold(fun); hold(arg); parent->type->clear(parent); parent->LEFT = fun; parent->RIGHT = arg; return fun->type->reduce(parent); } static struct type type = { reduce, clear_pair }; struct node *make_S(void) { return make_pair(&type,0,0); } OK now I'm pushing the limits of long-windedness, but I just wanted to feed you some information right away while I work on some other things.
- fexl 17y agoOh gosh how could I neglect a mention of type_app, the type which represents function application itself? #include "node.h" #include "type_app.h" static struct node *reduce(struct node *parent) { struct node *curr = parent->LEFT; while (curr->type == parent->type) { struct node *self = curr->LEFT; struct node *next = self->type->reduce(curr); if (next != curr) { hold(next); drop(curr); curr = next; } } parent->LEFT = curr; return curr->type->reduce(parent); } static struct type type = { reduce, clear_pair }; struct node *make_app(struct node *f, struct node *x) { return make_pair(&type, f, x); } That "while" loop you see there is essentially the only loop in the entire core of Fexl. (Obviously "plug-ins" can do their own loops.) That loop keeps reducing the parent node as long as it's still of type_app. Then the loop ends and it reduces whatever the parent node has become as a result of the evaluation loop.
- aerique 17y agoI'm a total Common Lisp whore but my code's still pretty procedural and loopy (although not bracey). I use iteration far more than recursion. Like someone else already mentioned the excellent ITER and LOOP macros take care of that. Dunno what all this says about me though :-)