Size: a a a

2021 December 19
Блог*
Понятия не имею, насколько правда, но звучит смешно
источник
Блог*
простите
источник
2021 December 20
Блог*
#meme

Сайт, кстати, реально есть. Но там ничего интересного
источник
Блог*
источник
2021 December 21
Блог*
#prog #rust #video

Type-Driven API Design in Rust

(thanks @oleg_log)
источник
Блог*
источник
Блог*
#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 #article

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

Очередная статья про обработку ошибок в Rust, да. Но полезная: ставит под сомнения и разбирает распространённые мнения об ошибках в Rust. В частности, разбирается совет "anyhow для приложений, thiserror для библиотек".
источник
Блог*
#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>;
источник
Блог*
Привет, @sypwex
источник
Блог*
Что пишут разработчики:
— Наш продукт основан на искусственном интеллекте!

Что слышу я:
— Когда наш софт сломается, мы не будем иметь ни малейшего понятия, как его чинить.
источник
2021 December 22
Блог*
Чат* радует
источник
Блог*
Переслано от Vlad Beskrovnyy
Вообще, с майнкрафтом вечная история - приходят школьники, начинают учиться программировать и чето под майнкрафт кодят. Получается продсказуемо - всё забаговано и залаговано. Школьники постепенно учатся, вырастают и идут на нормальную работу (по собственному опыту говорю). В майнкрафт приходят новые.

В итоге вечно всё лагает и нихуя не работает. Никто не тестирует ничего под реальными нагрузками. Тесты вообще никто нигде не пишет, ни разу не видел.
источник
Блог*
#prog #lisp #amazingopensource

LISP with GC in 436 bytes (достаточно, чтобы уместиться на загрузочном секторе)
источник
2021 December 23
Блог*
Ничто так не поднимает самооценку, как расписывание рекрутёру своей экспертизы в Rust
источник
Блог*
#ml

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