복붙노트

[SCALA] 어디 스칼라 implicits 찾아합니까?

SCALA

어디 스칼라 implicits 찾아합니까?

여기서 컴파일러가 implicits을 찾아 않습니다 스칼라 이민자에 대한 암시 적 질문은 것 같다? 문제는 결코 그것에 대한 단어가없는 것처럼 완전히 형성 얻을 것 같다 때문에 암시 적 의미한다. 예를 들어, 경우 통합에 대한 값은 아래 :-)에서 오는가?

scala> import scala.math._
import scala.math._

scala> def foo[T](t: T)(implicit integral: Integral[T]) {println(integral)}
foo: [T](t: T)(implicit integral: scala.math.Integral[T])Unit

scala> foo(0)
scala.math.Numeric$IntIsIntegral$@3dbea611

scala> foo(0L)
scala.math.Numeric$LongIsIntegral$@48c610af

첫 번째 질문에 대한 답변 내용을 결정하는 사람들에게 후속 않는 또 다른 질문 컴파일러는 명백한 모호성의 특정 상황에서 사용하는 암시하는 선택 (하지만 어쨌든 컴파일) 않습니다 어떻게?

StringOps에 WrappedString 한 다른 : 예를 들어, scala.Predef는 문자열에서이 변환을 정의합니다. 두 클래스는, 그러나, 방법을 많이 공유하므로 말,지도를 호출 할 때, 왜 스칼라는 모호함에 대해 불평하지 않는 이유는 무엇입니까?

참고 :이 질문에 좀 더 일반적인 방법으로 문제를 진술의 희망이 다른 질문에서 영감을했다. 이 대답에 언급되어 있기 때문에 예, 거기에서 복사되었습니다.

