Уровни гомоиконичности

Это продолжение моего предыдущего вопроса. Я не уверен, что код на Лиспе настолько же гомоичен, как и машинный код на архитектуре фон Неймана. Мне кажется очевидным, что в обоих случаях код представляется в виде данных, но также очевидно, что вы можете использовать это свойство гораздо более свободно в машинном коде, чем в Лиспе.

При работе с машинным кодом самоизменяющийся код настолько прост, что происходит постоянно, часто случайно и с (по моему опыту) веселыми результатами. При написании простой программы "печать чисел 0-15" у меня может быть ошибка "выключено одним" с одним из моих указателей. Я закончу тем, что случайно выгружу все, что находится в Регистре 1, в адрес в памяти, который содержит следующую инструкцию, и вместо этого будет выполнена случайная инструкция. (Всегда здорово, когда это что-то вроде "goto". Бог знает, где это закончится и что он будет делать после того, как это произойдет)

Там действительно нет разделения между кодом и данными. Все это одновременно инструкция (даже если это просто NOP), указатель и просто старое число. И код может измениться на ваших глазах.

Пожалуйста, помогите мне с сценарием Lisp, который я ломал голову. Скажем, у меня есть следующая программа:

(defun factorial (n)
   (if (<= n 1)
       1
       (* n (factorial (- n 1)))))
; -- Demonstrate the output of factorial --
; -- The part that does the Self modifying goes here –
; -- Demonstrate the changed output of factorial

Теперь я хочу добавить к этой программе некоторый код на Лиспе, который изменит * на a +, изменит <= на>>, вставит (+ 1 2 3) где-то там, и, как правило, вызовет функцию вверх. И тогда я хочу, чтобы программа выполнила полный беспорядок, который в результате.

Ключевой момент: если я не допустил фатальную ошибку в примере кода, вам разрешено только изменять -– More code goes here –- часть. То, что вы видите выше, это код. Я не хочу, чтобы вы цитировали весь список и сохраняли его в переменной, чтобы им можно было манипулировать и выплевывать как отдельную функцию с тем же именем; Я не хочу стандартного переопределения факториала как чего-то совершенно другого. Я хочу, чтобы этот код, прямо там, который я мог видеть на своем экране, изменился перед моими глазами, точно так же, как машинный код.

Если это невыполнимый / необоснованный запрос, то он только укрепляет мою мысль о том, что гомойконичность не является дискретным свойством, которое язык имеет или не имеет, а является спектром, а Лисп не на переднем крае. (В качестве альтернативы Лисп настолько же гомоичен, насколько и они, и я ищу какой-то другой термин для описания самодиагностики в машинном коде)

1 ответ

Решение

Это легко. Вам нужно только изменить представление списка. Все, что вам нужно, это интерпретатор Lisp.

Реализация Common Lisp LispWorks предоставляет нам интерпретатор Lisp:

CL-USER 137 > (defun factorial (n)
                (if (<= n 1)
                    1
                  (* n (factorial (- n 1)))))
FACTORIAL

CL-USER 138 > (fifth (function-lambda-expression #'factorial))
(IF (<= N 1) 1 (* N (FACTORIAL (- N 1))))

CL-USER 139 > (fourth (fifth (function-lambda-expression #'factorial)))
(* N (FACTORIAL (- N 1)))

CL-USER 140 > (setf (first (fourth (fifth (function-lambda-expression
                                             #'factorial))))
                    '+)
+

CL-USER 141 > (fourth (fifth (function-lambda-expression #'factorial)))
(+ N (FACTORIAL (- N 1)))

CL-USER 142 > (factorial 10)
55

CL-USER 143 > (setf (first (fourth (fifth (function-lambda-expression
                                             #'factorial))))
                    '*)
*

CL-USER 144 > (factorial 10)
3628800

Вот пример, где функция модифицирует себя. Чтобы сделать это немного проще, я использую функцию Common Lisp: она позволяет мне писать код, который представляет собой не просто вложенный список, а график. В этом случае функция может получить доступ к своему собственному коду:

CL-USER 180 > (defun factorial (n)
                (if (<= n 1)
                    1
                  (progn 
                    (setf (first '#1=(* n (factorial (- n 1))))
                          (case (first '#1#)
                            (+ '*)
                            (* '+)))
                    #1#)))
FACTORIAL

Выше функции альтернативно использует + или же * изменив его код.

#1= является меткой в ​​выражении, #1# затем ссылается на этот ярлык.

CL-USER 181 > (factorial 10)
4555

В более ранние времена (70-е /80-е) в некоторых группах Lisp разработчики использовали не текстовый редактор для написания кода на Lisp, а структурный редактор. Команды редактора напрямую меняли структуру кода на Лиспе.

Другие вопросы по тегам