1563
Обсуждение дизайна языков программирования (как новых, так и существующих). Литература: https://github.com/true-grue/Compiler-Development Создание и устройство компиляторов: @CompilerDev Для новичков: @pld_beginners
С одной стороны, cross-cutting concerns, наверное, лучше документировать в одном месте, а не в каждой функции. С другой стороны, эффект на файловую систему порождает не эта функция, а другой модуль, среда выполнения, или программа в целом.
Читать полностью…
Это работает до тех пор, пока обработчики — чистые функции (по бОльшей части). Но такие обработчики редко нужны. А когда обработчики начинают производить эффекты/трогать разделяемые ресурсы — всё начинает разваливаться феерическим образом.
Читать полностью…
Так мы докидываем ещё больше сложности и хрупкости, чтобы обойти проблему некомпозиционности обработчиков, с которой начали.
Читать полностью…
Тут проблемка же возникает из-за асинхронности, а не событий/обработчиков как таковых.
Должно быть const curValue = await globalStack.pop() (и асинхронный pop, и, быть может, перевод кнопки в состояние disable, пока данные не появятся).
А в примере был простой синхронный код. И обработчики событий там — простые функции. Если одна мешает другой — значит, их реализация нарушается какой-то контракт/соглашение/API.
в формальном смысле (речь же про формализацию?) у елфа таки есть аст, т.к. над ним вполне конкретно определена модель данных (система термов и отношений между ними), в виде экземпляра которой можно содержащуюся в нём информацию материализовать, и которая описывает "грамматику" этого аст; то что _на практике_ под аст "обычно понимаются" именно деревья разбора (как результаты работы "парсеров текста"), с формальной точки зрения не значительно
Читать полностью…
Кстати, я тут на досуге подумал, и осознал, что Constant Propagation/Folding только тем и занимаются, что подменяют Small-Step Semantics, особенно вкупе с Dead Parameter Elimination.
Например. Исходная функция:
λ x, (λ y, x + y*(2 - 2)) 42
λ x, x
Не. Речь идёт о том, что вот пусть у нас есть elf файл. Мы его в хекс редакторе создали, никакого аст никогда не было. В нём есть символ...
Читать полностью…
Или трассировка и сбор статистики по времени выполнения функции. В родственных АОР декораторах и PPX на это особо указывают — что нужно следить, чтобы разные декораторы/PPX не мешали друг другу.
https://ocaml-ppx.github.io/ppxlib/ppxlib/quick_intro.html
фраза
«Ambiguity when using several preprocessors due to lacking clear composition semantics»
Почему? Вот вызов. Ну syscall, конечно, скрыт в недрах стандартной библиотеки, но если мы уж доковыряли до неё, то там это будет вершина AST.
Читать полностью…
Ну, аспекты — это кмк вообще скорее философская штука. А придумывать им формальные определения — дело неблагодарное
Читать полностью…
Я последнее время думаю, что не надо давать формальное чёткое определение — уж больно разная практика.
Читать полностью…
Почему скорее упрощение, чем желание? Я, к примеру, не хочу, чтобы в расчётной задаче в семантику входило время выполнение операции + :: Int -> Int -> Int. И, кмк, мало кто хочет. Более того, несомненный успех ЯВУ означает, что нас в среднем интересует «более высокое».
Кажется, чтобы дать формальное опредение аспектам, Вам необходимо также уточнить определение семантики исходной программы — отрезать те части, которые кажутся незначительными. Точно также, как это делается при определении "оптимизации"
Читать полностью…
А есть ли пример для иллюстрации того, как один обработчик мешает другому? (кажется, такое возможно только при нарушении некоторого контракта)
Читать полностью…
Вот как раз когда назначение — сделать побочный эффект, тогда и не композятся. Композиционность обработчиков — это НЕ композиция функций. Это тогда, когда два корректных по отдельности обработчика (производящих нужные побочные эффекты), повешенные на одно и то же событие (а хоть бы и два разных) НЕ МЕШАЮТ друг другу, т.е. комбинация остаётся корректной.
Очевидно, для произвольных обработчиков событий это не выполняется даже в однопоточном JS.
тем временем "ватчпоинты", ставящиеся внешней тулой над кодом и пишущие что-то в лог - просто существуют, не трогая семантику программы
Читать полностью…
если про функцию в её контракте не сказано, что она порождает побочные эффекты на файловую систему, не должно ли нас в таком случае начать беспокоить то, что навешивание логирования методами АОП на что угодно будет контракты таких функций нарушать? "иногда" даже косвенно
Читать полностью…
Тут проблемка же возникает из-за асинхронности, а не событий/обработчиков как таковых.
Должно быть const curValue = await globalStack.pop()
pop тут самый обычный JS'овский синхронный. С ним никаких проблем нет. С push тоже. Проблемы возникают с порядком их вызовов.
Читать полностью…
Давайте забъём. По-моему, это предложение лучше.
Читать полностью…
Ок. Давайте с другой стороны. Spring security?
Читать полностью…
Ох. Ну это пограничное состояние. Тут дальше мы вваливаемся в терминологический спор об «исходном языке». Что это — машинный или ЯВУ? И дальше ещё relocations, расстановка которых тоже, в общем, АОР.
Читать полностью…
Дам несколько мыслей:
1. Иногда время исполнения хочется зашивать в семантику (условно, для симд)
2. Достаточно часто, операционная семантика слишком точная — нам нужно грубее. Ваш любимый пример с ostream.
3. В обратную сторону, не все желаемые свойства включены в операционную семантику (оптимизация не должна ломать внешние вызовы, например; или не должна ломать асм вставки)
Поэтому это вопрос сложный
Подумал, и осознал, что даже один обработчик может не композиться с самим собой. 😁 Ну, почти один...
Пусть мы написали обработчик, скажем, кнопки, который что-то берёт из контейнера, отправляет на сервер, и кладёт обратно результат:
function clickHandler() {
const curValue = globalStack.pop();
sendToTheServer(curValue, (response) => { globalStack.push(response.value); });
}
Это какая-то сильно сова на глобус натянута. Понятие аст здесь, кажется, слишком сложное и не нужно
Читать полностью…
Ну это и есть «часть вершин AST».
Читать полностью…
Кажется, хорошим примером здесь будет dprint. Там pointcut-ом является вызов любой функции (символа в бинарнике), или вызов сискола.
Читать полностью…
Ну, там ведь сложнее. Вообще, мы ещё, обычно, хотим, чтобы оптимизации не ломали всякие вызовы внешних функций/асм — а они в семантике вообще не отражены чаще всего.
Поэтому подобный аргумент плохой.
Время, память, стектрейсы, дебагинфо, гонки данных, взаимодействие с внешним миром... Оптимизация ломает слишком много всего, что в семантику может входить (то, что оно не входит — скорее упрощения, чем желанное)
Читать полностью…
Модель reactive streams/Rx тоже масштабируется — для простых случаев в одном потоке её можно реализовать очень "дёшево".
Читать полностью…
Это совсем другой масштаб по сравнению с простыми обработчиками. Далеко не всегда привлечение такой махины оправдано 🙃
Читать полностью…