#prog
TIL, что мьютексы из POSIX threads нельзя перемещать.
Once a mutex is created, it cannot be validly copied or moved to a new location. If the mutex is copied or moved to a new location, the new object is not valid and should not be used. Any attempt to use the invalid object will produce unpredictable results.
Здесь. Что ж, это объясняет, почему мьютексы из стандартной библиотеки Rust боксят нативные мьютексы.
TIL, что мьютексы из POSIX threads нельзя перемещать.
Once a mutex is created, it cannot be validly copied or moved to a new location. If the mutex is copied or moved to a new location, the new object is not valid and should not be used. Any attempt to use the invalid object will produce unpredictable results.
Здесь. Что ж, это объясняет, почему мьютексы из стандартной библиотеки Rust боксят нативные мьютексы.
GitHub
rust/library/std/src/sync/mutex.rs at e6d85ea5cbdc376ae388e1079769b67b9eda911c · rust-lang/rust
Empowering everyone to build reliable and efficient software. - rust-lang/rust
Forwarded from You Had No Job
Поправь опечатку:
• Хейт миддл: всё технологии говно, коллеги — чудаки, раньше было лучше
• Хайп миддл: перепишет фронт на Расте, устал от микросервисов и использует макросервисы
• Найт миддл: обожает томатный смузи, никогда не появлялся на утреннем дейли
• Хейт миддл: всё технологии говно, коллеги — чудаки, раньше было лучше
• Хайп миддл: перепишет фронт на Расте, устал от микросервисов и использует макросервисы
• Найт миддл: обожает томатный смузи, никогда не появлялся на утреннем дейли
Forwarded from рандомные картинки
документация к git, идентичная натуральной: https://git-man-page-generator.lokaltog.net/
Блог*
Когда-то я написал на Rust программу, которая переводила числа в строку прописью (т. е. 123 -> "сто двадцать три"). Написал и решил написать статью о том, как написать подобную программу. Это было год назад. Статья всё ещё не готова.
Всё ещё не готова. Кажется, я знаю, чем займусь на выходных
🌚1
#science #article
Замечательная статья про разбор художественного произведения с точки зрения теории информации. А в комментариях дали ссылку на замечательный рассказ Каганова на примерно ту же тему, что и Death Note
Замечательная статья про разбор художественного произведения с точки зрения теории информации. А в комментариях дали ссылку на замечательный рассказ Каганова на примерно ту же тему, что и Death Note
Хабр
Death Note, анонимность и энтропия
В начале “Death Note” местный гениальный детектив по сути занят деанонимизацией: он знает только то, что убийца существует где-то на планете. Никаких улик тот н...
Блог*
Ох, постараюсь уложить это в голове. Есть ещё что-то, что нужно знать о замыканиях? Да. Иногда требуется одно и тоже замыкание передать в качестве аргумента в несколько функций. Клонировать в этом случае не получится, потому что замыкание является клонируемым…
> И будем надеяться, что его не придётся ждать ещё пару месяцев
АХАХАХХАХАХХА
АХАХАХХАХАХХА
Блог*
Ох, постараюсь уложить это в голове. Есть ещё что-то, что нужно знать о замыканиях? Да. Иногда требуется одно и тоже замыкание передать в качестве аргумента в несколько функций. Клонировать в этом случае не получится, потому что замыкание является клонируемым…
#prog #rust #моё
Хроники замыканий
Есть ещё кое-что, что можно сказать про замыкания.
Пожалуй, первое, с чего надо начать — так это с того, что, несмотря на то, что замыкания — это автоматически генерируемые структуры, реализующие определённые трейты, реализовать их самому для своих типов нельзя — по крайней мере, на стабильной версии Rust. Для того, чтобы определить один из Fn*-трейтов для своего типа, нужно активировать две фичи. Первая — fn_traits — позволяет написать определение трейта в обычном виде, а не в засахаренном
Стоп, в Rust есть одноместный кортеж?!
Да. Он объявляется одинаково на уровне термов и на уровне типов:
Надо сказать, что замыкания являются, в сущности, обычными типами, которые отличаются в основном анонимностью. И на них, в частности, нужно в некоторых ситуациях накладывать нужные ограничения. Рассмотрим в качестве примера функцию, которая принимает некоторый счётчик и возвращает замыкание, которое инкрементирует этот счётчик на каждый вызов. Для простоты пусть это будет просто
А разве компилятор не может сам догадаться, как надо?
Нет. Компилятор проверяет правильность расстановки времён жизни, анализируя лишь сигнатуру функции, а не её тело.
Хорошо. Так как нам заставить этот код компилироваться?
Указать явно, что возвращаемое замыкание не может пережить захваченную ссылку. Мы можем сделать это, введя для времени жизни имя и приписав его ссылке и возвращаемому замыканию:
Это связано с тем, как замыкания в Rust работают с захваченными значениями (т. е. со значениями, объявленными снаружи самого замыкания). По умолчанию замыкания захватывают переменные по ссылке (то есть сгенерированный анонимный тип содержит ссылки на эти значения) — мутабельной или иммутабельной, в зависимости от того, как они используются внутри тела замыкания. Использование ключевого слова move переопределяет это поведение по умолчанию и заставляет замыкание захватывать переменные по значению (т. е. перемещает их в замыкание). Если его убрать, то
Так, стоп, так
В правильном или неправильном варианте?
...В правильном
По значению.
Но...
Просто в данном случае само захватываемое значение является ссылкой.
А, я понял. Кажется...
Ничего, это действительно поначалу немного сбивает с толку.
Что ж, это всё, что ты хотел рассказать про замыкания?
Всё? ВСЁ? АХАХХАХАХХАХХА
О_о
Хроники замыканий
Есть ещё кое-что, что можно сказать про замыкания.
Пожалуй, первое, с чего надо начать — так это с того, что, несмотря на то, что замыкания — это автоматически генерируемые структуры, реализующие определённые трейты, реализовать их самому для своих типов нельзя — по крайней мере, на стабильной версии Rust. Для того, чтобы определить один из Fn*-трейтов для своего типа, нужно активировать две фичи. Первая — fn_traits — позволяет написать определение трейта в обычном виде, а не в засахаренном
Fn(Foo) -> Bar, как обычно. Вторая — unboxed_closures — позволяет определять функции с ABI rust-call, которое имеют методы Fn*-трейтов. Если мы их используем, то мы можем сделать то, что невозможно на текущей стабильной версии Rust: перегрузку функции по количеству аргументов. Причина, по которой эти трейты не стабилизированы, видимо, состоит в том, что им в качестве ти́пового параметра требуется не произвольный тип, а кортеж типов аргументов. Это выглядит несколько неловко на фоне отсутствия вариадических обобщённых типов, особенно для функции от одного аргумента — его приходится заключать в одноместный кортеж.Стоп, в Rust есть одноместный кортеж?!
Да. Он объявляется одинаково на уровне термов и на уровне типов:
(x,)
Ужас какой. А что ещё можно сказать про замыкания?Надо сказать, что замыкания являются, в сущности, обычными типами, которые отличаются в основном анонимностью. И на них, в частности, нужно в некоторых ситуациях накладывать нужные ограничения. Рассмотрим в качестве примера функцию, которая принимает некоторый счётчик и возвращает замыкание, которое инкрементирует этот счётчик на каждый вызов. Для простоты пусть это будет просто
u32. Кажется, что можно написать вот так:fn make_incrementer(counter: &mut u32) -> impl FnMut() {
move || *counter += 1
}
, однако этого недостаточно. Дело в том, что возвращаемое замыкание хранит мутабельную ссылку, которая имеет своё время жизни, но это никак не отражено в сигнатуре. Трейты в сигнатурах без явно указанных ограничений времени получают ограничение 'static, что в данном случае явно неверно.А разве компилятор не может сам догадаться, как надо?
Нет. Компилятор проверяет правильность расстановки времён жизни, анализируя лишь сигнатуру функции, а не её тело.
Хорошо. Так как нам заставить этот код компилироваться?
Указать явно, что возвращаемое замыкание не может пережить захваченную ссылку. Мы можем сделать это, введя для времени жизни имя и приписав его ссылке и возвращаемому замыканию:
fn make_incrementer<'a>(counter: &'a mut u32) -> impl FnMut() + 'a { // ...
...или же мы можем побыть ленивыми и, последовав совету компилятора, навернуть анонимное время жизни:fn make_incrementer(counter: &mut u32) -> impl FnMut() + '_ { // ...
Ясно. А для чего там move?Это связано с тем, как замыкания в Rust работают с захваченными значениями (т. е. со значениями, объявленными снаружи самого замыкания). По умолчанию замыкания захватывают переменные по ссылке (то есть сгенерированный анонимный тип содержит ссылки на эти значения) — мутабельной или иммутабельной, в зависимости от того, как они используются внутри тела замыкания. Использование ключевого слова move переопределяет это поведение по умолчанию и заставляет замыкание захватывать переменные по значению (т. е. перемещает их в замыкание). Если его убрать, то
make_counter не будет компилироваться: аргумент counter — фактически, локальная переменная — захватывается по ссылке, время жизни которой ограничено скоупом make_counter, поэтому вернуть такое замыкание за пределы порождающей его функции нельзя.Так, стоп, так
counter захватывается по ссылке или по значению?В правильном или неправильном варианте?
...В правильном
По значению.
Но...
Просто в данном случае само захватываемое значение является ссылкой.
А, я понял. Кажется...
Ничего, это действительно поначалу немного сбивает с толку.
Что ж, это всё, что ты хотел рассказать про замыкания?
Всё? ВСЁ? АХАХХАХАХХАХХА
О_о