-
Couldn't load subscription status.
- Fork 8
lhs review2
Hyungsok Lee edited this page May 4, 2016
·
10 revisions
- 데이터 전달 객체, 인자 객체
- Tuple 22인자까지만
- 장점
- 여러개의 타입 값을 간단하게 하나의 단위로 묶을 수 있음
- 여러개의 반환값을 쉽게 리턴시켜줄 수 있음
val myTuple = (123, "abc")
myTuple._1 : 123
myTuple._2 : "abc"- 함수 리터럴
- (a:Int)=> a+1 : Funtion1
- Function Literal과 Function Value 구분점은?
- Function Value은 함수 리터럴을 이용해 만든 인스턴스
- 클로져 (Closure)
- function 의 범위 밖에 있는 variable 을 function 에서 쓸수있는 기능
var factor = 3
val multiplier = (i:Int) => i * factor- 믹스인(mix in) : with
- 트레이트의 믹스인(with)은 다중상속(implements)과 중요한 차이가 있다!
- 트레이트는 풍부한 인터페이스를 가졌다.(메소드 구현을 넣을 수 있음 )
- 자바는 메소드 구현을 해줘야 함
- 트레이트의 믹스인(with)은 다중상속(implements)과 중요한 차이가 있다!
- thin & rich interface
- stackable modification
- 맨오른쪽 부터 상위 클래스에서 올라가는 형식
trait A {
def a = {
print(" A ")
}
}
trait X extends A {
override def a = {
print(" X ")
super.a
}
}
trait Y extends A {
override def a = {
print(" Y ")
super.a
}
}
trait Z extends Y {
override def a = {
print(" Z ")
super.a
}
}
// 계층
> A - X
> A - Y - Z
new AnyRef with X with Y // Y X A
new AnyRef with Y with X // X Y A
new X with A with Y // Y X A
new Z with Y with A with X // X Z Y A
new Z with X with A with Y // X Z Y A
new X with Z with A with Y // Z Y X A
new A with Z with Y with X // X Z Y A
-
케이스 클래스는 손쉽게 내용을 어떤 클래스에 저장하고, 그에 따라 매치를 하고 싶은 경우 사용한다. new를 사용하지 않고도 케이스 클래스의 인스턴스 생성이 가능하다.
-
케이스 클래스는 자동으로 생성자 인자에 따른 동등성 검사(hashCode, equals)를 제공하며, 또한 보기 좋은 toString 메소드도 제공
-
match 에 성공하지 않는 selector 인 경우엔 (아무런 case 에도 만족하지 않는다면) MatchError 예외가 발생하므로, 모든 가능한 경우에 대한 처리를 하고자 한다면 반드시 디폴트 케이스를 추가해야 한다.
- case _ =>
-
패턴 => 계산할 표현식
- 상수 패턴 : case '+' => x
- 와일드카드 패턴 : case _ => x
- 생성자 패턴 : case A("X", 0) => ... (생성자 파라미터 오버로딩)
- 변수 패턴 : case xx => "xx : " + xx (와일드카드처럼 어떤객체와 매치)
- 시퀀스 패턴 : case List(0, _, _) => println("fount it")
- 튜플 패턴 : case (a, b, c) => println("matched"+a+b+c)
- 타입 지정 패턴 : case s: String => s.length
- 변수 바인딩 패턴 : case UnOp("abs", e @ UnOp("abs", _)) => e
- 클래스 멤버에 매치 : case x.a == 1 => "one"
-
패턴 가드(조건문)
- case (패턴) (조건절) => 계산할 표현식
- ex> case s: String if s == 'a' => ...
-
패턴 겸침
- 하나의 match 문에서 먼저 작성된 case 를 이후 case 에서 재사용 가능
-
봉인한 클래스
- 최상의 슈퍼클래스를 (sealed)로 선언
- 컴파일러가 경고 메세지와 함께 놓친 패턴의 조합을 환기시켜줌
- 이를 막기 위한 방법은 default case 를 작성해주어 exception 을 throw 해주는 방법도 있으나 @unchecked 어노테이션을 활용하는 방법 있음
-
Option 타입 : case문에서 선택적인 값을 나타내기 위해서 사용을 권장
- Some(값), None
- None : 아무것도 아닌값, No Value (null 여부 검사 안해도 됨)
- Int형인값을 DB 검색쿼리를 날렸는데 없다? 이럴경우 없는데 0인지 null인지 무엇을 보내야할까?
- 스칼라는 이런 아무것도 아닌값에 대한 대안을 마련함
-
패턴은 어디에나
- 시퀀스로 부분함수 만들기
- PartialFuntion
- 부분함수란 일부의 입력에 대해서만 처리를 하며, 처리하지 않은 입력에 대해서는 오류의 가능성을 가지고 있거나, 혹은 종료가 되지 않는 함수를 뜻한다.
- isDefinedAt : 주어진 인자를 받을 수 있는지
- PartialFuntion
- for 표현식에서 패턴 사용하기
- 시퀀스로 부분함수 만들기
-
Scala의 partially applied function과 partial function 이해하기
// Option Type
def show(x: Option[String]) = x match {
case Some(s) => s
case None = "?"
}// 함수는 객체이다!
///////////////////////////////////////////////////////////////////
// Funtion literal ( 함수 리터럴은 실제로는 FunctionN이라는 클래스 )
scala> val sum = new Function2[Int, Int, Int] {
| def apply(a:Int, b:Int):Int = {
| a + b
| }
| }
sum: java.lang.Object with (Int, Int) => Int = <function2>
scala> sum(1,2)
res0: Int = 3
// 위와 같은 코드
def sum(a:Int, b:Int) = a + b
///////////////////////////////////////////////////////////////////
// PartialFuntion
scala> val one: PartialFunction[Int, String] = { case 1 => "one" }
one: PartialFunction[Int,String] = <function1>
scala> one.isDefinedAt(1)
res0: Boolean = true
scala> one.isDefinedAt(2)
res1: Boolean = false
scala> val two: PartialFunction[Int, String] = { case 2 => "two" }
two: PartialFunction[Int,String] = <function1>
scala> val three: PartialFunction[Int, String] = { case 3 => "three" }
three: PartialFunction[Int,String] = <function1>
scala> val wildcard: PartialFunction[Int, String] = { case _ => "something else" }
wildcard: PartialFunction[Int,String] = <function1>
// orElse라 불리는 다른 함수를 사용해 합성이 가능
scala> val partial = one orElse two orElse three orElse wildcard
partial: PartialFunction[Int,String] = <function1>
scala> partial(5)
res24: String = something else
scala> partial(3)
res25: String = three
scala> partial(2)
res26: String = two
scala> partial(1)
res27: String = one
scala> partial(0)
res28: String = something else
///////////////////////////////////////////////////////////////////
// case 시퀀스로 부분 함수 만들기
// 컴파일러가 우선 getSecond 함수에 대해서는 warning을 알려준다. 사유는 Nil 처리가 안되어있다는 것이다.
def getSecond(x: List[Int]) = x match {
case x :: y :: _ => y
}
println(getSecond(List())) // scala.MatchError
// PartialFunction 을 이용하여 컴파일러에게 해당 함수가 부분함수임을 알려줄 필요
val getSecond: PartialFunction[List[Int], Int] = {
case x :: y :: _ => y
}
getSecond.isDefinedAt(List(1, 2, 3)) // result : true
getSecond.isDefinedAt(List()) // result : false
println(getSecond(List(1, 2, 3))) // 2
println(getSecond(List())) // scala.MatchError
val second: PartialFuntion[List[Int], Int] = {
case x :: y _ => y
}
// 같은 코드
val second = new PartialFuntion[List[Int], Int] {
def apply(xs: List[Int]) = xs match {
case x :: y :: _ => y
}
def isDefinedAt(xs: List[Int]) = xs match {
case x :: y :: _ => true
case _ => false
}
}
///////////////////////////////////////////////////////////////////
// for 표현식에서 패턴 사용하기
var captials = ("France" -> "paris", " Japan" -> "Tokyo")
for((country, city) <- capitals)
println("the capital of " + country + " is " + city)
val result = List(Some("Apple"), None, Some("orange"))
for(Some(fruit) <- result) println(fruit)
// 아래는 출력
the capital of France is Paris
the capital of Japan is Tokyo
Apple
orange