[lambda] extending lambda functions

For some application I need to sum the complex modulus of a collection
of elements.
In short, I want to be able to replace the lambda expression
_1 + bind(&std::norm<double>, _2)
by something more natural like
_1 + llnorm(_2)
For that I use std::accumulate and the lambda library, like in the
next working example;
#include

alfC wrote:
the question is what do I have to do to be able to use the following syntax instead _1 + llnorm(_2)
where llnorm is something I have to define (globally) somewhere else. The question is, how do I have to define llnorm to have the desired effect?
Lambda does not have such a facility. You can use Phoenix instead. Phoenix (lazy) functions allow you to do that. Phoenix is intended to supercede Lambda. Phoenix has been reviewed and is conditionally accepted into Boost after another mini-review. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

Hi Joel,
On Mar 21, 9:49 pm, Joel de Guzman
alfC wrote:
the question is what do I have to do to be able to use the following syntax instead _1 + llnorm(_2)
Lambda does not have such a facility.
Ok, I believe you, I will use bind instead for the moment. However I am still puzzled: for example, when boost::lambda defines some operator+ (the one use above) it does indeed what we expect. What is special about operator+ compared to any other user defined (lazy) function defined by the user? (i.e. the lazy function that I want but don't know how to define in the context of Lambda) After all the operator+ above must be a function defined somewhere.
You can use Phoenix instead. Phoenix (lazy) functions allow you to do that. Phoenix is intended to supercede Lambda. Phoenix has been reviewed and is conditionally accepted into Boost after another mini-review.
I used Spirit a little bit and I recall that Phoenix was part of Spirit or something like that. While we wait for the Phoenix library, would you recommend to use the Phoenix included in Spirit? Thanks, Alfredo

alfC wrote:
Hi Joel,
On Mar 21, 9:49 pm, Joel de Guzman
wrote: alfC wrote:
the question is what do I have to do to be able to use the following syntax instead _1 + llnorm(_2) Lambda does not have such a facility.
Ok, I believe you, I will use bind instead for the moment. However I am still puzzled: for example, when boost::lambda defines some operator+ (the one use above) it does indeed what we expect. What is special about operator+ compared to any other user defined (lazy) function defined by the user? (i.e. the lazy function that I want but don't know how to define in the context of Lambda) After all the operator+ above must be a function defined somewhere.
Because there is only a finite number of operators that we need to overload. OTOH, there's an infinite number of functions. In Phoenix, we take care of only a smallish subset related to STL algorithms and containers (e.g. for_each, etc.). It is easy to add more lazy standard functions if there are would be volunteers.
You can use Phoenix instead. Phoenix (lazy) functions allow you to do that. Phoenix is intended to supercede Lambda. Phoenix has been reviewed and is conditionally accepted into Boost after another mini-review.
I used Spirit a little bit and I recall that Phoenix was part of Spirit or something like that. While we wait for the Phoenix library, would you recommend to use the Phoenix included in Spirit?
Sure, why not? It is a very stable and mature library. Once we deal with the review related matters, there will be some changes, but I don't think it will be drastic. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

Hi Joel,
the question is what do I have to do to be able to use the following syntax instead _1 + llnorm(_2)
Lambdadoes not have such a facility. You can use Phoenix instead. Phoenix (lazy) functions allow you to do that. Phoenix is intended to supercedeLambda. Phoenix has been reviewed and is conditionally accepted into Boost after another mini-review.
Ok, I gave up with Boost.Lambda for defining such "lazy function" and
used Phoenix instead. The process was quite painless. Below is the
(working) code to define a lazy complex modulus function for those who
are interested. I have still two concerns though:
1) I am worried how the lazy function can figure out which version of
std::norm<T> to call to obtain the right result. For
std::complex<double> the lazy function works fine (double is hard
coded). But for std::complex<int> it seems that the lazy function will
always convert the result to double, I couldn't make the lazy funcion
as generic as the original std::norm<T>(std::complex<T> const& c)
function. Is it possible to improve the lazy function definition in
that respect?
(BTW, for std::complex, T == std::complex<T>::value_type)
(It is not that I think std::complex<int> is useful for something but
I thing it is a good example to ask about this).
2) I may be asking for too much sugar but is there a way to name the
function "std::norm" and not have conflicts with the standard
"std::norm<T>(std::complex<T> const& c)", the best I could do was to
call it std::norm_;
The following is the working example, compares the Lambda version with
the Phoenix version (sum5 and sum6):
#include<vector>
#include<iostream>
#include

