Optional struct in Swift3 - struct

I would like to declare a variable that stores an optional struct like so:
struct my_struct{
var x: Double
var y: Double
}
var my_variable = my_struct?
Am I right that this syntax was correct in Swift2? Unfortunately, it is not working in Swift3 anymore. What would be the "new" way to achieve this?

The syntax does not work in Swift 2 either.
First of all let's use a Swift compliant name
struct MyStruct { ... }
You have two options:
myVariable : MyStruct? declares an optional struct without a value (nil)
myVariable : MyStruct? = MyStruct() declares an optional empty struct.
Note: Consider that you have to assign default values for the properties of the struct in the second form or use the memberwise initializer or write a custom initializer.
PS: Don't use optionals as a don't-care alibi. Swift encourages you to use non-optional types a much as possible.

struct my_struct{
var x: Double
var y: Double
}
var my_variable:my_struct?
Note that types are usually capitalized and camel-cased by convention in Swift e.g.
struct MyStruct {
var x: Double
var y: Double
}
var myVariable: MyStruct?

Related

How can I make struct variables inaccessible to change from default value when using default initialization? [duplicate]

I'm getting an error when I have this sort of setup:
default_test.rs:
mod default_mod;
use default_mod::Point;
fn main() {
let _p1 = Point::new();
let _p2: Point = Point {
z: 1,
..Default::default()
};
}
default_mod.rs:
pub struct Point {
x: i32,
y: i32,
pub z: i32,
}
impl Point {
pub fn new() -> Self {
Point { x: 0, y: 0, z: 0 }
}
}
impl Default for Point {
fn default() -> Self {
Point { x: 0, y: 0, z: 0 }
}
}
which gives the compiler error:
default_test.rs:9:7
|
9 | ..Default::default()
| ^^^^^^^^^^^^^^^^^^ field `x` is private
error[E0451]: field `y` of struct `default_mod::Point` is private
Short version - I have a struct with both public and private fields. I would like to initialise this struct with default values, but sometimes override them.
I can't seem to fix this error, nor seen anything on the internet or the docs that even mentions errors like this.
It surprises me, because I'd think a common use-case would be to initialise a struct, and that some members of the struct would be private so you can hide implementation details behind and interface.
In my case the private field is a Vec as I have some logic that needs to go into adding or removing things from the vector, so I want to make it private to prevent anyone messing up the data structure.
What are my options here?
It surprises me, because I'd think a common use-case would be to initialise a struct, and that some members of the struct would be private so you can hide implementation details behind and interface.
The problem is that the struct update syntax doesn't do what you think it does. For example, the book shows the following code:
let user2 = User {
email: String::from("another#example.com"),
username: String::from("anotherusername567"),
..user1
};
The ..user1 syntax fills in the User fields we haven't explicitly specified, such as active: user1.active, signin_count: user1.signin_count. .. may be followed by an arbitrary expression which returns the structure, which is where Default::default() comes into play, and means the same as User::default() because a User is expected. However, the desugaring remains unchanged and boils down to assigning individual fields, in neither case granting special access to private fields.
To get back to your example, this code:
let p = Point {
z: 1,
..Default::default()
};
is syntactic sugar for:
let p = {
let _tmp = Point::default();
Point {
x: _tmp.x,
y: _tmp.y,
z: 1,
}
};
and not for the expected:
// NOT what happens
let p = {
let _tmp = Point::default();
p.z = 1;
_tmp
};
What are my options here?
The most idiomatic option is to provide a builder for Point. That is also somewhat bulky1, so if you're looking for a simple solution, you could also use Point::default() and set the z attribute manually. The struct update syntax is incompatible with structs with private fields and just not useful for your type.
1
Though there are crates like derive_builder, typed-builder and builder-pattern that take some of the drudgery away.
What are my options here?
A new() with parameters or a builder.
..struct is just a convenient way of doing functional updates, it doesn't bypass ACLs. Here since your struct has private fields, users can not manipulate it as a "bare" struct, they have to treat it as a largely opaque type.

Rust impl default trait with private fields

