-
Notifications
You must be signed in to change notification settings - Fork 306
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
Change syntax of azip! to be similar to for loops #626
Conversation
I prefer to this verbosity.
I think this confusion is mainly due to |
I have struggled with |
Great idea. Old The new syntax should work just as well for real world arrays that have longer names or expressions to specify themselves. I wonder if we could drop the parenthesis around the patterns and trade that for a mandatory block? Would that work out, like this? azip!(a in array1, &b in array2 { *a = 2.0 * b }); Edit Oh right, I guess that's why we have the in "keyword" in there, and it doesn't work. With this syntax I'm almost missing that the name of the macro does not use "for" somewhere, it would make it easier to read, like "array for a in array1, ..."? |
Here are a few options: azip!((a in array1, &b in array2) *a = 2.0 * b); // a
azip!(for (a in array1, &b in array2) *a = 2.0 * b); // b
azip!(a in array1, &b in array2 => *a = 2.0 * b); // c
azip!(for a in array1, &b in array2 => *a = 2.0 * b); // d
// Require braces around body:
azip!((a in array1, &b in array2) { *a = 2.0 * b }); // e
azip!(for (a in array1, &b in array2) { *a = 2.0 * b }); // f
azip!(a in array1, &b in array2 => { *a = 2.0 * b }); // g
azip!(for a in array1, &b in array2 => { *a = 2.0 * b }); // h
// Move body before loop specification, braces required:
azip!({ *a = 2.0 * b } for a in array1, &b in array2); // i I like all of these except for |
My thinking with syntax has generally been that I want to avoid "noise", especially punctuation. In this: Zip::from(&mut a).and(&b).and(&c).apply(|a, &b, &c| *a = b + c); Every symbol that is punctuation - :: (& ). (& ). (& ). (| , & , & | ); This is what we want to say: Zip from mut a and b and c apply a b c *a = b + c And now you know why I picked some obscure shorthands for However, I didn't exactly like how For the alternatives, a and e seem to be the best. (The arrow versions look neat but less so when we have a multiline loop body, maybe you agree=) Any one of them that are particularly natural to understand for the user? I think all of them are easy to read, I guess it could be tricky to remember how to write all of them. I'm fine with leaving it up to you to pick any variant you'd prefer @jturner314. By virtue of having patterns exposed like in a for loop and without the pipe symbols for the closure, we can say that we reach some level of noise reduction with |
It seems like there is consensus that the approach in this PR is good. I've rebased on the latest I've chosen not to require curly braces around the body expression. The user can always use braces if they prefer, but in simple cases, it's nice not to require the extra noise. |
The
azip!
macro is a common source of confusion for both new and experienced users. I think this is largely due to its unique and somewhat non-intuitive dereferencing behavior. (For example, it's inconsistent that the pattern corresponding tob
is&b
, but the pattern corresponding tomut a
ismut a
. You can see why this is the case (you generally want to dereference in the immutable case but not the mutable case), but it's confusing.)As I see it, the
azip!
macro is useful for two reasons:Zip::from
followed by.and
and.apply
.This PR proposes a new syntax for
azip!
, based on standardfor
loops, that still has both of these qualities:So, for example, you would write
instead of
(This example comes from #625.)
The goal of this new syntax is to match the behavior of
for
loops, which Rust users should be familiar with. Thepat
andexpr
in eachpat in expr
correspond directly to thepat
andexpr
infor pat in expr
:pat
is the pattern of the item, andexpr
is the expression creating the producer/iterator.The special
index
pattern is handled similarly to how it is now, for exampleThe example above does show one disadvantage of this approach compared to the current version of
azip
: it's necessary to write&b in &b
, while in the current version ofazip!
, this would simply beb
. If desired, we could interpret&b
as equivalent to&b in &b
. Unfortunately, that wouldn't help with mutable references (because you don't want to dereference the item in the pattern). IMO, the additional clarity and consistency is worth the additional verbosity in that occurs some cases with this PR.Please let me know what you think!
TODO: Change
par_azip
too.Closes #625.