Size: a a a

2021 February 11
Блог*
dereference_pointer_there
#prog #rust #моё

Кое-что я при разработке этого макроса упустил: проверка на недостижимость кода недостаточно точна. Если строка не начинается с префикса, скажем, "java", то пытаться отщипнуть префикс "javascript" уже не имеет смысла, потому что он заведомо отсутствует. Однако мой макрос проверяет строки на (не)равенство и не учитывает их возможных структурных отношений. Сейчас мы это исправим, и пойдём по уж проторенной дорожке: вынесем нужную проверку в const fn и будем генерировать код, который не тайпчекается в случае, если проверка завершилась неудачей.

Начнём с выяснения того, является ли одна строка префиксом другой. Ничего сложного в этом нет (кроме того, чтобы перепутать одну строку с другой, ага), просто несколько неудобно из-за ограничений const fn:

const fn is_prefix(s: &str, maybe_prefix: &str) -> bool {
   if maybe_prefix.len() > s.len() {
       return false;
   }

   let s = s.as_bytes();
   let mp = maybe_prefix.as_bytes();
   let mut i = 0;

   while i < mp.len() {
       if mp[i] != s[i] {
           return false;
       }
       i += 1;
   }

   true
}

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

const fn has_unreachable_patterns(ss: &[(&str, bool)]) -> bool {
   if ss.is_empty() {
       return false;
   }

   let mut i = 0;
   let mut j;
   while i < ss.len() - 1 {
       // строки, для которых есть охранное выражение, пропускаем
       if ss[i].1 {
           i += 1;
           continue
       }
       j = i + 1;
       while j < ss.len() {
           // А вот вторую строку в паре нужно проверять всегда,
           // вне зависимости от того, есть у него охранное выражение или нет:
           // если охранного выражения нет у первой строки, то исполнение
           // до ветки со второй строкой точно не дойдёт.
           if is_prefix(ss[j].0, ss[i].0) {
               return true;
           }
           j += 1;
       }
       i += 1;
   }

   false
}

Осталось только сгенерировать код для проверки, заменив в макросах функцию non_repeating (это изменение, кстати, одинаковое для всех двух (трёх) макросов) — и это, кажется, наиболее зубодробительная часть:

const _HAS_NO_UNREACHABLE_PATTERNS: [(); 0] = [
   ();
   has_unreachable_patterns(
       &[
           $((
               $prefix,
               false $(|| {stringify!($condition); true})?
           ),)*
       ]
   ) as _
];

Это довольно много, так что разберём по частям:

const _HAS_NO_UNREACHABLE_PATTERNS: [(); 0] = [
   ();
   has_unreachable_patterns(...) as _
];

Это объявление константы. Если has_unreachable_patterns(...) вычисляется в true, то оно при касте в usize становится 1, вызывая ошибку несоответствия типов.

&[
   $((
       $prefix,
       ...
   ),)*
]

Здесь мы формируем ссылку на литерал массива, элементами которого являются пары, первыми элементами которых являются строки-префиксы.

false $(|| {stringify!($condition); true})?

Здесь мы формируем значение true, если охранное выражение имеется. Сделать повтор синтаксического фрагмента без соответствующей синтаксической метапеременной нельзя, но и само выражение нам не требуется, поэтому воспользуемся стандартным трюком: переведём выражение в безвредную строку и отбросим её. На итоговое выражение это не повлияет, а наличие нужной метапеременной обеспечено. И да, это не замыкание, как может показаться, а выражение с оператором "или".
Что ж, с этим разобрались. Проверим теперь, как это работает на практике, и для этого модифицируем use_prefixes:

fn use_prefixes(s: &str) -> String {
   prefixes!(match s {
       "foo".. => s.to_string(),
       "bar".. => [s, s].concat(),
       "foobar".. => [s, "3"].concat(),
       _ => String::new(),
   })
}

Эта функция закономерно вызывает жалобы у компилятора на несоответствие типов. Отлов ошибок работает! Теперь немного поменяем определение:

fn use_prefixes(s: &str) -> String {
   prefixes!(match s {
       "foo".. if true => s.to_string(),
       "bar".. => [s, s].concat(),
       "foobar".. => [s, "3"].concat(),
       _ => String::new(),
   })
}

...И теперь у компилятора нет вопросов.

Есть недостатки у нашего решения? Определённо — помимо тех, о которых я уже писал. Во-первых, теперь это жёсткая ошибка вместо предупреждения компилятора — но да, это спорный недостаток. А во-вторых — и вот это уже недостаток куда как более существенный — ошибка компиляции не говорит о том, какие паттерны перекрываются. И я, к сожалению, не придумал, как их показывать, не выходя за пределы того, что умеет stable Rust.
источник
Блог*
#prog

Определение понятия "говнокод"
источник
Блог*
20% запросов к хранилищу файлов «Викисклад» приходятся на одно и то же фото цветка — инженеры выяснили, что трафик идёт от индийского приложения, набравшего популярность в стране после блокировки тиктока.

При этом приложение не отображает картинку, а отправляет к ней запрос во время запуска.

