为 Lambda 语法增加序运算能力

简介: 本文探讨了集合运算中与次序相关的Lambda语法。SQL基于无序集合概念,不关注遍历时的次序,但计算机执行时总有顺序。SPL引入`#`表示遍历次序号,简化了如取前半成员、偶数位置成员等操作。此外,SPL支持相邻成员引用(如`~[-1]`表示前一个成员),方便计算增长率、移动平均值等。相比SQL需用子查询或窗口函数,SPL的有序Lambda语法更简洁高效,增强了集合运算的描述能力。

我们继续讨论集合运算中的 Lamba 语法,引入和次序相关的运算能力。

SQL 延用了数学上的无序集合概念,遍历集合时也不关注次序。但计算机只能一步步地执行,循环时总会有个次序,充分利用这个次序就可以方便地表达更丰富的计算需求。
比如我们想从一个集合取出半数成员构成新集合。这看起来象是过滤运算,但过滤条件和集合成员本身并没有关系,而是由循环时的次序号决定的。

SPL 中只用 ~ 写法还无法方便地描述出这种运算,这时候还需有个符号(标识符)来表示循环的次序号。这是 Lambda 语法的第四条。

事实上,大部分高级语言在写循环语句时都会有个循环变量来表示次序号,就起到了这个作用。但在 Lambda 语法中并没有提供这个机制,碰到这种运算就只能再写循环或人为造个序号序列才能完成,就显得很繁琐。SQL 也没有表示遍历次序号的方案,只能先用子查询人为制造一个序号出来再针对这个序号进行过滤。

SPL 用 #来表示遍历的次序号,那么这个运算就很容易写了:

A.select(#<=A.len()/2)        取前一半成员
A.select(#%2==0)        取偶数位置的成员
AI 代码解读

对应地,在过滤运算中一般总是返回满足条件的成员,但有时候我们并不关心具体成员而只关心成员的次序号,SPL 中还设计返回次序号的过滤函数:

A.pselect( ~>5 )        返回大于5的成员的次序号
AI 代码解读

类似地,还可能有:

A.pmax()            返回最大值的次序号

...
AI 代码解读

关于这些位置相关的运算,我们以后还会专门讲。

考虑到集合上遍历的次序时,我们还可以进一步丰富计算的描述能力。
比如有 12 个月的销售额数据已经按次序准备好,要计算哪些月份的增长率超过了 5%。
SQL 写这种跨行计算比较麻烦,需要用 JOIN 或窗口函数把上月数据和本月数据对齐,然后再来计算增长率,这不可避免地用到子查询。
如果提供了相邻成员的引用语法,就可以很容易描述这个计算了。
SPL 中用 [i] 表示和当前成员距离为 i 的成员,再结合前述的 #写法,上面的计算就可以写成:

A.(if(~/~[-1]>1.05,#,0)).select(~>0)
AI 代码解读

~[-1] 表示前一个成员,也就是上月销售额。找出把增长率超过 5% 的月份(也就是 #),其它月份清 0,最后选出这些非 0 的月份。
如果用上述的返回次序号的过滤函数,还可以写成更简单的形式:

A.pselect(~/~[-1]>1.05)
AI 代码解读

除了相邻成员外,还可能有相邻集合的引用,比如还是上面的集合,我们希望计算前后各一个月的销售额移动平均值。
SPL 把 [i] 表达式扩展成 [a,b] 写法来表示相邻成员构成的集合,这个运算就很容易描述了:

A.(~[-1,1].avg())
相邻集合还可能有更复杂的情况,比如计算到当月的累积销售额。
SPL 允许 [a,b] 写法中 a 缺省表示从第一个成员开始(对等地,b 缺省可以理解为最后一个成员),这个运算可以写成

A.(~[,0].sum())
AI 代码解读

同样的,面向结构化数据计算也还可以直接使用字段名,如果例子中的集合是由“月份”和“销售额”的两个字段构成的表,则上述的运算可以分别写成:

A.select(amount/amount[-1]>1.05)            这里结果集中已有月份字段,不再需要用#了
A.derive(amount[-1,1].avg:move_average)            增加一个字段表示移动平均
A.derive(amount[,0].sum():cum_amount)
AI 代码解读

考虑到有序性时,Lambda 语法的规则就比常规集合运算要复杂一些,而这些有序运算是经常发生的,如果 Lambda 语法不支持,会导致这些计算难以描述,程序员就要再退回到编写多行循环语句的状态,或者人为造出序号,繁琐且影响可读性。

SQL 没有提供有序的 Lambda 语法,经常需要使用子查询和窗口函数来生成序号,某些复杂些的有序遍历运算甚至写不出来,也要用存储过程手段转换成多行循环语句才可以。从这个意义讲,SQL 虽然有集合化特性,但集合化不够彻底。

Python 提供了局部的序号能力,相邻引用也比较麻烦。SPL 可能是唯一提供较完整有序 Lambda 语法的语言。

SPL已开源免费,欢迎前往乾学院了解更多!

目录
打赏
0
3
3
0
62
分享
相关文章
从集合运算设计 Lambda 语法
集合化程序语言通过简洁的语句实现复杂集合运算,Lambda语法的设计至关重要。首先,直接使用集合成员进行简单运算如求和,无需Lambda。接着,引入Lambda表达式处理更复杂的运算,如计算平方和。SPL使用“~”表示当前成员,简化表达,而SQL则依赖字段引用机制,牺牲了对泛型成员的支持。在嵌套引用时,采用就近原则避免歧义。SPL拓展了SQL的数据组织,支持任意成员的集合,使Lambda语法更加灵活。
【多数组合 数学 字符串】2514. 统计同位异构字符串数目
【多数组合 数学 字符串】2514. 统计同位异构字符串数目
这个无敌设计,可以解析并运算任意数学表达式
下面用解释器模式来实现一个数学表达式计算器,包含加、减、乘、除运算。 首先定义抽象表达式角色IArithmeticInterpreter接口。
165 0
组合排序回溯编程题集合(leetcode)
组合排序回溯编程题集合(leetcode)
【C】操作符归纳+表达式运算原理
【C】操作符归纳+表达式运算原理
244 0
【C】操作符归纳+表达式运算原理
排序数组中只出现一次的数字(中等难度,三种方法)
排序数组中只出现一次的数字(中等难度,三种方法)
121 0
排序数组中只出现一次的数字(中等难度,三种方法)

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等