Python
Haskell
Scala
Compilers
Rust
Comments 139
0
В последнем семестре университета я выбрал курс компиляторов CS444. Там каждая группа из 1-3 человек должна была написать компилятор из существенного подмножества Java в x86.

а можно поподробнее о задаче, какие там точно действия после AST, желательно на русском, может и я на питоне что то накалякаю, сравним. Всё думаю о написании универсального компилятора, с контролем юзера над действиями и типом результата…

Её компилятор состоял из 4581 строки

для питона — гигантский проэкт, может там всё таки имеется флуд?
кстати с eval нечестно, но прелесть питона в том что там за строк 10 пишется свой eval

Другой пример мощи метапрограммирования и динамической типизации — 400-строчный файл visit.rs, это в основном повторяющийся шаблонный код, реализующий визитора на куче структур AST. В Python это может быть короткая функция примерно на 10 строк, которая рекурсивно интроспектирует поля узла AST и посещает их (используя атрибут __dict__).

А разве нельзя в другом языке сделать стирание типов например один класс ASTNode, с присваиванием функций даже java 8 там может, вместо того чтоб расписывать флуд, чем являются паттерны програмирования

Как поклонник Rust и статически типизированных языков в целом, я склонен отметить, что система типов очень полезна для предотвращения ошибок и для производительности.

Проверять ошибки можно, а при непредсказуемой структуре нужно в рантайме, в python это элегантно делается декоратором, при этом вы имеете приимущество встраивания любых своих проверок и возможностью включать и выключать по желанию. Собсветнно я сторонник включения / выключения проверки типов во желанию.

0
вряд ли вам расскажут подробнее

На странице оригинала указаны контакты автора, так что можно попробовать обратиться напрямую.
0
По ссылке на курс компиляторов CS444 можно больше о задании, например:
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).

Возможно даже можно будет найти открытые тесты.
+10
Очень интересно было бы еще увидеть сравнение производительности полученных компиляторов.
-5
главное не производительность а качество кода. А так на дворе 21 век так что можно задуматься можно ли сделать компилятор на паралельной платформе например CUDA какой нить.
-1

А длины строк не сравнивали? Или, может быть, размер по диагонали, скажем, программа на Python диагональю 52".

+4

По моему опыту с хаскелем вещи типа lens, uniplate/geniplate и паттерны типа trees that grow сокращают объём кода минимум на порядок по сравнению с теми же плюсами.


Жалко, что исходников нет.

+1
А на сколько они, по вашему опыту, сокращают время на прочтение?

PS Я знал что вы придёте!
+3

По моему — существенно. Но тут как с любыми паттернами, если вы их знаете, то вы их просто сразу выцепляете из кода, а иначе сложно, да.


Другое дело, что уровень абстракции чуть выше, чем, не знаю, у immediately invoked function, detector idiom в плюсах и тому подобных вещах.


PS Ну не мог же я пропустить такой тред!

-7
Необходимость дублировать все сигнатуры в заголовочных файлах, чего нет в Rust.

Это неверно. Такой необходимости нет.
+2
Вот и объективная критика пожаловала. Именно так она выглядит.
+4
(минус не мой)
Необходимости конечно нет, но разбиение на реализацию/объявление заметно улучшает читаемость, и ускоряет компиляцию. Это слишком серьезные преимущества, чтоб игнорировать их в проекте на несколько тысяч строк.
+1
Необходимости конечно нет, но разбиение на реализацию/объявление заметно улучшает читаемость, и ускоряет компиляцию.

А чего же их не разделяют в rust? Да и много где ещё. Подобные рассуждения не работают, вообще. Вы либо последовательно применяйте это ко всем языкам, либо не применяете вообще.
заметно улучшает читаемость

Это догмат. Лично для меня это ничего и никак не улучшает, как и для пользователей тысяч других языков, где нет этого разделение. К тому же не каждый С++-код можно разделить, а современный С++ разделить вообще почти нельзя.

и ускоряет компиляцию.

Это попросту глупость разоблачённая уже давно. Как-то ускорение есть лишь в очень редких случаях, либо на очень большой кодовой базе. Вернее даже не ускорение, а просто возможность распараллелить сборку.

К тому же, такого разделение в rust нет и там собирается всё модульно. Опять же, либо будьте последовательны и применяйте это ко всем языкам, либо не применяйте вообще.
Это слишком серьезные преимущества, чтоб игнорировать их в проекте на несколько тысяч строк.

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

+1
Если что, я не то чтобы топлю за Rust. Сам пишу на С++ и люблю его умеренной любовью.

А чего же их не разделяют в rust? Да и много где ещё. Подобные рассуждения не работают, вообще. Вы либо последовательно применяйте это ко всем языкам, либо не применяете вообще.

Не знаю :) Это вопрос к авторам дизайна языка.
Это догмат. Лично для меня это ничего и никак не улучшает, как и для пользователей тысяч других языков, где нет этого разделение.

На мой субъективный взгляд, при чтении кода некоторого модуля, проще сначала прикинуть что в этом модуле вообще находится, и только потом переходить к чтению реализаций. Читать протянку из смеси объявлений и реализаций не очень удобно. Эта проблема частично решается умными IDE в которых есть folding реализаций, конечно.
Да это мое субъективное мнение.

современный С++ разделить вообще почти нельзя.

А можно пример?

Это попросту глупость разоблачённая уже давно.

Было бы здорово увидеть пример.
Как-то ускорение есть лишь в очень редких случаях, либо на очень большой кодовой базе. Вернее даже не ускорение, а просто возможность распараллелить сборку.

Я не то чтобы спец, но предположим у вас в реализации функции не какая-нибудь банальщина, а инстанцирование тяжелых линейных солверов из Eigen, приправленных expression templates. В этом случае раздельная компиляция просто жизненно необходима. И это не то чтобы прям редкий случай, заметная доля проектов с С++ это числодробилки, в которых постоянно возникает подобная ситуация.
0
Если что, я не то чтобы топлю за 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


И чем сложнее будут инклюды — тем хуже ситуация будет с раздельной компиляцией. Оно будет почти всегда медленнее. И единственное для чего может потребоваться раздельная компиляция — это параллельная сборка большой кодовой базы. Но это явно не тот случай. Да и в том случае нужно будет модульное разделение, а не разделение по-файлам.
0
Ну ваши претензии не работают в рамках логики автора, да и в моей тоже.

Ну у меня все началось не с претензий, а с попытки обосновать, почему в 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

Пример интересный, спасибо, но не уверен что все это так же хорошо масштабируется на относительно большие проекты
0
Если вы про auto в сигнатуре, то лично я бы предпочел видеть там полноценный тип/шаблон. Да, не во всех ситуациях это будет красиво, но в большинстве — снимет кучу головной боли при чтении кода.
Да, шаблоны вполне себе разбиваются. Не на .h и .cpp, конечно, но на блоки объявления и реализации — вполне.

Это будет некрасиво в случае использования современного С++-кода. Современный С++-код полагается на типизацию и сложные типы, которые не так-то просто вывести руками. И именно auto убирает все эти проблемы.

