函数式编程中的战斗机(一):elm语言中的lambdas函数使用指南

1 函数式编程的优点

函数式编程(FP)是一种编程范式,渊源久远。与命令式编程、面向对象编程(OOP)合称为三大编程范式。也有专门的函数式编程语言,久远如大名鼎鼎的始祖LIST语言,近如haskell等。近年来,函数式编程有逐渐发展鼎盛的趋势。相对其余两种编程范式,它有如下特点和优势:

1.1 数据不可变,对外没有副作用;

函数式编程强调数据不可变,函数里面的数值是固定的,因此象randam这种随机数是不能放在函数里面。

1.2 纯函数;

同样的输入,通过函数可以有同样的输出。意即函数对外没有副作用,这次往函数里输入1输出10,下次还是这个结果。因此我们可以十分放心地使用函数,不用担心它会对外造成污染和出现一些不可预料、难以测试的结果。

1.3 柯里化;

多参数的函数,可以通过柯里化转变成单参数的函数,便于组合和阅读理解。柯里化是函数式编程里一个重要的特征和功能,它能够进一步把逻辑抽象出来。举例:foo a = bar foo a这样形式的一个功能函数,柯里化后,转化成 foo = bar a,既可以易于重用又容易理解。

1.4 功能组合,不易出错;

函数化编程由于它的上述特点,在实际应用中,可以大幅减少代码量,也去除了大量烦人的大括号小括号。同时通过纯函数的组合作用,可以用简短的语令实现相当复杂的功能,可以理解为柯里化后的纯函数是一个个质量可靠的乐高积木,通过这些乐高积木为基础砖块搭建的建筑极其坚固,不易坍塌。

在这里插入图片描述

1.5 近年来趋势

近年来,函数式编程有逐渐发展鼎盛的趋势,如大名鼎鼎的facebook的前端js框架react以及跨端应用框架react native就是充分应用了函数式编程的范例。排名前几位的编程语言,如python、javascipt 、C++等,都可以把函数作为一等对象,实现函数式编程范式的充分条件。

2 elm语言的简要说明

2.1 前端语言与javascript

近年来,前端技术发展迅速,各种前端框架层出不穷,更进一步巩固了javascript语言在前端的的地位。如haskell、LIST等的函数式编程语言,多数用在后端。

2.2 javascript语言的不足及替代

Javascript强大,是一种多范式语言,也非常适合于函数式编程,但它毕竟不是一种函数语言,而且动态类型也备受开发者鞭挞。同时,多范式语言便利,但也无形中局限开发者函数式编程思维模式。

2.3. 近年兴起的函数式编程

为此,聪明的大牛们创造了各种各样的框架和语言,以弥补javascript的不足,语言如purescript、conjascript、coffescript等,框架如ramda等,成功推动了函数式编程在javascript中的开花结果。

2.4. elm语言是其中的王者

众多语言和框架中,elm是其中的王者。Elm语言是一种静态、纯函数式编程的语言。与其它函数式语言不同,elm是专门用于前端,与平时的前端网页开发三剑客:HTML、CSS、javascript同时上阵不同,elm能抛弃其它javascript库,单纯用elm语言来构建前端UI,实现其中的逻辑功能,而且更妙的是,如果你掌握elm语言和函数式编程的精髓后,能用比javascript少50%左右的代码,构建出比react、VUE、等框架更快的模块,而且还不易出错。

2.5. 学会elm语言的优势

运用elm语言来写UI,能培养你的函数式编程思维,当开发者们用惯了命令式、面向对象式编程思维后,函数式编程能让你的编程技术更上一层楼。对于初学者,函数式编程是打开了编程世界的一扇大门,门后是想象不到的风景,其中蕴涵人类智慧会令你赞叹不己。而elm,就是这扇大门,这串钥匙。下面,让我们尝试探索一下elm世界的精妙之处。

3. Elm里的lambda函数指南

3.1. lambdas函数定义

大部分编程语言中都会有lambda函数,它是匿名函数的代名词。建立函数时通常需要有个定语,如“function”或“def”等,例如要在javascript中定义函数sum,一般如下:

Function sum(x) {
   ...功能定义    
};

lambda匿名函数可以把function、def这类定语去掉,直接定义函数。在elm语言中,lambda匿名函数以“\”代替。
Elm中,匿名函数的基本语法形式是:”\”+参数+“->”+功能主体。“\”号是匿名函数的定义,匿名函数后可以加多个参数,“->”提示后面是函数功能主体定义。

