Come notato da altri, le specifiche di tipo sono ingressi solo per strumenti di analisi come PropEr e Dialyzer. Se avete bisogno di far rispettare l'invariante balance >= 0
, il tipo di account deve essere incapsulato, accessibile solo alle funzioni che rispettano l'invariante:
-module(account).
-record(account, { name :: atom(),
type :: atom(),
balance = 0 :: non_neg_integer() }).
%% Declares a type whose structure should not be visible externally.
-opaque account() :: #account{}.
%% Exports the type, making it available to other modules as 'account:account()'.
-export_type([account/0]).
%% Account constructor. Used by other modules to create accounts.
-spec new(atom(), atom(), non_neg_integer()) -> account().
new(Name, Type, InitialBalance) ->
A = #account{name=Name, type=Type},
set_balance(A, InitialBalance).
%% Safe setter - checks the balance invariant
-spec set_balance(account(), non_neg_integer()) -> account().
set_balance(Account, Balance) when is_integer(Balance) andalso Balance >= 0 ->
Account#account{balance=Balance};
set_balance(_, _) -> error(badarg). % Bad balance
Avviso come questo assomiglia ad una classe con i campi privati in linguaggi orientati agli oggetti come Java o C++ . Limitando l'accesso a costruttori e accessori "fidati", l'invariante viene applicato.
Questa soluzione non fornisce protezione contro modifica dannosa del campo balance
. È del tutto possibile che il codice di un altro modulo ignori le specifiche del tipo "opaco" e sostituisca il campo del saldo nel record (dal records are just tuples).
fonte
2013-04-08 15:24:18
Si noti che mentre è possibile dichiarare che il tipo è un numero intero non negativo, questo ** non ** impone nulla in fase di esecuzione, in realtà è solo un commento. È possibile impostare il campo del saldo su qualsiasi valore scelto e qualsiasi tipo. – rvirding
@rviding Come posso applicare questo comportamento in fase di esecuzione (senza protezioni delle funzioni)? Oppure questa digitazione pseudo-statica non esiste in Erlang? – 2rs2ts
Non puoi! Erlang è troppo dinamico, quindi la digitazione statica non esiste nella lingua e il compilatore non usa queste informazioni. È solo per la documentazione e per il dializzatore di strumenti di controllo del tipo. – rvirding