You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: apps/nextra/pages/en/build/smart-contracts/book/functions.mdx
+28-10
Original file line number
Diff line number
Diff line change
@@ -232,8 +232,11 @@ script {
232
232
}
233
233
```
234
234
235
-
Entry functions can take primitive types, String, and vector arguments but cannot take Structs (e.g. Option). They also
236
-
must not have any return values.
235
+
Entry functions can accept parameters that are: primitive types, reference to a
236
+
`signer`, vectors (where the element type is itself acceptable),
237
+
and certain standard library types such as `String`, `Object`, and `Option`.
238
+
Entry functions must not have any return values.
239
+
237
240
238
241
### Name
239
242
@@ -733,7 +736,22 @@ The type of the `self` argument can be a struct or an immutable or mutable refer
733
736
734
737
Notice that you do not need to `use` the modules which introduce receiver functions. The compiler will find those functions automatically based on the argument type of `s` in a call like `s.foo(1)`. This, in combination with the automatic insertion of reference operators, can make code using this syntax significantly more concise.
735
738
736
-
## Function Values
739
+
The receiver style syntax can also be used on generic functions, like shown below for the generic function `std::vector::remove<T>(self: &mut vector<T>, i: u64): T`.
740
+
741
+
```move
742
+
module 0x42::example {
743
+
fun bar() {
744
+
let v = vector[1, 2, 3];
745
+
let e1 = v.remove(0); // type params inferred for `remove<T>`
746
+
assert!(e1 == 1);
747
+
let e2 = v.remove::<u8>(0); // type params explicitly specified
748
+
assert!(e2 == 2);
749
+
}
750
+
}
751
+
```
752
+
753
+
754
+
## Function Values
737
755
738
756
_Since language version 2.2_ (preview)
739
757
@@ -748,7 +766,7 @@ Function types can have associated abilities, written as `|u64|bool has copy`. M
748
766
Function values can be stored in fields of structs or enums. In this case, the field type inherits the abilities of the struct:
749
767
750
768
```move
751
-
struct S has key {
769
+
struct S has key {
752
770
func: |u64| bool /* has store */ // not needed since inherited
753
771
}
754
772
```
@@ -799,7 +817,7 @@ let f: |u64|bool has copy+drop+store = is_even;
799
817
let g: |u64|bool has copy+drop = is_odd;
800
818
```
801
819
802
-
A public function is required to build a storable function value because it needs to be guaranteed that the underlying function persists so the function value can be safely restored from storage at any point in the future. However, code upgrade may change the underlying implementation of the function, while its signature is persistent.
820
+
A public function is required to build a storable function value because it needs to be guaranteed that the underlying function persists so the function value can be safely restored from storage at any point in the future. However, code upgrade may change the underlying implementation of the function, while its signature is persistent.
803
821
804
822
If a function should storable which is non-public, an attribute can be used to mark this function as persistent, with the same upgrade behavior than public functions. This avoids exposing such a function outside of a package which can be a security risk:
805
823
@@ -840,11 +858,11 @@ let f: |u64|u64 has copy+drop+store = |y| add(x, y)
840
858
let f: |u64|u64 has copy+drop+store = |y| add(y, x)
841
859
```
842
860
843
-
For reference, this mechanism is also called 'currying' of `add` in functional programming languages.
861
+
For reference, this mechanism is also called 'currying' of `add` in functional programming languages.
844
862
845
863
### Reentrancy Check
846
864
847
-
Via dynamic dispatch of function values, reentrancy of modules in a chain of function calls is possible. If module `m1` uses module `m2`, and `m1` calls `m2::f` passing a function value to it, this function value can callback into `m1`. This situation is called _reentrancy_, and is not possible in Move without function values, since the module usage relation is acyclic.
865
+
Via dynamic dispatch of function values, reentrancy of modules in a chain of function calls is possible. If module `m1` uses module `m2`, and `m1` calls `m2::f` passing a function value to it, this function value can callback into `m1`. This situation is called _reentrancy_, and is not possible in Move without function values, since the module usage relation is acyclic.
848
866
849
867
The Move VM dynamically detects reentrancy for a module, and _locks_ all resources declared in this module from being accessed. Thus during reentrancy, calling the functions `borrow_global`, `borrow_global_mut`, and `move_from` lead to an abort. Here is an example:
850
868
@@ -855,7 +873,7 @@ module caller {
855
873
fun calling() acquires R {
856
874
let r = &mut R[@addr];
857
875
// This callback is OK, because `R` is not accessed
858
-
callee::call_me(r, |x| do_something(x))
876
+
callee::call_me(r, |x| do_something(x))
859
877
// This callback will lead to reentrancy runtime error
860
878
callee::call_me(r, |_| R[@addr].count += 1)
861
879
r.call_count += 1
@@ -867,12 +885,12 @@ module callee {
867
885
fun call_me<T(x: &mut T, action: |&mut T|) {
868
886
action(x)
869
887
}
870
-
}
888
+
}
871
889
```
872
890
873
891
Notice that dispatching a function value to a concrete function in the same module is also considered to be reentrancy. If the function `callee::call_me` would be moved into the module `caller`, the same semantics is in effect.
874
892
875
-
The default reentrancy check ensures consistency of Move's reference semantics and suppresses side-effects for the resources in a reentered module. But it does not protect from side-effects on other state of the app. For this purposes, the `#[module_lock]` attribute can be attached to a function. In a calling context where this attribute is active, reentrancy will be fully suppressed, causing an abort at the moment a module is reentered. In the example below, the state effected is owned by another module `account` instead of the module `caller` for which the can potentially happen via the `notify` callback:
893
+
The default reentrancy check ensures consistency of Move's reference semantics and suppresses side-effects for the resources in a reentered module. But it does not protect from side-effects on other state of the app. For this purposes, the `#[module_lock]` attribute can be attached to a function. In a calling context where this attribute is active, reentrancy will be fully suppressed, causing an abort at the moment a module is reentered. In the example below, the state effected is owned by another module `account` instead of the module `caller` for which the can potentially happen via the `notify` callback:
0 commit comments