Denis (cc'ing rust-dev)-

> How does it then interpret the line:
>      let it =  self.items[0];
> The only way to make sense of that is to copy, isn't it? What else?

An assignment expression can denote either a copy or a *move* of the 
right-hand-side into the left-hand-side. 

Note that your goal ("returning an item from a collection") is unclear, in that 
I cannot tell whether you want to move item out of the collection, or make a 
copy of it, or provide a shared reference to the item in the collection (but 
without removing it from the collection).

Anyway, the error message says "cannot move out of dereference of & pointer"

In this case, the assignment expression is being interpreted as an attempt to 
move content out of self.items[0].  But you cannot move the item out of the 
l-value denoted 
by that expression, for a couple different reasons (such as: `&self` is an 
immutable borrow, so you cannot modify it;  and also, even if you changed the 
borrow to be a mutable borrow, you still could not use the expression you want 
to extract the first item, since the vector needs something to replace the 
content that was removed).

Maybe you are more used to languages like Java/Scheme/ML/Haskell/etc, where a 
parameter or local variable denotes a *reference* to the value in question, and 
thus can be freely copied?  To get that effect in Rust, and thus allow multiple 
references to some shared piece of state, you need to use some explicit 
pointer/reference type.

Here is some code to illustrate what I'm saying.  Note that you should probably 
favor a data-structure representation where you can call the vec `pop()` method 
rather than `shift()`; compare the source code for each in vec.rs to see why.

```rust
struct Coll<Item> {
     items : ~[Item]
}

impl<Item> Coll<Item> {
     // *Moves* the first element out of self.
     // (Doing so requires that we mutably-borrow self.)
     fn first (&mut self) -> Item {
         //     ^^^ this is new

         let it =  self.items.shift();
         //                   ^^^^^ so is this
         return it;
     }

     // Provides reference to first element of self.
     fn first_ref<'a> (&'a self) -> &'a Item {
         // Note: The lifetime 'a tells us that the reference will
         // survive only as long as the immutable-borrow of self.
         let it =  &'a self.items[0];
         return it;
     }
}

fn main () {
     let mut coll = Coll{items:~[1,2,3]};
     //  ^^^ this is also new.

     {
        // This {} block acts effectively as the lifetime 'a for the
        // call to first_ref.

        // First lets take a reference, `fref`, into coll...
        let fref = coll.first_ref();
        println!("first ref : {:?}", fref);
        println!("coll : {:?}", coll);
        // ... which will only live until here...
     }

     // ... which is important, because we need to *mutably*
     // borrow `coll` in order to invoke `first()` here.
     println!("first : {:?}", coll.first());
     println!("coll : {:?}", coll);
}

```

Cheers,
-Felix

----- Original Message -----
From: "spir" <[email protected]>
To: "Rust-dev" <[email protected]>
Sent: Monday, November 11, 2013 1:44:04 PM
Subject: [rust-dev] returning an item from a collection

Hello,

I am searching for the easy or standard way to return an item from a 
collection. 
Here is a fictional example showing the issue:

struct Coll<Item> {
     items : ~[Item]
}

impl<Item> Coll<Item> {
     fn first (&self) -> Item {
         // this line is for comments below:
         let it =  self.items[0];            // error
         return it;
     }
}

fn main () {
     let coll = Coll{items:~[1,2,3]};
     println!("first : {:?}", coll.first());
}

==>
_.rs:12:18: 12:30 error: cannot move out of dereference of & pointer
_.rs:12         let it =  self.items[0];

I could not find any clue in docs. Have tried several approaches, finally 
succeeded with the following:

impl<Item:Clone> Coll<Item> {
     fn first (&self) -> Item {
         let it =  self.items[0].clone();
         return it;
     }
}

I find that surprising. A few questions:
* What does the error *mean* ?
* Is this solution the right way?
* What alternatives exist, if any?
* What is the difference between copy and clone?
* Why does clone work and not simple copy?

About the latter 2 questions, well, for me,
     y = x
just copies x into y [1]; and clone is just a synonym of copy. Where am I 
wrong? 
That we copy should remove any pointer safety question, shouldn't it? (This 
consideration was my lead to find a solution.) Again, where am I wrong?

The doc of the module 'clone' reads:
<< The Clone trait for types that cannot be "implicitly copied"

In Rust, some simple types are "implicitly copyable" and when you assign them 
or 
pass them as arguments, the receiver will get a copy, leaving the original 
value 
in place. These types do not require allocation to copy and do not have 
finalizers (i.e. they do not contain owned boxes or implement Drop), so the 
compiler considers them cheap and safe to copy. For other types copies must be 
made explicitly, by convention implementing the Clone trait and calling the 
clone method. >>

This is all good and makes sense for me. But then, in the first code example 
above, the compiler does not know anything about the "copy-ability" of Val 
specimens. How does it then interpret the line:
     let it =  self.items[0];
The only way to make sense of that is to copy, isn't it? What else? Then, the 
language should require Val to declare the trait Clone, shouldn't it? And there 
should not be a need for an explicit copy via the clone method in my view... 
Again, what other sense but copying does the compiler assign to a simple 
assignment "y=x" ?

Finally, is it so that for generic collections, item types must always be 
declared the Clone trait, else we just cannot read them? Same for generic 
struct 
fields? (If I add a field of type Item in Coll, I also cannot read it out 
without error.)

Denis

[1] shallow copy: the pointer, if x is a pointer, the "façade" struct is x is 
such an thing, etc...


_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to