scala 找到单位:必需的 Int。为什么错误不明显?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14205367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:50:01  来源:igfitidea点击:

found Unit: required Int. Why is the error not obvious?

scala

提问by ilango

I have a method that is supposed to return an Int. I am trying to understand why Eclipse won't let me compile this, even though it looks apparent to me inside the if statement that I am indeed returning an Int. Is there something I am missing very obvious? I am trying to understand this aspect of Scala before proceeding to write more code.

我有一个应该返回 Int 的方法。我试图理解为什么 Eclipse 不允许我编译它,即使在 if 语句中我看起来很明显我确实返回了一个 Int。有什么我很明显的遗漏吗?在继续编写更多代码之前,我试图了解 Scala 的这一方面。

Here is the method:

这是方法:

def contains1(sfType: TokenType): Int = {
     if (Tokens.KEYWORDS.contains(sfType)) {
      val retVal = TokenTypes.RESERVED_WORD
    }
  }

Eclipse complains on line 2 --- 'type mismatch; found : Unit required: Int"

Eclipse 在第 2 行抱怨 --- 'type mismatch; 找到:所需单位:整数”

TokenTypes is - public abstract interface org.fife.ui.rsyntaxtextarea.TokenTypes and RESERVED_WORD is - public static final int RESERVED_WORD = 6;

I have read this post here: found: Unit required: Int - How to correct this?and tried to solve the problem before posting it, but I am still at a loss.

我在这里阅读了这篇文章:找到:所需单位:Int - 如何更正?并试图在发布之前解决问题,但我仍然不知所措。

Edit: The method is supposed to return an Int and I had typed in the return type wrongly. My problem remains the same. Eclipse still complains.

编辑:该方法应该返回一个 Int 并且我错误地输入了返回类型。我的问题还是一样。Eclipse 仍然抱怨。

回答by Daniel C. Sobral

I'll first explain what type Unitis, just in case. Even if you know already, other people having the same kind of problem might well not know it.

我将首先解释什么是类型Unit,以防万一。即使您已经知道,其他有同样问题的人也可能不知道。

Type Unitis similar to what is known in C or Java as void. In those languages, that means "this does not return anything". However, every method in Scala returns a value.

类型Unit类似于在 C 或 Java 中称为void. 在这些语言中,这意味着“这不会返回任何内容”。然而,Scala 中的每个方法都返回一个 value

To bridge the gap between every method returning something and not having anything useful to return, there's Unit. This type is an AnyVal, which means it isn't allocated on the heap, unless it gets boxed or is the type of a field on an object. Furthermore, it has only onevalue, whose literal is (). That is, you could write this:

为了弥合每个方法返回一些东西和没有任何有用的东西返回之间的差距,有Unit. 这种类型是 an AnyVal,这意味着它不会在堆上分配,除非它被装箱或者是对象上的字段类型。此外,它只有一个值,其文字是()。也就是说,你可以这样写:

val x: Unit = ()

The practical effect of this is that, when a method "returns" Unit, the compiler doesn't have to actually return any value, since it already knows what that value is. Therefore, it can implement methods returning Unitby declaring them, on the bytecode level, as being void.

这样做的实际效果是,当方法“返回”时Unit,编译器实际上不必返回任何值,因为它已经知道该值是什么。因此,它可以Unit通过在字节码级别将方法声明为void.

Anyway, if you don't want to return anything, you return Unit.

无论如何,如果你不想返回任何东西,你就返回Unit

Now let's look at the code given. Eclipse says it returns Unit, and, in fact, Eclipse is correct. However, most people would actually make the error of having that method return AnyValor Any, not Unit. See the following snippet for an example:

现在让我们看看给出的代码。Eclipse 说它返回Unit,事实上,Eclipse 是正确的。但是,大多数人实际上会错误地使该方法返回AnyValor Any,而不是Unit。有关示例,请参见以下代码段:

scala> if (true) 2
res0: AnyVal = 2

So, what happened? Well, when Scala finds an ifstatement, it has to figure out what is the type returned by it (in Scala, ifstatements return values as well). Consider the following hypothetical line:

所以发生了什么事?好吧,当 Scala 找到一个if语句时,它必须弄清楚它返回的类型是什么(在 Scala 中,if语句也返回值)。考虑以下假设线:

if (flag) x else y

Clearly, the returned value will be either xor y, so the type must be such that both xand ywill fit. One such type is Any, since everythinghas type Any. If both xand ywere of the same type -- say, Int-- then that would also be a valid return type. Since Scala picks the most specific type, it would pick Intover Any.

