-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: salaheldinsoliman <[email protected]>
- Loading branch information
1 parent
ac9b15b
commit 67c08d6
Showing
11 changed files
with
541 additions
and
0 deletions.
There are no files selected for viewing
60 changes: 60 additions & 0 deletions
60
...tent/developer/iota-101/move-overview/structs-and-abilities/abilities-intro.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Abilities: Introduction | ||
|
||
Move has a unique type system which allows customizing _type abilities_. | ||
In the [struct section](./struct.mdx), we introduced the `struct` definition and how to use it. | ||
However, the instances of the `Artist` and `Record` structs had to be unpacked for the code to | ||
compile. This is default behavior of a struct without _abilities_. | ||
|
||
::: info | ||
Throughout the documentation you will see struct definitions with abilities. This section will cover abilities in detail, how it works, and how to use it | ||
in Move. | ||
::: | ||
|
||
## What are Abilities? | ||
|
||
Abilities are a way to allow certain behaviors for a type. They are a part of the struct declaration | ||
and define which behaviours are allowed for the instances of the struct. | ||
|
||
## Abilities syntax | ||
|
||
Abilities are set in the struct definition using the `has` keyword followed by a list of abilities. | ||
The abilities are separated by commas. Move supports 4 abilities: `copy`, `drop`, `key`, and | ||
`store`, each of them is used to define a specific behaviour for the struct instances. | ||
|
||
```move | ||
/// This struct has the `copy` and `drop` abilities. | ||
struct VeryAble has copy, drop { | ||
// field: Type1, | ||
// field2: Type2, | ||
// ... | ||
} | ||
``` | ||
|
||
## Overview | ||
|
||
A quick overview of the abilities: | ||
|
||
:::info | ||
All of the built-in types, except references, have `copy`, `drop` and `store` abilities. | ||
References have `copy` and `drop`. | ||
::: | ||
|
||
- `copy` - allows the struct to be _copied_. Explained in the [Ability: Copy](./copy.mdx) | ||
chapter. | ||
- `drop` - allows the struct to be _dropped_ or _discarded_. Explained in the | ||
[Ability: Drop](./drop.mdx) section. | ||
- `key` - allows the struct to be used as a _key_ in a storage. Explained in the | ||
[Ability: Key](./key.mdx) chapter. | ||
- `store` - allows the struct to be _stored_ in structs with the _key_ ability. Explained in the | ||
[Ability: Store](./store.mdx) chapter. | ||
|
||
While it is important to mention them here, we will go in detail about each ability in the following | ||
chapters and give a proper context on how to use them. | ||
|
||
## No abilities | ||
|
||
A struct without abilities cannot be discarded, or copied, or stored in the storage. We call such a | ||
struct a _Hot Potato_. It is a joke, but it is also a good way to remember that a struct without | ||
abilities is like a hot potato - it can only be passed around and requires special handling. Hot | ||
Potato is one of the most powerful patterns in Move, we go in detail about it in the | ||
[Hot Potato](../patterns/hot-potato.mdx) chapter. |
53 changes: 53 additions & 0 deletions
53
docs/content/developer/iota-101/move-overview/structs-and-abilities/copy.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Abilities: Copy | ||
|
||
In Move, the _copy_ ability on a type indicates that the instance or the value of the type can be | ||
copied. While this behavior may feel very natural when working with numbers or other simple types, | ||
it is not the default for custom types in Move. This is because Move is designed to express digital | ||
assets and resources, and inability to copy is a key element of the resource model. | ||
|
||
However, Move type system allows you to define custom types with the _copy_ ability. | ||
|
||
```move | ||
file=<rootDir>/docs/examples/move/move-overview/copy-ability.move#L8-L8 | ||
``` | ||
|
||
In the example above, we define a custom type `Copyable` with the _copy_ ability. This means that | ||
instances of `Copyable` can be copied, both implicitly and explicitly. | ||
|
||
```move | ||
file=<rootDir>/docs/examples/move/move-overview/copy-ability.move#L8 | ||
``` | ||
|
||
In the example above, `a` is copied to `b` implicitly, and then explicitly copied to `c` using the | ||
dereference operator. If `Copyable` did not have the _copy_ ability, the code would not compile, and | ||
the Move compiler would raise an error. | ||
|
||
## Copying and Drop | ||
|
||
The `copy` ability is closely related to [`drop` ability](./drop.mdx). If a type has the | ||
_copy_ ability, very likely that it should have `drop` too. This is because the _drop_ ability is | ||
required to clean up the resources when the instance is no longer needed. If a type has only _copy_, | ||
then managing its instances gets more complicated, as the values cannot be ignored. | ||
|
||
```move | ||
file=<rootDir>/docs/examples/move/move-overview/copy-ability.move#L25 | ||
``` | ||
|
||
All of the primitive types in Move behave as if they have the _copy_ and _drop_ abilities. This | ||
means that they can be copied and dropped, and the Move compiler will handle the memory management | ||
for them. | ||
|
||
## Types with the `copy` Ability | ||
|
||
All native types in Move have the `copy` ability. This includes: | ||
|
||
- bool | ||
- unsigned integers | ||
- [vector](../../../../references/framework/move-stdlib/vector.mdx) | ||
- [address](../../../../references/framework/move-stdlib/address.mdx) | ||
|
||
All of the types defined in the standard library have the `copy` ability as well. This includes: | ||
|
||
- [Option](../../../../references/framework/move-stdlib/option.mdx) | ||
- [String](../../../../references/framework/move-stdlib/string.mdx) | ||
- [TypeName](../../../../references/framework/move-stdlib/type_name.mdx) |
37 changes: 37 additions & 0 deletions
37
docs/content/developer/iota-101/move-overview/structs-and-abilities/drop.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Abilities: Drop | ||
|
||
The `drop` ability - the simplest of abilities - allows the instance of a struct to be _ignored_ or | ||
_discarded_. In many programming languages this behavior is considered default. However, in Move, a | ||
struct without the `drop` ability is not allowed to be ignored. This is a safety feature of the Move | ||
language, which ensures that all assets are properly handled. An attempt to ignore a struct without | ||
the `drop` ability will result in a compilation error. | ||
|
||
```move | ||
file=<rootDir>/docs/examples/move/move-overview/abilities-drop.move#L5-L25 | ||
``` | ||
|
||
|
||
The `drop` ability is often used on custom collection types to eliminate the need for special | ||
handling of the collection when it is no longer needed. For example, a `vector` type has the `drop` | ||
ability, which allows the vector to be ignored when it is no longer needed. However, the biggest | ||
feature of Move's type system is the ability to not have `drop`. This ensures that the assets are | ||
properly handled and not ignored. | ||
|
||
A struct with a single `drop` ability is called a _Witness_. We explain the concept of a _Witness_ | ||
in the [Witness and Abstract Implementation](../patterns/witness.mdx) | ||
section. | ||
|
||
## Types with the `drop` Ability | ||
|
||
All native types in Move have the `drop` ability. This includes: | ||
|
||
- bool | ||
- unsigned integers | ||
- [vector](../../../../references/framework/move-stdlib/vector.mdx) | ||
- [address](../../../../references/framework/move-stdlib/address.mdx) | ||
|
||
All of the types defined in the standard library have the `drop` ability as well. This includes: | ||
|
||
- [Option](../../../../references/framework/move-stdlib/option.mdx) | ||
- [String](../../../../references/framework/move-stdlib/string.mdx) | ||
- [TypeName](../../../../references/framework/move-stdlib/type_name.mdx) |
53 changes: 53 additions & 0 deletions
53
docs/content/developer/iota-101/move-overview/structs-and-abilities/key.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# The Key Ability | ||
|
||
We already covered two out of four abilities - | ||
[Drop](./drop.mdx) and [Copy](./copy.mdx). They affect the behaviour of the value in a | ||
scope and are not directly related to storage. It is time to cover the `key` ability, which allows | ||
the struct to be stored. | ||
|
||
Historically, the `key` ability was created to mark the type as a _key in the storage_. A type with | ||
the `key` ability could be stored at top-level in the storage, and could be _directly owned_ by an | ||
account or address. With the introduction of the [Object Model](../../objects/object-model.mdx), the `key` ability | ||
naturally became the defining ability for the object. | ||
|
||
|
||
## Object Definition | ||
|
||
A struct with the `key` ability is considered an object and can be used in the storage functions. | ||
The Sui Verifier will require the first field of the struct to be named `id` and have the type | ||
`UID`. | ||
|
||
```move | ||
public struct Object has key { | ||
id: UID, // required | ||
name: String, | ||
} | ||
/// Creates a new Object with a Unique ID | ||
public fun new(name: String, ctx: &mut TxContext): Object { | ||
Object { | ||
id: object::new(ctx), // creates a new UID | ||
name, | ||
} | ||
} | ||
``` | ||
|
||
A struct with the `key` ability is still a struct, and can have any number of fields and associated | ||
functions. There is no special handling or syntax for packing, accessing or unpacking the struct. | ||
|
||
However, because the first field of an object struct must be of type `UID` - a non-copyable and | ||
non-droppable type (we will get to it very soon!), the struct transitively cannot have `drop` and | ||
`copy` abilities. Thus, the object is non-discardable by design. | ||
|
||
|
||
## Types with the `key` Ability | ||
|
||
Due to the `UID` requirement for types with `key`, none of the native types in Move can have the | ||
`key` ability, nor can any of the [Standard Library](../../../../references/framework/move-stdlib/_category_.json) types. | ||
The `key` ability is only present in the [IOTA Framework](../../../../references/framework/iota-framework/_category_.json) and | ||
custom types. | ||
|
||
## Next Steps | ||
|
||
Key ability defines the object in Move, and objects are intended to be _stored_. In the next section | ||
we present the `iota::transfer` module, which provides native storage functions for objects. |
50 changes: 50 additions & 0 deletions
50
docs/content/developer/iota-101/move-overview/structs-and-abilities/store.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Ability: Store | ||
|
||
## Definition | ||
|
||
The `store` is a special ability that allows a type to be _stored_ in objects. This ability is | ||
required for the type to be used as a field in a struct that has the `key` ability. Another way to | ||
put it is that the `store` ability allows the value to be _wrapped_ in an object. | ||
|
||
:::info | ||
The `store` ability also relaxes restrictions on transfer operations. We talk about it more in the | ||
[Custome Transfer Rules](../../objects/transfers/custom-rules.mdx) section. | ||
Check warning on line 11 in docs/content/developer/iota-101/move-overview/structs-and-abilities/store.mdx GitHub Actions / typos / Spell Check with Typos
Check warning on line 11 in docs/content/developer/iota-101/move-overview/structs-and-abilities/store.mdx GitHub Actions / docs-lint / Lint documentation
Check warning on line 11 in docs/content/developer/iota-101/move-overview/structs-and-abilities/store.mdx GitHub Actions / typos / Spell Check with Typos
|
||
::: | ||
|
||
## Example | ||
|
||
In previous sections we already used types with the `key` ability: all objects must have a `UID` | ||
field, which we used in examples; we also used the `Storable` type as a part of the `Config` struct. | ||
The `Config` type also has the `store` ability. | ||
|
||
```move | ||
/// This type has the `store` ability. | ||
public struct Storable has store {} | ||
/// Config contains a `Storable` field which must have the `store` ability. | ||
public struct Config has key, store { | ||
id: UID, | ||
stores: Storable, | ||
} | ||
/// MegaConfig contains a `Config` field which has the `store` ability. | ||
public struct MegaConfig has key { | ||
id: UID, | ||
config: Config, // there it is! | ||
} | ||
``` | ||
|
||
## Types with the `store` Ability | ||
|
||
All native types (except for references) in Move have the `store` ability. This includes: | ||
|
||
- bool | ||
- unsigned integers | ||
- [vector](../../../../references/framework/move-stdlib/vector.mdx) | ||
- [address](../../../../references/framework/move-stdlib/address.mdx) | ||
|
||
All of the types defined in the standard library have the `store` ability as well. This includes: | ||
|
||
- [Option](../../../../references/framework/move-stdlib/option.mdx) | ||
- [String](../../../../references/framework/move-stdlib/string.mdx) | ||
- [TypeName](../../../../references/framework/move-stdlib/type_name.mdx) |
73 changes: 73 additions & 0 deletions
73
docs/content/developer/iota-101/move-overview/structs-and-abilities/struct.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Custom Types with Struct | ||
|
||
Move's type system offers the ability to define custom types. User defined types can be custom | ||
tailored to the specific needs of the application. Not just on the data level, but also in its | ||
behavior. In this section we introduce the struct definition and how to use it. | ||
|
||
## Struct | ||
|
||
To define a custom type, you can use the `struct` keyword followed by the name of the type. After | ||
the name, you can define the fields of the struct. Each field is defined with the | ||
`field_name: field_type` syntax. Field definitions must be separated by commas. The fields can be of | ||
any type, including other structs. | ||
|
||
:::info | ||
Move does not support recursive structs, meaning a struct cannot contain itself as a field. | ||
::: | ||
|
||
```move file=<rootDir>/docs/examples/move/move-overview/struct.move#L10-L28 | ||
``` | ||
|
||
|
||
In the example above, we define a `Record` struct with five fields. The `title` field is of type | ||
`String`, the `artist` field is of type `Artist`, the `year` field is of type `u16`, the `is_debut` | ||
field is of type `bool`, and the `edition` field is of type `Option<u16>`. The `edition` field is of | ||
type `Option<u16>` to represent that the edition is optional. | ||
|
||
Structs are private by default, meaning they cannot be imported and used outside of the module they | ||
are defined in. Their fields are also private and can't be accessed from outside the module. See | ||
[visibility](../visibility.mdx) for more information on different visibility modifiers. | ||
|
||
:::info | ||
Fields of a struct are private and can only be accessed by the module defining the struct. Reading | ||
and writing the fields of a struct in other modules is only possible if the module defining the | ||
struct provides public functions to access the fields. | ||
::: | ||
|
||
## Create and use an instance | ||
|
||
We described how struct _definition_ works. Now let's see how to initialize a struct and use it. A | ||
struct can be initialized using the `struct_name { field1: value1, field2: value2, ... }` syntax. | ||
The fields can be initialized in any order, and all of the fields must be set. | ||
|
||
```move file=<rootDir>/docs/examples/move/move-overview/struct.move#L34-L36 | ||
``` | ||
|
||
In the example above, we create an instance of the `Artist` struct and set the `name` field to a | ||
string "The Beatles". | ||
|
||
To access the fields of a struct, you can use the `.` operator followed by the field name. | ||
|
||
```move file=<rootDir>/docs/examples/move/move-overview/struct.move#L40-L50 | ||
``` | ||
|
||
Only module defining the struct can access its fields (both mutably and immutably). So the above | ||
code should be in the same module as the `Artist` struct. | ||
|
||
|
||
## Unpacking a struct | ||
|
||
Structs are non-discardable by default, meaning that the initiated struct value must be used: either | ||
stored or _unpacked_. Unpacking a struct means deconstructing it into its fields. This is done using | ||
the `let` keyword followed by the struct name and the field names. | ||
|
||
```move file=<rootDir>/docs/examples/move/move-overview/struct.move#L54-L56 | ||
``` | ||
|
||
In the example above we unpack the `Artist` struct and create a new variable `name` with the value | ||
of the `name` field. Because the variable is not used, the compiler will raise a warning. To | ||
suppress the warning, you can use the underscore `_` to indicate that the variable is intentionally | ||
unused. | ||
|
||
```move file=<rootDir>/docs/examples/move/move-overview/struct.move#L64-L65 | ||
``` |
Oops, something went wrong.