[swift-evolution] Remove forEach?

ilya ilya.nikokoshev at gmail.com
Thu Dec 31 04:41:30 CST 2015


I like having separate forEach. As already said, forEach produces different
visual grouping of logic compared to for operator. It's especially useful
if you just pass a named function to it.

forEach is also not the same as map:

let block: Int -> Void = ...
[1,2,3].map(block)

Here the result has the type [Void], not Void and the compiler correctly
produces a warning. We'd have to explicitly assign the result to silence
it, which now hides the fact that block wasn't producing anything in the
first place.

This will hold true for any advanced variant of map.

Ilya.
On Thu, Dec 31, 2015 at 10:30 Dave Abrahams via swift-evolution <
swift-evolution at swift.org> wrote:

>
> -Dave
>
> On Dec 30, 2015, at 8:48 PM, Kevin Ballard via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Swift didn't use to have forEach(). It was added fairly late, and I
> suspect (though I don't actually know) that it was done so to appease
> people who kept abusing map() for the same function, as well as the
> die-hard everything-must-be-functional crowd.
>
>
> Those are two of the reasons.  But the reason that put forEach over the
> line and convinced me to add it, just slightly, was syntactic:
>
> for x in some.very.long[chain]
>   .of.map { $0 }
>   .filter { something }.whatever {
>   ...
> }
>
> reads "inside-out," like nested(free(function(calls())))) vs.
>
> some.very.long[chain]
>   .of.map { $0 }
>   .filter { something }.whatever
>   .forEach { x in
>      ...
>    }
>
>
> Personally, I'd rather we didn't have it because it encourages people to
> use it, but I suppose it's better to give people an appropriate tool than
> to keep watching them abuse map().
>
> -Kevin Ballard
>
> On Wed, Dec 30, 2015, at 04:50 PM, Craig Cruden via swift-evolution wrote:
>
> I don’t see the benefit of taking a simple declarative expression (map,
> flatMap, filter) and turning it into a complicated imperative/iterative
> loop.  You already have the ability to iterate through a set and do
> whatever you want to do with with whatever logic you want to use using.  I
> would have no problem for the most part removing foreach - it is more of a
> convenience method for doing an iterative loop through a collection - and
> to be quite honest rarely use outside of maybe putting in a print statement
> temporarily in there (but more often just turn the resulting set into comma
> delimited output and printing it).
>
>
>
> On 2015-12-31, at 5:10:22, Howard Lovatt via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> You could replace `forEach` with a supped up `map` that also allowed
> `break` and `continue`. The following library function gives `continue`
> and `break` and also combines `repeat`, `times`, `forEach`, `filter`,
> `flatMap`, and `map` into one:
>
>
> public final class MapController<E, R> {
> var results = [R]()
>
> var isContinuing = true
>
> init<C: CollectionType where C.Generator.Element == E>(_ collection: C,
> sizeEstimate: Int = 0, @noescape mapper: (controller: MapController<E,
> R>, element: E) throws -> R?) rethrows {
>         results.reserveCapacity(sizeEstimate)
> for var generator = collection.generate(), element = generator.next();
> element != nil && isContinuing; element = generator.next() {
> let result = try mapper(controller: self, element: element!)
> if let actualResult = result {
>                 results.append(actualResult)
>             }
>         }
>     }
> }
>
> extensionCollectionType {
> /// Controllable `map`, additional controls beyond simple `map` are:
> ///
> ///   1. Continue without returning a result (`return nil`)
> ///   2. Return multiple results (`control.results += [...]` then `return
> nil`)
> ///   3. Break (`control.isContinuing = false` then `return nil`)
> ///
> /// These additional controls allow this `map` to function like `repeat`,
> `times`, `forEach`, `filter`, `flatMap`, and `map` combined into one as
> well as providing an early termination (break).
> @warn_unused_result func map<R>(sizeEstimate sizeEstimate: Int = 0,
> @noescape mapper: (controller: MapController<Self.Generator.Element, R>,
> element: Self.Generator.Element) throws -> R?) rethrows -> [R] {
> return try MapController(self, sizeEstimate: sizeEstimate, mapper:
> mapper).results
>     }
> }
>
> // Demonstration of full functionality including continue, break, and
> multiple returns
> var result = (0 ..< 5).map { (control, index) -> Int? in
> switch index {
> case 1:
> returnnil// Continue - skip 1 (`filter`)
> case 2:
>         control.results.append(2) // Yield two results - this one and the
> 'return’ yield (`flatMap`)
> case 3:
>         control.isContinuing = false// Break after next yield - which
> could be `return nil` if there are no more results
> default:
> break
>     }
> return index // Yield next result - except for case 1 all the above yield
> `index`
> }
> print(result) // prints `[0, 2, 2, 3]` note missing "1", double "2", and
> last is "3"
>
> // Demonstration of `repeat`/`forEach`/`times` like usage - note `(_, _)
> -> Void?`
> result = [Int]()
> (0 ..< 3).map { (_, _) -> Void? in
>     result.append(1) // Do whatever - in this case append to a global
> returnnil// Don't yield any results
> }
> print(result) // prints `[1, 1, 1]`
>
>
> Would this be a superior alternative to both `forEach` and `times` in the
> library and `repeat` as a language feature?
>
> Sent from my iPad
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> *_______________________________________________*
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151231/257e3d9d/attachment.html>


More information about the swift-evolution mailing list