All streams
Search
Write a publication
Pull to refresh
4
0
Александр Гиль @sashagil

Программист; преподаю в маткружке для детей

Send message
In my current projects I am inclined to not follow the last recommendation ("Never dereference or call a method of non-local shared_ptr, because this puts object outside of shared_ptr control (instead, first make a local copy of shared_ptr).").

That recommendation does not blend well with preceding ones that are not that over-protective or super-defensive. Let it crash, so to speak.

Your 2-part article is very good, I'll be glad to see more!
Regarding using English — sure why not (I cannot update the initial comment but I'll retell the core concern in brief below). Thanks for the links you provided in the post, I will trace details when I have a better chance (over the weekend, maybe). Thank you for listing arguments for not passing smart pointer arguments in favor of passing & references (stating explicitly that the contract guarantees that the reference is not null always) or * pointers (stating explicitly that the contract allows nullptr reference on some occasions so the callee has to handle that possibility in a meaningful way). I've read Core Guidelines and I agree, but a consideration linked to the last recommendation (see below) leaves a residue so to speak.

Regarding my core concern on the last section of your post: the last recommendation of that section kind of introduces a complication twist to «prefer using &, * and not smart pointer argument types» rule. Let' get back to my example: I am implementing a class that has a member variable shared_ptr<widget> m_p. It is guaranteed to be not null at a moment and I need to call an external function named «use» that takes widget&. Being a thorough defensive programmer (as the last recommendation teaches me) I have to do the following (now switching to auto):

auto pStabilized = m_p;
use(*pStabilized);

— because from a formal point of view I have no control over what other functions «use» will call. Note that in case of 5 reference arguments of «use» the caller will have 6 lines of code introducing 5 local variables that are used in one line of code — the «use» call. Well, it takes an effort to be a thorough defensive programmer (and never mind the impact on code readability / maintainability). Now imagine that I am not only doing that in my code but also insist on this pattern while doing code reviews…

Do you agree that this is the right conclusion when all recommendations of the last section are taken into account? If you have a better idea on how to reconcile all recommendations from the last section, please share! I'll do some experiments most likely, but not earlier than over the next weekend.
Большое спасибо, Алексей!

Хотел бы обсудить последний пункт последнего раздела «Never dereference or call a method of non-local shared_ptr, because this puts object outside of shared_ptr control (instead, first make a local copy of shared_ptr)» в сочетании с "// global (static or heap) or aliased local" комментарием в иллюстрирующем коде.

Далее в иллюстрирующем коде создаётся стабилизирующая локальная копия shared_ptr. Мотив понятен — действия внутри f могут привести к удалению widget-а. Таким образом, этот код иллюстрирует определённый «параноидально-защитный» паттерн программирования: в месте использования определённого типа ссылки (shared_ptr) знай, что безопаснее защититься от reentrancy pitfall.

Давайте теперь, взяв на вооружение этот совет (т.е., встав на сторону данного «параноидально-защитного паттерна»), рассмотрим первые две рекомендации раздела:

  • Do not pass shared_ptr (or other countref alternatives) by value, if you do not need to count references (reduces performance due to atomic operations with counter) — prefer passing objects by * or & as usual.
  • Do not pass shared_ptr (or other countref alternatives) by reference or const reference, if you do not need to count references — prefer passing objects by * or & as usual.


Давайте попытаемся совместить логику этих рекомендаций с «параноидально-защитным» паттерном. Caller имеет на руках shared_ptr на widget, который нужно передать в callee (под названием «use» — callee не интересуют манипуляции с ownership widget-а, он просто что-то делает с самим widget-ом). Рекомендовано передать ссылку на widget (то есть в сигнатуре use тип параметра — widget&). Получается, чтобы соблюсти «параноидально-защитный» паттерн, caller перед вызовом use должен удостовериться, что передаваемая ссылка подкреплена локальным инстансом shared_ptr. То есть, если shared_ptr на руках, например, member variable под именем m_p, надо делать так:

shared_ptr<widget> pStabilized = m_p;
use(*pStabilized);

Эту манипуляцию можно было бы выразить короче, если бы (в разрез с первой рекомендацией раздела) параметр use был бы shared_ptr (переданный по значению):

use(m_p);

То есть, в случае принятия обоих рекомендаций раздела (первой и последней) caller должен платить за комфорт callee и создавать стабилизирующие локальные копии не-локальных shared_ptr, так?
Согласен, отличный фильм, пресматривал раза два. Отличная эпизодическая роль у Henry Rollins-а. Ну, что там говорить.
Что вы посоветуете первым посмотреть, если выбор между nom и rust-peg?
Комментирую свой «другой, напишу в комментариях))» выбор в голосовании. «Захватить власть над человечеством» — ну это как люди захватили власть над муравьями, или таки-нет? Людям муравьи по барабану (хотя нечаянно могут всех спалить, ну так получилось, не специально). Та же история с пост-хьюман соображениями, «что там будет?» — посмотрите, люди в шахматы друг с другом продолжают играть не смотря на победу Deep Blue над Каспаровым… сколько лет там назад это было? Ой, 22 с хвостом года назад. Что-то сильно в мире любителей шахмат изменилось за эти 22 года? Нет. Один мой знакомый (сильный шахматист) искал в партиях AlphaZero плодотворную дебютную идею, не нашёл и был сильно тем разочарован (ну, как если бы муравьи не нашли интересных идей для совершенствования муравейников у людей… которые свои муравейники строят непонятным муравьям способом :) )
Выступление Херба про конкретный проект https://github.com/hsutter/gcpp называлось Lifetime Safety By Default — Making Code Leak-Free by Construction, он его делал примерно 3 года назад на CppCon, слайды здесь, видео здесь — это не про статический анализ, поэтому решил привести ссылки. Пользуясь случаем, про raw pointers (*) и references (&). Некоторое время назад я программировал, избегая их использования, возвращая результатами функций смартпойнтеры и передавая их аргументами, например, как в getChild в вашем коде. Однако, сейчас я пересмотрел этот подход в сторону рекомендаций Core Guidelines, конкретно F.7: For general use, take T* or T& arguments rather than smart pointers, F.60: Prefer T* over T& when “no argument” is a valid option и R.30: Take smart pointers as parameters only to explicitly express lifetime semantics. Херб подробно разбирает этот вопрос в GotW #91 Solution: Smart Pointer Parameters. Конечно, открытие «сырых» ссылок / указателей упрощает злоупотребление, идея в том, что злоупотребления пресекаются статическим анализатором (которому в таком контексте нужно не точно анализировать все возможные варианты lifetime management, а предупреждать о нарушениях конкретной модели lifetime management, предлагаемой в Core Guidelines). Насколько хороши в этом плане существующие анализаторы вроде clang-tidy, сейчас сказать не могу (надо когда-нибудь разобраться, конечно).
Если вы собираетесь писать небольшой генератор, почему бы не нацелить генератор на анализ графа сильных ссылок (для предотвращения циклов) ещё в фазе кодогенерации? Ещё один момент: мне попадались статьи Херба Саттера на данную тему, вам интересно было бы прочитать? Он нацеливался на добавление нового смартпойнтера в стандартную библиотеку (если я не путаю), но не довёл до этого.
Не хотел спорить — однако, заглянул в это обсуждение месяц спустя по другому поводу, заодно попробовал прояснить для себя этот терминологический вопрос (и пока решил остаться при своём мнении). Попадётся на глаза Dragon Book, загляну. Однако, на данный момент я в своей неправоте не убеждён — например, англоязычная Википедия перенаправляет «Syntax Analysis» на «Parsing» — страницу, начинающуюся с фразы «Parsing, syntax analysis, or syntactic analysis is the process of analysing a string of symbols, …». Далее, русская программистская терминология довольно последовательно следует за английской по понятным причинам.

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

