-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] <mailto:[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] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <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

Reply via email to