스칼라(Scala)
스칼라(Scala)는 2004년 마틴 오더스키(Martin Odersky)에 의해 만들어진 JVM 위에서 돌아가는 또 다른 함수형 언어이다.
클로저와 마찬가지로 모든 자바 라이브러리를 사용할 수 있으며, 객체지향과 함수형 패러다임이 절묘하게 결합되어서 주목받고 있다. 함수형 언어의 측면에서 봤을 때는 하스켈과 비슷한 느낌이 나며, 객체 지향의 측면에서는 자바의 냄새가 물씬 풍긴다. 따라서 자바에 익숙한 개발자들이 함수형 언어에 입문하기에 최적이자, 여러분이 실무에서 접할 가능성이 가장 높은 언어이기도 하다.
변수 val와 var
- val는 변경 불가(Immutable)한 변수를 만들 때 사용
- var은 변경 가능(Mutable)한 변수를 만들 때 사용
val x = 1
x = 2
error: reassignment to val
var y = 2
y = 3
함수
함수를 정의할 때는 def라는 키워드를 사용한다.
def 함수_이름(인자_이름:타입):출력_타입 = {
함수 본문
}
자바에서 넘어온 사람에게는 생소할 수 있는 부분이 바로 함수 본문의 마지막 표현식이 함수의 출력값으로 반환된다는 점이다. 이는 리스프를 비롯한 모든 함수형 언어에서 함수는 곧 값이라는 개념에 근거한다. 즉, 모든 함수는 값을 반환하는 것을 전제로 한다. 하지만 자바를 기준으로 쉽게 생각하자면 단순히 return이란 키워드가 생략되었다고 바도 무방하다.
def add(x: Int, y: Int): Int = {
x + y
}
함수의 본문이 한줄인 경우에는 다음과 같이 중괄호를 생략할 수 있다.
def add(x: Int, y: Int): Int = x + y
함수의 출력 타입은 컴파일러가 추론할 수 있기 때문에 생략할 수 있다. 다만 입력 타입은 생략할 수 없다.
def add(x: Int, y: Int) = x + y
꽤나 간결한 함수 표현이다. 다음은 같은 내용을 하스켈로 작성했을 때의 코드다.
add :: Int -> Int
add x y = x + y
둘 다 타입 정보가 적절히 기술되어 있고 군더더기 없이 함수를 짧고 간결하게 정의할 수 있는 유려한 문법을 갖추었음을 알 수 있다.
람다 함수
이름이 없는 함수인 람다 함수를 만드는 방법은 다음과 같다. 먼저, 앞서 살펴본 함수 정의에서부터 시작해 보자.
def add(x: Int, y: Int) = x + y
람다 함수는 이름이 없는 함수이니 여기서 이름을 지워보자.
def (x: Int, y: Int) = x + y
이어서 def를 지우고 중간의 = 를 =>로 바꾼다.
(x: Int, y: Int) => x + y
이것이 람다식이다. 람다식에 인자를 적용해 보자.
((x: Int, y: Int) => x + y) (1, 2)
람다식을 괄호로 감싸고 인자를 써 주었다. 이는 람다 대수에서 값을 적용했던 방식과 매우 유사하다.
람다식은 변수에 저장할 수도 있다.
val myLambda = (x: Int, y: Int) => x + y
myLambda(3, 5)
>> 8
한편, 다음은 람다식을 반환하는 람다 함수의 예이다.
(x: Int) => ((y: Int) => x + y)
위 람다 함수는 x를 입력으로 받고, (y: Int) => x + y라는 람다 함수를 반환한다. 따라서 입력인자 x에 1을 적용하면, (y: Int) => 1 + y가 반환된다.
따라서 최종값을 얻으려면 값을 한번 더 적용해야 한다.
((x: Int) => ((y: Int) => x + y) (1)) (2)
>> 3
또한, 람다 함수를 입력 인자로 받는 함수를 정의할 수 있다.
def lambdaAsInput(fp: Int=>Int, x: Int): Int => fp(x)
lambdaAsInput((x: Int) => (x * 3), 5)
15
lambdaAsInput 함수는 첫 번째 인자로 람다 함수를 받고, 두 번째 인자로 숫자를 받아서 람다 함수에 인자를 적용한 결과를 반환한다.
이처럼 스칼라에서도 함수는 1급 시민으로 간주되어 변수에 저장할 수 있으며, 함수의 인자나 결과로 사용할 수 있다.
C#으로 작성해본 코드
Func<Func<int, int>, int, int> lambdaAsInput = (fp, x) => fp(x);
lambdaAsInput(x => x * 3, 5);
>> 15
참고 서적
함께 읽으면 좋은 글
'프로그래밍 > 함수형 프로그래밍' 카테고리의 다른 글
함수를 변수로 사용하기, 함수를 반환값으로 사용하기 (1) | 2024.07.23 |
---|---|
스칼라(Scala) 리스트에 대해서 알아보자 (1) | 2024.07.23 |
리스프(LISP) 재귀 함수 구현해보자 (4) | 2024.07.16 |
리스프(LISP) 기본 문법에 대해서 알아보자 (0) | 2024.07.10 |
C#의 커링(Curring) (0) | 2024.03.25 |
댓글