Написание цикла while в схеме

Я пытаюсь реализовать цикл while, используя рекурсию с лямбдой, но я просто не понимаю, как это сделать.

Я должен начать с этого лямбда-выражения:

((lambda (x) (x x)) (lambda (x) (x x))

Мой первый вопрос: почему это вызывает «вечную» рекурсию? Я пытаюсь понять, как это работает, но никак не могу понять.

У меня также есть этот код:

((lambda (x) (x x))
 (lambda (x) 
   (if (not (= i 0))
       (begin
         (display i)
         (set! i (- i 1))
         (x x))
       )))

Этот код вызывает цикл, который печатает от i = n до i = 0, но я этого тоже не понимаю. Если кто-то захочет объяснить использование лямбда здесь, я был бы признателен :)

Изменить: я должен использовать это лямбда-выражение в качестве «отправной точки», и я не хочу использовать макросы (это добровольное упражнение, которое я пытаюсь понять, поэтому я хочу следовать рекомендациям :))


person user16655    schedule 16.05.2015    source источник
comment
Хотя обычно реализуется как макрос в Scheme. См. этот более или менее повторяющийся вопрос: /10968212/   -  person ben rudgers    schedule 17.05.2015


Ответы (1)


Чтобы увидеть, что происходит при оценке ((lambda (x) (x x)) (lambda (x) (x x)), используйте степпер в DrRacket. Он может показать вам шаги, которые выполняет оценка.

Напишите свое выражение в окне определения DrRacket. Затем выберите язык обучения «Студент среднего уровня с лямбдой». Затем нажмите кнопку шагового двигателя (зеленый треугольник, за которым следует полоса).

Вы увидите что-то похожее на изображение (которое использует другую программу):

введите здесь описание изображения

Обновлять:

Попробуйте эту программу:

(define i 5)

((lambda (x) (x x))
 (lambda (x) 
   (if (not (= i 0))
       (x x)
       'ignore)))

Обновлять:

(define i 5)

(define f
  (lambda (x) 
    (if (not (= i 0))
        (begin
          (display i)
          (set! i (- i 1))
          (x x))
        'done)))

(f f)

Или вообще без каких-либо определений:

((lambda (f) (f f))
 (lambda (x) 
   (if (not (= i 0))
       (begin
         (display i)
         (set! i (- i 1))
         (x x))
       'done)))

А здесь без внешней переменной:

((lambda (f i) (f f i))
 (lambda (x i) 
   (if (not (= i 0))
       (begin
         (display i)
         (x x (- i 1)))
       'done))
 5)

Использование функции while:

(define (while body . args)
  (apply body body args))

(while (lambda (loop i)
         (if (not (= i 0))
             (begin
               (display i)
               (loop loop (- i 1)))
             'done))
  5)
person soegaard    schedule 16.05.2015
comment
Я думаю, что это set!, с которым не может справиться степпер. Может быть, мы можем найти похожую программу, чтобы попробовать? - person soegaard; 16.05.2015
comment
Спасибо, сработало :) Может быть, я немного мудрее, я не совсем уверен. Можно ли поместить лямбда-выражение в функцию, чтобы ее можно было вызывать извне? - person user16655; 17.05.2015
comment
(определить f (лямбда (x) (x x))) - person soegaard; 17.05.2015
comment
Возможно, вам понравится этот пост в блоге. Речь идет о реализации рекурсии через механизм, с которым вы экспериментируете. wisdomandwonder.com/article/6344/ - person soegaard; 17.05.2015
comment
Я прочитал статью, но я все еще застрял в попытке создать цикл. Проблема в том, что я хочу отправить условие и тело в качестве параметров функции, но я не могу понять, как совместить это с лямбда-выражением... Мне также нужно использовать лямбда-выражение выше, поэтому я я просто застрял. Это не проблема, если я не понимаю, поскольку это добровольное упражнение, но меня расстраивает то, что я просто не понимаю, как это работает. - person user16655; 17.05.2015
comment
Я добавил одно решение. - person soegaard; 17.05.2015
comment
Подождите минутку - у вас уже есть решение в вашем вопросе. Я неправильно тебя понимаю? - person soegaard; 17.05.2015
comment
Итак, f — это функция, которая принимает один аргумент x. Намерение состоит в том, что f вызывается с (f f), что означает, что x привязан к той же функции. Для зацикливания телу просто нужно вызвать себя, а поскольку x связано с f, мы имеем, что (x x) будет вызывать себя. - person soegaard; 17.05.2015
comment
Ну вроде. Решение состоит в том, чтобы использовать вечную рекурсию с лямбда-выражениями, и пример, который находится в моем вопросе, является примером того, как это работает. Что мне нужно сделать, так это получить это внутри функции и иметь возможность отправлять условие и тело в качестве параметров этой функции. Так что я хочу сказать f.ex. (в то время как (= i 0) (отобразить i) (новая строка) (установить! i (- i 1)), и функция while позаботится об этом. - person user16655; 17.05.2015
comment
Хорошо, я добавил решение без внешней переменной. - person soegaard; 17.05.2015
comment
Спасибо. Я попытался обернуть это в функцию while, но я просто не могу это сделать. Спасибо за ваше время, я думаю, я должен понять, что это слишком сложно для меня... - person user16655; 17.05.2015
comment
Я добавил версию с функцией while. - person soegaard; 17.05.2015
comment
Спасибо. Я посмотрю на это еще немного, это почти готово, но я не хочу писать лямбда-выражение при вызове функции while, я хочу, чтобы оно было в функции while. Я думаю, что мне, возможно, придется прочитать (намного) больше о лямбде перед экзаменом ;-) - person user16655; 17.05.2015
comment
В этом случае вам нужно будет изучить макросы. - person soegaard; 17.05.2015