복붙노트

[SCALA] 수비력 foo는 [A, B] (XS : (A, B) *) : 어떻게 데프 foo는 사이에 [A] (A * XS)를 구별 할 수 있습니까?

SCALA

수비력 foo는 [A, B] (XS : (A, B) *) : 어떻게 데프 foo는 사이에 [A] (A * XS)를 구별 할 수 있습니까?

그 형의 삭제 그들을 그래서, 런타임에 유형이 많다는 동일 보이게 알고있다 :

class Bar {
    def foo[A](xs: A*) { xs.foreach(println) }
    def foo[A, B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) }
}   

다음과 같은 컴파일러 오류가 있습니다 :

<console>:7: error: double definition:
method foo:[A,B](xs: (A, B)*)Unit and
method foo:[A](xs: A*)Unit at line 6
have same type after erasure: (xs: Seq)Unit
        def foo[A,B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)
) }
            ^

그러나 쓸 수있는 간단한 방법이있다 :

bar.foo(1, 2, 3)
bar.foo(1 -> 2, 3 -> 4)

그리고 필요없이, foo는 이러한 호출 다른 오버로드 된 버전있는 것은 명시 적으로 이름을 :

bar.fooInts(1, 2, 3)
bar.fooPairs(1 -> 2, 3 -> 4)

