LINUX.ORG.RU

rust, сменить владельца Box указателя

 ,


1

6

Скажите, можно ли в расте поменять владельца Box указателя? Например я описываю простой стек двумя структурами:

enum Node<A> {
  Cons(A, Box<Node<A>>),
  Nil
}

struct stack {
  head : Box<Node<A>>,
  size : uint
}
и хочу сделать метод push
impl<A> Stack<A> {
  fn push(&mut self, data : A) {
    self.size += 1;
    self.head = box Cons(data, self.head)
  }
}
Но в таком случае компилятор ругается
cannot move out of dereference of `&mut`-pointer
Как поступить если я хочу переместить, а не скопировать значение?

★★★★★

Если бы ты давал куски кода, компилирующиеся в playpen, у тебя было бы больше шансов получить ответ.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Если бы у меня был компилирующийся код по моему вопросу, я бы вопрос не задавал. Я некомпилирующийся код привел, только что бы показать, что, собственно, хочу сделать.

Aswed ★★★★★
() автор топика
Ответ на: комментарий от Aswed

Если бы у меня был компилирующийся код по моему вопросу, я бы вопрос не задавал.

Твой код при компиляции в playpen выдает совсем не ту ошибку, на которую ты жалуешься.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

прошу прощения за дезинформацию

enum Node<A> {
  Cons(A, Box<Node<A>>),
  Nil
}

struct Stack<A> {
  head : Box<Node<A>>,
  size : uint
}

impl<A> Stack<A> {
  fn push(&mut self, data : A) {
    self.size += 1;
    self.head = box Cons(data, self.head)
  }
}

Aswed ★★★★★
() автор топика

Насколько я понимаю, ты уперся в принципиальное ограничение - Box<Whatever> нельзя копировать. Но стандартного трюка для обхода этого я не помню :/

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Так ему не совсем копировать надо, а просто свапнуть. Для этого реплейс и придуман.

Правда в данном случае, получается коряво. Вот если бы у бокса можно было явно «забрать владение»...

DarkEld3r ★★★★★
()
Последнее исправление: DarkEld3r (всего исправлений: 1)
Ответ на: комментарий от DarkEld3r

Если у него по-нормальному нельзя забрать владание, то в каких вообще случаях Box лучше чем Rc?

Aswed ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Я знаю, что нельзя копировать. Я думал, что раст позволяет сделать перемещения, привязывая время жизни бокса к другому объекту, не делая дубликат содержимого бокса.

Aswed ★★★★★
() автор топика
Ответ на: комментарий от Aswed

то в каких вообще случаях Box лучше чем Rc?

Очевидно, в тех, когда не требуется подсчёт ссылок.

Если у него по-нормальному нельзя забрать владание

Я так понимаю, что «в обычных условиях», забрать легко. В данном случае, не работает из-за того, что мы работаем с полем мутабельной структуры. Мне тоже кажется, что должен быть более прямой способ, чем вот такой реплейс. Возможно, кто-то, кто знает раст лучше сможет подсказать.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

прикольно, а как сделать, чтобы кровь из глаз перестала течь?

1. «Закаляться» путём написания сложных шаблонов на С++.

2. Донести проблему до разработчиков.

3. Надеяться, что до «релиза» исправят (весьма вероятно).

Выбирай, на свой вкус.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Aswed

Я думал, что раст позволяет сделать перемещения, привязывая время жизни бокса к другому объекту, не делая дубликат содержимого бокса.

Тогда ты сможешь запилить два объекта, которые владеют друг другом, а это нехорошо.

O02eg ★★★★★
()
Ответ на: комментарий от O02eg

Тогда ты сможешь запилить два объекта, которые владеют друг другом, а это нехорошо.

Каким образом? Присваивание передаёт владение и всё работает:

fn main() {
    let mut a = box 5i;
    println!("{}", a);
    
    let b = a;
    //println!("{}", a);
    println!("{}", b);
    
    a = b;
    println!("{}", a);
    //println!("{}", b);
}
Если принты раскомментировать, то не скомпилится так как компилятор за этим следит. Тут ведь бред из-за структуры происходит.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Я конечно совсем-совсем нубяра в Rust, но вроде как по дефолту все должно быть иммутабельным. Мутабельное стоит делать редко, и если сильно припичет. А когда припечет, нужно юзать unsafe, а не всякие ахутнг, типа как ты продемонстировал. Не?

dizza ★★★★★
()
Ответ на: комментарий от dizza

Я конечно совсем-совсем нубяра в Rust, но вроде как по дефолту все должно быть иммутабельным.

Имхо, «должно» оно быть как удобно. Хотя конечно, иммутабельность по дефолту - это хорошо. Но в данном случае, это ничего не меняет. Из иммутабельной переменной всё равно можно забрать владение, но обратно (естественно) уже не присвоишь. Это не отменяет того факта, что цикличные ссылки так сделать невозможно (без трюков с ансейф).

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

isocpp.org снова в строю.

так что не просто говно, но говно с удобным сайтиком.

qulinxao ★★☆
()
Ответ на: комментарий от anonymous

Ну вот как выйдет, тогда и будем судить. В конце концов, то, что доступно сейчас можно назвать бета тестом. Кроме того, на мой взгляд, с указателями тут уже удобнее работать чем в плюсах. Этот пример со стеком, который я хотел сделать на боксах можно запросто переписать на Rc. То, что здесь можно по своему желанию выбирать стек или кучу как в С/С++, и при этом не боятся висячих и нулевых указателей перекрывает многие его недостатки по сравнению с С/С++.

