我是Scala的新手,我希望这个问题不是太基础。我无法在网上找到这个问题的答案(这可能是因为我不知道相关的关键字)。
我试图理解以下定义:
def functionName[T <: AnyRef](name: Symbol)(range: String*)(f: T => String)(implicit tag: ClassTag[T]): DiscreteAttribute[T] = {
val r = ....
new anotherFunctionName[T](name.toString, f, Some(r))
}
def functionName[...](...)(...)(...)(...)
?我们无法将其定义为def functionName[...](..., ..., ..., ...)
?range: String*
的{{1}}怎么办?range: String
不存在会有问题吗? 答案 0 :(得分:4)
首先,为什么定义为def functionName ...(...)(...)(...)?我们不能将其定义为def functionName [...](...,...,...,...)?
使用currying的一个好理由是支持类型推断。考虑这两个功能:
def pred1[A](x: A, f: A => Boolean): Boolean = f(x)
def pred2[A](x: A)(f: A => Boolean): Boolean = f(x)
如果你试图像这样调用pred1
,类型信息会从左向右流动:
pred1(1, x => x > 0)
x => x > 0
的类型无法确定,您将收到错误消息:
<console>:22: error: missing parameter type
pred1(1, x => x > 0)
^
要使其工作,您必须指定匿名函数的参数类型:
pred1(1, (x: Int) => x > 0)
另一方面, pred2
可以在不指定参数类型的情况下使用:
pred2(1)(x => x > 0)
或简单地说:
pred2(1)(_ > 0)
其次,range:String * from range:String?
这是定义Repeated Parameters a.k.a varargs的语法。忽略其他差异,它只能在最后一个位置使用,并以scala.Seq
(此处为scala.Seq[String]
)提供。典型用法是集合类型的apply
方法,它允许使用SomeDummyCollection(1, 2, 3)
之类的语法。有关详情,请参阅:
第三,如果隐式标签:ClassTag [T]不存在会是一个问题吗?
如Aivean所述,这不应该是这样的。 ClassTags
由编译器自动生成,只要该类存在,就应该可以访问。一般情况下,如果无法访问隐式参数,则会收到错误:
scala> import scala.concurrent._
import scala.concurrent._
scala> val answer: Future[Int] = Future(42)
<console>:13: error: Cannot find an implicit ExecutionContext. You might pass
an (implicit ec: ExecutionContext) parameter to your method
or import scala.concurrent.ExecutionContext.Implicits.global.
val answer: Future[Int] = Future(42)
答案 1 :(得分:2)
多个参数列表:这称为“currying”,它使您能够仅使用一些参数调用函数,从而产生一个函数,该函数接受其余参数并生成结果类型(部分函数应用程序) )。 Here是Scala文档的链接,提供了使用此示例的示例。此外,函数的任何隐式参数必须在一个参数列表中一起指定,在任何其他参数列表之后。虽然以这种方式定义函数不是必需(除了任何隐式参数),这种函数定义有时可以更清楚地说明函数的使用方式,和/或使部分语法应用程序看起来更自然(f(x)
而不是f(x, _)
)。
带星号的参数:“varargs”。此语法表示不是预期的单个参数,而是可以传入可变数量的参数,这些参数将作为(在本例中)Seq[String]
处理。它相当于在Java中指定(String... range)
。
隐式ClassTag:这通常需要确保正确输入函数结果,其中在编译时无法确定类型(T
此处)。由于Scala在JVM上运行,JVM在编译时间之外不保留类型信息,因此这是Scala中使用的一种解决方法,以确保在运行时仍然可以获得有关所涉及类型的信息。
答案 2 :(得分:2)
方法可以定义多个参数列表。当使用较少数量的参数列表调用方法时,这将产生一个函数,将缺少的参数列表作为其参数。
range:String*
是syntax for varargs TypeTag
参数是Java中Class<T> clazz
参数的替代方法。如果您的类在范围内定义,它将始终可用。 Read more about type tags。