К тому же подобный код ненужно читать. 1min / 1s — вы же не будите руками писать тип? И вам ненужно при чтении знать тип. Задача системы типов сделать таким образом, что-бы вы не смогли написать 1min * 1s;

К тому же, выводит типы задача ide. Как и задача компилятора(ide) проверять синтаксическую корректность кода. Ненужно это делать за них. Это пустая трата сил на то, что реализуется автоматикой. Всё что автоматизируется должно быть автоматизировано.

Я про случаи когда

Ну это просто си-api.

Вполне себе С++, вполне себе хороший способ убрать компиляцию тяжелых частей в локализованные .cpp. Кроме прочего, таким образом можно уменьшить количество инклудов которые расползутся по проекту, ставя их только в .cpp

Ещё раз. Если ваша библиотека ho, то вы никаким образом подобное не сделаете. Если вы сделаете шаблонное api, то его нельзя будет засунуть в cpp. Вы можете сделать только сишное api.

Таким образом мы просто сделаете обёртку над шаблонной ho-библиотекой. Удобство сишного api крайне сомнительно в случае какой-то обобщённой логики. А такой логики в современной С++ навалом.

Пример интересный, спасибо, но не уверен что все это так же хорошо масштабируется на относительно большие проекты

Я думаю, что хром является «относительно большим проектом». Там всё так же работает. Именно это они и сделали.

0
«Если вы сделаете шаблонное api, то его нельзя будет засунуть в cpp»
Что за бред?
Я даже больше скажу, его еще и из dll можно экспортировать, если типы с которыми может быть инстанцирован шаблон, заранее известны) У нас в проекте это активно используется, для шаблонов, которые используются с 2-3-4 типами.
«есть ограничения» != «нельзя».
-3
Что за бред?

Бред это ваши рассуждения вызванные вашем же непониманием. Шаблон нельзя никуда эспортировать по определению. Эспортировать куда-то можно инстанс.

У нас в проекте это активно используется, для шаблонов, которые используются с 2-3-4 типами.

Что за бред? Во-первых 2-3-4 типа это не шаблон, у шаблона нету никаких ограничений. Во-вторых эспортируются не шаблоны, а инстансы.

Узнайте разницу между первым и вторым перед тем как кричать «бред».
+3

Ну ещё вспомните, что приватные шаблонные функции можно описывать в cpp без явного их инстанциирования.


Разговор ведь не об этом.

0
современный С++ разделить вообще почти нельзя.

Я думаю, имелись ввиду inline, constexpr и шаблонные функции/классы.

-11
Затем сравнил с компилятором на C++, и там вполне ожидаемо компилятор был примерно на 30% больше

Что это за ангажированные намёки ничем не обоснованные? Это сравнение, либо пропаганда?

Rust (основа для сравнения)

На каком основании это основа, а не это:

Rust (другая группа): трёхкратный размер из-за иного дизайна!


Почему эта разница в одном случае описывается дизайном, а в другом непонятным набором слов?

Я не очень глубоко копался в этих различиях по размеру. Предполагаю, это в основном объясняется:

А раньше же было «ожидаемо», а теперь «не копался», «не знаю»? Зачем что-то утверждать, если при этом ничего не знать?

Отсутствие типов sum и сопоставлений с образцом в C++, которые мы широко использовали и которые были очень полезны.

Никакое «сопоставлений с образцом» не является чем-то необходимым и в 95% случаев сливает более мощной концепции визиторов. В С++ есть исключения и ненужно матчить каждую функцию. К тому же, с чего вдруг в С++ нету сумтипов?

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

Необходимость дублировать все сигнатуры в заголовочных файлах, чего нет в Rust.

То, что это попросту обман я уже писал. Необходимость что-то там дублировать обусловлена разделением на h/cpp-файлы. Никак не обусловлена С++ и это разделение может не использоваться.

с оговоркой, что они помещают реализации множества небольших функций в заголовочные файлы

Какая разница какие функции? К тому же, тут явно видно взаимные противоречия.

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

Это просто глупость несусветная. Это мифология, которую была опровергнута уже тысячи раз. Особенно хромом. Уплотнение кода способствует ускорению компиляции т.к. инклюды в С++ тяжелые и компилятор делает ненужную работу каждый раз обрабатывая один и тот же код в каждом cpp-файле.

К тому же, уровень владения языком представителей С++-лагеря крайне скудны(судя по тексту). В С++ непросто так появилось ho и причины тому просты — шаблонный код попросту нельзя разделить. Попытки были и все они не имели успеха.

Таким образом из этого можно сделать вывод, что там не было никакого С++, а был типичный студенческий С/С++ начального уровня.

8733 строк

Никак не могут компилироваться секунды. К тому же сравнение скорости компиляции на разном железе меня так же удивляют. А так же меня удивляет отсутствие информации об компиляторе и какой-то конкретики в целом.

Опять же. Кода мы не видим. Никаких измерений нет. Есть «одна бабка сказала» и какие-то ничем не обоснованные заявления. Прослеживается явная ничем не обоснованная ангажированность и двойные стандарты.

0
К тому же, с чего вдруг в С++ нету сумтипов?

есть, есть std::variant, которым пользуется примерно никто

0
есть, есть std::variant, которым пользуется примерно никто

Это ничего не значит, да и попросту враньё. На это я могу ответить: есть rust|haskell, которыми пользуется примерно никто.

PS Опять табун раст-адептов набежал и начал гадить в карму.
0
На самом деле, здорово бы было, если вы привели бы пример сумтипов на с++ вместе с компактным примером их использования.
+5

Напоминаю: Haskell и Rust мозголомные и непонятные, а C++ — простой и очевидный. Смотрите не перепутайте!

0

Спросил у автора (т.к. это был перевод). Вот его ответ:
"As far as I know my friend didn’t use the new visitor feature."
Вообщем там наверно обходились enum + switch + cast/union.

+1
 Это ничего не значит, да и попросту враньё

я ищу вот так, находятся тесты из LLVM пополам с игрушечными проектами с нулём звёзд. И в QT нашёл QVariant, который умеет оборачивать variant при наличии, который, в свою очередь, находится в игрушечных проектах пополам с копиями qvariant.h


покажите, как правильно искать

+2

Не, ну я в своих проектах std::variant юзаю вместе с самописным костылем для эмуляции недопаттернматчинга через лямбдочки. Это даже удобно, в принципе. Ну, насколько код на плюсах может быть удобным.


Вот что действительно никто не использует — какой-нибудь Mach7.

-5
почему это даже близко не оно.

Это попросту враньё. Если кратко — автор узнал, что на С++ можно сделать аналогичный match. Вся его критика была именно в том, что «С++ вариант сложный, а match простой». Сам функционал он нигде не критиков. Нигде «это не оно» он не говорил. Что-то подобное он говорил только про версию на ифах. Да и вся его критика существует в рамках надуманного примера.

Если подробнее — это полная и нелепая чушь. После «else if» можно не читать. Основные тезисы — рядовая раст-пропаганда. Почему пропаганда, всё очень просто:

мы однажды захотим его извлечь, и что более важно, узнать его тип.

