В rust есть trait’ы. В C мне вместо них не раз приходилось использовать либо функции, генерируемые макросами, либо .c.h файлы. Не знаю, как называется последняя техника, но уверен, что не я первый её придумал: идея в том, что у нас есть файл frob.c.h вида
#define FROB_PREFIX froba
#define FROB_RETURN_TYPE int
#include "frob.c.h"
#undef FROB_RETURN_TYPE
#undef FROB_PREFIX
#define FROB_PREFIX frobs
#define FROB_RETURN_TYPE int
#define FROB_ACTION(a, b) (a) <<= (b)
#include "frob.c.h"
#undef FROB_ACTION
#undef FROB_RETURN_TYPE
#undef FROB_PREFIX
int main(const int argc, const char *const *const argv)
{
if (froba_frobnicate(argc) > 0) {
return frobs_frobnicate(argc);
} else {
return 0;
}
}
(#undef тут везде только чтобы не засорять пространство имён).
Такая вариация на тему generic’ов не слишком удобна, но она имеет несколько важных преимуществ перед определением функций в макросах:
В отладчике функции теперь не в одну строку и вы можете нормально ставить точки останова.
Подсветка синтаксиса работает лучше.
Не нужно помнить про \ в конце строки.
Можно сделать аргументы по‐умолчанию.
Из недостатков в первую очередь только бо́льший размер кода. Техника для случаев, когда вы хотите что‐то вроде HashMap<K, V> со всеми его функциями, но в C — т.е. когда кода достаточно много, чтобы вас волновало удобство работы с ним.
, то компилятор (gcc и clang) поругается на те места, где опущен int, но скомпилирует (на argcclang ругается только с -pedantic). Не знаю, правда, что из этого есть в стандарте, но, учитывая что при указании -std=c89 и gcc, и clang перестают ругаться (у clang надо ещё убрать -pedantic), я полагаю, что такой код был вполне допустим C89.
Также, из имеющихся у меня компиляторов есть ещё tcc, который глотает код без каких‐либо предупреждений, bcc, который отказывается компилировать и pcc, который компилирует данный код без предупреждений, только результат компиляции откуда‐то ловит SEGV.
Эм, так я написал, что у меня восстанавливается при перезапуске несколько окон. И почта/ленты оба оказываются в «первом», и отправить в другое их нельзя. Замечание не про восстановление нескольких окон при перезапуске — эта часть всегда отлично работала, — а про отсутствие контроля за тем, в каком окне функциональность почты доступна и про то, что я не могу иметь почту и ленты в разных окнах.
Плюс я не уверен, что «первое» окно всегда будет «первым» при перезапуске — я не знаю, как реализована функциональность сохранения и восстановления сессии.
Насколько я понял, в новой версии при наличии нескольких окон ленты новостей и почта по‐прежнему доступны только в одном из них, но никакого контроля за тем, в каком именно, нет. Точнее, насколько я понял при открытии браузера это всегда «первое» окно, при его закрытии будет следующее по порядку открытия, но эта «первость» зависит от деталей реализации сохранения текущей сессии.
Во время беты я как‐то ухитрился получить ленты новостей в новом окне вместо «первого» и был неприятно удивлён тем, что после перезапуска они оказались в другом. Сейчас что‐то не могу повторить.
Мне, собственно, не нужно иметь доступ к почте в нескольких окнах, равно как и к лентам новостей, но хотелось бы, во‐первых, иметь почту и ленты в разных окнах — одна из причин, почему я сейчас использую только RSS. Во‐вторых, иметь возможность указать, в каком именно. В‐третьих, чтобы эти данные сохранялись в сессии.
. Штатный инструмент автозапуска, это, конечно, хорошо, но, во‐первых, с ним вы каждый раз будете платить за запуск процесса Python, чтение всех модулей, …, во‐вторых, останавливать скрипт выше гораздо удобнее. В варианте выше период должен плавать не так сильно.
Если ставят фильтры, то это значит, что вода часто воспринимается как плохая. Скорее всего, это либо означает просто, что она невкусная, что не является синонимом вредности. Равно как и (без)вкусная вода не означает полезности, а для длительного проживания безвредность как‐то важнее. Я бы воду с ледников всё равно бы на всякий случай прогнал через обратный осмос.
У меня есть подозрение, что дело не столько в яйцах, сколько в том, что вода выкипает вся. Соответственно, всё, что пропустил фильтр, окажется в яйцеварке. Если он «простенький», но спасает от накипи, то там, вероятно, уголь (от накипи не помогает никак, но он не для этого) и что‐то с использованием ионного обмена. Последнее оставит на месте то же количество солей, что и до фильтра, просто одни ионы (Ca, Mg) заменяться на другие (скорее всего, Na) — не разлагающиеся от нагрева. При выпаривании эти соли всё равно выпадут.
Хотя, мне кажется, результат должен неплохо растворяться. Может, действительно дело в яйцах: насчёт именно грязи я совсем не уверен, но быстрый поиск показывает, что сама скорлупа состоит в основном из накипи (точнее, карбоната кальция). Вопрос только в том, как при его крайне слабой растворимости он оказывается внизу.
Во‐первых, там есть минерализатор. Конкретно у меня в стандартный комплект поставки даже входит кран, который позволяет забрать воду как до, так и после минерализатора (обычно если минерализатор и есть, то в комплект входит кран только с одним краником). Правда, вода после минерализатора невкусная, поэтому краник «после» там есть, а реально его никто не использует. Плюс, бытовые минерализаторы, насколько я знаю, эффективны только если вода в них постояла.
Во‐вторых, тема в отношении людей весьма спорная и, насколько я знаю, консенсуса сейчас нет: нужные вещества можно и из еды получить. Вот растения такой водой поливать точно не стоит.
Против накипи где угодно помогает использование воды, очищенной обратным осмосом. Поставив фильтры и заменив чайник на новый, я за год не увидел на нём накипи. Ресурс фильтров обычно вполне достаточен, чтобы наливать очищенную воду везде, где не хочется иметь дело с солевыми отложениями.
В Rust нет стандартного выражения для целочисленных перечислений. Для определения типа перечисления используем псевдоним на существующий базовый тип с помощью ключевого слова type. Перечислители объявляем константами.
Вообще‐то есть. У пакета num-traits также есть FromPrimitive, упрощающий каст в такой enum (derive для него поддерживается в отдельном пакете).
В рантайм протащить это было бы сложновато. Как технически, так и организационно. Во‐первых, у Rust в runtime просто нет такой кучи информации, которую можно получить в той же Java, если её туда специально не добавит компилятор. Я примерно представляю, как это «специально добавит» должно выглядеть и оно содержит множество принципиальных проблем и вообще непросто в реализации.
Во‐вторых, пока даже на простенькие форматные строки с произвольными выражениями RFC не собрали — а там из проблем по сути только «как экранировать» и «а оно точно нужно?». Предложение вида «давайте потратим несколько человекомесяцев, чтобы получить в std свой собственный log4shell», конечно же найдёт широкую поддержку у разработчиков и сообщества.
Более ограниченный вариант вида «пользователь должен сам собрать словарь со всеми переменными, которые он хочет сделать доступными» ещё может появится в std и наверняка в каком‐то виде уже есть в крейтах. Но это не особо опасно.
Я с Элитана тоже до сих пор получаю 0603 резисторы маркированными. Правда, YAGEO на резисторах вместо стандартной маркировки NME (в смысле NM×10^E Ω) вполне может написать что‐то другое: точно сейчас не скажу, но было что‐то вроде 085 вместо 102, и так примерно на четырёх номиналах из 48 (но маркировки везде разные).
Зачем сейчас писать на ЯА? Когда-то это позволяло заметно ускорить программу. Но сейчас современные компиляторы настолько хорошо оптимизируют, что ускорения от ручного кодинга на ЯА не получается. (Конечно, если такое хобби, то понятно. В списке Tiobe и ЯП Brainfuck есть ;)
Помимо оптимизаций есть ещё и куча «специальных» применений. У меня, к примеру, по сути embedded разработка, со своей спецификой. Попробуйте объяснить компилятору хотя бы C, что часть регистров общего назначения должна быть зарезервирована под volatile память с глобальными переменными, в которой я буду смотреть наличие одиночных сбоев. Ещё мне обычно проще написать на ассемблере, чем выяснить, что не так в программе на C (или компиляторе), что она не работает или работает медленно: выяснение всё равно потребует понимания ассемблерного кода.
У меня Excel как‐то умудрился сохранить файл с большинством формул в локализованном виде. А потом при открытии эти формулы просто выкидывал (правда, не молча, а утверждая, что файл повреждён). LibreOffice при этом ничего не выкидывал, но и формулы не считал. Проблема решилась нахождением последней рабочей версии в СКВ, сравнении текущей с ней в распакованном виде (после LibreOffice мне стало только понятно, что формулы там есть, а не что с ними не так) и делокализацией скриптами на VimL с последующей запаковкой обратно.
И я не помню, чтобы я обновлял в это время Office, или трогал связанные с локализацей настройки.
Я что‐то подобное делал для Word. Там макросы хранятся в бинарном файле, имитирующем файловую систему (OLE2), который много кто умеет разбирать, но мало кто умеет создавать. Я в итоге просто решил хранить документ без макросов в распакованном виде в VCS, отдельно там же хранить макросы и скриптом запаковывать файл обратно с последующим добавлением файлов с макросами посредством API Word.
PS: Кто-нибудь знает, на хабре еще осталась простая возможность указывать индексы, как ранее было корректно: H2O ?
На помощь может придти Unicode: там есть вещи вроде U+2082 Subscript two: H₂O. И у меня ещё старый интерфейс, если предпросмотр не отличается от реальности, то в цитате нижний индекс вместо тегов.
Вычисления производились с использованием 80-битных числе с плавающей запятой (тип long double). Результаты аппроксимации сравнивались со значением синуса, полученными стандартной функцией sinl() из библиотеки С компилятора gcc.
Мне вот интересно, почему ещё никто не прицепился к этой части? В стандарте по поводу этой функции сказано только, что она вычисляет синус, никаких требований к точности не предъявляется. А функция ведь будет сама использовать какую‐то аппроксимацию, а не вызывать особую компьютерную магию, чтобы в выходном регистре появилось настолько точное значение синуса, насколько это позволяет формат long double. Так что не хватает исследования точности sinl.
И, кстати, при чём тут gcc? sinl лежит в libm, а libm согласно моему пакетному менеджеру, относится к пакету glibc.
Тут может программа виновата: к примеру, обычно предупреждает о необходимости перезаливки, а тут нет.
Мне как‐то Резонит КЗ поправил: когда я подвинул группу компонентов с проводниками и поправил КЗ на внешних слоях из‐за наехавших на неподвинутые проводников на небольшом количестве проводников во внутренних слоях КЗ остался. Что интересно, при проведении DRC ошибок не было (Altium). Узнал о том, что КЗ вообще был, когда было нужно поменять плату позже.
В rust есть trait’ы. В C мне вместо них не раз приходилось использовать либо функции, генерируемые макросами, либо
.c.h
файлы. Не знаю, как называется последняя техника, но уверен, что не я первый её придумал: идея в том, что у нас есть файлfrob.c.h
видаи он используется так:
(
#undef
тут везде только чтобы не засорять пространство имён).Такая вариация на тему generic’ов не слишком удобна, но она имеет несколько важных преимуществ перед определением функций в макросах:
\
в конце строки.Из недостатков в первую очередь только бо́льший размер кода. Техника для случаев, когда вы хотите что‐то вроде
HashMap<K, V>
со всеми его функциями, но в C — т.е. когда кода достаточно много, чтобы вас волновало удобство работы с ним.C позволяет опускать
int
во многих случаях. Например, если вы напишете, то компилятор (
gcc
иclang
) поругается на те места, где опущенint
, но скомпилирует (наargc
clang
ругается только с-pedantic
). Не знаю, правда, что из этого есть в стандарте, но, учитывая что при указании-std=c89
и gcc, и clang перестают ругаться (уclang
надо ещё убрать-pedantic
), я полагаю, что такой код был вполне допустим C89.Также, из имеющихся у меня компиляторов есть ещё
tcc
, который глотает код без каких‐либо предупреждений,bcc
, который отказывается компилировать иpcc
, который компилирует данный код без предупреждений, только результат компиляции откуда‐то ловит SEGV.Эм, так я написал, что у меня восстанавливается при перезапуске несколько окон. И почта/ленты оба оказываются в «первом», и отправить в другое их нельзя. Замечание не про восстановление нескольких окон при перезапуске — эта часть всегда отлично работала, — а про отсутствие контроля за тем, в каком окне функциональность почты доступна и про то, что я не могу иметь почту и ленты в разных окнах.
Плюс я не уверен, что «первое» окно всегда будет «первым» при перезапуске — я не знаю, как реализована функциональность сохранения и восстановления сессии.
Насколько я понял, в новой версии при наличии нескольких окон ленты новостей и почта по‐прежнему доступны только в одном из них, но никакого контроля за тем, в каком именно, нет. Точнее, насколько я понял при открытии браузера это всегда «первое» окно, при его закрытии будет следующее по порядку открытия, но эта «первость» зависит от деталей реализации сохранения текущей сессии.
Во время беты я как‐то ухитрился получить ленты новостей в новом окне вместо «первого» и был неприятно удивлён тем, что после перезапуска они оказались в другом. Сейчас что‐то не могу повторить.
Мне, собственно, не нужно иметь доступ к почте в нескольких окнах, равно как и к лентам новостей, но хотелось бы, во‐первых, иметь почту и ленты в разных окнах — одна из причин, почему я сейчас использую только RSS. Во‐вторых, иметь возможность указать, в каком именно. В‐третьих, чтобы эти данные сохранялись в сессии.
Ещё можно просто использовать
. Штатный инструмент автозапуска, это, конечно, хорошо, но, во‐первых, с ним вы каждый раз будете платить за запуск процесса Python, чтение всех модулей, …, во‐вторых, останавливать скрипт выше гораздо удобнее. В варианте выше период должен плавать не так сильно.
Если ставят фильтры, то это значит, что вода часто воспринимается как плохая. Скорее всего, это либо означает просто, что она невкусная, что не является синонимом вредности. Равно как и (без)вкусная вода не означает полезности, а для длительного проживания безвредность как‐то важнее. Я бы воду с ледников всё равно бы на всякий случай прогнал через обратный осмос.
У меня есть подозрение, что дело не столько в яйцах, сколько в том, что вода выкипает вся. Соответственно, всё, что пропустил фильтр, окажется в яйцеварке. Если он «простенький», но спасает от накипи, то там, вероятно, уголь (от накипи не помогает никак, но он не для этого) и что‐то с использованием ионного обмена. Последнее оставит на месте то же количество солей, что и до фильтра, просто одни ионы (Ca, Mg) заменяться на другие (скорее всего, Na) — не разлагающиеся от нагрева. При выпаривании эти соли всё равно выпадут.
Хотя, мне кажется, результат должен неплохо растворяться. Может, действительно дело в яйцах: насчёт именно грязи я совсем не уверен, но быстрый поиск показывает, что сама скорлупа состоит в основном из накипи (точнее, карбоната кальция). Вопрос только в том, как при его крайне слабой растворимости он оказывается внизу.
Автор уже написал выше:
Там же предположение, что дело просто в том, сколько воды нужно, чтобы заполнить свободное пространство паром.
Во‐первых, там есть минерализатор. Конкретно у меня в стандартный комплект поставки даже входит кран, который позволяет забрать воду как до, так и после минерализатора (обычно если минерализатор и есть, то в комплект входит кран только с одним краником). Правда, вода после минерализатора невкусная, поэтому краник «после» там есть, а реально его никто не использует. Плюс, бытовые минерализаторы, насколько я знаю, эффективны только если вода в них постояла.
Во‐вторых, тема в отношении людей весьма спорная и, насколько я знаю, консенсуса сейчас нет: нужные вещества можно и из еды получить. Вот растения такой водой поливать точно не стоит.
Против накипи где угодно помогает использование воды, очищенной обратным осмосом. Поставив фильтры и заменив чайник на новый, я за год не увидел на нём накипи. Ресурс фильтров обычно вполне достаточен, чтобы наливать очищенную воду везде, где не хочется иметь дело с солевыми отложениями.
Вообще‐то есть. У пакета num-traits также есть FromPrimitive, упрощающий каст в такой enum (derive для него поддерживается в отдельном пакете).
В рантайм протащить это было бы сложновато. Как технически, так и организационно. Во‐первых, у Rust в runtime просто нет такой кучи информации, которую можно получить в той же Java, если её туда специально не добавит компилятор. Я примерно представляю, как это «специально добавит» должно выглядеть и оно содержит множество принципиальных проблем и вообще непросто в реализации.
Во‐вторых, пока даже на простенькие форматные строки с произвольными выражениями RFC не собрали — а там из проблем по сути только «как экранировать» и «а оно точно нужно?». Предложение вида «давайте потратим несколько человекомесяцев, чтобы получить в std свой собственный log4shell», конечно же найдёт широкую поддержку у разработчиков и сообщества.
Более ограниченный вариант вида «пользователь должен сам собрать словарь со всеми переменными, которые он хочет сделать доступными» ещё может появится в std и наверняка в каком‐то виде уже есть в крейтах. Но это не особо опасно.
Я с Элитана тоже до сих пор получаю 0603 резисторы маркированными. Правда, YAGEO на резисторах вместо стандартной маркировки NME (в смысле NM×10^E Ω) вполне может написать что‐то другое: точно сейчас не скажу, но было что‐то вроде 085 вместо 102, и так примерно на четырёх номиналах из 48 (но маркировки везде разные).
Помимо оптимизаций есть ещё и куча «специальных» применений. У меня, к примеру, по сути embedded разработка, со своей спецификой. Попробуйте объяснить компилятору хотя бы C, что часть регистров общего назначения должна быть зарезервирована под volatile память с глобальными переменными, в которой я буду смотреть наличие одиночных сбоев. Ещё мне обычно проще написать на ассемблере, чем выяснить, что не так в программе на C (или компиляторе), что она не работает или работает медленно: выяснение всё равно потребует понимания ассемблерного кода.
Я так понял, технику безопасности сейчас должен рассказывать работодатель — тем, кто до него дожил.
У меня Excel как‐то умудрился сохранить файл с большинством формул в локализованном виде. А потом при открытии эти формулы просто выкидывал (правда, не молча, а утверждая, что файл повреждён). LibreOffice при этом ничего не выкидывал, но и формулы не считал. Проблема решилась нахождением последней рабочей версии в СКВ, сравнении текущей с ней в распакованном виде (после LibreOffice мне стало только понятно, что формулы там есть, а не что с ними не так) и делокализацией скриптами на VimL с последующей запаковкой обратно.
И я не помню, чтобы я обновлял в это время Office, или трогал связанные с локализацей настройки.
Я что‐то подобное делал для Word. Там макросы хранятся в бинарном файле, имитирующем файловую систему (OLE2), который много кто умеет разбирать, но мало кто умеет создавать. Я в итоге просто решил хранить документ без макросов в распакованном виде в VCS, отдельно там же хранить макросы и скриптом запаковывать файл обратно с последующим добавлением файлов с макросами посредством API Word.
На помощь может придти Unicode: там есть вещи вроде U+2082 Subscript two: H₂O. И у меня ещё старый интерфейс, если предпросмотр не отличается от реальности, то в цитате нижний индекс вместо тегов.
Мне вот интересно, почему ещё никто не прицепился к этой части? В стандарте по поводу этой функции сказано только, что она вычисляет синус, никаких требований к точности не предъявляется. А функция ведь будет сама использовать какую‐то аппроксимацию, а не вызывать особую компьютерную магию, чтобы в выходном регистре появилось настолько точное значение синуса, насколько это позволяет формат long double. Так что не хватает исследования точности sinl.
И, кстати, при чём тут gcc? sinl лежит в libm, а libm согласно моему пакетному менеджеру, относится к пакету glibc.
Тут может программа виновата: к примеру, обычно предупреждает о необходимости перезаливки, а тут нет.
Мне как‐то Резонит КЗ поправил: когда я подвинул группу компонентов с проводниками и поправил КЗ на внешних слоях из‐за наехавших на неподвинутые проводников на небольшом количестве проводников во внутренних слоях КЗ остался. Что интересно, при проведении DRC ошибок не было (Altium). Узнал о том, что КЗ вообще был, когда было нужно поменять плату позже.