Transaction
883531D6D8607E…C7CBA16B95A7
Block 25,944 · index 0 · indexed
Summary
- Hash
- 883531D6D8607E4DDAB14B235EF7AA1763E3EE26018670242B17C7CBA16B95A7
- Block
- 25,944
- Size
- 6057 bytes
- Gas used
- 10,240,488 / 12,288,645
- Fee
- 1000000ugnot
- Memo
- gnopublish
- Status
- success
Messages
Arguments · 9
- #1orderedmap
- #2README.md
- #3# `gno.land/p/moul/x/daily/orderedmap/v0` **Map that remembers insertion order** — `New`, `Set`, `Get`, `Has`, `Delete`, `Keys`, `Values`, `Iterate`, `At`, `Clone`, `Len`, `MaxKeys`. ```go import "gno.land/p/moul/x/daily/orderedmap/v0" o := orderedmap.New() o.Set("delta", "4"); o.Set("alpha", "1") o.Keys() // ["delta" "alpha"] — insertion order, not sorted o.Set("delta", "99") // updates in place, keeps position ``` **This matters more on chain than off it.** gno map iteration order is unspecified, so a realm that ranges over a built-in map to build its `Render` can emit a different page on every call — a **consensus bug**, not a cosmetic one. This type gives back a deterministic order without requiring the keys to be sortable. Semantics worth knowing, each with a test: - **Updating keeps position.** Insertion order means *first* insertion, not last write. - **Re-inserting after a delete goes last** — it is a new insertion. - `Keys` returns a copy, so a caller cannot reorder the map through it. Backed by a built-in map for O(1) `Get` plus a slice holding the order. `Delete` is **O(n)**: closing the gap in that slice is what preserves order, and that trade is stated rather than hidden. `MaxKeys` (4096) bounds growth; a full map refuses new keys but still accepts updates to existing ones. **Live demo:** [`r/moul/x/daily/orderedmapdemo`](https://github.com/moul/gno-contracts/tree/main/r/moul/x/daily/orderedmapdemo/v0) · render it at [`/r/moul/x/daily/orderedmapdemo/v0`](https://gno.land/r/moul/x/daily/orderedmapdemo/v0). <!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) --> --- Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. > 🧪 **Highly experimental — potentially vibe-coded.** Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md). <!-- END GNOCONTRACTS FOOTER -->
- #4gnomod.toml
- #5module = "gno.land/p/moul/x/daily/orderedmap/v0" gno = "0.9"
- #6orderedmap.gno
- #7// Package orderedmap is a map that remembers the order its keys were inserted, // as a pure, reusable package. // // This matters more on chain than off it. gno map iteration order is // unspecified, so a realm that ranges over a built-in map to build its Render // can emit a different page on every call — which is a consensus bug, not a // cosmetic one. This type gives back a deterministic order without needing the // keys to be sortable. // // Backed by a built-in map for O(1) lookup plus a slice holding insertion // order. Delete is O(n) in the number of keys, because it has to close the gap // in that slice — an honest trade for O(1) Get and an allocation-free walk. // Re-Setting an existing key updates the value and KEEPS its original position: // insertion order means first insertion, not last write. // // A live demo of this package is at // [r/moul/x/daily/orderedmapdemo](/r/moul/x/daily/orderedmapdemo/v0). package orderedmap // MaxKeys bounds the map so gas stays predictable. const MaxKeys = 4096 // OrderedMap is a string-keyed map with deterministic iteration. type OrderedMap struct { m map[string]string keys []string } // New returns an empty OrderedMap. func New() *OrderedMap { return &OrderedMap{m: map[string]string{}} } // Len returns the number of entries. func (o *OrderedMap) Len() int { return len(o.keys) } // Set inserts or updates k. Updating an existing key keeps its original // position — insertion order means FIRST insertion. Returns false when the map // is full and k is new. func (o *OrderedMap) Set(k, v string) bool { if _, ok := o.m[k]; ok { o.m[k] = v return true } if len(o.keys) >= MaxKeys { return false } o.m[k] = v o.keys = append(o.keys, k) return true } // Get returns the value for k. func (o *OrderedMap) Get(k string) (string, bool) { v, ok := o.m[k] return v, ok } // Has reports whether k is present. func (o *OrderedMap) Has(k string) bool { _, ok := o.m[k] return ok } // Delete removes k and reports whether it was present. O(n): the key's slot in // the order slice has to be closed up, and the remaining keys shifted, so that // order is preserved. func (o *OrderedMap) Delete(k string) bool { if _, ok := o.m[k]; !ok { return false } delete(o.m, k) for i, kk := range o.keys { if kk == k { o.keys = append(o.keys[:i], o.keys[i+1:]...) break } } return true } // Keys returns the keys in insertion order, as an independent copy. func (o *OrderedMap) Keys() []string { out := make([]string, len(o.keys)) copy(out, o.keys) return out } // Values returns the values in key-insertion order. func (o *OrderedMap) Values() []string { out := make([]string, 0, len(o.keys)) for _, k := range o.keys { out = append(out, o.m[k]) } return out } // Iterate calls fn for each entry in insertion order, stopping early if fn // returns true. The map must not be mutated from inside fn — the walk is over // a live slice. func (o *OrderedMap) Iterate(fn func(k, v string) bool) { for _, k := range o.keys { if fn(k, o.m[k]) { return } } } // At returns the i-th entry in insertion order. func (o *OrderedMap) At(i int) (k, v string, ok bool) { if i < 0 || i >= len(o.keys) { return "", "", false } k = o.keys[i] return k, o.m[k], true } // Clone returns an independent copy preserving order. func (o *OrderedMap) Clone() *OrderedMap { c := New() for _, k := range o.keys { c.Set(k, o.m[k]) } return c }
- #8/gno.MemPackageType
- #9 MPUserProd
Result log
msg:0,success:true,log:,events:[]