在Scala中函数和方法有什么区别php
方法能够做为一个表达式的一部分出现(调用函数并传参),可是方法(带参方法)不能做为最终的表达式,html
可是函数能够做为最终的表达式出现:express
scala> //定义一个方法 scala> def m(x:Int) = 2*x m: (x: Int)Int scala> //定义一个函数 scala> val f = (x:Int) => 2*x f: Int => Int = <function1> scala> //方法不能做为最终表达式出现 scala> m <console>:9: error: missing arguments for method m; follow this method with `_‘ if you want to treat it as a partially applied function m ^ scala> //函数能够做为最终表达式出现 scala> f res9: Int => Int = <function1>
无参方法能够做为最终表达式出现,其实这属于方法调用,scala规定无参函数的调用能够省略括号缓存
(关于方法调用咱们下面会涉及到)app
scala> def m1()=1+2 m1: ()Int scala> m1 res10: Int = 3
参数列表对于方法是可选的,可是对于函数是强制的dom
方法的能够没有参数列表,参数列表也能够为空。可是函数必须有参数列表(也能够为空),见下面例子函数
scala> //方法能够没有参数列表
scala> def m2 = 100;
m2: Int
scala> //方法能够有一个空的参数列表
scala> def m3() = 100
m3: ()Int
scala> //函数必须有参数列表,不然报错
scala> var f1 = => 100
<console>:1: error: illegal start of simple expression
var f1 = => 100
^
scala> //函数也能够有一个空的参数列表
scala> var f2 = () => 100
f2: () => Int = <function0>
那么方法为何能够没有参数列表呢,往下看。ui
方法名意味着方法调用,函数名只是表明函数自身this
由于方法不能做为最终的表达式存在,因此若是你写了一个方法的名字而且该方法不带参数(没有参数列表或者无参)url
该表达式的意思是:调用该方法获得最终的表达式。由于函数能够做为最终表达式出现,若是你写下函数的名字,函数
调用并不会发生,该方法自身将做为最终的表达式进行返回,若是要强制调用一个函数,你必须在函数名后面写()
scala> //该方法没有参数列表 scala> m2 res11: Int = 100 scala> //该方法有一个空的参数列表 scala> m3 res12: Int = 100 scala> //获得函数自身,不会发生函数调用 scala> f2 res13: () => Int = <function0> scala> //调用函数 scala> f2() res14: Int = 100
为何在函数出现的地方咱们能够提供一个方法
在scala中不少高级函数,如map(),filter()等,都是要求提供一个函数做为参数。可是为何咱们能够提供一个方法呢
?就像下面这样:
scala> val myList = List(3,56,1,4,72) myList: List[Int] = List(3, 56, 1, 4, 72) scala> // map()参数是一个函数 scala> myList.map((x) => 2*x) res15: List[Int] = List(6, 112, 2, 8, 144) scala> //尝试给map()函提供一个方法做为参数 scala> def m4(x:Int) = 3*x m4: (x: Int)Int scala> //正常执行 scala> myList.map(m4) res17: List[Int] = List(9, 168, 3, 12, 216)
这是由于,若是指望出现函数的地方咱们提供了一个方法的话,该方法就会自动被转换成函数。该行为被称为ETA expansion。
这样的话使用函数将会变得简单不少。你能够按照下面的代码验证该行为:
scala> //指望出现函数的地方,咱们可使用方法 scala> val f3:(Int)=>Int = m4 f3: Int => Int = <function1> scala> //不指望出现函数的地方,方法并不会自动转换成函数 scala> val v3 = m4 <console>:8: error: missing arguments for method m4; follow this method with `_‘ if you want to treat it as a partially applied function val v3 = m4 ^
利用这种自动转换,咱们能够写出很简洁的代码,以下面这样
scala> //10.<被解释成obj.method,即整形的<的方法,因此该表达式是一个方法,会被解释成函数
scala> myList.filter(10.<)
res18: List[Int] = List(56, 72)
由于在scala中操做符被解释称方法
你能够写成10<而不是10.<
scala> myList.filter(10<) warning: there were 1 feature warning(s); re-run with -feature for details res19: List[Int] = List(56, 72)
如何强制把一个方法变成函数
能够在方法名后面加一个下划线强制变成函数,部分应用函数
scala> val f4 = m4 _ f4: Int => Int = <function1> scala> f4(2) res20: Int = 6
传名参数是一个方法
传名参数实质是一个没有参数列表的方法。正是所以你才可使用名字调用而不用添加()
scala> //使用两次‘x‘,意味着进行了两次方法调用 scala> def m1(x: => Int)=List(x,x) m1: (x: => Int)List[Int] scala> import util.Random import util.Random scala> val r = new Random() r: scala.util.Random = scala.util.Random@d4c330b scala> //由于方法被调用了两次,因此两个值不相等 scala> m1(r.nextInt) res21: List[Int] = List(-1273601135, 2004676878)
若是你在方法体部分缓存了传名参数(函数),那么你就缓存了值(由于x函数被调用了一次)
scala> //把传名参数表明的函数缓存起来
scala> def m1(x: => Int) ={val y=x;List(y,y)}
m1: (x: => Int)List[Int]
scala> m1(r.nextInt)
res22: List[Int] = List(-1040711922, -1040711922)
可否在函数体部分引用传名参数所表明的方法呢,是能够的(缓存的是传名参数所表明的方法)。
scala> def m1(x: => Int)={val y=x _;List(y(),y())} m1: (x: => Int)List[Int] scala> m1(r.nextInt) res23: List[Int] = List(-1982925840, -933815401)