Сделать процедуру в Схеме по лямбде - PullRequest
2 голосов
/ 29 сентября 2019

Я изучаю схему по ' Структура и интерпретация компьютерных программ '

В главе 1.3.2 Построение процедур с использованием лямбды .

Я понял лямбду следующим образом.

Значение, совпадающее с лямбда, записано вне скобок лямбды.

( (лямбда (x) (+ x 4) 4) ; (x) соответствует 4, результат равен 8

Но в SICP другой пример кода отличается.

Код:

(define (sum x y) (+ x y))

(define (pi-sum a b)
  (sum (lambda (x) (/ 1.0 (* x (+ x 3))))
        a
        (lambda (x) (+ x 4))
        b
         ))

(pi-sum 3 6)

Я думаю, что (lambda (x) (/ 1.0 (* x (+ x 3)))) хочет, чтобы совпадение с a, lambda и a обязалось связатьскобки.

Но в примере кода не используйте скобки.

Когда я запускаю этот код, возникает ошибка.

ошибка такая: 'sum: ожидает только 2 аргумента, но найдено 4'

Когда я использую больше скобок, как это:

(define (sum x y) (+ x y))

(define (pi-sum a b)
  (sum ((lambda (x) (/ 1.0 (* x (+ x 3))))
        a)
        ((lambda (x) (+ x 4))
        b)
         ))

(pi-sum 2 6) ; result is 10.1

Код выполняется.

Я в замешательстве, потому что SICP * Пример кода 1044 *.

Прав ли я по принципу лямбды?

Если я прав, почему SICP напиши как?

1 Ответ

3 голосов
/ 29 сентября 2019

В нем сказано использовать сумму из 1.3.1. На странице 77 (фактически начинающейся на 77 и заканчивающейся на 78) это выглядит следующим образом:

(define (sum term a next b)
  (if (> a b)
      0
      (+ (term a)
         (sum term (next a) next b))))

Как вы можете видеть, это выглядит сильно отличающимся от вашего sum, который просто складывает два числа вместе. У вас также была опечатка в pi-sum:

(define (pi-sum a b)
  (sum (lambda (x) (/ 1.0 (* x (+ x 2)))) ; multiplied by 2, not 3!
       a
       (lambda (x) (+ x 4))
       b))

(* 8 (pi-sum 1 1000))
; ==> 3.139592655589783

Итак, суть в том, что вы можете передавать лямбды вместо именованных процедур. Поскольку (define (name . args) body ...) является просто синтаксическим сахаром для (define name (lambda args body ...)), передача (lambda args body ...) вместо определения его и передачи имени является просто равным рефакторингом.

Скобки вокруг переменной (+) или лямбда ((lambda args body ...)) вызывают любую процедуру, вычисляемую операторным выражением. Это не то, что вы хотите, так как вы передаете процедуры, которые будут использоваться sum в качестве абстракции. sum может делать умножения или любое количество вещей в зависимости от того, что вы передаете. в sum term есть процедура (lambda (x) (/ 1.0 (* x (+ x 2)))), и вы видите, что она вызывает ее отдельно от кода.

...