ИИ не понимает, что int64_t это будет дважды по int32_t. Для него это несвязанные слова и типы
И хотя мы достоверно не знаем, прав здесь ИИ или нет (это может зависеть от фактических типов аргументов), чушь нагаллюцинировал тут, всё же, не он, а вы
Да, такое понятие как strict aliasing действительно существует и оно действительно не позволяет доступ к int64_t через указатель на объект типа int32_t (при условии, что по указателю действительно лежит объект типа int32_t). Даже если их там два подряд лежит. Да, для стандарта языка и компилятора это тоже “несвязанные слова и типы”
Просто потому что стандарт языка оперирует объектной моделью. Всё в языке является объектом некоторого типа. И чтобы по указателю достать какое-то значение, нужно туда сначала положить объект или этого же типа, или типа, через который int64_t будет type-accessible. В нашем случае под указателем на int32_t практически наверняка никто заранее не создавал объект типа int64_t или объект, через который он type-accessible. Потому доступ к такому несуществующему объекту попросту нелегален с точки зрения языка, чтобы там где не лежало
Это значит, что компилятор будет при оптимизации исходить из предположения, что так делать нельзя. И если вы, всё же, сделали то, чего компилятор от вас не ожидал… Что он накомпилирует, исходя из ложного предположения, никто не знает. Стандарт говорит, что что-то неопределённое
Великолепно. Вы только что ограничили возможности std::lock_guard, std::scoped_lock и других RAII-механизмов
Какие последствия вы выбираете вместе с этим "решением"?
Падение производительности: замену маленьких скоупов критических секций, которые можно было выразить раньше на те большие скоупы, что можно с вашим предложением?
Снижение надёжности и безопасности кода: из-за перехода на хрупкие ручные lock/unlock, которые можно забыть вызвать из-за невнимательности или необработанного внезапного исключения?
Предпочтёте генерировать под это дело уродливые вымученные конструкции вроде такой?
Вы своим "гениальным" решением выбрали одновременно все варианты. Все плохие варианты. Потому что кто-то в вашей кодовой базе в одном месте предпочтёт потерю производительности, в другом кто-то предпочтёт хрупкий небезопасный код, а где-то ещё кто-нибудь предпочтёт обойтись просто уродливой конструкцией, вызывающей загадки на ревью и мистические слухи среди стажёров
Поздравляю, вы только что сделали код на несколько порядков более хрупким, багованным и сложноподдерживаемым... Там, где его и так было сложно отлаживать, где анализаторы практически не помогают — в критических секциях
И всё ради того, чтобы... Что? Чтобы убрать необходимость проверки от... анализатора, который у вас и так должен быть настроен в проекте по тысяче других веских причин? От линтера в IDE, который у вас и так наверняка есть из коробки? Или от специального флага компиляции компиляции, который тривиально добавить в сборку?
Так вот, иногда маленькие необдуманные дизайн-решения и запреты выливаются в огромные баги на ровном месте. Иногда, если совсем не думать, они оказываются куда страшнее суммы перечисленных проблем во всей этой статье
Зачем было по-умолчанию реализовывать удаление именно завершающих пустых строк из результирующего массива? Как будто нужно либо удалять все пустые строки, либо не трогать вообще
Возможно, это объясняется тем, что trailing comma — удобная и сверхпопулярная вещь, а вот leading comma практически не встречается
Прямо сейчас у меня в initramfs нет баша, вообще. И очень вряд ли, что у вас иначе. А шелл-скрипты там есть и бывают в немалом количестве. У меня там ash, вроде
А ещё в дебиане вызовется dash, если ваш шебанг вдруг окажется так весьма популярным #!/bin/sh вместо #!/bin/bash
А ещё нередко встречается busybox в эмбеде, там тоже ash
А ещё нередко в прод ставят контейнеры, в которых до предела минимизируют окружение. И если там и нужен шелл, то им тоже будет не баш
А иногда даже бывает нужна совместимость с zsh, в котором есть массивы, но доступ в которых работает иначе. Это, например, важно для скриптов автокомплита. Там вариант с bash -c несколько затруднителен
В первую очередь – того, кто читает код. Потому что чем больше стена, тем труднее верно оценить её (во всех смыслах). Страдает не только процесс разработки, но и ревью, и аудита. Да даже банально будут страдать коллеги, которые работают с тобой в общей кодовой базе
Анализатор прекрасно видит несоответствие отступов отсутствию фигурных скобок. Он это безошибочно подчеркнёт как misleading indentation
А первый пример банально нереалистичен и рассматривать его нет никакого смысла. Потому что стейтменты обычно длинные и в одну строчку, да ещё и с ифом обычно не влезают – не пройдут ревью
Я вот лично попадал в другую нелепую ситуацию:
if (foo) {
} else if (bar) {
} else if (baz) {
} { // потерял else
}
Что предложите ещё запретить, чтобы решить ещё и эту проблему? Или, может, всё же, запреты это не панацея?
Ещё есть пакеты Flatpak, которые изолируют приложение, но вообще-то могут быть созданы кем угодно
Так и deb-пакеты может кто угодно. Суть не в сборке, а в репозитории и мейнтейнерах. Не доверяете Flathub? У RedHat есть свой репозиторий flatpak-пакетов от их мейнтейнеров
Сделайте фигурную скобку { обязательной после if — никто почти и не заметит, но эта ошибка умрёт навсегда
А ничего, что статические анализаторы в современном мире и так подчёркивают жёлтым ошибочные конструкции? Нет, действительно, давайте уж вместо этого писать такие полотна, убивающие early return:
if (not valid(foo))
{
return error("don't do this");
}
Ну а кому не будет приятно увидеть такой шедевр искусства в своей кодовой базе?
Дополнительно в C++ добавили... Нет, не так. В C++ СПЕЦИАЛЬНО добавили случаи, при которых происходит хрен знает что. Не программа падает, нет. ХРЕН ЗНАЕТ ЧТО происходит. Undefined behavior. Собственно, на что был расчёт?
А как автор объяснит наличие таких специальных случаев в так называемом "нормальном пистолете"? Там аж целое специальное ключевое слово придумали, чтобы разрешить компилятору собирать такие специальные случаи
А ведь если бы SQL разделял запрос и данные (SELECT %s FROM %s, (name, age), users) и делал бы подстановку именно значений, а не текста, то не было бы инъекций
Вы не поверите, но в современном мире это так и работает. Движки баз данных знают, что такое биндинг параметров и поддерживают его. И современные ORM под капотом это используют
Это запишет в переменную окружения KEY пустое значение: environment: { KEY: } Это передаст значение KEY с хоста внутрь контейнера: environment: [ KEY ] Во-первых, почему можно написать одно и то же разными способами? Во-вторых, почему работает по-разному?!
Во-первых, обосную значимость второго. Иметь возможность форвардить переменную, не задавая и не вычисляя её значения – это очень полезно и наглядно. Намного нагляднее, чем environment: [ "KEY=${KEY}" ]
Во-вторых, первое работает по той причине, что yaml – это отдельная от docker compose сущность. Его парсер, вероятно, не позволяет отличить environment: { KEY: "" } от environment: { KEY: }. И потому эти две записи не могут давать разный результат. Либо обе дают пустую строку, либо обе форвардят значение
А вы бы хотели, чтобы environment: { KEY: "" } передавал не KEY, равный пустой строке, а форвардил непустое значение? Я бы этого не хотел, это было бы контринтуитивно
Я уж молчу о том, что даже вне контекста достаточно здравого смысла, чтобы понять, что KEY: задаёт <ничего>. И пустая строка является одним из ожидаемых результатов для <ничего>. И точно так же интуитивно очевидно, что в KEY нет задания значения, а потому это особый случай, который тоже интуитивно понятен большинству
Именованные аргументы всегда лучше, потому что они явные и не ломаются при рефакторинге
Это не так. Иногда у аргументов бывает натуральный порядок. Ну, например, вот: divide(numerator = 42, denominator = 123). Или join(first = root, second = subdirectory, ??? = filename). Кстати, да, first, second,... А до скольки нам так имена резервировать?
Кроме того, иногда аргументы выводимы из контекста, а перепутать их нельзя
Но что важнее, вы назвали преимущества именованных аргументов. Но умолчали их проблему. А проблема есть и она видна в первом примере. Они генерируют стену текста там, где и без них всё ясно
А у стен текста есть объективная проблема. Их труднее парсить глазами, труднее даётся визуальная навигация по коду. Это всё приводит к более быстрому истощению внимания разработчика. Быстрее истощается внимание – больше ошибок за 8 рабочих часов. Либо просто ежедневно работаем меньше – пишем меньше фич
Я чаще всего rsync использую локально. Так вот, -z не нужен в этом случае, а -v не имеет большого смысла с -P, одна фича которого в свою очередь тоже не нужна при локальном копировании, а вторая удачнее заменяется опцией --info=progress2. Вот из полезных флагов и остался только -a
Какого вообще чёрта --create-home и --no-create-home существуют одновременно, ведь если есть поведение по умолчанию, то нужен только противоположный флаг?
Во-первых, бывают нетривиальные алиасы и функции с сильно недефолтным поведением. Иногда переопределить недефолт дефолтом может быть проще, чем отказаться от алиаса
Во-вторых, такие флаги могут явно, чётко и однозначно выражать намерение – "да, именно это я и хочу сделать"
Тем более, что запоминать флаги иногда проще, чем дефолты
есть короткие флаги -g и -G, -M и -m, -p и -P, которые непонятно зачем вообще есть
Затем, что любой шелл – это в первую очередь шелл, а не язык программирования. Приоритеты шелла склоняются в сторону удобства интерактивного набора и возможности выразить собственную мысль командой так быстро, как только можно. Это позволяет дольше сохранять концентрацию внимания, не забивая мозг вторичной рутиной вроде правильного написания или перечитывания длинных имён, которые вполне возможно уже не влезли в строку
И хотя мы достоверно не знаем, прав здесь ИИ или нет (это может зависеть от фактических типов аргументов), чушь нагаллюцинировал тут, всё же, не он, а вы
Да, такое понятие как strict aliasing действительно существует и оно действительно не позволяет доступ к
int64_tчерез указатель на объект типаint32_t(при условии, что по указателю действительно лежит объект типаint32_t). Даже если их там два подряд лежит. Да, для стандарта языка и компилятора это тоже “несвязанные слова и типы”Просто потому что стандарт языка оперирует объектной моделью. Всё в языке является объектом некоторого типа. И чтобы по указателю достать какое-то значение, нужно туда сначала положить объект или этого же типа, или типа, через который
int64_tбудет type-accessible. В нашем случае под указателем наint32_tпрактически наверняка никто заранее не создавал объект типаint64_tили объект, через который он type-accessible. Потому доступ к такому несуществующему объекту попросту нелегален с точки зрения языка, чтобы там где не лежалоЭто значит, что компилятор будет при оптимизации исходить из предположения, что так делать нельзя. И если вы, всё же, сделали то, чего компилятор от вас не ожидал… Что он накомпилирует, исходя из ложного предположения, никто не знает. Стандарт говорит, что что-то неопределённое
Великолепно. Вы только что ограничили возможности
std::lock_guard,std::scoped_lockи других RAII-механизмовКакие последствия вы выбираете вместе с этим "решением"?
Падение производительности: замену маленьких скоупов критических секций, которые можно было выразить раньше на те большие скоупы, что можно с вашим предложением?
Снижение надёжности и безопасности кода: из-за перехода на хрупкие ручные lock/unlock, которые можно забыть вызвать из-за невнимательности или необработанного внезапного исключения?
Предпочтёте генерировать под это дело уродливые вымученные конструкции вроде такой?
Я отвечу за вас
Вы своим "гениальным" решением выбрали одновременно все варианты. Все плохие варианты. Потому что кто-то в вашей кодовой базе в одном месте предпочтёт потерю производительности, в другом кто-то предпочтёт хрупкий небезопасный код, а где-то ещё кто-нибудь предпочтёт обойтись просто уродливой конструкцией, вызывающей загадки на ревью и мистические слухи среди стажёров
Поздравляю, вы только что сделали код на несколько порядков более хрупким, багованным и сложноподдерживаемым... Там, где его и так было сложно отлаживать, где анализаторы практически не помогают — в критических секциях
И всё ради того, чтобы... Что? Чтобы убрать необходимость проверки от... анализатора, который у вас и так должен быть настроен в проекте по тысяче других веских причин? От линтера в IDE, который у вас и так наверняка есть из коробки? Или от специального флага компиляции компиляции, который тривиально добавить в сборку?
Так вот, иногда маленькие необдуманные дизайн-решения и запреты выливаются в огромные баги на ровном месте. Иногда, если совсем не думать, они оказываются куда страшнее суммы перечисленных проблем во всей этой статье
Возможно, это объясняется тем, что trailing comma — удобная и сверхпопулярная вещь, а вот leading comma практически не встречается
Вообще, по секрету, в баше есть ещё один вариант (или, скорее, их семейство):
И иногда это единственный доступный вариант, если утилита хочет шелл-команду одной цельной строчкой. Как
script, напримерПрямо сейчас у меня в initramfs нет баша, вообще. И очень вряд ли, что у вас иначе. А шелл-скрипты там есть и бывают в немалом количестве. У меня там ash, вроде
А ещё в дебиане вызовется dash, если ваш шебанг вдруг окажется так весьма популярным
#!/bin/shвместо#!/bin/bashА ещё нередко встречается busybox в эмбеде, там тоже ash
А ещё нередко в прод ставят контейнеры, в которых до предела минимизируют окружение. И если там и нужен шелл, то им тоже будет не баш
А иногда даже бывает нужна совместимость с zsh, в котором есть массивы, но доступ в которых работает иначе. Это, например, важно для скриптов автокомплита. Там вариант с
bash -cнесколько затруднителенЭто не всегда решает автор скрипта
В первую очередь – того, кто читает код. Потому что чем больше стена, тем труднее верно оценить её (во всех смыслах). Страдает не только процесс разработки, но и ревью, и аудита. Да даже банально будут страдать коллеги, которые работают с тобой в общей кодовой базе
Речь про этот пример из статьи:
Анализатор прекрасно видит несоответствие отступов отсутствию фигурных скобок. Он это безошибочно подчеркнёт как misleading indentation
А первый пример банально нереалистичен и рассматривать его нет никакого смысла. Потому что стейтменты обычно длинные и в одну строчку, да ещё и с ифом обычно не влезают – не пройдут ревью
Я вот лично попадал в другую нелепую ситуацию:
Что предложите ещё запретить, чтобы решить ещё и эту проблему? Или, может, всё же, запреты это не панацея?
Так и deb-пакеты может кто угодно. Суть не в сборке, а в репозитории и мейнтейнерах. Не доверяете Flathub? У RedHat есть свой репозиторий flatpak-пакетов от их мейнтейнеров
Да, прокинуть переменную для дисплея и сокет от xorg/wayland – это неподъемная задача, конечно. Никто не справится:
Ах да, не забудьте в контейнере поставить само приложение и шрифты к нему, конечно. Это тоже нетривиальное знание, знаете ли
Вас никто не заставляет так делать. Современный chmod вполне принимает опции в формате
chmod u=rwx,g-w,o+xА ничего, что статические анализаторы в современном мире и так подчёркивают жёлтым ошибочные конструкции? Нет, действительно, давайте уж вместо этого писать такие полотна, убивающие early return:
Ну а кому не будет приятно увидеть такой шедевр искусства в своей кодовой базе?
А как автор объяснит наличие таких специальных случаев в так называемом "нормальном пистолете"? Там аж целое специальное ключевое слово придумали, чтобы разрешить компилятору собирать такие специальные случаи
Вы не поверите, но в современном мире это так и работает. Движки баз данных знают, что такое биндинг параметров и поддерживают его. И современные ORM под капотом это используют
Во-первых, обосную значимость второго. Иметь возможность форвардить переменную, не задавая и не вычисляя её значения – это очень полезно и наглядно. Намного нагляднее, чем
environment: [ "KEY=${KEY}" ]Во-вторых, первое работает по той причине, что yaml – это отдельная от docker compose сущность. Его парсер, вероятно, не позволяет отличить
environment: { KEY: "" }отenvironment: { KEY: }. И потому эти две записи не могут давать разный результат. Либо обе дают пустую строку, либо обе форвардят значениеА вы бы хотели, чтобы
environment: { KEY: "" }передавал неKEY, равный пустой строке, а форвардил непустое значение? Я бы этого не хотел, это было бы контринтуитивноЯ уж молчу о том, что даже вне контекста достаточно здравого смысла, чтобы понять, что
KEY:задаёт <ничего>. И пустая строка является одним из ожидаемых результатов для <ничего>. И точно так же интуитивно очевидно, что вKEYнет задания значения, а потому это особый случай, который тоже интуитивно понятен большинствуЭто не так. Иногда у аргументов бывает натуральный порядок. Ну, например, вот:
divide(numerator = 42, denominator = 123). Илиjoin(first = root, second = subdirectory, ??? = filename). Кстати, да,first,second,... А до скольки нам так имена резервировать?Кроме того, иногда аргументы выводимы из контекста, а перепутать их нельзя
Но что важнее, вы назвали преимущества именованных аргументов. Но умолчали их проблему. А проблема есть и она видна в первом примере. Они генерируют стену текста там, где и без них всё ясно
А у стен текста есть объективная проблема. Их труднее парсить глазами, труднее даётся визуальная навигация по коду. Это всё приводит к более быстрому истощению внимания разработчика. Быстрее истощается внимание – больше ошибок за 8 рабочих часов. Либо просто ежедневно работаем меньше – пишем меньше фич
Я чаще всего
rsyncиспользую локально. Так вот,-zне нужен в этом случае, а-vне имеет большого смысла с-P, одна фича которого в свою очередь тоже не нужна при локальном копировании, а вторая удачнее заменяется опцией--info=progress2. Вот из полезных флагов и остался только-aВо-первых, бывают нетривиальные алиасы и функции с сильно недефолтным поведением. Иногда переопределить недефолт дефолтом может быть проще, чем отказаться от алиаса
Во-вторых, такие флаги могут явно, чётко и однозначно выражать намерение – "да, именно это я и хочу сделать"
Тем более, что запоминать флаги иногда проще, чем дефолты
Затем, что любой шелл – это в первую очередь шелл, а не язык программирования. Приоритеты шелла склоняются в сторону удобства интерактивного набора и возможности выразить собственную мысль командой так быстро, как только можно. Это позволяет дольше сохранять концентрацию внимания, не забивая мозг вторичной рутиной вроде правильного написания или перечитывания длинных имён, которые вполне возможно уже не влезли в строку
Загадка может внезапно проясниться, если заглянуть в документацию и увидеть, что там бывает не только
-, но и+, и даже=с?Не каждый шелл является башем башем, поддерживающим массивы