[proto] The proper way to compose function returning expressions

2012-04-23 Thread Joel Falcou
Let's say we have a bunch of functions like sum and sqr defined on a 
proto domain to return
expression of tag sum_ and sqr_ in this domain. One day we want to make 
a norm2(x) function

which is basically sum(sqr(x)).

My feeling is that I should be able to write it using sqr and sum 
expressions.

Alas it seems this results in dandling reference, crash and some sad pandas.

Then I remember about proto::deep_copy but I have a worries. x is 
usually a terminal
holding a huge matrix like value and I just don't want this huge matrix 
to be copied.


What's the correct way to handle such a problem ? How can I build new 
function returning
expressions built from expression composition without incurring a huge 
amount of copy ?



___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] The proper way to compose function returning expressions

2012-04-23 Thread Eric Niebler
On 4/23/2012 1:01 PM, Joel Falcou wrote:
 Let's say we have a bunch of functions like sum and sqr defined on a
 proto domain to return
 expression of tag sum_ and sqr_ in this domain. One day we want to make
 a norm2(x) function
 which is basically sum(sqr(x)).
 
 My feeling is that I should be able to write it using sqr and sum
 expressions.
 Alas it seems this results in dandling reference, crash and some sad pandas.
 
 Then I remember about proto::deep_copy but I have a worries. x is
 usually a terminal
 holding a huge matrix like value and I just don't want this huge matrix
 to be copied.
 
 What's the correct way to handle such a problem ? How can I build new
 function returning
 expressions built from expression composition without incurring a huge
 amount of copy ?

Right. The canonical way of doing this is as follows:

#include boost/proto/proto.hpp
namespace proto = boost::proto;

struct sum_ {};
struct sqr_ {};

namespace result_of
{
templatetypename T
struct sum
  : proto::result_of::make_exprsum_, T
{};

templatetypename T
struct sqr
  : proto::result_of::make_exprsqr_, T
{};

templatetypename T
struct norm2
  : sumtypename sqrT::type
{};
}

templatetypename T
typename result_of::sumT ::type const
sum(T t)
{
return proto::make_exprsum_(boost::ref(t));
}

templatetypename T
typename result_of::sqrT ::type const
sqr(T t)
{
return proto::make_exprsqr_(boost::ref(t));
}

templatetypename T
typename result_of::norm2T ::type const
norm2(T t)
{
return
proto::make_exprsum_(proto::make_exprsqr_(boost::ref(t)));
}

int main()
{
sum(proto::lit(1));
sqr(proto::lit(1));
norm2(proto::lit(1));
}


As you can see, the norm2 is not implemented in terms of the sum and sqr
functions. That's not really ideal, but it's the only way I know of to
get fine grained control over which parts are stored by reference and
which by value.

You always need to use make_expr to build expression trees that you
intend to return from a function. That's true even for the built-in
operators. You can't ever return the result of expressions like a+b*42
... because of the lifetime issues.

You can't use deep_copy for the reason you mentioned.

I once had a function proto::implicit_expr, which you could have used
like this:

templatetypename T
typename result_of::norm2T ::type const
norm2(T t)
{
return proto::implicit_expr(sum(sqr(x)));
}

implicit_expr() returns an object that holds its argument and is
convertible to any expression type. The conversion is implemented by
trying to implicitly convert all the child expressions, recursively. It
sort of worked, but I never worked out all the corner cases, and
documenting it would have been a bitch. Perhaps I should take another
look. Patches welcome. :-)

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com
___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto


Re: [proto] The proper way to compose function returning expressions

2012-04-23 Thread Joel Falcou

On 04/24/2012 12:15 AM, Eric Niebler wrote:
implicit_expr() returns an object that holds its argument and is 
convertible to any expression type. The conversion is implemented by 
trying to implicitly convert all the child expressions, recursively. 
It sort of worked, but I never worked out all the corner cases, and 
documenting it would have been a bitch. Perhaps I should take another 
look. Patches welcome. :-) 


I think this is an important issues to solve as far as Proto grokability 
does.
One of my coworker on NT2 tried  to do just this (the norm2 thingy) and 
he get puzzled by the random crash.


I think we should at least document the issues (I can write that and 
submit a patch for the doc) and
maybe resurrect this implicit_expr. Do you have any remnant of code 
lying around so I don't start from scratch ?


___
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto