[swift-evolution] Remove forEach?
Daniel Duan
daniel at duan.org
Wed Dec 30 16:14:38 CST 2015
In most programming languages, map does not have any side-effect. This is may be the reason forEach was added.
> On Dec 30, 2015, at 2:10 PM, 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)
> }
> }
> }
> }
>
> extension CollectionType {
> /// 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:
> return nil // 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
> return nil // 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151230/8bc12c33/attachment.html>
More information about the swift-evolution
mailing list