Никогда мы такого не захотим. Это попытка автора подменить тему. Подобный код — это именно максимум, на что способен pm и это мусор. Это доказано даже автором статьи, да и это в принципе очевидная вещь.

const bool b) const

Это тоже часть пропаганды. Автор пытается засунуть в определения много непонятных ему кейвордов. Никакие const и прочая хрень там ненужны, потому что в ветках match нету подобных ограничений.

Уже лучше, но в стандартной библиотеке нет ничего похожего на функцию make_visitor,

Она пишется в 2 строчке и ниже она, даже, есть. И тут пропаганда теряется, пропаганда не сообщает нам о проблемах такого подхода? В этом подходе никаких «лишних» строк нету и всё, автор приплыл. Но нет, автор опять меняет тему. И начинает вещать про if constexpr и то, как это сложно. С чего вдруг? Ответ я дал выше — его задача не разобраться, не отразить реальную действительность.

Мы начали с простой цели: посмотреть на содержимое сигма-типа.

Это абсолютно бесполезная херня. Дело в том, что в С++ есть механизмы, которые нету в rust. Там нету компилтайм-вычислений, нету шаблонов, нету перегрузки функций.

Эта пропаганда нагло врёт. visitor — это базовая концепция С++, концепция перегрузки функции. Для неё ненужен никакой variant/visit. Задача variant/visit не обеспечить pm, как уверяет эта второсортная пропаганда, а попросту сделать динамический диспатч. Т.е. вызвать нужную функцию(в рантайме). Вызовы visit(f, x) == f(x). Всё. Сам pm в С++ реализован именно на базе перегрузки.

Но проблема в том, что во всяких rust перегрузки нету и написать f(x) попросту нельзя и match — это костыль, который позволяет получить нечто подобное.

Близкого знакомства с using-объявлениями с переменным количеством параметров, которые только появились в стандарте C++17.

Меня вот что удивляет, почему раст-пропаганда всегда, в своей нелепой методички, апеллирует к стандарту, которого у неё нет? Если мы не можем использовать «новый стандарт», либо «нестандартный код», то мы не можем использовать rust по той же логике. К чему эти нелепые лозунги?

собираются вместе, у них получается std::visit.

Зачем пропаганда пытается куда-то лезть, если она не понимает ничего в С++?

template <typename F>
typename std::enable_if<!std::is_reference<F>::value, int>::type
foo(F f)
{
    // ...
}

Что это за стиль говна? Что это за enable_if из 11 крестов. Как быстро пропаганда меняет тему. Ещё с 14 крестов это выглядит так:

template<typename F> std::enable_if_t<!std::is_reference_v<F>, int> foo(F f) {
  
} 


Я не говорю о каких-то там концептах, а так же смысле подобного поиска ссылки в F.

Скотт Мейерс, автор книг Effective C++ и Effective Modern C++, тоже высказал подобные мысли

Опять пропаганда врёт. Есть сложность вызванная функционалом, а есть сложность вызванная отсутствием функционала. typename std::enable_if<!std::is_reference::value, int>::type — эта сложность вызванная отсутствием функционала и именно с нею борются адекватные люди.

Проблемы существующие в С++ вызваны только тем, что в С++ мало функционала. Его, конечно, куда большее чем в 99% других языков, но всё равно мало. И тут пропаганда нам врёт. Она показывает проблему и говорит «проблемы из-за „много функционала“», но это не так. Точно так же она врёт и про авторов, выдирая их слова из контекста(хотя даже слов не приводит).

+5
Никакое «сопоставлений с образцом» не является чем-то необходимым и в 95% случаев сливает более мощной концепции визиторов.

Сливает по какому критерию? Что по выразительности, что по числу строк кода оно, наоборот, уделывает.


Как вы на визиторах замачтитесь на значение без того, чтобы городить тонны ифов?

0

анонимным классом с перегруженным operator() :)
производится ли при этом проверка на exhaustiveness, я не понял

+3

Для, э, конструкторов в ML-смысле производится. Для значений вам придется писать ифы, не сможете вы выразить матч на значение, а не только лишь на форму конструктора.

-2
godbolt.org/z/18aRS9

К тому же сами рассуждения не имеют смысла. Единственное что может pm «бесплатно» — это switch. Всё что далее — это непредсказуемая лапша. К тому же почти всё это реализуется по аналогии с visit/variant. Правда никому ненужно.

Описание мапы будет всегда лучше. К тому же С++ может без проблем хоть phf в компилтайте сгенерировать.

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

-4
Сливает по какому критерию? Что по выразительности, что по числу строк кода оно, наоборот, уделывает.

Вот зачем писать эти лозунги глупые, если даже сам автор говорит о том, что визиотор уделывает pm, по крайне мере в его кейс. Да и почти в любом другом кейсе.

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

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

match существует в rust и подобных языках лишь по одной причины — они крайне примитивных. В них нет шаблонов, перегрузки, компилтайм-вычислений, параметров-значения даже для генериков. В них попросту невозможно написать что-то типа overloaded-композитора, либо visit.

И самое интересное, как только будет реальная задача. Обход того же дерева — на нём будет очевидна вся несостоятельность pm. Что нам и сообщает автор. Но даже визиторы на rust будут написаны убого, т.к. нету перегрузки. Это будет тонна лапши на генерик-трейтах.

Как вы на визиторах замачтитесь на значение без того, чтобы городить тонны ифов?

Это ненужно. Для случае уровня свича есть свич. Реализовать тот же визитор для чего угодно — не является проблемой. Вообще визитор ничего не матчит, матчит перегрузка. Она уже есть на уровне языка.

тонны ифов?

Я бы в контексте раста об этом вообще не заикался. Как там не обработать ошибку без тонны ифов? Из-за тонны ифов раст-методичка даже nullptr из аллокатора игнорирует. А что, памяти нету — можно падать. Надёжность она такая. Особенно смешно выглядят рассуждения раст-адептов про «как вы можете игнорировать NULL у malloc».

Тут, кстати, видно уровень состоятельности ЦА. Как адепты бегут плюсовать какие угодно лозунги(ничем не обоснованные), лишь бы они соотносились с их верой.

+2
Вот зачем писать эти лозунги глупые, если даже сам автор говорит о том, что визиотор уделывает pm, по крайне мере в его кейс. Да и почти в любом другом кейсе.

Ну естественно, если автор пишет, что визитор лучше паттерн-матчинга, то это авторитетное мнение, а если кто-то пишет, что паттерн-матчинг лучше визитора, то это глупые лозунги и растопропаганда.


Тащем, после такого захода с козырей с вашей стороны обсуждение можно и прекращать, но я сегодня уже подустал от попыток скрестить MonadIO и MonadBase IO, так что можно продолжить.


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

В каком месте?


Я не хочу обсуждать растовский матч, впрочем, я его не знаю. Давайте обсуждать паттерн-матчинг в более функциональных языках, а чтобы обсуждение было конструктивным, я предлагаю обсудить преимущество визиторов на такой простой задаче и приятной каждому императивщику задаче, как балансирование красно-чёрного дерева. Как на визиторах будет выглядеть функция


balance :: Color -> Tree a -> a -> Tree a -> Tree a
balance B (Node R (Node R t1 e1 t2) e2 t3) e3 t4 = Node R (Node B t1 e1 t2) e2 (Node B t3 e3 t4)
balance B (Node R t1 e1 (Node R t2 e2 t3)) e3 t4 = Node R (Node B t1 e1 t2) e2 (Node B t3 e3 t4)
balance B t1 e1 (Node R (Node R t2 e2 t3) e3 t4) = Node R (Node B t1 e1 t2) e2 (Node B t3 e3 t4)
balance B t1 e1 (Node R t2 e2 (Node R t3 e3 t4)) = Node R (Node B t1 e1 t2) e2 (Node B t3 e3 t4)
balance color left elt right = Node { .. }

Цвет и дерево, если что — банально


data Color = R | B deriving (Eq, Show, Generic, NFData)

data Tree a
  = Empty
  | Node
    { color :: Color
    , left :: Tree a
    , elt :: a
    , right :: Tree a
    }
  deriving (Eq, Show, Functor, Generic, NFData)

Впрочем, даже это многословно. В некоторых диалектах SML есть расширения, позволяющие синтаксически одинаковую правую часть писать лишь один раз. Когда я этот код писал, я всерьёз подумывал запилить в ghc аналогичное.


Причины очевидны. Перегрузка может быть шаблонной, может быть частично шаблонной.

Может, она и по рантайм-значению может быть ещё?


И зачем вам в реальной жизни нужна частично специализированная шаблонная перегрузка при написании небиблиотечного кода? У вас в ADT ваших часто есть std::variant<std::vector<T1>, std::vector<T2>>, которые надо обрабатывать похожим образом? Поздравляю, вы хреново спроектировали ваши типы, потому что это значит, что T1 и T2 должны быть ветками одного ADT.


Для перегрузки можно использовать композицию из существующих функций/типов.

Для паттерн-матчинга нельзя?


И как этой композицией выразить «заматчить на тип Foo, если его вариант-член bar имеет значение типа Quux»?


Mach7 это может. Перегрузки функций — нет. Но Mach7 никто не пользуется.


Это ненужно.

Понятно.


Как там, строки на уровень шаблонов уже завезли? Или тоже ненужно?


А что, памяти нету — можно падать. Надёжность она такая. Особенно смешно выглядят рассуждения раст-адептов про «как вы можете игнорировать NULL у malloc».

Про аналогичный пропозал для, кажется, C++23 вы, видимо, не слышали?


Ну, что никто не обрабатывает ошибки выделения памяти для одного объекта в продакшен-коде (кроме чуваков из NASA и вояк, возможно). Даже на плюсах. Обрабатывают только ошибки выделения, не знаю, памяти под матрицу стопицот на стопицот.


Тут, кстати, видно уровень состоятельности ЦА. Как адепты бегут плюсовать какие угодно лозунги(ничем не обоснованные), лишь бы они соотносились с их верой.

В очередной раз игнорируя метаиронию контекста остальной части вашего комментария, можно лишь заметить, что да, куда им до лоровцев.

-8
Ну естественно, если автор пишет, что визитор лучше паттерн-матчинга, то это авторитетное мнение, а если кто-то пишет, что паттерн-матчинг лучше визитора, то это глупые лозунги и растопропаганда.

У вас методичка течёт. Что-то я не вижу от вас разоблачений автора и обсуждения того, какой же он дурак со своими тезисами. Чего же вы гадите мне, а не гадите автору?

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

Меня не интересует «функциональных языках» существующие только для написания хелвордов, хотя и хелворд вы не осилили на нём написать. Когда я увижу многопоточную версию хелворда?

как балансирование красно-чёрного дерева. Как на визиторах будет выглядеть функция

Когда я увижу хотя-бы одну состоятельную реализацию кд-дерева на этой лапше — тогда приходите. Заниматься и разбираться в синтаксическом мусоре я не хочу.

И зачем вам в реальной жизни нужна частично специализированная шаблонная перегрузка при написании небиблиотечного кода? У вас в ADT ваших часто есть std::variant<std::vector, std::vector>, которые надо обрабатывать похожим образом? Поздравляю, вы хреново спроектировали ваши типы, потому что это значит, что T1 и T2 должны быть ветками одного ADT.
Дальше лозунгов что-то будет?

Для паттерн-матчинга нельзя?

Опять лозунги? Меня это волнует мало. Можно — показывайте. На вопросы про матчинг отвечать должны вы, а не я.

И как этой композицией выразить «заматчить на тип Foo, если его вариант-член bar имеет значение типа Quux»?

Меня мало волнуют лозунги. Аналогичный код на расте в студию. Нету кода — с лозунгами не ко мне.

Mach7 это может. Перегрузки функций — нет. Но Mach7 никто не пользуется.

Что за нелепые попытки на каждый тезис придумывать новый супер-язык?

Понятно.

Опять убогая методичка. Либо цитируется тезис целиком, либо меня эта нелепица не волнует.

Как там, строки на уровень шаблонов уже завезли? Или тоже ненужно?

Что за нелепица? Строки на уровне шаблонов были всегда.

Про аналогичный пропозал для, кажется, C++23 вы, видимо, не слышали?

Что из этого нелепого срыва покровов следует?

Ну, что никто не обрабатывает ошибки выделения памяти для одного объекта в продакшен-коде (кроме чуваков из NASA и вояк, возможно). Даже на плюсах. Обрабатывают только ошибки выделения, не знаю, памяти под матрицу стопицот на стопицот.

Что это за набор нелепых лозунгов. Как быстро меняются методички. Буквально вчера все плюсовали статьи на тему «нужно проверять», а как случилась «лужа» мы всё забыли и оказывает проверять уже ненужно.

Даже на плюсах нельзя непроверить ошибку. В плюсах исключения.

В очередной раз игнорируя метаиронию контекста остальной части вашего комментария, можно лишь заметить, что да, куда им до лоровцев.

Ну да это очевидны. Вы в теме про ваш хелворд были слиты. Раст-адепты в теме про раст были слиты.

+3

Как тяжело жить, когда у всех вокруг одни сплошные методички и лозунги.


Mach7, кстати, не новый супер-язык, а PoC-библиотека за авторством Страуструпа и ещё пары крупных имён, а в C++20 не зря добавляют полноценные строки, а не последовательности char'ов, на уровне шаблонов, и думают, как разрешить выделять память в constexpr-контекстах, что ей можно было пользоваться в рантайме, но то такое.

-8
Как тяжело жить, когда у всех вокруг одни сплошные методички и лозунги.

Да нет, наоборот просто. Для адептов. Несёшь рандомную ахинею, кидаешься лозунгами, врёшь и т.д. И боты просто друг друга плюсуют, а неугодных минусуют.

Кстати, а что там случилось с предыдущими методичками? Кто там ходил в интернет из компилтайма и кому там непонятен был constexpr? Ах ну да, это же хабр. Неси ахинею, боты будут плюсовать, а потом слейся по-тихому. Как и сейчас.

Mach7, кстати, не новый супер-язык

О боже, что за нелепая пытка что-то из себя строить. Меня мало волнуют эта херня детсадовская. По поводу «новый» — очевидно, что меня абсолютно не интересует его новизна. Новый он не потому, что новый. А потому что новый в рамках контекста обсуждения.

а в C++20 не зря добавляют полноценные строки

Почему адепты пытаются мне с умным видом ретранслировать какую-то ахинею услышанную в интеренете?
, а не последовательности char'ов, на уровне шаблонов

Адепт поплыл. Вначале методичка была про «нету», а теперь вдруг после гугления оказалось, что есть. И адепт даже не думает что-то там отвечать. Забыл и пошел нести уже новую ахинею.

К тому же то, что там добавляют не имеет никакого отношения к строкам. Та методичка на тему «около С++-лозунгов для начальной школы» работает только в начальной школе, а ну и на хабре.

, и думают, как разрешить выделять память в constexpr-контекстах, что ей можно было пользоваться в рантайме, но то такое.

Очередной поток ахинеи, а именно ретрансляция услышанной в соседеней теме херни. К чему это, для чего? Нелепая попытка пустить пыль в глаза перед адептами с тем же уровнем понимания? Для справки. constexpr-аллокатор этот нелепая попса, которой заспамливали хабр не первый год. Да и само по себе оно колхоз.

+2
Адепт поплыл. Вначале методичка была про «нету», а теперь вдруг после гугления оказалось, что есть.

Как же оно "есть", когда его только добавляют в ещё не вышедший стандарт?

-4
Ладно, очевидно что боты просто так гадят и несут ахинею. Но всему же есть пределы.
Как же оно «есть», когда его только добавляют в ещё не вышедший стандарт?

Зачем вы что-то пишите, при этом нихрена не понимая? «строки в шаблонах» есть в С++ с момента появления шаблонов. Причём тут то, что выходит?

К тому же, методичка про стандарт не работает. Если того, чего нету в «вышедшем стандарте» — нету, то тогда нету раста. Что-то я не вижу от ботов рассуждений про «раста нету»? Чего же так?

Ну нести ахинею — это стандартное состояние бота.

0
> Как на визиторах будет выглядеть функция
Эту функцию крайне сложно написать хуже на любом языке и с любой техникой. И судя по исходнику типа внизу Вы и сами это заметили ;)
+2

Я бы предпочел сахарок этому варианту, но таки этот вариант любой ерунде с визиторами.

+2
То, что это попросту обман я уже писал. Необходимость что-то там дублировать обусловлена разделением на h/cpp-файлы. Никак не обусловлена С++ и это разделение может не использоваться.

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

-3
Так ведь именно в этом разделении и проблема. В других языках нет необходимости разделять модуль компиляции и заголовочный файл к нему

В С++ нету так же необходимости, а есть возможность.

а в C++ почему-то вот все так делают. Наверное, есть необходимость..

Ничего нет. Как минимум у вас нет никакой конкретики, зачем что-то писать без какого-либо представления о вопросе? Разделение кода не имеет абсолютно никакого смысла, его ноль. Там можно что-то начать рассказывать про раздельную компиляцию, но тут опять же проблема. Никакой раст не собирается пофайлово, а значит все эти рассуждения не имеют смысла. К тому же, какое-то ускорении это так же мифология.

technic93 В С++ никакие модули(это просто нелепый лозунг внешней пропаганды) ненужны, а макросы не имеют никакого отношения к модулям, либо теме.
+1

Я не совсем понял — Вы за что топите — что модули в С++ не нужны? Или они нужны, но разработчики стандартов их не осилили?

-1
Разделение кода не имеет абсолютно никакого смысла, его ноль

Но почему в таком случае во всех известных мне проектах на плюсах код разделен?

-3
Но почему в таком случае во всех известных мне проектах на плюсах код разделен?

Особенно в бусте и stdlib? Мне попросту лень отвечать на очередную идиотию в интернете. Эти нелепые аргументы уровня начальной школы уровня «мне»? С чего вдруг все проекты стали ограничиваться «мне»?

К тому же, даже если предположить, что их нет — это ничего не значит. Это такой же аргумент уровня начальной школы. Аргумент уровня «но почему в таком случае во всех известных мне лифтах было нассано?».

Что там вам известно — ни на что не влияет. Вы либо аргументируете за «нужно», либо продолжаете писать ахинею. Адепты всяких мастей вас будут плюсовать итак. Можете хоть рандомный набор слов писать.

+2
В С++ нету так же необходимости, а есть возможность.
В этих ваших крестах компиялтор тупо не соберёт код, если функция/переменная используется выше объявления. В 1980-ых такой подход может и имел смысл, но не в 2019.
-2
В этих ваших крестах компиялтор тупо не соберёт код, если функция/переменная используется выше объявления.

Меня не перестают удивлять эти срывы покровов. Объявления не имеют никакого отношения к инклюдам.
+1

Так модули в С++20 обещают добавить а многие компиляторы уже имеют какую-то реализацию. Сайты clang/gcc и статьи за авторством Страуструппа это не внешняя пропоганда. И речь идёт об одной простой вещи заменить #include по сути макрос на что то лучшее. Сборки больших проэктов занимают время, и поэтому их разделяют на несколько файлов которые компилируются раздельно и паралельно. Без объявления публичного интерфейса в хедере как у вас так получится? Неужили Вcе ваши проэкты инклюдится в один cpp?

0
У хаскеля свои недостатки. Собирает не быстро, зато весьма многословно и в большие бинарники. Меня, при небольшом знании хаскеля, больше всего удивляет почему нельзя в одном пространстве имён объявить два типа с одинаковыми именами полей.
+1
Собирает не быстро, зато весьма многословно и в большие бинарники.

Зависит от вашего кода. Код с type families и прочей ерундой на уровне типов, да, медленно собирается. Надо прикручивать jit к компилятору.


почему нельзя в одном пространстве имён объявить два типа с одинаковыми именами полей

Потому что это ломает вывод типов при их использовании.


Впрочем, есть расширение DuplicateRecordFields, которое это позволяет (правда, иногда таки приходится писать типы функций явно — см. выше про вывод типов).


Плюс, есть OverloadedLabels, но я пока не особо видел, чтобы оно как-то применялось в реальном коде.


Плюс, есть classy lenses.

+1

haskell-gi генерит биндинги с OverloadedLabels, получается очень удобно

+1

Никогда раньше не натыкался на эту библиотеку. Примеры кода выглядят интересно, да.

0
Потому что это ломает вывод типов при их использовании.
Инициализация — тип указывается явно. Если в сигнатуре не указано, то почему не сгенерировать несколько, а потом при вызове не подставить нужную?
+1

Именно это и делает DuplicateRecordFields, посмотрите там примеры, что становится возможным.

0
почему нельзя в одном пространстве имён объявить два типа с одинаковыми именами полей

Потому что каждое имя поля — ещё и функция, которая потом попадёт в это самое пространство имен...

0
Потому что каждое имя поля — ещё и функция, которая потом попадёт в это самое пространство имен...
Имхо это всё же зависит от дизайна языка. В том же elm c этим проблем нет
-1
Хорошо что хоть не полчаса собирался.

