|
Boost : |
From: David Abrahams (dave_at_[hidden])
Date: 2005-11-04 12:35:23
Joel de Guzman <joel_at_[hidden]> writes:
> Comments, feedback very welcome!
> Function
>
> Lazy functions...
>
> #include <boost/spirit/phoenix/function/function.hpp>
>
> The function template class provides a mechanism for lazily
^^^^^^^^^^^^^^
class template
> evaluating functions. Syntactically, a lazy function looks like an
> ordinary C/C++ function. The function call looks familiar and feels
> the same as ordinary C++ functions.
Except you can't use ADL.
> However, unlike ordinary
> functions, the actual function execution is deferred. For example
> here are sample factorial function calls:
Whoa, where did factorial come from?
> factorial(4)
> factorial(arg1)
> factorial(arg1 * 6 / factorial(ref(i)))
>
> These functions are automatically lazily bound
Really? Even the first one?
> unlike ordinary function pointers or functor objects that need to be
> explicitly bound through the bind function (see Bind).
>
> A lazy function works in conjunction with a user defined function
> object (as usual with a member operator()).
I'm lost. What do you mean "in conjunction with?"
> Only special forms of function objects are allowed.
Even more lost! Allowed where?
> This is required to enable true polymorphism
I happen to have a clue as to what you mean, but most won't. Probably
anyplace you mention polymorphism in this doc, you should link to the
discussion of its use in this context.
> (STL style monomorphic functors and function pointers can still be
> used through the bind facility (see Bind)).
>
>
> This special function object is expected to have a nested template
> class apply<T0...TN> (where N is the number of arguments of its
> operator()). The nested template class result should have a typedef
> type that reflects the return type of its operator().
I guess you might be describing the Eval concept. It's not obvious
though. This section needs to be reworked for clarity.
> There is a special case
Of what?
> for functors that accept no arguments. Such nullary functors are
> only required
By what?
> to define a typedef result_type that reflects the
> return type of its operator().
>
>
> Here's an example of a simple functor that computes the factorial of
> a number:
I would avoid "functor" except as a parenthesized note remarking that
function objects are often called functors in the C++ community. That
usage of "functor" is sorta deprecated and probably never should have
arisen, considering its prior use with other meanings.
> struct factorial_impl
> {
> template <typename Arg>
> struct apply
> {
> typedef Arg type;
> };
>
> template <typename Arg>
> Arg operator()(Arg n) const
> {
> return (n <= 0) ? 1 : n * this->operator()(n-1);
> }
> };
>
> (See factorial.cpp)
Oh, here it is. Way too late. Or mentioned too early.
> The functor is polymorphic. Its arguments and return type are not
> fixed to a particular type. The example above can handle any Arg
> type as long as it can carry out the required operations (i.e. <=, *
> and - ).
>
> We can declare and instantiate a lazy factorial function this way:
>
> function<factorial_impl> factorial;
Oh, this is the point of the section? Then why is it called
"Function" set in normal type, instead of "function" set in code font?
> Invoking a lazy function factorial does not immediately execute the function object factorial_impl. Instead, a composite object is created and returned to the caller. Example:
>
> factorial(arg1)
Even in factorial(4) ?
> does nothing more than return a composite. A second function call
> will invoke the actual factorial function. Example:
>
> int i = 4;
> cout << factorial(arg1)(i);
>
> will print out "24".
>
> Take note that in certain cases (e.g. for function objects with
> state), an instance of the functor may be passed on to the
> constructor. Example:
>
> function<factorial_impl> factorial(ftor);
>
> where ftor is an instance of factorial_impl (this is not necessary
^^^^
needs antecedent
> in this case since factorial is a simple stateless functor). Take
^^^^
too many "this"es. Eliminate the first.
> care though when using functors with state because the functors are
^^^^^^ ^
strike ,
> held by value.
I don't think you mean that. I think you mean "Functors are often
copied repeatedly, and the state may be changed in one or more copies,
rather than in the original."
> It is best to keep the data manipulated by a functor
> outside the functor itself and keep a reference to this data inside
> the functor. Also, it is best to keep functors as small as possible.
>
-- Dave Abrahams Boost Consulting www.boost-consulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk