Skip to content
LogoLogo

Generic modules

A generic module like Set(T : MapKey) is specialized for each element type it is used with. Set(OrderId) and Set(address) are distinct types with their own code.

(* Generic modules specialize at compile time: no runtime cost, no casts.
   `Set(T : mapKey)` accepts any type that can key a map. *)
 
import "std/evm";
import "./lib/set";
import "./lib/set_enumerable";
 
type OrderId is bytes32;
 
storage is record {
  admins : Set(address);
  orders : Set(OrderId);
  members : SetEnumerable(address);
}
 
(* Functions can be generic too. *)
pure function first(T)(const a : T; const b : T) : T is
  a
 
external function addAdmin(const who : address) is {
  Set.add(storage.admins, who);
}
 
external view function isAdmin(const who : address) : bool is
  Set.contains(storage.admins, who)
 
(* `Set(OrderId)` is not `Set(bytes32)`: the element type is checked. *)
external function track(const id : bytes32) is {
  Set.add(storage.orders, OrderId(id));
}
 
external function join() is {
  SetEnumerable.add(storage.members, first(Evm.sender(), Evm.txOrigin()));
}
 
external view function memberCount() : uint is
  SetEnumerable.length(storage.members)
 
external view function memberAt(const i : uint) : address
  raises OutOfBounds
is
  SetEnumerable.at(storage.members, i)
 
(* A module passes its own storage to a generic module the same way. *)
module Watchlist is {
  storage watchlist at "lithe.watchlist" is record {
    watched : SetEnumerable(address);
  }
 
  external function watch(const who : address) is {
    SetEnumerable.add(watchlist.watched, who);
  }
 
  external view function watchedCount() : uint is
    SetEnumerable.length(watchlist.watched)
}
 
use Watchlist exposing {
  function watch(who : address);
  view function watchedCount() : uint;
}
  • Set.add(storage.admins, who) works on the storage location it is given. The set module owns no storage of its own.
  • Watchlist hands watchlist.watched, from its own storage, to SetEnumerable just as the contract hands over storage.members.
  • MapKey limits T to types that can key a map. Set(string) is rejected.