Size: a a a

2021 November 04
Блог*
источник
2021 November 05
Блог*
Переслано от ruDALL-E Malevich (X...
Фото сгенерировано моделью ruDALL-E от Сбера по запросу "Вафелька"
источник
Блог*
#rust

Одна из вещей, которая мне нравится в Rust — это совершенно замечательные диагностические сообщения.

t.me/ihatereality/2516
t.me/ihatereality/2517
источник
Блог*
Eli Albert Loeb из Калифорнии написал или написала любопытную бакалаварскую работу (чтобы все бакалавры в России писали такие работы) про маскулиность гопников и истоки этого явления.
Почитать можно совершенно бесплатно
источник
Блог*
К сожалению, больше не могу рекомендовать. Мало то, что контент пошёл куда-то не туда, так ещё и в последние пару дней там начался откровенный скам.
источник
Блог*
Статья о том, зачем на самом деле штуки типа mod.rs, index.html и так далее и как от них избавиться

#prog #article #fs
источник
Блог*
#prog #rust #моё

При отладке подобного кода — с гетерогенными списками — может быть полезным иметь возможность их распечатывать. Казалось бы, фигня вопрос: просто навесим #[derive(Debug)] — и дело с концом:

#[derive(Debug)]
struct HNil;

#[derive(Debug)]
struct HCons<H, T> {
   head: H,
   tail: T,
}

Но всё не так радужно. Попробуем распечатать hlist![42, 'b', "sup", ((), (3.4, Vec::<i32>::new()))]:

HCons { head: 42, tail: HCons { head: 'b', tail: HCons { head: "sup", tail: HCons { head: ((), (3.4, [])), tail: HNil } } } }

Ну... Выглядит не особо читаемо. Но ведь если использовать "{:#?}" в качестве форматной строки, станет лучше, ведь так?

HCons {
   head: 42,
   tail: HCons {
       head: 'b',
       tail: HCons {
           head: "sup",
           tail: HCons {
               head: (
                   (),
                   (
                       3.4,
                       [],
                   ),
               ),
               tail: HNil,
           },
       },
   },
}

Нет, не стало. Мало того, что детали реализации просачиваются в вывод и замусоривают его, так ещё и добавляется по уровню вложенности на каждый элемент логически плоской последовательности. Вывод однозначен: нужно писать реализацию Debug руками.
источник
Блог*
Но как именно это сделать? Первый способ, лежащий на поверхности (aka способ ленивого программиста) — собрать в массив вектор элементы гетерогенного списка, ослабленные до dyn Debug, и попросту отформатировать этот вектор.

Так как HNil и HCons — разные типы, нам нужно абстрагировать в трейт общую для них операцию, а именно — добавление элементов в переданный вектор. Как должна выглядеть сигнатура метода? Кажется, что как-то так:

fn append_fmt_items(&self, items: &mut Vec<&dyn Debug>)

...но это так не работает. Дело в том, что сигнатура говорит о том, что времена жизни ссылки на self и ссылок на трейт-объекты не связаны друг с другом. Но это явно не так, ведь мы собираемся класть в items данные из self! Что ж, выразим этот факт в коде:

trait AppendFmt {
   fn append_fmt_items<'a>(&'a self, items: &mut Vec<&'a dyn Debug>);
}

Теперь напишем реализации для компонент списка:

impl AppendFmt for HNil {
   fn append_fmt_items<'a>(&'a self, _: &mut Vec<&'a dyn Debug>) {
       /* nothing to do here */
   }
}

impl<H, T> AppendFmt for HCons<H, T>
where
   H: Debug,
   T: AppendFmt,
{
   fn append_fmt_items<'a>(&'a self, items: &mut Vec<&'a dyn Debug>) {
       items.push(&self.head);
       self.tail.append_fmt_items(items);
   }
}

Теперь мне бы очень хотелось написать impl<T: AppendFmt> Debug for T... но, к сожалению, мне не даст компилятор, потому что это будет перекрываться с impl<T: Debug> Debug for &'_ T. Так что, стиснув зубы, пишем руками:

impl Debug for HNil {
   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
       let list: &[&dyn Debug] = &[];
       list.fmt(f)
       // или просто f.write_str("[]")
   }
}

impl<H, T> Debug for HCons<H, T>
where
   Self: AppendFmt,
{
   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
       let mut items = Vec::new();
       self.append_fmt_items(&mut items);
       items.fmt(f)
   }
}

Проверив, снова распечатав hlist![42, 'b', "sup", ((), (3.4, Vec::<i32>::new()))]:

[42, 'b', "sup", ((), (3.4, []))]

А если попросить "красивую" печать?

[
   42,
   'b',
   "sup",
   (
       (),
       (
           3.4,
           [],
       ),
   ),
]

Гораздо лучше.
источник
Блог*
Но действительно ли нам нужно собирать всё в один вектор и лишний раз выделять память? Мы же можем поступить так же, как и реализация Debug для слайса: воспользоваться хелпером std::fmt::DebugList и скормить ему элементы списка. Единственной сложностью тут выступает то, что мы, очевидно, не можем (ну то есть можем, но не хотим, потому что это потребует написания дофига кода и будет неэффективно в рантайме) воспользоваться DebugList::entries, так что придётся скармливать элементы по одному при помощи DebugList::entry.

Снова выделим общий функционал в отдельный трейт:

trait HlistFmt {
   fn finish_fmt(&self, list: &mut DebugList<'_, '_>) -> fmt::Result;
}

Реализуем для HNil и HCons:

impl HlistFmt for HNil {
   fn finish_fmt(&self, list: &mut DebugList<'_, '_>) -> fmt::Result {
       list.finish()
   }
}

impl<H, T> HlistFmt for HCons<H, T>
where
   H: Debug,
   T: HlistFmt,
{
   fn finish_fmt(&self, list: &mut DebugList<'_, '_>) -> fmt::Result {
       list.entry(&self.head);
       self.tail.finish_fmt(list)
   }
}

Теперь через это реализуем Debug:

impl Debug for HNil {
   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
       self.finish_fmt(&mut f.debug_list())
       // или опять f.write_str("[]")
   }
}

impl<H, T> Debug for HCons<H, T>
where
   Self: HlistFmt,
{
   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
       self.finish_fmt(&mut f.debug_list())
   }
}

Если мы теперь распечатаем тот же самый пробный список, то мы получим те же самые результаты, так что показывать это я не буду.

DebugList — не единственный хелпер для форматирования в std, есть также DebugMap, DebugSet, DebugStruct и DebugTuple, суть функционала которых ясна из названий. Эти вещи сильно облегчают написание кастомных реализаций Debug, так что используйте их, пожалуйста.

P. S.: как всегда, весь код в гисте.
источник
Блог*
За час с момента публикации пост расшарили трижды, но ни одного комментария не последовало. Всё и так понятно или всё совсем непонятно? 🤔
источник
Блог*
источник
2021 November 06
Блог*
#prog #rust

В каком-то смысле костыль, но штука нужная
источник
Блог*
Наткнулся в твиттере на анонс интересного инструмента:

>  cargo-hakari

Он автоматизирует создание и поддержку "workspace-hack" крейтов, ускоряя компиляцию для больших воркспейсов. Что такое "workspace-hack" и зачем его используют в rustc и firefox — читайте в треде.
источник
Блог*
Вы не поверите, но это японские блины. Их подают в Crepes de Anne в Нагое.
источник
Блог*
#prog #rust

Вафель продолжает просвещать о возможностях rustdoc.

t.me/ihatereality/2525
источник
2021 November 07
Блог*
Как сделать ноготочки на типах rust
источник
2021 November 08
Блог*
#prog #rust

Трейт Deserializer имеет методы вида deserialize_type. Трейт Serializer имеет методы вида serialize_type. Что это значит? Это значит, что одно можно непосредственно сцепить с другим, и таким образом перегонять данные из одного формата данных, поддерживаемых serde, в другой, никогда не материализуя экземпляры соответствующих типов в памяти целиком. Собственно, именно это и делает serde-transcode.

Пример из документации (преттификация JSON):

extern crate serde;
extern crate serde_json;
extern crate serde_transcode;

use serde::Serialize;
use serde_json::{Serializer, Deserializer};
use std::io::{Read, Write, BufReader, BufWriter};
use std::fs::File;

fn main() {
   let reader = BufReader::new(File::open("input.json").unwrap());
   let writer = BufWriter::new(File::create("output.json").unwrap());

   let mut deserializer = Deserializer::from_reader(reader);
   let mut serializer = Serializer::pretty(writer);
   serde_transcode::transcode(&mut deserializer, &mut serializer).unwrap();
   serializer.into_inner().flush().unwrap();
}
источник
Блог*
Сделать, что ли, отдельный хештег для serde 🤔
источник
2021 November 09
Блог*
#prog #meme
источник
Блог*
источник