
I was worried that I wouldn't properly express the issues. At least I know I'm an accurate judge of myself. :-) I had hoped to spend some time yesterday working with proto, but I have a deadline Friday. I'm still hoping to get in a few hours tonight, but I wanted to at least post a little follow up even if I can't respond with something more in-depth. I've already written this reply twice to try to ensure that I'm clearly communicating.
1) lazy_vector seemed like it could derive from lazy_vector_expr in CRTP fashion. I figured your use of std::vector<T> as the terminal type was just to make initialization easier;
??? It's a lazy_vector. My use of std::vector<> has nothing to do with initialization. It's to hold a vector of elements.
however, using CRTP fails to compile. Did I miss this in the documentation or is it not explicitly mentioned?
What failed to compile? Can you show me the code?
In your lazy_vector example, you have the following line: V1 += v2 - v3; When I see that line, from the view of the types involved I think, "lazy_vector plus-equals lazy_vector minus lazy_vector". And that's correct. Thus in the expression, I believe that the terminals in this expression are lazy_vector. That's wrong. The terminals in this case are of type std::vector<double>. My first stab at forming a vector type was, roughly: template<typename T> class vector : vector_expr< typename proto::terminal< vector<T> >::type > This fails to compile. So it would appear that the terminals of my expressions cannot be terminals in expressions (so much for clarity in this post!). Thus I need to split my class into two parts: one that stores the data and one that defines the DSEL. I guess my lack of understanding in this case boils down to the question: Why isn't a lazy_vector a terminal in expressions composed of lazy_vectors? I don't see the difference conceptually.
While you can certainly get Proto to build you the type that you want, that's not Proto's natural mode of operation. By default, Proto builds an abstract tree representing the expression, with little or no domain-specific information in it. All the domain-specific knowledge is centralized in your domain's contexts or transforms. The reason I did it this way was to facilitate cross-domain interoperability. The same expression can mean one thing in one domain and something else in a different one. That allows expressions from different domains to be intermingled freely, as with semantic actions (lambda domain) in a grammar (parser domain). Or consider the placeholder terminal _1. You would like that to mean different things to bind, lambda, spirit, karma, phoenix, xpressive, etc. If it were a proto terminal, all these libraries could use the same terminal -- it's just syntax -- and the semantics could vary by library.
I definitely see the potential for handling so many domains. After iterating a few times to figure out how to handle expression trees properly for a single domain, I definitely saw the value in a general-purpose system. It's a gigantic step from a single custom-written system to a general system. I'm very excited to get to the stage where I can play around with transforms as expression optimization was something I wanted to play with before, but I just hadn't gotten around to it yet. The vector class was what I figured would be the gentlest introduction to your library, seeing as I've already written an expression tree handler for it. There are a lot of uses for proto that I see. I'd like to try adapting phoenix to create a library that implements co-routines. There are some interesting possibilities for state machines. I just need more time! Thanks, Noah No virus found in this outgoing message. Checked by AVG. Version: 7.5.519 / Virus Database: 269.22.1/1346 - Release Date: 3/27/2008 10:03 AM