2016-04-17 25 views
6

私はエリクシルと関数型プログラミング言語には一般的にはかなり新しいです。エリクシール - モジュールの文字列名によるメソッドの呼び出し

エリクシルでは、モジュール名を文字列として指定して、モジュールで特定の関数を呼び出したいとします。

私はかなり私が欲しいものをしており、作業以下の(非常に悪い)のコードを持っているに:

module_name = elem(elem(Code.eval_file("module.ex", __DIR__), 0), 1) 
apply(module_name, :helloWorld, []) 

この(私はそれを理解し、少なくともとして)の(コンパイル済み)モジュールをコンパイル現在のディレクトリにmodule.ex私は2つのタプルの中からモジュール名(Stringではなく、実際にどのデータ型であるか)を抽出し、メソッドhelloWorldを実行します。それはredefining module Balanceのような警告を表示し

  1. は、このコードには二つの問題があります。私は確かにそれが生産で起こることを望んでいません。

  2. AFAIKこのコードはmodule.exをコンパイルします。しかし、module.exは既にコンパイルされてロードされているので、そのようなことは起こりたくありません。

これらのモジュールのメソッドをファイル名で呼び出す必要はありません。モジュール名もokです。しかし、それは動的でなければならない。コマンドラインに "Book"と入力すると、モジュールが存在するかどうかを確認した後、関数Book.helloWorldを呼び出す必要があります。

ありがとうございました。

答えて

9

よく聞いていることは次のとおりです。あなたが尋ねた分だけあなた自身で把握します。 ;)

ただ今apply(String.to_existing_atom("Elixir.Module"), :helloWorld, [])を使用しています。 (おそらく「モジュール」という名前は許可されていません。わかりません)

+2

小型ノート:可能な限り、あなたはto_existing_atom使用する必要があります。原子はゴミ収集されません! –

+0

ありがとう!私は、原子がガベージコレクションされていないことは知らなかった。私の答えを編集します。 – lschuermann

1

また、モジュールの名前はアトムなので、通常String.to_existing_atomは必要ありません。このコードを考えてみましょう:

apply(T,:first,[[1,2,3]]) 
#=> 1 

またはこの例(下記リストはエリクサーListモジュールです):

apply(List,:first,[[1,2,3]]) 
#=> 1 
あなたは、単にこの方法で適用を行うことができます。この場合

defmodule T do 
    def first([]), do: nil 
    def first([h|t]), do: h 
end 

モジュールの名前が分かっていれば、それを文字列として渡して文字列を既存のアトムに変換する必要はありません。単に引用符を使わないで名前を使用します。

+0

はい、それはまったく正しいです。しかし、私の場合、モジュール名を動的にすることが目標でした。もちろん、あなたがモジュールの名前を知っていれば、それもうまくいくでしょう。 – lschuermann

6

モジュールに接頭辞として "Elixir"を付ける必要があることに注意してください。

defmodule Test do 
    def test(text) do 
    IO.puts("#{text}") 
    end 
end 

apply(String.to_existing_atom("Elixir.Test"), :test, ["test"]) 

版画 "テスト" とリターン{:} OK

関連する問題