infix function은 무엇일까요? 우선 비슷한 단어 prefix는 어떤 행위가 앞에 오는 것이고, postfix는 뒤에 오는 것을 의미합니다.
간단한 예로 표기법(expression)을 들 수 있습니다. 표기법은 연산자의 위치에 따라 전위(prefix), 후위(postfix), 그리고 중위(infix)로 나뉩니다. 즉, infix는 두 개의 값 사이에 특정한 표현식을 넣는다는 의미입니다.
코틀린에서는 이 개념을 활용하여 특별한 함수식을 만들 수 있습니다. infix function이란 호출자의 점(.)과 파라미터 괄호()를 생략하고 함수명만으로 호출할 수 있는 코틀린의 표현식입니다.
아래 예제는 코틀린의 mockk라는 테스트 프레임워크에서 나오는 표현식입니다. 아래의 두 표현식은 완전히 동일합니다. 두 번째 줄이 infix function을 이용한 방식으로, 가독성이 훨씬 좋은 것을 확인할 수 있습니다.
every { service.get() }.returns(5) // 일반 함수 호출 방법
every { service.get() } returns 5 // infix 함수 호출 방법
이번에는 infix function을 만드는 방법에 대해 알아보겠습니다. 먼저 커스텀하게 만들기 전에 코틀린에서 기본적으로 사용할 수 있는 infix function을 살펴보겠습니다.
아래 코드를 봅시다. 이 코드는 두 개의 데이터를 하나로 묶어주는 Tuple인 Pair를 사용하여 map을 초기화하는 예시입니다. Pair를 이용하여 값을 넣으면 첫 번째 인자를 key로, 두 번째 인자를 value로 인식하여 사용할 수 있습니다.
val pairs = mapOf(
Pair(1, "a"),
Pair(2, "b"),
Pair(3, "c")
)
print("pair[1] = ${pairs[1]}") // "a"
Pair는 infix function을 지원합니다. 따라서 위의 예제를 infix function으로 표현할 수 있습니다. 아래 코드가 Pair의 infix function을 이용한 map의 초기화입니다. 보시면 더 깔끔해진 것을 알 수 있습니다.
val pairs = mapOf(
1 to "a",
2 to "b",
3 to "c"
)
print("pair[1] = ${pairs[1]}") // "a"
추가로 'to'가 어떻게 구현되었는지 살펴보겠습니다. 아래 코드가 Pair의 'to' 코드입니다. 확장(extension) 함수로 구현되어 있음을 알 수 있습니다. infix function을 만들기 위해서는 'infix'라는 키워드를 명시해야 합니다. 이 코드를 통해 to
는 'to'를 기준으로 앞에는 호출자, 뒤에는 파라미터가 오는 것을 확인할 수 있습니다.
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
이제 직접 infix function을 만들어보겠습니다. infix function을 만들기 위한 제약 조건은 다음과 같습니다:
이러한 제약 조건에 맞춰 두 개의 값을 더해주는 확장 함수를 만들어보겠습니다. infix function을 만들기 위해서는 함수에 'infix' 키워드를 추가해야 합니다. infix 문법을 추가하여 함수를 만들면 아래와 같은 더하기 함수를 만들 수 있습니다. 아래 함수는 Int에 대해 'add'라는 확장 함수를 infix로 만든 것입니다.
private infix fun Int.add(value: Int): Int = this + value