Merge pull request #311 from liracle/master

update 14.8, 14.8 done
This commit is contained in:
无闻
2017-02-06 10:48:16 -05:00
committed by GitHub

View File

@@ -49,8 +49,77 @@ func main() {
有一个细微的区别是从通道读取的值可能会是稍早前产生的并不是在程序被调用时生成的。如果确实需要这样的行为就得实现一个请求响应机制。当生成器生成数据的过程是计算密集型且各个结果的顺序并不重要时那么就可以将生成器放入到go协程实现并行化。但是得小心使用大量的go协程的开销可能会超过带来的性能增益。
这些原则可以概括为:通过巧妙地使用空接口、闭包和高阶函数,我们能实现一个通用的惰性生产器(这个应该放在一个工具包中实现)。
这些原则可以概括为:通过巧妙地使用空接口、闭包和高阶函数,我们能实现一个通用的惰性生产器的工厂函数`BuildLazyEvaluator`这个应该放在一个工具包中实现。工厂函数需要一个函数和一个初始状态作为输入参数返回一个无参、返回值是生成序列的函数。传入的函数需要计算出下一个返回值以及下一个状态参数。在工厂函数中创建一个通道和无限循环的go协程。返回值被放到了该通道中返回函数稍后被调用时从该通道中取得该返回值。每当取得一个值时下一个值即被计算。在下面的例子中定义了一个`evenFunc`函数其是一个惰性生成函数在main函数中我们创建了前10个偶数每个都是通过调用`even()`函数取得下一个值的。为此,我们需要在`BuildLazyIntEvaluator`函数中具体化我们的生成函数,然后我们再在
** Listing 14.13: general lazy evaluation1.go
```go
package main
import (
"fmt"
)
type Any interface{}
type EvalFunc func(Any) (Any, Any)
func main() {
evenFunc := func(state Any) (Any, Any) {
os := state.(int)
ns := os + 2
return os, ns
}
even := BuildLazyIntEvaluator(evenFunc, 0)
for i := 0; i < 10; i++ {
fmt.Printf("%vth even: %v\n", i, even())
}
}
func BuildLazyEvaluator(evalFunc EvalFunc, initState Any) func() Any {
retValChan := make(chan Any)
loopFunc := func() {
var actState Any = initState
var retVal Any
for {
retVal, actState = evalFunc(actState)
retValChan <- retVal
}
}
retFunc := func() Any {
return <- retValChan
}
go loopFunc()
return retFunc
}
func BuildLazyIntEvaluator(evalFunc EvalFunc, initState Any) func() int {
ef := BuildLazyEvaluator(evalFunc, initState)
return func() int {
return ef().(int)
}
}
```
输出:
```go
0th even: 0
1th even: 2
2th even: 4
3th even: 6
4th even: 8
5th even: 10
6th even: 12
7th even: 14
8th even: 16
9th even: 18
```
联系14.12general_lazy_evaluation2.go
通过使用14.12中工厂函数生成前10个斐波那契数
提示:因为斐波那契数增长很迅速,使用`uint64`类型。
这种计算通常被定义为递归函数但是在没有尾递归的语言中例如go语言这可能会导致栈溢出但随着go语言中堆栈可扩展的优化这个问题就不那么严重。这里使用的诀窍使用了惰性求值。gccgo编译器在某些情况下会实现尾递归。
## 链接