Skip to content

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

트레이트 (trait) 특징

  • 믹스인(mix in) : with
    • 트레이트의 믹스인(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

케이스(case) 클래스와 패턴 매치

  • 케이스 클래스는 손쉽게 내용을 어떤 클래스에 저장하고, 그에 따라 매치를 하고 싶은 경우 사용한다. 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 : 주어진 인자를 받을 수 있는지
    • for 표현식에서 패턴 사용하기
  • Scala의 partially applied function과 partial function 이해하기

  • https://blog.outsider.ne.kr/953)

// 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
Clone this wiki locally