По поводу предметности несогласия о терминологии: язык меняется со временем (я написал предыдущей комментарий на основании субъективных наблюдений — со временем «парсинг» попадается чаще и чаще в местах, где раньше я бы ожидал прочитать «синтаксический анализ»). «Абсолютная истина» может быть определена в узких (по тематике и времени) контекстах; более предметным спор становится в кругу экспертов (мне же с парсингом / синтаксическим анализом не так часто приходится иметь дело — большей ясности хотелось для себя лично).

В условиях неоднозначности я, если мне это сильно занятно, пытаюсь выяснить наиболее частое словоупотребление, и использовать именно его. Пример — ошибочно использовал везде слово «компонента» в женского роде (как в «компонента связности» и в прочих математических и физических «компонентах»), удивляясь, всё чаще встречая его в мужском роде (учился я на математическом факультете, а работать стал программистом). Постепенно осознал, что при употреблении в инженерном контексте большинство собеседников употребляют слово «компонент» в мужском роде, так что ввиду этого мне следует себя переучить — и вообще, это два разных слова, которые я принимал за одно (да, так и есть, ещё раз заглянул в Википедию, русскоязычную уже на этот раз). Возможное различие в словоупотреблении «парсинг» и «синтаксический анализ» беру на заметку, но пока — не убеждён.
Вы пишите о англоязычной (перешедшей также в русский язык) терминологии, а я упомянул французскую, вспомнив рассказ учителя программирования 30-летней давности примерно. Насколько справедливо это утверждение (о том, что французы используют французское слово «октет» в значении английского / русского «байт»?) было тогда, и насколько справедливо оно сейчас? Точно не знаю, но беглая проверка поисковиками меня убедила, что скорее, оно было и остаётся справедливым. Спрошу при случае у коллеги-француза.
Интересно, спасибо. В разделе про DSL вы пишете про «Реализации на базе flex и bison», это очень сурово и олдскульно — у меня опыт с ANTLR довольно позитивный (не уверен, что буду в следующий раз использовать ANTLR, скорее, попробую ещё что-нибудь… Но уж точно не flex и bison! 21 век всё-таки настал :) ). Что сегодня важно для хорошего DSL — реализация LSP (Language Server Protocol) с самого начала. Дойдёт до «следующего раза», буду ориентироваться на инструменты, облегчающие реализацию LSP в первую очередь.
Отличная подборка, спасибо! Добавления:

