Что означает «следующий» в этом контексте? - PullRequest
0 голосов
/ 06 мая 2018

Я читаю SICP и использую пакет Dr Racket SICP в качестве IDE и переводчика. Код из SICP:

(define (sum func a next b)
  (if (> a b)
      0
      (+ (func a)
         (sum func (next a) next b))))
(define (inc n) (+ n 1))

(define (sum-cubes a b)
  (sum cube a inc b))

(define (cube a) (* a a a))

(sum-cubes 1 10)

Функция состоит в том, чтобы вычислить сумму кубических значений от 1 до 10. Однако я понятия не имею, что означает next b, поскольку мы увеличиваем a вместо b, а функция приращения представляется как inc .

Итак, я удалил next в next b

Тогда я получил ошибку: define: duplicate argument identifier in: next

Я попытался найти «следующий» в синтаксисе, но ничего не нашел.

Как-то я сделал эту работу:

(define (sum func a b)
  (if (> a b)
      0
      (+ (func a)
         (sum func (inc a) b))))
(define (inc n) (+ n 1))

(define (sum-cubes a b)
  (sum cube a b))

(define (cube a) (* a a a))

(sum-cubes 1 10)

Но это кажется странным. func заменяется на cube, так что это почти как параметр функции в C ++? Но почему это не (func (inc a))? Почему Схема распознает func (inc a) и знает, что ее нужно заменить на cube?

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Эта форма:

(+ a b)

Является комбинацией с 3 переменными. +, a и b являются переменными, и Scheme оценивает их в любом порядке перед применением, которое принимает объект процедуры и значения.

Очень важно знать, что аргументы в пользовательской процедуре становятся переменными. они могут содержать любое значение , поэтому func и next являются просто именами. В коде вы видите, что они применяются, например. они заключаются в круглые скобки в позиции оператора, это единственный намек на то, что они должны быть процедурами. То есть помимо документации в комментариях: -)

Процедура в других местах, кроме позиции оператора, это просто передаваемое значение. Например. в (sum func (next a) next b) очевидно next - это процедура, которая используется для получения второго аргумента и которая передается как значение. Он будет связан с next на следующей итерации, так что его тоже можно будет использовать там. Вы можете избежать этого, используя замыкания:

;;; sums the numbers a ... b
;;; using procedure func as key and
;;; procedure next to compute next value
;;; example:
;;; (sum (λ (v) (* v 2)) ; func
;;;      1               ; a
;;;      (λ (v) (+ v 2)) ; next
;;;      10)             ; b 
;;; => 50
;;; = (+ 2 6 10 14 18)
(define (sum func a next b)
  (define (helper a)
    (if (> a b)
        0
        (+ (func a)
           (helper (next a)))))
  (helper a))

Более понятный способ, чем приведенный выше, - использовать имя let, и вы также можете ввести аккумулятор, который делает этот хвост рекурсивным, но я полагаю, что вы узнаете это в конечном итоге, просто следуя книге.

0 голосов
/ 06 мая 2018

next - это просто параметр, который является функцией. Передано значение inc, поэтому фрагмент (next a) в функции sum вычисляет (inc a). Следующий next b просто передает эти значения в рекурсивный вызов sum.

Добавление

Рекурсивный вызов просто увеличивает значение, переданное в a, и позволяет b как есть. Рекурсия прекращается, когда a > b. На каждом уровне func применяется к a и добавляется к накопленной стоимости. func - это функция cube в примере. Таким образом, это суммирование кубов, как задумано.

...