Вызов функции, которая не принимает параметр с параметром в схеме - PullRequest
0 голосов
/ 25 февраля 2019

Как работает этот код?Похоже, что ни одна из этих функций не имеет параметра, но вы можете вызвать его с параметром

(define (make-add-one)
  (define (inc x) (+ 1 x))
  inc)

(define myfn (make-add-one))

(myfn 2)

. Он запускается и возвращает 3.

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Поднимите определение inc из make-add-one:

(define (inc x) (+ 1 x))

(define (make-add-one)
  inc)

Теперь стало понятнее, что выражение (make-add-one) совпадает с inc, а inc - это явно процедурас одним параметром.
Другими словами, при вызове make-add-one без аргументов получается процедура, которая принимает один аргумент.

Вы можете использовать метод подстановки, чтобы следовать оценке:

    (myfn 2)
==> ((make-add-one) 2)
==> (inc 2)
==> (+ 1 2)
==> 3
0 голосов
/ 25 февраля 2019

Позволяет использовать правила замещения.make-add-one можно переписать так:

(define make-add-one (lambda () 
  (define inc (lambda (x) (+ 1 x))
  inc))

Поскольку inc только что возвращено, мы можем упростить его до следующего:

(define make-add-one (lambda () 
  (lambda (x) (+ 1 x)))

Теперь myfn мы можем заменитьвызов make-add-one с кодом, который есть внутри лямбды:

(define myfn (make-add-one)) ; ==
(define myfn (lambda (x) (+ 1 x)))

И наконец, мы можем использовать правила подстановки при последнем вызове:

(myfn 2)                 ; ==
((lambda (x) (+ 1 x)) 2) ; ==
(+ 1 2)                  ; ==
3

Сейчас make-add-oneсоздает новую функцию, идентичную всем остальным функциямЭто на самом деле ничего не добавляет.Хорошим примером того, где это полезно, является следующий пример:

(define (make-add by-what)
  (lambda (value) (+ value by-what)))

(define inc (make-add 1))
(define add5 (make-add 5))

(map add5 '(1 2 3)) ; ==> (6 7 8)
(map inc '(1 2 3))  ; ==> (2 3 4)

Просто чтобы увидеть, что это то же самое:

(add5 2)                         ; ==
((make-add 5) 2)                 ; ==
((lambda (value) (+ value 5)) 2) ; ==
(+ 2 5)                          ; ==
; ==> 7

И как это работает.В лексически ограниченном языке все формы lambda фиксируют переменные, которые не связаны в их собственном списке параметров из области, в которой он был создан.Это известно как закрытие.Простой пример этого приведен здесь:

(define x 10)
(define test 
  (let ((x 20)
    (lambda (y) (+ x y))))
(test 2) ; ==> 22

Так что в схеме test использует x из let даже после того, как область вышла, так как lambda была создана в этой области.В динамически ограниченном языке (test 2) вернет 12, а два предыдущих примера также приведут к другим результатам и ошибкам.

Лексическая область видимости появилась в первую очередь в Algol, который является предшественником всех языков семейства C, таких как C, java, perl.Схема была, вероятно, первым языком, и это был основной дизайн самого языка.Без закрытия первая версия Scheme была такой же, как и ее основной язык MacLisp.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...