The Racket Guide阅读笔记,chapter 20, 21,22, 23.
20 Parallelism
Racket提供两种形式的并行,future以及place。
Racket的thread只为并发使用,不为并行使用。
future的功能通过racket/future
库来实现。
20.1 Parallelism with Futures
例子:
#lang racket
(define (any-double? l)
(for/or ([i (in-list l)])
(for/or ([i2 (in-list l)])
(= i2 (* 2 i)))))
(define l1 (for/list ([i (in-range 5000)])
(+ (* 2 i) 1)))
(define l2 (for/list ([i (in-range 5000)])
(- (* 2 i) 1)))
(let ([f (future (lambda () (any-double? l2)))])
(or (any-double? l1)
(touch f)))
上述的f同步执行(any-double? l2)
。
future-visualizer可以用来剖析future:
(require future-visualizer)
(visualize-futures
(let ([f (future (lambda () (mandelbrot 10000000 62 501 1000)))])
(list (mandelbrot 10000000 62 500 1000)
(touch f))))
future-unsafe操作可分为两类:future的计算被阻塞;显示进行同步。
20.2 Parallelism with Places
racket/place
提供不同的raket运行实例间的通信。不同的place之间必须使用消息传递来通信,比如place-channel-put以及place-channel-get。
下面是一个例子:
(define (main)
(define p
(place ch
(define l (place-channel-get ch))
(define l-double? (any-double? l))
(place-channel-put ch l-double?)))
(place-channel-put p (list 1 2 4 8))
(place-channel-get p))
(place ch …)的内容会在一个新的place执行,而且可以通过ch来与原进程通信。
上面的代码保存成double.rkt之后可以通过racket -tm double.rkt
来执行。-tm
表示执行模块中的main函数。
place形式还有两个微妙的特性。首先place的正体部分会升格成一个匿名的,模块级别的函数,这意味着place正体部分所引用的符合必须在模块的顶层。其次,place形式会通过dynamic-require
来在新的place导入当前模块,这意味着不要在顶层直接或者间接调用place,会造成死循环:
#lang racket
(provide main)
; Don't do this!
(define p (place ch (place-channel-get ch)))
(define (indirect-place-invocation)
(define p2 (place ch (place-channel-get ch))))
; Don't do this, either!
(indirect-place-invocation)
20.3 Distributed Places
racket/place/distributed
提供了分布式编程。
21 Running and Creating Executables
21.1 Running racket and gracket
gracket和racket类似,不过以GUI程序出现。根据传入的参数不同,racket或者gracket可以运行:
- interactive mode
- module mode
- load mode
21.1.1 Interactive Mode
默认情况下,调用racket直接进入REPL模式。此模式下,racket会先请求racket/init
模块,并且会加载(find-system-path 'init-file)
中的文件。
如果在命令行求值racket -e '(display "hi\n")'
,可以在其之后使用-i
选项停留在交互模式。
可以使用-l
来加载一个模块,从而跳过racket/init
:racket -l racket/base -i
。这个例子中如果将-l
和-i
互换,那么会在加载racket/base
之前加载racket/init
。
21.1.2 Module Mode
如果单给racket提供一个文件:racket hello.rkt
,那么这个文件会被当成一个模块加载。这个后面可以跟其他选项,不过选项会被放置在current-command-line-arguments
之内。
可以通过-u
和-t
来加载模块的时候指定其相应的命令行。区别是对于后者,额外的命令行有racket处理,而不是直接传给模块本身。
-l
和-t
类似,不过是从库中加载。racket -l raco
等同于raco
。此格式下,如果要传参数给raco,需要指定在--
之后,如racket -l raco -- --help
。
21.1.3 Load Mode
使用-f
或者--load
标记可以直接从文件加载顶层表达式,而不是把文件当成一个模块。效果就像是在REPL中直接输入表达式一样,只不过不会打印结果,例子:
racket -f hi.rkts
也可以直接用-e
来指定在REPL中执行的表达式:
racket -e '(current-seconds)'
和交互模式相同,上述操作会请求racket/init
。同样地,可以指定-l
来修改默认请求的模块:
racket -l racket/base -e '(current-seconds)'
21.2 Scripts
21.2.1 Unix Scripts
略
21.2.2 Windows Batch Files
竟然可以这样:
; @echo off
; Racket.exe "%~f0" %*
; exit /b
#lang racket/base
"Hello, world!"
21.3 Creating Stand-Alone Executables
参考raco的文档。
22 More Libraries
只涉及在The racket reference中记录的语言和库。
22.1 Graphics and GUIs
racket/draw
,画图相关,可以画位图以及PostScriptracket/gui
,图形界面相关pict
,基于racket/draw
,可以用于Slideshow或者Scribble。2htdp/image
,和上一条类似,不过更适合于教学sgl
,提供OpenGL支持。
22.2 The Web Server
略
22.3 Using Foreign Libraries
略
22.4 And More
https://pkgs.racket-lang.org提供更多程序包。
23 Dialects of Racket and Scheme
racket并不只是支持racket。
23.1 More Rackets
Racket发行版中自带的一众语言
typed/racket
,静态类型lazy
,惰性求值frtime
,支持反应式编程scribble/base
,更像是Latex的语言,用于写文档
23.2 Standards
R5RS没有指定模块系统。但是对于单个的R5RS文件,可以使用#lang r5rs
让其在racket中运行。
R6RS给定义了一个模块系统。R6RS可以在文件头执行#!r6rs
,racket会将其等同于#lang r6rs
。
23.3 Teaching
略。
(完)