当我在另一个函数中定义一个函数时,我得到一个'错误的放置定义'错误

时间:2011-08-02 21:45:33

标签: scheme syntax-error

这是我的代码:

 (require 'hash-table)

 (define (hash-table-get htable key)
    ((hash-inquirer equal?) htable key))

 (define (hash-table-add! htable key val)
    ((hash-associator equal?) htable key val))

 (define (hash-table-remove! htable key)
    ((hash-remover equal?) htable key))


 (define (find-max-chain)
      (define table (make-hash-table 1000)) ; works
      .
      .
      .          ; proven working code

      (define (get-chain number) (let ((chain (hash-table-get table number))) chain))

      .
      .
      .        ; more code




    max-entry)
   (find-max-chain)

问题在于(define (get-chain number) [...] ))部分。当我在全局上下文中定义它并table(find-max-chain)之外时,它在我运行它时就会成功。但是当我在(get-chain)内部定义(find-max-chain)我需要它时,当我执行(find-max-chain)时,我从SCM得到了这个错误:

;ERROR: "problem14-new.scm": bad placement define
; in expression: (define (get-chain! number) (let ((chain (hash-table-ge ...
; in scope:
;   (update-max! table max-chain max-entry . #@define)
;   ()  procedure find-max-chain
; defined by load: "problem14-new.scm"

;STACK TRACE
1; (#@define ((update-max! (#@lambda (entry chain) (cond ((> chai ...
2; (#@find-max-chain)
3; (#@define ((hss (#@has-suffix? #@file (#@scheme-file-suffix))) ...

这是为什么?

2 个答案:

答案 0 :(得分:4)

在函数内部,define仅允许在函数的开头(或类函数体),在任何情况下它们都等同于letrec。请参阅R5RS的this section

答案 1 :(得分:2)

我对SCM及其错误消息并不熟悉,但我的第一个猜测是你正在与letrec vs letrec*问题发生冲突。 R5RS(粗略地)说,必须能够以letrec形式评估每个右侧,而不触及任何letrec绑定变量;内部定义也有同样的限制。 (IIRC,R6RS添加了letrec*表格,允许此类参考。)

例如,以下内容是非法的:

(let ()
  (define x 1)
  (define y (+ 1 x))
  y)

因为评估y rhs需要x的值。相比之下,这没关系:

(let ()
  (define x 1)
  (define f (lambda () (+ 1 x)))
  (f))

也就是说,这不是范围界定的问题,而是变量“何时可以使用”的问题。