揭开功能定义的神秘面纱

时间:2015-08-15 23:40:17

标签: scala

我是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不存在会有问题吗?

3 个答案:

答案 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)

  1. 检查currying
    方法可以定义多个参数列表。当使用较少数量的参数列表调用方法时,这将产生一个函数,将缺少的参数列表作为其参数。
  2. range:String*syntax for varargs
  3. Scala中的
  4. 隐式TypeTag参数是Java中Class<T> clazz参数的替代方法。如果您的类在范围内定义,它将始终可用。 Read more about type tags