博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Racket 模拟SICP的流(延时计算)
阅读量:6692 次
发布时间:2019-06-25

本文共 1882 字,大约阅读时间需要 6 分钟。

默认的Racket是要对函数参数进行求值的, 例如(f 1 (+ 1 2))里面,(+ 1 2)要先求值为3,变为(f 1 3)再进行下一步操作.因此, Racket若按照SICP使用define关键字来定义延时计算的关键函数delay和cons-stream是不可行的, 需要用宏来定义,绕过求值.

#lang racket(define (memo-proc proc)  (let ((already-run? #f) (result #f))    (lambda ()      (if already-run?          result          (begin (set! result (proc))                 (set! already-run? #t)                 result)))))(define-syntax-rule (delay exp)     (memo-proc (lambda () exp)))(define-syntax-rule (cons-stream a b)   (cons a (delay b)))

这里memo-proc是用于避免重复计算延时过程的. 比如首次调用延时过程(+ 1 2 3), 我们得到了结果6, 那么如果还需要反复调用它1万次, 显然再进行1万次(+ 1 2 3)的计算是不明智的,只需记住首次的结果, 以后再被调用时直接用它就可以了. 但这也说明了延时过程需要是无副作用的.

下面是其他延时函数的定义:

(define-syntax-rule (force delayed-object)  (delayed-object))(define (stream-car stream) (car stream))(define (stream-cdr stream) (force (cdr stream)))(define (stream-ref s n)  (if (= n 0)      (stream-car s)      (stream-ref (stream-cdr s) (- n 1))))(define (stream-map proc s)  (if (null? s)      '()      (cons-stream (proc (stream-car s))                   (stream-map proc (stream-cdr s)))))(define (stream-for-each proc s)  (if (null? s)      'done      (begin (proc (stream-car s))             (stream-for-each proc (stream-cdr s)))))(define (stream-enumerate-interval low high)  (if (> low high)      '()      (cons-stream       low       (stream-enumerate-interval (+ low 1) high))))(define (display-line x)  (newline)  (display x))(define (display-stream s)  (stream-for-each display-line s))(define (show x)  (display-line x)  x); test begins...(define x (stream-map show (stream-enumerate-interval 0 10)))(stream-ref x 5)(stream-ref x 7)

感慨: 其实我这里的宏只是相对于C语言里的那种文本替换宏. Racket的宏还能更加复杂. Scheme系语言的表达能力确实强悍, 但或许不太适合团队. 一是S表达式的形式繁琐, 语法简单优雅的代价就是视觉上的反人类,不利于交流. 二是这种语言可定制性太强, 你喜欢这样搞, 我还喜欢那样搞呢, 谁愿去理解你那些说不定你自己过段时间都理解不了的各种宏或延续的奇技淫巧呢.  此时对比Python, 其设计者的良苦用心可见一斑.

转载于:https://www.cnblogs.com/xiangnan/p/3930359.html

你可能感兴趣的文章
flutter-dart 组件构造函数介绍
查看>>
基于Java语言构建区块链(三)—— 持久化 & 命令行
查看>>
iOS开发,轻松获取根控制器当前控制器的正确方式
查看>>
Akka系列(九):Akka分布式之Akka Remote
查看>>
CDH安装系统环境准备——系统版本和安装包下载地址指南
查看>>
一个灵活设置十六进制颜色值的方法
查看>>
JavaScript 工作原理之十四-解析,语法抽象树及最小化解析时间的 5 条小技巧...
查看>>
Java杂记9—NIO
查看>>
算法(四):图解狄克斯特拉算法
查看>>
css3动画属性整理
查看>>
如何针对性替换数组里的某几个对象
查看>>
git基础整理
查看>>
【前端】 form.get 方式上传对象数组给后台
查看>>
阿里智能工作软件机器人——码栈应用教程,让一切变得自动化
查看>>
Angular service 详解
查看>>
百度研发面经
查看>>
深度解析 Go 语言中「切片」的三种特殊状态
查看>>
ES6 - 函数扩展
查看>>
Linux中apt与apt-get命令的区别与解释(转)
查看>>
原生js 类名操作 增加 删除
查看>>