# Currying
함수형 프로그래밍을 위한 Currying 학습.
# 계기
- SwiftUI를 사용하여 View를 모듈화를 시도.
- 더 잘 만들기 위해 함수형 프로그래밍의 해당 개념에 대한 학습이 필요하다고 느낌.
# 목표
- 간단한 덧셈 구현 (Level 1)
- 정규표현식 구현 (Level 2)
- Reduce, Map, Filter 구현
- FlatMap, CompactMap 구현 (⚠️ 실패한 구현)
: 기록하기 위해서 적어둠.
# 참고에서는 UI와 관련한 클로저를 함수형으로 받아서 간결하게 처리하는 예제도 있으니 확인하면 좋음.
❗️ 실패한 구현인 이유
: 결과값이 다르게 나타남.
# 파일
# 간단한 덧셈 구현 (Level 1)
import Foundation
public class LEVEL1 {
public func execute() {
print(add(2, 3))
print(curriedAdd(2)(3))
print(curriedAdd2(2)(3))
let stringDevideSlash = stringDevider("/")
let stringDevideAsterisk = stringDevider("*")
print(stringDevideSlash("aaa/bbb/ccc/ddd"))
print(stringDevideAsterisk("aaa*bbb*ccc*ddd"))
}
public init() { }
public func add(_ value1: Int, _ value2: Int) -> Int {
return value1 + value2
}
// 두개의 Int 값을 받아서 덧셈을 하고 결과값을 리턴해주는 함수.
public func curriedAdd(_ value1: Int) -> ( (Int) -> Int ) {
return { value2 in
return value1 + value2
}
}
public func curriedAdd2(_ value1: Int) -> (Int) -> Int {
return { value2 in
return value1 + value2
}
}
public func stringDevider(_ seperater: String) -> (String) -> [String] {
return { (string: String) -> [String] in
return string.components(separatedBy: seperater)
}
}
}
# 정규표현식 구현 (Level 2)
import Foundation
// MARK: - 클래스 형태로 사용
public class Regex {
public func execute() {
let regex = Regex("main")
print(regex.test("int main()")) // true
print(Regex("main").test("int main()")) // true
print(Regex("xx").test("int main()")) // false
print(Regex("t m").test("int main()")) // true
print(Regex("tm").test("int main()")) // false
print(Regex("main").test("int main()")) // true
let hasMainIn = Regex("main").test
print(hasMainIn("int main()")) // true
}
var internalExpression: NSRegularExpression?
public init(_ pattern: String) {
self.internalExpression = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive)
}
public func test(_ input: String) -> Bool {
let inputRange = NSMakeRange(0, input.count)
guard let matchesCount = self.internalExpression?
.matches(in: input, options: [], range: inputRange)
.count else { return false }
return matchesCount > 0
}
}
// MARK: - 함수 형태로 사용
public func regexFunctionTest(pattern: String) -> (String) -> Bool {
let expression: NSRegularExpression? = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive)
return { (input: String) -> Bool in
guard let expression = expression else { return false }
let inputRange = NSMakeRange(0, input.count)
let matches = expression.matches(in: input,
options: [],
range: inputRange)
return matches.count > 0
}
}
# Reduce, Map, Filter 구현
# Reduce
import Foundation
/*
초기값을 지정하고, 각 원소를 어떻게 결합시킬지 정의하는 함수의 제네릭 형태
*/
public func customReduce<A, R>(
xs: [A],
initialResult: R,
nextPartialResult: (R, A) -> R
) -> R {
var result = initialResult
for x in xs {
result = nextPartialResult(result, x)
}
return result
}
public func sumUsingReduce(xs: [Int]) -> Int {
return customReduce(xs: xs, initialResult: 0) { result, x in
result + x
}
}
public func conmbineUsingReduce(xs: [String]) -> String {
return customReduce(xs: xs, initialResult: "") { result, x in
result + x + " "
}
}
extension Array {
func customReduce<A, R>(
initialResult: R,
nextPartialResult: (R, A) -> R
) -> R {
var result = initialResult
for x in self {
result = nextPartialResult(result, x as! A)
}
return result
}
}
# Map
import Foundation
extension Array {
public func customMap<A, R>(
nextPartialResult: (A) -> R
) -> [R] {
var result = [R]()
for x in self {
result.append(nextPartialResult(x as! A))
}
return result
}
}
# Filter
import Foundation
extension Array {
public func customFilter<A>(
nextPartialResult: (A) -> Bool
) -> [A] {
var result = [A]()
for x in self where nextPartialResult(x as! A) {
result.append(x as! A)
}
return result
}
}
# FlatMap, CompactMap 구현
# FlatMap
import Foundation
extension Array {
func customFlatMap<R: Sequence>(
nextPartialResult: (Element) -> R?
) -> [R.Element] {
var result = [R.Element]()
for x in self {
if let value = nextPartialResult(x) {
result.append(contentsOf: value)
}
}
return result
}
func customFlatMap<R>(
nextPartialResult: (Element) -> R?
) -> [Element] {
var result = [Element]()
for xOrNil in self {
result.append(xOrNil)
}
return result
}
}
# CompactMap
import Foundation
extension Array {
func customCompactMap<R: Sequence>(
nextPartialResult: (Element) -> R?
) -> [R] {
var result = [R]()
for xOrNil in self {
if let value = nextPartialResult(xOrNil) {
result += [value]
}
}
return result
}
}
(참고)
https://academy.realm.io/kr/posts/currying-on-the-swift-functions/
https://github.com/pointfreeco/swift-overture
'apple > Docs, iOS, Swift' 카테고리의 다른 글
[WWDC23] Meet MapKit for SwiftUI (0) | 2023.06.18 |
---|---|
[XCode 15.0 beta] Preview Macro Bug (0) | 2023.06.08 |
[iOS] UIImage.Orientation (0) | 2022.12.09 |
Swift HTML 코드 로드하기 (0) | 2022.10.06 |
[Moya] Unable to parse empty data 대응하기 (0) | 2022.09.29 |