Scala 설치
$ brew install scalaScala
- 
확장 가능한 언어(SCAlable LAnguage)의 약자 
- 
2003년 마틴 오더스키(Martin Odersky) 교수와 EPFL(로잔 공과 대학)의 연구진이 JVM 플랫폼에서 FP와 OOP를 동시에 지원하는, 성능이 우수한 환경을 제공하기 위해 이 언어를 만듬 
- 
JVM 언어로 자바 런타임을 사용 
- 
REPL(Real-Eval-Print-Loop) 셸 제공 
- 
정적 타입 지원 - 정적 타입 언어
- 
컴파일 시간에 변수의 타입을 알게 되면 정적 타입 언어라고 함 
 
타입
- 
Any: 모든 타입들의 슈퍼타입, 직접적으로 두 개의 서브타입을 가지고 있음(AnyVal,AnyRef)
- 
AnyVal: 모든 값 타입의 루트, 9개의 값 타입이 있음(Double,Float,Long,Int,Short,Byte,Char,Unit,Boolean)
- 
AnyRef: 모든 참조 타입의 루트,java.lang.Object에 해당
- 
Noting: 모든 타입의 서브타입(바텀타입)
- 
Null: 모든 참조 타입의 서브타입
- 
Char: 숫자형 데이터 타입에도 등장할 수 있는 유일한 타입. String 타입의 기본이 되는 타입으로 단일 문자. Char 리터럴은 single quoter로 작성
- 
Boolean: true 혹은 boolean. 다른 언어들과 달리 불이 아닌 다른 값을 변환하지 않음(숫자 0은 false와 다름)
- 
Unit: 데이터 타입을 나타내는 대신 데이터가 없음을 나타냄. Unit 리터럴은 빈 괄호.val nada = ()
Tuple
- 
튜플은 둘 이상의 값을 가지는 순서가 있는 컨테이너 구문: 튜플 생성// ( <값 1>, <값 2[, <값 3>...] ) val info = (5, "Korben", true)
- 
튜플의 각 항목은 1부터 시작하는 인덱스를 이용하여 접근 가능 val name = info._2
- 
화살표 연산자( →)를 사용하는 방식도 존재. 튜플에서 키-값 쌍을 표현하는 가장 보편적인 방법scala> val red = "red" -> "0xff0000" red: (String, String) = (red, 0xff0000) scala> val reversed = red._2 -> red._1 reserved: (String, String) = (0xff0000,red)
String
- 
multiline literal, interpolation(보간) 기능 추가 
- 
자바와 달리 등호 연산자( ==)는 객체 참조가 같은지 검사하지 않고 실제 값이 같은지 검사함
- 
여러 줄의 String인 double quoter 세 개를 이용하여 생성 // 특수 문자의 시작을 나타내는 역슬래시를 인지하지 못함 scala> val str = """She suggested reformatting the file | by replacing tabs(\t) with newlines (\n); | "Why do that?", he asked. """ str: String = "She suggested reformatting the file by replacing tabs(\t) with newlines (\n); "Why do that?", he asked. "
- 
문자열 보간(string interpolation)은 첫 큰 따옴표 전에 접두사 s를 추가하여 표기.scala> println(s"Pi, using 355/113, is about $approx.") Pi, using 355/113, is about 3.141593. scala> val item = "apple" item: String = apple scala> s"How do you like them ${item}s?" res0: String = How do you like them apples? scala> s"Fish n chips n vinegar, ${"pepper " * 3}salt" res1: String = Fish n chips n vinegar, pepper pepper pepper salt
- 
문자열 보간의 또 다른 포맷은 printf 표기법을 사용하는 것(접두사 f사용)scala> val item = "apple" item: String = apple scala> f"I wrote a new $item%.3s today" // (1) res0: String = I wrote a new app today scala> f"Enjoying this $item ${355/113.0}%.5f times today" // (1) res1: String = Enjoying this apple 3.14159 times today- 
printf 표기법이 읽기는 다소 어렵지만, 출력을 근본적으로 제어할 수 있는 장점 
 
