课程内容复习
Lec5 函数式语言
-
急求值:急求值是严格求值(Strict),完全求值;急求值对应值调用,最安全
-
正规求值:函数中的形参每次出现均用实参替换(相当于传名调用)。要做多次实参计算。可能有副作用。
-
懒求值:是正规求值的特例。
-
它只到用到被结合的形参变量 的值时才对实参变元表达式求值(第一次出现),求值后将结果 值束定于形参变量,以后形参变量再次出现就不用求值了。
-
对于复杂的表达式如果子表达式求值对整个表达式求值没有影 响就不再求它。
-
短路(short circuit)求值,一般用作条件表达式,也叫短路条件。
E = Exp1 and Exp2 and …Expn 若Exp1求值为false,则E值已定为false。
再如: E = Exp1 or Exp2 or …Expn 若Exp1为true,则E值为true不论其它表达式取何值。
C、Ada及近代函数式语言均采用懒求值。
-
λ演算参考
并发——go语言
并发编程练习题:
假设存在一个生产者,依次产生数字0到9。存在一个奇数消费者,一个偶数消费者分别使用奇数和偶数,使用Go语言通道实现这个生产者消费者模型。使得数字按从小到大的顺序输出。
思路:新添加一个Channel,用以两个Consumer之间通信,传递一个flag。拿到flag的Consumer进行输出,没有拿到flag的Consumer阻塞。因为从0开始输出,所以flag最初在偶数消费者手中。
package main
import (
"fmt"
"sync"
)
// wg 用来等待程序结束
var wg sync.WaitGroup
func main() {
oddChannel := make(chan int)
evenChannel := make(chan int)
//排序标志,必须获取到这个量才能输出,false表示输出偶数,true表示输出奇数
flagChannel := make(chan bool)
// 计数加 3,表示要等待3个goroutine
wg.Add(3)
go producer(oddChannel, evenChannel)
go oddConsumer(oddChannel, flagChannel)
go evenConsumer(evenChannel, flagChannel)
//初始是偶数
flagChannel <- false
// 等待结束
wg.Wait()
}
func producer(odd chan int, even chan int) {
// 在函数退出时调用Done 来通知main 函数工作已经完成
defer wg.Done()
for i := 0; i < 10; i++ {
if i%2 == 0 {
even <- i
} else {
odd <- i
}
}
close(odd)
close(even)
}
func oddConsumer(odd chan int, flag chan bool) {
defer wg.Done()
for {
value, ok := <-odd
if !ok {
fmt.Printf("Consumer odd, work done\n")
return
}
outFlag := <-flag
if outFlag {
fmt.Printf("Consumer odd, get value %d\n", value)
}
flag <- false
}
}
func evenConsumer(even chan int, flag chan bool) {
defer wg.Done()
for {
value, ok := <-even
if !ok {
<-flag //n为偶数,偶数消费者需要在返回时处理掉最后一个flag
fmt.Printf("Consumer even, work done\n")
return
}
outFlag := <-flag
if !outFlag {
fmt.Printf("Consumer even, get value %d\n", value)
}
flag <- true
}
}
并发程序设计的模型:
-
共享变量模型
-
消息传递模型 (目前最灵活,最常用的模型):程序中不同的进程之间通过显式的方法(如函数调用、运算符)等传递消息来互相通信,实现进程之间的数据交换,同步控制等。
-
数据并行模型
-
面向对象模型
-
Go 语言的并发通过 goroutine 特性完成。
-
goroutine 类似于线程,但是可以根据需要创建多个 goroutine 并发工作。
-
goroutine 是由 Go 语言的运行时调度完成,而线程是由操作系统调度完成。
-
Go 语言提供 channel 在多个 goroutine 间进行通信:Go语言中的通道(channel)是一种特殊的类型。goroutine 通过通道就可以通信。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。
-
Go语言带缓冲的通道
Go语言关闭通道后继续使用通道
- 给被关闭通道发送数据将会触发panic。被关闭的通道不会被置为nil。如果尝试对已经关闭的通道进行发送,将会触发宕机;
package main
import "fmt"
func main() {
//创建一个整形的通道
ch := make(chan