함수 변수

함수 변수

이전 절에서 본 예시를 다시 꺼내 볼게요. 익명 함수가 변수에 할당되면 어떤 일이 벌어지는지, 그리고 그 함수를 다른 변수처럼 취급하는 방법을 이번 장에서 함께 살펴볼게요.

출처: Scala 3 Book

본문

이전 절의 이 예시로 다시 돌아가 볼게요.

val doubledInts = ints.map((i: Int) => i * 2)

표현식의 이 부분이 익명 함수(anonymous function)라는 걸 앞에서 언급했었죠.

(i: Int) => i * 2

익명(anonymous) 이라고 부르는 이유는, 이 함수가 변수에 할당되지 않아서 이름이 없기 때문이에요.

그런데 익명 함수—함수 리터럴(function literal) 이라고도 불러요—는 변수에 할당해서 함수 변수(function variable) 를 만들 수 있어요.

val double = (i: Int) => i * 2

이렇게 하면 double이라는 이름의 함수 변수가 생겨요. 이 표현식에서 원래 함수 리터럴은 = 기호의 오른쪽에 있어요.

val double = (i: Int) => i * 2
             -----------------

새 변수 이름은 왼쪽에 있죠.

val double = (i: Int) => i * 2
    ------

그리고 함수의 매개변수 목록은 여기 밑줄로 표시됐어요.

val double = (i: Int) => i * 2
             --------

메서드의 매개변수 목록과 마찬가지로, 이건 double 함수가 i라는 이름의 Int 매개변수 하나를 받는다는 뜻이에요. REPL에서 doubleInt => Int 타입을 갖는 걸 볼 수 있어요. 즉 단일 Int 매개변수를 받고 Int를 반환한다는 뜻이죠.

scala> val double = (i: Int) => i * 2
val double: Int => Int = ...

함수 호출하기 (Invoking the function)

이제 double 함수를 이렇게 호출할 수 있어요.

val x = double(2)   // 4

doublemap 호출에 넘길 수도 있어요.

List(1, 2, 3).map(double)   // List(2, 4, 6)

더 나아가, Int => Int 타입의 다른 함수들이 있으면:

val triple = (i: Int) => i * 3

그것들을 ListMap에 저장할 수 있어요.

val functionList = List(double, triple)

val functionMap = Map(
  "2x" -> double,
  "3x" -> triple
)

그 표현식들을 REPL에 붙여 넣으면, 이 타입들을 갖는다는 걸 볼 수 있어요.

// a List that contains functions of the type `Int => Int`
functionList: List[Int => Int]

// a Map whose keys have the type `String`, and whose
// values have the type `Int => Int`
functionMap: Map[String, Int => Int]

핵심 포인트 (Key points)

여기서 중요한 부분은 이거예요.

  • 함수 변수를 만들려면 변수 이름을 함수 리터럴에 할당하면 돼요
  • 함수를 얻으면 그걸 다른 변수처럼, 즉 String이나 Int 변수처럼 취급할 수 있어요

그리고 Scala 3의 개선된 Eta 확장(Eta Expansion) 덕분에, 메서드도 같은 방식으로 다룰 수 있어요.

더 알아보기