- 
Rich Wrapper classes
- 
스칼라에는 원시(primitive) 데이터 타입 개념 없음 
- 
Java의 primitive 타입을 표현하는데 사용 
문법
선언
- 
값과 변수는 관례상 소문자로 시작 → camelCas 
- 
문자, 숫자, 연산자 기호 사용 가능 
| Note | 연산자(operator) \u0020에서 \u007F 사이의 문자와 유니코드 Sm[Symbol/Math] 카테고리에서 대괄호와 마침표를 제외한 모든 문자 | 
- 
스칼라에서는 연산자 오버로딩을 지원하지 않음 
- 
연산자는 단순히 메서드 
- 
메서드 이름이 :으로 끝나면 오른쪽 결합이 된다.scala> val my_list = List(1, 2, 3, 4) my_list: List[Int] = List(1, 2, 3, 4) scala> val my_result1 = my_list :+ 5 my_result1: List[Int] = List(1, 2, 3, 4, 5) scala> val my_result2 = 0 +: my_list my_result2: List[Int] = List(0, 1, 2, 3, 4)
Variable
- 
mutable한 값 
- 
변수에 재할당은 가능하지만 지정된 타입을 바꿀 수는 없음 
varvar <name>: <type> = <literal>scala> var x: Int = 5
x: Int = 5
scala> x = 3
x: Int = 3Value
- 
immutable한 값 
- 
데이터를 통해 타입 추론(type inference)이 가능하여 type을 생략할 수 있음 
valval <name>[: <type>] = <literal>scala> val x: Int = 5
x: Int = 5
scala> x = 3
         ^
       error: reassignment to valLazy Value
- 
Regular Expression - 
자바 클래스 java.util.regex.Pattern에 기반함
- 
String 타입은 정규 표현식을 지원하는 built-in 연산을 제공 - 
matches scala> "Froggy went a' courting" matches ".*courting" res0: Boolean = true
- 
replaceAll scala> "milk, tea, muck" replaceAll ("m[^ ]+k", "coffie") res0: String = coffie, tea, coffie
- 
replaceFirst scala> "milk, tea, muck" replaceFirst ("m[^ ]+k", "coffie") res0: String = coffie, tea, muck
 
- 
- 
정규표현식으로 값 캡쳐하기 - 
r연산자를 호출하여 문자열을 정규 표현식 타입으로 전환
- 
Regex 인스턴스를 반환 
- 
Capture Group은 정규 표현식 패턴을 기반으로 주어진 문자열에서 항목을 선택하고 이를 로컬 값으로 전환할 수 있게 해줌 
- 
패턴은 최소 하나의 괄호로 정의된 캡처 그룹을 포함해야 함 
- 
역슬래시를 인식하기 위해 multiline string을 사용 scala> val input = "Enjoying this apple 3.14159 times today" input: String = Enjoying this apple 3.14159 times today scala> val pattern = """.* apple ([\d.]+) times .*""".r (1) pattern: scala.util.matching.Regex = .* apple ([\d.]+) times .* (2) scala> val pattern(amountText) = input amountText: String = 3.14159 (3) scala> val amount = amountText.toDouble amount: Double = 3.14159 (4)- 
.r을 붙혀 Regex 인스턴스를 반환 받음
- 
정규표현식 타입은 scala.util.matching.Regex또는 간단히util.matching.Regex
- 
val <regex value>(<name>) = <input string>
- 
Convert String type to Double type 
 
- 
 
- 
 
- 
조건문, 반복문
표현식
표현식(expression)은 값을 반환하는 코드의 단위
val <name>[: <type> = <expression>
var <name>[: <type> = <expression>표현식 블록(expression block)
scala> val x = 5 * 20; val amount = x + 10
x: Int = 100
amount: Int = 110scala> val amount = {val x = 5 * 20; x + 10} // (1)
amount: Int = 110- 
블록의 마지막 표현식은 블록의 반환값을 결정한다. 
scala> val amount = {
    val x = 5 * 20
    x + 10
}
amount: Int = 110문장
- 
문장(statement)은 값을 반환하지 않는 표현식 
- 
문장의 반환 타입은 값이 없음을 나타내는 Unit 
- 
아래 코드의 값 정의는 어떤 것도 반환하지 않기 때문에 문장에 해당함 scala> val x = 1 x: Int = 1
If .. Else expression block
- 
스칼라는 하나의 'if’와 선택적인 'else' 블록만을 지원 
- 
'else if' 블록을 단일 구성체로 인식하지 않음 
- 
스칼라에서 if와 else 블록은 한 줄에 간결하게 맞아떨어지기 때문에 삼항 표현식이 실제로 필요하지 않음 
// if (<부울식>) <표현식>
// if (<부울식>) <표현식> else <표현식>
scala> if (47 % 3 > 0 ) println("Not a multiple of 3")
Not a multiple of 3
scala> val result = if ( false ) "what does this return?"
result: Any = ()
scala> val x = 10; val y = 20
x: Int = 10
y: Int = 20
scala> val max = if (x > y) x else y
max: Int = 20Match Expression
- 
자바의 'switch’문과 유사 
- 
표현식은 단 하나의 패턴만 매칭할 수 있으므로 여러 개의 패턴을 한 번에 순서대로 매칭하는 형태의 제어 이동(fall-through)이 없음 - 
중간에 그 제거 이동에서 빠져나오는 'break' 문도 없음 
 
- 
- 
실제로 대부분 스칼라 개발자는 'if..else' 블록보다 매치 표현식을 더 선호. 표현력이 좋고 구문이 간결하기 때문 
- 
여러 패턴을 하나로 결합하여 그 패턴 중 하나라도 일치하면 case 블록을 동작시키려면 패턴 대안(pattern alternative) 
- 
매칭되는 것이 없는 에러를 예방하려면 wildcard match-all 패턴 사용 
- 
패턴 가드(pattern guard)는 값 바인딩 패턴에 if 표현식을 추가하여 match 표현식에 조건부 로직을 섞어 쓸 수 있음 
<expression> match {
  case <pattern match> => <expression>
  [case...]
}scala> val x = 10; val y = 20;
x: Int = 10
y: Int = 20
scala> val max = x > y match {
        case true => x
        case false => y
}
max: Int = 20scala> val status = 500
status: Int = 500
scala> val message = status match {
        case 200 =>
            "ok"
        case 400 => {
            println("ERROR - we called the service incorrectly")
            "error"
        }
        case 500 => {
            println("ERROR - the service encountered an error")
            "error"
        }
}
ERROR - the service encountered an error
message: String = errorscala> val day = "MON"
day: String = MON
scala> val kind = day match {
    case "MON" | "TUE" | "WED" | "THU" | "FRI" =>
        "weekday"
    case "SAT" | "SUN" =>
        "weekend"
}
kind: String = weekdayscala> val message = "OK"
message: String = OK
scala> val status = message match {
    case "OK" => 200
    case other => { // (1)
        println(s"Couldn't parse $other")
        -1
    }
}
status: Int = 200- 
other는 case 블록이 유지되는 동안 정의
scala> val message = "Unauthorized"
message: String = Unauthorized
scala> val status = message match {
    case "Ok" => 200
    case _ => {
        println(s"Couldn't parse $message")
        -1
    }
}
Couldn't parse Unauthorized
status: Int = -1함수
- 
return 키워드는 선택적이기 때문에 스칼라 컴파일러는 return 키워드가 없으면 마지막 할당 값을 리턴하게 설계됨 
중첩 함수
nested function
for comprehensions
Implicit
monad
Collection
Import문
import math._ // (1)
import math.{sin, cos} // (2)
import scala.collection.mutable.{Map => MutableMap} // (3)
import math.{cos => _, _} // (4)- 
_(underscore) 는 Java의*(asterisk)와 비슷하게 와일드카드로, math 패키지의 모든 것을 import 한다.
- 
{ }를 통해 math 패키지에 일부만 import 한다.
- 
이름을 변경해서 import 할 수 있다. 
- 
math 패키지를 모두 import하지만 cos는 안보이게 한다. 
컬렉션
Currying
객체지향
생성자
보조 생성자
오브젝트
- 
정적메서드 대신 오브젝트 
- 
클래스의 컴패니언 
트레이트
trait
- 
트레이트는 타입 파라미터만 가질 수 있다