【问题标题】:Simple issue - "Error: missing argument list for method"简单问题 - “错误:缺少方法的参数列表”
【发布时间】:2018-01-18 12:04:05
【问题描述】:

我有一个简单的类和一个带有重载应用方法的伴生对象:

case class A(val s: String,
         val x: Int,
         val y: Int,
         val z: Int,
         val foo: Int => Int,
         val l: Option[List[String]])

object A {
    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int) =
        new A(s, x, y, z, foo, None)

    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int, l: List[String]) =
        new A(s, x, y, z, foo, Some(l))
}

让我们也定义一个函数:

def foo(x: Int): Int = x + 1

使用第一个构造函数有效:

scala> val a1 = A("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,$$Lambda$1842/2112068307@598e02f0,None)

但是使用第二个不会:

val a2 = A("a1", 1, 2, 3, foo, List("b1", "b2"))
<console>:24: error: missing argument list for method foo
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `foo _` or `foo(_)` instead of `foo`.
       val a2 = A("a1", 1, 2, 3, foo, List("b1", "b2"))

问题:我需要传递 foo _foo(_) 而不是像 a1 示例中的 foo 的原因是什么?另外,我可以重新定义我的班级以使其可以只使用foo吗?

【问题讨论】:

  • 第二个apply的正文中的Some(l)部分包起来。
  • 对不起,我错过了,当我意识到时删除了我的旧评论
  • @toni057 我设法挖出了一个描述相同问题的问题:stackoverflow.com/questions/17324247/…(你只有applys 而不是rs)

标签: scala


【解决方案1】:

如果foo 被声明为函数val,它就可以正常工作

scala> val foo = (x: Int) => x + 1
foo: Int => Int = <function1>

scala> val a1 = A("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,<function1>,None)

scala> val a2 = A("a1", 1, 2, 3, foo, List("b1", "b2"))
a2: A = A(a1,1,2,3,<function1>,Some(List(b1, b2)))

为什么def foo 适用于a1 我不确定,但这可能与case class A 期望一个函数而不是一个方法有关,因为这显然是scala 中的两个不同的东西。

Here is a post that might explain better

【讨论】:

  • 只是阅读帖子,似乎A 需要一个函数而不是一个方法。有没有人可以证实这一点?
【解决方案2】:

我无法解释这一点。我的第一个想法是它与类型擦除有关,正如slouc 所说,但后来我更仔细地查看了签名,即使在擦除之后它们都没有相同的类型签名:

案例类apply:

String, Int, Int, Int, Function1, Option

伴随对象apply1:

String, Int, Int, Int, Function1

伴随对象apply2:

String, Int, Int, Int, Function1, List

所以,我不明白这是怎么回事。

试图让它工作我注意到如果你将第二个 apply 方法重命名为别的东西,它会正常工作:

scala> val a1 = A("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,$$Lambda$1286/1904652802@6b649efa,None)

scala> val a2 = A.apply2("a1", 1, 2, 3, foo, List("b1", "b2"))
a2: A = A(a1,1,2,3,$$Lambda$1287/866073173@2dd63e3,Some(List(b1, b2)))

或者定义两个 apply 方法不在伴随对象中:

object B {

    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int): A =
      new A(s, x, y, z, foo, None)

    def apply(s: String, x: Int, y: Int, z: Int, foo: Int => Int, l: List[String]): A =
      new A(s, x, y, z, foo, Some(l))
}

REPL:

scala> val a1 = B("a1", 1, 2, 3, foo)
a1: A = A(a1,1,2,3,$$Lambda$1351/814507488@50fa5938,None)

scala> val a2 = B("a1", 1, 2, 3, foo, List("b1", "b2"))
a2: A = A(a1,1,2,3,$$Lambda$1352/613231852@5d77be8e,Some(List(b1, b2)))

第三种方法,正如Robert Udah 提到的,将foo 定义为函数文字(x: Int) =&gt; x + 1 也解决了这个问题。不过,不一定非得是val,也可以是def

def foo = (x: Int) => x + 1

【讨论】:

  • 为什么定义对象 B 有助于我最初打算做的事情,这很奇怪。任何线索为什么它不能作为伴生对象工作?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-04
  • 2021-07-24
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
相关资源
最近更新 更多