Skip to content
LogoLogo

Overloading

Internal and external functions can share a name when their parameter types differ. A call picks the overload that takes as many arguments as it passes, and when several do, the one whose parameter types the arguments match.

overloads.lithe
(* Functions overload, internal and external alike. The number of arguments picks one;
   when several take as many, the argument types pick. *)
 
import "std/evm";
 
type Shares is uint;
 
storage is record {
  balances : map(address, uint);
  staked : map(address, uint);
  total : uint;
}
 
(* One argument or two. One overload can call another. *)
pure function fee(const amount : uint) : uint is
  fee(amount, 30)
 
pure function fee(const amount : uint; const bps : uint) : uint is
  amount * bps / 10_000
 
(* An overload can take storage: it writes the map it is given. *)
function credit(storage ledger : map(address, uint); const to : address; const amount : uint) is {
  ledger[to] := ledger[to] + amount;
}
 
function credit(const to : address; const amount : uint) is {
  credit(storage.balances, to, amount);
  storage.total := storage.total + amount;
}
 
(* `Shares` is its own type, so a `Shares` argument picks this overload. *)
function credit(const to : address; const amount : Shares) is {
  credit(storage.staked, to, uint(amount));
}
 
(* External overloads are separate entrypoints: `deposit(uint256)` and
   `deposit(uint256,uint256)`. *)
external function deposit(const amount : uint) is {
  credit(Evm.sender(), amount - fee(amount));
}
 
external function deposit(const amount : uint; const bps : uint) is {
  credit(Evm.sender(), amount - fee(amount, bps));
}
 
external function stake(const amount : uint) is {
  credit(Evm.sender(), Shares(amount));
}
 
external view function balanceOf(const who : address) : uint is
  storage.balances[who]
 
external view function stakedOf(const who : address) : uint is
  storage.staked[who]
 
external view function total() : uint is
  storage.total
  • Overloads of one name are all internal or all external, and no two take the same parameter types.
  • A nominal type like Shares is its own type, so it tells overloads apart from uint.
  • When the argument types decide, literals keep their own types: 1 is a uint. Convert a value to pick another overload.
  • Generic functions and functions of a module overload the same way.