Вот если брать только С++ времени компиляции — пишут Тьюринг полный. Ну ОК, это по вопросу вычислений. А по вопросу интеграции с системой — что можно а чего нельзя?
Можно сделать assert — вывести сообщение и отменить компиляцию. А что-то еще можно? Файл создать — никак?
Здравствуйте, Shmj, Вы писали:
S>Вот если брать только С++ времени компиляции — пишут Тьюринг полный. Ну ОК, это по вопросу вычислений. А по вопросу интеграции с системой — что можно а чего нельзя?
S>Можно сделать assert — вывести сообщение и отменить компиляцию. А что-то еще можно? Файл создать — никак?
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, rg45, Вы писали:
R>>Коноплю тебе в компайл-тайм не нужно выращивать?
M>Судя по новостям с легалайзом на Украине — ему скоро захочется
Здравствуйте, rg45, Вы писали:
R>Коноплю тебе в компайл-тайм не нужно выращивать?
кстати вопрос не такой смешной. Открытием для меня стало, что файл открыть в расте таки можно. После этого мне кажется до конопли остался один шаг
use compile_time_create_file::create_file;
create_file!(
"migrations/users.sql",
"create table if not exists users (
id serial,
username varchar(128) not null,
password varchar(512) not null,
email varchar(256) not null,
enabled boolean not null default true
);
"
);
Просто всегда думал, что то, что можно сделать в Rust довольно легко добиться в С++. А вот нет. Правда создать файл можно в "pre-build actions", но это всё-таки не поддержка языка.
Здравствуйте, Shmj, Вы писали:
S>Вот если брать только С++ времени компиляции — пишут Тьюринг полный. Ну ОК, это по вопросу вычислений. А по вопросу интеграции с системой — что можно а чего нельзя?
S>Можно сделать assert — вывести сообщение и отменить компиляцию. А что-то еще можно? Файл создать — никак?
Перенаправь вывод компилятора в программу, интерпретирующую этот вывод и делай что угодно.
Не, ну серьёзно, 10/20 последних тем в форуме про Си++ и все — какие-то философские и алхимические изыскания джуна, который не умеет пользоваться гуглом. Реально загажен один из самых адекватных технических форумов.
Здравствуйте, SaZ, Вы писали:
SaZ>Не, ну серьёзно, 10/20 последних тем в форуме про Си++ и все — какие-то философские и алхимические изыскания джуна,
Есть же форум СВ — можно темы туда сносить, если не подходит по тематике. Вроде начальные вопросы не запрещены.
SaZ>который не умеет пользоваться гуглом. Реально загажен один из самых адекватных технических форумов.
Ну этот вопрос, наверное, да — можно сказать для поддержания разговора — можно было и в СВ спросить. Тут не было целью просто получить готовый ответ — а больше пофилософствовать на эту тему — тема вычислимости и доступа к системе, нужен ли доступ к системе коду времени компиляции.
Здравствуйте, Shmj, Вы писали:
S>Есть же форум СВ — можно темы туда сносить, если не подходит по тематике. Вроде начальные вопросы не запрещены.
Так если б ты просто вопросы задавал, без этих своих "философских" размышлений. У тебя же обычно вопросам предшествуют пласты какой-то дичи, после прочтения которой на вопросы отвечать уже не хочется.
Здравствуйте, Shmj, Вы писали:
S>Ну этот вопрос, наверное, да — можно сказать для поддержания разговора — можно было и в СВ спросить. Тут не было целью просто получить готовый ответ — а больше пофилософствовать на эту тему — тема вычислимости и доступа к системе, нужен ли доступ к системе коду времени компиляции.
Позадавать вопросы, ответы на которые тебе нафиг не нужны и пофилософствовать на темы, в которые тебе лень вникать
Здравствуйте, netch80, Вы писали:
S>> Файл создать — никак?
N>Зойчем?
Если расширить вопрос до более общего (доступ к системе и сокетам), то вот что может быть полезно:
1. Подключаться во время компиляции к СУБД и генерировать маппиги из мета-информации. Можно проверять статически заданные SQL-запросы на ошибки.
2. Парсить файлы на других языках и генерировать код исходя из этого. К примеру генерировать парсер из БНФ. Или код из IDL.
3. Запрашивать OpenAPI схему и генерировать код для неё..
По сути можно взять любой крупный проект и посмотреть, что там в скриптах компиляции происходит помимо, собственно, компиляции. Вот это всё можно засунуть в компилятор, раз уж мы его делаем полноценным программируемым окружением.
Здравствуйте, B0FEE664, Вы писали:
BFE>Может быть полезно для кодогенерации.
Для кодогенерации сущесвуют custom build steps, куда можно запихать что угодно и сгенерировать что угодно. Правда к С++ времени компиляции это имеет мало отношения. C++ времени компиляции — это седьмая фаза трансляции и единственно возможная кодогенерация в этот период — это генерация translation units, которую выполняет сам компилятор.
Здравствуйте, rg45, Вы писали:
BFE>>Может быть полезно для кодогенерации.
R>Для кодогенерации сущесвуют custom build steps, куда можно запихать что угодно и сгенерировать что угодно.
Только вот в некоторых случаях для это нужно иметь инструменты равные компилятору по сложности.
R> Правда к С++ времени компиляции это имеет мало отношения. C++ времени компиляции — это седьмая фаза трансляции и единственно возможная кодогенерация в этот период — это генерация translation units, которую выполняет сам компилятор.
Допустим у вас есть где-то в коде перечисление:
enum class ABC { a, b, c };
И для этого enum хотите написать код, который позволит пройти во всем значениям перечисления:
for(const auto e : { ABC::a, ABC::b, ABC::c}) /*...*/;
Всё хорошо, пока кто-то не добавит ещё одно значение в ABC:
enum class ABC { a, b, c, d };
После такого изменения цикл становится некорректным. Но если цикл рождает кодогенератор, то проблем нет. Делать такое в custom build steps затруднительно, а вот компилятор мог бы, но...
Здравствуйте, B0FEE664, Вы писали:
BFE>Допустим у вас есть где-то в коде перечисление: BFE>
BFE>enum class ABC { a, b, c };
BFE>
BFE>И для этого enum хотите написать код, который позволит пройти во всем значениям перечисления: BFE>
BFE>for(const auto e : { ABC::a, ABC::b, ABC::c}) /*...*/;
BFE>
BFE>Всё хорошо, пока кто-то не добавит ещё одно значение в ABC: BFE>
BFE>enum class ABC { a, b, c, d };
BFE>
BFE>После такого изменения цикл становится некорректным. Но если цикл рождает кодогенератор, то проблем нет. Делать такое в custom build steps затруднительно, а вот компилятор мог бы, но...
Нет необходимости убеждать меня в полезности кодогенерации — я сам на эту тему ммогу лекцию прочитать. Только при чем здесь C++ времени компиляции, которому посвящена данная тема? Давайте не будем заниматься подменой понятий.
BFE>>Допустим у вас есть где-то в коде перечисление: BFE>>
BFE>>enum class ABC { a, b, c };
BFE>>
BFE>>И для этого enum хотите написать код, который позволит пройти во всем значениям перечисления: BFE>>
BFE>>for(const auto e : { ABC::a, ABC::b, ABC::c}) /*...*/;
BFE>>
BFE>>Всё хорошо, пока кто-то не добавит ещё одно значение в ABC: BFE>>
BFE>>enum class ABC { a, b, c, d };
BFE>>
BFE>>После такого изменения цикл становится некорректным. Но если цикл рождает кодогенератор, то проблем нет. Делать такое в custom build steps затруднительно, а вот компилятор мог бы, но...
R>Нет необходимости убеждать меня в полезности кодогенерации — я сам на эту тему ммогу лекцию прочитать. Только при чем здесь C++ времени компиляции, которому посвящена данная тема? Давайте не будем заниматься подменой понятий.
А когда ещё? Во время компиляции код уже разобран (и известно где какие поля и функции), а иначе нам придётся парсить код ещё раз и не факт, что код будет рапарсен одинаково.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, rg45, Вы писали:
BFE>>>Может быть полезно для кодогенерации.
R>>Для кодогенерации сущесвуют custom build steps, куда можно запихать что угодно и сгенерировать что угодно. BFE>Только вот в некоторых случаях для это нужно иметь инструменты равные компилятору по сложности.
R>> Правда к С++ времени компиляции это имеет мало отношения. C++ времени компиляции — это седьмая фаза трансляции и единственно возможная кодогенерация в этот период — это генерация translation units, которую выполняет сам компилятор.
BFE>Допустим у вас есть где-то в коде перечисление: BFE>
BFE>enum class ABC { a, b, c };
BFE>
BFE>И для этого enum хотите написать код, который позволит пройти во всем значениям перечисления: BFE>
BFE>for(const auto e : { ABC::a, ABC::b, ABC::c}) /*...*/;
BFE>
BFE>Всё хорошо, пока кто-то не добавит ещё одно значение в ABC: BFE>
BFE>enum class ABC { a, b, c, d };
BFE>
BFE>После такого изменения цикл становится некорректным. Но если цикл рождает кодогенератор, то проблем нет. Делать такое в custom build steps затруднительно, а вот компилятор мог бы, но...
BFE>А когда ещё? Во время компиляции код уже разобран (и известно где какие поля и функции), а иначе нам придётся парсить код ещё раз и не факт, что код будет рапарсен одинаково.
Необязательно парсить, можно генерить из условного питона, где эти a,b,c и d задаются.
Здравствуйте, B0FEE664, Вы писали:
R>>Нет необходимости убеждать меня в полезности кодогенерации — я сам на эту тему ммогу лекцию прочитать. Только при чем здесь C++ времени компиляции, которому посвящена данная тема? Давайте не будем заниматься подменой понятий.
BFE>А когда ещё? Во время компиляции код уже разобран (и известно где какие поля и функции), а иначе нам придётся парсить код ещё раз и не факт, что код будет рапарсен одинаково.
Похоже, я чего-то не понял. А что за файлы будут генерироваться при этом? Компилятор будет генерировать какие-то файлы, которые сам же потом и будет обрабатывать что ли? Или Shmj будет генерировать какие-то файлы в компайл-тайме, а компилятор должен будет их подхватить и откомпилировать?
Здравствуйте, McQwerty, Вы писали:
S>>> Файл создать — никак?
N>>Зойчем?
MQ>А потом его #include.
Я, конечно, помню ещё, что когда язык крестовых шаблонов стал тьюринг-полным, он потеснил с пьедестала "самого извращённого функционального языка" находившегося там лет 30 m4, и он претендует на нишу, имеющую много общего.
Но если ставить в принципе задачу что-то сгенерировать из исходников в момент выполнения make, и не форсировать себе использование средств определённого типа — возможности резко расширяются.
Здравствуйте, rg45, Вы писали:
BFE>>А когда ещё? Во время компиляции код уже разобран (и известно где какие поля и функции), а иначе нам придётся парсить код ещё раз и не факт, что код будет рапарсен одинаково. R>Похоже, я чего-то не понял. А что за файлы будут генерироваться при этом? Компилятор будет генерировать какие-то файлы, которые сам же потом и будет обрабатывать что ли? Или Shmj будет генерировать какие-то файлы в компайл-тайме, а компилятор должен будет их подхватить и откомпилировать?
Вечность впереди — много или мало?
Считаю, что в конечном итоге из C++ должен получится монстр включающий все возможные техники и парадигмы программирования. Поэтому — да, рефлексия будет добавлена в том или ином виде. Добавить генерацию файлов в компайл-тайме — чем плохо? И чем плохо это делать через внешние файлы? У нас есть успешные примеры с внешними инструментами (тот же Qt). Как по мне, так это лучше сделать с помощью компилятора, чем внешнего инструмента.
Здравствуйте, B0FEE664, Вы писали:
BFE>Считаю, что в конечном итоге из C++ должен получится монстр включающий все возможные техники и парадигмы программирования.
Т.е. вы настолько оптимистичны, что считаете, что этого еще не случилось?
Здравствуйте, B0FEE664, Вы писали:
BFE>Считаю, что в конечном итоге из C++ должен получится монстр включающий все возможные техники и парадигмы программирования. Поэтому — да, рефлексия будет добавлена в том или ином виде. Добавить генерацию файлов в компайл-тайме — чем плохо? И чем плохо это делать через внешние файлы? У нас есть успешные примеры с внешними инструментами (тот же Qt). Как по мне, так это лучше сделать с помощью компилятора, чем внешнего инструмента.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, B0FEE664, Вы писали:
R>Нет необходимости убеждать меня в полезности кодогенерации — я сам на эту тему ммогу лекцию прочитать.
Посоветуйте тогда (оба ) ЯП с кодогонерацией, в той же нише, что и плюсы. Т.е. без виртуальной машины (не .Net/JVM/JS). Спрашиваю для расширения кругозора, без конкретной цели.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, B0FEE664, Вы писали:
BFE>>Считаю, что в конечном итоге из C++ должен получится монстр включающий все возможные техники и парадигмы программирования.
S>Т.е. вы настолько оптимистичны, что считаете, что этого еще не случилось?
Ну вот call/cc, например, в него не успели встроить. А ведь есть языки, где это база, через которую строится всё остальное.
Думаю, к C++41 вполне успеют.
Закостылять на корутинах и лямбдах можно, но путано и дорого.
S>PS. Простите, не удержался...
Здравствуйте, Alekzander, Вы писали:
A>Посоветуйте тогда (оба ) ЯП с кодогонерацией, в той же нише, что и плюсы. Т.е. без виртуальной машины (не .Net/JVM/JS). Спрашиваю для расширения кругозора, без конкретной цели.
Ты имеешь в виду ран-тайм кодогенерацию, наподобие дотнетовых Emit и CodeDOM, или же генерацию исходного текста программ?
Здравствуйте, rg45, Вы писали:
A>>Посоветуйте тогда (оба ) ЯП с кодогонерацией, в той же нише, что и плюсы. Т.е. без виртуальной машины (не .Net/JVM/JS). Спрашиваю для расширения кругозора, без конкретной цели.
R>Ты имеешь в виду ран-тайм кодогенерацию, наподобие дотнетовых Emit и CodeDOM, или же генерацию исходного текста программ?
Типа макросов Nemerle А если этот ЯП в итоге транспилируется в C++ (как сами плюсы изначально транспилировались в си), то я даже знаю, где применить
Здравствуйте, Alekzander, Вы писали:
A>Типа макросов Nemerle А если этот ЯП в итоге транспилируется в C++ (как сами плюсы изначально транспилировались в си), то я даже знаю, где применить
Здравствуйте, Alekzander, Вы писали:
R>>Ты имеешь в виду ран-тайм кодогенерацию, наподобие дотнетовых Emit и CodeDOM, или же генерацию исходного текста программ?
A>Типа макросов Nemerle
Из относительно массовых только rust наверно, там есть полноценные процедурные макросы, правда гораздо менее удобные чем в немерле, так как из коробки работают только с токенами, но есть библиотеки который их поднимают до уровня квазицитирования. С файловой системой, и даже с сетью, эти макросы отлично могут работать Разработчик показал, как получить SSH-ключ с помощью compile-time макроса в Rust в VSCode просто при открытии приложения
A>А если этот ЯП в итоге транспилируется в C++ (как сами плюсы изначально транспилировались в си), то я даже знаю, где применить
Тут разве что nim, там есть макросы близкие к процедурным и шаблоны уровня C++, еще возможно haxe но не помню как там с макросами. Оба умеют транслироваться в си, а nim и в с++.
Здравствуйте, netch80, Вы писали:
S>>Т.е. вы настолько оптимистичны, что считаете, что этого еще не случилось?
N>Ну вот call/cc, например, в него не успели встроить.
А что, call/cc -- это необходимое условие для того, чтобы язык считался монстром?
Одной россыпи UB в языке (как унаследованной из C, так и собственной) уже вполне достаточно. А если добавить сюда еще и список способов инициализации локальных переменных...
Здравствуйте, sergii.p, Вы писали:
SP>кстати вопрос не такой смешной. Открытием для меня стало, что файл открыть в расте таки можно. После этого мне кажется до конопли остался один шаг
Справедливости ради, это макрос. В константных функциях раста так не получится.
Здравствуйте, Alekzander, Вы писали:
R>>Нет необходимости убеждать меня в полезности кодогенерации — я сам на эту тему ммогу лекцию прочитать. A>Посоветуйте тогда (оба ) ЯП с кодогонерацией, в той же нише, что и плюсы. Т.е. без виртуальной машины (не .Net/JVM/JS). Спрашиваю для расширения кругозора, без конкретной цели.
Я про другие языки ничего не скажу, а вот в C/C++ кодогенерация применяется, но с помощью внешних инструментов (всякие там Lex и YACC). Как правило генерация производится на основании некого формального (на спец. языке) описания структуры/интерфейса/устройства/данных, которое подаётся на вход инструмента, а на выходе получается код на С/С++. Простейший вариант — это взять картинку и сгенерировать массив пикселей этой картинки вида: const unsigned int imageLogo[40][180] = {{61309,1309,61309,61309, ...};.
А вот если надо взять код на C++ и на его основе сгенерировать какой-то добавочный код, вот тогда это уже довольно редко бывает. На практике для этих целей применяется, наверное, только Qt moc. По крайней мере других таким инструментов я не использовал. Отчасти это понятно, так как однажды сгенерированный код можно просто добавить в проект, а отслеживание изменений переложить на программиста, но иногда хочется большего.
Здравствуйте, so5team, Вы писали:
S>>>Т.е. вы настолько оптимистичны, что считаете, что этого еще не случилось?
N>>Ну вот call/cc, например, в него не успели встроить.
S>А что, call/cc -- это необходимое условие для того, чтобы язык считался монстром?
Если вопрос ставится в стиле
BFE>>Считаю, что в конечном итоге из C++ должен получится монстр включающий все возможные техники и парадигмы программирования.
то да, монстр, в котором _все_ техники и парадигмы — без call/cc недостаточен.
С другой стороны, если не ограничиваться им, то это не необходимое, а достаточное условие — по крайней мере для тех 95-99% коллег, что на любую рекурсию начинают смотреть как на признак присутствия самого Люцифера.
S>Одной россыпи UB в языке (как унаследованной из C, так и собственной) уже вполне достаточно. А если добавить сюда еще и список способов инициализации локальных переменных...
Подозреваю, что кое-кто в комитете или рядом с ним думает, что этого недостаточно.
Большое спасибо за ответ. А можно я попрошу прямо здесь показать, на что они годятся? На двух актуальных примерах, обсуждавшихся на этих форумах в последнее время.
Вот в таком виде, не потеряв в производительности?
if (!(errno is in (
EAGAIN,
EWOULDBLOCK,
EINTR,
ENOSPC,
ENOBUFS,
ENOMEM
))
{
...
}
(Я понимаю, что дизайнер языков из меня так себе и синтаксис "is in", возможно, не лучшее решение, и если это ещё выразительнее можно записать, то я не против ).
На самом-то деле, шаблон тут довольно уместен. Может быть даже, это самое выразительное решение при объявлении переменной. Но, допустим в духе идеи того обсуждения, нам захотелось изобразить псевдовстроенный тип с ограничениями и каким-нибудь выразительным синтаксисом наподобие (более удачные вариации приветствуются):
a: int 1..100
Можно ли это сделать на rust и как? Много хорошего про него слышу, но так и не удосужился попробовать самому. Буду благодарен за примеры, чтобы понять, стоит ли изучать.
A>>А если этот ЯП в итоге транспилируется в C++ (как сами плюсы изначально транспилировались в си), то я даже знаю, где применить
FR>Тут разве что nim, там есть макросы близкие к процедурным и шаблоны уровня C++, еще возможно haxe но не помню как там с макросами. Оба умеют транслироваться в си, а nim и в с++.
Здравствуйте, Alekzander, Вы писали:
A>Здравствуйте, FR, Вы писали:
A>Большое спасибо за ответ. А можно я попрошу прямо здесь показать, на что они годятся? На двух актуальных примерах, обсуждавшихся на этих форумах в последнее время.
Сейчас с примерами разбираться времени нет, может позже посмотрю.
Но сразу скажу что rust далеко не nemerle или lisp и произвольно менять синтаксис везде не дает, весь измененный синтаксис должен быть внутри макроса, и токены все должны быть допустимыми в rust, но примерно такое:
вполне при этом позволяет. Подробнее про пример выше можно тут посмотреть.
Твои примеры вполне реализуемы на процедурных макросах, но с теми ограничениями что я описал кажутся не очень полезными. Ну и второй пример наверно проще и удобнее будет реализовать через new type idiom.
Здравствуйте, B0FEE664, Вы писали:
R>>Для кодогенерации сущесвуют custom build steps, куда можно запихать что угодно и сгенерировать что угодно. BFE>Только вот в некоторых случаях для это нужно иметь инструменты равные компилятору по сложности.
Так и есть.
Можно получить модель кода с помощью clang — у него есть режим дампа AST.
А так же есть тулзины (если поискать) по чтению этого AST и манипулированию им.
BFE>иначе нам придётся парсить код ещё раз и не факт, что код будет рапарсен одинаково
Тоже верно.
Если пользоваться cmake, то есть возможность взять именно те же аргументы командной строки и добавить нужный аргумент -ast-dump.
Насчёт ситуации с другими целевыми компиляторами — clang может выступать фронендом для msvc и gcc, что покрывает щепетильный вопрос однозначности парсинга для кодогенерации и для целевого образа.
Здравствуйте, Shmj, Вы писали:
S>Вот если брать только С++ времени компиляции — пишут Тьюринг полный. Ну ОК, это по вопросу вычислений. А по вопросу интеграции с системой — что можно а чего нельзя?
S>Можно сделать assert — вывести сообщение и отменить компиляцию. А что-то еще можно? Файл создать — никак?
- Что делаешь?
— Пишу игру на шаблонах.
— И как?
— Победил во время компиляции.
R>Ты имеешь в виду ран-тайм кодогенерацию, наподобие дотнетовых Emit и CodeDOM, или же генерацию исходного текста программ?
А вот в nim, например, и не то, и не другое. И не эмитирование, и не генерация текста. А генерация AST. Коммон-лисповская идеология, так полюбившаяся в свое время Полу Грему, да натянутая на нативно компилируемый язык — это ж пЭстня же ж Да и вообще, как говаривал один мудрый Лиспер, "язык, не позволяющий размышлять в терминах AST больше мешает, чем помогает". Если б ещё сам nim в целом не был глючноват (при переходе от версии к версии порой происходит полный трындец), то цены б ему не было.
R>Коноплю тебе в компайл-тайм не нужно выращивать?
Тссс, не подсказывай. А то кто-нибудь из прочитавших упорется, и действительно такое сделает. И если раньше программисты пинали балду во время компиляции, играя в пинг-понг, то теперь будут ждать урожая