Kev*_*nch 10 lisp scheme sicp racket
我将通过SICP进行自学,并参与第2章的图片语言部分.我一直在使用DrRacket进行早期练习,但在尝试基于"画线"进行练习时出现编译错误本书这一部分的图片功能.
具体来说,这段代码......
(define (segments->painter segment-list)
(lambda (frame)
(for-each
(lambda (segment)
(draw-line
((frame-coord-map frame) (start-segment segment))
((frame-coord-map frame) (end-segment segment))))
segment-list)))
Run Code Online (Sandbox Code Playgroud)
...产生这个错误......
draw-line: unbound identifier in module in: draw-line
Run Code Online (Sandbox Code Playgroud)
所以我在这个论坛做了一些研究,并安装了Neil Van Dyke提供的SICP软件包(http://www.neilvandyke.org/racket-sicp/#(part._usage)).我按照所有步骤,按照指示将语言更改为SICP,但仍然得到相同的错误.
我认为这个软件包的目的是定义这个"内置"函数(以及书中的其他函数).只是为了预测一些问题,我在文件中没有'require'语句并使用'#lang planet neil/sicp'来指定语言而不是使用菜单(我也尝试使用菜单将语言更改为SICP并获取一个更奇怪的错误;请参阅下面的附言).我的环境是Windows 7,DrRacket的版本是5.3.1.
也许我只是犯了一个菜鸟错误; 任何见解将不胜感激.
谢谢.
PS:对于那些感兴趣的人,当我使用菜单将语言设置为'SICP(PLaneT 1.17)'时,对于我尝试编译的任何定义(即使是最微不足道的),我都会收到以下错误...
<unsaved editor>:1:0: #%top-interaction: unbound identifier;
also, no #%app syntax transformer is bound in: #%top-interaction
Run Code Online (Sandbox Code Playgroud)
在Racket中,这些定义通过SICP第2章中的图纸解决了我的问题,之后我成功地解决了这些练习:
(require graphics/graphics)
(open-graphics)
(define vp (open-viewport "A Picture Language" 500 500))
(define draw (draw-viewport vp))
(define (clear) ((clear-viewport vp)))
(define line (draw-line vp))
(define (make-vect x y)
(cons x y))
(define (xcor-vect v)
(car v))
(define (ycor-vect v)
(cdr v))
(define (add-vect v1 v2)
(make-vect (+ (xcor-vect v1)
(xcor-vect v2))
(+ (ycor-vect v1)
(ycor-vect v2))))
(define (sub-vect v1 v2)
(make-vect (- (xcor-vect v1)
(xcor-vect v2))
(- (ycor-vect v1)
(ycor-vect v2))))
(define (scale-vect s v)
(make-vect (* s (xcor-vect v))
(* s (ycor-vect v))))
(define (make-frame origin edge1 edge2)
(list origin edge1 edge2))
(define (origin-frame f)
(car f))
(define (edge1-frame f)
(cadr f))
(define (edge2-frame f)
(caddr f))
(define (frame-coord-map frame)
(lambda (v)
(add-vect
(origin-frame frame)
(add-vect (scale-vect (xcor-vect v)
(edge1-frame frame))
(scale-vect (ycor-vect v)
(edge2-frame frame))))))
Run Code Online (Sandbox Code Playgroud)
我要感谢 alinsoar、flamingo 和 Oscar 提供的非常有用的建议。
我决定采用 Oscar 的方法,它(显然)使用球拍图形库,而不是 Neil Van Dyke 组装的特殊包(我只是没有运气)。这是我的代码的重要部分(忽略了不依赖于图形库的定义):
#lang racket
(require graphics/graphics)
(open-graphics)
(define vp (open-viewport "A Picture Language" 500 500))
(define draw (draw-viewport vp))
(define (clear) ((clear-viewport vp)))
(define line (draw-line vp))
;need a wrapper function so that the graphics library works with my code...
(define (vector-to-posn v)
(make-posn (car v) (car(cdr v))))
(define (segments->painter segment-list)
(lambda (frame)
(for-each
(lambda (segment)
(line
(vector-to-posn ((frame-coord-map frame) (start-segment segment)))
(vector-to-posn ((frame-coord-map frame) (end-segment segment)))))
segment-list)))
Run Code Online (Sandbox Code Playgroud)
所以,有几点需要注意:
1) 如上所述,这使用标准球拍语言,而不是 Neil Van Dyke 实现目的的 SICP 语言。
2)这个库中的'draw-line'函数将一个视口(基本上是一个窗口)作为参数,并创建一个函数,该函数采用两个坐标作为参数(以及一个我没有使用的可选颜色参数)。然而,这种情况下的“坐标”不是练习使用的简单向量。坐标是结构 'posn' 的实例,它基本上只是 x 和 y 值的包装器。
这种 posn 数据类型的存在意味着我必须用 posn 构造函数包装我的向量,然后才能在“segments-painter”函数中使用它们。('vector-to-posn' 函数就是这个包装器)。另请注意,书中对“segments-painter”的定义中使用的“draw-line”一词被替换为“line”,它被定义为(draw-line vp)。
3) 有趣的是,球拍图形库定义的视口坐标与我预期的有点不同。坐标(0,0)的所述顶部在帧左点(I也能猜到左下)和(11)是右下角。(请注意,这里我说的是单位平方。在我在上面的代码中使用的框架中,右下角的真实坐标是 (500 500)。)
因为我正在做的练习 (2.49) 涉及绘制关于水平轴对称的图形,所以这个小皱纹并不重要,否则它可能会让你感到惊讶。我突然想到,解决这种“反转”的一种方法是使用书中的“翻转-垂直”功能,但我没有花时间这样做。
再次感谢大家的帮助!
| 归档时间: |
|
| 查看次数: |
2675 次 |
| 最近记录: |