AMDG alfC wrote:
Ok, I gave up with Boost.Lambda for defining such "lazy function" and used Phoenix instead. The process was quite painless. Below is the (working) code to define a lazy complex modulus function for those who are interested. I have still two concerns though:
1) I am worried how the lazy function can figure out which version of std::norm<T> to call to obtain the right result. For std::complex<double> the lazy function works fine (double is hard coded). But for std::complex<int> it seems that the lazy function will always convert the result to double, I couldn't make the lazy funcion as generic as the original std::norm<T>(std::complex<T> const& c) function. Is it possible to improve the lazy function definition in that respect? (BTW, for std::complex, T == std::complex<T>::value_type)
result is a template, so you just need to specialize it or use some kind of metaprogramming (for instance Boost.Typeof).
(It is not that I think std::complex<int> is useful for something but I thing it is a good example to ask about this).
In fact, according to 26.2 "The effect of instantiating the template complex for any type other than float, double or long double is unspecified."
2) I may be asking for too much sugar but is there a way to name the function "std::norm" and not have conflicts with the standard "std::norm<T>(std::complex<T> const& c)", the best I could do was to call it std::norm_;
You're not allowed to put it in namespace std at all. In Christ, Steven Watanabe

1) I am worried how the lazy function can figure out which version of std::norm<T> to call to obtain the right result. For std::complex<double> the lazy function works fine (double is hard coded). But for std::complex<int> it seems that the lazy function will always convert the result to double, I couldn't make the lazy funcion as generic as the original std::norm<T>(std::complex<T> const& c) function. Is it possible to improve the lazy function definition in that respect? (BTW, for std::complex, T == std::complex<T>::value_type)
result is a template, so you just need to specialize it or use some kind of metaprogramming (for instance Boost.Typeof).
Do you mean that I should do something like (not tested)::
template<class R>
struct norm_impl{
template <typename Arg>
struct result{
typedef R type;
};
template <typename Arg>
typename result<Arg>::type operator()(Arg ar1) const{
return std::norm(ar1);
}
};
template<class R> struct norm{
static(???) phoenix::function
(It is not that I think std::complex<int> is useful for something but I thing it is a good example to ask about this).
In fact, according to 26.2 "The effect of instantiating the template complex for any type other than float, double or long double is unspecified."
Good point, thank you. I should have asked for the std::complex<float> instead.
2) I may be asking for too much sugar but is there a way to name the function "std::norm" and not have conflicts with the standard "std::norm<T>(std::complex<T> const& c)", the best I could do was to call it std::norm_;
You're not allowed to put it in namespace std at all.
Obviously there is a mapping between standard functions and lazy functions (in Phoenix for example), Is there a way to express this mapping in their names? Thanks, Alfredo

AMDG alfC wrote:
result is a template, so you just need to specialize it or use some kind of metaprogramming (for instance Boost.Typeof).
Do you mean that I should do something like (not tested):: template<class R> struct norm_impl{ template <typename Arg> struct result{ typedef R type; }; template <typename Arg> typename result<Arg>::type operator()(Arg ar1) const{ return std::norm(ar1); } }; template<class R> struct norm{ static(???) phoenix::function
func; }; and use norm<double>::func (instead of norm_); How Boost.TypeOf fits in this or other approach?
No. I meant something like this:
struct norm_impl {
template<typename Arg>
struct result {
typedef Arg type;
};
template<typename T>
struct result
2) I may be asking for too much sugar but is there a way to name the function "std::norm" and not have conflicts with the standard "std::norm<T>(std::complex<T> const& c)", the best I could do was to call it std::norm_;
You're not allowed to put it in namespace std at all.
Obviously there is a mapping between standard functions and lazy functions (in Phoenix for example), Is there a way to express this mapping in their names?
Just put them in your own namespace. The ones defined by phoenix are in namespace boost::phoenix for instance. In Christ, Steven Watanabe
participants (3)
-
alfC
-
Joel de Guzman
-
Steven Watanabe