2020秋季学期程序语言设计原理(PL)复习

课程内容复习

Lec5 函数式语言

  • 急求值:急求值是严格求值(Strict),完全求值;急求值对应值调用,最安全

  • 正规求值:函数中的形参每次出现均用实参替换(相当于传名调用)。要做多次实参计算。可能有副作用。

  • 懒求值:是正规求值的特例。

    1. 它只到用到被结合的形参变量 的值时才对实参变元表达式求值(第一次出现),求值后将结果 值束定于形参变量,以后形参变量再次出现就不用求值了。

    2. 对于复杂的表达式如果子表达式求值对整个表达式求值没有影 响就不再求它。

    3. 短路(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 int
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值