Может кто-нибудь помочь объяснить эту схему процедуры - PullRequest
3 голосов
/ 22 октября 2008

Вопрос:

((lambda (x y) (x y)) (lambda (x) (* x x)) (* 3 3))

Это был № 1 в среднесрочной перспективе, я поставил «81 9», он подумал, что я забыл вычеркнуть один газон, поэтому я вычеркиваю 81, и он идет ужасно. В любом случае, я не понимаю, почему это 81.

Я понимаю, почему (lambda (x) (* x x)) (* 3 3) = 81, но первая лямбда Я не понимаю, какие значения x и y существуют, и что делает [body] (x y).

Так что я надеялся, что кто-нибудь сможет объяснить мне, почему первая часть, похоже, ничего не делает.

Ответы [ 4 ]

9 голосов
/ 22 октября 2008

Для уточнения требуется отступ.

((lambda (x y) (x y))
 (lambda (x) (* x x))
 (* 3 3))
  • (lambda (x y) (x y)); вызовите x с y в качестве единственного параметра.
  • (lambda (x) (* x x)); оцените по квадрату его параметра.
  • (* 3 3); оценить до 9

Таким образом, все это означает: «вызвать функцию квадрата с параметром 9».

РЕДАКТИРОВАТЬ: То же самое может быть написано как

((lambda (x) (* x x))
 (* 3 3))

Полагаю, цель этого упражнения - показать, как оценка формы схемы включает применение неявной функции.

6 голосов
/ 22 октября 2008

Давайте посмотрим на это снова ...

((lambda (x y) (x y)) (lambda (x) (* x x)) (* 3 3))

Чтобы оценить форму, мы оцениваем каждую ее часть по очереди. У нас есть три элемента в нашей форме. Этот находится на первой (функциональной) позиции:

(lambda (x y) (x y))

Это второй элемент формы и первый аргумент функции:

(lambda (x) (* x x))

Последний элемент формы, поэтому второй аргумент функции.

(* 3 3)

В этом случае порядок оценки не имеет значения, поэтому давайте начнем с левой стороны.

(lambda (x y) (x y))

Lambda создает функцию, поэтому она оценивает функцию, которая принимает два аргумента, x и y, а затем применяет x к y (другими словами, вызывает x с одним аргументом y). Давайте назовем это call-1 .

(lambda (x) (* x x))

Это вычисляет функцию, которая принимает один аргумент и возвращает квадрат этого аргумента. Таким образом, мы можем просто назвать это квадрат .

(* 3 3)

Это, очевидно, оценивается как 9 .

ОК, поэтому после первого запуска оценки мы имеем:

(call-1 square 9)

Для оценки этого мы вызываем call-1 с двумя аргументами: square и 9 Применение call-1 дает нам:

(square 9)

Так как это то, что делает call-1 - он вызывает свой первый аргумент со своим вторым аргументом. Теперь квадрат 9 равен 81 , что является значением всего выражения.

2 голосов
/ 22 октября 2008

Возможно, перевод этого кода в Common Lisp поможет прояснить его поведение:

((lambda (x y) (funcall x y)) (lambda (x) (* x x)) (* 3 3))

Или даже более явно:

(funcall (lambda (x y) (funcall x y))
         (lambda (x) (* x x))
         (* 3 3))

Действительно, эта первая лямбда не делает ничего полезного, поскольку сводится к:

(funcall (lambda (x) (* x x)) (* 3 3))

, что равно

(let ((x (* 3 3)))
  (* x x))

равно

(let ((x 9))
  (* x x))

равно

(* 9 9)

равно 81.

1 голос
/ 22 октября 2008

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

(define (square x) (* x x))

(define (call-with arg fun) (fun arg))

(call-with (* 3 3) square)

Это все еще выглядит странно?

...