揭开函数定义的神秘面纱 [英] Demystifying a function definition
问题描述
我是 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*
如何从range:String
? - 第三,如果
implicit tag: ClassTag[T]
不存在会不会有问题?
首先,为什么定义为 def functionName...(...)(...)(...)?不能定义为 def functionName[...](..., ..., ..., ...) 吗?
使用柯里化的一个很好的理由是支持类型推断.考虑这两个函数:
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 => 的类型×>0
还不能确定,你会得到一个错误:
:22: 错误:缺少参数类型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 怎么做?
它是定义 重复参数又名可变参数.忽略其他差异,它只能用于最后一个位置,并且可以作为 scala.Seq
使用(这里是 scala.Seq[String]
).典型的用法是集合类型的 apply
方法,它允许像 SomeDummyCollection(1, 2, 3)
这样的语法.更多内容请看:
第三,如果隐式标签:ClassTag[T]不存在会不会有问题?
正如 Aivean 所述,这里不应该是这种情况.ClassTags
由编译器自动生成,只要类存在就应该可以访问.在一般情况下,如果无法访问隐式参数,您将收到错误消息:
scala>导入 scala.concurrent._导入 scala.concurrent._标度>val 答案:Future[Int] = Future(42)<console>:13: 错误:找不到隐式的 ExecutionContext.你可能会通过方法的(隐式 ec:ExecutionContext)参数或导入 scala.concurrent.ExecutionContext.Implicits.global.val 答案:Future[Int] = Future(42)
I am new to Scala, and I hope this question is not too basic. I couldn't find the answer to this question on the web (which might be because I don't know the relevant keywords).
I am trying to understand the following definition:
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))
}
- First , why is it defined as
def functionName[...](...)(...)(...)(...)
? Can't we define it asdef functionName[...](..., ..., ..., ...)
? - Second, how does
range: String*
fromrange: String
? - Third, would it be a problem if
implicit tag: ClassTag[T]
did not exist?
First , why is it defined as def functionName...(...)(...)(...)? Can't we define it as def functionName[...](..., ..., ..., ...)?
One good reason to use currying is to support type inference. Consider these two functions:
def pred1[A](x: A, f: A => Boolean): Boolean = f(x)
def pred2[A](x: A)(f: A => Boolean): Boolean = f(x)
Since type information flows from left to right if you try to call pred1
like this:
pred1(1, x => x > 0)
type of the x => x > 0
cannot be determined yet and you'll get an error:
<console>:22: error: missing parameter type
pred1(1, x => x > 0)
^
To make it work you have to specify argument type of the anonymous function:
pred1(1, (x: Int) => x > 0)
pred2
from the other hand can be used without specifying argument type:
pred2(1)(x => x > 0)
or simply:
pred2(1)(_ > 0)
Second, how does range: String* from range: String?
It is a syntax for defining Repeated Parameters a.k.a varargs. Ignoring other differences it can be used only on the last position and is available as a scala.Seq
(here scala.Seq[String]
). Typical usage is apply
method of the collections types which allows for syntax like SomeDummyCollection(1, 2, 3)
. For more see:
- What does `:_*` (colon underscore star) do in Scala?
- Scala variadic functions and Seq
- Is there a difference in Scala between Seq[T] and T*?
Third, would it be a problem if implicit tag: ClassTag[T] did not exist?
As already stated by Aivean it shouldn't be the case here. ClassTags
are automatically generated by the compiler and should be accessible as long as the class exists. In general case if implicit argument cannot be accessed you'll get an error:
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)
这篇关于揭开函数定义的神秘面纱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!