【问题标题】:Why can't the compiler select the correct String.contains method when using this lambda shorthand?为什么编译器在使用这个 lambda 简写时不能选择正确的 String.contains 方法?
【发布时间】:2020-08-06 20:46:19
【问题描述】:

假设我想检查一个字符串是否包含“cory”中的任何个字母:

def hasCory(input: String): Boolean = {
  val myName = "cory"
  input.exists(myName.contains)
}

编译器抱怨:

error: type mismatch;
found   : CharSequence => Boolean
required: Char => Boolean

Scala提供了我想要的Char-accepting方法in StringOps

但除非我将代码更改为以下之一,否则编译器似乎无法看到此方法:

input.exists(myName.contains(_))
input.exists(c => myName.contains(c))

在原始示例中,它似乎使用了Java String's contains method,它确实确实接受CharSequence

这是否按预期工作?为什么编译器看不到我想要containsChar 版本?

【问题讨论】:

  • StringChar 的集合,而不是子String 的集合,exists 是相应定义的(类型不匹配)。
  • exists 的签名是def exists(p: (Char) => Boolean): Boolean,因此您需要向其传递一个接受Char 并返回Boolean 的方法。这正是 Scala StringOps contains 方法的签名。
  • 我想你的意思是def hasCory(input: String): Boolean = input.contains("cory")
  • @KrzysztofAtłasik 不,这将检查名称“cory”是否在字符串input 中。我想检查字符串input 是否包含我名字中的任何字母,即cory 中的任何字符。无论哪种方式,这个问题与其说是关于如何进行特定检查,不如说是关于为什么编译器不会让我这样做,除非我明确声明中间 c 值。跨度>
  • @CoryKlein 你也可以写input.exists(myName.contains(_))

标签: scala overloading type-inference implicit-conversion implicit


【解决方案1】:

StringOpsan implicit conversion

@inline implicit def augmentString(x: String): StringOps = new StringOps(x)

并且隐式转换仅适用于in three cases

  1. 如果表达式 ? 的类型为 ?,并且 ? 不符合表达式的预期类型 pt。
  2. 在选择中?.? 对于 ? 类型的 ?,如果选择器 ? 不表示 ? 的可访问成员
  3. 在选择中?.?(args) ? 类型为 ?,如果选择器 ? 表示 ? 的某些成员,但这些成员都不适用于参数 args。

当您写 myName.contains 时,这三种情况都不是(特别是,
不是第二种情况,因为contains String 的可访问成员)所以StringOps 不能被应用,它是String#contains(CharSequence) 和类型不匹配错误。

当您编写myName.contains(_)c => myName.contains(c) 时,这是第三种情况,因此可以应用StringOps,隐式转换后为StringOps#contains(Char)

是的,它按预期工作。

【讨论】:

  • 我也很怀疑。我想我最初对此感到最惊讶,因为我没有意识到String java.util.String。我一直在假设 Scala 拥有自己的 String 与 Java 的兼容。无论如何-感谢您的引用和详尽的回答!我学到了很多。
  • @CoryKlein 好吧,在 Scala 中,Stringscala.Predef.String,它是 java.util.String 的别名。
  • 没错。这就像一个 Java 字符串的桌面快捷方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
  • 2012-02-27
  • 1970-01-01
  • 2011-07-08
  • 1970-01-01
相关资源
最近更新 更多