2个不同的例子,第一个有效:
import cats.syntax.either._
val e = 10.asRight[String]
def i2s(i:Int):String = i.toString
e.map(i => List(i2s(i))) //using explicit parameter
e.map(List(i2s(_))) //using no-name _ parameter
现在没有编译带有 Option 的相同示例:
e.map(Option(i2s(_)))
错误:
Error:(27, 15) type mismatch;
found : Option[Int => String]
required: Int => ?
e.map(Option(i2s(_)))
使用显式参数它工作正常:
e.map(i => Option(i2s(i)))
在这两种情况下,apply 方法都是用 List 和 Option 调用的。
List.apply
签名: def apply[A](xs: A*): List[A] = ???
Option.apply
签名: def apply[A](x: A): Option[A]
请解释区别。
最佳答案
您的List
示例可以编译,但它们的意思不同,也不会产生相同的结果。
e.map(i => List(i2s(i))) //res0: scala.util.Either[String,List[String]] = Right(List(10))
e.map(List(i2s(_))) //java.lang.IndexOutOfBoundsException: 10
第一个很容易理解,那么第二个呢?
发生的事情是您正在使用 eta expansion创建一个
Int => String
来自 i2s()
的函数方法。然后填充 List
将该单个函数作为列表中的唯一元素,然后尝试检索索引 10
处的值,它不存在,因此是异常(exception)。如果将第一行更改为
val e = 0.asRight[String]
然后异常消失,因为索引 0
中确实存在某些内容,刚才放在那里的函数。这编译是因为
List
实例将接受 Int
作为参数(通过隐藏的 apply()
方法),但是一个 Option
实例没有 apply()
采用 Int
的方法(*) 所以无法编译。(*)
Option
对象确实有一个 apply()
方法,但那是另一种动物。
关于Scala:带有列表和选项的函数中的无名参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56250926/