Logo

Programming-Idioms

  • Fortran
  • Rust
  • Js

Idiom #223 for else loop

Loop through list items checking a condition. Do something else if no matches are found.

A typical use case is looping through a series of containers looking for one that matches a condition. If found, an item is inserted; otherwise, a new container is created.

These are mostly used as an inner nested loop, and in a location where refactoring inner logic into a separate function reduces clarity.

const found = items.some(condition);

if (!found) doSomethingElse();
  found = .false.
  do i=1,size(items)
    if (items(i) == "asdf") then
      found = .true.
      exit
    end if
  end do
  if (.not. found) call do_something

An alternative would be to check the value of the loop variable on exit - if it is larger than size(items), then the exit statement in the loop has not been executed.
items
    .iter()
    .find(|&&item| item == "rockstar programmer")
    .or_else(|| {
        println!("NotFound");
        Some(&"rockstar programmer")
    });

find returns the first Some(T) that satisfies condition, or returns None. We can use or_else to do action when None is returned. If you'd like to do something with found element, use and_then.
let mut found = false;
for item in items {
    if item == &"baz" {
        println!("found it");
        found = true;
        break;
    }
}
if !found {
    println!("never found it");
}

Rust does not have a for...else construct, so we use a found variable.
'label: {
	for &item in items {
		if item == "baz" {
			println!("found");
			break 'label;
		}
	}
	println!("not found");
}

Rust allows you to label scopes, which can then be used together with "break 'label". We can (ab)use this to emulate "for else" loops.
if 'search: loop {
    for i in items {
        if i == &"qux" {
            println!("found it");
            break 'search false;
        }
    }
    break 'search true
} {
    println!("not found!");
}

for within a loop, which is only executed once
if let None = items.iter().find(|&&item| item == "rockstar programmer") {
        println!("NotFound");
    };
(if (seq (filter odd? my-col))
  "contains odds"
  "no odds found")

(seq (filter pred-fn col)) returns nil when there are no matches, and nil is falsy.

New implementation...