Jim Hessin
Jim Hessin

Reputation: 156

How can I transfer ownership to a calling function?

I know there has to be a way to transfer ownership of a variable out of a function to its calling context. This is what I have so far:

fn get_transferables(creep: &Creep) -> &Vec<Structure> {
    let targets = creep.room().find(find::STRUCTURES);
    &targets
        .iter()
        .filter(|s| {
            use Structure::*;
            match s {
                Extension(s) => s.store_free_capacity(Some(ResourceType::Energy)) > 0,
                Spawn(s) => s.store_free_capacity(Some(ResourceType::Energy)) > 0,
                Tower(s) => s.store_free_capacity(Some(ResourceType::Energy)) > 0,
                _ => false,
            }
        })
        .collect::<Vec<&Structure>>()
        .iter()
        .map(|&element| Structure::from(*element))
        .collect()
}

I get "cannot move out of a shared reference" error when I try to dereference the element, and a "cannot return reference to temporary value".

If I comment out these lines:

// .collect::<Vec<&Structure>>()
// .iter()
// .map(|&element| Structure::from(*element))

I get "a value of type 'Vec' cannot be built from an iterator over elements of type '&Structure'".

When I try to have the function return a Vec<Structure> I get yet another error. I feel like I'm running in circles. I know with the ::new() constructor functions you just pass a struct immediately after you create it, but this is getting quite frustrating.

Upvotes: 0

Views: 641

Answers (1)

Jim Hessin
Jim Hessin

Reputation: 156

I had to break it into two separate functions and have my calling code pass references back and forth so there is a seamless chain of custody (like evidence at a crime scene). This is what I ended up with:

Inside my main function:

let structures = get_structures(&self);
let transferables = get_transferables(&structures);

My new functions:

fn get_structures(creep: &Creep) -> Vec<Structure> {
    creep.room().find(find::STRUCTURES)
}

fn get_transferables<'a>(targets: &'a Vec<Structure>) -> Vec<&'a Structure> {
    targets
        .iter()
        .filter(|s| {
            use Structure::*;
            match s {
                Extension(s) => s.store_free_capacity(Some(ResourceType::Energy)) > 0,
                Spawn(s) => s.store_free_capacity(Some(ResourceType::Energy)) > 0,
                Tower(s) => s.store_free_capacity(Some(ResourceType::Energy)) > 0,
                _ => false,
            }
        })
        // .collect::<Vec<&Structure>>()
        // .iter()
        // .map(|&element| Structure::from(*element))
        .collect()
}

I still think there should be a better solution.

Upvotes: 1

Related Questions