Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are you able to create partially initialised structs?

Tags:

rust

When creating a struct in Rust it seems like it's difficult to create one without having all of the fields set. For example with the following code

struct Connection {
    url: String,
    stream: TcpStream
}

You aren't able to set url without giving stream as well.

// Compilation error asking for 'stream'
let m = Connection { url: "www.google.com".to_string() }; 

How are you able to create these references that might be Option<None> until a later time?

The best I have found is using the Default trait, but I'd rather not have to create the TcpStream until a later time than when the struct is initialised. Am I able to do this with something like a Box?

like image 447
Paul Thompson Avatar asked May 22 '15 05:05

Paul Thompson


People also ask

Is it possible to partially initialize structure variable?

Hence in case of partially initialized structure, uninitialized member variable of numerical type (char, int, long, float, double) will be initialized to 0, and pointers will be initialized to NULL. Lets take one more case where in class is to be initialized with 8 and name and age is unknown.

How are structs initialized?

When initializing a struct, the first initializer in the list initializes the first declared member (unless a designator is specified) (since C99), and all subsequent initializers without designators (since C99)initialize the struct members declared after the one initialized by the previous expression.

How are structs initialized in C?

Structure members can be initialized using curly braces '{}'. For example, following is a valid initialization.

How do you initialize a struct in Swift?

An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }


Video Answer


2 Answers

One thing you can do is to wrap the TcpStream in an Option, i.e. Option<TcpStream>. When you first construct the struct, it'll be None, and when you initialize it you make it self.stream = Some(<initialize tcp stream>). Wherever you use the TCPStream, you'll have to check if it's Some, i.e. if it has already been initialized. If you can guarantee your behavior then you can just unwrap(), but it's probably better to make a check anyways.

struct Connection {
    url: String,
    stream: Option<TcpStream>
}

impl Connection {
    pub fn new() -> Connection {
        Connection {
            url: "www.google.com".to_string(),
            stream: None,
        }
    }

    pub fn initialize_stream(&mut self) {
        self.stream = Some(TcpStream::connect("127.0.0.1:34254").unwrap());
    }

    pub fn method_that_uses_stream(&self) {
        if let Some(ref stream) = self.stream {
            // can use the stream here
        } else {
            println!("the stream hasn't been initialized yet");
        }
    }
}

This is similar to what is done in Swift, in case you're familiar with that language.

like image 134
Jorge Israel Peña Avatar answered Sep 30 '22 03:09

Jorge Israel Peña


All fields indeed have to be initialized when creating the struct instance (there is no null in Rust) so all the memory is allocated. There is often a dedicated method (like new) that sets default values for fields which are supposed to be modified at a later stage.

I'd use the Box when you don't know the size of the field (like Vec does).

like image 36
tafia Avatar answered Sep 30 '22 04:09

tafia