1.83K subscribers
3.24K photos
127 videos
15 files
3.52K links
Блог со звёздочкой.

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

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
Forwarded from илья optozorax
когда цитируешь кого-то в канале своём, имхо лучше скидывать ссылку на чат, откуда ты это взял, чем пересылать сообщение, так можно хотя бы контекст отследить
Forwarded from oleg_log (Oleg Kovalov)
#prog #amazingopensource

Аллокатор памяти snmalloc, написанный в рамках разработки рантайма для исследовательского языка программирования от MIcrosoft Verona. Кажется, первый аллокатор, основанный на обмене сообщениями: операция освобождения памяти посылает сообщение об освобождении потоку, в котором память изначально была выделена. Уверяется, что эта пересылка задействует минимум атомарных операций и потому имеет небольшой оверхед. Также освобождение памяти в том же потоке, в котором она была выделена, не требует синхронизации вовсе.
Блог*
Аналогичной полезности вещь: перевод текста из одной раскладки в другую. raskladki.net.ru
А если вам нужно понять, в какой же, блин, кодировке этот текст в кракозябрах, то есть расшифровщик от студии Лебедева (да, того самого).

artlebedev.ru/decoder
#science

Спасибо, Илья
Forwarded from <илья as Человек> (ilya sheprut)
#prog #rust #rustlib #serde #amazingopensource

Хозяйке на заметку

Подборка библиотек для работы с serde от замечательного Толяна dtolnay.

erased-serde — трейты из serde со стёртыми типами. Позволяют сделать из (де)сериализаторов трейт-объекты. Обычно это запрещено правилами object safety из-за наличия обобщённых типов.

typetag — сериализация и десериализация трейт-объектов. Работает на костылях.

serde-repr — делегирует (де)сериализацию C-like enum его числовому значению.

serde-stacker — позволяет десериализовывать глубоко вложенные структуры, динамически выделяя память под стек. Работает, увы, не на всех OS: нормально работает на linux и MacOS и течёт на Windows.

serde-ignored — позволяет обернуть десериализатор с кастомный коллбеком, который будет вызываться на всех проигнорированных в процессе десериализации ключах.
Forwarded from Идеи неинтересных фильмов
"Призрачный гонщик".

Участковый во время сухого закона пытается обнаружить в Череповце производителя сивухи.
Блог*
Так, а что тут не так? И почему не совпадают типы? Дело в том, что у каждой функции — не только у замыканий — в Rust свой собственный уникальный тип. Здесь мы попытались сохранить значения двух разных типов в паре одинаковых типов, поэтому наш код не компилируется.…
#prog #rust #моё

Хроники замыканий

Как я уже говорил, для каждого литерала замыкания компилятор Rust создаёт свой собственный анонимный тип, в котором содержатся захваченные замыканием переменные. Эти сгенерированные типы объединяет одно: они реализуют один или несколько Fn-трейтов: core::ops::{FnOnce, FnMut, Fn}.

А почему их три? Разве нельзя обойтись одним?

Можно, но это серьёзно ограничило бы возможности замыканий. Трейтов три из-за того, что замыкания могут иметь различные возможности. Как ты помнишь, методы в Rust принимают первым параметром self, &mut self или &self (пошёл нафиг, arbitrary self types!). Соответственно и определения у Fn*-трейтов отличаются. Вот как они выглядят:

trait FnOnce<Args> {
type Output;
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

trait FnMut<Args>: FnOnce<Args> {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}

pub trait Fn<Args>: FnMut<Args> {
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}

Ти́повый параметр Args в сгенерированных реализациях — это кортеж, элементы которого — типы аргументов, по одному на каждый аргумент. Ассоциированный тип Output — это тип значения, возвращаемого при вызове замыкания. Методы трейтов объявлены с соглашением о вызове rust-call. Это, в частности, означает, что их нельзя сохранить или передать там, где ожидаются обычные функции.

Метод call трейта FnOnce принимает замыкание по значению, т. е. при вызове замыкание перемещается и его после этого нельзя использовать. Этот трейт не имеет никаких ограничений, что логично: если у нас есть замыкание, то его всегда можно вызвать как минимум один раз. В принципе, замыкание может не реализовывать другие трейты:

struct A;

let a = A;
let closure = || a;
closure();
// closure(); // use of moved value: closure

Здесь мы объявляем тип значение a типа A, которое не является копируемым, и замыкание, которое это значение захватывает и возвращает при вызове. Замыкания в Rust, если не указано ключевое слово move, захватывают значение по ссылке (возможно, мутабельной). Здесь a возвращается, поэтому его можно захватить только по значению. Так как это значение не копируемо, после вызова это значение перемещается из структуры данных, реализующей замыкание, и более замыкание вызвать нельзя. Собственно, это нам и скажет компилятор, если мы расскомментируем последную строку.

Окей, а что с другими трейтами?

Они дают возможность для более интересных замыканий. FnMut имеет в качестве супертрейта FnOnce — как я уже сказал, любое замыкание можно вызвать как минимум раз. Метод этого трейта call_mut принимает &mut self, а потому замыкание, во-первых, можно вызвать несколько раз, а во-вторых, может менять захваченные значения. Вот пример:

let mut n = 0;
let mut counter = || {
n += 1;
n
};
println!("{}", counter()); // 1
println!("{}", counter()); // 2
println!("{}", counter()); // 3

Здесь мы сделали переменную счётчик n и замыкание, которое его инкрементирует при каждом вызовом перед тем, как вернуть. Что тут важно — в силу того, что call_mut требует &mut self, а мутабельную ссылку можно взять только от мутабельного значения, нам пришлось объявить само замыкание как мутабельное. Если этот mut опустить, то компилятор резонно откажется компилировать код.

Понятно, а call принимает значение по ссылке и потому замыкание можно вызывать несколько раз, но оно не может менять захваченные значения?

Именно так. Более того, Fn является субтрейтом FnMut, и это тоже логично: если мы можем вызвать метод по разделяемой ссылке, то можем вызвать и по уникальной. Надо только иметь в виду, что &mut в Rust вообще-то означает не изменяемость, а уникальность, поэтому из-за interior mutability пример со счётчиком можно переделать и с "иммутабельным" замыканием.
Блог*
#prog #rust #моё Хроники замыканий Как я уже говорил, для каждого литерала замыкания компилятор Rust создаёт свой собственный анонимный тип, в котором содержатся захваченные замыканием переменные. Эти сгенерированные типы объединяет одно: они реализуют один…
Ох, постараюсь уложить это в голове. Есть ещё что-то, что нужно знать о замыканиях?

Да. Иногда требуется одно и тоже замыкание передать в качестве аргумента в несколько функций. Клонировать в этом случае не получится, потому что замыкание является клонируемым не всегда (а именно — начиная с версии 1.26.0, тогда, когда все захваченные значения клонируемы). Именно поэтому в стандартной библиотеке есть несколько blanket impl-ов, которые реализуют Fn*-трейты для ссылок на замыкания (например, вот). Поэтому, если, скажем, в двух функциях требуется замыкание, реализующее Fn(i32) -> i32, то можно сделать замыкание и передавать в качестве аргумента ссылку на него. В некоторых случаях сама функция требует ссылку на замыкание (хотя это, вообще говоря, странно). В таком случае можно взять ссылку непосредственно от литерала замыкания. Выглядит это несколько странно, но работает.

Видимо, на этом всё?

Отнюдь, о замыканиях можно рассказать ещё кое-что... Но это уже, видимо, тема для следующего поста. И будем надеяться, что его не придётся ждать ещё пару месяцев.
Блог*
Photo
Думаю, теперь вы лучше понимаете, что тут происходит во втором сниппете
Forwarded from 💮
Помню, мы как-то собирались у кого-то дома с ноутбуками и поднимали упоротую сеть такого вида:
(интернет) -eth- (PC) -eth- (ноутбук) -wifi- (ноутбук) -eth- (ноутбук)
Forwarded from codingteam@cjr
Orhideous
Топология SOSIG