lambda算子中的数

数学基础差加之受严重的功利主义思想的影响,我对数学一直是没有太大兴趣。不过最近一段时间在看《算法导论》和《SICP》,几周下来发现进度之慢,归结原因是大部分数学知识都被我遗弃了,然后看的时候不得不在案头放上离散数学、微积分、线性代数、统计学、运筹学等大学未弃之书作为速查手册,说能快起来那是在自我忽悠。
做程序不能不懂数学犹如绘画不能不懂素描,基本功扎实了才好发挥。但鉴于程序员与数学家还是有本质的不同,不但要保持思维跨度在1到pow(10,15)也就是15个数量级之间还要学习相应业务知识以及应对客户,有点爱好的还要研究下声乐,绘画。这种情况下大可不必去与数学较劲。所以开发人员在数学的学习上最好是贯彻‘广度优先’这一方针,将要应对的问题和与之对应的数学知识在头脑中建立一张dynamic lookup table即可,待到用的时候在去查阅相关资料。即便不知道具体公式,但若能在求最大公约数的时候立马想到欧老前辈,也就算基本合格了。但话说回来,像这种基础的还是记住的好,不然不好意思跟人家说I'm very professional!
废话一大堆,最近才看到SICP的第三章,前面有一些习题也没有来得及做,昨夜在回顾习题的时候碰上了exercise2.6,关于lambda算子中数的表示,这套形式系统中,酷就酷在可以全由lambda演算系统中的合法符号来表示数,通俗的说就是用没有一个数字的表达式来表达数字
SICP中的一个例子
看看数学中0(zero )是如何用lambda表达式来定义的:
[code](define zero (lambda(f)(lambda(z) z)))[/code]
对于Alonzo Church来说,看上面的代码好比看英语,但对于在数学之海的岸口张望的人来说,不太直观
那再看看one two three
[code](define one (lambda(f)(lambda(z)(f z))))
(define two (lambda(f)(lambda(z)(f (f z)))))
(define three (lambda(f)(lambda(z)(f (f (f z))))))[/code]
似曾相识?那看下面

int zero=0;
int one=zero+1;
int two=one+1;
int three=two+1;

通过这样一对比,很容易就可以得出一个Chruch数与自然数的转化式
[code]
;做个过度
(define f (lambda(x)(+ x 1)))
(display (f (f 0)));output 2
;转换式
(define (cn-to-n cn)
((cn (lambda(x)(+ x 1)))0))
[/code]
数的表达有了,接下来就是运算了,习题的要求是做了加法运算
[code]
(define (add x y)(+ x y))
[/code]
一个很典型的加法,但不适用于Chruch数
要支持Chruch数的运算,那至少要在运算式中将其表达出来吧。
从前面的定义来看,lambda(f)(lambda(z)..)是跑不了的,由于Chruch数本身即是嵌套的函数表达式,那只要我能将最后的结果组合成(f (f (f ..(f z)..)))这番模样就算大功告成了
这个时候再琢磨一下前面的Chruch数,然后换个写法
[code]
(define one (lambda(f)(lambda(z)(f ((zero f)z)))))
(define two (lambda(f)(lambda(z)(f ((one f)z)))))
(define three (lambda(f)(lambda(z)(f ((two f)z)))))
[/code]
在Chruch表达式里面(one f)就是one,(two f)就是two,从而推出(x f)=x,再考虑到函数的叠加,试着定义'5',
[code]
(define five (lambda(f)(lambda(z)((three f)((two f)z)))))
[/code]
然后从特殊到一般,得出加法运算式
[code]
(define (add x y)
(lambda(f)(lambda(z)((x f)((y f) z)))))
[/code]
习题是完成了,但凡是涉及到数学的问题都有让人去发散思维的魔力,加法都出来了,何不看看乘法,前面定义了五,现在试着定义下六
[code]
(define six (lambda(f)(lambda(z)((three (two f))z))))
;依葫芦画瓢得出乘法定义
(define (mul x y)
(lambda(f)(lambda(z)((x (y f))z))))
[/code]

