간단한 예제
object MyModule {
def abs(n: Int): Int =
if (n < 0) - n
else n
private def formatAbs(x: Int) = {
val msg = "The absolute value of %d is %d"
msg.format(x, abs(x))
}
def main(args: Array[String]): Unit =
println(formatAbs(-42))
}이 프로그램은 MyModule이라는 이름의 객체를 선언한다. 스칼라 코드는 반드시 object로 선언되는 객체나 class로 선언되는 클래스 안에 들어가야 한다.
object 키워드는 singleton을 만든다. 스칼라에는 java의 static 키워드에 해당하는 것이 없다.
프로그램을 실행할 때 main이라는 이름의 메서드를 찾는다. main메서드는 반드시 String의 Array를 인수로 받아야 하며, 반환 형식은 반드시 Unit이어야 한다. 일반적으로 Unit이라는 것은 그 메서드에 부수 효과가 존재함을 암시한다.
프로그램의 실행
$ scalac MyModule.scala
이렇게 하면 확장자가 .class인 파일들이 생긴다. 그 코드를 scala를 이용해서 실행할 수 있다.
$ scala MyModule
결과 : The absolute value of -42 is 42.
간단한 프로그램이라면 scala interpreter로 실행도 가능하다.
$ scala MyModule.scala
결과 : The absolute value of -42 is 42.
REPL(read-evaluate-print loop) 모드에서 소스파일을 불러서 실행해 볼 수도 있다.
$ scala
scala> :load MyModule.scala
scala> MyModule.abs(-42)
res0: Int = 42
고차 함수(higher-order function)
함수를 함수에 전달. 함수도 변수에 담거나 함수에 인수로 넘겨줄 수 있다.
꼬리 재귀
재귀 호출이 꼬리 위치에서 일어나는 것을 말한다. 재귀 호출의 결과값 반환 이후에 다른 일을 하지 않는다면 최적화(tail call elimination)가 적용된다. 매 반복마다 스택을 소모하지 않도록 루프 형태로 컴파일 되게 한다.
def factorial(n: Int): Int = {
def go(n: Int, acc: Int): Int =
if (n <= 0) acc
else go(n - 1, n \* acc)
go(n, 1)
}위 예제에서 재귀 호출 go(n - 1, n _ acc)는 꼬리 위치에서 일어난다. 1 + go(n - 1, n _ acc) 같은 재귀 호출은 꼬리 호출이 아니다. go의 결과에 대해 1을 더하는 일을 수행해야 하기 때문이다.
고차 함수 작성
object MyModule {
...
def formatResult(n: Int, f: Int => Int): Int = {
val msg = "The factorial of %d is %d."
msg.format(n, f(n))
}
}scala> formatResult(7, factorial)
res0: String = “The factorial of 7 is 5040.”
factorial을 f의 인수로서 formatResult에 넘겨줄 수 있다.
단형적 함수(monomorphic function)
// String 형식에만 특화되어 있다.
def findFirst(ss: Array[String], key: String): Int = {
@annotation.tailrec
def loop(n: Int): Int =
if (n >= ss.length) -1
else if (ss(n) == key) n
else loop(n + 1)
loop(0) // 배열의 첫 요소에서부터 루프를 시작한다.
}다형적 함수(parametric polymorphism)
// 임의의 형식 A에 대해 특정 A 값을 점검하는 함수를 인수로 받음
def findFirst[A](as: Array[A], p: A => Boolean): Int = {
@annotation.tailrec
def loop(n: Int): Int =
if (n >= as.length) -1
else if (p(as(n))) n
else loop(n + 1)
loop(0)
}부분 적용(partial application)
32p
커링(curring)
..작성중