00:00
我们现在已经了解了scla当中的函数质简原则,那就是能省则省,尽量的简化,让表达式简单明了啊,以至于有些场景下,我们可以直接把它简化成就像数学当中的一个函数表达一样啊,FX等于X这样的一个表达,那最后我们甚至呢,可以把函数名称和DEF也省略掉,得到的就是一个匿名函数,或者叫拉姆达表达式。那有些同学可能会有疑问,这样一个匿名函数,它连名字都没有,那后面我们怎么样去调用呢?没有名字的话,当然就没有办法直接调用啊,那它到底有什么用呢?其实啊,在scla里边,匿名函数是一个非常强大的功能,它可以实现很多高阶的应用啊,那所以接下来我们就给大家来说一说匿名函数到底有什么用,那接下来我们还是在当前的包下边去新建一个SC的object s05,我们要测试的是命名函数。
01:05
拉姆达表达式,那我们把前面的这个拉姆达表达式先copy过来,如果我们这里边只有这么一句拉姆达表达式的话,大家会发现运行显然是没有任何的输出的啊,当前只是一个函数声明嘛,相当于那我们接下来如果要调用它的话,那该怎么调呢?哎,这里有一个最简单的做法,就是可以直接定义一个量,比方说就叫做f fun,然后呢,后面这个不是一个拉姆达表达式吗?它既然是一个表达式,那其实它就应该有一个,有一个值,有一个返回值,那么把这个返回值我们直接就付给当前的变量,那大家想一想,当前这个变量应该是什么类型呢?它其实就是一个函数类型,所以接下来f fun可以认为当前就是当前这个函数的名称,那所谓的匿名函数当前不就有名了吗?有了名称之后,那接下来就可以正常调用了吗?F fun里边传进来对应的那硅谷看现在如果直接执行的话。
02:12
那就会正常的打印输出艾特硅谷啊,所以这是一个非常简单的实现,我们直接可以把它赋给一个变量,把当前的这个匿名函数啊,整个函数作为一个值赋给变量。那除了这种用法之外呢,其实更长,呃,大家可能会发现这种用法好像也没什么特别的对吧?这不就本来人家匿名函数是没有名称的,你现在付给一个变量,这不相当于又有了一个名称吗?啊,那你直接一开始就给他一个名不就完了吗?何必这么麻烦呢啊,那其实更多的使用是怎么样用呢?可以把它直接当成一个参数还给另外一个函数,这样的话就可以极大的扩展函数的功能,所以我们管它呃,叫做这个高阶的应用啊,这又是什么意思呢?这里我们可以另外的定义一个,定义一个函数,以函数作为函数输入,这是什么意思呢?比方说我们先把这个直接声明出来之前,这个函数我们就直接叫做F,然后它里边它接收的参数必须是一个。
03:26
是必须是一个另外一个函数啊,当然这里边的类型我们现在不太好想,我们先把它空下,那我是要接受一个叫做f fun的放啊,这样一个函数放进来才可以啊,如果大家想跟前面这个区分开的话,我们这个参数干脆叫f func吧,放,那有了这一个作为参数之后,最后比方说我们也不需要有任何的返回啊,就一个unit,那里边做什么操作呢?因为得到的这本身是一个参数,一个函数嘛,所以接下来呢,我就可以直接在这个F里边调用这个函数。
04:03
放直接调用一下,然后呢,Fun,我要求他必须有一个参数,这个参数是一个string类型的,我这里边呢,直接就把这个参数。你死了,比方说我们就叫F硅谷,直接传进来。要用一下这个func放这个函数,哎,那所以这里面的关键就在于func,这是一个函数,它必须以string作为作为参数返回值类型,这里好像没有什么要求啊,那我们可以定义成一个unit的返回值类型,那当前这个参数的类型,函数的类型到底应该怎么写呢?诶,大家会发现这不就是我们前面定义的这个fun这个匿名函数啊,后面这个匿名函数的这个类型吗?以一个string类型作为参数,然后啊,不需要有任何的返回值,返回值是一个unit类型,不就是它吗?我们可以在这里利用idea给我们的这么一个快捷方式啊,大家可以把它全部选出,按一下不是一个拉姆的表达式吗?看一下这个表达式的返回值到底是什么。
05:08
大家其实这里可以看到自动推断出来它的类型是这样的,一个string,然后加一个朝右的箭头unit这样的一个类型,这有点像拉姆达表达式,但是呢,大家注意这不是拉姆达表达式,因为真正的拉姆达表达式肯定是前面参数你必须有名称,然后冒号带上类型,后面是一个是一个函数企业对吧,执行真正能够执行的代码,而不是这样简单的就是两个类型,如果这里边只有两个类型的话,这其实表示的就是。就是一个函数类型,就是以string作为参数,Unit作为返回值类型的这样的一个函数。啊,所以大家就会发现了啊,之前如果我们要定义这个book的话,那是不是就相当于要有它的类型,就是这样的一个函数类型啊,String作为参数,然后一个箭头都以它作为返回值,就是这样的一个函数,所以接下来目前的这个F如果要做用的时候,那是不是它里边也必须得传一个这样的函数啊,那所以这里边我们传什么样这什么样的函数就符合这样的条件呢?我们前面定义的这个fun放不就符合这个条件吗?所以接下来调用其实就是F,然后把放作为参数给它传进去。
06:30
那这里面我们直接上面,我们还是写一个分接分割线。接下来做一个运行,我们就会看到当前其实就是直接把艾特硅谷做了一次打印,为什么可以直接打印呢?那就是因为F做调用的时候,相当于它底层调用的是。F func,它的参数这个函数,那当前这个参数到底又是谁呢?是传进来的fun for,所以相当于最终我们是调用了一个f fun,那f fun调用的时候得有一个参数啊,它的参数又是谁呢?就是这里定义好的艾特硅谷,所以最终我们还是把艾特硅谷打印输出了啊,那大家可能会发现这个东西好像有点绕,那它到底能实现什么样的一个功能呢?
07:17
简单来讲,就是我们一般想象的一个函数,都是定义好了这个函数里边要干什么事儿,然后呢,把需要的数据作为参数传进来,而现在我们定义的这个F呢,这个函数就比较特殊了,它不是要把数据传进来,而是要把你要干什么事儿,把操作要做的那个操作作为一个函数,作为参数传进来。而具体的数据呢,数据是定死的,已经写死在里边了,所以我们这里边呢,相当于是数据要处理的就是艾特硅谷,那你至于是要把这个艾特硅谷直接打印输出呢,还是说要把这个。
08:00
数据这个string,再做一些别的加工,做一些转换别的操作,然后得到一个别的,呃,其他的一个类型的数据结构呢,啊这个。就由我们这里的参数由这个放传入的函数来决定了,所以我们相当于就是定死了数据,然后传入一个对应的操作,这个操作就由函数定义。所以我们在调用的时候呢,可以直接传一个定义好的函数,当然也就可以传,大家看是不是就可以直接传一个匿名函数啊,所以我们把前面的这一部分直接作为一个匿名函数。工程F的参数写进来也是一样的,这个如果直行一下的话,就跟上面F直接传一个fun是完全一样的结果,哎,这就是匿名函数的一个最常见的用法。那关于这个用法,大家可能会发现,直接这么写的话,这个还是有点太复杂了,里边又涉及到拉姆达表达式的这种语法规则啊,一个右朝右的一个箭头,然后呢,呃,这里面又涉及到前面是参数,后边是这个函数体啊,那能不能它也做一些简化呢?那直观上这么看的话,我们这么用就觉得这不好用啊。
09:18
哎,那接下来我们来讲解一下匿名函数的。简化原则,那其实这一部分原则大家也可以归并到之前我们讲的函数质简原则里边,最终都是要把它变得简单明了啊,就程序员使用的时候越简单越好啊,那这里边又有哪些具体的原则呢?我们可以参考一下文档里边给大家介绍的匿名函数,接下来这些质检原则有主要有四条,我们还是直接copy过来。步调,然后接下来我们就依次来看一下到底说的是什么?首先一条说的是参数的类型可以省略,会根据行参进行自动推导,这是什么意思呢?哎,这是因为当前。
10:10
看看上边这个啊,我们这里边定义的这个行参啊,我们这里边本身这个拉姆达表达式就是一个行参嘛,那这里边的这个行参其实是不是它的类型在上边我们定义F的时候都已经确定了呀,哎,所以接下来我们后边传拉姆达表达式的时候,没有必要再定义这个,当前这个参数name一定是string类型了,我们定义死了这个函数它必须是参数是string类型,返回值是unit类型对吧?哎,所以接下来你这里边根本没必要再去强调这一点了,所以可以把它直接省略掉,好,那所以接下来我们就看一下这个要用的形式啊,但大家可能会放在一行里边看的会更舒服一点,我们还是先把它换行能写出来吧。首先就是前面的句。的类型可以直接省略掉,然后接下来我们继续省略。
11:04
第二个原则,省略掉之后,如果当前的参数只有一个参数的话,那括号可以省略啊,这个比较好理解对吧?啊,因为前面这里边我们只有一个参数,本身就是一个一个东西嘛,一个变量嘛,你直接把它单独列出来不就完了吗?啊,所以就是变成了内,然后后面是一个箭头,后面是它的函数题,大家看这个就看起来非常的简洁了,就是你传入一个参数,然后接下来呢,我就print line把这个参数直接打印出来,哎,这里边就非常的简单了啊,当然就是说这里边的要求就是说只有一个参数啊,如果要是没有参数,没有参数的话,是不是应该是一个空括号啊,这个空括号肯定就不能省略了,然后另外如果说参数要有两个或者两个以上的话,那都得用逗号分割,外边的括号也不能省略,所以只有是一个参数的时候,才能够做这样的一个省略,这个大家一定要注意,然后接下来呢啊,还可以继续省略,如果匿名。
12:05
函数的函数体只有一行。括号也可以省略啊,这个大家是非常的清楚的啊,那就这里边来,我们不就是打块只有一行的话,大括号可以省略吗?那接下来大家看到,那就我们直接放在一行,可能就非常的明确了啊,不是参数传入一个name,然后接下来就得到一个print line name,就把这个name做一个打印就完了,我们要做的操要做的操作其实就是这样的一步操作,之前我们说了F里边要传的不就是一个操作吗?针对定义好的数据艾特硅谷的一个操作,所以我们其实就是要把它做一个打印。那进一步大家其实就发现了啊,当前的这一个name其实只是一个参数名称而已,我们这里是叫name,那你如果叫我这里如果叫X可以吗?X也没有问题啊,这里如果叫A可以吗?
13:00
A也是可以的,哎,所以这里边大家会发现啊,当前这个参数名称是没有任何的影响,所以我干脆就可以把它做一个省略,因为至于你到底叫什么名,我根本不关心嘛,所以直接把它省略的话,那我干脆就连这一个拉姆达表达式的箭头也省略掉好了。所以大家看接下来就是四。原则,如果当前的参数后边只出现了一次的话,那么。参数可以直接省略,然后后边的就是包括这个箭头,拉德表达式的这个语法的箭头也可以省略,后边的参数出现的地方呢,用一个下划线通配符来做一个代替,所以当前我们调用写成了F里边直接print line一个下划线。大家看,这样写也是符合语法规则的。啊啊,那当然了,我们甚至还可以进一步再做一个,做一个简化,哎,那就是如果可以推断出。
14:13
当前传入特拉。是一个函数比,而不是。调用语句可以直接省略下划线,也就是说连下划线都可以直接省略,就是什么意思呢?啊,因为其实大家发现了我们当前要做的这个操作,这不就是要给F传一个对于艾特硅谷这个数据啊,要执行的要执行的一个方法,要执行的一步操作吗?我们要执行的是什么呢?就是print line嘛,就是把它直接打印出来嘛,所以当前其实我没有必要一定要传一个参数,然后再去把这个print line做一次调用,我直接传print line这个操作不就完事了吗?哎,所以基于这样的想法,我甚至直接可以。
15:16
大家要注意啊,这里就不能有调用了,而是直接传print来把这个函数名称作为一个整体,作为一个函数本身传进来,直接做一个打印,这也是合法的,所以最终我们就把它简化到了这一步。如果我们要是运行的话,大家会发现每一行代码我们这里简化之后,每一行都会直接打印输出一次艾特硅谷,最终我们简化的操作简化到这一步就看出来了,我们其实干什么,干了什么呢?F这个函数,它的作用就是要把艾特硅谷这个数据用一个操作做一个转换,做一个输出,那我们当前传进来的操作是什么呢?就是print line,就是把它打印输出。
16:02
这就是关于拉姆达表达式的使用,以及它的简化的规则。
我来说两句