解题过程中为求天时地利,坚持坐北朝南,并发扬一贯的连蒙带猜,猜中带推的作风,虽终得正解,但仍不能掩饰数学知识之贫乏,恶补在所难免。
<think>嗯,用户之前问过如何在Flink中过滤JSON字段值小于20250402的据,现在他们又想知道如何将filter算子写成lambda格式。这说明用户可能已经掌握了基本的过滤方法,但希望代码更简洁,或者他们正在学习如何用Java 8的lambda表达式来简化Flink作业。 首先,我需要回顾一下之前的回答。之前的例子是使用匿名内部类实现FilterFunction接口,用户现在想要用lambda表达式替换。Flink支持lambda表达式,但需要注意类型信息的处理,否则可能会因为类型擦除导致Flink无法推断类型,从而需要显式指定返回类型。 接下来,我需要考虑用户可能的背景。他们可能是刚开始接触Flink,或者对Java 8的新特性不太熟悉。所以,在回答中需要解释lambda的基本用法,同时提醒类型信息的问题,并提供解决方案,比如使用returns()方法或显式指定类型。 另外,用户可能在尝试优化代码,使其更简洁易读。Lambda表达式确实能让代码更简洁,但也要注意可能带来的类型推断问题。需要确保用户了解这一点,避免在实际应用中出现错误。 可能的疑问点包括:为什么需要returns()方法?什么时候可以省略?是否所有情况下都能用lambda?需要给出明确的示例,说明正确和错误的用法,帮助用户理解。 同时,用户可能希望看到Scala的示例,但这次问题明确提到lambda格式,而Scala本身支持lambda,可能用户主要关注Java。不过之前的回复中已经包含了Scala示例,可能不需要重复,但可以简要提及。 最后,确保回答结构清晰,步骤明确,突出修改后的lambda写法,并强调注意事项,帮助用户正确应用。</think>在 Flink 中使用 **Lambda 表达式**实现 `filter` 算子可以大幅简化代码,以下是具体实现方式及注意事项: --- ### 基础版 Lambda 写法(Java) ```java DataStream<JsonNode> filteredStream = stream.filter( jsonNode -> { JsonNode targetField = jsonNode.get("targetField"); return targetField != null && targetField.isNumber() && targetField.asLong() >= 20250402L; } ); ``` --- ### 关键注意事项 1. **类型信息保留问题** Flink 的 Java API 可能因类型擦除无法自动推断 Lambda 表达式类型,需通过以下两种方式解决: - **显式指定返回类型**(推荐): ```java .returns(Types.GENERIC(JsonNode.class)) ``` - **完整写法**: ```java .filter((FilterFunction<JsonNode>) jsonNode -> {...}) ``` 2. **防御性编程** Lambda 中仍需处理字段缺失、类型错误等异常: ```java jsonNode -> { if (!jsonNode.has("targetField")) return false; // 检查字段存在性 JsonNode field = jsonNode.get("targetField"); return field.isNumber() && field.asLong() >= 20250402L; } ``` --- ### 完整可运行示例(含类型声明) ```java DataStream<JsonNode> filteredStream = stream .filter(jsonNode -> { JsonNode field = jsonNode.get("targetField"); return field != null && field.isNumber() && field.asLong() >= 20250402L; }) .returns(TypeInformation.of(JsonNode.class)); // 显式声明类型 ``` --- ### Scala 版 Lambda 写法(天然支持类型推断) ```scala val filtered = stream .filter { jsonNode => val field = jsonNode.get("targetField") field != null && field.isNumber && field.asLong >= 20250402L } ``` --- ### 常见错误场景 1. **未处理空值导致 NPE** ```java // 错误写法(直接 get 未判空) .filter(jsonNode -> jsonNode.get("targetField").asLong() >= 20250402L) ``` 2. **未校验字段类型** ```java // 错误写法(字段可能是字符串) .filter(jsonNode -> jsonNode.get("targetField").asLong() >= 20250402L) ``` 3. **未指定返回值类型** ```java // 可能报错:Missing type information .filter(jsonNode -> true) // 修复:添加 .returns(...) ``` --- ### 性能优化建议 1. **避免复杂计算** Lambda 中避免嵌套 JSON 解析等耗时操作,建议提前通过 `map` 算子预处理据 2. **重用对象** 高频调用场景中,可在 Lambda 外创建 `ObjectMapper` 等复用对象: ```java ObjectMapper mapper = new ObjectMapper(); // 需确保线程安全 .filter(jsonStr -> { JsonNode node = mapper.readTree(jsonStr); // ...处理逻辑 }) ``` --- 通过 Lambda 表达式可使 Flink 代码更简洁,但需特别注意 **类型声明** 和 **异常处理**,建
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值