Scala:方法重载和类型推断

时间:2015-10-19 19:33:42

标签: scala

我无法理解为什么Scala无法推断出重载方法的参数:

object A {
    implicit object SequenceMarker
    implicit object IntMarker

    def b(f: Int => Seq[Int])(implicit ev: SequenceMarker.type) = 0
    def b(f: Int => Int)(implicit ev: IntMarker.type) = 0

    def c() = { b(i => i + 1) } // this doesn't compile
}

当我尝试编译时,我收到以下错误:

error: missing parameter type
    def c() = { b(i => i + 1) }

我使用javapscala -print进行了一些调查,并确定在未指定i的情况下无法编译以前的代码:

object A {
    ...
    def c() = { b((i: Int) => i + 1) }
}

为什么会这样?有没有其他方法来重载方法而不在调用期间指定其参数的类型?

提前谢谢。

更新

我注意到使用scala -print

@SerialVersionUID(value = 0) final <synthetic> class anonfun$c$1 extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
    final def apply(i: Int): Int = anonfun$c$1.this.apply$mcII$sp(i);
    <specialized> def apply$mcII$sp(i: Int): Int = i.+(1);
    final <bridge> <artifact> def apply(v1: Object): Object = scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)));
    def <init>(): <$anon: Function1> = {
      anonfun$c$1.super.<init>();
      ()
    }
  }

这个论点似乎是以某种方式进行的:

scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)))

此行根据参数的类型而变化:

scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)));
...
scala.Int.box(anonfun$c$1.this.apply(v1.$asInstanceOf[String]()))

这可以解释为什么需要这种类型。这是整个日志:

package <empty> {
  object A extends Object {
    def b(f: Function1, ev: A$SequenceMarker.type): Int = 0;
    def b(f: Function1, ev: A$IntMarker.type): Int = 0;
    def c(): Int = A.this.b({
      (new <$anon: Function1>(): Function1)
    }, A$IntMarker);
    def <init>(): A.type = {
      A.super.<init>();
      ()
    }
  };
  object A$SequenceMarker extends Object {
    def <init>(): A$SequenceMarker.type = {
      A$SequenceMarker.super.<init>();
      ()
    }
  };
  object A$IntMarker extends Object {
    def <init>(): A$IntMarker.type = {
      A$IntMarker.super.<init>();
      ()
    }
  };
  @SerialVersionUID(value = 0) final <synthetic> class anonfun$c$1 extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
    final def apply(i: Int): Int = anonfun$c$1.this.apply$mcII$sp(i);
    <specialized> def apply$mcII$sp(i: Int): Int = i.+(1);
    final <bridge> <artifact> def apply(v1: Object): Object = scala.Int.box(anonfun$c$1.this.apply(scala.Int.unbox(v1)));
    def <init>(): <$anon: Function1> = {
      anonfun$c$1.super.<init>();
      ()
    }
  }
}

因此,我想要实现的目标不能以前面描述的方式完成。还有其他想法吗?

更新2

我也试过了:

def c() = { b(_ + 1) }

但我收到了另一个错误

error: missing parameter type for expanded function ((x$1) => x$1.$plus(1))
    def c() = { b(_ + 1) }

当我评论第一个b(f: Int => Seq[Int])时,它编译得很好。

1 个答案:

答案 0 :(得分:1)

这是因为出于重载解析的目的,参数的类型没有预期的类型,因此没有关于预期函数的信息。

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#overloading-resolution

编译器并不关心可能的重载集只包含采用Int的方法。