Date: Fri, 7 Feb 2020 12:21:12 +0000
Nice.
As an example where coroutines don't fit without a suitably sized hammer,
consider a type Dictionary<key_t, value_ts...>, holding a set of
heterogeneous values (I.e. A pythonic dict) mapped by keys (through e.g. a
tuple of tuples), such that the type of element N is static. If you want to
access an element based on a key known only at runtime, the standard
solutions are to either return a std::variant, or to pass in a callback
that can handle every type in the set (value_ts...). Both are fairly ugly,
and the former branches twice - once when the initial decision about the
type to use is made, and once to figure out what the result type actually
was once it has been wrapped up for general use.
A loop over the dictionary would then also apply the same logic. If you
pass a callback F, it can call F with each of the types by recursing over
the stored values (the decision of which function specialisation to jump
into would be known at compilation time). If you return a variant, that
decision is passed over to runtime on every single iteration.
For the issues with templating of the body, I think this might be doable
with a custom block.
with(var result = dictionary.get("my key")){
// the body to specialise
}else{
// handle key not found error
}
On Fri, 7 Feb 2020, 10:40 Lee Howes, <xrikcus_at_[hidden]> wrote:
> This is similar to something that Lewis Baker presented in the last or
> last-but-one meeting relating to the mismatch between the capabilities of
> coroutines and sender/receiver. To apply this change to normal functions
> seems a stretch, but it isn't a completely crazy thing to do for
> coroutines, that are already implemented in terms of callbacks on some
> level and where we already have expectations of a change in semantics.
>
> Code similar to:
>
> template<class T> void bar(T param);
>
> task<void> foo(variant<int, float> param) {
> auto a = co_await param;
> bar(param);
> }
>
> would instantiate bar<int> and bar<float>. The body of foo after the
> co_await could be seen as being generated as a callback for each type the
> compiler generates on the return path from co_await.
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1745r0.pdf has a
> section on heterogeneous resume.
>
> So while sender/receiver is focused on async to some extent, you could
> argue the same of coroutines. Really, though, both of these things are just
> abstractions of callbacks, much as what you are proposing is. I don't think
> we see a clear path to making a compiler work for this, though - the way
> the body of the function would have to be instantiated is a big step from
> the way templates currently work.
>
> Lee
>
As an example where coroutines don't fit without a suitably sized hammer,
consider a type Dictionary<key_t, value_ts...>, holding a set of
heterogeneous values (I.e. A pythonic dict) mapped by keys (through e.g. a
tuple of tuples), such that the type of element N is static. If you want to
access an element based on a key known only at runtime, the standard
solutions are to either return a std::variant, or to pass in a callback
that can handle every type in the set (value_ts...). Both are fairly ugly,
and the former branches twice - once when the initial decision about the
type to use is made, and once to figure out what the result type actually
was once it has been wrapped up for general use.
A loop over the dictionary would then also apply the same logic. If you
pass a callback F, it can call F with each of the types by recursing over
the stored values (the decision of which function specialisation to jump
into would be known at compilation time). If you return a variant, that
decision is passed over to runtime on every single iteration.
For the issues with templating of the body, I think this might be doable
with a custom block.
with(var result = dictionary.get("my key")){
// the body to specialise
}else{
// handle key not found error
}
On Fri, 7 Feb 2020, 10:40 Lee Howes, <xrikcus_at_[hidden]> wrote:
> This is similar to something that Lewis Baker presented in the last or
> last-but-one meeting relating to the mismatch between the capabilities of
> coroutines and sender/receiver. To apply this change to normal functions
> seems a stretch, but it isn't a completely crazy thing to do for
> coroutines, that are already implemented in terms of callbacks on some
> level and where we already have expectations of a change in semantics.
>
> Code similar to:
>
> template<class T> void bar(T param);
>
> task<void> foo(variant<int, float> param) {
> auto a = co_await param;
> bar(param);
> }
>
> would instantiate bar<int> and bar<float>. The body of foo after the
> co_await could be seen as being generated as a callback for each type the
> compiler generates on the return path from co_await.
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1745r0.pdf has a
> section on heterogeneous resume.
>
> So while sender/receiver is focused on async to some extent, you could
> argue the same of coroutines. Really, though, both of these things are just
> abstractions of callbacks, much as what you are proposing is. I don't think
> we see a clear path to making a compiler work for this, though - the way
> the body of the function would have to be instantiated is a big step from
> the way templates currently work.
>
> Lee
>
Received on 2020-02-07 06:24:01