在DrRacket中编译SICP图片练习?

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)

Ósc*_*pez 6

在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)


Kev*_*nch 5

我要感谢 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) 涉及绘制关于水平轴对称的图形,所以这个小皱纹并不重要,否则它可能会让你感到惊讶。我突然想到,解决这种“反转”的一种方法是使用书中的“翻转-垂直”功能,但我没有花时间这样做。

再次感谢大家的帮助!