ar
Feedback
Блог*

Блог*

الذهاب إلى القناة على Telegram

Блог со звёздочкой. Много репостов, немножко программирования. Небольшое прикольное комьюнити: @decltype_chat_ptr_t Автор: @insert_reference_here

إظهار المزيد
1 948
المشتركون
+124 ساعات
+237 أيام
+2430 أيام
أرشيف المشاركات
sticker.webp0.32 KB

Так всё-таки, для чего нужен dependncy injection?

photo content

#prog #meme

когда я встречаю людей, которые носят одноразовые маски по несколько дней, мне всегда хочется спросить: "у вас есть любимая одноразовая салфетка, которой вы вытираете рот?"

С кем я вообще дружу, блин
+5
С кем я вообще дружу, блин

#ml Правда, у меня есть стойкое подозрение, что такие хорошие результаты достигаются на запросах, для которых есть точно подходящие изображения из обучающей выборки

Ничто так не поднимает самооценку, как расписывание рекрутёру своей экспертизы в Rust

#prog #lisp #amazingopensource LISP with GC in 436 bytes (достаточно, чтобы уместиться на загрузочном секторе)

Вообще, с майнкрафтом вечная история - приходят школьники, начинают учиться программировать и чето под майнкрафт кодят. Получается продсказуемо - всё забаговано и залаговано. Школьники постепенно учатся, вырастают и идут на нормальную работу (по собственному опыту говорю). В майнкрафт приходят новые. В итоге вечно всё лагает и нихуя не работает. Никто не тестирует ничего под реальными нагрузками. Тесты вообще никто нигде не пишет, ни разу не видел.

Чат* радует
Чат* радует

Что пишут разработчики: — Наш продукт основан на искусственном интеллекте! Что слышу я: — Когда наш софт сломается, мы не будем иметь ни малейшего понятия, как его чинить.

Привет, @sypwex

#prog #rust #моё Пара слов о фантомных типах и авто-трейтах. Иногда нам нужно включить нужный функционал, не привязанный к стейту. Примерно так: struct OptionA; struct OptionB; trait Param { fn op(); } impl Param for OptionA { ... } impl Param for OptionB { ... } struct Parametrised<P> { data: Data, _param: PhantomData<P>, } impl<P: Param> Parametrised<P> { fn func(&mut self) { self.data.process_foo(); P::op(); self.data.process_bar(); } } Вроде выглядит нормально. Однако тут есть подвох: авто-трейты, в отличие от дерайвов для большинства трейтов, смотрят не на типовые параметры, а на типы самих полей. В число авто-трейтов входят также Send и Sync. PhantomData (не) имеет те же реализации Send/Sync, что и тИповый параметр, которым параметризован. К чему это приводит? Да к тому, что если Parametrised<P> будет использован в контексте, когда выполнение этих трейтов имеет значение, нам придётся вешать ограничение P: Send/P: Sync, даже не смотря на то, что значения этих типов не используются вообще. Хуже, это придётся писать даже в том случае, если Data реализует Send/Sync. Что мы можем с этим сделать? Ответ очень прост: достаточно поменять определение поля _param: struct Parametrised<P> { data: Data, _param: PhantomData<fn(P)>, // <-- } Таким образом, мы всё ещё включаем тип P в описание типа Parametrised, но так как все функциональные указателя безусловно удовлетворяют Send и Sync, паразитные ограничения более не возникают. Есть, однако, и другой вариант использования фантомных типовых параметров: мы пишем тип данных, который как-то соотносится с неким параметром T, но не включает его напрямую. Использование PhantomData<T> может быть неправильным в том смысле, что оно показывает, что наш тип логически владеет значением типа T, что не обязательно является правдой. Более того, так как из-за лайфтаймов на типах в Rust есть отношение субтипизации, в полный рост встают проблемы вариантности. Прямолинейным подходом в подобных случаях является использование PhantomData, параметризованных *const T и *mut T. Этот подход опирается на тот факт, что *const T ковариантен по T, а *mut T контравариантен по T, и оба типа не требуют лайфтаймы. Однако тут легко упустить тот момент, что оба типа примитивных указателей безусловно не реализуют ни Send, ни Sync, что вкупе с протеканием автотрейтов через PhantomData может привести к тем же паразитным ограничениям. Причём этот случай это даже хуже, поскольку требует написания реализаций Send и Sync вручную, а эти имплы очень легко могут стать неправильными при внесении изменений в код. Для того, чтобы избежать этих проблем и иметь ограничения Send/Sync только на релевантные поля, мы опять воспользуемся тем фактом, что функциональные указатели реализуют Send и Sync безусловно, а так же тем фактом, что функциональные типы ковариантны по типу результата и контрвариантны по типу аргумента. Комбинируя эти типы с PhantomData, мы можем получить нужную нам вариантность без головной боли, связанной с потокобезопасностью. Проиллюстрирую это псевдонимами типов:
type Covariant<T> = PhantomData<fn() -> T>;
type Contravariant<T> = PhantomData<fn(T)>;
// ко- и контрвариантность — это про наложение ограничений,
// поэтому совмещение этих требований приводит к
// более строгому отношению: инвариантности (в смысле вариантности)
type Invariant<T> = PhantomData<fn(T) -> T>;

#prog #rust #article Очередная статья про обработку ошибок в Rust, да. Но полезная: ставит под сомнения и разбирает распространённые мнения об ошибках в Rust. В частности, разбирается совет "anyhow для приложений, thiserror для библиотек".

#prog #rust #article How not to learn Rust — статья с частыми ошибками новичков при изучении Rust

#prog #rust Синтаксис для условной компиляции (#[cfg(...)]) в Rust позволяет использовать условные выражения, но не в очень эргономичном виде: через all, any и not. Библиотека efg позволяет использовать более привычный синтаксис, похожий на то, что пишут в коде на самом Rust. Пример: #[efg(feature "proc-macro" && !(target_arch "wasm32" && target_os "unknown"))] extern crate proc_macro; Кстати, написана Толяном.

#prog #rust #video Type-Driven API Design in Rust (thanks @oleg_log)