«Когда-то давно» www.youtube.com/watch?v=o5jgrUVNhWY (люблю пересматривать, интересная графика и саундтрек интересный)

«Урок» www.youtube.com/watch?v=_Z9G7AHb05g (кажется, «Урок» был выше в комментариях, потом проверю)
Достойное примечание, напомнило про «октет» в французском вместо чуждого «байт». Исторически, боюсь, «лексический анализ» уступит «парсингу», увы. Кстати, с языковой точки зрения «лексический анализ» — устаревшее заимствование, архаичное, в сравнении с более современным заимствованием «парсинг».
Немного обидно читать про «владение» там, где хотелось услышать про линейную логику. Упор на иммутабельные (пардон, неизменяемые) локальные переменные при том, что поля структур мутабельные (пардон, изменяемые) по умолчанию… Ой, встаньте дети, встаньте в Krug.
Предложение переводчику: «был ли Джаг «серым зелёным»» — лучше «седым зелёным», по-моему (другой смысл gray, что потребовало в английском оригинале отдельного пояснения, в русском ненужного при употреблении перевода «седой» вместо «серый»).
Просмотрел комментарии — никто не похвалил за загадку с Coil, а мне она понравилась!
Спасибо! Отправил вам личное сообщение минуту назад в надежде переключиться на e-mail переписку по возможности.
С удовольствием читаю ваши заметки на этом сайте — как из этой серии, так и другие (по программированию, в частности — я по профессии программист, хотя в институте получал образование с математическим уклоном).

С моей точки зрения эта глава — весьма добротная, затрагивает важные вопросы и потому заслуживает включения в книгу. Небольшая поправка: в уравнении для нахождения корня из двух x через представление этого числа в виде цепной дроби вы в левой части отняли единицу (x — 1 = …), а в правой оставили (… = 1 + …), правильное уравнение получится, если убрать эту «1 + » в правой части.

Приведу пару примеров, иллюстрирующих важность достаточно детального рассмотрения в книге условных вероятностей и формулы Байеса. Один — история про Эрдоша, который не поверил в правильность рассуждений о знаменитом парадоксе Монти Холла, пока ему не продемонстрировали численный эксперимент на компьютере — при том, что Эрдош прекрасно владел теоретическим аппаратом и, среди прочих заслуг, продемонстрировал эффективность применения аппарата теории вероятностей при решении строго определённых задач дискретной математики. Ну, парадокс Монти Холла лучше оставить в стороне из-за нечёткостей его формулировки и возможностей различно его интерпретировать. В следующем примере проблема нечёткости формулировки задачи на условные вероятности практически отсутствует: автор заметки на Хабре отреагировал на дискуссию в комментариях и исправил формулировку задачи.

Я имею в виду вот это обсуждение задачи про 12 стульев: https://habr.com/post/225031/ — я там недавно оставил подробный комментарий внизу обсуждения. Мне кажется, эта задача может послужить хорошей игровой моделью экспериментальной проверки теоретических гипотез, в процессе которой после каждого эксперимента уточняется уверенность в том, что гипотеза согласуется с реальным миром.

Пользуясь случаем, хотел бы предложить вам обсуждение некоторых смежных тем — в личной переписке, потому что прямого отношение к данной главе вашей будущей книги они не имеют, так что я не хотел бы мусорить в комментариях здесь. Я сейчас отправлю вам небольшое затравочное сообщение на этом сайте в надежде, что вы отзовётесь.
Почему же, я на Idris смотрю, и дичью он мне не кажется. Вы можете сравнить ATS и Idris?
Заинтересовался, что такое ATS — выглядит, как будто один автор, или кафедра в каком-то китайском университете пилит понемногу, диковато как-то.

Information

Rating
5,436-th
Location
Redmond, Washington, США
Registered
Activity