Initialize a custom struct reference inside vec![]?

Hello there, sorry for the newbie question I'm very new to rust but I have made two structs Neuron and GeneticNetwork the idea is that GeneticNetwork contains fields that are type Vec<&Neuron>

this is the code I have so far:
genetic_network.rs

pub struct GeneticNetwork<'a> {
    /// a vector containing all input neurons to be used within the network
    pub input_neurons: Vec<&'a Neuron<'a>>,
    /// a vector containing all internal neurons to be used within the network
    pub internal_neurons: Vec<&'a Neuron<'a>>,
    /// a vector containing all output neurons to be used within the network
    pub output_neurons: Vec<&'a Neuron<'a>>
}

impl<'a> GeneticNetwork<'a> {
    pub fn new(input_neurons: Vec<&'a Neuron<'a>>, internal_neurons: Vec<&'a Neuron<'a>>, output_neurons: Vec<&'a Neuron<'a>>) -> GeneticNetwork<'a> {

        GeneticNetwork { 
            input_neurons: input_neurons, 
            internal_neurons: internal_neurons, 
            output_neurons: output_neurons 
        }

    }
}

main.rs

fn main() {
    let in_n1: &Neuron = &Neuron::new(0.3, NeuronType::Input);
    let in_n2: &Neuron = &Neuron::new(0.6, NeuronType::Input);

    let int_n1: &Neuron = &Neuron::default();
    let int_n2: &Neuron = &Neuron::default();

    let o_n1: &Neuron = &Neuron { neuron_type: NeuronType::Output, ..Default::default() };
    let o_n2: &Neuron = &Neuron { neuron_type: NeuronType::Output, ..Default::default() };

    let input_neurons: Vec<&Neuron> = vec![in_n1, in_n2];
    let internal_neurons: Vec<&Neuron> = vec![int_n1, int_n2];
    let output_neurons: Vec<&Neuron> = vec![o_n1, o_n2];

    let network: GeneticNetwork = GeneticNetwork::new(
        input_neurons,
        internal_neurons,
        output_neurons
    );
}

the issue I'm having is the way I'm initializing the vectors, I initialize the neurons first then add them into a vector, this is the only way I could get it working, I wish to do something like this instead:

let input_neurons: Vec<&Neuron> = vec![&Neuron::default(), &Neuron::default()];

but this results in this error:

temporary value dropped while borrowed
consider using a `let` binding to create a longer lived value

sorry if anything is not clear, thanks in advance:)

You must store the Neurons somewhere, e.g. something like:

let input_neuron_storage = vec![Neuron::default(), Neuron::default()];
let input_neurons: Vec<&Neuron> = input_neuron_storage.iter().collect();

or:

let neuron1 = Neuron::default();
let neuron2 = Neuron::default();
let input_neurons = vec![&neuron1, &neuron2];

But I'm not sure if the approach to store references to Neurons in the Vec is the best.

2 Likes

You can't use & to store data "by reference". Rust references mean something else - they mean the type is not owned, and must have already been stored elsewhere.

& in structs means the struct does not contain this data, so your GeneticNetwork means there's some other data source elsewhere that stores Neurons, and GeneticNetwork has none.

The correct type to store data "by reference" is Box or Arc, but not &. Do not put references in structs.

2 Likes

Also, if you are doing things like this where you are immediately borrowing something from a function call, I typically refer to this as an anti-pattern. Instead, assign the variable to the value itself, not a borrow of a temporary value:

let in_n1: Neuron = Neuron::new(0.3, NeuronType::Input);

If you need &Neuron later, you can borrow the variable as &in_n1. Now you know exactly what the lifetime of borrow is, and who owns the data.

1 Like

One of the more traditional approaches for handling interior references like this is using indexes into a vector so you can share them and change references without having ambiguous identity or ownership.

Rc or Arc is fine too, to be clear, but you can't mutate though them without additional complexity.

If you don't need to share, just store the value directly without a reference, just to be clear!