lua 字符串分割_Lua函数式编程(中)

9ad854ed02b545fe80b7d43360303cc5.png

书接前文,我们继续慢慢的了解 所谓的函数式编程思想。考查下面的例子

判断给定的数是否是偶数

在Lua里面这似乎是个幼儿园问题

local isEven = function(v) return v % 2 == 0 end

但我们如何用函数式的思维去解决问题?是的,假设我们有了以下函数

R.mod -- 求余数
R.equals -- 判断是否相等

我们为何要新造一个函数轮子呢?有什么办法可以重复利用已有的函数算法呢?

函数组合

最强大的函数式编程核武器出现了。这就是函数组合,但是理解这个概念一点都不困难,就像是数学中的函数一样

y = f(x) , z = g(y) = g(f(x))
h = ComposeMagic(f, g) //考虑将f函数和g函数进行组合
z = h(x) //这样可以直接得到最终结果

函数组合就像一个管道一样,假想一组数据要经过f g h三个函数的加工,变成最终我们需要的数据

values -> f() -> g() -> h() -> results

那么中间的函数实际上可以经由compose组合,变成一个函数算法

values -> composed() -> results

这个就是函数组合的思维核心,经由函数自身的逻辑操作,而非针对值的操作,因此可以充分的利用诸多已经实现好的小函数、小算法、小轮子,自由组合而成为我们需求的算法

是时候用函数式思想实现之前的那个算法了

local isEven = R.compose(R.equals(0), R.mod(2))

compose方案会组合后面的函数,使其从后往前依次接收数据、返回处理结果。

number -> R.mod(2) 求得余数 -> 返回结果 -> R.equals(0) 判断是否与0相等 -> 返回结果

不过这对于这个算法来说确实大材小用了,但是这其中的思想还是值得我们研习的。来看个复杂点的例子

实现一个算法,将IP4的地址转换为一个Int32的数

我们先看传统的实现(其中仍然借助了R.split方法,我们就当成一个传统方法来使用)

local function convertIp2Int(ip)local ip_numbers = R.split(".", ip)local result = 0local offset = 1for i, ipn in ipairs(ip_numbers) doresult = result + tonumber(ipn) * offsetoffset = offset * 256endreturn result
end

这个实现的确不怎么好看,而且还要注意他的约定是 big-endian,如果修改成little-endian,我们得钻到函数细节里面去想办法。

让我们体会下函数组合的强大吧。先看看最终实现

local split = R.split(".")
local parse = R.map(tonumber)
local offset = function(f, s) return f * 256 + s end
local convertIp2Int = R.compose(R.reduce(offset, 0), parse, R.reverse, split)

如果想实现little-endian版本的,只需要移除组合函数中的R.reverse方法即可,基于原题目,我们可以简化一下

local offset = function(f, s) return f * 256 + s end
local convertIp2Int = R.compose(R.reduce(offset, 0), R.map(tonumber), R.split('.'))

数据流向如下

"192.168.1.1"             -> R.split('.') 分割字符串 ->
{"192","168","1","1"}     -> R.map(tonumber) 对列表中的每个元素进行tonumber转换 ->
{192, 168, 1, 1}          -> R.reduce(offset, 0) 每两个元素执行一次offset操作,将列表合并为一个Int32数字
-> 3232235777

而且欣慰的是,过程中的中间函数,都可以作为其他算法的子函数继续组合使用,函数组合充分的解放了对造轮子的冲动,这就是函数编程思想的核心魅力。

副作用(Side Effect)和不可变(Immutable)

什么是函数?经典的Pascal语言有两个关键字,很好的区分了函数和过程

function --> 给定输入,经过函数算法,返回给定的输出;相同的输入永远返回相同的输出,没有副作用。
procedure --> 给定输入,经过过程算法,改变某些状态,有副作用。

在函数式编程思维中,function必须的纯净的,无副作用的,其特性为

  1. 不依赖全局变量
  2. 不修改函数参数
  3. 不修改任何状态(db、io、网络、标准输出、对象等等)
  4. 只要输入一样,输出必定一样

