Ci sono due parti per questa risposta. Il primo è che probabilmente non si desidera utilizzare i moduli parametrizzati finché non si è abbastanza esperti di Erlang. Tutto quello che ti danno è un modo diverso per passare argomenti in giro.
-module(test_module, [Param1]).
some_method() -> Param1.
è equivalente a
-module(test_non_paramatized_module).
some_method(Param1) -> Param1.
Il primo non comprarti molto a tutti, e molto poco codice Erlang esistente utilizza quello stile.
È più normale passare l'argomento del nome (presupponendo che si stia creando un numero di simili gen_server registrati con nomi diversi) alla funzione start_link.
start_link(Name) -> gen_server:start_link({local, Name}, ?MODULE, [Name], []).
La seconda parte della risposta è che gen_server è compatibile con i moduli paramatized:
-module(some_module, [Param1, Param2]).
start_link() ->
PModule = ?MODULE:new(Param1, Param2),
gen_server:start_link(PModule, [], []).
Param1
e Param2
sarà quindi disponibile in tutte le funzioni gen_server callback.
Come cita Zed, come start_link
appartiene ad un modulo paramatized, si avrebbe bisogno di fare quanto segue al fine di chiamarlo:
Instance = some_module:new(Param1, Param2),
Instance:start_link().
Trovo che questo sia un particolare brutto stile - il codice che chiama some_module:new/n
deve conoscere il numero e l'ordine dei parametri del modulo. Anche il codice che chiama some_module:new/n
non può vivere nello stesso some_module
. Ciò a sua volta rende più difficile l'aggiornamento a caldo se il numero o l'ordine dei parametri del modulo cambiano. Dovresti coordinare il caricamento di due moduli invece di uno (some_module
e il suo modulo interfaccia/costruttore) anche se potresti trovare un modo per eseguire l'aggiornamento del codice some_module
. In una nota minore, questo stile rende un po 'più difficile l'uso della base di codice per gli usi di some_module:start_link
.
Il metodo consigliato per passare parametri a gen_servers
è esplicitamente tramite gen_server:start_link/3,4
argomenti della funzione e memorizzarli nel valore dello stato si torna dalla ?MODULE:init/1
callack.
-module(good_style).
-record(state, {param1, param2}).
start_link(Param1, Param2) ->
gen_server:start_link(?MODULE, [Param1, Param2], []).
init([Param1, Param2]) ->
{ok, #state{param1=Param1,param2=Param2}}.
Utilizzando questo stile significa che non sarete catturati dalle varie parti del OTP che ancora non supporta completamente i moduli paramatized (una caratteristica nuova e ancora in fase sperimentale). Inoltre, il valore dello stato può essere modificato mentre l'istanza gen_server è in esecuzione, ma i parametri del modulo non possono.
Questo stile supporta anche l'aggiornamento a caldo tramite il meccanismo di modifica del codice. Quando viene chiamata la funzione code_change/3
, è possibile restituire un nuovo valore di stato. Non esiste un modo corrispondente per restituire una nuova istanza del modulo parametrizzata al codice gen_server
.
Vuoi più server di gen utilizzando lo stesso modulo di callback, ognuno con un nome diverso? O più gen_server con lo stesso nome? – Jacob
Più server di gen utilizzando lo stesso modulo di callback. Puoi passare a start_link un nome per registrare "istanze" differenti con. Quando hai una singola istanza, sembra che sia tipico dargli lo stesso nome del modulo, e quindi la tua API pubblica funziona come: some_module: some_function(). ... ma sembra essere solo una comodità. Se registri il gen_server con un nome diverso, non funziona più. Mi piacerebbe finire con qualcosa di simile: 1> Mod: some_function(). 2> Mod1: some_function(). ... dove ogni variabile fa riferimento a diverse istanze del modulo gen_server – mwt
Oppure, in alternativa, mi piacerebbe sapere perché non dovrei preoccuparmene. Ogni intro di gen_server che ho visto imposta un'API piuttosto che usare solo giga/chiamate gen_server.Essendo nuovo di Erlang, mi aspettavo di poter clonare facilmente molti processi e sono sorpreso che la funzionalità API si interrompa non appena si rinomina il proprio gen_server. – mwt