
Thanks for your comments. A few quick replies to questions: On Mon, Mar 01, 2004 at 10:10:15PM -0800, Jared Roberts wrote:
I've been generally impressed with the design. There are a few things that bother me. I dislike having to manually promote direct functoids to full functoids. This is particularly sticky if the functoid is recursive, as above. I worked around this at (A) by using a lambda variable to hold the full functoid, but I would have thought there was a better way. If there is, I didn't see it in the documentation. I also
For recursion, you can always just say "make_full1(*this)", but that's still a little big/ugly; it would be nice if you could just say "*this". Alternatively, you can define the whole algorithm inside lambda and use "letrec" to create a recursive function definition.
One thing in particular that seems to have been overlooked by some others about the lambda variables is that they allow you to do a fair amount of type inference! Looking again at the quicksort example, rather than worry about types, I just declared everything lambda and the compiler was able to figure everything out. This is true even for qs_rec, which is bound to the full-functoid version of quicksort to be used in the recursive step at (B). FC++ is able to figure all this out, even though qs_rec isn't bound when declared. It's not quite "auto", but it's pretty cool!
Indeed! I'd never really considered FC++'s lambda/let as a stop-gap solution for the proposed "auto" type inference, but it does kinda accomplish this.
(side note: Is there any reason the lambda() has to be there at all? It seems a bit silly to define a lambda and then immediately evaluate it. Shouldn't the let ideally be able to suffice here?)
Well, "let[...].in[...]" is a lambda expression, so you need some operation to transform it into its value. But yeah, wow, lambda()[ blah ]() is pretty ugly/verbose, and I could easily make just blah() (or something similar) work. Good idea.
The documentation isn't great. [...] I'm still not sure, for example: In the quicksort example again, at (B), there is a recursive call "qs_rec[rights]". Is this call automatically lazy? Or do I have to do something to it? Earlier versions of the code didn't have this part wrapped up in a lambda, and I was able to do thunk1(qs_rec, rights), but I couldn't figure out what I needed to do here. My hunch is that I need to do nothing, but I couldn't find anything that told me so for sure.
It is not lazy. (More precisely, it is not lazy with respect to the lists, which I think is what you want. It is lazy in the sense that it is a lambda expression, and thus will not get evaluated until the lambda is evaluated.) To fix it, just change qs_rec[lefts] %cat% (pivot %cons% qs_rec[rights]) to qs_rec[lefts] %cat% (pivot %cons% thunk1[qs_rec,rights]) Except, that I just tried it and this doesn't work. Doh! Here's a comment in the library implementation: // FIX THIS: the thunkNs are not full functoids. Oh well. Until I find // a need to make them so, I'm not going through the effort. So consider this a bug/oversight, and watch the library author sheepishly slink away to fix it. :) -- -Brian McNamara (lorgon@cc.gatech.edu)