in some languages like python, the else
keyword could not only be used in if
, but also in for
and while
loop.
I want to know is there any difficult prevent Rust from adding else
to for
and while
loop?
$ python
Python 3.8.6 (default, Sep 30 2020, 04:00:38)
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> i=3
>>> while i>0:
... i-=1
... else:
... print(i)
...
0
>>>
currently, Rust do not have such syntax, although we could using loop to simulate the while-else
statement, and using map-filter
to simulate the for-else
loop, add both for-else
and while-else
syntax may give rust a more beautiful look.
let mut cond=true;
loop {
if !cond {break {
//else_statement
}}
//loop_body, may contais another break
}
---vs---
let mut cond=true;
while cond{
//loop_body, may contais break
}else{
//else_statement
}
------------------
let mut should_break=false;
iter.filter_map(|&x|{
//loop_body, when need break, set `should_break` to true
if should_break{Some(result)}else{None}
}).next().unwrap_or_else(||{
//else_statement
})
---vs---
for &x in iter{
//loop_body, include break here
}else{
//else_statement
}
if we enable the else
block for for-loop
and while-loop
, we could make Rust more cool than before: using let clause with for
and while
, not just loop
.
let index=for index,x in iter.enumerate(){
//...
if meet_cond{break Some(index)}
}else{None};
before this proposal, we could using the following code instead:
let mut index=None;
for id,x in iter.enumerate(){
//...
if meet_cond{index=Some(id);break}
}
let index=index;
but we could only mark index as mut
, and change it later, which is not cool.
update:
I want to add an else statement is because the actual problem I met:
what I wrote and some accept answers are quite ugly without while-let statement:
//what I wrote
impl Solution {
pub fn find_content_children(mut g: Vec<i32>, mut s: Vec<i32>) -> i32 {
let mut ans=0;
g.sort_unstable();
s.sort_unstable();
let mut g=g.into_iter();
let mut s=s.into_iter();
while let Some(g)=g.next(){
while let Some(s)=s.next(){
if g<=s{ans+=1;break}
}
// if s.next() is none, there is no necessary to check the rest elements in the outer loop
}
ans
}
}
// other accepted answer
impl Solution {
pub fn find_content_children(mut g: Vec<i32>, mut s: Vec<i32>) -> i32 {
g.sort();
s.sort();
let mut i = 0;
let mut j = 0;
while i < g.len() && j < s.len() {// if g is short and s is long, and most of elements in s smaller than it is in g, we have to perform much useless check for the statement `i < g.len()`
if g[i] <= s[j] {
i += 1;
}
j += 1;
}
i as i32
}
}
what we actually need is an else statement here:
impl Solution {
pub fn find_content_children(mut g: Vec<i32>, mut s: Vec<i32>) -> i32 {
let mut ans=0;
g.sort_unstable();
s.sort_unstable();
let mut g=g.into_iter();
let mut s=s.into_iter();
while let Some(g)=g.next(){
while let Some(s)=s.next(){
if g<=s{ans+=1;break}
}else{// if `s.next()` is `None`
break//break the outer loop
}
}
ans
}
}