Practice using structs.
struct
type allows you to organize related data of different types.
struct
(user-defined type) that contains several different data typesstruct
to maximize storage efficiencystruct
s depending on the types they containmapping
to create a relationship between an address
and a uint
. But what if your users have favorite colors too? Or favorite cars? You could create a mapping
for each of these, but it would quickly get awkward. Instead, a struct
can be used to create a custom type that can store all of a user’s favorites within one data type.
Create a new contract called Structs
.
struct
with the keyword, followed by a name for the type, curly brackets, and the variables that make up the type. Add a stub for Favorites
:
uint
s for those variables. However, people don’t change their favorite number very often, and the day of the month that they were born on never changes.
Therefore, it’s probably more gas-efficient and less cumbersome to write other parts of the code, if we just use uint
for both variables.
Favorite color can be a string
.
For Lucky Lottery Numbers, we need a collection. We could use a dynamic array, since this will be in storage, but we already know that the lottery has 5 numbers.
Try to use this information to build the struct
on your own. You should end up with something similar to:
Reveal code
Favorites
in storage. There are a few options, as always, each with tradeoffs. You could match the pattern you used for favorite numbers and utilize a mapping
to match addresses
to Favorites
.
Another popular method is to use an array, which takes advantage of .push
returning a reference to the newly added element, and the fact that the concept of undefined does not exist in Solidity.
First, instantiate an array of Favorites
:
public
function to add submitted favorites to the list. It should take each of the members as an argument. Then, assign each argument to the new element via the reference returned by push()
.
Reveal code
push
it to storage.
Reveal code
lotteryNumbers
. As it turns out, not every locality has lotteries where 5 numbers are drawn. Some have 3, 4, or even 6!.
You might think this is an easy enough change. After all, you can just remove the size from the array declaration inside Favorites
. Go ahead and try it:
memory
method shown above.
push()
to create an empty instance of Favorites
, then assigning the values.
The reason this works is a little obtuse. In the failing example, an unsized uint
array is the expected type for the argument, but a sized uint
array is provided. Solidity cannot perform implicit conversions like this most of the time and you’ll get a compiler error if you provide the wrong type for an argument, even if it is convertible.
One exception to this rule is that Solidity can perform an implicit conversion during assignment if the variable on the right side “fits” into the variable on the left side.
uint[5]
fits in uint[]
, so Solidity will allow it to sit 🐈.
But what happens if you use the getter for userFavorites
to retrieve your entry?
mappings
inside of struct
s, subject to a few quirks and restrictions. Add mapping (uint => uint) numberPairs;
to Favorites
.
In addFavorites
, assign newFavorite.numberPairs[33] = 66;
Deploy and test. So far, so good!
Déjà vu ahead: But what happens if you use the getter for userFavorites
to retrieve your entry?
addFavorite
function to return a reference to the new favorite?
mapping
type cannot be returned by a public
or external
function, so neither can a struct
that contains one.
newFavorite
to a memory
variable? Again, an error occurs because mapping
s can only be in storage
.
public
struct
in storage at the contract level, the compiler will generate a getter automatically. However, these don’t work quite the way you might expect. For example, imagine:
myStruct
will not be:
struct
keyword to create a custom type that stores related data. You’ve also learned three methods of instantiating them and common patterns for storing struct
s in storage. Finally, you’ve explored some of the constraints that emerge when working with more complex data types within a struct
.