I'm getting an error when I have this sort of setup:
default_test.rs:
mod default_mod;
use default_mod::Point;
fn main() {
let _p1 = Point::new();
let _p2: Point = Point {
z: 1,
..Default::default()
};
}
default_mod.rs:
pub struct Point {
x: i32,
y: i32,
pub z: i32,
}
impl Point {
pub fn new() -> Self {
Point { x: 0, y: 0, z: 0 }
}
}
impl Default for Point {
fn default() -> Self {
Point { x: 0, y: 0, z: 0 }
}
}
which gives the compiler error:
default_test.rs:9:7
|
9 | ..Default::default()
| ^^^^^^^^^^^^^^^^^^ field `x` is private
error[E0451]: field `y` of struct `default_mod::Point` is private
Short version - I have a struct with both public and private fields. I would like to initialise this struct with default values, but sometimes override them.
I can't seem to fix this error, nor seen anything on the internet or the docs that even mentions errors like this.
It surprises me, because I'd think a common use-case would be to initialise a struct, and that some members of the struct would be private so you can hide implementation details behind and interface.
In my case the private field is a Vec as I have some logic that needs to go into adding or removing things from the vector, so I want to make it private to prevent anyone messing up the data structure.
What are my options here?
It surprises me, because I'd think a common use-case would be to initialise a struct, and that some members of the struct would be private so you can hide implementation details behind and interface.
The problem is that the struct update syntax doesn't do what you think it does. For example, the book shows the following code:
let user2 = User {
email: String::from("another#example.com"),
username: String::from("anotherusername567"),
..user1
};
The ..user1 syntax fills in the User fields we haven't explicitly specified, such as active: user1.active, signin_count: user1.signin_count. .. may be followed by an arbitrary expression which returns the structure, which is where Default::default() comes into play, and means the same as User::default() because a User is expected. However, the desugaring remains unchanged and boils down to assigning individual fields, in neither case granting special access to private fields.
To get back to your example, this code:
let p = Point {
z: 1,
..Default::default()
};
is syntactic sugar for:
let p = {
let _tmp = Point::default();
Point {
x: _tmp.x,
y: _tmp.y,
z: 1,
}
};
and not for the expected:
// NOT what happens
let p = {
let _tmp = Point::default();
p.z = 1;
_tmp
};
What are my options here?
The most idiomatic option is to provide a builder for Point. That is also somewhat bulky1, so if you're looking for a simple solution, you could also use Point::default() and set the z attribute manually. The struct update syntax is incompatible with structs with private fields and just not useful for your type.
1
Though there are crates like derive_builder, typed-builder and builder-pattern that take some of the drudgery away.
What are my options here?
A new() with parameters or a builder.
..struct is just a convenient way of doing functional updates, it doesn't bypass ACLs. Here since your struct has private fields, users can not manipulate it as a "bare" struct, they have to treat it as a largely opaque type.

Writing a Rust struct type that contains a string and can be used in a constant