https://tjournal.ru/internet/337806
источник
2021 February 12
Блог*
Вышел Rust 1.50!

Интересные (на мой взгляд) обновления:
Присваивание полям union'ов типа MaybeUninit<_> теперь safe
Теперь можно использовать константы в выражениях массива [x; N] (до этого можно было только :Copy типы)

ops::{Index, IndexMut} теперь реализованы для массивов всех длин
На unix системах, std::fs::File теперь имеет "нишу" -1, это значит что Option<File> и File могут иметь один размер

Стабилизировали bool::then, {Ord, f32, f64}::clamp, <[_]>::fill. Многие методы чисел стабилизировали как const (например pow).

Так-же метод compare_and_swap у атомиков депрекейтнули в пользу compare_exchange{,_weak} (pr), забавно что планировали это сделать ещё в (!) Rust 1.12, но забыли.

[анонс в блоге]
источник
2021 February 13
Блог*
#prog #quotes
источник
Блог*
Переслано от Dr. Friedrich von Ne...
«Башскрипт» звучит как название какой-нибудь башкирской госконторы.
источник
Блог*
Один из коммунити-мемберов DC8044 нашел ошибку, при которой картинка из ASCII крашит клиент Телеграм. Воспроизвести удалось на последней десктопной версии клиента под Виндовс. Для реализации необходимо скопировать содержимое конкретного файла и попробовать вставить в любой из диалогов. Происходит краш клиента _отправителя_. Возможно исследователям удастся творчески раскрутить найденную ошибку до каких-то интересных масштабов.
P.S.: зарепортить багу в Телеграм не удается, так как там крашится бот, принимающий репорты....
источник
2021 February 14
Блог*
Внутри меня два волка, но один из них почему-то кошкодевочка, а другой вообще умер
источник
Блог*
#prog #cpp

Данила написал немного о своём участии в контесте от Telegram. Попутно от него чуток пригорело с кривости постановки условий задач
Telegram
Experimental chill
Поучаствовал в очередном контесте от Телеграма. Как обычно, мутно, с неполными условиями по оцениванию, но всё как в настоящей жизни, им нужна классификация публичных каналов с >=1000 подписчиков и нулевой разметкой на 42 категории для рекламы. Всё это ещё и на C++ (а лучше вообще на C). Решение у меня получилось необычным, как выложут результаты и если что-то займу, расскажу.

Ну а так, конечно, нескольких необычных деталей

1. Категории в предоставленном тестере и в условии задачи отличаются в двух местах, ещё попробуй потом найти несоответствие в оценках
2. Огромное количество шлака в каналах, 10 категорий составляют примерно 90% всех каналов, 14 категорий составляют 98%. Крипта, ставки, бинарные опционы, стабильно проскальзывает порно и наркотики. Задумываешься после этого, есть ли вообще модерация у Телеграма, много накрученных и hate speech каналов. На русском языке ситуация получше
3. В тестере молодцы ребята в хедер файле с интерфейсом опубликовали глобальную переменную, так ещё и с санитайзером падает…
источник
Блог*
#music

Шикарный саундтрек из замечательной игры Hades, про которую я, возможно, расскажу.

youtube.com/watch?v=SqFaCDvHxU4
источник
2021 February 15
Блог*
#video

Совершенно завораживающая машина для установки электронных компонент на плату. Техно-порно, да.

(thanks @lynxformal)

youtube.com/watch?v=nyh9u-t7yvQ
источник
2021 February 16
Блог*
Нужно больше странных фоток.

Что это: Icons8 — архив стоковых фотографий, где можно не только скачивать готовые, но компоновать свои варианты: подобрать фон, добавить или убрать предметы, людей, лица и всё что хочется.
источник
Блог*
По работе наконец-то смержили мой MR, устраняющий unsoundness в растовом коде

#трудовыебудни
источник
2021 February 17
Блог*
#prog #rust #article

I show how to implement event listeners and dependency injection using Rust's type system to avoid common errors in stringly-typed versions of these extensible architectures.

willcrichton.net/notes/types-over-strings
источник
2021 February 18
Блог*
— Имярек писал сервис метрик, а получился криптомайнер.

(контекст: сервис метрик выжирает всё отведённое ему процессорное время)

#трудовыебудни
источник
Блог*
#prog #javascript #amazingopensource

Карта мира в терминале, к которой можно подключиться по telnet!

github.com/rastapasta/mapscii
источник
Блог*
#prog #rust #go
источник
Блог*
В "This week in Rust" запостили интересную ссылочку на обсуждение того как гошный рантайм очень уверенно побеждает Tokio при работе с блокирующими системными вызовами (в 3 раза).
В топовом комменте на редите объясняется почему так, и как подкрутить настройки Tokio чтобы почти убрать разницу, ну и почему эти настройки не применяются по дефолту.
Вот такое вот перформанс доминирование у нас получается.
источник
2021 February 19
Блог*
Нормальные пословицы, а не эта ваша народная мудрость

twitter.com/fellvein/status/1347425508707987456
источник
Блог*
Начало цикла статей по процедурным макросам в Rust

#prog #rust #proc_macro #article
источник