2011-02-04 2 views
4

Легко выразить and, or и not в терминах if (с помощью местной переплета для or). Я хотел бы знать, верно ли обратное. Моя наивная первая попытка:В Схеме может быть выражено как комбинация булевых операторов?

(if test conseq altern) => (or (and test conseq) altern) 

Однако, если test является не- #f и conseq является #f, перевод вычисляется в altern, что неверно.

Есть ли перевод, который оценивает правильное значение при сохранении характера короткого замыкания if?

+0

Возможно (или (и (или conseq #t)) альтернативный вариант)? – knivil

+0

Ах, но тогда '(if #t #f #t)' будет оценивать '# t'. Тем не менее, это те трюки, которые я ищу, чтобы решить эту проблему. – acfoltzer

ответ

4

Похоже, у вас есть хорошее объяснение, почему if делает чуть больше and и or. Но если вы можете обмануть и добавить lambda задержать фактический результат:

(define-syntax-rule (if c t e) ((or (and c (lambda() t)) (lambda() e)))) 
+0

Ницца; Мне нравится идея добавить тон лени. Любые мысли о том, как это возможно, без обмана? – acfoltzer

+0

лень не требуется. важно обернуть его во все, что заставляет его оценивать значение true, а затем извлечь его. – user102008

+0

. * Вам нужна * эта лень - другими словами, вам нужно, чтобы оболочка содержала * вычисление *, а не значение *. В противном случае вы не получите свойство short-circuiting, которое делает '(if #f (print-stuff) 1)' not print stuff. –

2

Попробуйте (or (and test conseq) (and (not test) altern)) как общий шаблон. Отрицая test во втором and, это гарантирует, что внешний дизъюнкция будет либо conseq#f если test верно, или #faltern если test ложно.

+2

Недостатком является то, что это может оценивать «тест» дважды – Sean

+0

Nice; локально связывающий «тест» и использование этого шаблона, похоже, будет работать.Интересно, возможно ли это без привязки? – acfoltzer

1

Это то же самое, как ответ Эли Barzilay, за исключением вместо того, обернув его в лямбда, я обернуть его в списке на 1-элементного

(if test conseq altern) => (car (or (and test (list conseq)) (list altern))) 

Кстати, Python до 2,5 имел точно такую ​​проблему , Не было красивого способа написать условное выражение (то есть test ? conseq : altern в C, что и есть if в Схеме) в Python. Самая простая попытка была

test and conseq or altern 

, который работал в большинстве случаев, но потерпели неудачу, когда conseq считается ложным в Python (то есть значение False, 0, пустой список, пустая строка и т.д.). Какая именно проблема вы обнаружили выше. Исправление было обернуть его в списке (не пустые списки всегда верно) и извлечь его снова:

(test and [conseq] or [altern])[0] 

который выглядит некрасиво. Вот почему они добавили синтаксис conseq if test else altern в Python 2.5.

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