
I don't know what the boost rules are as far as random strangers giving drive-by reviews (do you have to be a member or anything-- feel free to ignore me if I'm out of place), but I thought I'd chime in in case I accidently say something useful. This probably isn't in-depth enough to be a real review, but from what I've seen of FC++, if I had a vote, I would vote to accept FC++ into boost, conditional on the author fixing some things up (non-const refs, dropping the N from fullN, and many of the suggestions by Jonathan Turkanis). * What is your evaluation of the design? To help me evaluate the design, I wrote a few quick client programs to try and get a feel for the 'language'. The most instructive of these, was a quicksort function, modelled after the example given on the haskell home page ( http://www.haskell.org/aboutHaskell.html ): template<typename ordT> struct quicksort : public c_fun_type<list<ordT>, list<ordT> > { list<ordT> operator()(list<ordT> in) const { if(null(in)) return NIL; lambda_var<1> X; lambda_var<2> pivot; lambda_var<3> tl; lambda_var<4> lefts; lambda_var<5> rights; lambda_var<6> qs_rec; return lambda()[ let [ pivot == head[in], tl == tail[in], lefts == comp_m<list_m>()[X | X <= tl, guard[X %less% pivot]], rights == comp_m<list_m>()[X | X <= tl, guard[X %greater_equal% pivot]], /* (A) */ qs_rec == full1<quicksort<ordT> >() ].in[ /* (B) */ qs_rec[lefts] %cat% (pivot %cons% qs_rec[rights]) ] ](); } }; 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 could have had a member typedef quicksort::full or something, but I find that even worse. On a positive note, I really like the explicit lambda syntax. Most of what I've seen from others has stated that it's not as easy to use as boost::lambda, or that it's too verbose. I disagree-- I found it very frustrating to read the boost::lambda documentation and try and remember all these little rules about when to use protect() or unlambda() or constant() or make_const() or whatever. Further, the explicit lambda syntax is much more convienant when constructing nested lambdas, since you can still access variables in the outer scope. It's unfortunate that the variables require a unique integer template parameter, but I don't think this really limits their usefulness. 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! (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?) * What is your evaluation of the implementation? I didn't look at the code enough to have an intellegent opinion on this. Everything I did seemed to work as advertized though, so at least it's relatively bug-free. * What is your evaluation of the documentation? The documentation isn't great. I don't think it's as terrible as some have made out, but there were numerous times I had questions and was unable to find an answer. One of the questions I had did have a solution in the documentation (use make_manip()-- ick), but I didn't find it in the docs before I worked it out on my own. In some cases, 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. * What is your evaluation of the potential usefulness of the library? I think FC++ would be most useful in the business logic portions of applications that contain a heavy amount of interface code to the outside world. My understanding is that FP most shines for the sort of pure-data calculations that you'd normally do in a spreadsheet, Mathematica or S-plus. Using FC++ would make it easer to write bug-free logic (once the dang thing compiles, it's amazing how it seems to just DTRT), while still tying in to a C++ UI, a database, network services and whatever else is easier to do in an imperative way, or for which bindings do not exist for functional languages. Having FC++ as part of boost would help guarantee that the transition from "normal" C++ code to functional C++ code is a smooth one-- or at least that the pitfalls are known. For myself, I look forward most to being able to use lambda library. I know this is probably the part that most overlaps with existing parts of boost, but I think the two libraries have slightly different goals. The boost::lambda library seems most useful when you need a terse little functor to drop into an STL algorithm, whereas the FC++ lambda library seems to be useful who basically see their whole function as one big, nested lambda (which is the FP viewpoint). As I mentioned, I also believe that FC++ strives more for KISS, while BLL aims more for handling the common cases automatically (for example, the overloading of "<<") * Did you try to use the library? With what compiler? Did you have any problems? I used g++ 3.3. The only problem was slow compliation times. And trying to wrap my head around what was going on :) * How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? I've been anxiously awaiting FC++'s introduction to boost since I first found out about FC++ in Brian's review request last summer/fall. I read the papers on his website at that tme and have since revisted them. I also read through the new boost docs and monkeyed around for awhile. If you pushed it all together, it'd probably be a solid couple of days. * Are you knowledgeable about the problem domain? Not really. I had a class in functional programming using SML. I discovered Haskell while listening to a presentation about Functional Images ( now at http://conal.net/papers/functional-images/ ). I then tried to read the Gentle Introduction to Haskell, and got about as far as Monads, when my head promptly exploded. I see FC++ as a good way to approach this again, while staying in familiar territory. * Do you think the library should be accepted as a Boost library? I do. There are a fair number of improvements suggested by others that I don't disagree with, and although some seem larger in scope, when taken in consideration with the overall size of the library itself, I don't think any of the problems is so large as to require a later review before acceptance.