스칼라 번역- 고차함수 (Higher Order Functions)

이 포스팅은 [scala-exercises 번역 시리즈]scala-exercises 사이트의 스칼라 튜토리얼을 공부하며 번역한 문서 입니다.
scala-exercises 는 스칼라 창시자인 마틴 오더스키 강의의 강의자료입니다.
따라서 강의를 들으며 본 문서를 같이 보는것을 추천합니다.
의역이 많습니다. 오역 및 오타 등은 코멘트로 알려주세요 😄
원문 : [scala tutorial higher order functions]


고차함수(Higher Order Functions)

함수형 언어는 함수를 일급 시민(first-class) 으로 다룹니다.
즉 값처럼 함수를 매개변수로 전달하고 결과를 반환할 수 있습니다.
고차함수는 프로그램을 유연하게 조립하는 방법을 제공합니다.
이렇게 마치 값 처럼 다른 함수를 매개변수로 사용하거나 함수를 결과로 리턴하는 함수를 고차함수라고 합니다.

MOTIVATION

a와 b사이의 정수(integer)들을 더합니다.

1
2
def sumInts(a: Int, b: Int): Int =
if (a > b) 0 else a + sumInts(a + 1, b)

a 와 b 사이의 정수(integer)들인 cube 들을 더합니다.

1
2
3
4
def cube(x: Int): Int = x * x * x

def sumCubes(a: Int, b: Int): Int =
if (a > b) 0 else cube(a) + sumCubes(a + 1, b)

a 와 b 사이의 정수(integer)들인 factorial 들을 더합니다.

1
2
def sumFactorials(a: Int, b: Int): Int =
if (a > b) 0 else factorial(a) + sumFactorials(a + 1, b)

어떻게 이 비슷한 메소드들의 공통 패턴을 제거할수 있을까요?

고차함수를 이용해 더하기

sum 함수는 다음과 같습니다.

1
2
3
def sum(f: Int => Int, a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sum(f, a + 1, b)

그리고 다음과 같이 작성할수 있습니다.

1
2
3
4
def id(x: Int): Int = x
def sumInts(a: Int, b: Int) = sum(id, a, b)
def sumCubes(a: Int, b: Int) = sum(cube, a, b)
def sumFactorials(a: Int, b: Int) = sum(factorial, a, b)

함수 타입

A => B의 타입은 함수 입니다. 함수 형태인 A argument 를 입력한 결과를 B 라는 결과로 리턴합니다.
그러므로, Int => Int는 int를 int로 맵핑하는 함수 입니다.

익명함수(ANONYMOUS FUNCTIONS)

함수를 매개변수로 전달하려면 많은 작은 함수가 필요하고, 생성해야합니다.
그리고 def 로 이런 함수(및 함수의 이름)를 일일히 정의해야하는 일은 너무 번거롭습니다.

1
val str = "abc"; println(str) // 지루한 코드

그러니 스칼라는 바로 아래와 같이 이렇게 작성할 수 있습니다.

1
println("abc")

string 과 비교하자면 : val을 사용해 string을 정의할 필요가 없습니다.
왜냐하면, string리터럴(literals)로 존재하기 때문입니다.
이와 비슷하게 함수 리터럴을 원하므로, 함수 리터럴에 이름을 주지않고 함수를 작성하게 됩니다.
이를 익명 함수(anonymous functions) 라고 합니다.

익명함수의 문법

argumentcube 로 전달하는 함수는 다음과 같습니다.

1
(x: Int) => x * x * x

(x: Int)함수의 매개변수(parameter) 이며 x * x * x는 함수의 body 입니다.
만약 컴파일러가 컨텍스트에서 유추할 수 있는 경우 파라미터의 타입은 생략할 수 있습니다.
파라미터가 여러개인 경우 쉼표로 구분됩니다.

1
(x: Int, y: Int) => x + y

익명함수는 Syntax Sugar 입니다(Anonymous Functions are Syntactic Sugar)

익명함수 (x1: T1, …, xn: Tn) => e는 항상 def 를 사용해 다음과 같이 표현할 수 있습니다.

1
{ def f(x1: T1, …, xn: Tn) = e ; f }

여기서 f 는 프로그램에서 아직 사용되지않은 임의의 새로운 이름입니다 따라서 익명함수로 표현될수 있습니다.
이렇게 익명함수는 문법적 설탕입니다.

익명함수를 이용한 sum 함수 작성

익명함수를 이용하면, sum 함수를 좀더 짧게 작성할 수 있습니다.

1
2
def sumInts(a: Int, b: Int) = sum(x => x, a, b)
def sumCubes(a: Int, b: Int) = sum(x => x * x * x, a, b)

읽어주셔서 감사합니다. 혹 글에 오역/추가할 내용이 있다면 코멘트 남겨주세요.

같이 보면 좋은 포스팅 : 일급 함수