[scala] Scala에서 “컨텍스트 바인딩”이란 무엇입니까?

Scala 2.8의 새로운 기능 중 하나는 컨텍스트 경계입니다. 컨텍스트 바운드 란 무엇이며 어디에 유용합니까?

물론 먼저 검색을 했지만 ( 예를 들어 this를 찾았 지만) 정말 명확하고 자세한 정보를 찾을 수 없었습니다.



답변

이 기사 를 찾았습니까 ? 배열 개선의 맥락에서 새로운 컨텍스트 바인딩 기능을 다룹니다.

일반적으로 컨텍스트 바인딩 이 있는 형식 매개 변수 는 형식입니다 [T: Bound]. 유형 T의 암시 적 매개 변수 와 함께 일반 유형 매개 변수로 확장됩니다 Bound[T].

tabulate0에서 주어진 길이까지의 숫자 범위에 주어진 함수 f를 적용한 결과로부터 배열을 형성하는 방법 을 고려하십시오 . Scala 2.7까지 테이블 형식은 다음과 같이 작성할 수 있습니다.

def tabulate[T](len: Int, f: Int => T) = {
    val xs = new Array[T](len)
    for (i <- 0 until len) xs(i) = f(i)
    xs
}

Scala 2.8에서는 런타임 정보가 올바른 표현을 생성하는 데 필요하기 때문에 더 이상 불가능합니다 Array[T]. ClassManifest[T]암시 적 매개 변수로 메소드 에를 전달하여이 정보를 제공해야합니다 .

def tabulate[T](len: Int, f: Int => T)(implicit m: ClassManifest[T]) = {
    val xs = new Array[T](len)
    for (i <- 0 until len) xs(i) = f(i)
    xs
}

속기 형식으로 컨텍스트 바인딩T대신 형식 매개 변수에 사용할 수 있습니다 .

def tabulate[T: ClassManifest](len: Int, f: Int => T) = {
    val xs = new Array[T](len)
    for (i <- 0 until len) xs(i) = f(i)
    xs
}


답변

Robert의 답변은 Context Bounds의 기술적 세부 사항을 다룹니다. 그 의미에 대한 제 해석을 드릴게요.

Scala에서 View Bound ( A <% B)는 ‘can be seen as’ <:의 개념을 캡처합니다 ( 상한값 은 ‘is a’의 개념을 캡처 함). 컨텍스트 바인딩 ( A : C)은 유형에 대해 ‘has a’라고 말합니다. ” Thas a Manifest” 로 매니페스트에 대한 예제를 읽을 수 있습니다 . about Orderedvs에 링크 한 예 Ordering는 차이점을 보여줍니다. 방법

def example[T <% Ordered[T]](param: T)

매개 변수가 Ordered. 비교

def example[T : Ordering](param: T)

매개 변수에 Ordering.

사용 측면에서 규칙을 설정하는 데 시간이 걸리지 만 컨텍스트 경계가 뷰 경계보다 선호 됩니다 (이제 뷰 경계는 더 이상 사용되지 않음 ). 한 가지 제안은 직접 참조 할 필요없이 암시 적 정의를 한 범위에서 다른 범위로 전송해야 할 때 컨텍스트 바인딩이 선호된다는 것입니다 (이것은 확실히 ClassManifest배열을 만드는 데 사용되는 경우입니다 ).

뷰 경계와 컨텍스트 경계에 대해 생각하는 또 다른 방법은 첫 번째가 호출자의 범위에서 암시 적 변환을 전송한다는 것입니다. 두 번째는 호출자의 범위에서 암시 적 개체를 전송합니다.


답변

(이것은 괄호 안의 메모입니다. 먼저 다른 답변을 읽고 이해하십시오.)

컨텍스트 경계는 실제로 뷰 경계를 일반화합니다.

따라서이 코드는 View Bound로 표현됩니다.

scala> implicit def int2str(i: Int): String = i.toString
int2str: (i: Int)String

scala> def f1[T <% String](t: T) = 0
f1: [T](t: T)(implicit evidence$1: (T) => String)Int

이것은 또한 유형에서 유형 F으로의 함수를 나타내는 유형 별칭의 도움으로 Context Bound로 표현 될 수 있습니다 T.

scala> trait To[T] { type From[F] = F => T }
defined trait To

scala> def f2[T : To[String]#From](t: T) = 0
f2: [T](t: T)(implicit evidence$1: (T) => java.lang.String)Int

scala> f2(1)
res1: Int = 0

컨텍스트 바인딩은 유형 생성자와 함께 사용해야합니다 * => *. 그러나 유형 생성자 Function1는 종류 (*, *) => *입니다. 유형 별칭을 사용하면 두 번째 유형 매개 변수를 유형과 함께 부분적으로 적용 String하여 컨텍스트 바인딩으로 사용할 올바른 유형의 유형 생성자를 생성합니다.

트레이 트 내에서 타입 별칭을 사용하지 않고 Scala에서 부분적으로 적용된 타입을 직접 표현할 수 있도록하는 제안이 있습니다. 그런 다음 다음과 같이 작성할 수 있습니다.

def f3[T : [X](X => String)](t: T) = 0 


답변

이것은 또 다른 괄호 안의 메모입니다.

벤 지적 , 바인딩 컨텍스트는 형식 매개 변수 및 유형 클래스 사이에 “이-는”제약 조건을 나타냅니다. 즉, 특정 유형 클래스의 암시 적 값이 존재한다는 제약 조건을 나타냅니다.

컨텍스트 바운드를 사용할 때 종종 암시 적 값을 표면화해야합니다. 예를 들어 제약 조건이 주어지면 제약 조건 을 충족하는 T : Ordering인스턴스가 종종 필요합니다 Ordering[T]. 여기설명 된대로implicitly 메서드 또는 약간 더 유용한 context메서드 를 사용하여 암시 적 값에 액세스 할 수 있습니다 .

def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) =
   xs zip ys map { t => implicitly[Numeric[T]].times(t._1, t._2) }

또는

def **[T : Numeric](xs: Iterable[T], ys: Iterable[T]) =
   xs zip ys map { t => context[T]().times(t._1, t._2) }


답변