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

djh*_*987 3 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)
Run Code Online (Sandbox Code Playgroud)

我根据手册找不到任何问题,谷歌搜索时没有任何问题,但是当我运行代码时,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)
Run Code Online (Sandbox Code Playgroud)

但是,当我使我的代码看起来像这样,它工作正常:

(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)
Run Code Online (Sandbox Code Playgroud)

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

Chr*_*ung 6

允许实现define使用两种可能的语义之一来实现内部:letrecletrec*.

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

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

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

(let ((returned (get-fields)))
  (close-input-port port)
  returned)
Run Code Online (Sandbox Code Playgroud)