Boost logo

Boost :

Subject: Re: [boost] [mpl] multiset
From: Louis Dionne (ldionne.2_at_[hidden])
Date: 2015-03-11 11:00:30


Eric Niebler <eniebler <at> boost.org> writes:

> [...]
>
> The identity function hack is a little unfortunate, but I understand the
> need for it.

It is, but at the same time, when you start mastering it, it becomes
a powerful way of controlling exactly what should be deferred and what
shouldn't. I agree that for 80% of the use cases, it would be better
if the compiler could just "figure it out" himself.

> What if the two branches return different types? It seems like it
> /should/ work when passed a runtime int like 11, as well as when passed
> a compile-time integral constant wrapper like
> std::integral_constant<int,11>. Is that how it works? That would be nifty.

Having both branches return objects of different types is definitely
possible. Actually, the whole thing was designed to make this possible.
However, in order for the branches to be able to return unrelated
objects, i.e. ones without a common_type, the condition has to be
known at compile-time (e.g. an IntegralConstant). If the eval_if is
passed a runtime Logical (say a bool or an int), then both branches
must return objects with a common_type. For example:

Works:
    std::string s = eval_if(true_, // IntegralConstant condition
        [](auto _) { return std::string{"abcd"}; },
        [](auto _) { return 1; }
    );

    double d = eval_if(true, // bool condition
        [](auto _) { return 3.4; },
        [](auto _) { return 1; }
    );

Fails (std::string and int don't share a common type):
    eval_if(true,
        [](auto _) { return std::string{"abcd"}; },
        [](auto _) { return 1; }
    );

> [...]
>
> Using lambdas for lazy conditionals brings limitations and pitfalls.
> Would you consider adding a pure type-level alternative for people doing
> straight metaprogramming?

I think that might be a good idea. More generally, It might be
possible to provide a mini EDSL for lambda expressions that could
look like Proto's transforms? I'm really just thinking out loud,
but what do you think?

For simple laziness, Hana also has a tool called `lazy`, which allows
creating function calls that can be evaluated later. For example:

    // nothing is evaluated nor instantiated at this point
    auto lazy_result = lazy(f)(x1, x2, x3);

    // everything happens now
    auto result = eval(lazy_result);

Lazy is a Monad, which allows chaining lazy computations as shown
in [1]. However, Lazy is not integrated with eval_if right now, which
makes it pretty much useless. The reason why it is not integrated is
because I think it can also be made a Comonad, and I wanted to see how
lazy branching might be generalizable to arbitrary Comonads.
I haven't had the time to explore this further for now though.

Regards,
Louis

[1]: http://ldionne.github.io/hana/structboost_1_1hana_1_1_lazy.html


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk