lambda算子简介1.a

接着前两天的转载继续写。上次说到lambda算子的函数只接受一个参数。那怎么处理多个参数呢?如果只有一个参数,那岂不是连加法都不能实现?这当然难不倒像丘齐这样的天才。于是, lo and behold,  一个我们至今在编程里常用的技巧粉墨登场:

Currying

据说Currying翻译为局部套用函数,也不知真假。喜欢吃印度美食的老大们不要激动。Currying和咖喱没有半点关系。这个技巧以逻辑学家Haskell Curry的姓命名。Haskell Curry也是名动一时的人物。他和Moses Schönfinkel 共创了组合逻辑(combinatory logic),并把这们学科发扬光大。当初Curry搞出组合逻辑,主要是为了在数理逻辑里避免使用变量。后来搞函数编程的人们发现,组合逻辑是一类函数编程语言的理论基础。一些函数语言里常见的特性,比如说高阶函数合lazy evaluation, 就是用组合逻辑里的combinator实现的。当初Alanzo Church对这个理论也相当熟悉。难说lambda理论不是受了组合逻辑的影响。大牛Philip Wadler为了纪念Curry, 把他的函数语言叫做Haskell。Haskell也是一门巨酷的函数语言,兼顾数学的优美和软件开发的实用性。连LInspire的开发组都决定用Haskell作为系统开发的语言(但我很奇怪他们为什么放弃使用另一门酷酷的函数语言Ocaml)。说远了。

解决参数限制的关键在于认识到函数也是数据(用更严格的说法,是值)。既然是数据,就可以传来传去。如果有两个参数,我们可以写一个接受第一个参数的函数,而这个函数返回的是接受第二个参数的函数。“就那么简单!我们在JavaScript里不是常用这个功能?” 嘻嘻,我们在JavaScript里的确常用这个功能。JavaScript其实是带C句法的函数语言,支持高阶函数,自然支持Currying。JavaScript的功能其实颇为强大,不然Douglas Crockford不会说JavaScript是最被人误解的语言

举例来说,假设我们要写一个函数,把x和y相加。最自然的写法是lambda x y . plus x y.  既然我们只能一次接受一个参数,我们可以先写一个接受 x 的函数。这个函数返回一个接受 y 的函数。这个被返回的函数把 x 和 y 相加:lambda x.(lambda y. plus x y)。简单吧?数学奇妙之处就在于我们用极为简单的砖块搭建出恢弘的宫殿。事实上,数学家们总是极力追求理论基础的简洁。他们不知疲倦地挥舞着奥卡姆剃刀,直到把自己的理论切割成东家之子:增之一分则太长,减之一分则太短。有了Currying这个工具,我们可以放心使用多参数的标记了。反正多参数的lambda不过是单参数lambda的方便用法而已,没有任何实质上的改变。

(待续。累死了。什么时候才能写到让人拍案叫绝的Y Combinator啊? )

### Spark算子概述 Spark 是一种分布式计算框架,其核心概念之一是 **RDD(弹性分布式数据集)**。通过一系列的转换操作(Transformation),可以构建复杂的并行计算流程。最终可以通过行动操作(Action)触发实际的任务执行。 以下是常见的 Spark 算子分类及其使用方法: --- #### 转换算子(Transformation) ##### `map` 将输入中的每一个元素应用指定函数,并返回一个新的 RDD。 ```python rdd = sc.parallelize([1, 2, 3]) mapped_rdd = rdd.map(lambda x: x * 2) print(mapped_rdd.collect()) # 输出: [2, 4, 6] ``` ##### `filter` 过滤掉不满足条件的数据项。 ```python filtered_rdd = rdd.filter(lambda x: x % 2 == 0) print(filtered_rdd.collect()) # 输出: [2] ``` ##### `flatMap` 类似于 map,但是会将结果扁平化处理。 ```python words = ["hello world", "this is a test"] flat_mapped_rdd = sc.parallelize(words).flatMap(lambda line: line.split()) print(flat_mapped_rdd.collect()) # 输出: ['hello', 'world', 'this', 'is', 'a', 'test'] ``` ##### `repartition` 重新分配分区数量,可能引发 Shuffle 操作。 ```python rep_rdd = rdd.repartition(4) # 将分区数调整为4 print(rep_rdd.getNumPartitions()) # 输出: 4 ``` 此过程涉及 Shuffle 的实现细节可参见[^3]。 --- #### 行动算子(Action) ##### `reduce` 对 RDD 中的所有元素进行两两聚合运算。 ```python sum_result = rdd.reduce(lambda x, y: x + y) print(sum_result) # 输出: 7 ``` ##### `collect` 将整个 RDD 收集到驱动程序中作为列表返回。 ```python collected_data = rdd.collect() print(collected_data) # 输出: [1, 2, 3] ``` ##### `count` 统计 RDD 中的元素总数。 ```python cnt = rdd.count() print(cnt) # 输出: 3 ``` ##### `take` 获取前 N 个元素。 ```python taken_elements = rdd.take(2) print(taken_elements) # 输出: [1, 2] ``` --- #### Join 类型算子 ##### `join` 和 `leftOuterJoin` 用于两个键值对类型的 RDD 进行连接操作。 ```python rdd1 = sc.parallelize([(1, "Apple"), (2, "Banana")]) rdd2 = sc.parallelize([(2, "Yellow"), (3, "Red")]) joined_rdd = rdd1.join(rdd2) print(joined_rdd.collect()) # 输出 [(2, ('Banana', 'Yellow'))] outer_joined_rdd = rdd1.leftOuterJoin(rdd2) print(outer_joined_rdd.collect()) # 结果示例可见于[^4] ``` --- #### 自定义算子 在 Java 或 Scala 中自定义算子时,通常需要继承特定接口并重写方法。例如,在 Java 中实现 Filter 功能: ```java JavaRDD<String> filteredRdd = rdd.filter(new Function<String, Boolean>() { public Boolean call(String row) throws Exception { return !row.isEmpty(); // 只保留非空字符串 } }); ``` 上述逻辑也可扩展至其他复杂场景下,具体实现方式详见[^2]。 --- ### 总结 以上展示了部分常用的 Spark 算子以及它们的应用实例。每种算子都有独特的用途和性能特点,合理选择能够显著提升作业效率。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值