Мне не нравится реальность N.B. waffle is unhinged Кормить назад: @wafflelapkin Кормить вперёд: boosty.to/meowaffle Чят: https://t.me/joinchat/-TMz-LvAgTwyZTli
Сегодня у меня для вас фотография самой большой вафли в мире. Завтра? Кто знает
Читать полностью…Вышел Rust 1.50
!
Интересные (на мой взгляд) обновления:
— Присваивание полям union'ов типа MaybeUninit<_>
теперь safe
— Теперь можно использовать константы в выражениях массива [x; N]
(до этого можно было только :Copy
типы)
— ops::{Index, IndexMut}
теперь реализованы для массивов всех длин
— На unix
системах, std::fs::File
теперь имеет "нишу" -1, это значит что Option<File>
и File
могут иметь один размер
Стабилизировали bool::then
, {Ord, f32, f64}::clamp
, <[_]>::fill
. Многие методы чисел стабилизировали как const
(например pow
).
Так-же метод compare_and_swap
у атомиков депрекейтнули в пользу compare_exchange{,_weak}
(pr), забавно что планировали это сделать ещё в (!) Rust 1.12
, но забыли.
[анонс в блоге]
вафель держит Илью 2021 год, фото в цвете
Читать полностью…Bad Apple на вкладках лисы
https://youtu.be/JjTqE69ZkUs
Антон как обычно написал интересный пост, на этот раз про симуляцию iota
из Go
в Rust
при помощи макросов (прочитайте его прежде, чем этот пост).
Однако в посте есть небольшая ошибка:
Хочу отметить, что добиться в полной мере той же эргономики, что и на Go, несколько проблематично, поскольку в Rust декларативные макросы [...] имеют гигиену и потому не могут генерировать новые идентификаторы, доступные извне макроса, а могут лишь использовать те что уже имеются.
Это правда, но не в полной мере. В растовых макросах действительно есть гигиена, но не для всего, например — не для констант. Это значит, что мы можем просто заменить $iota
на iota
(или любой идентификатор по вкусу) и это продолжит работать:
iota_consts! {Читать полностью…
// Явно передавать идентификатор не нужно
const FOO: u32 = 1 << iota; // iota = 0, FOO = 1
const BAR: i32; // iota = 1, BAR = 2
_; // iota = 2
const BAZ: i8 = iota + 2; // iota = 3, BAZ = 5
const QUX: i16; // iota = 4, QUX = 6
}
В Твиттере тут подсказали замечательный сайт: shapecatcher.com
Можно нарисовать символ, а сайт попробует найти похожие в юникоде. Теперь можно без проблем писать n ∈ ℤ!
#video (видео ли?) #music
Bad apple, но с картинкой, составленной из субтитров.
(thanks @zoraxblog)
[1]: звучно — sound, т.е. безопасно, без UB, etc
Читать полностью…Недавно приняли RFC "Pointer metadata & VTable" которое добавляет новый #[lang_item]
— trait Pointee { type Metadata: ...; }
.Pointee
реализован для всех типов. Metadata
отвечает за тип метаданных (вау) в указателе (/ссылке) на этот тип. Для :Sized
и extern
типов Metadata = ()
, для str и [_]
Metadata = usize
, для dyn Trait
Metadata = DynMetadata<dyn Trait>
. Это значит что, например, &str
состоит из (*const (), usize)
.
По сути так было и раньше, но до этого RFC было не возможно записать эти правила средствами языка. Нельзя было узнать из чего состоит &T
(T: ?Sized
). Теперь можно — (*const (), <T as Pointee>::Metadata)
[0]
Это позволяет очень многое, например:
— ThinBox
, аналог Box
, но хранит метадату в куче
— Специализированные структуры для хранения ?Sized
типов (у меня была идея что-то подобное написать, но на тот момент это было не возможно)
— Нормально/честно/звучно работать с dyn Trait
, а не то как делали раньше (через transmute
безопасность которого не гарантированна)
Так же это первый шаг к поддержке полноценных CDST.
Я очень давно ждал эту фичу (какой это по счёту RFC на тему? 3-й?) и невероятно рад видеть что PR который её добавляет уже готов
Initial states:
m: 0.280 x: -2.816 y: 3.340 vx: -0.012 vy: 0.147
m: 0.668 x: 5.560 y: -7.085 vx: 0.426 vy: 0.126
m: 6.954 x: 4.808 y: -4.225 vx: -0.852 vy: 0.104
Interest-ness score: 35
Скоро конст-дество! ⛄
https://twitter.com/bitshiftmask/status/1359881273876045830?s=09
https://www.youtube.com/watch?v=b5x-r3iMKj0
Читать полностью…Привет!
Я тут релизнул новый крейт — kiam ("when" на Эсперанто).
Он предоставляет более удобную замену if
/else
— макрос when!
.
Синтаксис похож на match
, за тем лишь исключением, что вместо паттернов используются boolean
выражения как в обычных if
(так же можно использовать и паттерны но в формате if let
— по выражению на паттерн).
7 человек которым хотелось.... отпишитесь в комменты что-ли зачем вам это было нужно....
Читать полностью…@Hirrolot тут занимается моим любимым делом: извращением (с макросами).
Правда в отличии от меня занимается он этим не на Rust
, а на C
=)
Подробнее о его новой C
библиотеке с сумтипами в его статье: hirrolot/unleashing-sum-types-in-pure-c99-31544302d2ba" rel="nofollow">https://medium.com/@hirrolot/unleashing-sum-types-in-pure-c99-31544302d2ba
А вы помните как я говорил о стабилизации reduce
ещё в прошлом году?
Споры об имени тянулись так долго, что замерджили PR только сегодня. В итоге стабильным метод станет в rust 1.51
.
Наконец-то!
Когда-то давно охуенная @datstuff вышила мне формулу комбинатора неподвижной точки. Если не таким стоит украшать стены возле рабочего места, то я даже не знаю, чем.
Читать полностью…Присылайте в комменты стикеры я сделаю на них обзор
всем спокойной ночи сладких снов
видео наверное меньше чем субтитры по размеру, лол
Читать полностью…Привет девочки!!
Мой PR в std
(alloc
) добавляющий Vec::extend_from_within
наконец-то смерджили (tracking issue)!
tl;dr:
— Этот метод был предложен в RFC pr #2714
— Этот метод используется в разных крейтах и раньше его неправильные реализации приводили к UB
— Метод позволяет скопировать (склонировать) данные из вектора и добавить их в его же конецlet mut vec = vec![0, 1, 2, 3, 4];
vec.extend_from_within(2..);
assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]);
# Unsized типы и все-все-все
Пояснение к предыдущему посту, объясняющее что такое метадата, DST и зачем они нужны.
В расте есть так называемые DST — dynamically sized types. Это такие типы, которые не имеют размера известного на момент компиляции. Вместо этого их размер можно узнать только динамически — во время исполнения.
Такие типы нельзя хранить на стеке т.к. для этого потребовалось бы знать их размер во время компиляции. Такие типы нельзя передать в функцию по значению, их можно передать только по ссылке.
На данный момент примерами таких типов служат:
— [T]
— слайс, продолжительный кусок памяти состоящий из нескольких значений T
— str
— по сути [u8]
— dyn Trait
Q: Если их нельзя хранить на стеке, то как тогда создать значения этих типов?
A: Либо литералами ("aaa"
— литерал типа &'static str
), либо из типов с известным размером. Например из String
можно получить &str
, а из [T; N]
или Vec<T>
можно получить &[T]
. Из Ty
можно получить &dyn Trait
(при условии что Ty: Trait
).
Q: А откуда в рантайме берётся размер этих типов?
A: Вот тут мы и подходим к теме предыдущего поста — метадата.
Для обычных, :Sized
, (note: по умолчанию все дженерики :Sized
, чтобы такое отключить используется :?Sized
) типов &T
это просто указатель, одно машинное слово, usize
(семантически это не совсем так, но это совсем другая история).
Однако для DST
, !Sized
типов это не так. Ссылка на DST
это толстый указатель (англ: fat pointer) — указатель + мета.
Для разных типов метадата может быть разной. Например для [T]
метадата это usize
— количество элементов. А для dyn Trait
— ссылка на виртуальную таблицу с layout'ом объекта и методами трейта.
Важно подчеркнуть что метадата находится не только в ссылках (&_
, &mut _
), но и во всех других указателях: *const _
, *mut _
, Box<_>
, Arc<_>
, .... Исключениями являются только особые теоретические указатели вроде ThinBox
, которые хранят метадату где-то в другом месте.
Т.е. что &[T]
, что Box<str>
, что *mut dyn Trait
— все кроме указателя хранят ещё и метадату.
Так-же стоит отметить что указатели на !Sized
типы являются Sized
.
Q: Зачем так сложно??
A: ну ээээмммммм
Во-первых то, что мета хранится рядом с указателем, хорошо для кэша. Это хорошо выделяет Rust
на фоне других языков, где указатель на VTable
(метадата dyn Trait
) для динамической диспетчеризации находится в самом объекте (т.е. чтобы добраться до VTable
нужно 2 раза пройтись н- по указателю).
Во-вторых это позволяет переиспользовать разные контейнеры — &[T]
, &mut [T]
, Box<[T]>
, Arc<[T]>
, ... — всё это валидные типы, которые можно создать и всё они имеют смысл. Можно было бы вместо &str
сделать StrView<'a> { data: &'a (), len: usize }
, но тогда бы пришлось для каждого вида указателя городить свой тип.
В-третьих это позволяет коерсить (от англ.: coercion, в данном контексте: преобразовывать без изменений) объекты о которых известна информацию во время компиляции, в объекты о которых информация известна во время исполнения. Например: [T; N]
(массив) не хранит нигде свой размер, размер известен во время компиляции — N
. При этом из [T; N]
можно получить &[T]
, для которого размер уже надо где-то хранить. Рядом с данными размер мы хранить не можем — это потребует добавление чего-то перед массивом. Так что хранить размер в ссылке оказывается очень удобно (тоже самое получается и с dyn Trait
).
Надеюсь я объяснил всё достаточно понятно, но если всё ещё не понятно — не стесняйтесь спрашивать в комментариях. Дополнительное чтиво по теме:
— Rust Book: Dynamically Sized Types and the Sized Trait
— Nomicon: Dynamically Sized Types (DSTs)
— Nomicon: Coercions
— cheats.rs
— fasterthanlime: Working with strings in Rust
[0]: уточнение: layout ссылок не гарантирован, чтобы разобрать указатель на части используйте соответствующий метод стандартной библиотеки и проконсультируйтесь со специалистом
Читать полностью…А что можно почитать про компиляторо строение? Покидайте в комменты книжек/статей для таких вафелек как я
Читать полностью…По такому поводу, допилил поддержку кастомных тем и интеграцию с ночным режимом на docs.rs, теперь всё няшненько-нативненько
Читать полностью…