Комментарии 138
В последнем семестре университета я выбрал курс компиляторов CS444. Там каждая группа из 1-3 человек должна была написать компилятор из существенного подмножества Java в x86.
а можно поподробнее о задаче, какие там точно действия после AST, желательно на русском, может и я на питоне что то накалякаю, сравним. Всё думаю о написании универсального компилятора, с контролем юзера над действиями и типом результата…
Её компилятор состоял из 4581 строки
для питона — гигантский проэкт, может там всё таки имеется флуд?
кстати с eval нечестно, но прелесть питона в том что там за строк 10 пишется свой eval
Другой пример мощи метапрограммирования и динамической типизации — 400-строчный файл visit.rs, это в основном повторяющийся шаблонный код, реализующий визитора на куче структур AST. В Python это может быть короткая функция примерно на 10 строк, которая рекурсивно интроспектирует поля узла AST и посещает их (используя атрибут __dict__).
А разве нельзя в другом языке сделать стирание типов например один класс ASTNode, с присваиванием функций даже java 8 там может, вместо того чтоб расписывать флуд, чем являются паттерны програмирования
Как поклонник Rust и статически типизированных языков в целом, я склонен отметить, что система типов очень полезна для предотвращения ошибок и для производительности.
Проверять ошибки можно, а при непредсказуемой структуре нужно в рантайме, в python это элегантно делается декоратором, при этом вы имеете приимущество встраивания любых своих проверок и возможностью включать и выключать по желанию. Собсветнно я сторонник включения / выключения проверки типов во желанию.
Это перевод, так что вряд ли вам расскажут подробнее. :)
The overall project for the course is to write a compiler from Joos 1W, a fairly large subset of Java, to i386 assembly language (the Netwide Assembler dialect).
Возможно даже можно будет найти открытые тесты.
> состоял из 4581 строки
для питона — гигантский проэкт
Забавное мнение. Расскажите это любому не hello world проекту на питоне
2.
главное не производительность а качество кода.это как раз та причина почему много есть УГ приложений, например, Skype, Dropbox и список будет большим, которые тащат за собой фреймворки с кучей оверхеда, а в случае Skype вообще не нативный Electron и потом адово тупят и тормозят даже на мощном железе, а на
Главное и производительность и качество кода и архитектура, нельзя забивать на производительность и эффективность. Именно поэтому сейчас Android убивает всё что убирается в фон, а некоторые производители убивают даже то что только что было использовано ибо ПО превратилось в унылое неповоротливое, тормозящее и выжирающее батарею биоразложимое ясделие.
А длины строк не сравнивали? Или, может быть, размер по диагонали, скажем, программа на Python диагональю 52".
Необходимость дублировать все сигнатуры в заголовочных файлах, чего нет в Rust.
Это неверно. Такой необходимости нет.
Необходимости конечно нет, но разбиение на реализацию/объявление заметно улучшает читаемость, и ускоряет компиляцию. Это слишком серьезные преимущества, чтоб игнорировать их в проекте на несколько тысяч строк.
Необходимости конечно нет, но разбиение на реализацию/объявление заметно улучшает читаемость, и ускоряет компиляцию.
А чего же их не разделяют в rust? Да и много где ещё. Подобные рассуждения не работают, вообще. Вы либо последовательно применяйте это ко всем языкам, либо не применяете вообще.
заметно улучшает читаемость
Это догмат. Лично для меня это ничего и никак не улучшает, как и для пользователей тысяч других языков, где нет этого разделение. К тому же не каждый С++-код можно разделить, а современный С++ разделить вообще почти нельзя.
и ускоряет компиляцию.
Это попросту глупость разоблачённая уже давно. Как-то ускорение есть лишь в очень редких случаях, либо на очень большой кодовой базе. Вернее даже не ускорение, а просто возможность распараллелить сборку.
К тому же, такого разделение в rust нет и там собирается всё модульно. Опять же, либо будьте последовательны и применяйте это ко всем языкам, либо не применяйте вообще.
Это слишком серьезные преимущества, чтоб игнорировать их в проекте на несколько тысяч строк.
Повторю, они игнорируются в «несколько тысяч строк на rust» и проблем не вызывают, как и в тысячах других языков.
А чего же их не разделяют в rust? Да и много где ещё. Подобные рассуждения не работают, вообще. Вы либо последовательно применяйте это ко всем языкам, либо не применяете вообще.
Не знаю :) Это вопрос к авторам дизайна языка.
Это догмат. Лично для меня это ничего и никак не улучшает, как и для пользователей тысяч других языков, где нет этого разделение.
На мой субъективный взгляд, при чтении кода некоторого модуля, проще сначала прикинуть что в этом модуле вообще находится, и только потом переходить к чтению реализаций. Читать протянку из смеси объявлений и реализаций не очень удобно. Эта проблема частично решается умными IDE в которых есть folding реализаций, конечно.
Да это мое субъективное мнение.
современный С++ разделить вообще почти нельзя.
А можно пример?
Это попросту глупость разоблачённая уже давно.
Было бы здорово увидеть пример.
Как-то ускорение есть лишь в очень редких случаях, либо на очень большой кодовой базе. Вернее даже не ускорение, а просто возможность распараллелить сборку.
Я не то чтобы спец, но предположим у вас в реализации функции не какая-нибудь банальщина, а инстанцирование тяжелых линейных солверов из Eigen, приправленных expression templates. В этом случае раздельная компиляция просто жизненно необходима. И это не то чтобы прям редкий случай, заметная доля проектов с С++ это числодробилки, в которых постоянно возникает подобная ситуация.
Если что, я не то чтобы топлю за Rust. Сам пишу на С++ и люблю его умеренной любовью.
Ну ваши претензии не работают в рамках логики автора, да и в моей тоже.
А можно пример?
Всё что связано с шаблонами. Разделять то же auto не имеет смысла, т.к. типы по-сути неизвестен. Много примеров.
Было бы здорово увидеть пример.
chromium.googlesource.com/chromium/src/+/lkgr/docs/jumbo.md
Я не то чтобы спец, но предположим у вас в реализации функции не какая-нибудь банальщина, а инстанцирование тяжелых линейных солверов из Eigen, приправленных expression templates. В этом случае раздельная компиляция просто жизненно необходима. И это не то чтобы прям редкий случай, заметная доля проектов с С++ это числодробилки, в которых постоянно возникает подобная ситуация.
Вам это никак не поможет. Это поможет только в том случае, если вы обернёте шаблонное api в c-api и уже с ним будете работать. Но будет уже не С++. Если же ваша логика будет так же шаблонной и так же использовать какую-то логику из библиотеки в cpp-файле, то это ничего не даст.
В современном С++-коде код не разбивается(в силу нежелания этого делать и в силу невозможности этого сделать). Существует тысячи ho-библиотек и тот же stdlib так же является ho-библиотекой.
Таким образом в каждом вашем cpp-файле будет 1% вашего кода и 99% заинклюженого. Таким образом компилятор будет делать лишнюю работу, собирая тысячи раз одно и те же инклюды.
Просто для понимания сделайте подобный бенчмарк:
$ cat a.cpp
#include <iostream>
void a() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
$ cat b.cpp
#include <iostream>
void b() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
$ cat c.cpp
#include <iostream>
void c() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
$ cat main.cpp
#ifdef HO
#include "a.cpp"
#include "b.cpp"
#include "c.cpp"
#else
void a(); void b(); void c();
#endif
int main() {
a(); b(); c();
}
$ time g++ a.cpp b.cpp c.cpp main.cpp
real 0m0,466s
user 0m0,398s
sys 0m0,068s
$ time g++ main.cpp -DHO
real 0m0,178s
user 0m0,152s
sys 0m0,026s
$ time clang++ main.cpp -DHO
real 0m0,684s
user 0m0,589s
sys 0m0,046s
$ time clang++ a.cpp b.cpp c.cpp main.cpp
real 0m1,831s
user 0m1,721s
sys 0m0,100s
И чем сложнее будут инклюды — тем хуже ситуация будет с раздельной компиляцией. Оно будет почти всегда медленнее. И единственное для чего может потребоваться раздельная компиляция — это параллельная сборка большой кодовой базы. Но это явно не тот случай. Да и в том случае нужно будет модульное разделение, а не разделение по-файлам.
Ну ваши претензии не работают в рамках логики автора, да и в моей тоже.
Ну у меня все началось не с претензий, а с попытки обосновать, почему в production ready c++ коде хорошо разделять объявления и реализацию.
chromium.googlesource.com/chromium/src/+/lkgr/docs/jumbo.md
Прикольно, почитаю, спасибо.
Всё что связано с шаблонами. Разделять то же auto не имеет смысла, т.к. типы по-сути неизвестен. Много примеров.
Если вы про auto в сигнатуре, то лично я бы предпочел видеть там полноценный тип/шаблон. Да, не во всех ситуациях это будет красиво, но в большинстве — снимет кучу головной боли при чтении кода.
Да, шаблоны вполне себе разбиваются. Не на .h и .cpp, конечно, но на блоки объявления и реализации — вполне.
Вам это никак не поможет. Это поможет только в том случае, если вы обернёте шаблонное api в c-api и уже с ним будете работать. Но будет уже не С++.
Я про случаи когда
«MyFuncs.h»
Eigen::VectorXf someHeavyFunction(const Eigen::VectorXf &someArg);
«MyFuncs.cpp»
Eigen::VectorXf someHeavyFunction(const Eigen::VectorXf &someArg)
{
// Put some heavy template stuff here
}
Вполне себе С++, вполне себе хороший способ убрать компиляцию тяжелых частей в локализованные .cpp. Кроме прочего, таким образом можно уменьшить количество инклудов которые расползутся по проекту, ставя их только в .cpp
Пример интересный, спасибо, но не уверен что все это так же хорошо масштабируется на относительно большие проекты
Если вы про auto в сигнатуре, то лично я бы предпочел видеть там полноценный тип/шаблон. Да, не во всех ситуациях это будет красиво, но в большинстве — снимет кучу головной боли при чтении кода.
Да, шаблоны вполне себе разбиваются. Не на .h и .cpp, конечно, но на блоки объявления и реализации — вполне.
Это будет некрасиво в случае использования современного С++-кода. Современный С++-код полагается на типизацию и сложные типы, которые не так-то просто вывести руками. И именно auto убирает все эти проблемы.
К тому же подобный код ненужно читать. 1min / 1s — вы же не будите руками писать тип? И вам ненужно при чтении знать тип. Задача системы типов сделать таким образом, что-бы вы не смогли написать 1min * 1s;
К тому же, выводит типы задача ide. Как и задача компилятора(ide) проверять синтаксическую корректность кода. Ненужно это делать за них. Это пустая трата сил на то, что реализуется автоматикой. Всё что автоматизируется должно быть автоматизировано.
Я про случаи когда
Ну это просто си-api.
Вполне себе С++, вполне себе хороший способ убрать компиляцию тяжелых частей в локализованные .cpp. Кроме прочего, таким образом можно уменьшить количество инклудов которые расползутся по проекту, ставя их только в .cpp
Ещё раз. Если ваша библиотека ho, то вы никаким образом подобное не сделаете. Если вы сделаете шаблонное api, то его нельзя будет засунуть в cpp. Вы можете сделать только сишное api.
Таким образом мы просто сделаете обёртку над шаблонной ho-библиотекой. Удобство сишного api крайне сомнительно в случае какой-то обобщённой логики. А такой логики в современной С++ навалом.
Пример интересный, спасибо, но не уверен что все это так же хорошо масштабируется на относительно большие проекты
Я думаю, что хром является «относительно большим проектом». Там всё так же работает. Именно это они и сделали.
Что за бред?
Я даже больше скажу, его еще и из dll можно экспортировать, если типы с которыми может быть инстанцирован шаблон, заранее известны) У нас в проекте это активно используется, для шаблонов, которые используются с 2-3-4 типами.
«есть ограничения» != «нельзя».
Что за бред?
Бред это ваши рассуждения вызванные вашем же непониманием. Шаблон нельзя никуда эспортировать по определению. Эспортировать куда-то можно инстанс.
У нас в проекте это активно используется, для шаблонов, которые используются с 2-3-4 типами.
Что за бред? Во-первых 2-3-4 типа это не шаблон, у шаблона нету никаких ограничений. Во-вторых эспортируются не шаблоны, а инстансы.
Узнайте разницу между первым и вторым перед тем как кричать «бред».
современный С++ разделить вообще почти нельзя.
Я думаю, имелись ввиду inline, constexpr и шаблонные функции/классы.
Затем сравнил с компилятором на C++, и там вполне ожидаемо компилятор был примерно на 30% больше
Что это за ангажированные намёки ничем не обоснованные? Это сравнение, либо пропаганда?
Rust (основа для сравнения)
На каком основании это основа, а не это:
Rust (другая группа): трёхкратный размер из-за иного дизайна!
Почему эта разница в одном случае описывается дизайном, а в другом непонятным набором слов?
Я не очень глубоко копался в этих различиях по размеру. Предполагаю, это в основном объясняется:
А раньше же было «ожидаемо», а теперь «не копался», «не знаю»? Зачем что-то утверждать, если при этом ничего не знать?
Отсутствие типов sum и сопоставлений с образцом в C++, которые мы широко использовали и которые были очень полезны.
Никакое «сопоставлений с образцом» не является чем-то необходимым и в 95% случаев сливает более мощной концепции визиторов. В С++ есть исключения и ненужно матчить каждую функцию. К тому же, с чего вдруг в С++ нету сумтипов?
В рамках той же концепции визиторов С++ обладаем куда большими преимуществами. В rust нету перегрузки функций, нету шаблонов. Для реализации чего-то уровня С++-перегрузки требуются генерик трейты, тонна бойлерплейта и даже тогда это не будет чем-то равным.
Необходимость дублировать все сигнатуры в заголовочных файлах, чего нет в Rust.
То, что это попросту обман я уже писал. Необходимость что-то там дублировать обусловлена разделением на h/cpp-файлы. Никак не обусловлена С++ и это разделение может не использоваться.
с оговоркой, что они помещают реализации множества небольших функций в заголовочные файлы
Какая разница какие функции? К тому же, тут явно видно взаимные противоречия.
чтобы уменьшить дублирование сигнатур ценой более длительного времени (именно поэтому я не могу измерить чистые накладные расходы на строки в заголовочных файлах).
Это просто глупость несусветная. Это мифология, которую была опровергнута уже тысячи раз. Особенно хромом. Уплотнение кода способствует ускорению компиляции т.к. инклюды в С++ тяжелые и компилятор делает ненужную работу каждый раз обрабатывая один и тот же код в каждом cpp-файле.
К тому же, уровень владения языком представителей С++-лагеря крайне скудны(судя по тексту). В С++ непросто так появилось ho и причины тому просты — шаблонный код попросту нельзя разделить. Попытки были и все они не имели успеха.
Таким образом из этого можно сделать вывод, что там не было никакого С++, а был типичный студенческий С/С++ начального уровня.
8733 строк
Никак не могут компилироваться секунды. К тому же сравнение скорости компиляции на разном железе меня так же удивляют. А так же меня удивляет отсутствие информации об компиляторе и какой-то конкретики в целом.
Опять же. Кода мы не видим. Никаких измерений нет. Есть «одна бабка сказала» и какие-то ничем не обоснованные заявления. Прослеживается явная ничем не обоснованная ангажированность и двойные стандарты.
есть, есть std::variant, которым пользуется примерно никто
Это ничего не значит, да и попросту враньё. На это я могу ответить: есть rust|haskell, которыми пользуется примерно никто.
PS Опять табун раст-адептов набежал и начал гадить в карму.
Спросил у автора (т.к. это был перевод). Вот его ответ:
"As far as I know my friend didn’t use the new visitor feature."
Вообщем там наверно обходились enum + switch + cast/union.
К тому же сами рассуждения не имеют смысла. Единственное что может pm «бесплатно» — это switch. Всё что далее — это непредсказуемая лапша. К тому же почти всё это реализуется по аналогии с visit/variant. Правда никому ненужно.
Описание мапы будет всегда лучше. К тому же С++ может без проблем хоть phf в компилтайте сгенерировать.
Реализовать синтаксис схожий в pm так же можно. Интернет завален подобным. Правда, как я уже говорил, спросом не пользуется т.к. в подавляющем большинстве случаев бесполезно.
Сливает по какому критерию? Что по выразительности, что по числу строк кода оно, наоборот, уделывает.
Вот зачем писать эти лозунги глупые, если даже сам автор говорит о том, что визиотор уделывает pm, по крайне мере в его кейс. Да и почти в любом другом кейсе.
По какому критерию — по любому. Ваш критерий «по стракам» несостоятелен. Там уже выше кидали статью в которой автор «больше строк» не нашел, да и нейти их. К тому же искал он их в заведомо подложном кейсе. Критерий «по выразительности» так же несостоятелен, т.к. перегрузка куда более выразительна, нежели match.
Причины очевидны. Перегрузка может быть шаблонной, может быть частично шаблонной. Для перегрузки можно использовать композицию из существующих функций/типов.
match существует в rust и подобных языках лишь по одной причины — они крайне примитивных. В них нет шаблонов, перегрузки, компилтайм-вычислений, параметров-значения даже для генериков. В них попросту невозможно написать что-то типа overloaded-композитора, либо visit.
И самое интересное, как только будет реальная задача. Обход того же дерева — на нём будет очевидна вся несостоятельность pm. Что нам и сообщает автор. Но даже визиторы на rust будут написаны убого, т.к. нету перегрузки. Это будет тонна лапши на генерик-трейтах.
Как вы на визиторах замачтитесь на значение без того, чтобы городить тонны ифов?
Это ненужно. Для случае уровня свича есть свич. Реализовать тот же визитор для чего угодно — не является проблемой. Вообще визитор ничего не матчит, матчит перегрузка. Она уже есть на уровне языка.
тонны ифов?
Я бы в контексте раста об этом вообще не заикался. Как там не обработать ошибку без тонны ифов? Из-за тонны ифов раст-методичка даже nullptr из аллокатора игнорирует. А что, памяти нету — можно падать. Надёжность она такая. Особенно смешно выглядят рассуждения раст-адептов про «как вы можете игнорировать NULL у malloc».
Тут, кстати, видно уровень состоятельности ЦА. Как адепты бегут плюсовать какие угодно лозунги(ничем не обоснованные), лишь бы они соотносились с их верой.
Ну естественно, если автор пишет, что визитор лучше паттерн-матчинга, то это авторитетное мнение, а если кто-то пишет, что паттерн-матчинг лучше визитора, то это глупые лозунги и растопропаганда.
У вас методичка течёт. Что-то я не вижу от вас разоблачений автора и обсуждения того, какой же он дурак со своими тезисами. Чего же вы гадите мне, а не гадите автору?
Я не хочу обсуждать растовский матч, впрочем, я его не знаю. Давайте обсуждать паттерн-матчинг в более функциональных языках,
Меня не интересует «функциональных языках» существующие только для написания хелвордов, хотя и хелворд вы не осилили на нём написать. Когда я увижу многопоточную версию хелворда?
как балансирование красно-чёрного дерева. Как на визиторах будет выглядеть функция
Когда я увижу хотя-бы одну состоятельную реализацию кд-дерева на этой лапше — тогда приходите. Заниматься и разбираться в синтаксическом мусоре я не хочу.
И зачем вам в реальной жизни нужна частично специализированная шаблонная перегрузка при написании небиблиотечного кода? У вас в ADT ваших часто есть std::variant<std::vector, std::vector>, которые надо обрабатывать похожим образом? Поздравляю, вы хреново спроектировали ваши типы, потому что это значит, что T1 и T2 должны быть ветками одного ADT.
Дальше лозунгов что-то будет?
Для паттерн-матчинга нельзя?
Опять лозунги? Меня это волнует мало. Можно — показывайте. На вопросы про матчинг отвечать должны вы, а не я.
И как этой композицией выразить «заматчить на тип Foo, если его вариант-член bar имеет значение типа Quux»?
Меня мало волнуют лозунги. Аналогичный код на расте в студию. Нету кода — с лозунгами не ко мне.
Mach7 это может. Перегрузки функций — нет. Но Mach7 никто не пользуется.
Что за нелепые попытки на каждый тезис придумывать новый супер-язык?
Понятно.
Опять убогая методичка. Либо цитируется тезис целиком, либо меня эта нелепица не волнует.
Как там, строки на уровень шаблонов уже завезли? Или тоже ненужно?
Что за нелепица? Строки на уровне шаблонов были всегда.
Про аналогичный пропозал для, кажется, C++23 вы, видимо, не слышали?
Что из этого нелепого срыва покровов следует?
Ну, что никто не обрабатывает ошибки выделения памяти для одного объекта в продакшен-коде (кроме чуваков из NASA и вояк, возможно). Даже на плюсах. Обрабатывают только ошибки выделения, не знаю, памяти под матрицу стопицот на стопицот.
Что это за набор нелепых лозунгов. Как быстро меняются методички. Буквально вчера все плюсовали статьи на тему «нужно проверять», а как случилась «лужа» мы всё забыли и оказывает проверять уже ненужно.
Даже на плюсах нельзя непроверить ошибку. В плюсах исключения.
В очередной раз игнорируя метаиронию контекста остальной части вашего комментария, можно лишь заметить, что да, куда им до лоровцев.
Ну да это очевидны. Вы в теме про ваш хелворд были слиты. Раст-адепты в теме про раст были слиты.
Эту функцию крайне сложно написать хуже на любом языке и с любой техникой. И судя по исходнику типа внизу Вы и сами это заметили ;)
Хех, а вот и адепты церкви свидетелей крестов подъехали.
То, что это попросту обман я уже писал. Необходимость что-то там дублировать обусловлена разделением на h/cpp-файлы. Никак не обусловлена С++ и это разделение может не использоваться.
Так ведь именно в этом разделении и проблема. В других языках нет необходимости разделять модуль компиляции и заголовочный файл к нему, а в C++ почему-то вот все так делают. Наверное, есть необходимость...
Ну в с++ до сих пор нету модулей. Всё через макросы.
Так ведь именно в этом разделении и проблема. В других языках нет необходимости разделять модуль компиляции и заголовочный файл к нему
В С++ нету так же необходимости, а есть возможность.
а в C++ почему-то вот все так делают. Наверное, есть необходимость..
Ничего нет. Как минимум у вас нет никакой конкретики, зачем что-то писать без какого-либо представления о вопросе? Разделение кода не имеет абсолютно никакого смысла, его ноль. Там можно что-то начать рассказывать про раздельную компиляцию, но тут опять же проблема. Никакой раст не собирается пофайлово, а значит все эти рассуждения не имеют смысла. К тому же, какое-то ускорении это так же мифология.
technic93 В С++ никакие модули(это просто нелепый лозунг внешней пропаганды) ненужны, а макросы не имеют никакого отношения к модулям, либо теме.
Я не совсем понял — Вы за что топите — что модули в С++ не нужны? Или они нужны, но разработчики стандартов их не осилили?
Разделение кода не имеет абсолютно никакого смысла, его ноль
Но почему в таком случае во всех известных мне проектах на плюсах код разделен?
Но почему в таком случае во всех известных мне проектах на плюсах код разделен?
Особенно в бусте и stdlib? Мне попросту лень отвечать на очередную идиотию в интернете. Эти нелепые аргументы уровня начальной школы уровня «мне»? С чего вдруг все проекты стали ограничиваться «мне»?
К тому же, даже если предположить, что их нет — это ничего не значит. Это такой же аргумент уровня начальной школы. Аргумент уровня «но почему в таком случае во всех известных мне лифтах было нассано?».
Что там вам известно — ни на что не влияет. Вы либо аргументируете за «нужно», либо продолжаете писать ахинею. Адепты всяких мастей вас будут плюсовать итак. Можете хоть рандомный набор слов писать.
В С++ нету так же необходимости, а есть возможность.В этих ваших крестах компиялтор тупо не соберёт код, если функция/переменная используется выше объявления. В 1980-ых такой подход может и имел смысл, но не в 2019.
Так модули в С++20 обещают добавить а многие компиляторы уже имеют какую-то реализацию. Сайты clang/gcc и статьи за авторством Страуструппа это не внешняя пропоганда. И речь идёт об одной простой вещи заменить #include
по сути макрос на что то лучшее. Сборки больших проэктов занимают время, и поэтому их разделяют на несколько файлов которые компилируются раздельно и паралельно. Без объявления публичного интерфейса в хедере как у вас так получится? Неужили Вcе ваши проэкты инклюдится в один cpp?
почему нельзя в одном пространстве имён объявить два типа с одинаковыми именами полей
Потому что каждое имя поля — ещё и функция, которая потом попадёт в это самое пространство имен...
Хорошо что хоть не полчаса собирался.
Типичное «слышал звон». cpp -E в студию.
Полностью согласен, какие то "очень хорошие программисты" пачками в группе в универе, угу. Верю(нет).
Сравнения компиляторов(которые непонятно в чём собственно компиляторы и что они умеют делать) по примерному количеству строчек кода, потрясающе
Визитор позволяет нашим проходам анализа обращать внимание только на части AST, в которых они нуждались, вместо того, чтобы сопоставлять шаблон по всей структуре AST. Это экономит много кода.
Ой, оказывается те другие попросту использовали «сопоставлять шаблон» и это было плохо. Но это ведь была проблема С++, а теперь оказывается rust-код отказывается от pm в пользу визиторов, которое в С++ попросту нативны(в отличии от rust, где это делается через тысячи костылей и боейлерплейта).
Каждая новая строчка пробивает очередной дно.
Ну вот не любят на Хабре такой тон, для многих это как красная тряпка, причем поставить минус могут даже не разбираясь кому и почему вы так писали (бывает прилетает даже когда оппонент явный тролль). Сомневаюсь, что хотя бы один минус вам прилетел именно от адептов раста.
P.S. Я вам минусов в карму и комментарии не ставил.
Совет. Не использую ни раст, ни С++, но чем больше вы используете фразы «Каждая новая строчка пробивает очередной дно», «сливаться и гадить», «гадящие в карму», «бред это ваши рассуждения вызванные вашем же непониманием», «да и попросту враньё», тем больше вам будут снижать карму, причем даже если вы писали по делу.
Ваши рассуждения не работают. Гадить начали до всего, а значит не в следствии. «бредом» было названо моё утверждение, где ваш коммент там? Нету. А что же так? Неужели вы просто пытаетесь что-то оправдываться, даже не разобравшись в теме?
Ну вот не любят на Хабре такой тон, для многих это как красная тряпка, причем поставить минус могут даже не разбираясь кому и почему вы так писали (бывает прилетает даже когда оппонент явный тролль). Сомневаюсь, что хотя бы один минус вам прилетел именно от адептов раста.
Именно адептов. Эти адепты набегают табунами из всяких чатов и прочих сборов и минусуют. Это мною доказанный факт.
Я уже отвечал в нескольких темах и в этих самых темах я то и делал, что опровергал мифология раста. Как и побеждал адептов попросту кодом. Именно это их тригерит и вы можете пойти и изучит мои комментарии.
Таким образом с моей стороны есть аргументация, код и победы. Со стороны адептом — нет ничего. Они мотивированы гадить, что они и делают. Точно так же мы не видим их аргументации, но видим минусы.
Всё это было мною разобрано и доказано тысячи раз. Разберитесь перед тем как кого-то оправдывать.
Ах да, существуют адекватные адепты раста. Они способны писать код, способны понимать. Но проблема в том, что их очень мало и адекватный человек просто так не гадит. Гадит только тот, кому нечего сказать. Кто пытается заткнуть меня/неугодных.
Я вам ещё раз советую почитать историю Посмотреть как мне угрожали эти адепты. И где же все честные люди были, когда мне писали откровенные угрозы? А, никого не было.
У вас бред преследования, обратитесь к врачу.
У вас бред преследования, обратитесь к врачу.
Отличная история. Адепты гадят и делают вид будто бы ничего не было. Ответы будут? Ответы за угрозы, ответы за то, что гадят? Где ответы? А Нету ответов, есть только «Гадят» и нелепые обвинения уровня начальной школы
Я вас ни в чём не обвиняю, просто читая ваши комментарии складывается впечатление, что вы не совсем адекватны (именно реакция на критику, минусы в "карму" и т. п.). Почему вас так волнует, что кто-то в интернете поставил вам минус в какую-то "карму", как от этого изменится ваша жизнь? Социальный рейтинг у нас ещё пока не ввели. Почему вы так агрессивно и остро реагируете? Симптомы бреда преследования прослеживаются (какая-то группа лиц желает зла, гадит и угрожает).
(именно реакция на критику, минусы в «карму» и т. п.).
В чём она неадекватно? В том, что обиженные адепты раста гадят в карму и минусуют, набегая на меня табунами?
Я вам так же советую изучить тему перед тем как делать какие-то выводы. Это уже не первая тема в которой они гадят. В корой угрожают. В которой они проигрывают.
Почему вас так волнует, что кто-то в интернете поставил вам минус в какую-то «карму», как от этого изменится ваша жизнь?
Мотивация гадящих адептов очевидна — не дать мне писать комменты. Таково устройство этого ресурса, что табун гадящих адептов может лишить тебя возможности свободно что-то писать.
Почему вы так агрессивно и остро реагируете? Симптомы бреда преследования прослеживаются (какая-то группа лиц желает зла, гадит и угрожает).
У меня всё задокументировано. А вы просто кидаетесь нелепыми обвинениями.
И да, я не хочу видеть ваши комментарии на хабре, мне неприятно, поэтому и голосую против вас — это способ саморегуляции сообщества.
На самом деле, вам не очень сложно побороть мое мнение и мнение других пользователей: достаточно просто приносить сообществу пользу, превышающую негатив от комментариев, например, писать полезные статьи.
Я читал и жалел, что подобного курса не было у меня. Можно говорить, что российское образование впереди планеты всей и хакеры тоже, но на практике у меня в институте подобного курса в программе не было, да и вообще программа была довольно фиксированной без возможности выбрать курсы по своим хотелкам.
И я почему-то уверен, что если бы такой курс был, мало кто из наших студентов использовал бы немейнстримные языки типа Haskell/Rust/Okaml/Scala.
Что-то похожее по уровню хардкорности было в шаде, но он больше про машинное обучение, построения компиляторов и тому подобных курсов там нет.
- В шаде на курсе по С++ писал интерпретатор лиспа. Как мне показалось, для подобных штук плюсы не очень удобно использовать, код получается довольно громоздким. Если бы я писал код на скале, было бы в 2-3 раза короче. Меня удивляет, что в статье выше код на плюсах получился не таким уж и большим — видимо, кто-то познал дзен и очень хорошо выбрал уровень абстракций.
- Ещё (там же в шаде) на курсе по питону была домашка с интерпретатором питоновского байт-кода, написанном на питоне. Но, видимо, мой мозг слишком привык к статической типизации, т.к. динамическими фишками питона я почти не пользуюсь и в большинстве задач код получается таким же или дальше длинее, чем в скале.
P.S. А где вообще есть хорошие хардкорные курсы по классическому CS с построением компиляторов, алгоритмами и прочим? Интересуют как онлайн курсы, так и аспирантура в России/за границей.
Будет Вам млн CS во всех проявлениях
Можно говорить, что российское образование впереди планеты всей и хакеры тоже, но на практике у меня в институте подобного курса в программе не было
Это Миф. Я разговаривал со своим боссом (который получал образование у нас и в штатах и создал международную ИТ компанию с филиалами в России, соотвественно мог сравнить образование у нас и Западе). Вот он говорил «В России отличное школьное образование, отвратительное высшее и хорошие программисты». Вот такой парадокс.
Суть в том, на Западе они сами выбирают нужные им курсы, свое расписание и получают знания без воды и устаревших курсов уровня программирования на перфокартах. У нас хорошими программистами становятся не благодаря высшему образованию, а скорее вопреки. Просто программирование это чуть ли не единственная профессия в РФ для умных технических ребят, где можно получать очень неплохие деньги для РФ и уехать почти в любую страну на зарплату выше средней.
На Западе профессия программиста не настолько привлекательна, плюс школьное образование дает относительно хорошую базу, а высшее в РФ… ИМХО, проигрывает даже простому самообразованию, может не во всех программерских вузах, но во многих.
Возвращаясь к компиляторам: есть курс от computer science center www.youtube.com/watch?v=DKr45aBUtFU&list=PLlb7e2G7aSpQ4Ym2TWTYyMcfMevxpKoxj
Он там не один такой, есть прочитанные в другое время. Я сам не интересовался, за качество отвечать не берусь, но ознакомиться можете.
P.S. А где вообще есть хорошие хардкорные курсы по классическому CS с построением компиляторов, алгоритмами и прочим? Интересуют как онлайн курсы, так и аспирантура в России/за границей.
У JetBrains и Computer Science Center вроде интересная магистратура в ИТМО, вот программа, а вот темы работ недавних выпусников. Конечно, много прикладного, но какой-то чел защищался по завтипам, например.
Еще важный вопрос: сколько времени потрачено на разработку, отладку и какое количество багов было выявлено в процессе отладки?
Сколько времени требуется на написание одной безошибочной строки на каждом из языков?
Особенно интересно сравнение в этом плане двух реализаций на Rust.
А тут просто wc -l сделали.
Да вроде бы в том и плюс — не писать тесты там, где может справиться компилятор/интерпретатор.
Дык если это код из разряда написал и забыл, то ок, а если понадобится за девочкой на питоне потом код поддерживать, то это будет сложнее, чем с остальными языками.
Одна большая часть этого различия, вероятно, динамическая типизация. Только в нашем ast.rs 500 строк определений типов, и ещё много типов, определённых в других местах компилятора. Мы также всегда ограничены самой системой типов. Например, нам нужна инфраструктура для эргономичного добавления новой информации в AST по мере прохождения и доступа к ней позже. В то время как в Python вы можете просто установить новые поля на узлах AST.
за счет 2х времени и 3х обьема кода в котором так же можно ошибится… так себе плюс.
Сравнение одинакового проекта в Rust, Haskell, C++, Python, Scala и OCamlА в каком месте он одинаковый? Алгоритмы разные, абстракции разные, готовность разная, количество дополнительных функций тоже разное. Тем более, что больше всего отличаются друг от друга реализации на одном и том же языке. Почему код меряют в байтах и строках?
Не кажется ли вам, что php лишний в этом списке? Это, конечно, целая эпоха, но вспоминать про нее не хочется
Ко всем остальным питаю теплые чувства
Да нет, нормальная технология, уровень сайтов-визиток тоже должен быть кем-то закрыт. Причем учитывая, что 80% веб-сайов это вордпресс поделия, то технология вполне себе успешна.
Отичный пример почему динамическая типизация это очень круто если применять правильно!
Кода гораздо меньше и результат получен одним человеком а не двумя-тремя.
Pyton фактически избежал типизации потому что arg:type толком не работает, сам тестил туда без какого либо сообщения пролезает тип который там быть не должен.
Да щас я тут кучу минусов понахватаю)
моё предложение — возможность включать / отключать типизацию
А зачем статическую типизацию отключать? Это всё равно что посадить льва в открытую клетку — рано или поздно но лев выйдет. Рано или поздо, кто-то в своей библиотеки да отключит типизацию и заразит таким образом весь оставшийся код
Большинство рассматривает статическую типизацию как это реализовано в си, в лучшем случае в крестах или яве. Прогресс неумолим и уже появились гораздо более подходящие варианты.
плюс инспекция действительно ли переменная динамическая, или её можно заменить одной (вроде auto ) или несколькими статическими в препроцессингеВозьмите crystal. Вот это вот не собирается.
if Random.rand > 0.5
test = "text"
else
test = 5
end
puts test.upcase
А вот это — собираетсяif Random.rand > 0.5
test = "text"
else
test = 5
end
puts test.is_a?(String) ? test.upcase : test
Типизация на месте, ошибок в рантайме нет.Pyton фактически избежал типизации потому что arg:type толком не работает, сам тестил туда без какого либо сообщения пролезает тип который там быть не должен.Не даром я не любливаю python, ибо не смотря на свой дзен он умудряется быть непростым, непонятным и неявным. В итоге люди будут писать код который ещё и не работает
Возвращаясь к Вашему примеру с crystal — это прекрасно, что такое отловит компилятор, но тут меня неизбежно всегда мучает вопрос про троллейбус из буханки. Да мы отловим на этапе компиляции некоторый весьма ограниченный набор багов, которые, на самом деле, одни из самых тривиальных. Но никакой компилятор не отловит ошибки в логике, да те же перепутанные местами аргументы одного типа, с которыми уже можно всего веселого наворотить, типа copy(input_file, output_file), а вызвать наоборот. Т.е. отбрасывание (ценой повышения трудоемкости написания кода в разы) заведомо небольшого количества проблем почему то постулируется как повышающее надежность до недостижимых другими методами высот. Что есть самообман, по-моему. То же TDD или контрактное программирование здесь выглядят гораздо более системным.
Вообщем придерживюсь мнения что статическая типизация суть анахронизм, абсолютно необходимый в компилируемых языках прошлого поколения, когда требуется точное знание размера бинарного представления объекта на этапе компиляции, там да. А коли у нас объект — это бирка с типом и счетчиком ссылок в куче — ну какой смысл таскать его тип в коде — понимать отказываюсь.
Да мы отловим на этапе компиляции некоторый весьма ограниченный набор багов, которые, на самом деле, одни из самых тривиальных.Что быстрее — компиляция или прохождение всех тестов? А если используется библиотечный код? Что быстрее — указание типа или написание достаточного количества тестов? Насколько легко среде разработки будет указать на то, что тут неверный тип(например после рефакторинга)?
А коли у нас объект — это бирка с типом и счетчиком ссылок в кучеСчётчики ссылок это дорого, так как при каждом присваивании/выходе из зоны видимости их нужно обновлять. От циклических ссылок они не защищают. Единственное, зачем они нужны — избежать остановки на сборку мусора.
Единственное, зачем они нужны — избежать остановки на сборку мусора.
И вот выходит у Вас из области видимости развесистое дерево умных указателей с подсчетом ссылок…
Дерево как раз нет, а какой-то граф с циклами вполне
Так это даже в языках с ручным управлением памяти прийдётся решать каким то своим пуллом объектов или умным аллокатором. Единственно что счётчики не будут вносить дополнительную нагрузку.
Питон на основе подсчёта ссылок работает и деструктор вызывается сразу как объект покидает скоуп если счётчик стал равен нулю, а GC только для циклических случаев.
А на С/C++ подсчёт ссылок не нужен если иерархия владельцев ресурсов известна заранее.
Я с Вами соглашусь и не соглашусь. Соглашусь по поводу того, что проблемы в логике кода не отловить. А не соглашусь, что статическая типизация анахронизм (или анахрЕнизм — кому как больше нравится, в зависимости от отношения). Я действительно хочу быструю компиляцию и быстрый код, а языки с динамической типизацией отстают в этом аспекте (но это очень холиварная тема). А еще чтоб среда подсказывала что и где (в случае динамической нестрогой типизации — среда тоже будет путаться и подсказывать не то или вообще не подсказывать).
С другой стороны, тот же Питон — прекрасен для БЫСТРОГО прототипирования. Здесь он вне конкуренции.
если потом будет присвоение другому типу там test = 42.0, согласен в питоне есть ряд вещей которые я бы подкоректировал или поудалял, сделав его таким языком чтобы других ненадо было ))
стоп, вышеописанный код для тебя — статическая, динамическая типизация или безтипная?Сильная статическая неявная. Все три слова важны. Тип данной переменной String | Int. Это означает, что каждый раз, когда с переменной что-то происходит, компилятор проверяет, может ли данное действие быть совершено над данным типом. Метод is_a? есть и у String и у Int. По этому, компилятор принимает безусловный вызов метода. А вот upcase есть только у String и по этой причине компилятор требует явной проверки типа. Компилятор достаточно умён, чтобы понять что в первой ветке тернарного оператора тип String и не требует обязательного приведения типов.
потому что тут может быть и статическая смотря как работает rand))Рекомендую поставить на машину и поиграться.
a=[1,"str", [1,2]]
for i in a: i.upcase
оно справится? Ибо самое интересное про типы, как известно, начинается в коллекциях.
a = [1, "str", [1, 2]]
a.map do |i|
if i.is_a?(String)
puts i.upcase
else
puts i
end
end
Или то же самое, только в две строки
a = [1, "str", [1, 2]]
a.map { |i| i.is_a?(String) ? puts i.upcase : puts i }
Допустим функция не принимает тип Int, а я ей его передаю.
a = [1, "str", [1, 2]]
def func(arg)
arg.map do |i|
if i.is_a?(String)
puts i.upcase # Строка
else
puts i.uniq # Массив
end
end
end
func(a)
Тогда вот что скажет компилятор
Error in line 13: instantiating 'func(Array(Array(Int32) | Int32 | String))'
in line 8: undefined method 'uniq' for Int32 (compile-time type is (Array(Int32) | Int32))
Rerun with --error-trace to show a complete error trace.
Вот ещё один пример
def func(arg : String | Array)
puts arg.size # метод есть у строк и у массивов
end
func("текст")
func([0, 1, 2, 3])
Если нужно, можно явно указать тип переменной.val['sum'] = val['a'] + val['b']
Будет
val["sum"] = (int)val["a"] + (int)val["b"]
А если ещё и паттерн расширения прикрутить для хеша или объекта, то совсем динамический язык получится, поскольку можно будет не только значения брать, но и методы вызывать.
ИМХО динамическая типизация хороша либо для скриптов которые можно написать за пять минут, либо как промежуточное представление.
О результатах мы мало что знаем, особенно о стоимости отладки и доработки.
Рецензия на книгу по ссылке.
Сравнение одинакового проекта в Rust, Haskell, C++, Python, Scala и OCaml