Just my 2 cents, forEach is a simple concept to understand, it exists in most other languages that have a language level understanding of containers, retaining it has no downsides, but has the upside of making swift more approachable.
'map' on the otherhand may be much more powerful a construct, but it is less famliar as a concept. Is there any reason why both cant coexist, with one being a simple form of the other. On Jan 1, 2016 7:31 AM, "Howard Lovatt via swift-evolution" < [email protected]> wrote: > I suspect that if there were an 'advanced' `map` it would largely > eliminate `forEach` since a main use of `forEach` is because of > limitation in map like multiple returns, combined map and filtering, etc. > > The comment that you have to ignore a warning is however a valid point, > perhaps like other languages, e.g. Java, you could have a > `@suppress_unused_result_warning` annotation. > > Sent from my iPad > > On 31 Dec 2015, at 9:41 PM, ilya via swift-evolution < > [email protected]> wrote: > > 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 < > [email protected]> wrote: > >> >> -Dave >> >> On Dec 30, 2015, at 8:48 PM, Kevin Ballard via swift-evolution < >> [email protected]> 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 < >> [email protected]> 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 >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> *_______________________________________________* >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> >> _______________________________________________ >> swift-evolution mailing list >> [email protected] >> https://lists.swift.org/mailman/listinfo/swift-evolution >> > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
