mentby.com
Blog | Jobs | Help | Signup | Login

boost lambda for processing std::vector



Hi,

I am trying to understand if boost.lambda is well suited for the quick processing of an std::vector<double>.
I must apologize for my sketchy understanding of the library and this is the reason why I turn to you for
your help.

Imagine that we are given an std::vector<double>, say, x', of some size and that we need to extend x'
somehow to x in order to use it as an argument for some function f.

So, say x' = (3,3,3) and x can be obtained by some map as x = (3,1,3,1,3).

Ideally, this problem would fit into function composition using bind or lambda::bind. Define g(x) = f[x(x')].
The composition operation is standard. What is not for me is how to write the function x(x') using
boost.lambda.

It is always possible to write a quick C++ functor that will encode in its state the map defining how to
generate x from x'. This would typically proceed by constructing a return std::vector<double> to be
populated according to the map. But, can this be done easily with boost.lambda also? I am not sure. I
seem to be finding it difficult to formulate expressions that return types such as std::vectors, while
operating on the vector elements. I can see that the library is well suited to write small functors on the fly
that will operate on container items (as is documented), but when it comes to full containers, I am kind of
stuck. Any attempt seems to be leading to complicated script and dead ends, which makes me think that
I am better off relegating the case to a small C++ functor written elsewhere in the file.

Not sure if you see where I am coming from, but in a functional programming language or a higher level scripting
language such as python, this kind of operation is quite easy to do on the fly. What I am trying to figure out
is how much of the 'in-place definition of code in c++' should reasonably be handled with boost.lambda. Again,
I can clearly see the power of boost.lambda when applied to std::for_each or std::transform, etc..., but I am
not sure how to leverage it beyond that and I haven't seen many examples out there trying to do that either.

Insights and help greatly appreciated,

Many thanks,
ChrisK


CR Koudella Sat, 28 Nov 2009 08:44:35 -0800

Use Boost.Phoenix, it does everything Boost.Lambda does and a lot
more, as well as having vector handling functionality already
built-in.


OvermindDL1 Sat, 28 Nov 2009 18:41:48 -0800

Thanks for your answer. I see, I am pretty out of time here. I will look into phoenix.
Can you provide an indication as to how you would handle my example with phoenix?
That would be of great help.

PS: If this message doesn't end up in the right thread, I apologize. I haven't figured
out how to reply to the list... Do I have to not user list receive messages in a digest,
but receive them one by one?


CR Koudella Sun, 29 Nov 2009 09:25:51 -0800

First, the docs: http://boost-spirit.com/dl_docs/phoenix-2/libs/spirit/phoeni[..]

Second, I am not sure what exactly you are wanting done, wanting to
generate {3,1,3,1,3} from {3,3,3} or something?  Do you have some
pseudo-code?

You did it correct, and yes, receiving one-by-one is much easier.  :)


OvermindDL1 Sun, 29 Nov 2009 17:37:56 -0800

thanks, I have started to look at the doc, but I am not there yet.

imagine we have something like this, without too much thought and excuse
the basic style laid out here:

struct XMapVec
{
public:
XMapVec(const std::vector<double> & vY, const std::vector<unsigned> & vMap)
: _vY(vY), _vMap(vMap), _vBuffer(vMap)
{
}

std::vector<double> operator()(const std::vector<double> & vX) const
{
unsigned nCnt = 0
for (int nI = 0; nI < _vBuffer.size(); ++nI)
{
    if (_vMap[nI])
    {
        _vBuffer[nI] = vX[nCnt];
        ++nCnt;
    }
}

return _vBuffer;
}
private:

// assume _vY same size as _vMap
// the state
std::vector<double> _vY;
// binary Map: if element = 1, then update corresponding entry in _vBuffer
std::vector<unsigned> _vMap;
// set initial state at construction and mutate relevant elements on () call
mutable std::vector<double> _vBuffer;
};

this is not nicely written, but more importantly it is not nice to have this in
a dedicated functor. the question is, how to rewrite this in terms of a lambda
expression, which can then be used in a function composition operation?

thanks,
ChrisK


CR Koudella Sun, 29 Nov 2009 18:15:36 -0800

Looks like an accumulator...
Well a completely lazy version of that could be (using both phoenix and fusion):

std::vector<double> vY;
std::vector<unsigned> vMap;
std::vector<double> vBuffer;

// Assuming vY is the same size as vMap and vBuffer
auto XMapVec    let(_a=begin(vY),_b=begin(vMap),_c=begin(vBuffer),_d=end(vY),_e=(unsigned)0)
    [
        for_(nothing,_a!=_d,(++_a,++_b,++_c))
        [
            if_(*_b)
            [
                (*_c) = _1(_e),
                ++_e
            ]
        ]
    ];

This is not nicely written either, but demonstrates how it can be used anyway.

This is still completely untested, I am still at work.


OvermindDL1 Sun, 29 Nov 2009 18:49:25 -0800

Hi OvermindDL1,

thanks again. You are bringing up yet another library here. I need to do some study.
Will write again.

Thanks,
ChrisK


CR Koudella Mon, 30 Nov 2009 05:54:37 -0800

'generically' using Fusion, but figured to just simplify it with the
example I did give and never took out that Fusion pip I added.  ^.^


OvermindDL1 Mon, 30 Nov 2009 05:58:32 -0800



Related Topics

Post a Comment