SCALA TYPE ERASURE & TYPETAG

language/scala 2017.06.30 09:28 posted by dev.bistro

다른  JVM 언어처럼 Scala  역시  컴파일시점에 type 정보를 잃어버린다.

SCALA는 JVM의 type erasure issue 를  TypeTag(이전에는 Manifest)로 해결 할 수 있다

// TODO undeprecated until Scala reflection becomes non-experimental
// @deprecated("Use `scala.reflect.ClassTag` (to capture erasures) or scala.reflect.runtime.universe.TypeTag (to capture types) or both instead", "2.10.0")
type Manifest[T]      = scala.reflect.Manifest[T]
scala> def evenElems[T : ClassTag](xs: Vector[T]): Array[T] = {
| val arr = new Array[T]((xs.length + 1) / 2)
| for (i <- 0 until xs.length by 2)
| arr(i / 2) = xs(i)
| arr
| }
evenElems: [T](xs: Vector[T])(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]

scala>

 

 

 

ClassTag는 최상위의 Class의 Type정보만을 생성해준다.
ex) ClassTag[List[String]] -> collection.immutable.List

실제로 Intellij에서 Debugging 화면에서 보면 implicit evidence 를 볼 수 있다

스크린샷 2016-06-19 오후 4.07.52

스크린샷 2016-06-19 오후 3.37.56



신고

'language > scala' 카테고리의 다른 글

SCALA TYPE ERASURE & TYPETAG  (0) 2017.06.30
SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND  (0) 2017.06.28
Superseded by Akka HTTP  (0) 2017.05.01
FP 비엄격성  (1) 2015.05.18
scala package object  (0) 2014.11.05
scala의 lazy 비용  (0) 2014.10.21

SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND

language/scala 2017.06.28 13:58 posted by dev.bistro

하나 이상의 타입인자가 있는 클래스는 ‘제네릭 클래스’이고  타입인자를 실제 타입으로 대체하면 일반 클래스이다.

1
2
3
4
class Pair[T,S](val first:T, val second:S) //제네릭 클래스
 
val p1 = new Pair(42, "String") //추론에 의해서 일반 클래스
val p2 = new Pair[Int, String](42, "String") //명시적 선언에 의해서 일반 클래스

 

함수,  메소드도 타입인자를 가질 수 있다.

1
2
3
4
5
def getMiddle[T](a: Array[T]) = a(a.length) / 2
 
ex)
getMiddle(Array("Mary", "had")) //추론의 의해서 getMiddle 호출
val f = getMiddle[String] _ //타입인자를 명시적으로 지정함

 

타입에 제한(bound)를 걸어야 할 필요가 있다. 다음의 예로 쉽게 이해 가능하다

1
2
3
4
5
6
7
8
9
10
11
class Pair[T](val first:T, val second:S) {
def smaller = if (first.compareTo(second) < 0 ) <<--여기
}
/* first가 compareTo를 가지고 있는지 확인 할 수 없기 때문에 오류가 발생한다.
이를 해결하기 위해서는 first가 'compareTo'를 항상 가지고 있으면 될 것이다. 아래처럼 */
 
class Pair[T <: Comparable[T]](val first: T, val second: T) {
def smaller = if (first.compareTo(second) < 0 )
}
/* 처럼 'T가 반드시 Comparable[T]의 sub-type'임을 지정하면 된다.
=> 그리고 'T의 상위 타입을 지정했거나, upper bound 지정,제약했다' 라고 표현 가능 */

 

그와 비슷하게 lower bound를 선언할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Queue[+T] (private val leading: List[T], val trail: List[T] ) {
def enqueue[U >: T] (x: U) = new Queue[U](leading, x :: trail)
}
// U >: T 를 이용해 T 를 U 의 하위 바운드로 지정했으니 U가 T의 슈퍼클래스여야 한다.
 
ex1)
/* Fruit 클래스에 2개의 서브 클래스 Apple, Orange가 있다.
Queue[Apple]에 Oragne를 추가할 수 있고 결과는 Queue[Fruit]가 된다. */
 
ex2)
class Animal
class Bird extends Animal
class Chicken extends Bird
 
val flock = List(new Bird, new Bird)
flock: List[Bird] = List(Bird@7e1ec70e, Bird@169ea8d2)
 
new Chicken :: flock
res53: List[Bird] = List(Chicken@56fbda05, Bird@7e1ec70e, Bird@169ea8d2)
 
// 처럼 공통적인 각기 다른 타입을 하나로 분류할 수 있는 이점이 생긴다.

 

upper , lower bound와 같은 상하위가 아니라 implicit의 암묵적 변환에도 그대로 사용하고 싶을 경우에는 <% 를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
class Pair[T <: Comparable[T] ](val first:T, val second:T)
val p = new Pair(4,2)
 
output> Error:(6, 9) inferred type arguments [Int] do not conform to class Pair's type parameter bounds [T <: Comparable[T]]
// 4, 2같은 Int는 Comparable를 구현하지 않기 때문이다 하지만 RichInt에는 있다.
 
class Pair[T <% Comparable[T] ](val first:T, val second:T)
/* 처럼 수정하면 된다. 이를 다시 풀어보면
a. T가 Comparable[T]로 암묵적 변환이 가능하다 라는 의미이다.
b. T를 Comparable[T]로 다룰수 있는 모든 T type을 사용 할 수 있다.
c. class Pair[T ](..)(implicit imp: T => Comparable[T]) 의 축약형이다.


신고

'language > scala' 카테고리의 다른 글

SCALA TYPE ERASURE & TYPETAG  (0) 2017.06.30
SCALA UPPER/LOWER TYPE BOUND & VIEW BOUND  (0) 2017.06.28
Superseded by Akka HTTP  (0) 2017.05.01
FP 비엄격성  (1) 2015.05.18
scala package object  (0) 2014.11.05
scala의 lazy 비용  (0) 2014.10.21

코틀린 1.0 으로 프로젝트를 진행 한 후 1년만에 다시 코틀린을 손에 잡았다.

뒤에 분이 '자바를 하려거든 코틀린'을 하세요~ 라는 노래를 부르고, 메인 프로젝트가 아니고 검증용 간단한 서비스를 필요로 했기에 부담없이 코틀린을 다시 쓰고 있는데....

역시 자바보다는 코틀린 ㅋ (개인적으로는 스칼라 >>>> 코틀린 >>>>>>>> 자바)


fun BufferedWriter.writeAndFlush(str: String) {
    this.write(str).let { newLine() }.let { flush() }
}


자바로 했으면 메소드를 하나 만들고  Streams.writeAndFlush(bw, str) 을 했겠지만 코틀린은 뭐 저렇게 된다는..?

저 개념 자체는 http://docs.scala-lang.org/overviews/core/implicit-classes.html 로 비슷하게? 사용 했지만

https://kotlinlang.org/docs/reference/extensions.html#extensions 'Extension' 라는 단어 자체는 SWIFT에서 먼저 접하고 사용했다. 


그리고 .let 은 정식 명칭이 멀까 찾아보니 못찾겠다 ㅋㅋ

참고 링크 1 : http://beust.com/weblog/2016/01/14/a-close-look-at-kotlins-let/
참고 링크 2: http://kunny.github.io/lecture/kotlin/2016/07/06/kotlin_let_apply_run_with/


신고


티스토리 툴바