# `nupp.store` Typed keys and the stores they index. A key is a phantom-typed identity: Nupp remembers `T`, the runtime holds an id and an optional name. A store is one table indexed by id behind generic methods, so `store:get(key)` reads `T?` and `store:set(key, value)` accepts `T`. Names are opaque strings registered once per runtime state. Ids are allocated in declaration order and identify a key inside this state only; the name is the identity that persists. ## Constructors ### `newKey` _constructor_ ```nupp function newKey(name: string?): Key ``` Creates a key. The type argument comes from the annotation at the declaration. A named key is registered for the runtime state's lifetime; an anonymous key is retained by nothing but its holders. #### Type parameters | Name | Description | | --- | --- | | `T` | | #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string?` | the opaque name to register, or nil for an anonymous key | #### Returns | Type | Description | | --- | --- | | `Key\` | the key | #### Raises - when the name is empty or already registered, before an id is used ### `newStore` _constructor_ ```nupp function newStore(): Store ``` Creates an empty store. #### Returns | Type | Description | | --- | --- | | `Store` | the store | ## Types ### `Key` _interface_ ```nupp interface Key readonly id: integer readonly name: string? end ``` A typed identity for one value in a [`nupp.store.Store`](#nupp.store.Store). `id` and `name` are all a key holds at runtime. `_valueType` is never present: it mentions `T` in both positions so that keys are invariant, which is what makes a wrong write through one a checker error rather than a silent widening. #### Type parameters | Name | Description | | --- | --- | | `T` | | #### Fields ##### `id` ```nupp id: integer ``` ##### `name` ```nupp name: string? ``` ### `KeyStep` _type_ ```nupp type KeyStep = function(any, integer): (integer, string) ``` The step of [`nupp.store.registeredKeys`](#nupp.store.registeredKeys). Terminating on nil is the generic for's business, so the surface type promises what the loop delivers rather than what the last call returns. ### `Store` _record_ ```nupp record Store get: function(self: Store, key: Key): T? set: function(self: Store, key: Key, value: T): nil remove: function(self: Store, key: Key): nil clear: function(self: Store): nil entries: function( borrows self: Store ): (function(Store, integer): (integer, string?, string), Store borrows (self), integer) end ``` An independent typed bag indexed by keys. #### Methods ##### `get` ```nupp get: function(self: Store, key: Key): T? ``` Answers the value held under a key. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Store` | | | `key` | `Key\` | | ###### Returns | Type | Description | | --- | --- | | `T?` | | ##### `set` ```nupp set: function(self: Store, key: Key, value: T): nil ``` Stores a non-nil value under a key. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Store` | | | `key` | `Key\` | | | `value` | `T` | | ###### Returns | Type | Description | | --- | --- | | `nil` | | ###### Raises - when value is nil; use `remove` to delete an entry ##### `remove` ```nupp remove: function(self: Store, key: Key): nil ``` Removes the value held under a key. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Store` | | | `key` | `Key\` | | ###### Returns | Type | Description | | --- | --- | | `nil` | | ##### `clear` ```nupp clear: function(self: Store): nil ``` Removes every value without touching key registration. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Store` | | ###### Returns | Type | Description | | --- | --- | | `nil` | | ##### `entries` ```nupp entries: function( borrows self: Store ): (function(Store, integer): (integer, string?, string), Store borrows (self), integer) ``` Walks every occupied key ascending by id, without its value. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows self` | `Store` | | ###### Returns | Type | Description | | --- | --- | | `function(Store, integer): (integer, string?, string)` | | | `Store borrows (self)` | | | `integer` | | ### `StoreStep` _type_ ```nupp type StoreStep = function(Store, integer): (integer, string?, string) ``` The step of [`Store.entries`](#nupp.store.Store.entries). Terminating on nil is the generic for's business, so the surface type promises what the loop delivers rather than what the last call returns. ## Functions ### `findKey` _function_ ```nupp function findKey(name: string): unknown ``` Finds a registered key by name. The registry knows the name's id and nothing about its type, so the result is `unknown` and the caller casts to the `Key` it claims. #### Arguments | Name | Type | Description | | --- | --- | --- | | `name` | `string` | the registered name | #### Returns | Type | Description | | --- | --- | | `unknown` | the key, or nil when the name is not registered | ### `registeredKeys` _function_ ```nupp function registeredKeys(): KeyStep, any, integer ``` Walks every registered name, ascending by id. The walk allocates nothing: the step is one shared function and the control variable is the id it last reported. The registry itself is never handed out, so nothing the loop is given can be used to reach or change it. An anonymous key registers no name and is not walked. #### Returns | Type | Description | | --- | --- | | `KeyStep` | the step the loop calls | | `any` | nothing to carry, since the ids are the whole state | | `integer` | the id to resume after, 0 to start |