这些特性使得函数具有了非常诱人的特性

  1. 可测试性(只需要给定参数就能判定这个函数是否工作正常,不需要Mock任何对象系统)
  2. 可缓存性(只要参数一样,就返回一样的内容,很容易缓存算法结果)
  3. 可并发性(没有副作用,没任何数据竞争,多线程跑跑算法,安全的很)
  4. 自解释性(描述参数和返回值即可,不用考虑任何外部系统知识)
  5. 引用透明(可以在算法中将函数调用替换为他的结果)

但是很遗憾,本文无法做深入展开(您可以参考任何一篇介绍函数式编程思想的文章)

纯净的函数使得传入的参数被安全的保护起来,你不希望你的列表传入一个算法,然后被这个算法破坏的乱七八糟吧。

local list = {1,2,3}
R.append(4, list) --> list 仍然是1,2,3 这种保障去掉了相当多对引用做修改而导致的Bug

下一篇我们会就性能、函数签名做一番探讨,有兴趣的可以继续关注。

谢谢阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/397879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mybatis 乐观锁和逻辑删除

本篇介绍easymybatis如配置乐观锁和逻辑删除。 乐观锁 easymybatis提供的乐观锁使用方式跟JPA一样,使用Version注解来实现。即:数据库增加一个int或long类型字段version,然后实体类version字段上加上Version注解即可。实现原理是根据mysql的行…

WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)...

WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序) 原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)基于HTTP-GET的元数据发布方式与基于WS-MEX原理类似…

网络配置 rpm yum

vm0 vm1 vm2安装vmware后:安装vmware tools工具1 物理机和虚拟机复制 粘贴 unity模式 共享文件夹等功能2设置共享文件夹网络相关命令# lspci |grep eth 查看驱动卡信息#mii-tool eth1eth1:negoriated 100baseTX-FD,link ok ,如果fail表示网线没连接好ifconfig 查看…

)标识符不能是c语言的关键字,标识符不能是C的关键字

满意答案tftgcl882014.08.07采纳率:58% 等级:9已帮助:3967人所谓关键字就是已被Turbo C2.0本身使用, 不能作其它用途使用的字。例如关键字不能用作变量名、函数名等。Turbo C2.0有以下关键字:Turbo C2.0扩展的共11个asm …

不同类的方法 事务问题_【高中地理】描述类问题的答题方法

