Как исправить эту ошибку: начать (возможно, неявно): нет выражения после последовательности внутренних определений - PullRequest
2 голосов
/ 08 июня 2019

У меня проблемы с реализацией одного генератора с именем 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 Ответ

2 голосов
/ 08 июня 2019

Как говорится в ошибке, у вас нет выражений в определении вашей функции, за исключением некоторого внутреннего определения (которое, очевидно, заложено в неявное begin).Определив ее, что должна делать функция?

Что еще более важно, есть проблемы с общим дизайном вашего решения.

При написании определения функции сразу запишите ее примеры вызовов, чтобы выПосмотрите, как это предполагается / предназначено / будет называться.В частности,

  (define (take n g)

предполагает, что вы намереваетесь назвать его как (take 10 fib), так что внутри определения take g будет получено значение fib.

Но fib - это один глобальный генератор.Он никак не может быть перезапущен между различными вызовами.Вот почему вы начали копировать его источник, но потом, возможно, поняли, почему тогда у параметра 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
> 
...