1

Учитывая следующий код:Задержка оценки на схеме

(define (my-if condition iftrue iffalse) 
(cond (condition iftrue) 
     (else iffalse))) 

'-----example1 
(my-if #t 
     (display "my if was true!") 
     (display "my if was false!")) 
(newline) 
'-----example2 
(my-if #t 
     (display "my if was true!") 
     (+ 2 3)) 

почему бы пример 1 оценить оба параметра сразу давая выход

my if was true!my if was false! 

еще в примере 2, только

my if was true! 

- выход?

Это потому, что display никогда не задерживается, но арифметические операторы, или это что-то еще?

ответ

3

В оба случая как аргументы получить оценку - это как процедуры работы, все аргументы вызова функции вычисляются до того выполняется тело функции, они никогда не задерживается! (если это явно не сделано).

И именно поэтому вы не можете реализовать my-if как процедура, она должна быть особая форма, как if и cond, которые оценивают только часть, соответствующая истинному условию, или else часть, если никто не будет правда. Кроме того, имейте в виду, что display только печатает свой аргумент на консоли, но это не return любое значение.

Вашего второй пример печатает сообщение, но добавление слишком было выполнено в любом случае, это просто, что его значение не было возвращено, поскольку первого условие было верно, так my-if возвращает значение первого параметра, который является значение, возвращенное из звонка display (доmy-if), который недействителен. Например, посмотрим, что это выводит на консоль:

(my-if #t 
     (+ 2 3) 
     (display "my if was false!")) 

Как и ожидалось, оба параметра получить оценку, но значение только первый в возвращается:

my if was false! ; this got printed anyway 
5    ; this is the value returned by `my-if` 
+0

Вы имели в виду '(дисплей«мой, если был ложным!»)' Для случая еще, не так ли? –

+0

@AlexKnauth Yup, спасибо. Теперь это исправлено! –

1

Не уверен, что если вы можете использовать lazy racket, но если это так, что это будет работать для вас

#lang lazy 

(define (my-if p t f) 
    (cond [p t] 
     [else f])) 

(my-if #t (display 'true) (display 'false)) 

; => true 

Если запустить его в обычной ракетке ...

#lang racket 

(define (if p t f) 
    (cond [p t] 
     [else f])) 

(if #t (display 'true) (display 'false)) 

; => truefalse 

Другим способом вы могли бы достичь лени будет оборачивать аргументы в лямбдах:

#lang racket 

(define (my-if p t f) 
    ; this calls the correct function with zero arguments 
    ((if p t f))) 

; wrap the delayed arguments in zero-argument functions 
(my-if #t (λ() (display 'true)) (λ() (display 'false))) 

; => true 
+2

Последнее не очень хорошее использование 'eval', особенно когда вы можете сделать' (define-syntax my-if (syntax-rules() ((my-if pca) (cond (pc) (else a))))) ' – Sylwester

+0

Как насчет использования' quote' и 'eval', используя thunks для задержки аргументов? –

+0

@AlexKnauth благодарит за изменение. Я здесь, чтобы узнать^_ ^ – naomik

Смежные вопросы