Ana*_*ran 244 methods scala function
我阅读了Scala Functions(另一个Scala之旅的一部分).在那篇文章中他说:
方法和功能不是一回事
但他没有解释任何有关它的事情.他想说什么?
Dan*_*ral 229
吉姆在他的博客文章中已经详细介绍了这一点,但我在这里发布了一个简报以供参考.
首先,让我们看看Scala规范告诉我们的内容.第3章(类型)告诉我们函数类型(3.2.9)和方法类型(3.3.1).第4章(基本声明)涉及价值声明和定义(4.1),变量声明和定义(4.2)以及函数声明和定义(4.6).第6章(表达式)讲述了匿名函数(6.23)和方法值(6.7).奇怪的是,函数值在3.2.9中被称为一次,而在其他地方则没有.
甲函数类型是(大约)的类型的形式(T1,...,TN)=>Ü,这对于该性状的简写FunctionN在标准库.匿名函数和方法值具有函数类型,函数类型可以用作值,变量和函数声明和定义的一部分.实际上,它可以是方法类型的一部分.
甲方法类型是一个非值类型.这意味着没有值 - 没有对象,没有实例 - 具有方法类型.如上所述,方法值实际上具有函数类型.方法类型是一个def声明 - def除了它的主体之外的一切.
值声明和定义以及变量声明和定义是val和var声明,包括类型和值 - 它们可以分别是函数类型和匿名函数或方法值.请注意,在JVM上,这些(方法值)是使用Java调用"方法"实现的.
甲函数声明 是一个def声明,包括类型和身体.类型部分是方法类型,主体是表达式或块.这也是在Java上用Java调用"方法"的JVM上实现的.
最后,匿名函数是函数类型的实例(即特征的实例FunctionN),而方法值是同一个东西!的区别在于,一个方法数值是从方法,或者通过加上后缀下划线创建(m _对应于该"函数声明"的方法的值(def)m),或者通过被称为过程ETA-膨胀,这就像是从方法的自动浇注发挥作用.
这就是规范所说的,所以让我把它放在前面:我们不使用那个术语!这导致了所谓的"函数声明"之间的混淆,它是程序的一部分(第4章 - 基本声明)和"匿名函数",它是一个表达式,而"函数类型",它是,一种类型 - 一种特质.
下面的术语,由经验丰富的Scala程序员使用,从规范的术语做了一个改变:我们说方法,而不是说函数声明.甚至方法声明.此外,我们注意到值声明和变量声明也是实用的方法.
因此,鉴于上述术语的变化,这里是对这种区别的实际解释.
甲函数是一个对象,包括所述的一个FunctionX特征,诸如Function0,Function1,Function2等.它可以被包括PartialFunction为好,这实际上延伸Function1.
让我们看看其中一个特征的类型签名:
trait Function2[-T1, -T2, +R] extends AnyRef
Run Code Online (Sandbox Code Playgroud)
这个特性有一个抽象方法(它也有一些具体的方法):
def apply(v1: T1, v2: T2): R
Run Code Online (Sandbox Code Playgroud)
这告诉我们所有人都应该了解它.甲函数有一个apply接收方法Ñ类型的参数T1,T2,...,TN,并返回型的东西R.它在接收的参数上是反变量的,并且在结果上是共变量.
这种差异意味着a Function1[Seq[T], String]是a的子类型Function1[List[T], AnyRef].作为子类型意味着它可以用来代替它.人们可以很容易地看到,如果我要打电话f(List(1, 2, 3))并期待AnyRef回来,上述两种类型中的任何一种都可以.
现在,方法和函数的相似之处是什么?好吧,如果f是一个函数并且m是作用域的本地方法,则可以像这样调用它们:
val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
这些调用实际上是不同的,因为第一个只是一个语法糖.Scala将其扩展为:
val o1 = f.apply(List(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
当然,这是对对象的方法调用f.函数还有其他语法糖的优点:函数文字(实际上是其中两个)和(T1, T2) => R类型签名.例如:
val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
case i: Int => "Int"
case d: Double => "Double"
case o => "Other"
}
Run Code Online (Sandbox Code Playgroud)
方法和函数之间的另一个相似之处是前者可以很容易地转换为后者:
val f = m _
Run Code Online (Sandbox Code Playgroud)
假设类型为(Scala 2.7),Scala将扩展它:m(List[Int])AnyRef
val f = new AnyRef with Function1[List[Int], AnyRef] {
def apply(x$1: List[Int]) = this.m(x$1)
}
Run Code Online (Sandbox Code Playgroud)
在Scala 2.8上,它实际上使用了一个AbstractFunction1类来减少类的大小.
请注意,无法转换其他方式 - 从函数到方法.
然而,方法有一个很大的优点(好吧,两个 - 它们可以稍快一些):它们可以接收类型参数.例如,虽然f上面可以指定List它接收的类型(List[Int]在示例中),但m可以参数化它:
def m[T](l: List[T]): String = l mkString ""
Run Code Online (Sandbox Code Playgroud)
我认为这几乎涵盖了所有内容,但我很乐意将其与可能存在的任何问题的答案相辅相成.
Ben*_*ngs 66
方法和功能之间的一个重要的实际区别是什么return意思. return只从方法返回.例如:
scala> val f = () => { return "test" }
<console>:4: error: return outside method definition
val f = () => { return "test" }
^
Run Code Online (Sandbox Code Playgroud)
从方法中定义的函数返回非本地返回:
scala> def f: String = {
| val g = () => { return "test" }
| g()
| "not this"
| }
f: String
scala> f
res4: String = test
Run Code Online (Sandbox Code Playgroud)
而从本地方法返回只从该方法返回.
scala> def f2: String = {
| def g(): String = { return "test" }
| g()
| "is this"
| }
f2: String
scala> f2
res5: String = is this
Run Code Online (Sandbox Code Playgroud)
jam*_*het 36
function可以使用参数列表调用函数以生成结果.函数具有参数列表,正文和结果类型.作为类,特征或单个对象的成员的函数称为方法.在其他函数内定义的函数称为局部函数.结果类型为Unit的函数称为过程.源代码中的匿名函数称为函数文字.在运行时,函数文字被实例化为称为函数值的对象.
在Scala第二版中编程.Martin Odersky - Lex Spoon - Bill Venners
ani*_*ish 29
假设你有一个清单
scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
Run Code Online (Sandbox Code Playgroud)
定义方法
scala> def m1(i:Int)=i+2
m1: (i: Int)Int
Run Code Online (Sandbox Code Playgroud)
定义一个函数
scala> (i:Int)=>i+2
res0: Int => Int = <function1>
scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Run Code Online (Sandbox Code Playgroud)
接受论证的方法
scala> m1(2)
res3: Int = 4
Run Code Online (Sandbox Code Playgroud)
用val定义函数
scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>
Run Code Online (Sandbox Code Playgroud)
功能参数是可选的
scala> p(2)
res4: Int = 4
scala> p
res5: Int => Int = <function1>
Run Code Online (Sandbox Code Playgroud)
对方法的争论是强制性的
scala> m1
<console>:9: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
Run Code Online (Sandbox Code Playgroud)
检查以下教程,解释通过其他示例传递其他差异,例如使用方法Vs函数的diff的其他示例,使用函数作为变量,创建返回函数的函数
这里有一篇不错的文章,从中可以得到我大多数的描述。关于我的理解,仅是功能和方法的简短比较。希望能帮助到你:
功能:它们基本上是一个对象。更准确地说,函数是具有apply方法的对象;因此,由于它们的开销,它们比方法要慢一些。从某种意义上说,它与静态方法类似,它们独立于要调用的对象。一个简单的函数示例就像下面这样:
val f1 = (x: Int) => x + x
f1(2) // 4
Run Code Online (Sandbox Code Playgroud)
除了将一个对象分配给另一个对象(如object1 = object2)外,上面的行什么都没有。实际上,在我们的示例中,object2是一个匿名函数,因此,左侧获取了对象的类型。因此,现在f1是一个对象(函数)。匿名函数实际上是Function1 [Int,Int]的实例,这意味着具有1个Int类型的参数和Int类型的返回值的函数。不带参数调用f1将为我们提供匿名函数的签名(Int => Int =)
方法:它们不是对象,而是分配给类的实例(即对象)。与Java中的方法或c ++中的成员函数(如Raffi Khatchadourian在对此问题的评论中指出)等完全相同。方法的一个简单示例就像下面这样:
def m1(x: Int) = x + x
m1(2) // 4
Run Code Online (Sandbox Code Playgroud)
上面的行不是简单的值分配,而是方法的定义。当您像第二行一样使用值2调用此方法时,x将替换为2,并且将计算结果,并获得4作为输出。如果只是简单地写入m1,这是一个错误,因为它是方法并且需要输入值。通过使用_,您可以将方法分配给以下函数:
val f2 = m1 _ // Int => Int = <function1>
Run Code Online (Sandbox Code Playgroud)