해결법

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

    1.할 수 있습니다, 매우 라운드에 대한 방법입니다. 푸는 형 클래스이며, 컴파일러는 암시 적으로 (추정) 형식 매개 변수의 A.와 호환 형 클래스의 인스턴스를, 통과

    할 수 있습니다, 매우 라운드에 대한 방법입니다. 푸는 형 클래스이며, 컴파일러는 암시 적으로 (추정) 형식 매개 변수의 A.와 호환 형 클래스의 인스턴스를, 통과

    trait Foo[X] {
      def apply(xs: Seq[X]): Unit
    }
    
    object Foo {
     implicit def FooAny[A]: Foo[A] = new Foo[A] {
        def apply(xs: Seq[A]) = println("apply(xs: Seq[A])")
      }
      implicit def FooTuple2[A, B]: Foo[(A, B)] = new Foo[(A, B)] {
        def apply(xs: Seq[(A, B)]) = println("apply(xs: Seq[(A, B)])")
      }
    
      def apply[A](xs: A*)(implicit f: Foo[A]) = f(xs)
    }
    
    
    Foo(1, 2, 3)        // apply(xs: Seq[A])
    Foo(1 -> 2, 2 -> 3) // apply(xs: Seq[(A, B)])
    

    제 호에서 FooAny 및 FooTuple2 둘다 전달 될 수 있지만, 컴파일러의 정적 메소드 오버로딩의 규칙에 따라, FooTuple2을 픽업. FooTuple2는 FooAny이 더 구체적으로 간주됩니다. 두 후보가 서로 구체적으로 간주하는 경우, 모호한 오류가 발생합니다. 당신은 또한 scala.LowPriorityImplicits에서 이루어집니다, 슈퍼 클래스에 하나를 배치하여 다른 이상을 선호 할 수 있습니다.

    최신 정보

    DummyImplicit 아이디어 및 스칼라 사용자에 대한 후속 스레드를 Riffing :

    trait __[+_]
    object __ {
     implicit object __ extends __[Any]
    }
    
    object overload {
     def foo(a: Seq[Boolean]) = 0
    
     def foo[_: __](a: Seq[Int]) = 1
    
     def foo[_: __ : __](a: Seq[String]) = 2
    }
    
    import overload._
    foo(Seq(true)) 
    foo(Seq(1)) 
    foo(Seq("s")) 
    

    이 _의 이름이 형식 매개 변수의 형식 매개 변수 특성 __, 공변를 선언합니다. 그 동반자 개체는 __ [모든], 우리는 나중에해야하는 __의 암시 적 인스턴스를 포함하고 있습니다. foo에 두 번째와 세 번째 과부하 다시 명명 더미 유형 파라미터를 포함한다. 이것은 모든으로 추정됩니다. 이 유형의 매개 변수는 예를 들어, 추가 암시 적 매개 변수로 desugared되는 하나 개 이상의 컨텍스트 경계를 가지고 :

     def foo[A](a: Seq[Int])(implicit ev$1: __[A]) = 1
    

    다중 매개 변수 목록은 바이트 코드에서 하나의 매개 변수 목록에 연결된다, 그래서 이중 정의 문제는 회피한다.

    삭제, 상황에 맞는 범위 및 암시 적 검색에 대해 배울 수있는 기회로 생각하십시오보다는 패턴이 실제 코드에 적용 할로!

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

    2.우리는 단지 2 과부하를 가지고있는 경우, 우리는 Landei의 답변을 간소화하고 자동으로 당신을 위해 모든 범위로 가져 scala.Predef.DummyImplicit를 사용하여 암시 적 우리 자신을 정의 할 필요를 방지 할 수 있습니다.

    우리는 단지 2 과부하를 가지고있는 경우, 우리는 Landei의 답변을 간소화하고 자동으로 당신을 위해 모든 범위로 가져 scala.Predef.DummyImplicit를 사용하여 암시 적 우리 자신을 정의 할 필요를 방지 할 수 있습니다.

    class Bar {
      def foo[A](xs: A*) { xs.foreach(println) }
      def foo[A, B](xs: (A, B)*)(implicit s:DummyImplicit){
        xs.foreach(x => println(x._1 + " - " + x._2))
      }
    }
    
  3. ==============================

    3.당신이 제로 인수 foo는 호출의 가능성 (빈 서열, 당신이 좋아하는 경우)을 잃는 괜찮다면,이 트릭은 도움이 될 수 있습니다 :

    당신이 제로 인수 foo는 호출의 가능성 (빈 서열, 당신이 좋아하는 경우)을 잃는 괜찮다면,이 트릭은 도움이 될 수 있습니다 :

    def foo[A](x: A, xs: A*) { x::xs.foreach(println) }
    def foo[A, B](x: (A, B), xs: (A, B)*) { (x::xs.toList).foreach(x => println(x._1 + " - " + x._2)) }
    

    컴파일러가에 따라 차이를 만들 수 있도록, 첫 번째 매개 변수의 유형이 삭제되지 않습니다 : 지금 (이 컴파일되지 않더라도) 작동하는지 나는 확인할 수 없습니다,하지만 난 주요 아이디어는 이해하기 아주 쉽게 생각 .

    이미 서열이 있고 foo는에 전달하려는 경우 불행하게도 그것은 또한 매우 편리 아니다.

  4. ==============================

    4.

    class Bar {
        def foo[A](xs: A*) { xs.foreach{
           case (a,b) => println(a + " - " + b)
           case a => println(a)}
        }
    }
    

    이 수

    bar.foo(1,2)
    bar.foo(1->3,2->4)
    

    그러나 또한 허용

    bar.foo(1->2,5)
    
  5. ==============================

    5.이것은 적은 retronym의 방법보다 복잡한 것, 그리고 켄 블룸의 DummyImplicit 솔루션의 다소 덜 장황 (이하 일반적이기는하지만) 버전입니다 :

    이것은 적은 retronym의 방법보다 복잡한 것, 그리고 켄 블룸의 DummyImplicit 솔루션의 다소 덜 장황 (이하 일반적이기는하지만) 버전입니다 :

    class Bar {
       def foo[A : ClassManifest](xs: A*) = { xs.foreach(println) }
    
       def foo[A : ClassManifest, B : ClassManifest](xs: (A, B)*) = { 
          xs.foreach(x => println(x._1 + " - " + x._2)) 
       }
    
       def foo[A : ClassManifest, 
               B : ClassManifest, 
               C : ClassManifest](xs: (A, B, C)*) = {
          xs.foreach(x => println(x._1 + ", " + x._2 + ", " + x._3))
       }
    }
    

    당신이 형 같은 수의 매개 변수 두 개의 오버로드가있는 경우이 기술은 사용할 수 있습니다 :

    class Bar {
       def foo[A <: Int](xs: A*) = { 
          println("Ints:"); 
          xs.foreach(println) 
       }
    
       def foo[A <: String : ClassManifest](xs: A*) = {
          println("Strings:");
          xs.foreach(println)
       }
    }
    
  6. ==============================

    6.방법 중 하나에 관련이없는 암시 인수는 접착제 :이이 작업을 얻을 수있는 또 다른 해키 방법입니다 :

    방법 중 하나에 관련이없는 암시 인수는 접착제 :이이 작업을 얻을 수있는 또 다른 해키 방법입니다 :

    class Bar {
        def foo[A](xs: A*) { xs.foreach(println) }
        def foo[A, B](xs: (A, B)*)(implicit s:String) { xs.foreach(x => println(x._1 + " - " + x._2)) }
    }
    
    implicit val s = ""
    
    new Bar().foo(1,2,3,4)
    //--> 1
    //--> 2
    //--> 3
    //--> 4
    new Bar().foo((1,2),(3,4))
    //--> 1 - 2
    //--> 3 - 4
    
  7. from https://stackoverflow.com/questions/3422336/how-can-i-differentiate-between-def-fooaxs-a-and-def-fooa-bxs-a-b by cc-by-sa and MIT license