# 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/
Swift 함수에 커링 사용하기
다음: Realm Swift를 사용하면 iOS 앱 모델 레이어를 효과적으로 작성할 수 있습니다.
academy.realm.io
https://github.com/pointfreeco/swift-overture
GitHub - pointfreeco/swift-overture: 🎼 A library for function composition.
🎼 A library for function composition. Contribute to pointfreeco/swift-overture development by creating an account on GitHub.
github.com
Introduction to Function Currying in Swift
Function currying in Swift might not be immediately obvious, but once you see the applications, it can be another incredibly powerful tool at your disposal.
thoughtbot.com
'apple > iOS, UIKit, Documentation' 카테고리의 다른 글
[Swift] plain ol' data(POD) (0) | 2023.08.08 |
---|---|
UILabel Inset and CornerRadius (UIKit) (0) | 2023.06.23 |
[iOS] UIImage.Orientation (0) | 2022.12.09 |
such module 'RxCocoaRuntime' (0) | 2022.10.19 |
Swift HTML 코드 로드하기 (0) | 2022.10.06 |