很明显,返回值将是xor y,因此类型必须是xy都适合。一种这样的类型是Any,因为一切都有类型Any。如果xy都是相同的类型——比如说Int——那么这也是一个有效的返回类型。由于斯卡拉挑选最具体的类型,这将挑选IntAny

Now, what happens when you don'thave an elsestatement? Even in the absence of an elsestatement, the condition may be false -- otherwise, there would be no point in using if. What Scala does, in this case, is to add an elsestatement. That is, it rewrites that ifstatement like this:

现在,当你发生了什么具备的else声明?即使没有else语句,条件也可能为假——否则,使用if. 在这种情况下,Scala 所做的是添加一个elsestatement。也就是说,它会if像这样重写该语句:

if (true) 2 else ()

Like I said before: if you do not have anything to return, return Unit! That is exactly what happens. Since both Intand Unitare AnyVal, and given that AnyValis more specific than Any, that line returns AnyVal.

就像我之前说的:如果您没有任何东西可退货,请退货Unit!这正是发生的事情。由于IntUnit都是AnyVal,并且AnyVal比 更具体Any,该行返回AnyVal

So far I have explained what others mighthave seen, but not what happens in that specific code in the question:

到目前为止,我已经解释了其他人可能看到的内容,但没有解释问题中特定代码中发生的情况:

if (Tokens.KEYWORDS.contains(sfType)) {
  val retVal = TokenTypes.RESERVED_WORD
}

We have seen already that Scala will rewrite it like this:

我们已经看到 Scala 会像这样重写它:

if (Tokens.KEYWORDS.contains(sfType)) {
  val retVal = TokenTypes.RESERVED_WORD
} else ()

We have alsoseen that Scala will pick the most specific type between the two possible results. Finally, Eclipse tells use that the return type is Unit, so the only possible explanation is that the type of this:

我们看到 Scala 会在两个可能的结果中选择最具体的类型。最后,Eclipse 告诉 use 返回类型是Unit,所以唯一可能的解释是 this 的类型:

  val retVal = TokenTypes.RESERVED_WORD

is also Unit. And that's precisely correct: statements that declare things in Scala have type Unit. And, so, by the way, do assignments.

也是Unit。这完全正确:在 Scala 中声明事物的语句具有 type Unit。而且,顺便说一下,做作业。

The solution, as others have pointed out, is to remove the assignment and add an elsestatement also returning an Int:

正如其他人所指出的,解决方案是删除赋值并添加一条else语句,同时返回一个Int

def contains1(sfType: TokenType): Int =
  if (Tokens.KEYWORDS.contains(sfType)) TokenTypes.RESERVED_WORD
  else -1

(note: I have reformatted the method to follow the coding style more common among Scala programmers)

(注意:我重新格式化了该方法以遵循 Scala 程序员中更常见的编码风格)

回答by sberry

I have a feeling you need to change your method to look like one of the following

我有一种感觉,你需要改变你的方法,看起来像以下之一

def contains1(sfType: TokeType): Int = {
  if (Tokens.KEYWORDS.contains(sfType))
    TokenTypes.RESERVED_WORD
  else 
    -1
}

def contains1(sfType: TokenType) = if (Tokens.KEYWORDS.contains(sfType)) TokenTypes.RESERVED_WORD else -1

回答by pagoda_5b

In scala there's no single ifstatement

在 scala 中没有单一的if语句

Since each expression when evaluated must return a value (it can be an empty value, of type Unit), the ifexpression must be always matched with an elsebranch, and both must return the same type, or in the worst case scala will infer the most common supertype.

由于当评价必须返回一个值的每个表达式(它可以是一个空值的类型,Unit),则if表达式必须总是以匹配else分支,都必须返回相同的类型,或者在最坏的情况下阶将推断的最常见超类型。

In your code you return a Intfrom the ifbranch, but the elsebranch is missing.

在您的代码中,您Intif分支返回 a ,但else缺少分支。

updated

更新

As stated correctly in other answers:

正如其他答案中所述:

the single ifexpression returns the only alternative within it, which for the original post is the return value of an assignment, which is ()of type Unit

单个if表达式返回其中的唯一替代项,对于原始帖子,它是赋值的返回值,其()类型为Unit

回答by Bob

Eclipse thinks that if the "if" block is false, i.e, Tokens.KEYWORDS.contains(sfType)is false, then the return type will indeed be Unit, which is the problem.

Eclipse 认为如果“if”块为假,即Tokens.KEYWORDS.contains(sfType)is false,那么返回类型确实是Unit,这就是问题所在。