Filipp
Можно сделать Vec<T> Where T: Calc
Vadim Agishev
Не, не получится, т.к. нужно поведение (т.е. возможность вызвать calc функцию для любого элемента вектора), а не просто данные (struct - это просто данные)
Alexander
а всего просто хотел функцию для прохода по нескольким векторам написать, ну типа zip'а+map если руками бы.
Alexander
В общем похоже надо делать макрос, который из структуры будет генерить все для ее обработки: play и new даже. Я что-то такое видел, типа из hashmap автоматом структуру описанную делали как-то.
Alexander
Но это конечно не весело.
Filipp
Alexander
На примитивном уровне это выглядит проще простого: структура со ссылками. Ее можно было бы и для хранения векторов данных использовать и передавать в функцию с i-м элементом каждого из этих векторов.
Сергей
Alexander
я там izip! в Ind::new использовал, но это только часть - все равно в обработчик хочется структуру отдавать.
Vadim Agishev
Мономорфизировать то можно
это только для generic параметров прокатит. Например, когда компилятор точно знает, какие конкретные типы ты использовал в generic структурах, анализируя твой код и генерируя специализации для этих типов.
Для trait - это не работает, потому что размер объекта, реализующего трейт может быть разный. Например, struct ind1 имеет размер n байт, а struct ind2 имеет размер m байт, но они оба реализуют трейт Calc. Если бы в Vec можно было бы напрямую класть Calc, то мы смогли бы сначала засунуть в вектор n байт, а потом m байт. Что запрещено!
Alexander
это только для generic параметров прокатит. Например, когда компилятор точно знает, какие конкретные типы ты использовал в generic структурах, анализируя твой код и генерируя специализации для этих типов.
Для trait - это не работает, потому что размер объекта, реализующего трейт может быть разный. Например, struct ind1 имеет размер n байт, а struct ind2 имеет размер m байт, но они оба реализуют трейт Calc. Если бы в Vec можно было бы напрямую класть Calc, то мы смогли бы сначала засунуть в вектор n байт, а потом m байт. Что запрещено!
я вот только после этого текста понял почему расту это действительно не нравится. В том плане что в одном инстансе calc могут быть разные ind*
Alexander
Получается трейт тут вообще использовать нельзя, может как-то через генерик, но идей пока нет. Потому что возможность запихивать разные Ind в один calc и не нужна.
Vadim Agishev
Почему? Ведь удобно, что твоя функция будет работать не строго с f32, а с любыми другими типами, главное, чтобы они умели calc, что достигается путем реализации трейта Calc. Это хороший подход, когда мы абстрагируемся от данных и отталкиваемся от их поведения - т.е. что они могут и умеют делать. Можно ии String научить вычисляться, если calc функцию для нее напишешь
Filipp
Аа я думал генерик хотите сделать
Alexander
Может я запутался, это потенциально может и удобно, но мне совсем не надо. Вектор у меня будет только один тип содержать.
Alexander
Есть два вектора a:1 2 3 и b:10 20 30. Я хочу описать структуру {а:&f32 , b:&f32} и отдавать ее в calc { self.a + self.b} который делает например.
Alexander
Разные ind там никак не окажутся, так как это просто и zip и итератор по векторам по сути.
Vadim Agishev
Тогда можно перевернуть реализацию - не для каждого элемента вызывать функцию calc, а написать функцию, которая принимает два вектора Vec<T> и уже с ними производит вычисление, порождая новый вектор на выходе
Alexander
Я про это думал. Но вся логика только в функции calc, которой нужен только срез этих векторов.
Alexander
Иначе в calc надо будет реализовывать все эти итераторы и тд, что как раз хотелось вынести за пределы.
Alexander
И иметь просто много разных реализаций calc+ind, но при этом они не мешаются.
Vadim Agishev
Ты еще можешь функции передавать в другие функции. Например, написать функцию calc1, принимающую два среза и производящую вычисление 1, потом написать такую же функцию calc2, но производящую вычисление2. А потом, передавать куда-то либо calc1 либо calc2, в зависимости от того, какое вычисление ты хочешь получить
Victor
а зачем там трэйты если по условию только тип Ind есть?
Alexander
по сути это не особо нужно сейчас.
Alexander
Alexander
Но это да, не трейт, а параметры типа
Victor
ясно. но при этом в одном векторе лежат только одного типа значения?
Alexander
Да
Victor
ну тогда почему бы правда не сделать:
impl <T> CalcExt for Vec<T> where T: Calc {
fn play(&self) -> Vec<f32> {
self.iter().map(|x| x.calc()).collect()
}
}
или это уже разобрали почему не подходит? )
Alexander
Я попробую, как до компа доберусь, спасибо.
Alexander
Я признаться на вид не видел разницы между for Vec<Calc> и Vec<T> where T: Calc. Но в ходе этой переписки кажется начинаю понимать что это возможно разные вещи.
Filipp
Прочитай главу про trait object
Alexander
Одно делает трейт-обьект Calc, а другое уточная тип, тут правда хз когда он это сделает и присет ли Ind1 как один тип. Позже проверю.
Loo
Alexander
Всем спасибо, позже проверю и напишу.
Vadim Agishev
impl<T> CalcExt for Vec<T> {
fn play(&self) -> Vec<f32> {
self.iter().map(|x| x.calc()).collect()
}
}
fn main() {
// let calc1 = Ind::new(vec![1.1, 1.2]);
let calc1 = vec![Ind{a:1.1}, Ind{a:1.2}];
println!("{:?}", calc1.play());
}
Это, кстати, работает. Значит, все-таки Rust настолько умный, что и trait в качестве generic параметра умеет мономорфизировать)
После мономорфизации, эта конструкция
impl<T> CalcExt for Vec<T> {
fn play(&self) -> Vec<f32> {
self.iter().map(|x| x.calc()).collect()
}
}
превращается в
impl CalcExt for Vec<Ind> {
fn play(&self) -> Vec<f32> {
self.iter().map(|x| x.calc()).collect()
}
}Т.к. rust увидел, что в строке let calc1 = vec![Ind{a:1.1}, Ind{a:1.2}]; мы используем тип Ind в качестве элемента вектора, а т.к. экземпляры Ind имеют одинаковый размер, то здесь все ок.
պլհկ
В чем тут умность? даже вывод никакой не нужен. Передали Ind, надо проверить что он удовлетворяет условию
Loo
Неявность
https://habrahabr.ru/post/348282/
Рома
а есть какой-то чат, rust-beginner?
Рома
именно в телеге
Loo
Loo
в крайнем случае спросят читал ли ты книгу
Kerrigan
Рома
а второе издание в переводе есть? я могу понимать текст, но не отлично прям, некоторые моменты могу упускать
Tuntz
@pam3ess самое худшее - тыкнут пальцем в параграф книги
Nikita
Тут раст-то не обсуждают почти, какой агриться
Loo
Sergey
Sergey
Ну чисто для новичков
Sergey
@rust_beginners_ru
Safort
Safort
@rust_beginners_ru
Господи, ты какой-то новый проДот по количеству админства в чатах)
Sergey
Safort
Loo
Loo
в гиттере сделали 250 чатов
Loo
удобно стало
Loo
отвечаю
Loo
(нет)
Loo
Loo
Safort
по моему не единственная
Ну, ок, основная, на мой взгляд. Если мы говорим именно о сообществе, а не глючном интерфейсе самого гиттера, конечно)
Рома
вообще есть discord, оно разрабатывалась для геймеров в основном, но он был бы удобный и для прогеров, я думаю, я даже находил там каналы прогеров
Рома
возможностей больше чем в телеге
Victor
а какой смысл в отдельном чате для новичков? туда ведь всё равно нужно чтоб подписались те кто знают что-то. Иначе кто отвечать-то будет?
Loo
Рома
Loo
Victor