Лист звичайний, 58 символів
#1=(let((*print-circle* t))(print'(write '#1# :circle t)))
... або 24 символи, якщо ви не заперечуєте, якщо *print-circle*
глобально встановлено T
:
#1=(print '(write '#1#))
Надруковане представлення коду читається як циклічна структура, де #1#
вказується на клітинку, що йде проти #1=
. Ми цитуємо програми так, щоб вони не виконувалися. Оскільки *print-circle*
це T, REPL піклується про випромінення таких змінних читачів під час друку; ось що друкує вищезгаданий код і повертає:
#1=(write '(print '#1#))
Коли ми оцінюємо наведений вище код, він друкує:
#1=(print '(write '#1#))
Якщо ви хочете дотримуватися значення за замовчуванням для *print-circle*
, яке NIL у відповідній реалізації, вам доведеться тимчасово відновлювати змінну:
#1=(let((*print-circle* t))(print'(write '#1# :circle t)))
Всередині тіла LET ми друкуємо речі з *print-circle*
буквою T. Отже, ми отримуємо:
#1=(write
'(let ((*print-circle* t))
(print '#1#))
:circle t)
Як бачите, нова програма не відновлює *print-circle*
, але оскільки ми використовуємо write
, що викликається функцією низького рівня print
, ми можемо передавати додаткові аргументи, такі як :circle
. Потім код працює, як очікувалося:
#1=(let ((*print-circle* t))
(print '(write '#1# :circle t)))
Однак вам потрібно виконати вищезазначені програми як сценарій, а не всередині REPL, оскільки, хоч ви друкуєте речі, піклуючись про кругові структури, і те, write
і print
також повертає значення, що друкується; і в REPL за замовчуванням значення також друкується, але поза динамічним контекстом, де *print-circle*
T.