Есть два разных подхода к разработке фронтэнда: первый — это статически описывать разметку в шаблоне и добавлять вкрапления исполняемого кода; второй — это создавать фронтенд программно, а для упрощения кода по созданию отдельных элементов использовать вкрапления DSL-синтаксиса, описывающего структуру элементов. Вот как раз второй подход и используется в yew, как и в React/JSX.
pub struct S<'a> {
link: &'a i32 // иммутабельная ссылка
}
struct S2<'a> {
vec: Vec<S<'a>> // глобальный массив объектов, которые будут разделять владение переменной
}
impl<'a> S2<'a> {
fn create_vector(&mut self) {
self.vec = Vec::new(); // создаем массив
let x = 170239; // переменная, на которую будем ссылаться
for _ in 0..10 {
let s = S {
link: &x
};
self.vec.push(s);
}
}
fn change_vector(&mut self) {
let x = 239017; // другая переменная, некоторые ссылки из массива мы обновим на нее
for _ in 0..20 {
// обновляем случайный элемент
let ind = rand::random::<usize>() % 10;
let s = S {
link: &x
};
self.vec[ind] = s;
}
}
}
И как вы может убедиться сами, несовпадение времен жизни ссылок приведут к ошибкам компиляции:
error[E0597]: `x` does not live long enough
--> src/main.rs:17:24
|
17 | link: &x
| ^ borrowed value does not live long enough
...
21 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 11:1...
--> src/main.rs:11:1
|
11 | impl<'a> S2<'a> {
| ^^^^^^^^^^^^^^^
И? Переведете кодовую базу в режим сопровождения и начнете писать новый код на Rust?
Собственно, почему бы и нет? )
Но, конечно, чтобы такое провернуть нужны средства и время. И главное — уверенность в том, что этот переход будет действительно стратегически выгоден. А без этого разумно оставить все как есть. В лучшем случае остается только следить и ждать. Но и в этом случае можно прогадать, время может оказаться упущенным.
У меня возникала пару раз ситуация, когда однозначность `dyn Trait` избавила бы от необходимости уточнять, что именно имелось ввиду в коде. Но насколько оправдано использование дополнительного слова во всех случаях использования типажей-объектов — практика и время покажут.
Язык должен жить и развиваться :) Если в сотый раз новые люди наталкиваются на одни и те же проблемы с синтаксисом, и в сотый раз нужно одно и то же рассказывать им о нем — то вообще, это может свидетельствовать о недостаточной организованности и канализированности данной темы. А если она уже канализирована — то пусть в своем канале она и обсуждается, глядишь, со временем может что еще новенькое родится там. Это — нормально.
Это происходит потому, что impl Trait определяет анонимизированный тип. То есть он скрывает имя реально используемого типа, а не позволяет использовать множество разных типов в этом месте, как делают переменные типа <T: Trait> статически или Box<Trait> динамически. Вот пример:
fn foo<T: Clone>(a: &T) -> T {
a.clone()
}
fn bar(a: &impl Clone) -> impl Clone {
a.clone()
}
fn main() {
let a: f32 = foo(&2.5); // Ok
let b: i32 = foo(&5); // Ok
let c: i32 = bar(&5); // Error: expected i32, found anonymized type
}
В случае с функцией bar мы лишили результирующий тип имени и как бы урезали его до возможностей типажа Clone. Но не более: никакой возможности использовать разные типы в этом месте, как у foo, мы не получили.
А насчет [0..256), то это выглядит хорошо только для простейшего случая с константами. А если границы будут определяться сложнее? Разные виды скобок будут плохо восприниматься не только парсером, но и человеком. Более того, придется все время искать правую границу выражения, чтобы по скобке определить тип диапазона. Тогда как с синтаксисом ..= тип диапазона виден сразу.
Но соглашусь, что ..= тоже не идеален, особенно в паттернах if let:
if let 1..=5 = a {
// тело
}
Но пока это лучшее, до чего договорилось сообщество. Если у вас есть альтернативные идеи — то добро пожаловать на GitHub, вы всегда можете высказать свое предложение в соответствующем issue :)
Вообще-то абсолютное большинство населения в современном обществе работает по-найму и создает какие-то ценности в составе совокупного рабочего того или иного предприятия.
Возможно стоило такой обзор отдельным хабропостом сделать. )
Есть два разных подхода к разработке фронтэнда: первый — это статически описывать разметку в шаблоне и добавлять вкрапления исполняемого кода; второй — это создавать фронтенд программно, а для упрощения кода по созданию отдельных элементов использовать вкрапления DSL-синтаксиса, описывающего структуру элементов. Вот как раз второй подход и используется в yew, как и в React/JSX.
Поясните, а зачем нам template engine, если мы можем компонетны с кусками html определять прямо в коде?
Вот как будет выглядеть такой код на Rust:
https://play.rust-lang.org/?gist=dd87625906cb942982ab1b4388695f2d&version=stable&mode=debug&edition=2015
И как вы может убедиться сами, несовпадение времен жизни ссылок приведут к ошибкам компиляции:
Собственно, почему бы и нет? )
Но, конечно, чтобы такое провернуть нужны средства и время. И главное — уверенность в том, что этот переход будет действительно стратегически выгоден. А без этого разумно оставить все как есть. В лучшем случае остается только следить и ждать. Но и в этом случае можно прогадать, время может оказаться упущенным.
Вот дельное замечание. А позиция некоторых, дескать "автор сам дурак и нечего тут рассуждать" — неконструктивна.
Сейчас в Rust (с версии 1.26) можно записать так:
…vs..=for inclusive rangesОднако в позиции аргумента
impl Traitведет себя по-другому, а именно — как универсальный тип. Поэтому такой код корректен:Хотя результирующие типы для
dиeмы указать не можем.Это происходит потому, что
impl Traitопределяет анонимизированный тип. То есть он скрывает имя реально используемого типа, а не позволяет использовать множество разных типов в этом месте, как делают переменные типа<T: Trait>статически илиBox<Trait>динамически. Вот пример:https://play.rust-lang.org/?gist=c0adf6c27c0554d11e3f172cdce32bc7&version=stable&mode=debug
В случае с функцией
barмы лишили результирующий тип имени и как бы урезали его до возможностей типажаClone. Но не более: никакой возможности использовать разные типы в этом месте, как уfoo, мы не получили.В будущем
...в паттернах также заменят на..=. Сейчас уже работает эта конструкция как псевдоним: https://github.com/rust-lang/rust/issues/28237А насчет
[0..256), то это выглядит хорошо только для простейшего случая с константами. А если границы будут определяться сложнее? Разные виды скобок будут плохо восприниматься не только парсером, но и человеком. Более того, придется все время искать правую границу выражения, чтобы по скобке определить тип диапазона. Тогда как с синтаксисом..=тип диапазона виден сразу.Но соглашусь, что
..=тоже не идеален, особенно в паттернахif let:Но пока это лучшее, до чего договорилось сообщество. Если у вас есть альтернативные идеи — то добро пожаловать на GitHub, вы всегда можете высказать свое предложение в соответствующем issue :)
Вообще-то абсолютное большинство населения в современном обществе работает по-найму и создает какие-то ценности в составе совокупного рабочего того или иного предприятия.