Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: method specialization #3268

Merged
merged 3 commits into from
Oct 24, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions docs/docs/language_concepts/01_functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,34 @@
assert(MyStruct::sum(s) == 42);
```

It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type:

```rust
struct Foo<T> {}

impl Foo<u32> {
fn foo(self) -> Field { 1 }
}

impl Foo<u64> {
fn foo(self) -> Field { 2 }
}

fn main() {
let f1: Foo<u32> = Foo{};
let f2: Foo<u64> = Foo{};
assert(f1.foo() + f2.foo() == 3);
}
```

jfecher marked this conversation as resolved.
Show resolved Hide resolved
Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo<u32>` and `Foo<u64>` like we do above, we cannot also define `foo` in an `impl<T> Foo<T>` since it would be ambiguous which version of `foo` to choose.

```rs
// Including this impl in the same project as the above snippet would
// cause an overlapping impls error
impl<T> Foo<T> {
fn foo(self) -> Field { 3 }
}
## Lambdas

Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`.
Expand All @@ -148,19 +176,21 @@
Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`.

Supported attributes include:

- **builtin**: the function is implemented by the compiler, for efficiency purposes.
- **deprecated**: mark the function as *deprecated*. Calling the function will generate a warning: `warning: use of deprecated function`
- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details
- **oracle**: mark the function as *oracle*; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [Noir js](../noir_js/noir_js.md) for more details.
- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details

### Field Attribute

The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field.
The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form.
As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve.


Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve.

Check warning on line 192 in docs/docs/language_concepts/01_functions.md

View workflow job for this annotation

GitHub Actions / Spellcheck / Spellcheck

Unknown word (mathbb)

```rust
#[field(bn254)]
fn foo() -> u32 {
Expand All @@ -184,4 +214,4 @@
}
```

If the field name is not known to Noir, it will discard the function. Field names are case insensitive.
If the field name is not known to Noir, it will discard the function. Field names are case insensitive.
Loading