Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Почему программирование / другая инженерия?
Anonymous Poll
41%
Ради денег - если не будут достойно платить, то не буду ничего кодить, чисто бизнес
36%
Просто по-кайфу - буду кодить даже если это никому не нужно или даже если за это придется платить
23%
Ко мне не относится / не инженер
This media is not supported in your browser
VIEW IN TELEGRAM
Решил я к Новому году удочерить вот эту малышку из приюта - ее бросили, а ей всего 4 недели. Теперь и мне будет повеселее, и у девочки появится новый дом. По своей традиции я всегда называю домашних животных в честь небесных тел - Марсик, Плутончик, а её теперь зову Ио, в честь спутника Юпитера. Пожелайте малышке скорейшей адаптации:)
Хочу запостить сюда перевод одного моего поста с реддита, который достаточно хорошо зашел. Неинженеры, скипайте, я человеческий язык тут не юзал.
- - -
Всем привет,
На данный момент я работаю над своим языком программирования (Системный язык, Plasm, но сейчас не об этом). Пока я работал над HIR->MIR->LLVM-IR преобразованиями, я начал задумываться о фундаментальной асимметрии в том как мы проектируем языки.
Практически во всех языках программирования у нас есть следующие определяемые пользователем категории первого порядка:
* Данные: структуры, классы, перечисления.
* Функции: вход->выход логика.
* Переменные: хранение и псевдонимы привязок.
* Операторы: Мы можем переопределять поведение
Однако операторы управления потоком (такие как if-elif-else, do-while, for-in, switch-case) строго зашиты в семантику языков. Другими словами, вы не можете переопределить, например, понятие "цикл" на фундаментальном уровне.
Вы можете возразить: "На самом деле мы можем это все делать в Swift/Kotlin/Scala".
Хотя эти языки позволяют использовать синтаксис, который выглядит словно кастомные операторы управления потоком, это на самом деле просто синтаксический сахар вокруг обычных функций, и под капотом они все равно опираются на жестко зашитые примитивы (вроде while или if).
Например, в Swift
Хотя подобные трюки можно проделать и в Kotlin (через
У меня есть вот такая фантазия: "Что если вместо синтаксического сахара мы введем новую категорию
Это могла бы быть, например, конструкция со специфичными синтаксическими правилами, которые позволили бы нам описать любой оператор управления потоком через явное определение как он будет транслироваться в LLVM CFG (Граф управления потоком). Это вовсе не означает, что мы должны позволять пользователю открыто использовать сырые
Представьте, что вы можете определить цикл
Это все приводит меня к нескольким вопросам, которые мне бы хотелось тут обсудить:
1. Реально ли определить такой набор правил описания потока, который был бы достаточно гибким для описания таких сложных операторов как pattern matching? (обработка именованных привязок, множества путей выхода и структурное сопоставление с compile time гарантиями)?
2. Можем ли мы описать
Кто нибудь пытался создать строго-типизированные, определяемые пользователем операторы управления потоком, которые строго ложатся в узлы CFG, а не как макросы/замыкания/сахар? Буду рад почитать критику, референсы к существующим попыткам или причины почему это ужаснейшая идея:)
- - -
В принципе на все эти вопросы мы нашли ответы, но если кто то захочет написать свои идеи в комментах, то я буду рад их почитать;)
- - -
Всем привет,
На данный момент я работаю над своим языком программирования (Системный язык, Plasm, но сейчас не об этом). Пока я работал над HIR->MIR->LLVM-IR преобразованиями, я начал задумываться о фундаментальной асимметрии в том как мы проектируем языки.
Практически во всех языках программирования у нас есть следующие определяемые пользователем категории первого порядка:
* Данные: структуры, классы, перечисления.
* Функции: вход->выход логика.
* Переменные: хранение и псевдонимы привязок.
* Операторы: Мы можем переопределять поведение
<<, +, ==.Однако операторы управления потоком (такие как if-elif-else, do-while, for-in, switch-case) строго зашиты в семантику языков. Другими словами, вы не можете переопределить, например, понятие "цикл" на фундаментальном уровне.
Вы можете возразить: "На самом деле мы можем это все делать в Swift/Kotlin/Scala".
Хотя эти языки позволяют использовать синтаксис, который выглядит словно кастомные операторы управления потоком, это на самом деле просто синтаксический сахар вокруг обычных функций, и под капотом они все равно опираются на жестко зашитые примитивы (вроде while или if).
Например, в Swift
@autoclosure позволяет нам передать условие как неявное замыкание, а блок кода мы можем передать как замыкание, написанное вне списка аргументов. Это выглядит симпатично, но внутренне это просто обертка вокруг стандартного цикла:func until(_ condition: @autoclosure () -> Bool, do action: () -> Void) {
while !condition() {
action()
}
}
var i = 0
until(i == 5) {
print("Iter \(i)")
i += 1
}
Хотя подобные трюки можно проделать и в Kotlin (через
inline в функции) или в Scala (через : => синтаксис), это всегда просто абстрагирование уже имеющихся примитивов.У меня есть вот такая фантазия: "Что если вместо синтаксического сахара мы введем новую категорию
flow первого порядка?"Это могла бы быть, например, конструкция со специфичными синтаксическими правилами, которые позволили бы нам описать любой оператор управления потоком через явное определение как он будет транслироваться в LLVM CFG (Граф управления потоком). Это вовсе не означает, что мы должны позволять пользователю открыто использовать сырые
goto операторы везде, это скорее про структурированный способ определить как совершаются прыжки между блоками кода.Представьте, что вы можете определить цикл
while не просто как ключевое слово языка, а как импортируемую структуру с внутренней реализацией через более простые фундаментальные сущности с возможностью их прочитать через "Go to definition", которая явно определяет точки входа, выхода и логику переходов.Это все приводит меня к нескольким вопросам, которые мне бы хотелось тут обсудить:
1. Реально ли определить такой набор правил описания потока, который был бы достаточно гибким для описания таких сложных операторов как pattern matching? (обработка именованных привязок, множества путей выхода и структурное сопоставление с compile time гарантиями)?
2. Можем ли мы описать
async/await/yield полностью как кастомные операторы потока? Когда мы делаем if/else, мы производим прыжки между двумя локальными блоками кода, а когда мы делаем await, мы по сути тоже делаем прыжок, просто не локально, а за пределы текущего контекста функции (в событийный цикл или планировщик) и объявляем точку возврата. Вместо того чтобы рассматривать асинхронность как преобразование конечного автомата, жестко заданное в компиляторе, можем ли мы определить асинхронность просто как межконтекстные прыжки?Кто нибудь пытался создать строго-типизированные, определяемые пользователем операторы управления потоком, которые строго ложатся в узлы CFG, а не как макросы/замыкания/сахар? Буду рад почитать критику, референсы к существующим попыткам или причины почему это ужаснейшая идея:)
- - -
В принципе на все эти вопросы мы нашли ответы, но если кто то захочет написать свои идеи в комментах, то я буду рад их почитать;)
1 5 4 2
Please open Telegram to view this post
VIEW IN TELEGRAM