在Scheme中,当递归函数返回一个列表时,我无法将它分配给变量

时间:2011-07-18 19:45:03

标签: syntax recursion scheme

我有以下代码:

(define (get-data)
  (define port (open-input-file "../data/problem11.txt"))
  (define field 0)
  (define (get-fields)
    (define field (read port))
    (cond ((not (eof-object? field)) 
           (cons field (get-fields)))  
          (else '())))

  (define returned (get-fields))
  (close-input-port port)
  returned)

(get-data)

根据手册我的代码找不到任何问题,搜索时谷歌没有任何问题,但是当我运行代码时,SCM(我选择的方案解释器)给出了以下错误:

;ERROR: "/usr/lib/scm/Iedline.scm": unbound variable:  get-fields
; in expression: (get-fields)
; in scope:
;   (returned get-fields field port . #@define)
;   ()  procedure get-data
;STACK TRACE
1; (#@define ((returned (get-fields)) (get-fields (#@lambda () (# ...
2; (#@get-data)

但是当我让我的代码看起来像这样时,它运行正常:

(define (get-data port)
  (define field 0)
  (define (get-fields)
    (define field (read port))
    (cond ((not (eof-object? field))
           (cons field (get-fields)))
          (else '())))
  (get-fields))


(define port (open-input-file "../data/problem11.txt"))
(define alfa (get-data port))
(close-input-port port)

为什么当我尝试将返回的get作为返回的get-fields列表返回时,我得到一个未绑定的变量错误,但是当我将alfa定义为返回的get-data列表时(在第二个代码块中),它运作正常吗?是get-fields是递归的吗?我不明白。这里的任何答案都很棒,谢谢。

1 个答案:

答案 0 :(得分:6)

允许实现使用两种可能的语义之一实现内部defineletrecletrec*

SCM显然选择使用letrec语义。这意味着,给定一堆内部define,它们都不能立即引用同一束中另一个内部define的值:适用于letrec的相同限制。

某些实现(如Racket)使用letrec*语义。这意味着早期内部define中定义的任何变量都可以由后来的内部define直接使用。 (换句话说,您的代码可以在任何基于letrec*的实现中正常工作。)

由于您使用的是基于letrec的实现,请执行以下操作:

(let ((returned (get-fields)))
  (close-input-port port)
  returned)