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

feat(docs): map.deepEquals() #939

Merged
merged 5 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `storeBit` method for `Builder` type and the `loadBit` method for `Slice` type: PR [#699](https://github.com/tact-lang/tact/pull/699)
- The `toSlice` method for structs and messages: PR [#630](https://github.com/tact-lang/tact/pull/630)
- Wider range of serialization options for integers — `uint1` through `uint256` and `int1` through `int257`: PR [#558](https://github.com/tact-lang/tact/pull/558), PR [#937](https://github.com/tact-lang/tact/pull/937)
- The `deepEquals` method for the `Map` type: PR [#637](https://github.com/tact-lang/tact/pull/637)
- The `deepEquals` method for the `Map` type: PR [#637](https://github.com/tact-lang/tact/pull/637), PR [#939](https://github.com/tact-lang/tact/pull/939)
- `asm` bodies for module-level functions: PR [#769](https://github.com/tact-lang/tact/pull/769), PR [#825](https://github.com/tact-lang/tact/pull/825)
- Corresponding stdlib functions for new TVM instructions from 2023.07 and 2024.04 upgrades: PR [#331](https://github.com/tact-lang/tact/pull/331). Added the `storeBuilder` extension function and `gasConsumed`, `getComputeFee`, `getStorageFee`, `getForwardFee`, `getSimpleComputeFee`, `getSimpleForwardFee`, `getOriginalFwdFee`, `myStorageDue` functions.
- `slice`, `rawSlice`, `ascii` and `crc32` built-in functions: PR [#787](https://github.com/tact-lang/tact/pull/787), PR [#799](https://github.com/tact-lang/tact/pull/799)
Expand Down
25 changes: 25 additions & 0 deletions docs/src/content/docs/book/maps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: Maps
description: "The composite type map is used as a way to associate keys with corresponding values of various types"
---

import { Badge } from '@astrojs/starlight/components';

The [composite type](/book/types#composite-types) `map<K, V>{:tact}` is used as a way to associate keys of type `K{:tact}` with corresponding values of type `V{:tact}`.

For example, `map<Int, Int>{:tact}` uses [`Int{:tact}`][int] type for its keys and values:
Expand Down Expand Up @@ -151,6 +153,29 @@ if (fizz == null) {
}
```

### Compare with `.deepEquals()` {#deepequals}

<Badge text="Available since Tact 1.5" variant="tip" size="medium"/><p/>

The `.deepEquals(){:tact}` [method](/book/functions#extension-function) on maps returns `true{:tact}` if all the entries of the map match respective entries of another map and their [underlying serialization logic](https://docs.ton.org/develop/data-formats/tl-b-types#hashmap) is exactly the same. Returns `false{:tact}` otherwise.
anton-trunov marked this conversation as resolved.
Show resolved Hide resolved

```tact
let fizz: map<Int, Int> = emptyMap();
let buzz: map<Int, Int> = emptyMap();

fizz.set(1, 2);
buzz.set(1, 2);

fizz.deepEquals(buzz); // true
fizz == buzz; // true, and uses much less gas to compute
```

:::note

This function is very gas expensive, and for the majority of cases it'll be enough to use the shallow comparison via the [equality `=={:tact}`](/book/operators#binary-equality) or [inequality `!={:tact}`](/book/operators#binary-equality) operators.

:::

### Convert to a `Cell`, `.asCell()` {#ascell}

Use `.asCell(){:tact}` [method](/book/functions#extension-function) on maps to convert all their values to a [`Cell{:tact}`][cell] type. Be mindful, that [`Cell{:tact}`][cell] type is able to store up to 1023 bits, so converting larger maps to the Cell will result in error.
Expand Down
12 changes: 10 additions & 2 deletions docs/src/content/docs/book/operators.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,8 @@ Both operators can be applied to the following list of types and values:
* [`Int{:tact}`][int]
* [`Bool{:tact}`][bool]
* [`Address{:tact}`][p]
* [`Cell{:tact}`][cell], implicitly compares via `.hash(){:tact}`
* [`Slice{:tact}`][slice], implicitly compares via `.hash(){:tact}`
* [`Cell{:tact}`][cell], implicitly compares via [`.hash(){:tact}`](/ref/core-cells#cellhash)
* [`Slice{:tact}`][slice], implicitly compares via [`.hash(){:tact}`](/ref/core-cells#slicehash)
* [`String{:tact}`][p]
* [`map<K, V>{:tact}`](/book/maps), but only if their key and value types are identical
* [Optionals and `null{:tact}` value](/book/optionals)
Expand Down Expand Up @@ -431,6 +431,14 @@ nullable == anotherNullable; // false
nullable != anotherNullable; // true
```

:::note

Binary equality `=={:tact}` and inequality `!={:tact}` operators implicitly compare [maps](/book/maps) by the hashes of their respective [cells][cell] via [`.hash(){:tact}`](/ref/core-cells#cellhash) function. While this is ok for the majority of cases because most map serializers work identically to the one from TON Blockchain sources, it's still possible to get false negative results by serializing a map manually or by changing the logic of the serializer in some library.

If you need to guarantee that maps you're comparing are equal, and you're willing to pay a lot more gas for it, use the [`map.deepEquals(){:tact}`](/book/maps#deepequals) function.

:::

### Bitwise AND, `&` {#binary-bitwise-and}

Binary ampersand (_bitwise AND_) operator `&{:tact}` applies a [bitwise AND](https://en.wikipedia.org/wiki/Bitwise_operation#AND), which performs the [logical AND](#binary-logical-and) operation on each pair of the corresponding bits of operands. This is useful when we want to clear selected bits off a number, where each bit represents an individual flag or a boolean state, which makes it possible to "store" up to $257$ boolean values per integer, as all integers in Tact are $257$-bit signed.
Expand Down
Loading