You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala为何无法推断省略括号与点的方法类型?附代码实例

Understanding Type Inference Issues in Your Scala Code

Great question! Let's break down the two parts of your problem to understand why Scala's type inference behaves differently in these cases.

1. Why type inference fails for the infix :+ call (m.getOrElse(string(i), Vector()) :+ i)

Let's start with the core issue here: when you write Vector() without a type parameter, Scala infers its type as Vector[Nothing] by default (since Nothing is Scala's bottom type—its subtype of every other type). Here's the step-by-step breakdown of why the infix call breaks:

  • First, Scala evaluates m.getOrElse(string(i), Vector()). The getOrElse method has this signature:
    def getOrElse[B >: V](key: K, default: => B): B
    
    For your map, V is Vector[Int]. Since you pass Vector[Nothing] as the default, Scala infers B as Vector[Nothing] (because Vector[Nothing] is a subtype of Vector[Int], satisfying B >: V).
  • Next, you try to call :+ i on this Vector[Nothing]. The :+ method for Vector looks like this:
    def :+(elem: A): Vector[A]
    
    For Vector[Nothing], A is Nothing—so this method expects an element of type Nothing, but you're passing an Int. Since Int isn't a subtype of Nothing, this causes a type mismatch, and inference fails.

The key here is that infix expressions are evaluated left-to-right, so Scala can't use the context of the :+ i call to retroactively infer a more specific type for Vector() earlier in the chain.

2. Why the dot notation works (m.getOrElse(string(i), Vector()).:+(i))

When you use dot notation to call :+, Scala can leverage target type inference—it looks at the expected type of the entire expression to guide inference. Here's what happens:

  • The entire expression m.getOrElse(...).:+(i) needs to produce a Vector[Int] (since it's being used as the value in your Map[Char, Vector[Int]]).
  • Scala knows that .:+(i) (with i: Int) returns a Vector[Int], so the receiver of this method call (the result of m.getOrElse(...)) must be a Vector[Int].
  • Going back to getOrElse, Scala now infers B as Vector[Int] (matching the expected return type), so it treats Vector() as Vector[Int] instead of Vector[Nothing]. This aligns perfectly with the :+ i call, and everything works as intended.

A Simple Fix for the Infix Case

If you want to use infix notation and avoid the type inference issue, just explicitly specify the type parameter for Vector:

def indexes(string: String): Map[Char, Vector[Int]] = 
  (0 until string.length).foldLeft(Map[Char, Vector[Int]]()){ (m, i) => 
    m + (string(i) -> (m.getOrElse(string(i), Vector[Int]()) :+ i)) 
  }

By writing Vector[Int]() instead of Vector(), you remove the ambiguity for Scala, and the infix call works without problems.


内容的提问来源于stack exchange,提问作者Andrei Iatsuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:34:56