스칼라 (프로그래밍 언어)

위키백과, 우리 모두의 백과사전.
이동: 둘러보기, 검색
스칼라
Scala
패러다임 프로그래밍 패러다임: 함수형 프로그래밍, 객체 지향 프로그래밍, 명령형 프로그래밍, 병행 컴퓨팅
발표년도 2004년 1월 20일
설계자 마틴 오데스키
개발자 École Polytechnique Fédérale de Lausanne
최근 버전 2.12.2
최근 버전 출시일 2017년 4월 18일(7달 전)(2017-04-18)
영향을 받은 언어 에펠, 얼랭, 하스켈, 자바, 리스프, 피자, 스텔데드 ML, OCaml, 스킴, 스몰토크, 오즈
영향을 준 언어 실론, 팬텀, F#, 코틀린, 랩소, 레드
라이선스 BSD 라이선스
사용 중인 파일 확장자 .scala, .sc

스칼라(영어: Scala)는 객체 지향 프로그래밍 언어함수형 프로그래밍의 요소가 결합된 다중패러다임 프로그래밍 언어이다. 스칼라의 이름은 <skah-lah>라고 발음하며 'Scalable Language'에서 따왔다.

기존의 Java 언어가 너무 복잡하다는 단점을 극복하기 위해 2004년 Martin Odersky가 처음 개발하여 배포했다. 간결한 소스 코드를 사용하여 Java에서 구현할 수 있는 대부분의 기능을 구현할 수 있다.[1] Scala는 자바 바이트코드를 사용하기 때문에 자바 가상 머신(JVM)에서 실행할 수 있고, Java 언어와 호환되어 대부분의 자바 API를 그대로 사용할 수 있다.

개요[편집]

스칼라는 다른 언어로 표현할 수 있는 패턴을 매우 간결하게 표현할 수 있는 범용 프로그래밍 언어이다. 객체 지향 프로그래밍 언어함수형 프로그래밍의 요소의 결합과 자바 API의 적용을 통해 프로그래머의 생산성을 높이는데 도움을 준다. 그 예로 같은 기능을 하는 프로그램을 작성했을 때 자바로 작성했을 때에 비해 2-3배의 코드 길이가 줄어든다.[2]

자바 런타임 환경(런타임 환경 (JRE))과의 상호 호환성이 좋으며, .NET을 위한 지원도 제공하고 있다.[3]

영향받은 언어[편집]

스칼라는 많은 언어로부터 프로그래밍의 다양한 개념을 차용하여 쓰고있다.[1] 그 목록은 아래와 같다:

자바와의 연관성[편집]

공통점[편집]

대부분의 스칼라 관련 문서들에서 스칼라와 자바의 연관성을 '너무 바빠서 다른 언어를 따로 배울 시간이 없는 자바 프로그래머를 위한'[4] 이라는 표현을 사용하여 나타낼 정도로 비슷한 부분이 많이 나타난다...

패키지[편집]

import 키워드를 통해 사용할 패키지의 선언을 한다. 이 때 _(밑줄, underscore)을 사용함을 통해 패키지나 객체의 멤버에 대해 접근성을 향상시킬 수 있다.

import java.util.Scanner
import scala.collection.mutable._

자바 API의 사용[편집]

스칼라에서는 자바 API도 사용할 수 있다. 다음은 java.util.Scanner를 통해 문자열 입력을 받아 출력하는 예제이다.

import java.util._

object Example1 {
  val s = new Scanner(System.in)
  def main(args: Array[String]): Unit = {
    println("Your input: " + s.nextLine)
  }
}

실행 환경[편집]

스칼라 고유의 라이브러리 파일을 추가로 가지고 있으면 기존의 자바 가상 머신에서 그대로 실행할 수 있다. 다음은 리눅스에서 자바 실행기(CUI환경)를 통해 스칼라로 컴파일한 프로그램을 실행하는 예이다.(bin에 클래스 파일들이, lib에 스칼라 라이브러리 파일들이 있다고 가정한다.)

