On Wed, Jan 11, 2017 at 6:21 PM, Brook Milligan
On Jan 11, 2017, at 4:34 PM, Brook Milligan
wrote: Now at least I can give it a try. Thanks again for the help.
OK, now that I’m trying it, I have another suggestion. Please include your “customization points” code as an example file in the codebase.
There are already numerous examples of using the customization points in Yap in the tests and eamples.
I started with that and noted that your “make_terminal(user::number({2.0})” bits are missing a template parameter for the expression. I used boost::yap::expression, which seems to work fine. That might be confusing for some users.
There are two overloaded make_terminal() templates. The one that requires no explicit template parameter already uses boost::yap::expression -- it's not missing in the quoted code above.
This brings up some questions. I recall you stating in the docs that boost::yap::expression<> should be used only for prototyping.
I think this will be true for most users.
The Expression concept is really simple and seems mostly to be a type placeholder for overload resolution. Is that fair?
Not exactly. Expression is meant to be the place where you do the important work for your use case. This may include a set of operator overloads that you care about. Ultimately, using a model of Expression in your code allows you to use all the Yap algorithms. That's the most important idea.
If one is not “supposed” to use boost::yap::expression<>, are there any design considerations / best practices for making a custom expression type? For example, it would seem that a common idiom might be an expression class with a function call operator for evaluation. Does that make sense?
Maybe. In the tarray example, there is this member of tarray, which is an Expression: int operator[] (std::size_t n) const { return boost::yap::evaluate(boost::yap::transform(*this, take_nth{n})); } Since tarray does all its significant work when it is indexed, that is the place where it makes the most sense to put the evaluations. For some other type/template, operator() may make sense too.
Are there general features that useful expression classes “ought” to have or at least should be considered in their design?
Not in the general case.
Or are they really just the bare bones of the concept itself?
Yes.
Can you give some guidelines regarding best practices for all of this?
The best guideline I know of is: make your Expression model do exactly what is required for your use case, and no more.
Generally, I feel the documentation is good for a basic understanding and the examples illustrate some very simple use cases. But for anyone wishing to use Yap more deeply, a great deal of extrapolation from those cases will be necessary. It would be really helpful to encapsulate more use cases, common idioms, or best practices in the reference documentation so that practitioners can make more effective use of the library.
I'm assuming that any reader already needs ETs for some reason. I'm not willing to explain what they are and why they are useful, because there are many such articles online already. If someone needs ETs, they already know what their users' code should look like (or they should figure that out first!), and following the many examples will give them a pretty good idea how to use Yap to get the interfaces they need. Zach