How does one iterate in for loops in parallel?

I'm trying to write my own which(1) and I discovered, that iterating over loops is faster. What's the most idiomatic way of iterating over

  1. std::env::args() and
  2. std::str::Split in Rust?

I come from the land of D and I would iterate over std::env::args this way:

import std.stdio : writeln;
import std.process : environment;
import std.path : dirSeparator, pathSeparator;
import std.algorithm : splitter;
import std.file : exists;
import std.parallelism : parallel;

pragma(inline, true) void findPrint(in ref string toFind) {
	foreach (path; environment.get("PATH", "").splitter(pathSeparator)) { // parallelism here is not trivial
		const auto probe = path ~ dirSeparator ~ toFind;
		if (exists(probe)) {
			writeln(probe);
			break;
		}
	}
}

void main(in string[] args) {
	if (args.length < 3)
		foreach (arg; args[1 .. $])
			findPrint(arg);
	else
		foreach (arg; args[1 .. $].parallel()) 
			findPrint(arg);
}

To add, my single threaded solution insofar is:

use std::io::Write;

fn main() {
    let stdout = std::io::stdout();
    let mut lock = stdout.lock();
    for arg in std::env::args().skip(1) {
        for path in std::env::var("PATH").unwrap().split(':') {
            let mut probe = std::path::PathBuf::from(path);
            probe.push(&arg);
            if probe.exists() {
                lock.write_fmt(format_args!("{}\n", probe.display())).unwrap();
                break;
            }
        }
    }
}

Rust's for loops don't have any magic, they're just single threaded while let Some(item) = iter.next() {}.

Change the code to be an iterator (using filter_map(), for_each(), etc.), and then parallelize it with rayon.

1 Like