java -cp .:./bin:./lib/* Example1

차이점[편집]

타입 추론[편집]

자료형[편집]

자바에서의 자료형은 기본 자료형(int, short, long, float, double, byte, char, boolean)과 참조 자료형(기본 자료형의 조합으로 생성한 클래스)으로 나뉜다. 이는 성능에는 도움이 될 지 몰라도 기본 자료형과 참조 자료형 간의 변환 문제로 언어의 표현이 복잡해지는 경향이 있다. 이에 반해 스칼라에서는 스몰토크루비와 같이 모든 자료형을 객체로 취급하고 있다.[5] 그 예로 3 + 4 와 같은 수식은 정수 3의 메소드 +를 4라는 정수 인자값으로 호출한다고 표현하여 (3).+(4) 와 같이 표현할 수 있다. 스칼라의 모든 객체는 scala 패키지의 Any를 최상위 클래스로 값(AnyVal)과 레퍼런스(AnyRef)를 모두 아우르고 있다.[5][6]

싱글턴 객체[편집]

자바에서는 생성자를 private를 통해 선언함과 메소드를 static으로 선언함을 통해 싱글턴 객체를 생성한다. 이렇게 생성된 객체는 생성자가 private으로 선언되어있기 때문에 새로 객체를 생성할 수 없고 static 메소드를 통해 어디서나 접근하는 것이 가능하다. 하지만 static은 객체지향이 지향하는 바에 부합하지도 않을 뿐 더러 객체를 프로그램 실행 초기에 미리 생성해두어야 하기 때문에 자원의 낭비 가능성이 존재하게 된다.[7] 이를 스칼라에서는 object라는 키워드를 통해 선언한다. 내부동작에는 크게 차이가 없으나 코드 표현에 있어서 간결성을 보인다.

다중 상속[편집]

스칼라 API[편집]

자바 API[편집]

예제[편집]

Hello, world 프로그램[편집]

object HelloWorld {
  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
}

Hello, world 프로그램 2[편집]

object HelloWorld extends App {
  println "Hello, world!"
}

Quick Sort 프로그램[편집]

명령형 프로그래밍 방식으로 구현한 경우 ▼

def qsort(arr: Array[Int]): Array[Int] = {
  def swap(i: Int, j: Int): Unit = {
    val tmp = arr(i)
    arr(i) = arr(j)
    arr(j) = tmp
  }

  def partition(left: Int, right: Int): Unit =
    if (right <= left ) ()
    else {
      val pivot = arr((left + right) / 2)
      var i = left
      var j = right

      while (i <= j) {
        while (arr(i) < pivot) i += 1
        while (arr(j) > pivot) j -= 1

        if (i <= j) {
          swap(i, j)

          i += 1
          j -= 1
        }
      }

    if (left < j) partition(left, j)
    if (j < right) partition(i, right)
  }

  partition(0, arr.length - 1)
  arr
}

if-else문을 사용한 경우 ▼

def qsort(seq: Seq[Int]): Seq[Int] =
  if (seq.isEmpty) seq
  else {
    val (pivot, rest) = (seq.head, seq.tail)
    val (lt, ge) = rest partition { _ < pivot }
    qsort(lt) ++ (pivot +: qsort(ge))
  }

패턴 매칭을 활용한 경우 ▼

def qsort(seq: Seq[Int]): Seq[Int] = seq match {
  case pivot +: rest =>
    val (lt, ge) = rest partition { _ < pivot }
    qsort(lt) ++ (pivot +: qsort(ge))
  case _             =>
    seq
}

제네릭을 활용한 경우 ▼

def qsort[T](seq: Seq[T], lessThan: (T, T) => Boolean): Seq[T] = seq match {
  case pivot +: rest =>
    val (lt, ge) = rest partition { lessThan(_, pivot) }
    qsort(lt, lessThan) ++ (pivot +: qsort(ge, lessThan))
  case _             =>
    seq
}

뷰 바운드(View Bounds)을 활용한 경우 ▼

def qsort[T <% Ordered[T]](seq: Seq[T]): Seq[T] = seq match {
  case pivot +: rest =>
    val (lt, ge) = rest partition { _ < pivot }
    qsort(lt) ++ (pivot +: qsort(ge))
  case _             =>
    seq
}

컨텍스트 바운드(Context Bounds)을 활용한 경우 ▼

def qsort[T: Ordering](seq: Seq[T]): Seq[T] = seq match {
  case pivot +: rest =>
    val (lt, ge) =
      rest partition { implicitly[Ordering[T]].lt(_, pivot) }
    qsort(lt) ++ (pivot +: qsort(ge))
  case _             =>
    seq
}

각주[편집]

  1. Programming in Scala, Martin Odersky, Lex Spoon, Bill Venners. Artima Press
  2. The Scala Programming Language | The Scala Programming Language
  3. Scala Distribution | The Scala Programming Language
  4. http://www.ibm.com/developerworks/java/library/j-scala01228.html - The busy Java developer's guide to Scala
  5. 서광열의 프로그래밍 언어 이야기, 마이크로소프트웨어 2008년 5월호
  6. Programming in Scala, Martin Odersky, Lex Spoon, Bill Venners. Artima Press
  7. http://kyungseo.pe.kr/blog/111 - 결론>정적 클래스 변수(메서드) vs. 싱글턴 패턴

외부 링크[편집]