1.84K subscribers
3.39K photos
134 videos
15 files
3.65K links
Блог со звёздочкой.

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

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
#prog #rust #rustlib #ml #abnormalprogramming

unwrap_or_ai

Tired of manually handling unwrap() results? Let AI do the heavy lifting!
🤩19🤡2
😁19💯10🌚9🤡2
#prog #go #article

How we found a bug in Go's arm64 compiler

TL;DR: для горутин с большим стеком (больше, чем может быть закодировано в литерале в одной инструкции на ARM) в эпилоге функций изменение sp, регистра, указывающего на верхушку стека, происходило через две операции ADD, обе из которых оперировали на sp непосредственно. Если переключение (preemption) между горутинами происходило между этими двумя операциями, любые операции, которые разворачивали стек — в частности, сборщик мусора — следовали вверх по стеку вызовов по частично обновлённому и потому невалидному значению из sp, и в результате предсказуемо крашились.

Может, ввести отдельный хештег для историй дебага? 🤔
🤡6👍51😱1🌚1
#prog #article

Cloudflare just got faster and more secure, powered by Rust

Про то, как в Cloudflare заменяют (пока что не довели до конца, но закончат к началу 2026 года) так называемый FL, центральный компонент своих сервисов. Заголовок несколько вводит в заблуждение: Rust определённо помогает, но большая часть хороших вещей из новой версии связана с архитектурой.

Одна из вещей, которая даёт преимущество новой версии — разделение на модули, каждый из которых сам по себе не занимается IO и явно перечисляет, что он принимает на вход и что возвращает. Это не только даёт возможность на уровне архитектуры явно видеть, как модули зависят друг от друга, но и позволило интегрировать модули в предыдущую версию FL, чтобы избежать параллельной поддержки двух версий одних и тех же функций во время перехода с одной версии на другую.

Отдельно хочу отметить, что часть про отсутствие IO язык с системой эффектов (даже такой примитивной, как в Haskell) мог бы предовтращать надёжно на уровне компилятора, а не соглашений, так что конкретно тут Rust не помогает.
👍6🤔1🤡1
#prog #article

Know your SCM_RIGHTS

TIL что в Linux (на самом деле UNIX) есть способ передавать файловые дескрипторы между процессами. И эти файловые дескрипторы могут быть в том числе TCP- и UDP-сокетами.
👍7😍3👌1🤡1
#prog #cpp #rust #article

Why we didn't rewrite our feed handler in Rust

Отдельно отмечается, что Rust в технологическом стеке в этой компании уже есть и успешно используется. Проблемы возникли с переписыванием конкретного компонента, который уже есть и написан на C++. Конкретно в тексте приведены три паттерна, которые валидны в C++ и не выразимы или выразимы неудобно на Rust.

Первое касается ограничений borrow checker-а. Вот какой пример приводят:

fn process_source(sources: Vec<Source>) {
for source in sources {
let mut buffer: Vec<&[u8]> = Vec::new();
let data: Vec<u8> = source.fetch_data();
buffer.extend(data.split(splitter));
process_data(&buffer);
}
}


Простой и понятный код — но, к сожалению, выделяющий память в цикле. Логично было бы вынести аллокацию за цикл и очищать буфер в конце — но тогда компилятор не даёт скомпилировать код:

error[E0597]: `data` does not live long enough
--> src/lib.rs:32:23
|
31 | let data: Vec<u8> = source.fetch_data();
| ---- binding `data` declared here
32 | buffer.extend(data.split(splitter));
| ------ ^^^^ borrowed value does not live long enough
| |
| borrow later used here
33 | process_data(&buffer);
34 | }
| - `data` dropped here while still borrowed


Второй паттерн — самоссылающиеся структуры, известная больная тема в Rust.

Третий паттерн — множество определений разных версий и унифицированный код для работы с ними (из-за необходимости поддержки разных версий схем обмена данных, насколько я понял). Пример из статьи на C++:

struct RecV1 {
uint32_t x;
uint32_t y;
}

struct RecV2 {
uint32_t x;
uint32_t y;
uint32_t z;
}


Унифицированный код для работы с обоими этими типами можно написать при помощи шаблонов:

template <typename T>
T InitRec() {
T res;
res.x = 1;
res.y = 2;
if constexpr(std::is_same_v<T, RecV2>()) {
res.z = 3;
}
return res;
}


Нетрудно видеть, как это обобщается на случай большего количества полей и различных версий. В Rust можно попробовать сделать нечто подобное, но это вырождается в бойлерплейт, облегчать который приходится макросами — иными словами, попытка повторить шаблоны из C++.
👍10🤡5🔥1
#prog #rust #abnormalprogramming

fibonacci-numbers crate with self-recursive dependencies

I have created a crate called fibonacci-numbers. There are 187 different major versions of the crate, each exporting the Fibonacci number corresponding to that version.
<...>
Version 186 depends on version 184 and 185 and exports the largest Fibonacci number that fits in a u128:


pub const VALUE: u128 = fib184::VALUE + fib185::VALUE;
😁28🔥7🤡3🤯1
#prog #article

That boolean should probably be something else

By storing a boolean as our data, we're coupling that data tightly to our application logic.

Instead, we should remain critical and ask what data the boolean depends on, and should we maybe store that instead?


Да, про сумм-типы там тоже упоминается.
#prog #abnormalprogramming

spellscript

esotoric [sic!] programming language that's read like a spellbook


begin the grimoire.
summon the power with essence of 7.
conjure ritual named amplify with value to return value multiplied by value.
enchant power with essence 0 of through ritual amplify with power.
inscribe whispers of "the power is amplified: " bound with power.
close the grimoire.

output: the power is amplified: 49
11🤯3🤡3😁1
#prog #rust

rustc_codegen_gcc: Progress Report #38

В rustc_codegen_gcc теперь работает LTO, в том числе и cross-language! 🎉
😢16👍9🌚3