Aswed ★★★★★
() автор топика
Ответ на: комментарий от buddhist

Кажется, образуется секта похлеще лисперов и хаскелистов вместе взятых.

We are the Borg of Rust. Resistence is futile. Prepare to be assimilated.

tailgunner ★★★★★
()
Ответ на: комментарий от Aswed

В смысле? В плюсах-то чем хуже? Смартпоинтеров разных много, свой можно сделать, если есть необходимость.

anonymous
()
Ответ на: комментарий от Aswed

У плюсов, например. Большая часть пользователей воспринимает его просто как инструмент. Может и есть «сектанты», но мне кажется, что среди пользователей C++ больше хейтеров, чем сектантов. В Java/C# примерно такая же ситуация.

anonymous
()
Ответ на: комментарий от anonymous

В смысле? В плюсах-то чем хуже?

Плюсы позволяют не выстрелить себе в ногу. Раст мешает выстрелить себе в ногу. На нем сложнее случайно или специально написать говнокод. Конечно, написать говнокод можно на любом языке, но некоторые мешают это делать, запрещая те или иные грязные хаки и небезопасные действия. Писать на таких вещах сложнее, зато в разы проще отлаживать.

среди пользователей C++ больше хейтеров, чем сектантов

Конечно меньше, это же популярный язык. Непопулярные языки учат когда возникает острая необходимость или когда хочется странного. Меня, например, к расту толкает второе.

Aswed ★★★★★
() автор топика
Ответ на: комментарий от buddhist

Культ карго, ага. :)

А по каким критериям человека из категории просто интересующихся-увлекающихся каким-то языком переводят в категорию сектантов? Думаю, нужен какой-то зловещий обряд посвящения.

ozkriff
()
Ответ на: комментарий от ozkriff

В программировании, считай, что сразу можно переводить в категорию фанатиков-сектантов :)

buddhist ★★★★★
()
Ответ на: комментарий от ozkriff

критерий «некритичности к объекту обожания»

qulinxao ★★☆
()
Ответ на: комментарий от anonymous

А у какого языка нет своей «секты»?

У плюсов, например [...] В Java/C# примерно такая же ситуация.

«Секты» плюсов, Java и C# просто были активны слишком много лет назад, чтобы молодняк их помнил. Но они были.

tailgunner ★★★★★
()
Ответ на: комментарий от DarkEld3r

println!(«{}», a);

Вообще, довольно криво, что макрос println! принимает не ссылки, а сами переменные, хотя владение не забирает. Т.е. можно написать и println!("{}", a); и println!("{}", &a); - сейчас одинаково должно работать, вроде. Надеюсь, добавление & все-таки уберут из логики макроса. Где-то были обсуждения, но гугл меня подводит. Чертова забота о новичках, которые могут испугаться взятия ссылки.

ozkriff
()
Ответ на: комментарий от anonymous

У плюсов, например.

Это просто потому что язык довольно «мейнстримовый». В итоге хватает и людей которые осознанно выбрали инструмент и тех, кто «ненавидит язык, но вынужден пользоваться». Очевидно, у новых языков таких людей нет.

Тем не менее, «фанатиков» тоже хватает.

DarkEld3r ★★★★★
()
Ответ на: комментарий от ozkriff

Надеюсь, добавление & все-таки уберут из логики макроса.

А что это даст кроме дополнительной писанины? Ведь принтом ничего поломать нельзя.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

А что это даст...? Ведь принтом ничего поломать нельзя.

На одно исключение из правил меньше, язык станет немного более последовательным.

println! - макрос только потому, что ему надо во время компиляции проверять параметры. Я не вижу особого смысла в отличных от обычного вызова функций синтаксисе и семантике.

Хотя эта особенность, как мне помнится, оправдывалась именно тем, что новички ничего про ссылки не знают на определенном этапе, а печатать значения в примерах им как-то надо. Но потом эти же новички (видел и в irc и в /r/rust) остаются с вопросом «почему println! не забирает владение, хотя мы передаем не ссылку, а объекты?». Мне кажется, что оно того не стоит. Ржавчина в любом случае не Питон, что бы выглядеть псевдокодом и сразу быть полностью понятной.

Ну, кстати, это не единственная кривость. После println!(....) можно еще точку с запятой не ставить - все будет работать (http://is.gd/uR6JjO). Раскрывается, наверное, в {...}. Тоже не слишком-то красиво. В си и то макросы (не совсем для этого, но тем не менее) оборачивают в do{}while(0).

... кроме дополнительной писанины? ...

Всего по символу & на аргумент - я бы не называл это «писаниной». Все равно почти все параметры в функции так передаются.

ozkriff
()
Ответ на: комментарий от ozkriff

На одно исключение из правил меньше, язык станет немного более последовательным.

Не уверен, что этот аргумент актуален в данном случае. Всё-таки макросы могут «делать что угодно» - логично почитать документацию.

Плюс, мне кажется, что чаще нам всё-таки значение интереснее. А сокращение кода - тоже хорошо. Для этого (в том числе) макросы и нужны.

Но потом эти же новички (видел и в irc и в /r/rust) остаются с вопросом «почему println! не забирает владение, хотя мы передаем не ссылку, а объекты?».

Если мне не изменяет память, то в стартовом гайде этот момент упоминается.

Ну, кстати, это не единственная кривость. После println!(....) можно еще точку с запятой не ставить - все будет работать

Вот тут соглашусь - некрасиво.

DarkEld3r ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.