2013-06-04 3 views
9

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

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

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

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

(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 

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

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

Если это неосуществимый/необоснованный запрос, то это только затвердевает в моей голове мысль о том, что Homoiconicity не является дискретным свойством, которое язык имеет или не имеет, это спектр, а Lisp не находится в край кровотечения. (В качестве альтернативы Lisp как Homoiconic, поскольку они приходят, и я ищу другой термин для описания самомодификации машинного кода)

+0

также, inb4 комментировать, что код на моем экране вряд ли изменится на моих глазах, потому что это просто какой-то текст на веб-странице. Если вы честно не понимаете, что я имею в виду и не троллинг, я попытаюсь прояснить еще кое-что :) – TheIronKnuckle

+0

Типичный машинный код не является «homoiconic», а язык ассемблера меньше. Хотя машинный код представляет собой массив бит, машинные языки не имеют инструментов для специфического управления массивами битов, которые представляют программы машинного языка. Например, учитывая массив бит, вы даже не знаете, где, скажем, начинается 17-я инструкция, если они не имеют точно такой же длины. Если вы вставляете код в шаблон, смещения ответвлений, которые пересекают точку вставки, должны быть пересчитаны и исправлены. Вам нужна большая библиотека подпрограмм, чтобы что-то сделать, и она не включена в машинный язык. – Kaz

+0

Языки машин ** действительно имеют инструменты для специфического управления массивами бит, которые представляют программы машинного языка. Каждый раз, когда вы используете инструкцию «store», это именно то, что происходит. – TheIronKnuckle

ответ

15

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

Общий Lisp реализация LispWorks предоставляет нам интерпретатор Лиспа:

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 

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

+1

haha ​​wow. Это потрясающе. Я искал что-то подобное для yonks. И я думаю, вам нечего мешать вам делать такие вещи за пределами REPL (так что вы могли бы иметь рекурсивную функцию, которая меняет себя снова и снова?) – TheIronKnuckle

+0

Обратите внимание, что это не переносимый Common Lisp, как FUNCTION- LAMBDA-EXPRESSION разрешено возвращать NIL. –

+2

@ThomasBartscher: true. Я также предполагаю, что это интерпретатор - тоже то, что не переносимо. Common Lisp относится не только к переносимому языку, но и к тому, где отдельные реализации имеют определенную степень свободы (Interpreter vs. Compiler, разработка и доставка, оптимизация, сборка мусора, ...). Просто выберите реализацию Common Lisp, которая имеет правильный набор функций. –

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