Отлично, теперь переходим к самому вкусному: написанию макроса! Нам нужно разобрать
Что ж, давайте опробуем макрос в действии:
match
, так что начнём с этого:macro_rules! ascii_case_insensitive {
(match $value:ident {
$(... ,)*
_ => $catch_all:expr $(,)?
}) => { ... }
}
А теперь на минуту остановимся и подумаем, что из себя представляет паттерн, который мы пытаемся разобрать. В прошлый раз я совершенно упустил из виду, что обычно мы можем перечислить несколько паттернов, разделив их |
, равно как и то, что паттерн может также предваряться |
. Таким образом, корректный кусок макроса для распознавания паттернов должен выглядеть так:$(|)? $($pattern:literal)|+
$(|)?
отвечает за опциональную черту в начале. $pattern:literal
говорит, что $pattern
— это литерал, а $(...)|+
говорит о том, что то, что внутри скобок, повторяется один или более раз, и что повторы разделены |
. Но постойте-ка, есть же ещё и опциональное охранное выражение! С учётом всего этого паттерн для одной ветви принимает такой вид:$(|)? $($pattern:literal)|+ $(if $condition:expr)? => $arm:expr,Отлично, с разбором мы справились (правда, всё так же упустив возможность привязать имена к паттернам). Что мы со всем этим делаем? Мы проверяем, что все строки в нижнем регистре:
#[deny(const_err)]И что они все разные:
const _ARE_ALL_ASCII_LOWERCASE: [(); 1] = [(); are_all_ascii_lowercase(&[$($($pattern,)+)*]) as _];
#[allow(dead_code)]А что нам делать непосредственно самой проверкой? Мы проверяем, что значение равно, за вычетом ASCII-регистра, одному из паттернов... И что охранное выражение также справедливо, если оно есть:
fn non_repeating(s: &str) {
#[deny(unreachable_patterns)]
match s {
$($(| $pattern)+ => (),)*
_ => (),
}
}
x if ($(x.eq_ignore_ascii_case($pattern))||+) $(&& $condition)? => $arm,Обратите внимание, здесь мы повторяем (
+
) выражения для паттернов, разделив их ||
.Что ж, давайте опробуем макрос в действии:
#[derive(Debug)]Эта программа выдаёт следующее:
enum Example {
Foo,
Bar,
FourtyTwo,
}
impl std::str::FromStr for Example {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ascii_case_insensitive!(match s {
"foo" => Self::Foo,
"bar" if s.as_bytes()[0].is_ascii_lowercase() => Self::Bar,
"fourtytwo" | "fourty_two" | "42" => Self::FourtyTwo,
_ => return Err(s.into()),
}))
}
}
fn main() {
let inputs = [
"foo",
"Foo",
"FOO",
"bar",
"bAr",
"BAR", // ошибка, первый символ в верхнем регистре
"fourtytwo",
"Fourtytwo",
"FOURTYTWO",
"fourty_two",
"fOuRtY_tWo",
"42",
"bogus",
];
for &input in &inputs[..] {
println!("{:?}", input.parse::<Example>());
}
}
Ok(Foo)...как и ожидалось. Что будет, если мы попытаемся сделать два одинаковых паттерна? Скажем, так:
Ok(Foo)
Ok(Foo)
Ok(Bar)
Ok(Bar)
Err("BAR")
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Err("bogus")
...Компилятор жалуется:
"foo" | "foo" => Self::Foo,
...
error: unreachable patternА если один из паттернов не в нижнем регистре:
...то компилятор опять жалуется:
"Foo" => Self::Foo,
...
error[E0308]: mismatched typesВсё работает, как и ожидалось! Как всегда, весь код в гисте.
Telegram
Блог*
#prog #rust #моё
В Rust есть такая удобная вещь, как сопоставление с образцом (pattern matching), и она работает в том числе и для строк. К сожалению, оно позволяет сопоставлять только строки целиком, но не по частям. В частности (no pun intended), match…
В Rust есть такая удобная вещь, как сопоставление с образцом (pattern matching), и она работает в том числе и для строк. К сожалению, оно позволяет сопоставлять только строки целиком, но не по частям. В частности (no pun intended), match…
#prog #article
Обзор истории систем контроля версий с разбором их внутренних устройств в двух частях: первая, вторая.
В тему также интервью с Pierre-Étienne Meunier, ведущим разработчиком Pijul.
Обзор истории систем контроля версий с разбором их внутренних устройств в двух частях: первая, вторая.
В тему также интервью с Pierre-Étienne Meunier, ведущим разработчиком Pijul.
Initial Commit
Version Control Systems | A Technical Guide to VCS Internals
Learn what a version control system is and provide technical details of some of the most popular version control systems like SCCS, RCS, CVS, Subversion, Git, and Mercurial.
#prog #rust #article
Статья о том, чего бы автору хотелось видеть для Rust в 2021 году. Всё ключевые моменты выделять не буду (а иначе зачем я вам ссылку даю?), выделю только то, что привлекло моё внимание:
* I want to see Rust shed some of its reputation for being hard to learn
Согласно автору, новички сталкиваются с повышенной нагрузкой при изучении языка, поскольку им приходится учить и сам язык, и то, как писать на нём идиоматичный код. Учить Rust сложно ввиду того, что он схож с мейнстримными ЯП, но при этом довольно сильно от них отличается — достаточно, чтобы предыдущий опыт был не слишком полезен. Одним из следствий этих отличий является то, что лучшие практики из одних языков считаются антипаттернами в Rust (pub/sub, observer pattern), равно как и наоборот (затенение переменных). Автор считает, что новичкам имеет смысл позволить себе писать сначала неаккуратный и/или неидиоматичный код, а улучшать его уже потом. Да, это вопрос чисто психологический, но в интернете чаще выкладывают хороший код и редко — скажем так, не очень хороший, что создаёт определённое психологическое давление. Именно это и пишет автор:
I am not exactly sure how to create the conditions for this outcome. Maybe more people can publish more Rust that looks messy but “just works”.
Собственно, как совершенно справедливо заметил trentj на URLO (что в итоге стало фразой недели в TWiR №360):
"Just because Rust allows you to write super cool non-allocating zero-copy algorithms safely, doesn’t mean every algorithm you write should be super cool, zero-copy and non-allocating."
* More blog posts from developers and management using Rust at work
Особенно автору хочется видеть материалы с информацией о том, почему был выбран именно Rust, и о том, каков был опыт по сравнению с предыдущей реализацией — как правило, написанной на другом языке.
It’s great to hear Rust used in complicated, low-level development, but it would be normalizing to read about more trivial types of applications, just as a way to highlight Rust as being good for general purpose use.
Я со своей стороны могу лишь добавить, что по мере возможности стараюсь закрывать этот пробел в русскоязычном сообществе Telegram. Некоторые из подобных постов на моём канале можно найти по хештегу #successstory.
* More shared experiences from people picking up Rust as a second language.
Во многом перекликается с первым тезисом. Согласно автору, это может поспособствовать двум вещам: показать, что для того, чтобы выучить Rust, не нужно быть каким-то выдающимся человеком, и раскрыть глаза на вещи, которые опытные Rust-разработчики не замечают или воспринимают как должное.
I believe content from this crowd would be my favorites to read since I think they’ll give valid opinions to someone who has been using Rust for years (like me) now overlook or accept without second thoughts.
Статья о том, чего бы автору хотелось видеть для Rust в 2021 году. Всё ключевые моменты выделять не буду (а иначе зачем я вам ссылку даю?), выделю только то, что привлекло моё внимание:
* I want to see Rust shed some of its reputation for being hard to learn
Согласно автору, новички сталкиваются с повышенной нагрузкой при изучении языка, поскольку им приходится учить и сам язык, и то, как писать на нём идиоматичный код. Учить Rust сложно ввиду того, что он схож с мейнстримными ЯП, но при этом довольно сильно от них отличается — достаточно, чтобы предыдущий опыт был не слишком полезен. Одним из следствий этих отличий является то, что лучшие практики из одних языков считаются антипаттернами в Rust (pub/sub, observer pattern), равно как и наоборот (затенение переменных). Автор считает, что новичкам имеет смысл позволить себе писать сначала неаккуратный и/или неидиоматичный код, а улучшать его уже потом. Да, это вопрос чисто психологический, но в интернете чаще выкладывают хороший код и редко — скажем так, не очень хороший, что создаёт определённое психологическое давление. Именно это и пишет автор:
I am not exactly sure how to create the conditions for this outcome. Maybe more people can publish more Rust that looks messy but “just works”.
Собственно, как совершенно справедливо заметил trentj на URLO (что в итоге стало фразой недели в TWiR №360):
"Just because Rust allows you to write super cool non-allocating zero-copy algorithms safely, doesn’t mean every algorithm you write should be super cool, zero-copy and non-allocating."
* More blog posts from developers and management using Rust at work
Особенно автору хочется видеть материалы с информацией о том, почему был выбран именно Rust, и о том, каков был опыт по сравнению с предыдущей реализацией — как правило, написанной на другом языке.
It’s great to hear Rust used in complicated, low-level development, but it would be normalizing to read about more trivial types of applications, just as a way to highlight Rust as being good for general purpose use.
Я со своей стороны могу лишь добавить, что по мере возможности стараюсь закрывать этот пробел в русскоязычном сообществе Telegram. Некоторые из подобных постов на моём канале можно найти по хештегу #successstory.
* More shared experiences from people picking up Rust as a second language.
Во многом перекликается с первым тезисом. Согласно автору, это может поспособствовать двум вещам: показать, что для того, чтобы выучить Rust, не нужно быть каким-то выдающимся человеком, и раскрыть глаза на вещи, которые опытные Rust-разработчики не замечают или воспринимают как должное.
I believe content from this crowd would be my favorites to read since I think they’ll give valid opinions to someone who has been using Rust for years (like me) now overlook or accept without second thoughts.
DEV Community
Rust in 2021
I missed the official call for blog post submissions, I still want to share some ramblings of my hope...
#prog #rust #article
Тем временем народ настолько звереет от нехватки анонимных сумм-типов в Rust (а RFC для них было немало — Вафель не даст соврать), что пишет свои. В этот раз получилось даже неплохо.
Тем временем народ настолько звереет от нехватки анонимных сумм-типов в Rust (а RFC для них было немало — Вафель не даст соврать), что пишет свои. В этот раз получилось даже неплохо.
jam1garner
Anonymous Sum Types for Rust Error Handling
Blog post from 18 November 2020
#prog #go #article
Статья о внутреннем устройстве
Ключевая фишка реализации — фактически нетипизированная реализация мапы как таковой, отвечающая структуре hmap. Поле
Не знаю, как вам, а мне эта картина кажется весьма шаткой, особенно с учётом комментариев вроде "сохраняйте это определение структуры согласованным с вот этим местом в реализации рефлексии и той части компилятора, которая обходит AST". Ну и дублирование кода между
Статья о внутреннем устройстве
map
в Go. К сожалению, в статье длиннющая преамбула о различных вариантах реализации хэш-таблиц в разных языках и крайне мало о собственно реализации в Go.Ключевая фишка реализации — фактически нетипизированная реализация мапы как таковой, отвечающая структуре hmap. Поле
buckets
имеет тип unsafe.Pointer
, который является аналогом void*
из C: может указывать на что угодно. В контексте Go примечателен ещё и тем, что, в отличие от встроенных указателей, он не отслеживается сборщиком мусора. Все мало-мальски интересные функции, манипулирующие map
, принимают также указатель на значение типа maptype. В нем описаны характеристики хэш-таблицы — такие, как размер ключей, значений, бакетов, хранятся ли они значения по месту или же хранятся лишь указатели на них, а также функция для хэширования ключей и (через поле тип type_) функции для сравнения значений ключей и значений. Откуда берутся значения для maptype
? А их генерирует компилятор автоматически, когда переписывает обращения к map
через функции типа mapaccess1/mapaccess2. На этапе же компиляции он может проверить, что для типа ключа map
определены операции хэширования и сравнения.Не знаю, как вам, а мне эта картина кажется весьма шаткой, особенно с учётом комментариев вроде "сохраняйте это определение структуры согласованным с вот этим местом в реализации рефлексии и той части компилятора, которая обходит AST". Ну и дублирование кода между
mapaccess1
/mapaccess2
не может не радовать.GitHub
go/src/runtime/map.go at 8d3458517199f5aa2be0ec0f316fd406c9ca6cbb · golang/go
The Go programming language. Contribute to golang/go development by creating an account on GitHub.
Forwarded from Generative Anton (Anton Repushko)
Если быстро выдернуть чеку у гранаты и поднести ухо к дыре, где была чека, можно услышать, как увеличивается средний мировой IQ.
#prog #cpp
Длиннющий тред с примерами undefined behavior в C++. По состоянию на этот день в нём 98 записей
Длиннющий тред с примерами undefined behavior в C++. По состоянию на этот день в нём 98 записей
Twitter
Dmitry /Undefined Behavior/ Sviridkin
@vzverovich 98. Начиная с C++11, все временные значения живут до ; (end of statement). Начиная с него же появился удобный range based for. Но вот незадача: он раскрывается не в один statement, а в несколько. И временные значения в заголовке цикла могут не…
В разработке пост с рабочим названием "как быть, если тебе нужно написать простенький парсер, но nom выглядит перебором"
Forwarded from crates.io updates (crates.io update notifier bot)
Forwarded from мне не нравится реальность (вафель 🧇🍓)
А я тут маленький крейтик релизнул 👀
Он добавляет методы Option::{err_or,err_or_else} аналогичные к Option::{ok_or,ok_or_else}
Он добавляет методы Option::{err_or,err_or_else} аналогичные к Option::{ok_or,ok_or_else}
Forwarded from Санечка Ъысь (ǺʎĔĶ₡Ǻ)
Когда у меня спрашивают, почему я не люблю одинэсников. Хотя бы, блять, за это.
Из рабочей переписки. В общем, базу товаров синхронизируем в 1С и мускуле.
Из рабочей переписки. В общем, базу товаров синхронизируем в 1С и мускуле.
Санечка Ъысь
Когда у меня спрашивают, почему я не люблю одинэсников. Хотя бы, блять, за это. Из рабочей переписки. В общем, базу товаров синхронизируем в 1С и мускуле.
"1C — врождённое генетическое заболевание. Когда-нибудь генная инженерия позволит исправлять такие промахи при планировании беременности"
#quotes от подписчика, попросившего его (или её?) не называть
#quotes от подписчика, попросившего его (или её?) не называть
#prog
Нафиг эти ваши "задачки на сообразительность". (Или о том, как бы Фейнман проходил бы собеседование в IT-компанию в то время, когда все спрашивали, почему люки круглые)
Нафиг эти ваши "задачки на сообразительность". (Или о том, как бы Фейнман проходил бы собеседование в IT-компанию в то время, когда все спрашивали, почему люки круглые)
www.dotnetblog.ru
"Задачки на сообразительность" на интервью - .NetBlog - блог о программировании на C# .Net, и других, не мене интересных вещах.
Программист Евгений Михайлов, Блог о программировании, шаблоны проектирования, .Net programming blog, c# developer, разработка приложений, .Net tips and tricks, программирование на .Net, язык программирования C#, что почитать про Sharepoint, Sharepoint для…
#prog #video
Доклад Юрия Богомолова о том, как применили схемы рекурсии (recursive schemes) применительно к реальной задаче. Неплохой пример практичности ФП (пусть и на немножко хреновом ЯП TypeScript).
Могу со своей стороны добавить, что введение, на мой взгляд вышло чересчур сжатым, так что если вы раньше не знали, что такое схемы рекурсии, то не факт, что понимания добавится именно после просмотра этого доклада
Доклад Юрия Богомолова о том, как применили схемы рекурсии (recursive schemes) применительно к реальной задаче. Неплохой пример практичности ФП (пусть и на немножко хреновом ЯП TypeScript).
Могу со своей стороны добавить, что введение, на мой взгляд вышло чересчур сжатым, так что если вы раньше не знали, что такое схемы рекурсии, то не факт, что понимания добавится именно после просмотра этого доклада
YouTube
MoscowJS 46 — Схемы рекурсии, или как мы решали задачу управления фронтом с бэка — Юрий Богомолов
В своём докладе я расскажу о том, как я и моя команда подходили к решению задачи, поставленной заказчиком — отображению динамических данных с непредсказуемыми взаимосвязями компонентов, получаемых с бэкенда. Для решения этой задачи были применены так называемые…