From ec1f0f90acb57887329ac9b3b29f6559369c11c6 Mon Sep 17 00:00:00 2001 From: Todd Nowacki Date: Fri, 19 Jul 2024 15:54:34 -0700 Subject: [PATCH] Apply suggestions from code review Co-authored-by: Cam Swords Co-authored-by: Tim Zakian <2895723+tzakian@users.noreply.github.com> --- reference/src/functions.md | 12 ++++++------ reference/src/functions/macros.md | 23 +++++++---------------- reference/src/generics.md | 5 +++-- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/reference/src/functions.md b/reference/src/functions.md index 4e8f6188..e7d30c24 100644 --- a/reference/src/functions.md +++ b/reference/src/functions.md @@ -149,12 +149,12 @@ module a::m_test { ### `macro` modifier -Unlike normal functions, `macro` functions do not exist at runtime. Instead, the function is -substituted and inlined at each call site during compilation. Leveraging this, `macro` functions -have additional functionality that is not available to normal functions, namely the ability to -create higher-order functions with lambda arguments. These lambda arguments allow for parts of the -function's body to be passed as an argument by the caller. For example, the following is a simple -loop macro, where the body of the loop is passed as a lambda: +Unlike normal functions, `macro` functions do not exist at runtime. Instead, these functions are +substituted inline at each call site during compilation. These `macro` functions leverage this +compilation process to provide functionality beyond standard functions, such as accepting +higher-order _lambda_-style functions as arguments. These lambda arguments, also expanded +during compilation, allow you to pass parts of the function body to the macro as arguments. +For instance, consider the following simple loop macro, where the loop body is supplied as a lambda: ```move macro fun ntimes($n: u64, $body: |u64| -> ()) { diff --git a/reference/src/functions/macros.md b/reference/src/functions/macros.md index 4d670af9..5086ea47 100644 --- a/reference/src/functions/macros.md +++ b/reference/src/functions/macros.md @@ -1,13 +1,13 @@ # Macro Functions -Macro functions are a way of defining functions that are expanded at compile time at each call site. +Macro functions are a way of defining functions that are expanded during compilation at each call site. The arguments of the macro are not evaluated eagerly like a normal function, and instead are substituted by expression. In addition, the caller can supply code to the macro via [lambdas](#lambdas). These expression substitution mechanics make `macro` functions similar [to macros found in other programming languages](); -however, they are more constrained in Move than you might expect from other languages. The parametrs +however, they are more constrained in Move than you might expect from other languages. The parameters and return values of `macro` functions are still typed--though this can be partially relaxed with the [`_` type](TODO). The upside of this restriction however, is that `macro` functions can be used anywhere a normal function can be used, which is notably helpful with @@ -50,13 +50,13 @@ instead the argument expression will be substituted at each usage. ## Lambdas -Lambdas a new type of expression that can be used only with `macro`s. These are used to pass code +Lambdas are a new type of expression that can only be used with `macro`s. These are used to pass code from the caller into the body of the `macro`. While the substition is done at compile time, they are used similarly to [anonymous functions](https://en.wikipedia.org/wiki/Anonymous_function), [lambdas](https://en.wikipedia.org/wiki/Lambda_calculus), or [closures]() in other languages. -As seen in the example above (`$f: |$T| -> $U`), lambdas types defined with the syntax +As seen in the example above (`$f: |$T| -> $U`), lambda types are defined with the syntax ```text |,*| (-> )? @@ -77,7 +77,7 @@ If the return type is not annotated, it is unit `()` by default. |&mut vector, u64| -> () ``` -Lambda expressions then are defined at the call site of the `macro` the syntax +Lambda expressions are then defined at the call site of the `macro` with the syntax ```text |( (: )?),*| @@ -118,21 +118,12 @@ See the [Examples](#iterating-over-a-vector) section for more complicated usages ### Limitations Currently, lambdas can only be used directly in the call of a `macro` function. They cannot be bound -to a variable. - -For example, the following is allowed - -```move -let doubled: vector = map!(vector[1, 2, 3], |x| 2 * x); -``` - -But binding `|x| 2 * x` to a variable is not allowed +to a variable. For example, the following is code will produce an error: ```move let f = |x| 2 * x; // ^^^^^^^^^ Error! Lambdas must be used directly in 'macro' calls let doubled: vector = map!(vector[1, 2, 3], f); -``` ## Typing @@ -341,7 +332,7 @@ In the example above, the `dup` macro had a local variable `a` that was used to `$x`. You might ask, what would happen if the variable was instead named `x`? Would that conflict with the `x` in the lambda? -The short answer is, no. `macro` functions [hygienic](https://en.wikipedia.org/wiki/Hygienic_macro), +The short answer is, no. `macro` functions are [hygienic](https://en.wikipedia.org/wiki/Hygienic_macro), meaning that the expansion of `macro`s and lambdas will not accidentally capture variables from another scope. diff --git a/reference/src/generics.md b/reference/src/generics.md index 38c56d46..a3bb2e8b 100644 --- a/reference/src/generics.md +++ b/reference/src/generics.md @@ -163,8 +163,9 @@ let bar = Bar { x: 0, y: vector[b"hello"] }; // ^ vector is inferred ``` -The placeholder `_` cannot be used in any signatures, only in expressions. This means function -signatures, constant signatures, and datatype fields cannot use the `_` type. +The placeholder `_` may only appear in expressions and macro function definitions, not signatures. +This means you cannot use `_` as pat of the definition of a function +parameter, function return type, constant definition type, and datatype field. ## Integers