Functional Progrmaming Principles in Scala 수업을 듣고 스터디를 하면서 배운 스칼라의 문법 및 언어 특징들을 Haskell과 비교하면서 적어본다.
Type inference
Scala는 함수를 정의할 때 return type이 무엇인지 생략해도 알아서 추론을 할 수 있다.
scala> def double (x: Int) = x * 2
scala> :type double
(x: Int)Int
하지만 formal parameter의 타입은 생략할 수 없다.
scala> def double (x) = x * 2
<console>:1: error: ':' expected but ')' found.
def double(x) = x * 2
^
Haskell은 둘 다 생략해도 정확하게 추론해준다.
Prelude> let double x = x * 2
Prelude> :t double
double :: Num a => a -> a
currying
Scala는 currying을 쉽게 할 수 있도록, multiple parameter list를 지원한다.
scala> def sum1 (x: Int, y: Int) = x + y
scala> def sum2 (x: Int)(y: Int) = x + y
scala> sum1(3, 4) == sum2(3)(4)
res2: Boolean = true
Haskell도 지원한다.
Prelude> let sum1 (x, y) = x + y
Prelude> let sum2 x y = x + y
Prelude> sum1(3, 4) == sum2 3 4
True
Haskell은 어째 후자가 더 자연스러워보인다.
High order function
Scala에서 function은 first class citizen이다.
scala> def apply (f: Int => Int, x: Int) = f(x)
scala> def double (x: Int) = > x * 2
scala> apply(double, 4)
res1: Int = 8
apply의 첫번째 parameter에 들어갈 함수가 Int가 아닌 다른 타입을 다룰 수 있게 하려면 다음과 같이 타입 파라메터를 명시해야한다.
scala> def apply[T, U](f: T => U, x: T) = f(x)
scala> def double (x: Int) => x * 2
scala> apply(double, 4)
res2: Int = 8
scala> def hello (x: String) => "hello, " + x
scala> apply(hello, "world")
res3: java.lang.String = hello, world
Haskell은 타입 추론이 잘 되니 타입 파라메터가 필요없다.
Prelude> let apply (f, x) = f x
Prelude> let double x = x * 2
Prelude> apply(double, 4)
8
Prelude> let hello x = "hello, " ++ x
Prelude> apply(hello, "world")
"hello, world"
Anonymous function
Scala에서 익명 함수(anonymous function)를 정의하는 문법은 보통 함수을 정의하는 문법과 살짝 다르다.
scala> def sum (x: Int, y: Int) = x + y
scala> sum(3, 4)
res1: Int = 7
scala> ((x: Int, y: Int) => x + y)(3, 4)
res2: Int = 7
솔직히 항상 헷갈린다. 특히 =
가 =>
로 바뀌는 부분이.
Haskell도 마찬가지로 익명 함수 정의 문법이 별도로 있다.
Prelude> let sum x y = x + y
Prelude> sum 3 4
7
Prelude> (x y -> x + y) 3 4
7
Haskell도 =
가 ->
로 바뀐다. 뿐만 아니라 파라메터 목록 앞에 가 더해진다.
Scala나 Haskell이 맨날 쓰는 언어면 익명함수 문법 정도 그냥 외워버리겠지만 어쩌다 한번 쓰는거다보니 매번 까먹고 적어놓은 것을 뒤적거리게 된다.
C++의 템플릿같은 걸 Scala나 Java에서는 보통 제네릭이라고 부르는데, 실제로 하는 역할도 C++의 템플릿과는 조금 다릅니다.
좋아요좋아요
고맙습니다. 사실 저건 [T, U] 요 부분을 가리키는 단어를 몰라서 애매하고 정확하지 않은 표현을 해버렸던 것 같네요. “템플릿을 써야 한다” 대신 “타입 매개변수(Type parameter)를 명시해야 한다.” 정도로 고쳐야겠습니다.
좋아요좋아요