Structs in Sway are a named grouping of types. You may also be familiar with structs via another name: product types. Sway does not make any significantly unique usages of structs; they are similar to most other languages which have structs. If you're coming from an object-oriented background, a struct is like the data attributes of an object.
Firstly, we declare a struct named Foo with two fields. The first field is named bar and it accepts values of type u64, the second field is named baz and it accepts bool values.
In order to instantiate the struct we use struct instantiation syntax, which is very similar to the declaration syntax except with expressions in place of types.
There are three ways to instantiate the struct.
Hard coding values for the fields
Passing in variables with names different than the struct fields
Using a shorthand notation via variables that are the same as the field names
library;mod data_structures;use data_structures::{Foo, Line, Point, TupleInStruct};fnhardcoded_instantiation() -> Foo { // Instantiate `foo` as `Foo`letmut foo =Foo { bar:42, baz:false, }; // Access and write to "baz" foo.baz =true; // Return the struct foo}fnvariable_instantiation() -> Foo { // Declare variables with the same names as the fields in `Foo`let number =42;let truthness =false; // Instantiate `foo` as `Foo`letmut foo =Foo { bar: number, baz: truthness, }; // Access and write to "baz" foo.baz =true; // Return the struct foo}fnshorthand_instantiation() -> Foo { // Declare variables with the same names as the fields in `Foo`let bar =42;let baz =false; // Instantiate `foo` as `Foo`letmut foo =Foo { bar, baz }; // Access and write to "baz" foo.baz =true; // Return the struct foo}fnstruct_destructuring() {let point1 =Point { x:0, y:0 }; // Destructure the values from the struct into variablesletPoint { x, y } = point1;let point2 =Point { x:1, y:1 }; // If you do not care about specific struct fields then use ".." at the end of your variable listletPoint { x, .. } = point2;let line =Line { p1: point1, p2: point2, }; // Destructure the values from the nested structs into variablesletLine { p1:Point { x: x0, y: y0 }, p2:Point { x: x1, y: y1 }, } = line; // You may also destructure tuples nested in structs and structs nested in tupleslet tuple_in_struct =TupleInStruct { nested_tuple: (42u64, (42u32, (true, "ok"))), };letTupleInStruct { nested_tuple: (a, (b, (c, d))), } = tuple_in_struct;let struct_in_tuple = (Point { x:2, y:4 }, Point { x:3, y:6 });let (Point { x: x0, y: y0 }, Point { x: x1, y: y1 }) = struct_in_tuple;}
Icon InfoCircle
Note
You can mix and match all 3 ways to instantiate the struct at the same time.
Moreover, the order of the fields does not matter when instantiating however we encourage declaring the fields in alphabetical order and instantiating them in the same alphabetical order
Furthermore, multiple variables can be extracted from a struct using the destructuring syntax.
Note
This information is not vital if you are new to the language, or programming in general
Structs have zero memory overhead. What that means is that in memory, each struct field is laid out sequentially. No metadata regarding the struct's name or other properties is preserved at runtime. In other words, structs are compile-time constructs. This is the same in Rust, but different in other languages with runtimes like Java.
Tuples are a basic static-length type which contain multiple different types within themselves. The type of a tuple is defined by the types of the values within it, and a tuple can contain basic types as well as structs and enums.
You can access values directly by using the . syntax. Moreover, multiple variables can be extracted from a tuple using the destructuring syntax.
library;fntuple() { // You can declare the types youselflet tuple1: (u8, bool, u64) = (100, false, 10000); // Or have the types be inferredletmut tuple2 = (5, true, ("Sway", 8)); // Retrieve values from tupleslet number = tuple1.0;let sway = tuple2.2.1; // Destructure the values from the tuple into variableslet (n1, truthness, n2) = tuple1; // If you do not care about specific values then use "_"let (_, truthness, _) = tuple2; // Internally mutate the tuple tuple2.1=false; // Or change the values all at once (must keep the same data types) tuple2 = (9, false, ("Fuel", 99));}
Enumerations, or enums, are also known as sum types. An enum is a type that could be one of several variants. To declare an enum, you enumerate all potential variants.
Here, we have defined five potential colors. Each enum variant is just the color name. As there is no extra data associated with each variant, we say that each variant is of type (), or unit.
library;// Declare the enumenumColor {Blue: (),Green: (),Red: (),Silver: (),Grey: (),}fnmain() { // To instantiate a variable with the value of an enum the syntax islet blue =Color::Blue;let silver =Color::Silver;}
It is also possible to have an enum variant contain extra data. Take a look at this more substantial example, which combines struct declarations with enum variants:
If you wish to use the nested form of enums via the Error enum from the example above, then you can instantiate them into variables using the following syntax:
Note
This information is not vital if you are new to the language, or programming in general.
Enums do have some memory overhead. To know which variant is being represented, Sway stores a one-word (8-byte) tag for the enum variant. The space reserved after the tag is equivalent to the size of the largest enum variant. So, to calculate the size of an enum in memory, add 8 bytes to the size of the largest variant. For example, in the case of Color above, where the variants are all (), the size would be 8 bytes since the size of the largest variant is 0 bytes.