복붙노트

[SCALA] 왜 스칼라 컴파일러 해제하면 기본 인수 방법을 오버로드는 무엇입니까?

SCALA

왜 스칼라 컴파일러 해제하면 기본 인수 방법을 오버로드는 무엇입니까?

같은 방법 오버로딩이 모호한 될 수있는 유효한 경우가있을 수도 있지만, 이유는 무엇입니까 컴파일 타임이나 런타임에도 모호 컴파일러 사용 해제 코드?

예:

// This fails:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int)   (b: Int = 42) = a + b

// This fails, too. Even if there is no position in the argument list,
// where the types are the same.
def foo(a: Int)   (b: Int = 42) = a + b
def foo(a: String)(b: String = "Foo") = a + b

// This is OK:
def foo(a: String)(b: Int) = a + b
def foo(a: Int)   (b: Int = 42) = a + b    

// Even this is OK.
def foo(a: Int)(b: Int) = a + b
def foo(a: Int)(b: String = "Foo") = a + b

val bar = foo(42)_ // This complains obviously ...

이러한 제한은 조금 느슨하게 할 수없는 이유는 어떤 이유가 있습니까?

스칼라 기본 인수에 특히 많이 과부하로 변환 자바 코드는 매우 중요하고 하나 개의 스칼라 방법이 사양 / 컴파일러 강요하며 임의의 제한에 의해 Java 메소드의 많음을 교체 한 후 찾아 좋은하지 않습니다.

