start | find | index | login or register | edit
Montag, 6. Juli 2009 link

Sometimes, being pointless point-free is annoying. And, there's C++:

accumulate(I->begin(), I->end(), 0, compose2(plus<int>(),
identity<int>(),
mem_fun(&C::F)));

Update: the above is nonsense (as in: won't compile). Problem is, compose2 composes one binary and two unary functions such that:

compose2(f, g, h)(x) = f(g(x), h(x)).

What I want/need is a similar functional F such that:

F(f, g, h)(x, y) = f(g(x), h(y)).

Any hints? How'd you call that, does it exist already? I know about Boost's rather versatile bind, but that doesn't meet the point-free criterion.

Update: In lack of a better name, let's call it compose3:

#include <functional>

template <typename F, typename G, typename H>
struct compose3_t : public std::binary_function<typename G::argument_type,
typename H::argument_type,
typename F::result_type> {
F f;
G g;
H h;

compose3_t(const F &f, const G &g, const H &h): f(f), g(g), h(h) {}

typename F::result_type operator()(const typename G::argument_type &x,
const typename H::argument_type &y) const {
return f(g(x), h(y));
}
};

template <typename F, typename G, typename H>
compose3_t<F, G, H> compose3(const F &f, const G &g, const H &h) {
return compose3_t<F, G, H>(f, g, h);
}

Now if we replace compose2 with compose3 in the original example, it will compile and work as expected/desired.

For illustration purposes, the same thing in Haskell:

compose3 :: (a -> b -> c) -> (u -> a) -> (v -> b) -> u -> v -> c
compose3 f g h x y = f (g x) (h y)

foldl (compose3 (+) id (f)) 0 v

Finally, let's let go of the insane hiding of points, but simply use lambdas (using boost::bind for the C++ version):

C++:
accumulate(V->begin(), V->end(), 0, bind(plus<int>(), _1, bind(F, _2)))

Haskell:
foldl (r x -> r + f x) 0 v

K:
0 {x+f y}/v

If we relax things further, to allow a temporary vector being created, this simply collapses to:

Haskell:
sum map (f) v

K:
+/f v

Q:
sum f v

Which concisely describes what the original piece of code was intended to achieve: sum a list element-wise transformed by a function.


themel 5399 days ago:
Ha, that's why I love C++ so much ever since I made the mistake of learning a couple of functional languages.

You can do whatever the hell you want, but

- it takes approximately forever for the added elegance of your nice language extensions to pay off the disgustingness of the template wonkery to enable them because the stupid/ugly syntax eats about 90% of the beauty of the idea
- the next person touching that code will just throw it away and rewrite in what I lovingly call "copy-paste C++", where everything that doesn't fit a for loop is just spelled out in brute force.

Please log in (you may want to register first) to post comments!

powered by vanilla
echo earlZstrainYat|tr ZY @.
earl.strain.at • esa3 • online for 8446 days • c'est un vanilla site