Итоги года
Итак, очередной, 2020, год, подходит к концу (и слава б-гу!), а это значит, что пора окинуть взглядом прошлое и набросать планы на будущее. Без лишних слов представляю вам мысли, которыми бы хотелось поделиться с вами:
1. Итоги года переоценены.
Итак, очередной, 2020, год, подходит к концу (и слава б-гу!), а это значит, что пора окинуть взглядом прошлое и набросать планы на будущее. Без лишних слов представляю вам мысли, которыми бы хотелось поделиться с вами:
1. Итоги года переоценены.
Forwarded from ☕️ Мерлин заваривает τσάι 🐌
Любопытный, но довольно бесполезный пример полиморфизма в Go
В гошечке есть несколько способов писать полиморфные функции:
1. интерфейсы;
2. тайп свитчи и тайп кастинг интерфейсов;
3. рефлексия;
Недавно мне понял, что есть чётвёртый подход, который стал возможен с появлением type alias — назовём его апкастингом типов. Работает оно так:
К сожалению, это не слишком полезно — наверное только если вы не хотите делать пачку геттеров и у вас есть пачка одинаковых структур разных типов.
В гошечке есть несколько способов писать полиморфные функции:
1. интерфейсы;
2. тайп свитчи и тайп кастинг интерфейсов;
3. рефлексия;
Недавно мне понял, что есть чётвёртый подход, который стал возможен с появлением type alias — назовём его апкастингом типов. Работает оно так:
func main() {В спеке Go указано, что присваивание x типа V к переменной типа T валидно в случае, если V и T основаны на одинаковых типах и T — не именованный тип ("x's type V and T have identical underlying types and at least one of V or T is not a defined type."). Псевдонимы типов не считются именованными типами, так что мы можем принимать в аргумент n любую кастуемую структуру.
printName(Cat{"Whiskey"})
printName(Dog{"Chappie"})
}
type Cat struct { Name string }
type Dog struct { Name string }
type named = struct { Name string }
func printName(n named) {
fmt.Println(n.Name)
}
К сожалению, это не слишком полезно — наверное только если вы не хотите делать пачку геттеров и у вас есть пачка одинаковых структур разных типов.
#prog #rust
Мне недавно мой друг @ilyavenner подкинул такую задачу:
"
предотвратить неопределённое поведение при вызове функции
условия:
1. запрещено изменять тело функции;
2. исправленная версия функции не должна мешать остальному коду компилироваться (если она нигде не вызывается)"
Надо отметить, что из-за безусловного вызова unreachable_unchecked данную функцию в принципе нельзя вызвать, не вызывая неопределённого поведения, но это в данном случае роли не играет.
Мои первые попытки решить эту задачу были скорее читерскими: отклонить MR, добавляющий эту функцию (передаю привет своим коллегам) или просто обернуть функцию в
Для того, чтобы вызвать функцию, нужно сначала предоставить ей аргументы (это справедливо только для энергичного (call-by-value) языка, коим является Rust). А что, если тип аргумента ненаселён? В этом случае создать значение аргумента будет невозможно (нормальное, а не через днище), поэтому вызывать функцию будет нельзя:
Да,
Так что же, надежда совсем потеряна? Отнюдь. Илья показал решение, до которого я, к своему стыду, не додумался:
Мне недавно мой друг @ilyavenner подкинул такую задачу:
"
fn f() -> i32 {
unsafe { core::hint::unreachable_unchecked() }
}
задача:предотвратить неопределённое поведение при вызове функции
условия:
1. запрещено изменять тело функции;
2. исправленная версия функции не должна мешать остальному коду компилироваться (если она нигде не вызывается)"
Надо отметить, что из-за безусловного вызова unreachable_unchecked данную функцию в принципе нельзя вызвать, не вызывая неопределённого поведения, но это в данном случае роли не играет.
Мои первые попытки решить эту задачу были скорее читерскими: отклонить MR, добавляющий эту функцию (передаю привет своим коллегам) или просто обернуть функцию в
/* */
. В рабочем чате коллеги предлагали и аналогичные пути решения проблемы, вроде #[cfg(some_defintely_non_existent_feature_name)]
или #[cfg(all(x, not(x)))]
. Есть, однако и более тонкие пути разрешения проблемы.Для того, чтобы вызвать функцию, нужно сначала предоставить ей аргументы (это справедливо только для энергичного (call-by-value) языка, коим является Rust). А что, если тип аргумента ненаселён? В этом случае создать значение аргумента будет невозможно (нормальное, а не через днище), поэтому вызывать функцию будет нельзя:
fn f(_:
::core::convert::Infallible) -> i32 {
unsafe { core::hint::unreachable_unchecked() }
}
Однако, как показал Илья, эту красивую вещь можно обойти при помощи unsafe:unsafe { f(core::mem::transmute::<_, core::convert::Infallible>(())); }
Да,
transmute
проверяет, что оба типы — входной и возвращаемый — имеют один и тот же размер (из-за чего её в общем случае нельзя использовать в обобщенных контекстах), однако компилятор Rust считает, что ненаселённые типы имеют размер 0 байт — практическая полезная аппроксимация, но не совсем верная.Так что же, надежда совсем потеряна? Отнюдь. Илья показал решение, до которого я, к своему стыду, не додумался:
fn f<T: Copy + Drop>() -> i32 {
unsafe { core::hint::unreachable_unchecked() }
}
Дело в том, что ни один тип в Rust не может одновременно реализовывать Drop и Copy. Вызов этой функции потребует инстанцировать T
неким типом, а его нет и быть не может. Более того, использовать transmute
для обхода не получится, поскольку для этого нужно, опять-таки, конкретизировать тип f
, что невозможно сделать. Вот она, сила типов!doc.rust-lang.org
unreachable_unchecked in std::hint - Rust
Informs the compiler that the site which is calling this function is not reachable, possibly enabling further optimizations.
Forwarded from ozkriff.games 🦀 (Andrey @ozkriff Lesnikóv)
Когда твоя жена - ветеринар, то это не только много живности в доме, но и, внезапно, крабоугодные иконы от её коллег ветеринаров-художниц.
Я теперь, видимо, сертифицированный Rust-евангелист.
Клац-клац! 🦀
Я теперь, видимо, сертифицированный Rust-евангелист.
Клац-клац! 🦀
Редкие эпизоды из абсурдной жизни программиста.
"Две пиццы — это не про размер команды, а про размер фонда оплаты труда"
@topizza #blogrecommendation
"Две пиццы — это не про размер команды, а про размер фонда оплаты труда"
@topizza #blogrecommendation
Не ждите ни развёрнутых новогодних представлений — их вы и так уже услышали достаточно, чтобы они смешались в однородную массу счастьяздоровьябогаствавсегонаилучшего — ни итогов года, потому что, во-первых, они переоценены, а во-вторых, я уже суммировал всё, что мне было важно, на дне рождения Блог*а (https://t.iss.one/dereference_pointer_there/1405), и с тех пор ничего нового не прибавилось
Telegram
Блог*
Итак, сегодня 5 декабря. Чем примечателен этот день? Это — день, когда Блог* появился на свет.
Тогда мои амбиции были невелики: я считал, что этот блог будут читать только моя семья и ближайшие знакомые — полтора-два десятка человек максимум. Собственно…
Тогда мои амбиции были невелики: я считал, что этот блог будут читать только моя семья и ближайшие знакомые — полтора-два десятка человек максимум. Собственно…