-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better choose API #28
Comments
There are two well-formedness issues with this:
|
Unfortunately there doesn't appear to be a way to design the |
Sorry for not getting back sooner... The fn offer() -> Chan<E, P> { ... } But given I'm wondering though if there is a way to combine #23 with this choose API? That way, The error messages reported when selecting an non-existing branch are a little obscure though 😄 <anon>:45:24: 45:39 error: the trait `Chooser<u64>` is not implemented for the type `Finally<()>` [E0277]
<anon>:45 println!("{:?}", a.choose::<u64>());
^~~~~~~~~~~~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
<anon>:45:5: 45:41 note: in this expansion of println! (defined in <std macros>)
<anon>:45:24: 45:39 help: see the detailed explanation for E0277
error: aborting due to previous error
playpen: application terminated with error code 101 |
I implemented this It requires doing...
... in combination with a hack I discovered that allows you to express type inequality ( trait NotSame { }
impl NotSame for .. { }
impl<A> !NotSame for (A, A) { } It was tricky to get the offer side of this working but I did it. It should be possible to prevent something like Choose call: https://github.com/ebfull/nemo/blob/master/tests/lib.rs#L180 The reason I don't think it's possible in your library is that you do not have generic handlers, and it would be messy to try to add them without redesigning a lot of other stuff. |
It's possible in your library without generic handlers. fn whatever(c: Chan<(), Accept<P, Accept<S, Finally<Q>>>>) {
c.accept::<P>(|c| { /* do stuff with Chan<(), P> */ })
.or::<S>(|c| { /* do stuff with Chan<(), S> */ })
.or::<Q>(|c| { /* do stuff with Chan<(), Q> */ });
} This would only require reading a single number from the channel (perhaps only a single byte). The discriminant would be carried through a guard type that There are probably downsides to this approach but it's still cool. |
This is cool 😎 The only potential downside I see, is the use of closures - but they seem necessary in this situation. Historically, Is there a way where we could have both |
I'm not sure there's a way to preserve the current semantics -- it's barely even possible to achieve my design, as it requires a hack that the Rust developers claim should not be possible. Closures though aren't a concern unless you're dealing with recursion, in which case you can't use closures anyway, but you will almost certainly run into stack overflows if you're not careful. |
Right now the path down a
Choose
style decision tree is formed by signaling with booleans over the channel, which is not (space) efficient. Further, you must use macros to avoid having to do a bunch of annoying compositions to select the branches you want.Here's an alternative API which unfortunately requires Rust nightly, but (somehow) works:
Basically, in theory you can just call
chan.choose::<Protocol>()
and it will signal over the channel that you're switching to that protocol using a single number. Perhaps if there's a monomorphization recursion limit anyway, we could use u8 or u16 instead of usize to make the discriminant as small as possible. (Safety note: if the number wraps around it will cause memory safety violations. Perhaps we can use peano numbers to encode a maximum limit here.)Also, I believe with inlining LLVM will completely optimize this away.
The text was updated successfully, but these errors were encountered: