Search
Write a publication
Pull to refresh
56
0
Сергей Садовников @FlexFerrum

Пользователь

Send message
Нет. Лично мне на них пофиг. Вот на github-аккаунт с публичными репозиториями — уже нет. Хотя там, выше, в камментах, кто-то и не очень жаждет его заводить. На статьи здесь, на хабре, на публикации, на выступления на конфах — тоже не пофиг. Но, понятно, далеко не у всех такое есть в анамнезе.
Вот простой вопрос: как алгоритмическая задача в стиле «сделайте с двумя векторами вот такую вот фигню» проверит умение кандидата работать с многопоточным кодом, его знание основных подводных камней акторных архитектур и прочей, гораздо более полезной в хозяйстве фигни? Ну хорошо, мы поняли, что на leetcode и прочих ресурсах он натренировался. А реальные то задачи он умеет решать? Это я сейчас говорю как человек, который занимался подбором и собеседованием кандидатов. Мне вот лично пофиг, может ли кандидат смержить два неотсортированных вектора (погуглит — и сможет). Мне гораздо важнее, чтобы он фигни в коде не написал, от чего потом рейс-кондишены случаются, например. Или buffer overrun'ы по незнанию. А опыт он чаще закопан именно в таких вот тонкостях.
За пожелание — спасибо. Проблем как таковых нет. :) Но предложенное вряд ли сработает с топовыми международными компаниями. Они вряд ли согласятся — им проще послать и попросить следующего из очереди. :) Вопрос был больше риторический.
Сейчас, в процессе поиска работы, тоже с таким столкнулся. И возник вопрос: а какой именно скилл, полезный для компании, таким образом тестируется? Ответ найти не смог. А поскольку от результата такого теста зависит дальнейшее продвижение по интервью — скилл, получается, ключевой.

Да, полагаю, правильнее так. Но это цитата из оригинального документа. :)

Ну вот, собственно, в субботу на C++ Russia буду рассказывать об одном из решений, которое и парсеры IDE смогут прожевать (просто потому, что всё в итоге в явный исходный текст превращается). Сами метаклассы (на уровне компилятора) — сильно сочувствую тем, кто будет это реализовывать.

Qt с его moc заточены под конкретные кейсы. Ну и требуют, собственно, Qt и его инфраструктуры. Средство хорошее, работающее, но, на мой взгляд, нишевое. Можно, конечно, было упомянуть в разделе про генерацию кода, но не хотелось сильно объём раздувать.
У Java будут свои слабые места. Но другие. Но так то да — для кого-то может быть и проще. Для других — уже нет. Скажем, где-то Java может оказаться неприменимым как инструмент.
Тут как бы дело в том, что в качестве парсера «входных данных» у меня clang frontend полным ростом. Можно было бы, конечно, сделать биндинг из него в питон или в Lua… Но таки хотелось, чтобы шаблоны выглядели шаблонами, а не программами на питоне/Lua. :)
Ну, можно и оператор индексирования для списка написать. Тут ведь вопрос — нужно ли. :)
Хм. Интересная интерпретация. :) Я думал, что «техническая причина» — это невозможность (техническая) в языке вернуть заведомо невалидное значение независимо от его типа. В С++ такой возможности действительно нет. А то, что я перечислил — это исключительно вопросы контракта. Можно реализовать так, а можно иначе. Принципиальных технический препятствий в языке для любого из вариантов нет.

Не всё так просто. Сейчас эту техническую составляющую можно убрать — pop может возвращать std::optional. Но такая операция даёт разработчику (by design!) меньше гарантий, чем пара top/pop. Возникает, например, интересный вопрос: что делать, если во время создания копии объекта для возврата из pop возникло исключение? Что делать, если это случилось на этапе создания возвращаемого значения? Гарантировать, что pop всегда будет делаться через move нельзя — для объектов в стеке эта операция может быть попросту не определена. Полагаться на RVO/copy elision тоже не всегда можно.
В примере с in такая реализация сужает контракт. Работая с итераторами (казалось бы, удобно!) быстро утыкаешься в то, что для ассоциативных контейнеров и сиквенсов они разные. А стоит переключиться на значения — см. выше.

Хм… Странный подход. Сейчас, вроде, в C++ наметился тренд в сторону функциональной нотации. То есть не key in map, а contains(map, key) например. Но это ладно, это мелочи. В предложенном методе нарушается подход Single Responsibility. Это как если бы в std::stack был метод pop_and_get (например), или pop не только бы извлекал элемент со стека, но и возвращал бы его. Но такого метода нет (можно у Саттера почитать, почему) — и это правильно. Так же и тут: зачем в одном операторе совмещать две разных ответственности? Оператору in оставить возвращаемое значение bool. А то, что хочется, реализуется чуть проще:


template<typename M, typename K>
std::optional<typename M::const_iterator> from(const M& m, K&& key)
{
    auto p = m.find(key);
    if (p != m.end())
         return p;

    return std::optional<typename M::const_iterator>();
}

//...

if (auto res = from(some_map, "cat"))
{
     std::cout << res->second << std::endl;
}

Можно даже optional на значение возвращать, чтобы не только map'ы, но и списки с векторами поддержать.

Угу. Да. Вижу. github.com/llvm-mirror/clang/blob/4418c5b56fafe30928f418be4eaee39d275628dc/lib/Frontend/FrontendActions.cpp#L157

На 3.7 мне этот патч приходилось самому класть. А судя по блейму, появилось это не раньше пятой версии.

Вам спасибо за развёрнутый комментарий. Читать было интересно.


Описанная картина довольно мрачная и примерно соответствует действительности, но некоторые факты позволяют смотреть в будущее более позитивно

С моей ТЗ основная проблема в том, что очень сложно (в данном случае) усидеть на двух стульях. Всё-таки задача просто компиляции и задача поддержки IDE — достаточно разные, чтобы можно было эффективно их обьеденить под одной крышкой. Да, интегрируют, да, пользуются, но за прошедшие семь лет развития и того, и другого (а это довольно внушительный срок) — результат не очень впечатляет. По крайней мере меня. :)


Если не использовать libclang (и не заботиться о том, чтобы работать со старыми стабильными версиями clang-а из коробки), то можно сделать достаточно много через C++ API уже сейчас

Именно на этом API и сидел. В том числе для того, чтобы исключать лишние преобразования типов и дополнительного менеджмента.


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

Хорошая цель. :) Насколько достижимая — вот вопрос. Но это как раз в тему форка кланга и пиления вполне конкретных фичей, специфичных для IDE, без оглядки на функции компиляции. Кстати, хороший вопрос возник: а что IDE должно делать с constexpr-функциями? А если они сложные и ресурсоемкие? :)


И libclang, и clangd умеют работать с т. н. "preambles" — это автоматически генерируемые PCH для всей пачки #include-директив, которые идут в начале файла. Работает очень хорошо — если первая подсветка — примерно как компиляция, то последующее редактирование — гораздо приятнее.

Да. И я даже ходил в эту сторону. Но есть нюанс. Даже два. Первый описан в статье — ошибки в хедере, и создание преамбулы обламывается. А ошибки возникали у меня как-то слишком часто (и в основном в системных заголовках). Второй — pch можно перекомпилировать реже, а польза от него почти такая же. Только в редких проектах исходники включают вязанку заголовков, и все они из project root. Чаще основной объем приходится на библиотеки/фреймворки. А так — да, что pch, что преамбула — это сериализованное AST. Шагов до комбинированния итогового AST из нескольких — совсем чуть чуть осталось. Но для того, чтобы такое комбинированния было возможно — сам clang парсер должен быть глубоко интегрирован в IDE. То есть IDE (та часть, которая занимается обработкой кода — с индексами и прочим) становится как бы фронтендом для библиотек clang'а. Но чтобы так сделать — довольно существенно всё перепиливать надо.

Я не могу сходу ответить на этот вопрос — надо изучать реализацию. Могу лишь сказать, что наличие возможности в рамках одного проекта работать над исходниками с разными опциями компиляции/тулчейнами (что может серьёзно отражаться на AST) наличие единого сервера для моделей кода исходников становится сомнительным бенефитом. В контексте С++, разумеется. Но, возможно, это проблема как-то решена.
Да. Есть такая фича у clang. А теперь история о том, как я её нашёл. В попытках поднять перформанс работы связки IDE + clang я полез смотреть, а на что же clang тратит процессорное время. И довольно быстро обнаружил в первой двадцатке функций алгоритм подсчёта дистанции Левенштейна. «Что за фигня? — думаю, — Зачем?». Полез копаться дальше и наткнулся как раз на алгоритм подбора подходящего идентификатора к «неправильно написанному» в рамках видимого скоупа. Хорошая фича для компилятора. Но при работе в связке с IDE, когда компиляция запускается буквально на каждый чих — эмм… Не уверен. При условии, что невалидных идентификаторов может быть в достатке по тем или иным причинам. Пробежаться по скоупу может может и код, который автокомплит делает, а не FixIt-хинты для найденных ошибок. При работе в связке с IDE, разумеется.
Всё так. Только начиная с 4.7 clang backend по-умолчанию включен. И, насколько я понял из комментариев к релизу, развивать они дальше будут именно эту ветку, а не самописный парсер.
Да. Всё так. :) Приходится извращаться.

Information

Rating
Does not participate
Location
Москва и Московская обл., Россия
Date of birth
Registered
Activity