해결법

  1. ==============================

    1.스칼라 Implicits 말하자면, "자동"전달 될 수있는 값 또는 자동으로 이루어지는 것이 한 유형에서 다른 유형으로 변환 중 하나를 의미한다.

    스칼라 Implicits 말하자면, "자동"전달 될 수있는 값 또는 자동으로 이루어지는 것이 한 유형에서 다른 유형으로 변환 중 하나를 의미한다.

    하나는 클래스 C의 O를 객체에 메소드 m를 호출하고, 그 클래스는 방법 m를 지원하지 않는 경우, 후자의 유형에 대해 아주 간략하게 말하자면, 다음 스칼라는 m을 지원 뭔가를 C에서 암시 적 변환을 찾을 것이다. 간단한 예는 문자열에 대한 방법을지도 할 것이다 :

    "abc".map(_.toInt)
    

    문자열 메소드지도를 지원하지 않지만 StringOps는 않습니다, 사용 가능한 StringOps (PREDEF에 암시 데프 augmentString 참조) 문자열에서 암시 적 변환이있다.

    암시의 다른 종류의 암시 적 매개 변수입니다. 이들은 메서드에 전달되는 다른 모든 매개 변수처럼 호출하지만 컴파일러는 자동으로 기입하려고합니다. 그것은 할 수없는 경우에는 불평 할 것이다. 하나는 하나가 (당신이 도전까지 기분 일에, 브레이크 아웃에 대한 질문을 참조) 예를 들어, 브레이크 아웃을 사용하는 방법이며, 명시 적으로 이러한 매개 변수를 전달할 수 있습니다.

    이 경우에, 하나는 푸 메소드 선언 같이 암시 필요성을 선언한다 :

    def foo[T](t: T)(implicit integral: Integral[T]) {println(integral)}
    

    암시는 암시 적 변환과 암시 적 매개 변수를 모두 하나의 상황이있다. 예를 들면 :

    def getIndex[T, CC](seq: CC, value: T)(implicit conv: CC => Seq[T]) = seq.indexOf(value)
    
    getIndex("abc", 'a')
    

    메소드 getIndex는 긴 서열 [T]에 해당 클래스에서 제공 암시 적 변환이 존재하는 한, 임의의 객체를 수신 할 수있다. 그 때문에, 나는 getIndex 문자열을 전달할 수 있습니다, 그것은 작동합니다.

    내부적 컴파일러로 전환 seq.IndexOf (값) (SEQ) .indexOf (값)를 변경한다.

    이것은 그들를 작성하는 문법 설탕이 너무 유용합니다. 이 문법 설탕을 사용 getIndex는 다음과 같이 정의 할 수 있습니다 :

    def getIndex[T, CC <% Seq[T]](seq: CC, value: T) = seq.indexOf(value)
    

    <: 또는 하한 (T (서열 [지능] NULL)이 문법적이 상한에 가깝다 바인딩 도면, CC)>으로 기술된다.

    암시 적 매개 변수의 또 다른 일반적인 패턴 유형 클래스 패턴이다. 이 패턴을 선언하지 않은 클래스에 공통 인터페이스를 제공 할 수 있습니다. 의 분리를 얻고 - - 그것은 두 다리 패턴이 될 수 있으며, 어댑터 패턴으로.

    당신이 언급 한 적분 클래스 타입 클래스 패턴의 전형적인 예이다. 스칼라의 표준 라이브러리에 대한 또 다른 예는 주문한다. Scalaz이라는 패턴을 많이 사용한다 도서관이있다.

    이것은 그것의 사용의 예입니다 :

    def sum[T](list: List[T])(implicit integral: Integral[T]): T = {
        import integral._   // get the implicits in question into scope
        list.foldLeft(integral.zero)(_ + _)
    }
    

    암시 적으로 참조 할 필요가 덜 유용 만든 바인딩 컨텍스트라고 그것에 대한 문법 설탕도있다. 그 방법의 직선 변환은 다음과 같다 :

    def sum[T : Integral](list: List[T]): T = {
        val integral = implicitly[Integral[T]]
        import integral._   // get the implicits in question into scope
        list.foldLeft(integral.zero)(_ + _)
    }
    

    당신은 단지 그들을 사용하는 다른 방법에 전달해야 할 때 상황에 맞는 범위가 더 유용합니다. 예를 들어, 서열에 정렬 방법은 암시 적 주문이 필요합니다. 메소드 reverseSort를 만들려면, 하나는 쓸 수있다 :

    def reverseSort[T : Ordering](seq: Seq[T]) = seq.sorted.reverse
    

    [T]를 주문하는 것은 암시 적으로 reverseSort에 전달하기 때문에 분류에, 그 다음 암시를 전달할 수 있습니다.

    컴파일러는 암시의 필요성을 볼 때 당신이 객체의 클래스에 존재하지 않는 방법을 호출하기 때문에 당신이 암시 적 매개 변수를 필요로하는 메소드를 호출하기 때문에 중, 또는, 그것은 필요에 맞게 것이다 암시를 검색합니다 .

    이 검색은 볼 수 있으며되지 않는 어떤 implicits 정의하는 특정 규칙을 준수하십시오. 컴파일러는 implicits를 검색합니다 다음 표를 보여주는이 나는 진심으로 자신의 스칼라 지식을 향상하고자하는 사람에게 추천 조쉬 Suereth에 의해 implicits에 대한 훌륭한 프리젠 테이션에서 가져온 것입니다. 그런 다음 피드백과 업데이트 이후 보완하고있다.

    암시 적 매개 변수의 유형, 가장 고유 한 정적 과부하 해상도의 규칙을 사용하여 선택됩니다 일치하는 몇 가지 자격 인자가있는 경우 숫자 1에서 사용할 수있는 implicits 아래보다 다른 번호 2 아래에있는 것들보다 우선 순위 (스칼라을 볼 수있다 사양 §6.26.3). 더 자세한 정보는 내가이 답변의 마지막에 링크 질문에서 찾을 수 있습니다.

    의 그들에 대한 몇 가지 예를 들어 보겠습니다 :

    implicit val n: Int = 5
    def add(x: Int)(implicit y: Int) = x + y
    add(5) // takes n from the current scope
    
    import scala.collection.JavaConversions.mapAsScalaMap
    def env = System.getenv() // Java map
    val term = env("TERM")    // implicit conversion from Java Map to Scala Map
    
    def sum[T : Integral](list: List[T]): T = {
        val integral = implicitly[Integral[T]]
        import integral._   // get the implicits in question into scope
        list.foldLeft(integral.zero)(_ + _)
    }
    

    편집 :이 다른 우선 순위를 가지고 있지 않는 것 같다. 당신이 우선 순위의 차이를 보여줍니다 몇 가지 예제가있는 경우 댓글을 확인하시기 바랍니다. 그렇지 않으면,이에 의존하지 않습니다.

    이 첫 번째 예와 비슷하지만 내재 된 정의를 가정하고 그 사용이 아닌 다른 파일에 있습니다. 또한 패키지 오브젝트가 implicits에 가져다에서 사용하는 방법을 참조하십시오.

    여기에 노트의 두 개체 동료가있다. 첫째, "소스"유형의 개체 동반자로보고있다. 하나는 옵션에서의 Iterable 메소드를 호출하거나의 Iterable을 기대 뭔가 옵션을 전달할 수 있도록 예를 들어, 객체 옵션 내부의 Iterable에 암시 적 변환이 있습니다. 예를 들면 :

    for {
        x <- List(1, 2, 3)
        y <- Some('x')
    } yield (x, y)
    

    그 표현은 컴파일러에 의해 번역됩니다

    List(1, 2, 3).flatMap(x => Some('x').map(y => (x, y)))
    

    그러나 List.flatMap는 옵션이 아닌 TraversableOnce를 기대하고있다. 컴파일러는 다음 옵션의 객체 동반자 내부 모습이 표현이 정확하게하는 TraversableOnce 인의 Iterable로의 전환을 찾습니다.

    둘째, 예상되는 형태의 동반자 개체 :

    List(1, 2, 3).sorted
    

    분류 방법은 암시 적 주문을합니다. 이 경우, 클래스 주문에 객체 주문, 동반자 내부보고, 거기에 암시 주문 [지능]을 찾습니다.

    또한으로보고있다 슈퍼 클래스의 동반자 개체를합니다. 예를 들면 :

    class A(val n: Int)
    object A { 
        implicit def str(a: A) = "A: %d" format a.n
    }
    class B(val x: Int, y: Int) extends A(y)
    val b = new B(5, 2)
    val s: String = b  // s == "A: 2"
    

    이것은 그들이, 숫자 내부에 일체형하지 발견으로 스칼라는, 그런데, 귀하의 질문에 암시 적 숫자 [지능] 및 숫자 [긴]을 발견하는 방법입니다.

    당신이 인수 A 형과 방법이있는 경우, A 형의 내재 된 범위도 고려 될 것입니다. 예를 들어,의 동반자 객체 위의 규칙에 따라, implicits 검색됩니다 - "암시 적 범위"에 의하여 나는이 모든 규칙을 반복적으로 적용됩니다 것을 의미한다.

    이하지만, 전체 표현하는 암시 적 범위는 해당 매개 변수의 변환 검색 할 의미하지 않습니다. 예를 들면 :

    class A(val n: Int) {
      def +(other: A) = new A(n + other.n)
    }
    object A {
      implicit def fromInt(n: Int) = new A(n)
    }
    
    // This becomes possible:
    1 + new A(1)
    // because it is converted into this:
    A.fromInt(1) + new A(1)
    

    이 스칼라 2.9.1부터 사용할 수 있습니다.

    이는 유형 클래스 패턴이 정말 작동하도록해야합니다. 그것은 자사의 동반자 개체의 일부 implicits와 함께 제공됩니다,하지만 당신은 거기에 물건을 추가 할 수 없습니다 : 예를 들어, 주문 생각해 보자. 그래서 내가 어떻게하면 자동으로 발견되는 자신의 클래스에 대한 주문을 할 수 있습니까?

    이제 구현을 시작하자 :

    class A(val n: Int)
    object A {
        implicit val ord = new Ordering[A] {
            def compare(x: A, y: A) = implicitly[Ordering[Int]].compare(x.n, y.n)
        }
    }
    

    그래서, 당신이 호출 할 때 발생하는 고려

    List(new A(5), new A(2)).sorted
    

    우리가 본 바와 같이, 정렬 방법은 오더링은 [A]는 (사실, 오더링 [B] B>를 기대한다 : A) 예상. 주문 내부에 같은 건 없다, 그리고보고에는 "소스"유형이 없습니다. 물론, 그것은 주문의 형식 인수 인, 내부를 찾는 것입니다.

    동반자 CanBuildFrom의 형식 매개 변수에 객체 내부의 implicits이 발견이 어떻게 CanBuildFrom 작업을 기대 수집 방법 다양한도있다.

    주 : 주문은 T는 입력 매개 변수 특성 주문 [T]로 정의된다. 이전에, 나는 스칼라 훨씬 이해가되지 않습니다 유형 매개 변수, 내부에보고했다. 이 주문에 입력 인자이다 암시는 상기 A는 실제의 형태이고, [A]에 대한 주문되고, 파라미터를 입력하지 보았다. 스칼라 사양의 7.2 절을 참조하십시오.

    이 스칼라 2.8.0부터 사용할 수 있습니다.

    실제로이의 예를 보지 못했다. 사람이 하나를 공유 할 수 있다면 나는 감사하게 될 거라고. 원리는 간단하다 :

    class A(val n: Int) {
      class B(val m: Int) { require(m < n) }
    }
    object A {
      implicit def bToString(b: A#B) = "B: %d" format b.m
    }
    val a = new A(5)
    val b = new a.B(3)
    val s: String = b  // s == "B: 3"
    

    나는 이것이 농담 확신 해요,하지만이 답변이 최신하지 않을 수 있습니다. 그래서 무슨 일이 일어나고 있는지의 최종 중재자로서이 질문을하고, 당신이 경우에 내가 그것을 해결할 수 있도록이 오래된, 저에게 알려주십시오 얻었다 발견하지 않습니다.

    편집하다

    관심의 관련 질문 :

  2. ==============================

    2.나는 그것이 찾습니다뿐만 아니라 암시 적 매개 변수 해상도의 우선 순위를 알아 싶어서 (일부 피드백 후 다시 암시 적 매개 변수 우선 순위) 수입 세금없이 implicits을 재 방문이 블로그 포스트를 작성했습니다.

    나는 그것이 찾습니다뿐만 아니라 암시 적 매개 변수 해상도의 우선 순위를 알아 싶어서 (일부 피드백 후 다시 암시 적 매개 변수 우선 순위) 수입 세금없이 implicits을 재 방문이 블로그 포스트를 작성했습니다.

    여기 목록입니다 :

    두 단계의 경우 우리는 하나 이상의 암시 적 정적 오버로드 규칙을 해결하는 데 사용됩니다 찾을 수 있습니다.

  3. from https://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits by cc-by-sa and MIT license