본문 바로가기
Swift

Custom Operator =>

by zinozino 2022. 12. 2.

이번 시간에는 https://devamor.tistory.com/6에서 배운 연산자 만들기를 통해서  새로운 연산자를 만들도록 하겠습니다. 

 

아래의 코드를 보면서 설명드릴게요!

 

func increaseTwo(value: Int) -> Int { // 인수를 받아서 2을 더해서 반환하는 함수
    return value + 2
}


func decreaseOne(value: Int) -> Int { // 인수를 받아서 1을 빼서 반환하는 함수
    return value - 1
}

 

사용할 때!

decreaseOne(value: increaseTwo(value: 5)) // print 6


((Int) -> Int) -> Int

 

increaseTwo함수의 반환 값을 decreaseOne 함수에 넣어서 결괏값을 출력합니다.  매우 자연스럽게 보이며 실제 프로젝트에서도 이렇게 사용하고 있을 겁니다.  

여기서 생각해볼 점은 우리가 무엇을 읽을 때는  LTR(left to right)로 읽게 되는데요  

 

값을 구하는 함수가 내부에서 많아질수록 가독성이 떨어진다는 것을 알 수 있습니다. 

 

그래서

함수 -> 함수로 값을 LTR로 읽을 수 있도록  연산자를 만들어보겠습니다. 

 

 

저는 연산자 이름은 " =>"로 만들 것이고 중위 연산자로 만들 것입니다.

첫 번째 편을 보신 분이라면 아래 코드를 바로 보시지 마시고 한번 작성해보시는 것을 추천드립니다!

.

.

.

.

.

.

.

 

 

간단합니다. 사실..ㅎㅎ

infix operator =>

 

그럼 이제  연산자를 정의해보겠습니다.

 

 

1) 왼쪽 함수에서 B를 반환하고  오른쪽 함수가 이것을 받아서 C를 반환해야겠죠. 

결과적으로 (A)에서 C가 나오도록 하면 되겠습니다.

2)  실제 a를 받아서 처리하는 부분은  "decreaseOne(value: increaseTwo(value: 5))"  같죠!

func => <A,B,C>(
	leftFunction: @escaping (A) -> (B),
	rightFunction: @escaping (B) -> C) -> ((A) -> C) { // 1)
    
    return { a in rightFunction(leftFunction(a)) } //2)
    
}

 

실제로 함수 마지막에 반환되는 함수의 시그니처는 이렇습니다.

숫자를 넣으면 왼쪽에서 처리하고 그 이후 오른쪽에서 처리해서 Int를 반환한다.

 

(increaseTwo(value:) => decreaseOne(value:))(5) // print 6

 

 

마지막! 첫 시간에 만든 :> 연산자를  5를 마지막에 넣는 것이 아닌 왼쪽에서부터 넣어볼게요!

:>는 왼쪽에 값을 오른쪽에는 그것을 처리하는 함수를 반환하는 연산자입니다. 

 

 

이렇게 하면 될 것 같지만 에러가 발생하네요

2 |> increaseTwo(value:) >>> decreaseOne(value:)
// error: Adjacent operators are in unordered precedence groups 'SubstitutionPrecedence' and 'DefaultPrecedence'

 

'SubstitutionPrecedence'과 'DefaultPrecedence' 사이에  연산자 우선순위가 정해지지 않음!

예를 들어 x + y  * z 가 있을 때 우리는 *연산자 우선순위가 높기 때문에 먼저 계산하는 것처럼 

커스텀 연산자 사이에도  우선순위를 정해줘야 한다는 것입니다.

 

 "=>" 연산자도   커스텀 Precendence를  따르도록 하겠습니다.

infix operator =>: LogicProcessingPrecedence
precedencegroup LogicProcessingPrecedence {
    associativity: left
    higherThan: SubstitutionPrecedence // |> 연산자의 우선순위그룹
    
}

 

"=> 연산자 우선순위가 |> 우선순위보다 높다"라고 정의했으니  =>가 먼저 연산되어서

함수 (Int) -> Int가 나오고 

|>을 통해서 5가 해당 함수로 전달됩니다.

5 |> increaseTwo(value:) >>> decreaseOne(value:) //print 6
5 |>  (Int) -> Int //print 6

 

테스트!

숫자 5에 2를 3번 더하고 1을 한번 빼고  다시 2를 더하면  결괏값은 12가 나올까요?

5 |> increaseTwo(value:) // + 2 = 7
  => increaseTwo(value:) // + 2 = 9
  => increaseTwo(value:) // + 2 = 11
  => decreaseOne(value:) // - 1 = 10
  => increaseTwo(value:) // + 2 = 12 잘나올까?

 

잘나오는군!

 

오늘 끗!

'Swift' 카테고리의 다른 글

KeyPath  (2) 2023.01.16
FP에서 Setter 사용법  (0) 2022.12.10
Currying  (2) 2022.11.30
Custom Operator |>  (2) 2022.11.29
ObjectIdentifier을 이용한 DI - 2  (1) 2022.04.13