[stdlib] Implement reduce with inout (SE-0171)

Implement and document `reduce(into:_:)`, with a few notes:

 - The `initial` parameter was renamed `initialResult` to match the first parameter in `reduce(_:_:)`.
 - The unnamed `combining` parameter was renamed `updateAccumulatingResult` to try and resemble the naming of the closure parameter in `reduce(_:_:)`.
 - The closure throws and `reduce(into:_)` re-throws.
 - This documentation mentions that `reduce(into:_)` is preferred over `reduce(_:_:)` when the result is a copy-on-write type and an example where the result is a dictionary.

Add benchmarks for reduce with accumulation into a scalar, an array, and a dictionary.

Update expected error message in closures test (since there are now two `reduce` methods, the diagnostic is different).
This commit is contained in:
David Rönnqvist
2017-07-14 23:24:42 +02:00
parent b37b3ba367
commit e15ea5fcf3
5 changed files with 147 additions and 1 deletions

View File

@@ -0,0 +1,84 @@
//===--- ReduceInto.swift -------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import TestsUtils
import Foundation
@inline(never)
public func run_ReduceIntoInt(_ N: Int) {
let numbers = [Int](0..<1000)
var c = 0
for _ in 1...N*100 {
c = c &+ numbers.reduce(into: 0) { (acc: inout Int, num: Int) in
acc = acc &+ num
}
}
CheckResults(c != 0)
}
@inline(never)
public func run_ReduceIntoArray(_ N: Int) {
let numbers = [Int](0..<100)
var c = 0
for _ in 1...N*100 {
let a = numbers.reduce(into: []) { (acc: inout [Int], num: Int) in
acc.append(num)
}
c = c &+ a.count
}
CheckResults(c != 0)
}
@inline(never)
public func run_ReduceIntoDictionary(_ N: Int) {
let numbers = [Int](0..<100)
var c = 0
for _ in 1...N*100 {
let d = numbers.reduce(into: [:]) { (acc: inout [Int: Int], num: Int) in
acc[num] = num
}
c = c &+ d.count
}
CheckResults(c != 0)
}
@inline(never)
public func run_MapUsingReduceInto(_ N: Int) {
let numbers = [Int](0..<100)
var c = 0
let f: (Int) -> Int = { $0 &+ 5 }
for _ in 1...N*100 {
let a = numbers.reduce(into: []) { (acc: inout [Int], x: Int) in
acc.append(f(x))
}
c = c &+ a.count
}
CheckResults(c != 0)
}
@inline(never)
public func run_FrequenciesUsingReduceInto(_ N: Int) {
let s = "thequickbrownfoxjumpsoverthelazydogusingasmanycharacteraspossible123456789"
var c = 0
for _ in 1...N*100 {
let a = s.reduce(into: [:]) { (acc: inout [Character: Int], c: Character) in
acc[c, default: 0] += 1
}
c = c &+ a.count
}
CheckResults(c != 0)
}