2016-01-03 11 views
6

Si supponga di avere due moduli a.erl e b.erl. Entrambi i moduli contengono le stesse funzioni (in Java direi "entrambe le classi implementano la stessa interfaccia"). Nel modulo "c.erl" Voglio avere una funzione che restituirà modulo "a" o "b" (dipende dal parametro)Come chiamare dinamicamente un modulo in Erlang?

Ecco quello che voglio avere nel modulo c.erl

-module(c) 

get_handler(Id) -> 

% if Id == "a" return a 

% if Id == "b" return b 

test() -> 

get_handler("a"):some_function1("here were go for a"), 

get_handler("a"):some_function2("aaaa"), 

get_handler("b"):some_function1("here we go for b") 

Come posso fare questo lavoro? Sono relativamente nuovo a Erlang e non so come farlo. In Java sarebbe molto ovvio, perché si restituisce solo una nuova istanza della classe.

+0

Non sono sicuro di aver capito questa domanda dal modo in cui è scritta. Non importeresti semplicemente come: -import (Module, [Function1/Arity, ..., FunctionN/Arity]). 'E poi chiamerai' a: some_function/arity' o 'b: some_function/arity'? –

+0

Non voglio avere chiamate diverse nelle istruzioni modulo "c" o "if". Voglio che lo stesso codice che chiamerà funzioni dipenda da cosa restituisce get_handler.Nel mio esempio get_handler sceglie tra "a" e "b", ma potrebbero esserci molti più moduli tra cui scegliere. – cactus

risposta

7

Basta avere get_handler/1 ritorno il nome del modulo come un atomo, e quindi utilizzarlo per chiamare la funzione desiderata:

(get_handler("a")):some_function2("aaaa"), 
(get_handler("b")):some_function1("here we go for b"). 

Nota che è necessario parentesi intorno alla chiamata a get_handler/1 in questo caso.

una semplice versione di get_handler/1 per i moduli a e b potrebbe essere:

get_handler("a") -> a; 
get_handler("b") -> b. 
+0

Grazie mille per la risposta. È esattamente ciò di cui ho bisogno. Il mio problema è stato risolto. – cactus

5

Se si dispone di un atomo in una variabile è possibile utilizzarlo come un nome del modulo.

Quindi, è possibile definire c:get_handler/1 come questo:

get_handler("a") -> a; 
get_handler("b") -> b. 

tuo c:test/0 sembra ok, tranne che avete bisogno di parentesi in più, in questo modo:

test() -> 
    (get_handler("a")):some_function1("here were go for a"), 
    (get_handler("a")):some_function2("aaaa"), 
    (get_handler("b")):some_function1("here we go for b"). 

Poi in moduli a e b solo definire un some_function1/1 e some_function/2, ad esempio:

some_function1(Str) -> 
    io:format("module ~s function some_function1 string ~s~n", [?MODULE, Str]). 

some_function2(Str) -> 
    io:format("module ~s function some_function2 string ~s~n", [?MODULE, Str]). 

Edit: Si dovrebbe forse anche definire un comportamento se avete intenzione di fare questo genere di cose BTW, il che significherebbe che si dichiarano in moduli a e b qualcosa di simile:

-behaviour(some_behaviour). 

quindi creare modulo some_behaviour qualcosa di simile:

-module(some_behaviour). 
-callback some_function1 (String :: string()) -> ok . 
-callback some_function2 (String :: string()) -> ok . 

questo significa qualsiasi modulo come a e b che dichiarano di supportare il comportamento some_behaviour deve definire quelle funzioni, e il compilatore parlerà se non lo fanno. I tipi di parametri e il valore di ritorno sono anche definiti qui per l'analisi statica, ecc.

+0

Grazie mille per la risposta. È esattamente ciò di cui ho bisogno. Il mio problema è stato risolto. – cactus

Problemi correlati