Hi,
We had some discussion recently about reforming the for-loop syntax
since we'll be switching it to external iterators and it's a bit
deceptive to the user to be writing a lambda-pattern there. Many people
have suggested we use a simple and familiar:
for <pattern> in <expr> { ... }
form. I am inclined to agree with this though I should point out a few
minor concerns:
- It's a new keyword. We've been really, really trying not to do that.
- No-pattern form now requires a dummy pattern. That is, we can't do:
for 10.times { ... }
anymore, rather we have to write:
for _ in 10.times() { ... }
which is possibly unsightly. We can't disambiguate patterns from
exprs just by peeking at them. I don't know. The 10.times thing
always seemed a little clever to me anyways.
- The 'do' form starts to look a little lonely / incongruous. We use
it presently for passing-in-a-closure when a function takes an
optional value, such as:
do hashmap.find_or_insert_with(k) {
def()
}
Given we're discussing macro-izing the other main use of 'do' to
generate an owning thunk Trait object, It's not entirely clear to
me that this pattern alone warrants keeping 'do'.
Anyway, neither of these seem like showstoppers to me, I just thought
I'd mention them in passing in case anyone wanted to chew on possible
solutions (or point out other issues with for .. in that I didn't
picture yet).
I found it more interesting to note that, should we take 'in' as a new
keyword, it's a perfectly reasonable keyword to reuse for the putative
"allocation expressions" we've been talking about needing for supporting
C++-like placement-new. That is, evaluating an expression "into" a bit
of memory provided by one of the operands. This is useful for arenas,
GCs, custom smart pointers and memory pools, etc. We've been somewhat
concerned that we're sealing up the language without the ability to
implement evaluate-into-place forms; evaluating into a local and then
moving into a place doesn't actually work either, due to unknown-sized
types (vectors and such). I think it kinda has to be a built-in expression.
So I'm wondering how this looks for people:
<expr> in <expr>
as a new bottom-precedence binop. The RHS is evaluated first, to a *mut
u8 or perhaps some lang-item trait we define for "the interface to a
memory allocator", then the LHS is "evaluated into it". I do not _think_
it would collide with "for <pat> in <expr>", unless my eyes confuse me.
It might need to be an unsafe expr; not clear.
Any thoughts? Ghastly? Convenient? I don't much like evaluating RHS
before LHS but in this case it seems like it'd be necessary. And lest
you complain that reusing 'in' this way is a comprehension menace, I'd
point out that we reuse several other keywords in differing contexts
('for', 'mod', 'self', 'super') without too much confusion.
-Graydon
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev