Scala 스터디 1

young·2021년 9월 26일
0

Scala

  • 객체 지향 언어 + 함수형 언어
  • JVM 위에서 동작해 자바의 모든 라이브러리 사용 가능

객체

  • 스칼라는 기본 자료형, 함수, 클래스 등 모든 것을 객체 취급
objectdescription
Unit리턴값이 없음을 표현
Option값이 있거나 없는 상태를 표현

*==, != 연산자로 문자열/객체 등 비교 가능

자료형

  • 자료형은 자바와 동일하면서 모든 것이 클래스
  • 변수 타입을 선언하지 않으면 컴파일러가 자동으로 정수형은 Int, 실수형은 Double로 선언
기본 자료형참조 자료형
Byte, Short, Int, Long, Float, Double, Char, BooleanString, Unit, Null, Nothing, Any, AnyVal, AnyRef
  • 업/다운캐스팅
scala> s = b	// 업캐스팅은 자동으로 진행 (8bit > 16bit) 
scala> i = l	// error: 64bit > 32bit
<console> error: type mismatch;
...
scala> i = l.toInt	// 다운캐스팅은 변환 메소드를 이용해 명시적으로 진행
  • 데이터 형 선언
// 암시적 선언
scala> var x = 10

// 명시적 선언
scala> var b: Byte = 10 
scala> var f = 10.0f

문자열

  • 문자열은 쌍따옴표("), 멀티라인 문자열은 세 개의 쌍따옴표(""") 이용
// 접두어 s: ${변수명}으로 문자열 안의 변수를 값으로 치환 
scala> val name = "David"
scala> println(s"Hello ${name})
Hello David
scala> println(s"${1+1}")
2

// 접두어 f: 문자열 format 처리
scala> val height:Double = 182.3
scala> val name = "James"
scala> println(f"$name%s is $height%2.2f meters tall") 
James is 182.30 meters tall

// 접두어 raw: 특수 문자를 처리하지 않고 원본 문자로 인식 
scala> raw"David\n\nJames"
res0: String = David\n\nJames

변수

가변 변수 var불변 변수 val
재할당 가능재할당 불가능 (오류 발생)
데이터를 단순하게 처리할 수 있음

함수

  • 리턴문/리턴 타입은 생략 가능하지만 매개변수의 파라미터 타입은 생략 불가능
  • 리턴값이 없는 함수를 선언할 때는 Unit을 이용
  • 리턴문이 생략되고 리턴 타입이 Unit이 아니면, 함수의 마지막 값을 리턴
scala> def add(x: Int, y: Int): Int = { return x+y }	// 함수 선언
scala> def add(x: Int): Int = { x = 10 } 	// x는 val이므로 변경 불가
scala> def add(x: Int, y: Double) = { x+y } 	// 리턴 타입 생략
scala> def add(x: Int, y: Int): Unit = { println(x+y) }	// 리턴 데이터가 없는 경우 Unit 선언 
scala> def add(x: Int, y: Int) = { println(x+y) }	// 리턴 타입 Unit도 생략

scala> def printUpper(msg:String):Unit = println(msg.toUpperCase())	// {} 없이 선언 가능 
scala> def printLower(msg:String) = println(msg.toLowerCase())	// 리턴 타입 생략

// 파라미터 기본값 설정
scala> def add(x: Int, y: Int=10) = { println(x+y) }	// y에 기본값 
scala> add(1)
11
scala> add(10, 3)
13
  • 같은 타입의 개수가 다른 가변 길이의 파라미터를 입력받을 때 *를 이용하면 Seq형으로 변환되어 입력
scala> def sum(num: Int*) = num.reduce(_+_) 
scala> sum(1, 2, 3)
res0: Int = 6
  • 함수를 var/val로 선언하면 함수를 실행해 그 반환값을 변수에 저장
scala> val random1 = Math.random()	// random1과 random2는 선언 시점에 값 확정 scala> var random2 = Math.random()
scala> def random3 = Math.random()	// 실행 시점에 값 확정
  • 함수를 중첩해 선언하고 사용 가능
scala> def run() {
	| 	def middle() {
	| 		println("middle")
	|	}
	| 	println("start") 
	| 	middle()
	| 	println("end")
	| }
scala> run 
start 
middle 
run

1) 람다 함수

  • 언더바 _를 이용해 묵시적인 파라미터 지정 가능
  • 묵시적인 파라미터를 이용할 때는 언더바의 위치에 따라 파라미터 선택
// exec는 3개의 파라미터(함수 f, x, y)
scala> def exec(f: (Int, Int) => Int, x: Int, y: Int) = f(x, y)

scala> exec((x: Int, y: Int) => x+y, 2, 3)	// 람다 함수(x+y) 전달
res0: Int = 5
scala> exec((x, y) => x+y, 7, 3)	// 함수 선언 시 타입을 입력했기 때문에 추가적인 설정 없이도 처리 가능 
res1: Int = 10
scala> exec((x, y) => x-y, 7, 3)
res2: Int = 4
scala> exec(_+_, 3, 1)	// 언더바 _를 이용해 묵시적인 처리
res3: Int = 4

2) 커링

  • 여러 개의 인수 목록을 여러 개의 괄호로 정의할 수 있음
  • 함수를 정해진 인수의 수보다 적은 인수로 호출하면 그 리턴 값은 나머지 인수를 받는 함수
  • 커링을 이용해 파라미터 값을 미리 바인딩 하는 다른 함수로 선언하거나, 다른 함수의 파라미터로 전달할 수 있음
// x를 n으로 나누어 나머지가 0인지 확인하는 함수 
scala> def modN(n: Int)(x: Int) = ((x%n) == 0)
// 커링을 이용해 modN 함수를 n 값이 정해진 변수로 호출 
scala> def modOne:Int => Boolean = modN(1)
scala> def modTwo = modN(2) _

scala> println(modOne(4)) 
true
scala> println(modTwo(5)) 
false

3) 클로저

  • 내부에 참조되는 모든 인수에 대한 묵시적 바인딩을 지닌 함수로 자신이 참조하는 것들의 문맥 포함
  • 클로저 블록에 코드를 바인딩함으로써 그 블록의 실행을 나중으로 연기할 수 있음 (지연 실행)
scala> def divide(n:Int) = (x:Int) => { x/n }	// divide는 x/n인 함수 반환
scala> def divideFive = divide(5)	// n에 5를 바인딩
scala> println(divideFive(10))
2

scala> var factor = 10
scala> def multiplier = (x:Int) => x*factor 
scala> println(multiplier(4))
40

4) 타입

  • 타입을 이용해 클래스와 함수를 제네릭하게 생성 가능
// 클래스 적용
scala> import scala.collection.mutable	// scala는 기본적으로 불변 데이터를 이용하기 때문에 변경가능한 스택처리를 위해 import 추가
scala> trait TestStack[T] {	// trait: scala에서의 interface 
	| 	def pop():T
	| 	def push(value:T)
	| }
scala> class StackSample[T] extends TestStack[T] {
	| 	val stack = new scala.collection.mutable.Stack[T] 
	| 	override def pop(): T = {
	|		stack.pop()
	| 	}
	| 	override def push(value:T) {
	|		stack.push(value)
	| 	}
	| }
scala> val s = new StackSample[String] 
scala> s.push("1")
scala> s.push("2")
scala> s.pop()
1
scala> s.pop()
2

// 메소드 적용
scala> def sample[K](key:K) { println(key) } 
scala> def sample2 = sample[String] _ 
scala> sample2("Hello")
Hello

0개의 댓글