Forwarded from oleg_log (Oleg Kovalov)
Open Access to ACM Digital Library During Coronavirus Pandemic
For the next three months, there will be no fees assessed for accessing or downloading work published by ACM. We hope this will help researchers, practitioners and students maintain access to our publications as well as increasing visibility and awareness of ACM’s journals, proceedings and magazines. Please be sure to inform your colleagues that the ACM DL is now open, and will continue that way through June 30, 2020.
https://www.acm.org/articles/bulletins/2020/march/dl-access-during-covid-19
For the next three months, there will be no fees assessed for accessing or downloading work published by ACM. We hope this will help researchers, practitioners and students maintain access to our publications as well as increasing visibility and awareness of ACM’s journals, proceedings and magazines. Please be sure to inform your colleagues that the ACM DL is now open, and will continue that way through June 30, 2020.
https://www.acm.org/articles/bulletins/2020/march/dl-access-during-covid-19
www.acm.org
Message from ACM Regarding Open Access to ACM Digital Library during Coronavirus
All work published by ACM in the ACM Digital Library will be freely accessible until 6/30/20.
Forwarded from мне не нравится реальность
# методы в трейтах под #[cfg]
Условная компиляция (aka conditional compilation) часто используется в расте, чтобы добавить какой-то функционал только если включена определённая фича. Но есть проблема — в трейтах такое сложно применять т.к. если крейт
Можно использовать дефолтные реализации, но это путь вникуда. Честно. Никаких
Настоящее решение проблемы /которое я подсмотрел в serde/ — сделать макрос который с фичей раскрывается то что ему передали, а без — в ничего.
Чтобы потом пользователи библиотеки могли легко реализовать твой трейт:
#rust #tip
Условная компиляция (aka conditional compilation) часто используется в расте, чтобы добавить какой-то функционал только если включена определённая фича. Но есть проблема — в трейтах такое сложно применять т.к. если крейт
A
реализует твой трейт, но не использует твою фичу, то он отдельно может компилироваться, а с крейтом B
, который использует твою фичу — нет т.к. крейт A
не реализует требуемую функцию. (я вас не запутал?)Можно использовать дефолтные реализации, но это путь вникуда. Честно. Никаких
unimplemented!()
. Пожалуйста.Настоящее решение проблемы /которое я подсмотрел в serde/ — сделать макрос который с фичей раскрывается то что ему передали, а без — в ничего.
#[cfg(feature = "feature")]
#[macro_export]
macro_rules! if_feature {
($($tt:tt)*) => {
$($tt)*
};
}
#[cfg(not(feature = "feature"))]
#[macro_export]
macro_rules! if_feature {
($($tt:tt)*) => {};
}
Чтобы потом пользователи библиотеки могли легко реализовать твой трейт:
impl Trait for Type {
// ...
lib::if_feature! {
fn uses_feature() {
// ...
}
}
}
#rust #tip
#prog #article
Статья о том, как взаимодействие различных фич выливается в уязвимости. Автор, приверженец OpenBSD, предлагает решать проблему отсутствием фич. Радикальный подход, который мне не импонирует, но рассказывает автор убедительно.
flak.tedunangst.com/post/features-are-faults-redux
Статья о том, как взаимодействие различных фич выливается в уязвимости. Автор, приверженец OpenBSD, предлагает решать проблему отсутствием фич. Радикальный подход, который мне не импонирует, но рассказывает автор убедительно.
flak.tedunangst.com/post/features-are-faults-redux
Блог*
#prog #article Статья о том, как взаимодействие различных фич выливается в уязвимости. Автор, приверженец OpenBSD, предлагает решать проблему отсутствием фич. Радикальный подход, который мне не импонирует, но рассказывает автор убедительно. flak.tedun…
#prog #article
В той статье есть ссылка на эту:
Читается на одном дыхании, как неплохой детектив.
daniellesucher.com/2014/04/24/my-new-favorite-vim-tmux-bug/
В той статье есть ссылка на эту:
minimal repro:
On Suffolk (one of our machines), open tmux, open vim, open new terminal tab.
Vim gets “lililililililill” inserted in current file, and beeps a lot
If the file already has content, it prepends i and appends ll to ~10 lines, and sometimes capitalizes something
Читается на одном дыхании, как неплохой детектив.
daniellesucher.com/2014/04/24/my-new-favorite-vim-tmux-bug/
Forwarded from folex
Ну нет. JS – не норм. Всё имеет доступ ко всему. Всё принимает всё, и возвращает всё. Каждый на свой лад оборачивает значения в свои полупрозрачные обертки с прокидыванием методов.
Где что используется понять невозможно. Откуда берутся методы у объектов понять невозможно. У кого есть ссылка на объект понять невозможно. Всё имеет влияние не всё, сайдэффект на сайдэффекте.
Это как глобальные переменные, только они не объявлены в верхнем скоупе, а пролазят из внутренностей кода наружу, и расползаются, метастазируя стейтом.
Где что используется понять невозможно. Откуда берутся методы у объектов понять невозможно. У кого есть ссылка на объект понять невозможно. Всё имеет влияние не всё, сайдэффект на сайдэффекте.
Это как глобальные переменные, только они не объявлены в верхнем скоупе, а пролазят из внутренностей кода наружу, и расползаются, метастазируя стейтом.
#article
@milfgard опять причиняет интерес. На этот раз — разбор деталей карточной игры в "Пиковой даме".
Бы ли б у меня подобные уроки в школе — наверняка куда больше литературу любил.
habr.com/ru/company/tuturu/blog/495110/
@milfgard опять причиняет интерес. На этот раз — разбор деталей карточной игры в "Пиковой даме".
Бы ли б у меня подобные уроки в школе — наверняка куда больше литературу любил.
habr.com/ru/company/tuturu/blog/495110/
Хабр
Что происходит в «Пиковой даме» Пушкина и во что они играют?
Если коротко — Пушкин открыл жанр «киберспортивной фантастики». Только до появления фантастики и киберспорта. Его одно из самых известных произведений — «Пиковая дама» — это рассказ про мегапопулярную...
Предыдущий пин: https://t.iss.one/dereference_pointer_there/378
Telegram
Блог*
#prog #rust #article
Как сделать API, оперирующее глобальным состоянием, которое не даёт возможности использовать себя некорректно. Rust особенно хорош в части предотвращения неправильного использования на этапе компиляции: единственная проверка в рантайме…
Как сделать API, оперирующее глобальным состоянием, которое не даёт возможности использовать себя некорректно. Rust особенно хорош в части предотвращения неправильного использования на этапе компиляции: единственная проверка в рантайме…
#prog #rust
Как хорошо, что rust core team тратит время на по-настоящему важные вещи.
https://github.com/rust-lang/rust/pull/70645
Как хорошо, что rust core team тратит время на по-настоящему важные вещи.
https://github.com/rust-lang/rust/pull/70645
GitHub
Forbid pineapple on pizza by pietroalbini · Pull Request #70645 · rust-lang/rust
This PR adds a new forbid-by-default lint to the Rust compiler, preventing users from writing wildly untasteful types such as Pizza<Pineapple>.
r? @estebank
cc @steveklabnik, what do...
r? @estebank
cc @steveklabnik, what do...
#prog #rust #моё
В Rust в некоторых случаях можно использовать анонимный лайфтайм (
Времена жизни — пожалуй, именно та фича, которая больше всего делает Rust непохожим на мейнстримные языки программирования. В частности, их синтаксис (
Раскрытие сокращённой записи начинается с введения нового явного параметра для каждого аргумента, тип которого параметризован временем жизни (далее ВЖ), но для которого конкретное значение ВЖ не указано. Например, если у нас функция
Далее компилятор пытается приписать времена жизни возвращаемому типу. В обычном коде произвольные времена жизни не материализуются из ничего, они появляются из ссылок на имеющиеся значения. Логично предположить, что если у тебя есть функция с ВЖ, то ВЖ возвращаемого типа должно быть связано с аргументами. Если аргументов нет вовсе, то компилятор откажется компилировать функцию. Если аргумент есть только один и с одним обобщенным параметром ВЖ, то возвращаемый тип параметризуется этим ВЖ для всех возможных обобщённых параметров. Например, если есть функция
В Rust в некоторых случаях можно использовать анонимный лайфтайм (
'_
). Практика показывает, что эта фича некоторым не до конца понятна, поэтому я решил написать об этом подробнее.Времена жизни — пожалуй, именно та фича, которая больше всего делает Rust непохожим на мейнстримные языки программирования. В частности, их синтаксис (
'identifier
) — это то, что приходит первым на ум тому, кто уверяет, что у Rust нечитаемый синтаксис. Тем не менее, если взглянуть на код программы на Rust, то этих времён жизни можно увидеть очень мало. Казалось бы, как так может быть, если учесть, что каждая ссылка параметризована временем жизни, а ссылки в Rust используются достаточно активно? Дело в том, что бо́льшая часть вариантов использования времён жизни подпадает под один из достаточно простых паттернов, для которых компилятор в состоянии вывести отсутствующие времена жизни сам. Это называется lifetime elision, и правила, по которым оно происходит, перечислены в растономиконе. Раскрытие сокращённой записи начинается с введения нового явного параметра для каждого аргумента, тип которого параметризован временем жизни (далее ВЖ), но для которого конкретное значение ВЖ не указано. Например, если у нас функция
fn do_something(a: &mut u32, b: (&u32, &u32), c: Cow<str>) { ... }, то после первого шага преобразования она выглядит так:
fn do_something<'lt1, 'lt2, 'lt3, 'lt4>(a: &'lt1 mut u32, b: (&'lt2 u32, &'lt3 u32), c: Cow<'lt4, str>) { ... }Обратите внимание, это работает не только с ссылками.
Далее компилятор пытается приписать времена жизни возвращаемому типу. В обычном коде произвольные времена жизни не материализуются из ничего, они появляются из ссылок на имеющиеся значения. Логично предположить, что если у тебя есть функция с ВЖ, то ВЖ возвращаемого типа должно быть связано с аргументами. Если аргументов нет вовсе, то компилятор откажется компилировать функцию. Если аргумент есть только один и с одним обобщенным параметром ВЖ, то возвращаемый тип параметризуется этим ВЖ для всех возможных обобщённых параметров. Например, если есть функция
fn first_and_second(arg: &(u32, u32, u32))- > (&u32, &u32) {, то её развёрнутый тип будет
(&arg.0, &arg.1)
}
fn first_and_second<'a>(arg: &'a (u32, u32, u32))- > (&'a u32, &'a u32) {Что же делать, если аргументов несколько? В случае, когда функция принимает
(&arg.0, &arg.1)
}
&self
или &mut self
, ВЖ возвращаемого типа приравнивается ВЖ self
. Из этого, кстати, следует несколько неожиданный результат, что нижеприведённый код не компилируется:struct Foo;Если расписать тип полностью, то станет понятно, почему:
impl Foo {
fn use_str(&self, s: &str) -> &str {
s
}
}
struct Foo;Действительно, lifetime elision приводит к тому, что возвращаемая строка имеет то же ВЖ, что и
impl Foo {
fn use_str<'foo, 's>(&'foo self, s: &'s str) -> &'foo str {
s
}
}
self
, но в теле функции используется строка с другим ВЖ 's
, которое никак не связано с 'foo
. Для того, чтобы решить эту проблему, нужно явно ввести обобщённый параметр времени жизни и указать, что он один и тот же у аргумента и возвращаемого значения:struct Foo;Такой код уже компилируется.
impl Foo {
fn use_str<'s>(&self, s: &'s str) -> &'s str {
s
}
}
Telegram
folex in codingteam
Не выходит прототипировать на расте у меня
Собственно, это все правила, которым подчиняется lifetime elision. Если описанные выше случаи не применимы, то компилятор скажет "я не могу, у меня лапки". Отчасти именно из-за этого начинающим настолько затруднительно усваивать концепцию времён жизни: в простых случаях их писать не надо, поэтому ситуации, в которых ВЖ действительно нужно писать, уже не очень тривиальны. Какое это имеет отношение к анонимным временам жизни? Само непосредственное:
Но погодите-ка, это ещё не всё! Анонимное ВЖ можно также использовать и в блоке
Недостатки у такого способа тоже есть. Каждое использование
Подведём итоги:
* Анонимные времена жизни можно использовать в возращаемых типах и в заголовках
* В возвращаемых типах анонимные ВЖ заполняются с использованием нехитрых правил lifetime elision
* В
- В силу их анонимности их нельзя использовать напрямую
'_
можно указать вместо обобщённого параметра ВЖ, чтобы компилятор его вывел. Скажем, сигнатуру first_and_second
можно написать и так: fn first_and_second(arg: &(u32, u32, u32))- > (&'_ u32, &'_ u32)
. Кажется, что это ненужное добавление, но есть случаи, когда это необходимо (при условии, что программист всё ещё не хочет писать ВЖ явно). Рассмотрим вот такой код (несколько надуманный, но достаточно наглядный);fn non_zero(slice: &[u32]) -> Box<dyn Iterator<Item = &u32>> {Этот код не компилируется. Претензия компилятора сводится к несовпадению типов:
Box::new(slice.iter().filter(|&&n| n != 0))
}
= note: expected `std::boxed::Box<(dyn std::iter::Iterator<Item = &u32> + 'static)>`Да, тут есть ссылка в возвращаемом типе, и ей приписывается то же ВЖ, что и у
found `std::boxed::Box<dyn std::iter::Iterator<Item = &u32>>`
slice
, но мы не записали время жизни типа внутри коробки, то есть dyn Iterator
. Компилятор предположил, что это владеющий тип и, следовательно, он имеет ВЖ 'static
, которое является более долгоживущим, чем любое другое ВЖ. Но это не так: возвращаемый итератор содержит ссылку на слайс и потому не может пережить этот слайс. Один из способов исправить ошибку — это ввести новый параметр ВЖ и указать, что возвращаемый тип столько же и живёт, но... Мы ленивые программисты и не хотим писать много, поэтому мы напишем ровно столько, чтобы заставить компилятор работать за нас:fn non_zero(slice: &[u32]) -> Box<dyn Iterator<Item = &u32> + '_> { ... }Да, разница действительно всего в 3 символа, не считая пробелов. С такой сигнатурой код уже компилируется, потому теперь благодаря lifetime elision возвращаемому типу приписывается корректное ВЖ.
Но погодите-ка, это ещё не всё! Анонимное ВЖ можно также использовать и в блоке
impl
. Об этом написано в edition guide здесь и здесь. Порой в impl
-блоке типа, параметризованного ВЖ, ничто не зависит от указанного ВЖ, поэтому вместо того, чтобы вводить явно ВЖ после impl
и использовать его для типа, можно просто указать '_
. Например, если у нас есть определение struct StrWrap<'a>(&'a str);
, то можно написать блок методов так:impl<'a> StrWrap<'a> { ..., а можно — так:
impl StrWrap<'_>Это работает и в том случае, если параметров ВЖ несколько: для
struct StrPair<'a, 'b: 'a>('a str, &'b str);
можно написать так;impl StrPair<'_, '_> { ...Если между ВЖ заданы отношения, то сгенерированные ВЖ будут также им удовлетворять.
Недостатки у такого способа тоже есть. Каждое использование
'_
в заголовке impl
-блока создаёт новое ВЖ, что не всегда желательно. Например, в коде нижеtrait WithLifetime<'a> {}реализация трейта эквивалентна
impl WithLifetime<'_> for &str {}
impl<'a, 'b> WithLifetime<'a> for &'b str {}, а не
impl<'a> WithLifetime<'a> for &'a str {}, как можно было подумать. Если требуется, чтобы двое ВЖ для методов было одинаковым, то их надо указывать (и вводить) явно — но только их, остальные можно заполнить анонимным ВЖ. Например, если у нас есть
struct Triple<'a, 'b, 'c>(&'a u32, &'b u32, &'c u32);
, то можно написать impl
-блок так:impl<'a> Triple<'a, 'a, '_> {}Также, очевидно, в силу анонимности этих параметров на них нельзя напрямую ссылаться (но можно через псевдоним типа
Self
).Подведём итоги:
* Анонимные времена жизни можно использовать в возращаемых типах и в заголовках
impl
-блоков* В возвращаемых типах анонимные ВЖ заполняются с использованием нехитрых правил lifetime elision
* В
impl
-блоках анонимные ВЖ генерируют новые ВЖ на каждое упоминание- В силу их анонимности их нельзя использовать напрямую
Напоминаю: если вам есть, что сказать — какие-то детали непонятны, или видите неточность — пишите мне в @decltype_chat_ptr_t
#prog
Leetcode проводит челлендж: 30 дней задач по программированию, из числа тех, что задают на интервью. Обещают простые задачи. Для тех, кто хорошо решает, разыгрываются призы.
Только, это... Уже неделю как идёт.
leetcode.com/explore/featured/card/30-day-leetcoding-challenge/
Leetcode проводит челлендж: 30 дней задач по программированию, из числа тех, что задают на интервью. Обещают простые задачи. Для тех, кто хорошо решает, разыгрываются призы.
Только, это... Уже неделю как идёт.
leetcode.com/explore/featured/card/30-day-leetcoding-challenge/
Leetcode
Explore - LeetCode
LeetCode Explore is the best place for everyone to start practicing and learning on LeetCode. No matter if you are a beginner or a master, there are always new topics waiting for you to explore.