2009-08-21 13 views
13

Chcę wywołać xyz z nazwą funkcji do wywołania.W języku Erlang, w jaki sposób wywołujesz funkcję dynamicznie?

-module(sample). 
-export([xyz/1]). 

xyz(Name) -> Name(). 

p() -> "you called p". 
g() -> "you called g". 

Ale pojawia się następujący błąd:

1> c(sample.erl). 
./sample.erl:6: Warning: function p/0 is unused 
./sample.erl:7: Warning: function g/0 is unused 
{ok,sample} 
2> sample:xyz('p'). 
** exception error: bad function p 
    in function sample:xyz/1 
3> 
+2

Moja wiedza Erlang jest bliska zeru, ale przypuszczam, że trzeba eksportować p (i ewentualnie g, jeśli chcesz z niego korzystać). – balpha

Odpowiedz

22

Prawdą jest, że trzeba eksportować p i g. Możesz wtedy użyć polecenia/3, aby go wywołać.

erlang:apply(sample, p, []) 

Tylko zabawne wartości można wykorzystywać ze składnią Fun (...). Podajesz wartość atomu. Atom to "zła funkcja", ponieważ komunikat o błędzie jest wyświetlany. Można zrobić coś podobnego do

xyz(p) -> fun p/0; 
xyz(g) -> fun g/0. 

Wtedy śmiało nazwać

Fun = xyz(p), 
Fun() 
+0

Dzięki. Mam teraz: -moduł (próbka). -export ([xyz/1, p/0, g/0]). xyz (Nazwa) -> zastosuj (przykład, nazwa, []). p() -> "zadzwoniłeś p". g() -> "dzwonisz g". i jestem w stanie wykonać: 26> c (sample.erl). {ok, sample} 27> sample: xyz ('p'). "nazwałaś p" 28> sample: xyz (p). "nazwałaś p" 29> sample: xyz ("g"). "Ty nazwałeś g" 30> sample: xyz (g). "Ty nazwałeś g" Ale czy nie istnieje sposób na wyeksportowanie tych funkcji? Nie chcę, aby był widoczny dla użytkowników modułów. Wydaje się, że nie działa również z funkcją apply/2. Oczywiście jestem nowicjuszem erlang – ottodidakt

+1

Twórczo zakodowujesz mapowanie połączeń za pomocą dopasowania do wzorca lub eksportujesz swoje funkcje. – Zed

+0

Jedynym sposobem na "wyciekanie" nieodnotowanej funkcji jest zwrócenie wartości zabawy, która się do niej odnosi. Podobnie jak moja jawna funkcja xyz/1, która zwraca wartość zabawy. – Christian

7

Wzór mecz jest idiom użycia:

-module(sample). 
-export([xyz/1]). 

xyz(p) -> p(); 
xyz(q) -> g(). 

p() -> "you called p". 
g() -> "you called g". 

Jeśli chcesz być dynamiczne można użyć gen_event serwer.

Zasadniczo co to jest serwer, który posiada państwo, które składa się z pary klucz/funkcyjnego tak:

[{p, #func1}, 
{g, #func2}, 
{..., ...}, 
...] 

Można wówczas zasadniczo wiązać zdarzenia do funkcji. (Tam jest, rzecz jasna, nieco więcej niż tylko to.

+1

podczas gdy jest to technicznie jeden sposób, aby to zrobić Myślę, że pytanie jest bardziej dostosowane do mechaniki w języku, aby dynamicznie wywoływać funkcję. Funkcja zastosowania jest odpowiedzią, której szuka. –

8
-module(sample). 
-export([xyz/1, p/0, g/0]). 

xyz(Name) -> ?MODULE:Name(). 

p() -> "you called p". 
g() -> "you called g". 


1> sample:xyz(p). 
"you called p" 
+1

To całkiem fajne. Gdzie mogę przeczytać o "? MODULE"? Teraz, gdybyśmy tylko mogli pozbyć się eksportu p i q. – ottodidakt

+0

Oto wstępnie zdefiniowane makra: http://erlang.org/doc/reference_manual/macros.html#7.3. Niestety Erlang ma tylko "publiczną" i "prywatną" widoczność, ale nie ma chronionego i chronionego pakietu. Więc albo wyeksportuj go, albo "zakodowuj" połączenia. – Zed

+1

Ale dlaczego nie muszę eksportować w przypadku statycznie powiązanego xyz (Name) -> p(). i wymagane do eksportu, gdy jest dynamicznie związany? Myśląc w kategoriach "prywatnej" widoczności, jestem w prywatnym zasięgu, prawda? – ottodidakt

0

Innym sposobem, aby spojrzeć na to, że jest (w zależności od problemu jesteś rozwiązywania) dynamicznych wywołań funkcji jest niekoniecznie Właściwe podejście: biorąc pod uwagę, że procesy i przekazywanie wiadomości są sposobem w jaki organizujesz swój kod w Erlang, ponieważ jest to "język zorientowany na współbieżność", może mógłbyś po prostu użyć przekazu wiadomości z selektywnym odbiorem zamiast naśladować idiomy języka sekwencyjnego? Wyślij wiadomość za to, co chcesz, i uzyskaj niestandardową odpowiedź na podstawie tego, że chodzi o wynik każdej funkcji, a nie o samą funkcję (plus jest elastyczność i skalowalność przekazywania wiadomości, itp.)

Alt procesy hough nie są całkowicie darmowe w porównaniu do wywoływania z modułu bibliotecznego, procesy na poziomie Erlanga są tanie pod względem ilości zanieczyszczeń (szczególnie jeśli komunikacja komunikacyjna jest w tym samym węźle). Nie są to procesy na poziomie systemu operacyjnego. Narzut byłby porównywalny (lub lepszy) z dynamicznymi wywołaniami funkcji i tworzeniem obiektów w cięższych językach skryptowych.

1

Najprostszym sposobem jest wypróbowanie eksportu p i g wraz z Xyz.

-export([xyz/1, p/0,g/0]). 

Po wyeksportowaniu funkcji P i G mogą być nazywane w następujący sposób:

1> sample:xyz(fun sample:p/0). 
"you called p" 
2> sample:xyz(fun sample:g/0). 
"you called g" 
Powiązane problemy