[Swift] Custom Operators (사용자 정의 연산자)

Geon·2022년 8월 10일

Swift 기초

목록 보기
7/10

지난 시간엔 기존에 존재하던 연산자를 확장하는 방법을 배웠다면, 이번 시간엔 새로운 연산자를 만드는 방법을 알아볼 것이다.
사용자 정의 연산자를 만들땐 연산자의 위치에 따라 아래와 같이 선언한다.

전위 연산자 : prefix operator 연산자
후위 연산자 : postfix operator 연산자
중위 연산자 : infix operator 연산자

위와 같이 선언을 해서 연산자를 생성해주었다면, 다음은 생성한 연산자가 어떻게 연산을 할 건지를 구성해주는 작업을 해야하는데, 아래와 같은 형식이다.

전위 : static prefix func 연산자(파라매터) -> 반환타입{
//연산 방식
}

후위 : static postfix func 연산자(파라매터) -> 반환타입{
//연산 방식
}

중위 : static func 연산자(파라매터) -> 반환타입{
//연산 방식
}

선언부와 달리 이곳에서 중위 연산자의 경우 infix라고 명시해주지 않고 생략하여 사용한다. 또한 반환타입은 생략 가능하다. 이렇게만 보면 어려울 수 있으니 이를 직접 활용한 예시를 보고 이해해보도록 하자. 2씩 더해주는 전위 연산자 +++ 를 만들어보도록 하겠다.

prefix operator +++

extension Int{
	static prefix func +++(num : inout Int){
    	num = num + 2
    }
}

우리는 Int타입에 대해 새로운 연산자를 만들어 주는 것이니 extension Int를 통해 확장을 시켜주고, 나머지는 위에서 설명한 문법을 그대로 따라해 주었다. 파라매터 부분에 num이 inout으로 되어 있는 것은 그 밑에 계산이 num = num + 2 로 num 자기 자신의 값이 변경이 되고, 그 값을 유지해야 하기 때문이니 참고해두자. 위에서 생성한 +++ 연산자를 활용하면 다음과 같은 결과가 나온다.

var a = 1
+++a
print(a) //3

원하던 결과대로 1에 2가 더해져 3이 도출됨을 확인할 수 있다.

이번에는 두 수를 곱한 뒤 더해주는 이항연산자를 만들어보겠다.

infix operator *+*

extension Int{
	static func *+*(lNum : Int, rNum : Int) -> Int {
    	return (lNum * rNum) + (lNum * rNum)
    }
}

print(4 *+* 2) //16

4와 2를 우선 곱하여 8이 되고, 그 8끼리 더하여 16의 결과가 올바르게 도출됨을 확인할 수 있다.

우선순위 지정

4 *+* 2 + 3 //error!

우리가 만든 커스텀 연산자의 계산 후에 3을 더해서 19라는 결과를 얻고 싶어 위와 같이 시도했지만 에러가 나온다. 이는 우리가 만든 연산자의 우선순위를 따로 지정해주지 않았고, 그렇게 되면 기본적으로 우선순위 그룹이 default precedence group에 소속되는데, 이 그룹에 속한 연산자는 단독으로 쓰일 땐 문제가 없지만, 우선순위가 지정되지 않은 상태이기에 다른 연산자와 함께 연산을 수행하면 스위프트에서 어느 연산을 먼저 수행해야 하는지 알 수 없어 에러가 발생하는 것이다. 아래는 주요 연산자들의 우선순위다.(위일수록 우선순위가 높은 그룹, 밑일수록 낮은 그룹이다.)

이 우선순위 그룹을 우리가 만든 연산자에게 부여하는 방법은 다음과 같다.

infix operator 연산자 : PrecedenceGroup

자 그럼 아까 전에 만든 코드에 우선순위 그룹을 부여하여 우리가 원하는 결과를 도출해보도록 하자.

infix operator *+* : MultiplicationPrecedence 
extension Int{
	static func *+*(lNum : Int, rNum : Int) -> Int {
    	return (lNum * rNum) + (lNum * rNum)
    }
}
print(4 *+* 2 + 3) //19

곱하기 연산자와 같은 우선순위 레벨을 부여받았기 때문에 우리가 만든 연산자가 먼저 계산이 되고 후에 3이 더해져 19가 도출된다.

사용자 지정 연산자를 만들었듯이, 우선순위 그룹을 직접 만드는 것도 가능하다. 형식은 아래와 같다.

precedencegroup 우선순위 그룹 이름 {
higherThan : 어떤 그룹보다 높은지
lowerThan : 어떤 그룹보다 낮은지
associativity : 연산자의 결합규칙 (left / right / none)
}

여기서 higherThan,lowerThan 중 하나만 명시한다면 나머지는 생략이 가능하다. 결합규칙을 쓰는 부분은 생략시 기본으로 none으로 지정된다. 그럼 ComparisonPrecedence보단 높고, AdditionPrecedence보단 낮은 연산자 그룹을 만들어보자.

precedencegroup CustomPrecedence{
    higherThan : ComparisonPrecedence 
    lowerThan : AdditionPrecedence
}

이렇게 그룹을 생성하여

infix operator ^^^ : CustomPrecedence

extension Int{
	static func ^^^(left : Int, right : Int) -> Int{
    ...
    }
}

이러한 방식으로 이용할 수 있으니 알아두도록 하자.

profile
별에 별 지식 저장해놓고 꺼내먹기📚

0개의 댓글