Типичное «слышал звон». cpp -E в студию.
-4
Визитор позволяет нашим проходам анализа обращать внимание только на части AST, в которых они нуждались, вместо того, чтобы сопоставлять шаблон по всей структуре AST. Это экономит много кода.

Ой, оказывается те другие попросту использовали «сопоставлять шаблон» и это было плохо. Но это ведь была проблема С++, а теперь оказывается rust-код отказывается от pm в пользу визиторов, которое в С++ попросту нативны(в отличии от rust, где это делается через тысячи костылей и боейлерплейта).

Каждая новая строчка пробивает очередной дно.
-14
Гадящие в карму адепты раста. Вы так и будите из треда в тред сливаться и гадить? Где же ваш код, где же ваши ответы? Нету, не можете? Зачем гадите?
+22
Совет. Не использую ни раст, ни С++, но чем больше вы используете фразы «Каждая новая строчка пробивает очередной дно», «сливаться и гадить», «гадящие в карму», «бред это ваши рассуждения вызванные вашем же непониманием», «да и попросту враньё», тем больше вам будут снижать карму, причем даже если вы писали по делу.

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

P.S. Я вам минусов в карму и комментарии не ставил.
-19
Совет. Не использую ни раст, ни С++, но чем больше вы используете фразы «Каждая новая строчка пробивает очередной дно», «сливаться и гадить», «гадящие в карму», «бред это ваши рассуждения вызванные вашем же непониманием», «да и попросту враньё», тем больше вам будут снижать карму, причем даже если вы писали по делу.


Ваши рассуждения не работают. Гадить начали до всего, а значит не в следствии. «бредом» было названо моё утверждение, где ваш коммент там? Нету. А что же так? Неужели вы просто пытаетесь что-то оправдываться, даже не разобравшись в теме?

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

Именно адептов. Эти адепты набегают табунами из всяких чатов и прочих сборов и минусуют. Это мною доказанный факт.

Я уже отвечал в нескольких темах и в этих самых темах я то и делал, что опровергал мифология раста. Как и побеждал адептов попросту кодом. Именно это их тригерит и вы можете пойти и изучит мои комментарии.

Таким образом с моей стороны есть аргументация, код и победы. Со стороны адептом — нет ничего. Они мотивированы гадить, что они и делают. Точно так же мы не видим их аргументации, но видим минусы.

Всё это было мною разобрано и доказано тысячи раз. Разберитесь перед тем как кого-то оправдывать.

Ах да, существуют адекватные адепты раста. Они способны писать код, способны понимать. Но проблема в том, что их очень мало и адекватный человек просто так не гадит. Гадит только тот, кому нечего сказать. Кто пытается заткнуть меня/неугодных.

Я вам ещё раз советую почитать историю Посмотреть как мне угрожали эти адепты. И где же все честные люди были, когда мне писали откровенные угрозы? А, никого не было.
-15
Адепты увидели ни на чём не обоснованный трёп и начали плюсовать того, кто нагло врёт и оправдывает их. И гадят, гадят. Ведь ничего иного они не могут.
-7
У вас бред преследования, обратитесь к врачу.

Отличная история. Адепты гадят и делают вид будто бы ничего не было. Ответы будут? Ответы за угрозы, ответы за то, что гадят? Где ответы? А Нету ответов, есть только «Гадят» и нелепые обвинения уровня начальной школы
+8

Я вас ни в чём не обвиняю, просто читая ваши комментарии складывается впечатление, что вы не совсем адекватны (именно реакция на критику, минусы в "карму" и т. п.). Почему вас так волнует, что кто-то в интернете поставил вам минус в какую-то "карму", как от этого изменится ваша жизнь? Социальный рейтинг у нас ещё пока не ввели. Почему вы так агрессивно и остро реагируете? Симптомы бреда преследования прослеживаются (какая-то группа лиц желает зла, гадит и угрожает).

-10
(именно реакция на критику, минусы в «карму» и т. п.).

В чём она неадекватно? В том, что обиженные адепты раста гадят в карму и минусуют, набегая на меня табунами?

Я вам так же советую изучить тему перед тем как делать какие-то выводы. Это уже не первая тема в которой они гадят. В корой угрожают. В которой они проигрывают.

Почему вас так волнует, что кто-то в интернете поставил вам минус в какую-то «карму», как от этого изменится ваша жизнь?

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

Почему вы так агрессивно и остро реагируете? Симптомы бреда преследования прослеживаются (какая-то группа лиц желает зла, гадит и угрожает).

У меня всё задокументировано. А вы просто кидаетесь нелепыми обвинениями.
+27
Я не адепт, но я поставил вам минус: вы общаетесь без уважения к собеседнику(даже если вы считаете, что конкретный собеседник вашего уважения недостоин, есть еще другие пользователи, которые вынуждены читать ваши ругательства), а кроме этого, еще и параноите, говоря, что кто-то там набегает и вас минусует, хотя ваши минусы вполне объясняются первым пунктом.

И да, я не хочу видеть ваши комментарии на хабре, мне неприятно, поэтому и голосую против вас — это способ саморегуляции сообщества.
На самом деле, вам не очень сложно побороть мое мнение и мнение других пользователей: достаточно просто приносить сообществу пользу, превышающую негатив от комментариев, например, писать полезные статьи.
+3
Несодержательно. Гораздо интереснее бенчмарки и сравнение временных затрат на разработку. Например, на С++ x человеко-часов, на Rust — y, на Python — z. Ну особенно интересно сравнить в этой задаче производительность Rust и C++.
+4
К сожалению такой подход будет содержательным, только когда у команд одинаковый опыт, и задача решается с использованием одних и тех же алгоритмов
+12

Я читал и жалел, что подобного курса не было у меня. Можно говорить, что российское образование впереди планеты всей и хакеры тоже, но на практике у меня в институте подобного курса в программе не было, да и вообще программа была довольно фиксированной без возможности выбрать курсы по своим хотелкам.


И я почему-то уверен, что если бы такой курс был, мало кто из наших студентов использовал бы немейнстримные языки типа Haskell/Rust/Okaml/Scala.


Что-то похожее по уровню хардкорности было в шаде, но он больше про машинное обучение, построения компиляторов и тому подобных курсов там нет.


  • В шаде на курсе по С++ писал интерпретатор лиспа. Как мне показалось, для подобных штук плюсы не очень удобно использовать, код получается довольно громоздким. Если бы я писал код на скале, было бы в 2-3 раза короче. Меня удивляет, что в статье выше код на плюсах получился не таким уж и большим — видимо, кто-то познал дзен и очень хорошо выбрал уровень абстракций.
  • Ещё (там же в шаде) на курсе по питону была домашка с интерпретатором питоновского байт-кода, написанном на питоне. Но, видимо, мой мозг слишком привык к статической типизации, т.к. динамическими фишками питона я почти не пользуюсь и в большинстве задач код получается таким же или дальше длинее, чем в скале.

P.S. А где вообще есть хорошие хардкорные курсы по классическому CS с построением компиляторов, алгоритмами и прочим? Интересуют как онлайн курсы, так и аспирантура в России/за границей.

+2
СПбГУ, Булычев или Григорьев (лаба языковых инструментов JB)
Будет Вам млн CS во всех проявлениях
+9
Можно говорить, что российское образование впереди планеты всей и хакеры тоже, но на практике у меня в институте подобного курса в программе не было


Это Миф. Я разговаривал со своим боссом (который получал образование у нас и в штатах и создал международную ИТ компанию с филиалами в России, соотвественно мог сравнить образование у нас и Западе). Вот он говорил «В России отличное школьное образование, отвратительное высшее и хорошие программисты». Вот такой парадокс.

Суть в том, на Западе они сами выбирают нужные им курсы, свое расписание и получают знания без воды и устаревших курсов уровня программирования на перфокартах. У нас хорошими программистами становятся не благодаря высшему образованию, а скорее вопреки. Просто программирование это чуть ли не единственная профессия в РФ для умных технических ребят, где можно получать очень неплохие деньги для РФ и уехать почти в любую страну на зарплату выше средней.

На Западе профессия программиста не настолько привлекательна, плюс школьное образование дает относительно хорошую базу, а высшее в РФ… ИМХО, проигрывает даже простому самообразованию, может не во всех программерских вузах, но во многих.
+2
Как уже было замечено в наших краях хорошее школьное образование, плохое высшее и отвратительные магистратуры, в США всё наоборот.

Возвращаясь к компиляторам: есть курс от computer science center www.youtube.com/watch?v=DKr45aBUtFU&list=PLlb7e2G7aSpQ4Ym2TWTYyMcfMevxpKoxj

Он там не один такой, есть прочитанные в другое время. Я сам не интересовался, за качество отвечать не берусь, но ознакомиться можете.
+1
P.S. А где вообще есть хорошие хардкорные курсы по классическому CS с построением компиляторов, алгоритмами и прочим? Интересуют как онлайн курсы, так и аспирантура в России/за границей.

У JetBrains и Computer Science Center вроде интересная магистратура в ИТМО, вот программа, а вот темы работ недавних выпусников. Конечно, много прикладного, но какой-то чел защищался по завтипам, например.
+3

Еще важный вопрос: сколько времени потрачено на разработку, отладку и какое количество багов было выявлено в процессе отладки?
Сколько времени требуется на написание одной безошибочной строки на каждом из языков?
Особенно интересно сравнение в этом плане двух реализаций на Rust.

+4
Думал будет всестороннее сравнение: скорость разработки, скорость выполнения, читабельность итд…
А тут просто wc -l сделали.
-9
Отлично! Чтд. Динамическая типизация рулит. Таскать с собой зверское мозголомство с ковариантными и контрвариантными шаблонами чтобы случайно переданную str вместо int отловил компилятор, при том что такая конструкция завалится на первом же тесте — ну такое.
+9

Да вроде бы в том и плюс — не писать тесты там, где может справиться компилятор/интерпретатор.

0
в статье как раз есть абзац про трудоемкость описания системы типов, при том что тесты придется прогонять и там и там.
+3

Дык если это код из разряда написал и забыл, то ок, а если понадобится за девочкой на питоне потом код поддерживать, то это будет сложнее, чем с остальными языками.

0

вот этого мы не узнаем… тем более по условию этого задания все писали на один раз.

+1

Я, наверное, слишком быстро читал, но пропустил этот абзац.


Или вы имеете в виду тот, где говорится о том, что корректность решения задания будет проверяться тестами?

0
Одна большая часть этого различия, вероятно, динамическая типизация. Только в нашем ast.rs 500 строк определений типов, и ещё много типов, определённых в других местах компилятора. Мы также всегда ограничены самой системой типов. Например, нам нужна инфраструктура для эргономичного добавления новой информации в AST по мере прохождения и доступа к ней позже. В то время как в Python вы можете просто установить новые поля на узлах AST.
+5

Так именно ради этого и есть trees that grow. Притом это не «напихали чо-т в словарь, вроде работает», а полноценные статически проверяемые тайпчекером аннотации.


Другое дело, что в Rust это нереализуемо (согласно тому, что я знаю о его системе типов).

+1

Поэтому и жаль, что исходников нет. Судя по косвенным признакам, упомянутым в тексте, там этим всем тупо не пользовались.

-1

за счет 2х времени и 3х обьема кода в котором так же можно ошибится… так себе плюс.

+2
Сравнение одинакового проекта в Rust, Haskell, C++, Python, Scala и OCaml
А в каком месте он одинаковый? Алгоритмы разные, абстракции разные, готовность разная, количество дополнительных функций тоже разное. Тем более, что больше всего отличаются друг от друга реализации на одном и том же языке. Почему код меряют в байтах и строках?
0

Это сравнение интересно однокурсникам автора и самому автору для резюме. Без более детальных подробностей что то обсуждать сложно.

+1
К слову, Waterloo самый лучший университет в Канаде в компьютерной области и пожалуй один из самых в мире. Там, к примеру, написали знаменитый Watcom и создали Maple. PHP, QNX и BlackBerry тоже оттуда же.
+1

Не кажется ли вам, что php лишний в этом списке? Это, конечно, целая эпоха, но вспоминать про нее не хочется
Ко всем остальным питаю теплые чувства

0

Да нет, нормальная технология, уровень сайтов-визиток тоже должен быть кем-то закрыт. Причем учитывая, что 80% веб-сайов это вордпресс поделия, то технология вполне себе успешна.

0

Для человека, который хочет просто в WISIWYG-редакторе накидать страницу, вообще без разницы, что там под капотом. Он просто возьмет Тильду, ВордПресс, что там еще модно — wix — как сервис, не вдаваясь в детали реализации.

-2

Отичный пример почему динамическая типизация это очень круто если применять правильно!
Кода гораздо меньше и результат получен одним человеком а не двумя-тремя.

0
что за маньяки ставят минус за динамическую декларацию в 21 веке? Это же не значит что переменная действительно должна быть object))
+3
Вначале выходит новый-прогрессивный язык без типизации, потом на нём пишут кучу кода, а потом, спустя время к нему через костыли в отдельных местах начинают прикручивать статическую типизацию, которая во-первых работает не везде, во-вторых требует огромной работы по переписыванию, написанию биндингов и так далее. Какой популярный динамический язык избежал подобной участи?
0
варианты не только «без типизации» и со «статической типизацией». Опять 25 — моё предложение — возможность включать / отключать типизацию, плюс инспекция действительно ли переменная динамическая, или её можно заменить одной (вроде auto ) или несколькими статическими в препроцессинге
Pyton фактически избежал типизации потому что arg:type толком не работает, сам тестил туда без какого либо сообщения пролезает тип который там быть не должен.
Да щас я тут кучу минусов понахватаю)
+1
моё предложение — возможность включать / отключать типизацию

А зачем статическую типизацию отключать? Это всё равно что посадить льва в открытую клетку — рано или поздно но лев выйдет. Рано или поздо, кто-то в своей библиотеки да отключит типизацию и заразит таким образом весь оставшийся код

