2016-04-17 19 views
6

Tôi khá mới đối với Elixir và các ngôn ngữ lập trình chức năng nói chung.Elixir - Gọi phương thức trên mô-đun bằng String-name

Trong Elixir, tôi muốn gọi một hàm cụ thể trên Mô-đun, với tên Mô-đun là Chuỗi.

Tôi đã có như sau (rất xấu) mã làm việc, trong đó khá nhiều những gì tôi muốn:

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

này (ít nhất là như tôi hiểu nó) biên dịch (đã được biên soạn) mô-đun của module.ex trong thư mục hiện tại. Tôi đang giải nén tên mô-đun (không phải là một String, không biết dữ liệu loại nó thực sự là gì) trong số hai bộ dữ liệu và chạy phương thức helloWorld trên đó.

Có hai vấn đề với mã này:

  1. Nó in một cảnh báo như redefining module Balance. Tôi chắc chắn không muốn điều đó xảy ra trong sản xuất.

  2. AFAIK mã này biên dịch module.ex. Nhưng như module.ex đã được biên dịch và tải, nó không muốn điều đó xảy ra.

Tôi không cần gọi các phương thức trên các mô-đun này bằng tên tệp, tên mô-đun cũng sẽ ổn. Nhưng nó phải bằng năng động, ví dụ. nhập "Sách" tại dòng lệnh, sau khi kiểm tra xem mô-đun có tồn tại hay không, hãy gọi hàm Book.helloWorld.

Cảm ơn.

Trả lời

9

Vâng, đó là nơi yêu cầu giúp: Bạn sẽ tự mình tìm ra số phút bạn yêu cầu. ;)

Chỉ cần sử dụng apply(String.to_existing_atom("Elixir.Module"), :helloWorld, []) ngay bây giờ. (có thể tên "Mô-đun" không được phép, không biết)

+2

lưu ý nhỏ: bạn nên sử dụng to_existing_atom bất cứ khi nào có thể. Nguyên tử arent rác thu thập! –

+0

Cảm ơn! Tôi không biết rằng các nguyên tử không phải là rác được thu thập. Sẽ chỉnh sửa câu trả lời của tôi. – lschuermann

1

Cũng lưu ý rằng tên của một mô-đun là một nguyên tử để làm String.to_existing_atom thường không cần thiết. Hãy xem xét mã này:

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

Trong trường hợp này bạn chỉ có thể làm như áp dụng theo cách này:

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

Hoặc ví dụ này (Danh sách dưới đây là Elixir List mô-đun):

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

Tôi muốn nói rằng nếu bạn biết tên của mô-đun, không cần phải chuyển nó thành một chuỗi và sau đó chuyển đổi chuỗi thành một nguyên tử hiện có. Đơn giản chỉ cần sử dụng tên mà không có dấu ngoặc kép.

+0

Vâng, đó là hoàn toàn chính xác.Nhưng trong trường hợp của tôi, đó là mục tiêu để làm cho mô-đun năng động. Tất nhiên, nếu bạn biết tên của Module, điều đó cũng sẽ hoạt động. – lschuermann

6

Lưu ý rằng bạn luôn cần tiền tố mô-đun của mình bằng "Elixir".

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

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

in "test" và trả về {: ok}

Các vấn đề liên quan