3.2. Elm中lambda匿名函数实现以下功能

3.2.1 模式匹配

例如,实现统计列表中大于10的数字数量,代码以下:

Num:int  
Num sumLarge = List.length <| List.filter(/xs>10) <| List.range 1 100

两行代码便可实现,其中第一行 Num int 提示统计数量是一个int类型定义,List.range 1 100 是生成1至100的数字列表(elm中,函数参数间以空格隔开),“<|”是级别最低的右关联符号,意即生成列表后把列表结果作为输入向右侧函数提交。List.filter是系统默认的梳理函数,其参数是一个lambda匿名函数,意即按照这个函数的功能对列表进行梳理。这个lambda匿名函数(/xs>10)的功能就很容易理解,把大于10的数字选出来。括号也可以取消,转化成 “<|”右关联函数 如<|xs>10。 当把大于10的数字filter选出来后结果也是一个列表,把列表作为输入右关联到函数List.length,就得出输出结果,梳理出的列表个数,这是个int类型的数字,与第一行定义num:int一致。
注意的是,lambda匿名函数虽然给了开发者便利,但不是什么情况下都要用,有些情况下,不用lambda更好。如要把列表里的数字简单加3映射一下:

Sum: a -> List a -> List b
Sum newList = List.map(/xs = xs + 3) xs

在上例中,会感觉newList函数定义得有些累赘,出现了三个xs,究其原因,是因为map映射函数后定义的lambda匿名函数累赘,其实完全可以如下所写:

Sum: a -> List a -> List b 
Sum newList = List.map((+) 3) xs

原来 + 号也是一个lambda函数,简单定义 (+) 3 就把原先的 xs抽离,函数功能更加抽象,这就是纯函数的意义。

3.2.2 类型定义

Lambda函数还可以用作类型定义,例如,要实现一个参数交换的类型定义。显式如下:

   Arg: (a,b,c) -> b -> a -> c 
   Flip f x y = f y x

如果用lambda匿名函数的话,可以如下:

   Flip f = \x y =  f y x

“\”号是lambda匿名函数, Flip函数用匿名函数定义,既易读又比较酷。

3.2.3 折叠功能

elm函数式编程中,map(映射)、fliter(过滤)、foldl、foldr(折叠)是常用的几个内置函数,map和fliter方才已经运用过了,现在尝试用foldl(左折叠)和foldr(右折叠)对列表元素进行折叠实现有趣的功能。
首先是实现最基本的sum累加函数:

   Sum: List number -> number
   Sum xs = List.foldl(\x acc->acc+x) 0 xs

Foldl是左向折叠,对象是xs列表,0是折叠的起始值(也称累加器),(\x acc->acc+x)就是lambda实现累加的匿名函数,foldl每向左折叠一个元素时,就把lambda应用其它,象扑克牌一样,到最后就成为一叠(number)了。
接下来实现一个检查元素是否在列表里的member函数:

   Member: a->List a->Bool
   Member y ys = List.foldl(\x acc -> if x==y then True else acc) False ys

在上例里,最终输出是一个Bool布尔判断的结果(True or False),False作为 foldl的初始值,如果不存在元素,就False,foldl折叠的动作就是一个lambda匿名函数(\x acc -> if x==y then True else acc),意思是判断输入元素是否与列表映射元素相符,如果相符则初始值由False变为True,否则还是原封不动)。
好了,通过折叠函数和lambda匿名函数,我们顺利的制作了两个新函数:sum和member,纯净没有副作用,下来就可以利用这两个新函数,作为乐高积木的最小块,来尝试组合应用一下:

New1: List a ->Bool -> int
New1 result = sum <| member 1 [1,1,2,3,4]

得出结果是: 2

New2: list a ->Bool -> int
New2: result = sum <| member [1,2] [[1,2],[2,3],[3,4]]

得出结果是: 1

四、结语

函数式编程,是未来的趋势,elm语言是前端特有的函数式编程语言,而掌握函数式编程,lambda匿名函数是其中的精妙之一,和map(映射)、filter(过滤)、foldl(折叠)组合起来,变化无穷,编程的过程既奥妙又愉悦。本文只略作介绍,欢迎讨论。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值