Большинство рассматривает статическую типизацию как это реализовано в си, в лучшем случае в крестах или яве. Прогресс неумолим и уже появились гораздо более подходящие варианты.
плюс инспекция действительно ли переменная динамическая, или её можно заменить одной (вроде 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, ибо не смотря на свой дзен он умудряется быть непростым, непонятным и неявным. В итоге люди будут писать код который ещё и не работает
-1
Да уж, дзен питона где везде надо таскать self, которого становится по пол экрана, но при этом магическая комбинация подчеркиваний превращается в другую магическую комбинацию подчеркиваний молча — он прекрасен. Тем не менее питон — очень мощная штука, система типизации с динамическими атрибутами — это оч клево. Уверен на следующем витке чуток причесав синтаксис из этого сделают отличный инструмент.

Возвращаясь к Вашему примеру с crystal — это прекрасно, что такое отловит компилятор, но тут меня неизбежно всегда мучает вопрос про троллейбус из буханки. Да мы отловим на этапе компиляции некоторый весьма ограниченный набор багов, которые, на самом деле, одни из самых тривиальных. Но никакой компилятор не отловит ошибки в логике, да те же перепутанные местами аргументы одного типа, с которыми уже можно всего веселого наворотить, типа copy(input_file, output_file), а вызвать наоборот. Т.е. отбрасывание (ценой повышения трудоемкости написания кода в разы) заведомо небольшого количества проблем почему то постулируется как повышающее надежность до недостижимых другими методами высот. Что есть самообман, по-моему. То же TDD или контрактное программирование здесь выглядят гораздо более системным.

Вообщем придерживюсь мнения что статическая типизация суть анахронизм, абсолютно необходимый в компилируемых языках прошлого поколения, когда требуется точное знание размера бинарного представления объекта на этапе компиляции, там да. А коли у нас объект — это бирка с типом и счетчиком ссылок в куче — ну какой смысл таскать его тип в коде — понимать отказываюсь.
0
Да мы отловим на этапе компиляции некоторый весьма ограниченный набор багов, которые, на самом деле, одни из самых тривиальных.
Что быстрее — компиляция или прохождение всех тестов? А если используется библиотечный код? Что быстрее — указание типа или написание достаточного количества тестов? Насколько легко среде разработки будет указать на то, что тут неверный тип(например после рефакторинга)?
А коли у нас объект — это бирка с типом и счетчиком ссылок в куче
Счётчики ссылок это дорого, так как при каждом присваивании/выходе из зоны видимости их нужно обновлять. От циклических ссылок они не защищают. Единственное, зачем они нужны — избежать остановки на сборку мусора.
+4
Единственное, зачем они нужны — избежать остановки на сборку мусора.

И вот выходит у Вас из области видимости развесистое дерево умных указателей с подсчетом ссылок…
0
Циклы тут даже могут облегчить ситуацию, хотя память, да, может утекать. А вот stop world из-за одновременного обнуления счетчиков и освобождения многих объектов — нет-нет да и да…
0

Так это даже в языках с ручным управлением памяти прийдётся решать каким то своим пуллом объектов или умным аллокатором. Единственно что счётчики не будут вносить дополнительную нагрузку.

0
Звучит как будто Вы разделяете языки с ручным управлением памятью и применение умных указателей с подсчетом ссылок. Разве такие указатели применяются при другом управлении памятью?
0

Питон на основе подсчёта ссылок работает и деструктор вызывается сразу как объект покидает скоуп если счётчик стал равен нулю, а GC только для циклических случаев.
А на С/C++ подсчёт ссылок не нужен если иерархия владельцев ресурсов известна заранее.

-2
Я не знаток управления памятью в python, но есть два вопроса:
  1. Вы уверены, что объект с ненулевым счетчиком освобождается по выходы из области видимости,
  2. В питоне есть деструкторы? Прям у всех-всех типов? Как его задают для пользовательских типов?
+3

Я с Вами соглашусь и не соглашусь. Соглашусь по поводу того, что проблемы в логике кода не отловить. А не соглашусь, что статическая типизация анахронизм (или анахрЕнизм — кому как больше нравится, в зависимости от отношения). Я действительно хочу быструю компиляцию и быстрый код, а языки с динамической типизацией отстают в этом аспекте (но это очень холиварная тема). А еще чтоб среда подсказывала что и где (в случае динамической нестрогой типизации — среда тоже будет путаться и подсказывать не то или вообще не подсказывать).
С другой стороны, тот же Питон — прекрасен для БЫСТРОГО прототипирования. Здесь он вне конкуренции.

-1
стоп, вышеописанный код для тебя — статическая, динамическая типизация или безтипная? потому что тут может быть и статическая смотря как работает rand))
если потом будет присвоение другому типу там test = 42.0, согласен в питоне есть ряд вещей которые я бы подкоректировал или поудалял, сделав его таким языком чтобы других ненадо было ))
0
стоп, вышеописанный код для тебя — статическая, динамическая типизация или безтипная?
Сильная статическая неявная. Все три слова важны. Тип данной переменной String | Int. Это означает, что каждый раз, когда с переменной что-то происходит, компилятор проверяет, может ли данное действие быть совершено над данным типом. Метод is_a? есть и у String и у Int. По этому, компилятор принимает безусловный вызов метода. А вот upcase есть только у String и по этой причине компилятор требует явной проверки типа. Компилятор достаточно умён, чтобы понять что в первой ветке тернарного оператора тип String и не требует обязательного приведения типов.
потому что тут может быть и статическая смотря как работает rand))
Рекомендую поставить на машину и поиграться.
0
а с чемньть типа

a=[1,"str", [1,2]]
for i in a: i.upcase 

оно справится? Ибо самое интересное про типы, как известно, начинается в коллекциях.
+1
Crystal это ближе к ruby, чем к python.
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])
Если нужно, можно явно указать тип переменной.
+2
С тем же успехом можно и в C# писать как на javascript и получится ненамного многословнее. Вместо
val['sum'] = val['a'] + val['b']

Будет
val["sum"] = (int)val["a"] + (int)val["b"]

А если ещё и паттерн расширения прикрутить для хеша или объекта, то совсем динамический язык получится, поскольку можно будет не только значения брать, но и методы вызывать.

ИМХО динамическая типизация хороша либо для скриптов которые можно написать за пять минут, либо как промежуточное представление.
-1
С тем же успехом можно и в C# писать как на javascript

мне кажется вы мало програмировали на Python или JS раз говорите такое. Аргументы функции вы не сделаете динамическими.

+3

А params object[] на что?


Если же совсем-совсем динамика нужна, то в C# и тип dynamic есть...

0

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


Получилось даже забавно, можно в отдельную библиотечку оформить.

0

О результатах мы мало что знаем, особенно о стоимости отладки и доработки.

0

Автор был впечатлен, этого мне кажется достаточно в рамках этой статьи.

+1
В книге С.Свердлова «Языки программирования и методы трансляции» (2007) транслятор учебного языка реализован на нескольких языках: Паскале, Си, Обероне, Яве и Сишарпе. Это не только иллюстрирует принципы кросс-трансляции, но и позволяет получить множество сравнительных характеристик. На стр.400 эти характеристики сведены в таблицу.
Рецензия на книгу по ссылке.
Only those users with full accounts are able to leave comments. , please.