
Joel de Guzman <joel <at> boost-consulting.com> writes:
On 2/4/2011 10:36 AM, Gregory Crosswhite wrote:
In conclusion, I have found that Boost.Phoenix is simply too painful to use in practice for most cases where I have been using Boost.Local. Although it could potentially allow for very elegant code in many cases, it is so hard to figure out what you are doing wrong that it seems to be more trouble than it is worth. I am actually a little sad at having arrived at this conclusion, because the library looked incredibly cool and I was very excited about trying it out, and now I am just walking away from the whole experience feeling incredibly frustrated. Furthermore, even if I were an expert in it I have trouble seeing how in most of the places in my code it would result in code that was either more clear or easier to write. The Boost.Local code has extra noise at the beginning, but when the main body of the nested function contains lots of calls it is far more expressive to write the C++ code directly than to use lots of pheonix::bind functions to accomplish the same thing.
This doesn't mean that I think that Boost.Phoenix is a bad library. Reading through the documentation I am absolutely amazed at how it can be used to create very expressive functions; the authors have clearly worked very hard on it and should be proud of their work. However, it simply cannot be treated as invaliding the need for something like Boost.Local, because for one to accomplish many of the same tasks in Boost.Phoenix as one can accomplish in Boost.Local one has to deal with a whole lot of extra mental effort and frustration, and the result at the end is often less expressive and clear (and potentially less maintainable) as it would have been if one had used Boost.Local since the body is no longer expressed in standard C++.
I think what you have shown is a prime example of the clash of two programming paradigms. It became very clear that the examples you've shown just didn't fit in well in the Phoenix programming model. However, Phoenix provides an interface for that as well, phoenix::function ... see Joel's comment. Additionally, I have to agree with you that the error message you experienced lead to a lot frustration. They probably dominated the overall impression you got of the library. These (overly verbose) error messages can be seen as a bug of the library! There are techniques to improve them, however none of these are implemented yet. Ironically, while developing the library, I needed the full exposure of the error messages to debug all the template code ;)
You've just scratched the surface, and IMO, learned about the library in a way that I would not advice. To be honest, I never liked bind -- not a bit. If I did it my way, I'd write small modular phoenix functions just like you would in C++ or any FP language, but are fully curryable and lazy. It's very similar to what Local provides, albeit in C++ syntax instead of macros. By doing so, you avoid overly complex phoenix expressions and work closer to C++ but at the same time get all the benefits of FP.
As I hinted, it is also possible to provide Local like macros to make the code even more concise. Right now, admittedly, phoenix function is more verbose, but it does a lot more and is more flexible.
George, thank you for the effort you put into trying out Phoenix! If it doesn't lead to too much trouble I would like to have a (selfcontained) testcase I can work on to analyze the problems you had and improve either the documentation or fix some bugs you might have run into. I think your experience shows that there is a need for a Troubleshooting section in the docs. Thanks, Thomas