Lazy Evaluation by Difference Language
# Lazy Evaluation by Difference Language
# What is lazy evaluation(LE)
惰性求值特别适用于函数式编程语言中,表达式不在声明的时候求值而是在该值取用的时候进行计算。 其中包含两部分隐喻:
- 延迟计算(call-on-need),
- 最小化求值(short-circuit evaluation),针对non-strict模式的一种逻辑运算符求值策略优化[1] 延迟求值特别适合函数式编程语言,而函数式编程语言又是基于lambda演算为基础的[2]。
# non-strict and strict evaluation
Note: 这里所说的的严格与非严格模式,与JS语言use strict
不是一个概念[3]
非严格模式:
static int DoOneThing() { Console.WriteLine("Do One Thing Run"); return 1; }
static void Main(string[] args)
{
bool b = true || DoOneThing() > 0;
}
2
3
4
5
6
结果:并没有打印出"Do One Thing Run",因为true||(逻辑或)上任何逻辑都会为true,所以不需要检查||后面的逻辑。
严格模式
static int DoOneThing() { Console.WriteLine("Do One Thing Run"); return 1; }
static void DoSomeThing(bool a, int b)
{
Console.WriteLine("Do Some Thing Run");
if (a)
{
Console.WriteLine("The b is run {0}", b);
}
Console.WriteLine("Do Some Thing Finish");
}
static void Main(string[] args)
{
DoSomeThing(false, DoOneThing());
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
结果:
- Do One Thing Run
- Do Some Thing Run
- Do Some Thing Finish 因为在这正是这行了严格模式的结果,入参如果是个执行函数,当然就会被立刻执行并将执行结果赋值给b,如果操作很耗时,就会产生不必要的开销。 如何优化请参考Func<>和Lazy<>[4]
# LE in language
# Functional language as Haskell
非限定性语义(non-strict)和强静态类型的函数式语言[5]。 Haskell是现有的一门开放的、已发布标准的,且有多种实现的语言。[11]支持惰性求值、模式匹配、列表解析、类型类和类型多态。它是一门纯函数编程语言,这意味着大体上,Haskell中的函数没有副作用。Haskell用特定的类型来表达副作用,该类型与函数类型相互独立。纯函数可以操作并返回可执行的副作用的类型,但不能够执行它们,只有用于表达副作用的类型才能执行这些副作用,Haskell以此表达其它语言中的非纯函数。
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Following the release of Miranda by Research Software Ltd. in 1985, interest in lazy functional languages grew. By 1987, more than a dozen non-strict, purely functional programming languages existed. Miranda was the most widely used, but it was proprietary software. At the conference on Functional Programming Languages and Computer Architecture (FPCA '87) in Portland, Oregon, there was a strong consensus that a committee be formed to define an open standard for such languages. The committee's purpose was to consolidate existing functional languages into a common one to serve as a basis for future research in functional-language design.
# How C# Linq do with it.
2007年由DoNet Framework 3.5引入,实现了惰性求值
var results = from c in SomeCollection
where c.SomeProperty < 10
select new {c.SomeProperty, c.OtherProperty};
// 只有在foreach循环的时候才真正计算results的值
foreach (var result in results)
{
Console.WriteLine(result);
}
2
3
4
5
6
7
8
9
# How does JS do
JavaScript 并非从语言层面就支持这样的特性,而是要通过一些技术来模拟、实现。 例如,Lazy.js[6], 大数据量的情况下性能显著提升并优于lodash, underscore[7], 甚至在某些情况下性能优化是惊人的[8]。
Lazy.generate(Math.random)
.map(function(e) { return Math.floor(e * 1000) + 1; })
.uniq()
.take(300)
.each(function(e) { console.log(e); });
2
3
4
5
# How does Java do
Java8 Stream Lazy Evaluation
public static void main(final String[] args) {
List<String> names = Arrays.asList("Brad", "Kate", "Kim", "Jack", "Joe", "Mike", "Susan", "George", "Robert", "Julia", "Parker", "Benson");
final String firstNameWith3Letters = names.stream()
.filter(name -> length(name) == 3)
.map(name -> toUpper(name))
.findFirst()
.get();
System.out.println(firstNameWith3Letters);
}
2
3
4
5
6
7
8
9
10
11
# Reference
最小化求值:https://www.wikiwand.com/zh/%E7%9F%AD%E8%B7%AF%E6%B1%82%E5%80%BC ↩︎
λ演算:https://www.wikiwand.com/zh/%CE%9B%E6%BC%94%E7%AE%97 ↩︎
https://blog.csdn.net/weixin_33860722/article/details/90621634 ↩︎
严格模式和非严格模式:https://www.zhangshengrong.com/p/7B1L3V7Xwp/ ↩︎
Haskell:https://www.wikiwand.com/zh/Haskell ↩︎
lazyJS:http://danieltao.com/lazy.js/ ↩︎
lazyJSPerformanceOnline:http://danieltao.com/lazy.js/ ↩︎
BenchmarkData:https://github.com/Cuiyansong/my-react-experiment/blob/master/src/Javascript-Performance/lazy-js-and-lodash-performance.perf.js ↩︎
FusingOperationSOF:https://stackoverflow.com/questions/35069055/java-stream-operation-fusion-and-stateful-intermediate-operations ↩︎
JavaFusingOperationDemo:https://github.com/Cuiyansong/java-benchmark/blob/master/demo/src/main/java/com/cuiyansong/benchmark/demo/stream/FindPerf.java ↩︎