해결법

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

    1.나는 (여기에서) 루카스 Rytz를 인용하고 싶습니다 :

    나는 (여기에서) 루카스 Rytz를 인용하고 싶습니다 :

    미래 스칼라 버전에 대한 해결책은 명명 스키마에, 예를 들어,로 (버전 과부하 명확하게하는 방법의 시작 부분에 그) 기본이 아닌 인수 유형 이름을 통합 할 수 이 경우 :

    def foo(a: String)(b: Int = 42) = a + b
    def foo(a: Int)   (b: Int = 42) = a + b
    

    그것은 같은 것입니다 :

    def foo$String$default$2 = 42
    def foo$Int$default$2 = 42
    

    는 SIP 제안서를 작성하고자하는 사람?

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

    2.기본 인수 해상도를 오버로드의 상호 작용을 읽을 수있는 정확한 스펙을 얻기 위해 매우 어려울 것이다. 하나는 여기에 제시된 것처럼 물론, 여러 개인 경우에, 그것은 어떻게해야 무슨 말을하는 것은 쉽다. 그러나 그것은 충분하지 않습니다. 우리는 가능한 모든 코너 케이스를 결정 스펙을 필요 했어. 해상도를 오버로드 열심히 지정하려면 이미. 믹스의 기본 인자를 추가하면 어렵게 여전히 만들 것입니다. 우리는 두 가지를 분리하기로 선택한 이유입니다.

    기본 인수 해상도를 오버로드의 상호 작용을 읽을 수있는 정확한 스펙을 얻기 위해 매우 어려울 것이다. 하나는 여기에 제시된 것처럼 물론, 여러 개인 경우에, 그것은 어떻게해야 무슨 말을하는 것은 쉽다. 그러나 그것은 충분하지 않습니다. 우리는 가능한 모든 코너 케이스를 결정 스펙을 필요 했어. 해상도를 오버로드 열심히 지정하려면 이미. 믹스의 기본 인자를 추가하면 어렵게 여전히 만들 것입니다. 우리는 두 가지를 분리하기로 선택한 이유입니다.

  3. ==============================

    3.나는 귀하의 질문에 대답 할 수는 없지만 여기에 해결 방법은 :

    나는 귀하의 질문에 대답 할 수는 없지만 여기에 해결 방법은 :

    implicit def left2Either[A,B](a:A):Either[A,B] = Left(a)
    implicit def right2Either[A,B](b:B):Either[A,B] = Right(b)
    
    def foo(a: Either[Int, String], b: Int = 42) = a match {
      case Left(i) => i + b
      case Right(s) => s + b
    }
    

    당신이 단 하나 개의 인수가 다른 두 개의 매우 긴 인수 목록이있는 경우, 그것은 가치가 문제가 될 수 ...

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

    4.무엇 나를 위해 일한 것은 (Java 스타일)에 과부하 방법을 재정의하는 것입니다.

    무엇 나를 위해 일한 것은 (Java 스타일)에 과부하 방법을 재정의하는 것입니다.

    def foo(a: Int, b: Int) = a + b
    def foo(a: Int, b: String) = a + b
    def foo(a: Int) = a + "42"
    def foo(a: String) = a + "42"
    

    이것은 당신이 본 매개 변수에 따라 원하는 해상도 컴파일러를 보장합니다.

  5. ==============================

    5.여기 @Landei 응답의 일반화이다 :

    여기 @Landei 응답의 일반화이다 :

    당신이 정말로 원하는 것은 :

    def pretty(tree: Tree, showFields: Boolean = false): String = // ...
    def pretty(tree: List[Tree], showFields: Boolean = false): String = // ...
    def pretty(tree: Option[Tree], showFields: Boolean = false): String = // ...
    

    해결 방법

    def pretty(input: CanPretty, showFields: Boolean = false): String = {
      input match {
        case TreeCanPretty(tree)       => prettyTree(tree, showFields)
        case ListTreeCanPretty(tree)   => prettyList(tree, showFields)
        case OptionTreeCanPretty(tree) => prettyOption(tree, showFields)
      }
    }
    
    sealed trait CanPretty
    case class TreeCanPretty(tree: Tree) extends CanPretty
    case class ListTreeCanPretty(tree: List[Tree]) extends CanPretty
    case class OptionTreeCanPretty(tree: Option[Tree]) extends CanPretty
    
    import scala.language.implicitConversions
    implicit def treeCanPretty(tree: Tree): CanPretty = TreeCanPretty(tree)
    implicit def listTreeCanPretty(tree: List[Tree]): CanPretty = ListTreeCanPretty(tree)
    implicit def optionTreeCanPretty(tree: Option[Tree]): CanPretty = OptionTreeCanPretty(tree)
    
    private def prettyTree(tree: Tree, showFields: Boolean): String = "fun ..."
    private def prettyList(tree: List[Tree], showFields: Boolean): String = "fun ..."
    private def prettyOption(tree: Option[Tree], showFields: Boolean): String = "fun ..."
    
  6. ==============================

    6.가능한 시나리오 중 하나는

    가능한 시나리오 중 하나는

    
      def foo(a: Int)(b: Int = 10)(c: String = "10") = a + b + c
      def foo(a: Int)(b: String = "10")(c: Int = 10) = a + b + c
    

    어느 통화에 대해 컴파일러는 혼동 될 것이다. 다른 가능한 위험의 예방 컴파일러는 최대 하나의 오버로드 방법은 기본 인수가 허용합니다.

    그냥 내 생각 :-)

  7. ==============================

    7.나의 이해는 기본 인자 값을 사용하여 컴파일 된 클래스에서 이름 충돌이있을 수 있다는 것입니다. 나는 여러 스레드에서 언급이 라인을 따라 뭔가를 보았다.

    나의 이해는 기본 인자 값을 사용하여 컴파일 된 클래스에서 이름 충돌이있을 수 있다는 것입니다. 나는 여러 스레드에서 언급이 라인을 따라 뭔가를 보았다.

    명명 된 인수 사양은 여기에 있습니다 : http://www.scala-lang.org/sites/default/files/sids/rytz/Mon,%202009-11-09,%2017:29/named-args.pdf

    그것은 상태 :

     Overloading If there are multiple overloaded alternatives of a method, at most one is
     allowed to specify default arguments.
    

    그래서, 시간이 어떤 속도로되고, 그것은 일을 없을거야.

    당신은 당신이 자바 예에서 할 수있는 어떤 식으로 뭔가를 할 수 :

    def foo(a: String)(b: Int) =  a + (if (b > 0) b else 42)
    
  8. from https://stackoverflow.com/questions/4652095/why-does-the-scala-compiler-disallow-overloaded-methods-with-default-arguments by cc-by-sa and MIT license