Скомпилированный язык может быть гомографическим?

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

, Если у Вас есть односторонние зависимости, необходимо также перезагрузить все модули, которые зависят от перезагруженный модуль для избавлений от всех ссылок на старый код. И затем модули перезагрузки, которые зависят от перезагруженных модулей, рекурсивно.

, Если у Вас есть круговые зависимости, который очень распространен, например, когда Вы имеете дело с перезагрузкой пакета, необходимо разгрузить все модули в группе сразу. Вы не можете сделать этого с reload(), потому что это повторно импортирует каждый модуль, прежде чем его зависимости были обновлены, позволив старым ссылкам вползти в новые модули.

единственный способ сделать это в этом случае состоит в том, чтобы взломать sys.modules, который отчасти не поддерживается. Необходимо было бы пройти и удалить каждый sys.modules запись, Вы хотели быть перезагруженными на следующем импорте, и также удалить записи, значения которых None, чтобы заниматься проблемой реализации, чтобы сделать с кэшированием неудавшегося относительного импорта. Это не ужасно хорошо, но, пока у Вас есть полностью автономный набор зависимостей, который не оставляет ссылки вне его кодовой базы, это осуществимо.

, вероятно, лучше перезапустить сервер.:-)

27
задан Pinochle 6 August 2009 в 13:41
поделиться

9 ответов

«Гомоиконический» - это своего рода расплывчатая конструкция. «Код есть данные» немного яснее.

В любом случае, первое предложение в Википедии для Homoiconic не так уж и плохо. Он говорит, что язык должен иметь исходное представление с использованием своих структур данных . Если мы забываем «строки» как исходное представление (это тривиально и не настолько полезно, чтобы иметь полезную концепцию «гомоиконность»), тогда в Лиспе есть списки, символы, числа, строки и т. Д., Которые используются для представления исходного кода. Интерфейс функции EVAL определяет, над каким видом исходного представления работает язык. В данном случае Лисп - это не строки. EVAL ожидает обычного разнообразия структур данных, и правила вычисления Lisp определяют, что строка оценивается сама по себе (и, таким образом, не будет интерпретироваться как выражение программы, а просто строковые данные). Число также оценивает само по себе. Список (sin 3.0) - это список символа и числа. Правила оценки говорят, что этот список с символом, обозначающим функцию в качестве первого объекта, будет оцениваться как приложение функции. Есть несколько подобных правил оценки для данных, специальных операторов, макросов и функций. Вот и все.

Чтобы прояснить: в Лиспе функция EVAL определена над структурами данных Лиспа . Он ожидает структуру данных, оценивает ее в соответствии со своими правилами оценки и возвращает результат - снова используя свои структуры данных.

Это соответствует определению гомоиконности: исходный код имеет собственное представление с использованием типов данных Lisp.

Теперь самое интересное: не имеет значения, как реализован EVAL . Все, что имеет значение, это то, что он принимает исходный код с использованием структур данных Lisp, что он выполняет код и возвращает результат.

Итак совершенно законно, что EVAL использует компилятор .

(EVAL code)  =  (run (compile-expression code))

Так работают несколько систем Lisp, у некоторых даже нет интерпретатора.

Итак, «Homoiconic» говорит, что код SOURCE имеет представление данных. Он НЕ говорит, что во время выполнения этот исходный код должен быть интерпретирован или что выполнение основано на этом исходном коде.

Если код скомпилирован, ни компилятор, ни интерпретатор не нужны во время выполнения . Они понадобятся только в том случае, если программа хочет выполнить оценку или компилировать код во время выполнения - что часто не требуется.

Lisp также предоставляет примитивную функцию READ , которая переводит внешнее представление (S-выражения ) данных во внутреннее представление данных (данные Лиспа). Таким образом, его также можно использовать для преобразования внешнего представления исходного кода во внутреннее представление исходного кода. Lisp не использует специальный парсер для исходного кода - поскольку код - это данные, есть только READ.

Таким образом, его также можно использовать для преобразования внешнего представления исходного кода во внутреннее представление исходного кода. Lisp не использует специальный парсер для исходного кода - поскольку код - это данные, есть только READ.

Таким образом, его также можно использовать для преобразования внешнего представления исходного кода во внутреннее представление исходного кода. Lisp не использует специальный парсер для исходного кода - поскольку код - это данные, есть только READ.

35
ответ дан 28 November 2019 в 04:59
поделиться

В самом буквальном смысле C является гомоиконным. Вы можете получить доступ к представлению функции с помощью & functionName и выполнить данные с помощью somePtrCastToFnPtr (SomeArgs) . Однако это на уровне машинного кода, и без какой-либо поддержки библиотеки вам будет очень сложно работать. Какой-нибудь встраиваемый компилятор (я, кажется, помню, что это умеет LLVM) сделал бы его более практичным.

2
ответ дан 28 November 2019 в 04:59
поделиться

Проблема в том, что многие процессоры разделяют области инструкций и данных и активно предотвращают программы от изменения собственного кода. Такой код раньше назывался «вырожденным кодом» и считался очень плохим.

Интерпретаторы (и виртуальные машины) не имеют этой проблемы, поскольку они могут обрабатывать всю программу как данные, с единственным «кодом». "быть переводчиком.

1
ответ дан 28 November 2019 в 04:59
поделиться

да. lisp может быть скомпилирован в собственный двоичный файл

8
ответ дан 28 November 2019 в 04:59
поделиться

Lisp обычно компилируется. Были реализации с JIT-компиляторами вместо интерпретаторов.

Следовательно, нет необходимости иметь интерпретатор (в смысле «не компилятор») для языков «код есть данные».

2
ответ дан 28 November 2019 в 04:59
поделиться

Да; вам просто нужно вставить копию компилятора в среду исполнения языка. Chez Scheme - один из многих прекрасных компиляторов, которые делают именно это.

1
ответ дан 28 November 2019 в 04:59
поделиться

Языки, построенные на основе виртуальных машин (.net clr, jre ect), могут использовать передовые технологии, позволяющие генерировать код на лету. Одно из них - ИЖ ткачество. Хотя это не так ясно, как eval для ECMAScript / Lisp / Scheme и т. Д., Но он может в некоторой степени имитировать такое поведение.

Для примеров проверьте Castle DynamicProxy, а для более интерактивных примеров проверьте LinqPAD, F # Interactive, Scala interactive.

]
0
ответ дан 28 November 2019 в 04:59
поделиться

Мне кажется странным вопрос:

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

Машинный код dsm является хорошим моментом, но обеспечивает:

  1. Синтаксис и представленная семантика является гомоиконной
  2. . Перевод в форму более низкого уровня (машинный код, или интерпретируемый, или иначе) не удаляет никакой исходной семантики, тогда

, почему здесь важна реализация более низкого уровня?

Также:

скомпилированные языки без интерпретатора времени компиляции

Без какой-либо программы, интерпретирующей его, потребовалось бы быть родным для ЦП, поэтому ЦП '

3
ответ дан 28 November 2019 в 04:59
поделиться

Машинный код сам по себе гомоиконный, так что да.

Данные или инструкции - это всего лишь вопрос семантики (и, возможно, сегмент памяти, в котором они находятся).

2
ответ дан 28 November 2019 в 04:59
поделиться