一、描述地理位置的特征及意义位置:半球位置、纬度位置、海陆位置、相对位置(邻省或邻国、地形区、地势阶梯交界处、气候区、图例中的特殊地理事物)、板块位置、交通位置等。意义:①所处位置(是否是重要分界线&#xf…

JqGrid 列时间格式化

{name:createTime,index:createTime,label:"创建时间", editable:false,formatter:"date",formatoptions: {srcformat:Y-m-d H:i:s,newformat:Y-m-d H:i:s}}, 转载于:https://www.cnblogs.com/youmingkuang/p/9095497.html

Debian 系统安装 Nagios 服务器监控端

安装apt-get updateapt-get install nagios* perlapt-get install --no-install-recommends pnp4nagiosapt-get install apache2 apache2-utils php5 php-pear 修改npcd设置# vim /etc/default/npcdRun"yes"# service npcd start 添加process_perfdata.pl执行权限ch…

spark-stream 访问 Redis

最近在spark-stream上写了一些流计算处理程序,程序架构如下 程序运行在Spark-stream上,我的目标是kafka、Redis的参数都支持在启动时指定。 在写代码时参考了这篇文章 https://www.iteblog.com/archi...,该文讲的比较清楚,但是有两…

c语言打印空心等腰梯形乐学,C语言做激光发射

/*C语言做激光发射器游戏,按上下左右箭头键移动发射器,按空格键发射激光,按Esc键结束游戏*/#include #include #include void main(){int i,j;//定义循环变量int x15,y10;//定义横坐标与纵坐标初始值char in;int fire0;int kill0;int nx10;//…

东软睿云用户认证_【硬件资讯】尘埃落定!11代酷睿规格曝光!i7、i9难分差距,退回8核16线程!...

新闻①:Intel第11代酷睿处理器规格曝光,旗舰i9-11900K与i7-11700K同为8核16线程Intel的代号为Rocket Lake-S的第11代酷睿台式机CPU阵容将于明年推出,其中四个型号的规格现已曝光。拥有8个Cypress Cove核心、5.3GHz、PL2功耗限制250W的酷睿i9-…

环上的游戏

环上的游戏(cycle)有一个取数的游戏。初始时,给出一个环,环上的每条边上都有一个非负整数。这些整数中至少有一个0。然后,将一枚硬币放在环上的一个节点上。两个玩家就是以这个放硬币的节点为起点开始这个游戏&#xf…

python基础课程_2学习笔记3:图形用户界面

图形用户界面 丰富的平台 写作Python GUI程序前,须要决定使用哪个GUI平台。 简单来说,平台是图形组件的一个特定集合。能够通过叫做GUI工具包的给定Python模块进行訪问。工具包 描写叙述 Tkinter 使用Tk平台。非常easy得到。半标准。 wxpython 基于…

vim编辑器之按键说明

viim编辑器文本:纯文本,ASCII test;文本编辑种类:行编辑器:sed全屏编辑器:nano,vi其他编辑器:gedit 一个简单的图形编辑器gvim 一个vim编辑器的图形版本 一.打开文件几种方法命令格式:vim [options] [files]常用选项:#:打开文件后,直接让光标处于第#行的行首/PATTERN:打开…

idea ssm打war包_IDEA下从零开始搭建SpringBoot工程

SpringBoot的具体介绍可以参看其他网上介绍,这里就不多说了,就这几天的学习,个人理解,简而言之:如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友…

c语言一维数组转化为二维矩阵,js将一维数组转化为二维数组

遇到的问题:后端返回的是一组一维数组,但是需要展示的格式是二维数组,常见的场景举例:后台返回10个长度的数组,需要分成3个一组展示在banner上。例:[1,2,3,4,5,6,7,8,9,10] > [[1,2,3], [4,5,6], [7,8…

nano使用说明

Main nano help text The nano editor is designed to emulate 仿真、模拟 the functionality and ease-of-use of the UW Pico text editor. There are four main sections of the editor. The top line shows the program version, the current filename being edited, and w…

dataframe 众数的方法_学习数据分析数据方法论 [描述性统计分析]

数理统计:数理统计是以概率论为基础,研究社会和自然界中大量随机现象数量变化基本规律的一种方法。分为:描述统计(描述统计的任务是搜集资料,进行整理、分组,编制次数分配表,绘制次数分配曲线,计…

c语言高级语言期中测试答案,上海理工大学C语言2011期中试题和答案

C语言2010/2011学年 第二学期 期中测试高级语言程序设计(C)试卷 A □BA1. 输入一行字符&#xff0c;统计其中的英文字母个数。#include void main(){ char ch;int n0;printf(“Input a string:\n”);while(1){ chgetchar();if (ch \n ) break;if (ch> a && ch< z…

前端基础进阶(十):面向对象实战之封装拖拽对象

https://segmentfault.com/a/1190000012646488 https://yangbo5207.github.io/wutongluo/ 说明&#xff1a;此处只是记录阅读前端基础进阶的理解和总结&#xff0c;如有需要请阅读上面的链接 1.如何让元素动起来 要让元素动起来就要修改元素的top、left 、translate 属性。因为…

iOS - LocalCache 本地数据缓存

1、自定义方式本地数据缓存 1.1 自定义缓存 1 沙盒路径下的 Library/Caches 用来存放缓存文件&#xff0c;保存从网络下载的请求数据&#xff0c;后续仍然需要继续使用的文件&#xff0c;例如网络下载的离线数据&#xff0c;图片&#xff0c;视频文件等。该目录中的文件系统不会…