如何解决此错误:开始(可能是隐式):在一系列内部定义之后没有表达式

时间:2019-06-08 03:08:24

标签: scheme racket

我在函数中实现一个名为fib的生成器时遇到问题。 我希望函数返回一个生成器,该生成器生成第一个n斐波那契数。

 ;THIS IS MY GENERATOR

 (define fib
  (let ((a 0) (b 1))
    (lambda ()
      (let ((return a))
        (set! a b)
        (set! b (+ b return)
        )return))))

 ;THIS IS MY FUNCTION
  (define (take n g)  
  (define fib
    (let ((a 0) (b 1) (cont 1))
      (lambda ()
        (if (>= cont n) #f
            (let ((return a))
              (set! cont (+ cont 1))
              (set! a b)
              (set! b (+ b return)
                    )(return)))))))

我希望生成器返回斐波纳契数直至N(传递给函数)。但是实际输出是:

  

开始(可能是隐式的):在以下一系列内部定义之后没有表达式:

(begin 
    (define fib 
       (let ((a 0) (b 1) (cont 1)) 
          (lambda () 
            (if (>= cont n) #f 
              (let ((return a)) 
                 (set! cont (+ cont 1)) 
                 (set! a b) 
                 (set! b (+ b return)) 
                 (return)))))))

1 个答案:

答案 0 :(得分:2)

正如错误所言,函数定义中没有表达式,除了一些内部定义(显然,它被包含在隐式begin中)。定义好之后,要执行的功能是什么?

更重要的是,您的解决方案的整体设计存在问题。

在编写函数的定义时,请立即记下其示例调用,这样您就可以知道应该如何/打算/如何调用它。特别是

  (define (take n g)

建议您将其命名为(take 10 fib),以便在take的定义g中获得fib的值。

但是fib是一个 global 生成器。在不同的调用之间,它不能以任何方式重新启动。这就是为什么您开始复制其源代码,然后又意识到,为什么要使用g参数呢?那里不太合适。

您需要在需要时创建一种新的新鲜斐波那契发生器的方法:

(define (mk-fib)
  (let ((a 0) (b 1))
    (lambda ()
      (let ((ret a))
        (set! a b)
        (set! b (+ ret b))
        ret))))    ;; ..... as before .....

现在,每个(mk-fib)调用都将创建并返回一个新的斐波那契数字生成器,因此现在 可以用作take调用的参数:

(define (taking n g)      ;; (define q (taking 4 (mk-fib)))

现在,无需像以前尝试的那样定义同一全局fib生成器的新本地副本。我们只有take本身的特定内容:

   (let ((i 1))
     (lambda ()         ; a generator interface is a function call
       (if (> i n)      ; not so good: what if #f
           #f           ;  is a legitimately produced value?
           (begin
             (set! i (+ i 1))
             (g))))))   ; a generator interface is a function call

现在我们可以定义

> (define q (taking 4 (mk-fib)))
> (q)
0
> (q)
1
> (q)
1
> (q)
2
> (q)
#f
> (q)
#f
>