在Scala中函数和方法有什么区别

方法可以作为一个表达式的一部分出现(调用函数并传参),但是方法(带参方法)不能作为最终的表达式,

但是函数可以作为最终的表达式出现:

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规定无参函数的调用可以省略括号

(关于方法调用我们下面会涉及到)

scala> def m1()=1+2

m1: ()Int

scala> m1

res10: Int = 3

参数列表对于方法是可选的,但是对于函数是强制的

方法的可以没有参数列表,参数列表也可以为空。但是函数必须有参数列表(也可以为空),见下面例子

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>

那么方法为什么可以没有参数列表呢,往下看。

方法名意味着方法调用,函数名只是代表函数自身

因为方法不能作为最终的表达式存在,所以如果你写了一个方法的名字并且该方法不带参数(没有参数列表或者无参)

该表达式的意思是:调用该方法得到最终的表达式。因为函数可以作为最终表达式出现,如果你写下函数的名字,函数

调用并不会发生,该方法自身将作为最终的表达式进行返回,如果要强制调用一个函数,你必须在函数名后面写()

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中操作符被解释称方法

前缀操作符:op obj 被解释称obj.op

中缀操作符:obj1 op obj2被解释称obj1.op(obj2)

后缀操作符:obj op被解释称obj.op

你可以写成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 = [email protected]

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)

时间: 2024-10-04 09:30:04

在Scala中函数和方法有什么区别的相关文章

Go - 反射中 函数 和 方法 的调用

上一篇文章 说到了 Golang 中的反射的一些基本规则,重点就是文章中最后的三点,但是这篇文章并没有说如何在反射中调用函数和方法,这就是接下来要说的. 反射中调用 函数 众所周知,Golang 中的函数是可以像普通的 int.float 等类型变量那样作为值的,例如: package main import "fmt" func hello() { fmt.Println("Hello world!") } func main() { hl := hello hl

Javscript调用iframe框架页面中函数的方法

Javscript调用iframe框架页面中函数的方法,可以实现iframe之间传值或修改值了, 访问iframe里面的函数: window.frames['CallCenter_iframe'].hw_CallIn(callerid,sessionid); 说明: CallCenter_iframe为iframe的id hw_CallIn为iframe中页面中的方法名 callerid和sessionid为方法中的参数 例子如下:index.html <a href="#" o

Matlab中函数定义方法

Matlab自定义函数的六种方法 n1.函数文件+调用函数(命令)文件:需单独定义一个自定义函数的M文件: n2.函数文件+子函数:定义一个具有多个自定义函数的M文件: n3.Inline:无需M文件,直接定义: n4.匿名函数: n5.Syms+subs:无需M文件,直接定义: n6.字符串+subs:无需M文件,直接定义. ------------ 1.函数文件+调用函数文件:定义多个M文件 % 调用函数文件:myfile.m clear clc for t=1:10 y=mylfg(t);

Python中函数和方法的区别

1.函数要手动传self,方法不用传self 2.如果是一个函数,用类名去调用,如果是一个方法,用对象去调用 举例说明: class Foo(object): def __init__(self): self.name="haiyan" def func(self): print(self.name) obj = Foo() obj.func() Foo.func(obj) 判断函数和方法的方式 from types import FunctionType,MethodType obj

php中函数和方法的区别

php的方法就是定义在类里面的方法,一般不建议在方法内部定义方法,但是这种也可以这种叫做内部方法,一般只能本方法调用. 如果定义在同一个类中的方法,在同类的其他方法中调用是$this->方法名就可以这样调用了 php函数是可以在框架中增加的D:\web\yezhufang\code\Application\Admin\Common\function.php 是可以在这个页面中增加的.

python中函数和方法区别,以及如何给python类动态绑定方法和属性(涉及types.MethodType()和__slots__)

网上有很多同义但不同方式的说法,下面的这个说法比较让你容易理解和接受 1 与类和实例无绑定关系的function都属于函数(function): 2 与类和实例有绑定关系的function都属于方法(method). “与类和实例无绑定关系”就道出了其中的关键 我们知道python是动态的编程语言,python的类除了可以预先定义好外,还可以在执行过程中,动态地将函数绑定到类上,绑定成功后,那些函数就变成类的方法了. 定义User类 可以使用__slots__来限制绑定的属性和方法 1 user

scala中函数简单使用记录

object funcHighLevel { def main(args: Array[String]): Unit = { // 创建一个匿名函数 val sayFunc = (name: String) => println("hello ," + name) // 定义一个方法传入一个函数 def greeting(func: (String) => Unit, names: String) { func(names) } // 在定义一个 name,age是参数 v

Scala 中 case class 与 class 的区别(代码示例)

class 类似Java中的class case class 被称为样例类,是一种也输的类,常被用于模式匹配 具体区别: 1,初始化的时候可以不用new ,也可以加上,但是普通类必须加上new 2,默认实现了equals.hashCode方法 3,默认是可以序列化的,实现了Serializable 4,case class 构造函数参数是public的,我们可以直接按访问 5,case class默认情况下不能修改属性值 7,case class 最重要的功能,支持模式匹配,这也是定义case

JavaScript中函数对象和对象的区别

function Test (word) { console.log (word); } Test('哈哈,我是函数'); new Test('哈哈,我是对象'); //将以上的调用方式换种通俗易懂的方式 Test.call("哈哈,我是函数"); //相当于Test(); //相当于new Test(); var obj = {}; obj._proto_ = Test.prototype; Test.call(obj); 本质的区别就是,两次调用之中的this不同.调用Test('