Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

feat: new page for functions #281

Closed
wants to merge 1 commit into from
Closed
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
160 changes: 108 additions & 52 deletions pages/book/functions.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Functions and their types

{/* TODO: work on terminology & update relevant pages in book/contracts too */}
{/* TODO: global static -> just global, internal -> storage, persistent state -> storage */}
{/* TODO: fix all links leading onto this page */}

{/* TODO: rewrite this paragraph */}

Functions in Tact could be defined in different ways:

* Global static function
Expand All @@ -23,47 +29,99 @@ fun bar() {
}
```

## Global static functions
## Native functions, `native` [#native]

{/* TODO Top-level, mappings to FunC */}

Native functions are direct bindings of FunC functions:

> **Note**
> Native functions could be also mutable and extension ones.
novusnota marked this conversation as resolved.
Show resolved Hide resolved

```tact
@name(store_uint)
native storeUint(s: Builder, value: Int, bits: Int): Builder;

@name(load_int)
extends mutates native loadInt(self: Slice, l: Int): Int;
```

## Regular functions, `fun` [#fun]

{/* TODO: Regular functions are ... */}

### Global [#fun-global]

You can define global function anywhere in your program:

```tact
fun customPow(a: Int, c: Int): Int {
let res: Int = 1;
repeat(c) {
res *= a;
}
return res;
require(c >= 0, "Can't raise to negative power here!");
let res = 1;
repeat(c) { res *= a }
return res;
}
```

## Virtual and abstract functions
{/* TODO: Top-level */}

You can allow the contract inheriting a [traits](/book/types#traits) to modify an internal function, if it has the `virtual{:tact}` keyword, using `override{:tact}`. The function can be also marked as `abstract{:tact}`, in which case the inheriting contract has to define its implementation:
### Storage [#fun-storage]

{/* Internal to traits and contracts. Currently called internal functions, but might as well be called storage ones */}

## Receivers [#receivers]

Receiver functions are special functions that are responsible for receiving messages in contracts and could be defined only within a contract or trait.

```tact
trait FilterTrait with Ownable {
// Virtual functions can be overridden by users of this trait
virtual fun filterMessage(): Bool {
return sender() != self.owner;
contract Treasure {
// This means that this contract can receive the comment "Increment" and this function would be called for such messages
receive("Increment") {
self.counter += 1;
}

abstract fun specialFilter(): Bool;
}
```

contract Filter with FilterTrait {
// Overriding default behavior of the FilterTrait
override fun filterMessage(): Bool {
return true;
}
{/* TODO: investigate into attributes */}
{/* TODO: cross-link from and to /book/receive and /book/contracts */}

override fun specialFilter(): Bool {
return true;
### Internal message receivers, `receive` [#internal-receivers]

{/* TODO */}

### External message receivers, `external` [#external-receivers]

{/* TODO */}

### Bounced message receivers, `bounced` [#bounced-receivers]

{/* TODO */}

## Attributes [#attributes]

{/* When applied... */}

### Off-chain functions, `get` [#attributes-get]

{/* TODO */}

Off-chain functions, otherwise known as _getter_ functions, define special functions, that are unaccessible from other contracts and exported only to off-chain world.

Moreover, they cannot modify the contract's state as their only purpose is to read and retrieve the information from the contract.

Notice, however, that you can evaluate expressions and create local variables just fine. It's only those storage variables that cannot be modified.

```tact
contract Treasure {
get fun counter(): Int {
return self.counter;
}
}
````
```

### Extension functions, `extends` [#attributes-extends]

## Extension function
{/* TODO */}

Extension functions allow you to implement extensions for any possible type.

Expand All @@ -73,14 +131,16 @@ Extension functions allow you to implement extensions for any possible type.
```tact
extends fun customPow(self: Int, c: Int): Int {
let res: Int = 1;
repeat(c) {
res *= self;
}
repeat(c) { res *= self }
return res;
}
```

## Mutable functions
### Mutation functions, `mutates` [#attributes-mutates]

{/* TODO */}

A sub-set of extension functions...

Mutable functions are performing mutation of a value replacing it with an execution result. To perform mutation, the function must change the `self` value.

Expand All @@ -94,42 +154,38 @@ extends mutates fun customPow(self: Int, c: Int) {
}
```

## Native functions

Native functions are direct bindings of FunC functions:
### `abstract` [#attributes-abstract]

> **Note**
> Native functions could be also mutable and extension ones.
### `virtual` [#attributes-virtual]

```tact
@name(store_uint)
native storeUint(s: Builder, value: Int, bits: Int): Builder;
### `override` [#attributes-override]

@name(load_int)
extends mutates native loadInt(self: Slice, l: Int): Int;
```
{/* TODO: "virtual and abstract functions" split this description in three consecutive parts */}

## Receiver functions
You can allow the contract inheriting [traits](/book/types#traits) to modify an internal function, if it has the `virtual{:tact}` keyword, using `override{:tact}`.

Receiver functions are special functions that are responsible for receiving messages in contracts and could be defined only within a contract or trait.
The function can be also marked as `abstract{:tact}`, in which case the inheriting contract has to define its implementation:

```tact
contract Treasure {
// This means that this contract can receive the comment "Increment" and this function would be called for such messages
receive("Increment") {
self.counter += 1;
trait FilterTrait with Ownable {
// Virtual functions can be overridden by users of this trait
virtual fun filterMessage(): Bool {
return sender() != self.owner;
}
}
```

## Getter Functions
abstract fun specialFilter(): Bool;
}

Getter functions define getters on smart contracts and can be defined only within a contract or trait.
contract Filter with FilterTrait {
// Overriding default behavior of the FilterTrait
override fun filterMessage(): Bool {
return true;
}

```tact
contract Treasure {
get fun counter(): Int {
return self.counter;
override fun specialFilter(): Bool {
return true;
}
}
```

{/* TODO: `inline` — in a separate PR, targeting https://github.com/tact-lang/tact-docs/issues/241 */}
Loading