Boost logo

Boost Users :

Subject: Re: [Boost-users] [lambda] extending lambda functions
From: alfC (alfredo.correa_at_[hidden])
Date: 2009-03-23 20:58:39


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<boost/lambda/lambda.hpp>
#include<boost/lambda/bind.hpp>

#include<boost/spirit/phoenix.hpp>

#include<numeric> //for accumulate
#include<complex>

using std::cout;
using std::endl;
using std::complex;
using std::vector;

double sum_norm(double acc, complex<double> elem){
  return acc+std::norm(elem);
}

namespace std{
  struct norm_impl{
    template <typename Arg>
    struct result{
      typedef double type;
    };
    template <typename Arg>
    typename result<Arg>::type operator()(Arg ar1) const{
      return std::norm(ar1);
    }
  };
  phoenix::function<norm_impl> norm_;
}

int main(){

  //create data
  unsigned l=9;
  vector<complex<double> > v(l);
  for(int i=0; i!=v.size(); ++i) v[i]=std::complex<double>(i,1.2+i);

  // using manual loop over array
  double sum1=0;
  for(int i=0; i!=v.size(); ++i) sum1+=norm(v[i]);
  cout<<"sum1 = "<<sum1<<endl;

  // using manual loop over container
  double sum2=0;
  for(vector<complex<double> >::const_iterator it=v.begin(); it!=v.end
(); ++it) sum2+=norm(*it);
  cout<<"sum2 = "<<sum2<<endl;

  //using automatic loop (accumulate) and free function
  double sum3=std::accumulate(v.begin(), v.end(), double(0),
sum_norm);
  cout<<"sum3 = "<<sum3<<endl;

  //using accumulate and lambda with pure bind
  using namespace boost::lambda;
  double sum4=std::accumulate(v.begin(), v.end(), double(0),
                              bind(
                                   std::plus<double>(),
                                   _1,
                                   bind(&std::norm<double>, _2)
                                   )
                              );
  cout<<"sum4 = "<<sum4<<endl;

  //using accumulate and lambda
  double sum5=std::accumulate(v.begin(), v.end(), double(0),
                              _1 + bind(&std::norm<double>,_2));
  cout<<"sum5 = "<<sum5<<endl; // (cout << _1 << " = " << _2 << "\n")
("fancy print sum5", sum5);

  //using accumulate and phoenix
  using namespace phoenix;
  double sum6=std::accumulate(v.begin(), v.end(), double(0),
                              arg1 + std::norm_(arg2) );
  cout<<"sum6 = "<<sum6<<endl;

  return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net