Skip to content

Behaviours

A behaviour is an ordinary module. declares names the contract. callback lines are signatures only. Optional callbacks may be omitted. The compiler checks every implementation against this contract.

mod behaviours.store
@moduledoc """
A behaviour is an ordinary module. `declares` names the contract.
`callback` lines are signatures only. Optional callbacks may be omitted.
The compiler checks every implementation against this contract.
"""
declares Store<K, V>
callback get(data: Map<K, V>, key: K) -> Option<V>
callback put(data: Map<K, V>, key: K, value: V) -> Map<K, V>
optional callback close() -> :ok

implements is a module header. Required callbacks are ordinary public functions. Optional close is omitted here, so it is not callable through mod Store.

mod behaviours.memory
@moduledoc """
`implements` is a module header. Required callbacks are ordinary public
functions. Optional `close` is omitted here, so it is not callable through
`mod Store`.
"""
alias behaviours.store
alias gale_std.map
implements store.Store<String, Integer> as memory
pub fn get(data: Map<String, Integer>, key: String) -> Option<Integer> {
map.get(data, key)
}
pub fn put(
data: Map<String, Integer>,
key: String,
value: Integer
) -> Map<String, Integer> {
map.put(data, key, value)
}

A mod Store<K, V> value is a module that implements the behaviour. The caller selects the implementation; there is no implicit lookup. Passing a module that does not implement Store is a compile-time error.

mod behaviours
alias behaviours.store
alias gale_std.map
pub fn round_trip(
store: mod store.Store<String, Integer>,
key: String,
value: Integer
) -> Option<Integer> {
data = store.put(map.new(), key, value)
store.get(data, key)
}

A module missing a required callback is rejected:

mod behaviours.broken
alias behaviours.store
implements store.Store<String, Integer> as memory
pub fn get(data: Map<String, Integer>, key: String) -> Option<Integer> {
None
}

OTP behaviours such as GenServer use the same declares / implements mechanism, with extern "Elixir.GenServer" naming the native contract. See OTP.