swift 고차함수에는 map, compactMap, flatmap, reduce, zip, filter, forEach가 있다.
그중에 reudce는 초기값을 받아, 모든 아이템을 순환하는 로직을 구현하는데 적합하다는 건 익히 알고 있는 사실이었다.
reduce(_,_)
만을 사용해왔는데, 자동화리스트에 reduce(into,_)
가 있다는 걸 보게됐다.
그럼 이 함수는 왜 있는 것인가에 대한 물음으로 글을 쓰게 됐다.
두 형제 함수의 예제 코드를 보면:
let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(0) { result, number in
return result + number
}
print(sum) // 출력: 15
let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(into: 0) { result, number in
result += number
}
print(sum) // 출력: 15
reduce(_,_)
는 리턴형을 받고, reduce(into,_)
는 받지 않는다는 차이가 있다.
따라서 전자는 return 값의 복사가 항상 일어날 것이고,
후자는 연상중에 사용되는 result변수의 레퍼런스로 가지고 재활용할 것이라는 것을 예상할 수 있었다.
예상처럼 애플의 공식 문서에 따르면
func reduce<Result>(
into initialResult: Result,
_ updateAccumulatingResult: (inout Result, Self.Element) throws -> ()
) rethrows -> Result
reduce(into,_)
는 handler 첫 번째 파라미터가 inout
인 것을 확인 할 수 있었다.
결론을 내자면 reduce(_,_)
는 성능에 의미를 두지 않는 코드를 작성하는 편리함을 위해 사용하고, reduce(into,_)
는 최적화를 해야하는 곳에서 사용하면 좋겠다.
reduce(0, +)
이 코드가 왜 동작하는지에 대해서 추가적으로 알아보았다.
왜 핸들러가 들어갈 위치에 연산자를 넣어도 동작하는 것일까?
+연산자는 func +(lhs: Int, rhs: Int) -> Int
의 정의를 가진 함수이기 때문이었다.