[rust-dev] bikeshed on closure syntax

Patrick Walton pwalton at mozilla.com
Wed Apr 18 08:14:01 PDT 2012


On 04/18/2012 06:46 AM, Niko Matsakis wrote:
> On 4/17/12 10:35 PM, Grahame Bowland wrote:
>> Hi Patrick
>>
>> Thanks for the visual example. I prefer the old { |x| } style. It
>> might look slightly ugly but glancing upwards from a piece of code I
>> find it much easier to spot that a given pair of braces are a block
>> closure. I guess || sticks out like a pair of thumbs, which is useful.
>
> I have to admit, even I prefer the "|x|" to ": x {" when I see it laid
> out like that. They are much easier to spot.

Yeah, I have to agree. If we want a minimal delta on the current syntax 
that addresses issues (1) and (2) (and I'm not insisting that we address 
them, mind you), how about this?

Change the current function call syntax to:

     Call ::== Primary '(' Args ')' (':' BlockLambda (',' BlockLambda)*)?

And change BlockLambda to:

     BlockLambda ::== '->' Expr
                    | '|' InferredArg (',' InferredArg)* '|' Expr

It establishes a fairly simple set of rules:

1. Bars indicate a closure.

2. A thin arrow indicates a zero-argument thunk.

3. In any function call, trailing closure arguments can be pulled out 
and placed after a colon. If this is done, the semicolon statement 
separator after the call can be omitted.

So we would have:

     #[inline(always)]
     fn get_rand_env() -> rand_env {
         let rng = rand::rng();

         let disk_samples = vec::from_fn(513): |x| {
             // compute random position on light disk
             let r_sqrt = rng.next_float().(f32).sqrt();
             let theta = rng.next_float().(f32) * 2.0 * f32::consts::pi;
             (r_sqrt * theta.cos(), r_sqrt * theta.sin());
         }

         let mut hemicos_samples = []/~;
         for uint::range(0, NUM_GI_SAMPLES_SQRT): |x| {
             for uint::range(0, NUM_GI_SAMPLES_SQRT): |y| {
                 let (u, v) = ((x.(f32) + rng.next_float().(f32)) /
                               NUM_GI_SAMPLES_SQRT.(f32),
                               (y.(f32) + rng.next_float().(f32)) /
                               NUM_GI_SAMPLES_SQRT.(f32));
                 hemicos_samples.push(cosine_hemisphere_sample(u, v));
             }
         }

         {
             rng: rng,
             floats: vec::from_fn(513, |_| rng.next_float().(f32)),
             disk_samples: disk_samples,
             hemicos_samples: hemicos_samples
         };
     }

Patrick


More information about the Rust-dev mailing list