Комментарии 17
"Если требуется более полный контроль над программой, это можно организовать"
Хочу передать указатель в два потока. Хочу двусвязный список. Этот гений расскажет как это сделать?
двусвязный список в стандарте: https://doc.rust-lang.org/std/collections/struct.LinkedList.html
указатель в два потока: Arc + Mutex или RwLock и тд
Справедливости ради, боюсь, что вопрос был о том, как сделать красивый, идиоматически верный двусвязный список. Конечно же он уже реализован в std (сплошной unsafe, btw), конечно писать велосипед смысла нет. Но, если, вдруг, возникнет необходимость создать подобную структуру данных, как сделать её красиво? Не обмазываясь счетчиками ссылок и unsafe.
И если что - я раст не хейчу и даже активно использую.
Здесь хорошо написано :)
https://rust-unofficial.github.io/too-many-lists/index.html
Ну, такое себе. Реализация через счетчики ссылок, ожидаемо, Bad, а Production вариант - unsafe через unsafe, с информативными комментариями // SAFETY: it's a linked-list, what do you want?
. А вариант с full safe ареной даже не упомянут...
если, вдруг, возникнет необходимость создать подобную структуру данных, как сделать её красиво?
А почему вы уверены что это вообще возможно? Может структура байдизайн фиговая.
.Боюсь, именно задача реализации структур данных, (точнее, оптимальная и производительная их реализация) – это то, что сейчас не написать без unsafe. Но прошу заметить, что unsafe вовсе не означает небезопасный код. unsafe означает, что компилятор (пока) не может проверить и гарантировать безопасность этих участков кода, поэтому за их безопасность отвечает программист. Т.е. во всем остальном коде он может гарантировать отсутствие undefined behavior, а тут нет, тут это должен гарантировать программист. Поэтому и комментарии SAFETY оставляют. В таких местах использование unsafe – это нормально. Места, которые не может проверить компилятор, сразу привлекают к себе внимание, и уж unsafe секциям вы наверняка будете уделять больше внимания. Эти места обычно обкладываются тестами + используется miri (последнее важно). Miri очень часто может находить ошибки и undefined behavior в unsafe секциях, похоже на сишный статический анализатор
В целом согласен, посто предложенный вами туториал довольно странный. В нем показано, как делать не надо и как можно сделать через через сырые указатели. Я не против unsafe в расте. Но в, условно, в каждую графоподобную структуру пихать unsafe, гхм, экспириенс на 3/10. Те же, забытые в гайде, арены позволяют писать структуры с приемлемой производительностью и не прибегая к unsafe.
И про SAFETY-комментарии. Я обротил внимание только из-за их бессмысленности, в конкретном гайде. Повторяющийся "it's a linked-list, what do you want?" несет смысловой нагрузки едва ли больше, чем начало unsafe блока. Хорошие SAFETY-комментарии, все же, описывают почему и как мы гарантируем безопасность операции.
примеры //SAFETY из std
// Safety: We know that `push_front` does not change the position in
// memory of other nodes. This ensures that `self.current` remains
// valid.
// SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc and leaked
// SAFETY: In a LinkedList, either both the head and tail are None because
// the list is empty, or both head and tail are Some because the list is populated.
// Since we have verified the head is Some, we are sure the tail is Some too.
Да, согласен. Конечно же, SAFETY-комментарии должны быть лучше, чем в том туториале. Про деревья: вы имеете ввиду нечто такое? https://docs.rs/indextree/latest/indextree/
P.S. Про арены раньше не слышал, спасибо за наводку. Пойду изучать
Признаться, не совсем уловил суть вопроса. В комментарии ниже я упомянул абстрактную, графоподобную структуру. indextree, по сути, подходит под определение и даже построено на базе арены. В принципе, я, вероятно, дерево/граф подобным образом и написал бы. Только не на сыром Vec, а на том же Slab
PS Вообще, в дискуссию я ввязался, исключительно в надежде, что меня ткнут носом в красивую реализацию без rc, unsafe и арен. Но, видимо, пока что не судьба :D
Справедливости ради, боюсь, что вопрос был о том, как сделать красивый, идиоматически верный двусвязный список.
Сколько раз после университета вам приходилось для рабочих задач реализовывать двухсвязный список? А сколько раз использовать готовый?
Я просто на 4 языках писал в разное время и 0 раз его использовал. Навскидку не могу придумать ни одной продуктовой задачи, где он был бы эффективнее вектора.
Сколько раз после университета вам приходилось для рабочих задач реализовывать двухсвязный список? А сколько раз использовать готовый?
конечно писать велосипед смысла нет. Но, если, вдруг, возникнет необходимость создать подобную структуру данных, как сделать её красиво?
Ну, ей-богу. Где хваленое, программерское, абстрактное мышление? Двусвязный список это примитивный пример структуры данных, элементы которой имеют двунаправленные связи. Если возникают проблемы с реализацией подобного примитива, как нам дерево или любую графоподобную структуру изобразить? Никто, надеюсь, в здравом уме не станет в прод самопальный LinkedList тащить… Правда ведь?
Двухсвязный список очень специфическая структура данных, применяется ИМХО ровно в 2 областях: RTOS и кастомные аллокаторы. Причем глубоко внутри, во внешнем API его нет. Во всех остальных случаях достаточно вектора и однонаправленной очереди.
От дерева же никто не ждет идеальную производительность, и вполне допустимо сделать его на счетчиках ссылок без unsafe вообще.
Фишки Rust, связанные не только с производительностью