Add .foreach method to Iterators for side effects


#1

Using .map for side effects and not using the result might give warnings, and it’s not good practice to do side effects on map. Adding .foreach sugar clearly states the intention of performing an action just for the side effects.

It was suggested on IRC to discuss this change here. It has also been discussed on reddit:

See the related pull request:


#2

I’m a big fan of this. I don’t like having to have a variable to save the iterator and then switch to the for-style loop when I have big chains of iterator adapters.


#3

I’m not against it if and only if iterator.foreach(cb).filter(another_cb).foreach(last_cb) is made possible by this. foreach should be something like map(|f| { foreach_cb(f); f}), but eagerly-evaluated.

As far as eager evaluation goes it, it must be documented very clearly that this is exception to convention of iterators being lazy.

EDIT: obviously this also means there’s an implicit list of intermediate values at the boundary of each foreach.


#4

I wonder if a name like into instead of foreach would make it a bit clearer that it’s a consuming, evaluating method. I’d love to have something like this, even though I’m unsure about what a clear name would be.

An into could possibly also be more useful than just eager iteration of a closure. It could take anything with an IteratorReceiver trait as argument. Some examples:

# the general use-case
range(0, 100).into(|n| println!("n {}", n));

# populating a Vec
let mut v = vec![1, 2, 3];
range(20, 50).into(&mut v);
range(100, 200).into(&mut v);

Channels might also be sane receivers.

Unsure if this could be done without requiring the closure to be passed as &mut |n| ... implicitly.


#5

I would actually very much want foreach() to not be an adapter, but be more like collect(). Currently, all iterators are lazy, this would break that rule.


#6

In that case

.fold((), |_, x|{ 
    statement1;
    statement2;
})

is equivalent to the proposed method.


#7

This has a RFC.