1.82K subscribers
3.31K photos
132 videos
15 files
3.58K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
Forwarded from Коза кричала
Разгадана одна из главных тайн мироздания: Почему вомбат срет кубиками?

Эта загадка будоражила умы ученых давно, но ответ был получен лишь теперь. Попутно доказали несостоятельность всех прежних гипотез, имевших в академических кругах широкое хождение. Одни говорили, что у вомбатов квадратный анус. Другие - что какашки приобретают необычную форму при прохождении костей таза. Третьи - что вомбаты лепят из какашек геометрически строгие куличики уже, так сказать, пост-фактум - посрамши.

Так вот это не так. У вомбатов любопытный кишечник. Одни участки мышц в нем твердые, другие эластичные. И именно поэтому какашки получаются почти квадратными. Но возникает вопрос - а зачем им быть такими? Какой смысл заложила в это Природа? Дело в том, что вомбаты таким образом помечают территорию и общаются с сородичами. Какашка, выпав из жопы, должна остаться на месте, чтобы донести свой "месседж". А будь она круглой, то просто укатится хрен знает куда. Поэтому куб - идеальная форма.

Знание - сила!
Forwarded from Ofee
Если ты в душе плюсовик — ты и на JS уб понапишешь
Скажите что-то хорошее о канале
Скажите что-то плохое о канале
#prog #rust #meme

Какой же ор. Жаль, что те, кто не пишут на Rust, не поймут.
Forwarded from мне не нравится реальность (вафель 🧇🍓)
This media is not supported in your browser
VIEW IN TELEGRAM
Forwarded from мне не нравится реальность (вафель 🧇🍓)
вафель держит Илью 2021 год, фото в цвете
Никто:
Абсолютно никто:
Мой коллега в час ночи в рабочем чатике:

— Эй, а попробуйте решить на расте вот такую задачу по десериализации YAML!..

#трудовыебудни
Блог*
#prog #rust #моё В Rust есть такая удобная вещь, как сопоставление с образцом (pattern matching), и она работает в том числе и для строк. К сожалению, оно позволяет сопоставлять только строки целиком, но не по частям. В частности (no pun intended), match…
#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, если охранное выражение имеется. Сделать повтор синтаксического фрагмента без соответствующей синтаксической метапеременной нельзя, но и само выражение нам не требуется, поэтому воспользуемся стандартным трюком: переведём выражение в безвредную строку и отбросим её. На итоговое выражение это не повлияет, а наличие нужной метапеременной обеспечено. И да, это не замыкание, как может показаться, а выражение с оператором "или".
Блог*
#prog #rust #моё Кое-что я при разработке этого макроса упустил: проверка на недостижимость кода недостаточно точна. Если строка не начинается с префикса, скажем, "java", то пытаться отщипнуть префикс "javascript" уже не имеет смысла, потому что он заведомо…
Что ж, с этим разобрались. Проверим теперь, как это работает на практике, и для этого модифицируем 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.