I'm getting started with Rust. I want to have a struct that contains (among other things) a string:
#[derive(Clone, Debug)]
struct Foo {
string_field: &str, // won't compile, but suppose String or Box<str> or &'a str or &'static str...
}
And I want to be able to declare constants or statics of it:
static FOO1: Foo = Foo {
string_field: "",
};
And I also want to be able to have it contain a string constructed at runtime:
let foo2 = Foo {
string_field: ("a".to_owned() + "b").as_str(),
};
I could add a lifetime parameter to Foo so that I can declare that the string reference has the same lifetime. That's fine, except that it then seems to require an explicit lifetime parameter for everything that contains a Foo, which means that it complicates the rest of my program (even parts that don't care about being able to use constant expressions).
I could write
enum StringOfAdequateLifetime {
Static(&'static str),
Dynamic(Box<str>), // or String, if you like
}
struct Foo {
string_field: StringOfAdequateLifetime,
}
and that seems to work so far but clutters up writing out literal Foos.
It seems obvious enough that the desired runtime behavior is sound: when you drop a Foo, drop the string it contains — and if it's static it's never dropped, so no extra information is needed to handle the two cases. Is there a clean way to ask Rust for just that?
(It seems like what I could use is some kind of "smart pointer" type to hold the string that can also be written as a constant expression for the static case, but I haven't seen one in the standard library, and when I tried to genericize StringOfAdequateLifetime to apply to any type, I ran into further complications with implementing and using the various standard traits like Deref, which I suspect were due to something about the differences between Sized and non-Sized types.)
The rust standard library has a built-in type for this exact use case, Cow. It's an enum that can represent either a reference or an owned value, and will clone the value if necessary to allow mutable access. In your particular use case, you could define the struct like so:
struct Foo {
string_field: Cow<'static, str>
}
Then you could instantiate it in one of two ways, depending on whether you want a borrowed constant string or an owned runtime-constructed value:
const BORROWED: Foo = Foo { string_field: Cow::Borrowed("some constant") };
let owned = Foo { string_field: Cow::Owned(String::from("owned string")) };
To simplify this syntax, you can define your own constructor functions for the type using a const fn to allow using the borrowed constructor in a constant context:
impl Foo {
pub const fn new_const(value: &'static str) -> Self {
Self { string_field: Cow::borrowed(value) }
}
pub fn new_runtime(value: String) -> Self {
Self { string_field: Cow::Owned(value) }
}
}
This allows you to use a simpler syntax for initializing the values:
const BORROWED: Foo = Foo::new_const("some constant");
let owned = Foo::new_runtime(String::from("owned string"));

What is the ".." syntax inside a struct literal in Rust?

From the std::default::Default docs:
#[derive(Default)]
struct SomeOptions {
foo: i32,
bar: f32,
}
fn main() {
let options = SomeOptions { foo: 42, ..Default::default() };
}
What is the .. prefix doing to the returned value of Default::default() and why is it necessary here? It almost seems like it's acting as a spread operator, but I'm not sure. I understand what ..Default::default() is doing -- filling in the remaining struct parameters with the default values of SomeOptions, but not how .. works. What is the name of this operator?
This is the struct update syntax. It is "needed" only to have a succinct way of moving / copying all of the members of a struct to a new one, potentially with some small modifications.
The "long" way of writing this would be:
let a = SomeOptions::default();
let options = SomeOptions { foo: 42, bar: a.bar };
You could indeed think of it similar to the JavaScript "spread" operator, but Rust's nuances of ownership and strong typing still come into play, so it's not as widely used. For example, you can't use this syntax to go between values of different types.

Accessing tuple from within an enum

I have a Rust enum defined like this
enum MyFirstEnum {
TupleType(f32, i8, String),
StuctType {varone: i32, vartwo: f64},
NewTypeTuple(i32),
SomeVarName
}
I have the following code:
let mfe: MyFirstEnum = MyFirstEnum::TupleType(3.14, 1, "Hello".to_string());
I'm following the Rust documentation and this looks fine. I don't need to define everything in the enum, but how would I go about accessing the mid element in the enum tuple?
mfe.TupleType.1 and mfe.1 don't work when I add them to a println!
I know Rust provides the facility to do pattern matching to obtain the value, but if I changed the code to define the other variants within the enum, the code to output a particular variant would quickly become a mess.
Is there a simple way to output the variant of the tuple (or any other variant) in the enum?
This is a common misconception: enum variants are not their own types (at least in Rust 1.9). Therefore when you create a variable like this:
let value = MyFirstEnum::TupleType(3.14, 1, "Hello".to_string());
The fact that it's a specific variant is immediately "lost". You will need to pattern match to prevent accessing the enum as the wrong variant. You may prefer to use an if let statement instead of a match:
if let MyFirstEnum::TupleType(f, i, s) = value {
// Values available here
println!("f: {:?}", f);
}
Example solution:
enum MyFirstEnum {
TupleType(f32, i8, String),
// StuctType { varone: i32, vartwo: f64 },
// NewTypeTuple(i32),
// SomeVarName,
}
fn main() {
let mfe: MyFirstEnum = MyFirstEnum::TupleType(3.14, 1, "Hello".to_string());
let MyFirstEnum::TupleType(value, id, text) = &mfe;
println!("[{}; {}; {}]", value, id, text);
//or
match &mfe {
MyFirstEnum::TupleType(value, id, text) => {
println!("[{}; {}; {}]", value, id, text);
}
// _ => {}
}
}
Playground link

Resources