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
Use Boost.Phoenix, it does everything Boost.Lambda does and a lot
more, as well as having vector handling functionality already
built-in.
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?
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. :)
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
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.
Hi OvermindDL1,
thanks again. You are bringing up yet another library here. I need to do some study.
Will write again.
Thanks,
ChrisK
'generically' using Fusion, but figured to just simplify it with the
example I did give and never took out that Fusion pip I added. ^.^