Made a mistake with #iter. It should be:
alt (e) {
  f_normal { }
  f_break | f_continue { fail; }
  f_return(?x) { return x; }
}

----- Original Message -----
> There are approximately 549839483286534 interrelated sub-issues
> currently complicating figuring out how we want to treat
> functions/closures/blocks.
> 
> Patrick, Graydon, and I spent some time yesterday tackling the
> sub-issue of dealing with blocks that can affect control flow, for use
> in iterator functions.
> 
> Originally the plan was that all lambda-blocks could trigger
> break/continue. The downside of this is that it means we need to
> support a block causing a break or continue whenever we call one. It
> also means that blocks would have a different calling convention, so
> to pass a "normal" function to something that can also take a block,
> it needs to be converted. Furthermore, there are a lot of places that
> should be able to take blocks where it doesn't really make sense to
> break and continue (map, for instance: what does map return if the
> block returns early?).
> 
> The proposal we discussed looked something like:
> Make the flow-controlling return value of an iterator-body-block
> explicit by introducing a new type "flow_control" that represents the
> flow-controlling implicit return value of the iterator-body-block.
> Then, the type of a vec_for_each function would be something like
> "fn[T](&fn(&T) -> flow_control, &T[])".
> And then we require that you can call only a function that returns
> flow_control from within a loop. (We could also reify flow_control
> even more, so that you can actually get and create and inspect
> flow_control values, and then have some explicit operation to apply
> the result of a flow_control value.)
> 
> A little trickier is if we want to allow a iterator-body-block to
> force a return of the function that called the iterator. This is
> useful but a little terrifying. It requires that the flow_control
> value be passed through the iterator function and then interpreted by
> the calling function. If we want to be able to force the return of
> some value, then we would probably need to make flow_control
> parameterized, giving flow_control[T]. Furthermore, you want the
> iterator function to propagate the return flow_control but you just
> want the calling function to return without forcing /its/ caller to
> return... You could do something where you inspect the return types of
> the function and use that to figure out what to do, but. I think
> trying to do that while keeping handling of the flow_control value
> completely implicit gets pretty hairy pretty fast.
> 
> Also note that one downside of making explicit the flow_control type
> is that you can no longer directly pass
> 
> ----------------------------------------------------------------
> I have an extension to that scheme that I think fixes up some of these
> issues. My idea is to take the idea of reifying flow_control to its
> extreme, getting rid of most of the special cases.
> 
> We could make flow_control an ordinary tag type and then have
> convenience macros that return the tags as well as a macro that
> interprets a flow_control value and applies it. (All of the things I
> say are macros could also just be language features.)
> 
> so we could do something like:
> tag flow_control[T] {
> f_normal;
> f_break;
> f_continue;
> f_return(T);
> }
> 
> And then we have some simple macros to return the different
> flow_control values, so that #return means "ret f_return" (or don't
> bother and do it explicitly).
> 
> The actual control flow would be handled by some macros (I'm not sure
> what our macro syntax will be like, so I'm making things up):
> The #call_body macro, which is for calling the body of an iterator.
> "#call_body e" would expand to:
> alt (e) {
> f_normal { }
> f_break { break; }
> f_continue { continue; }
> f_return(?x) { return f_return(x); } // propagate the return to the
> caller
> }
> And the #iter macro, which is for calling an iterator function if you
> want to allow the block to trigger a return. "#iter e" would expand
> to:
> alt (e) {
> f_normal { }
> f_break { break; }
> f_continue { continue; }
> f_return(?x) { return x; }
> }
> 
> A full example of this scheme in action:
> fn for_each[T,S](&T[] v, &fn(&T) -> flow_control[S] f) ->
> flow_control[S] {
> for each (x in v) {
> #call_body f(x);
> }
> ret f_normal;
> }
> 
> fn contains[T](&T[] v, &T x) -> bool {
> #iter for_each(v, {|y|
> if (x == y) { #return true; }
> ret f_normal;
> });
> ret false;
> }
> 
> I think this is mostly very clean and unburdensome, except for the
> "ret f_normal"s that are required at the end of all bodies, which is
> an enormous burden. I have two possibilities to solve that:
> 1) The "more principled" solution is to introduce a macro #body such
> that #body {|x1|...|xn| code} becomes {|x1|...|xn| { code } ret
> f_normal;}. contains then becomes:
> fn contains[T](&T[] v, &T x) -> bool {
> #iter for_each(v, #body {|y|
> if (x == y) { #return true; }
> });
> ret false;
> }
> 
> 2) Alternately, we could make it so that there is an implicit "ret
> f_normal" at the end of every function that returns flow_control, in
> the same way that (notionally) there is an implicit "ret ()" at the
> end of every function that returns ().
> 
> I like this solution because I think it effectively captures a really
> handy use of blocks without needing add much "magic" or special cases.
> In particular, I think that making it explicit gives us a good method
> for forcing the return of a value from an iterator body block whereas
> I don't think we had a good way to do that when keeping the control
> flow handling implicit. It also has the advantage that the
> flow_control value can be inspected and handled in custom ways
> (perhaps there is some cleanup that needs to be done before
> returning).
> 
> ------------------------------------------------------------------
> 
> What are people's thoughts?
> 
> -sully
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to