2015-11-22 16 views
23

Trong Ruby, nếu một định nghĩa hằng số trong các lớp, chúng sẽ định nghĩa chúng bằng tất cả các mũ. Ví dụ:Làm thế nào để bạn xác định các hằng số trong các mô-đun Elixir?

class MyClass 
    MY_FAVORITE_NUMBER = 13 
end 

Bạn làm điều này trong Elixir như thế nào? Và nếu không có tương đương như vậy tồn tại, làm thế nào để bạn có được xung quanh vấn đề số ma thuật trong Elixir?

Trả lời

25

Bạn có thể thêm vào trước tên biến của bạn với @:

defmodule MyModule do 
    @my_favorite_number 13 
end 

Sau đây là các docs

+1

nhưng @my_favorite_num không thể truy cập được từ bên ngoài mô-đun –

+0

@lfx_cool đúng. nếu bạn muốn truy cập nó từ bên ngoài mô-đun, bạn có thể xác định hàm trả về giá trị của nó: 'def my_favorite_number, do: @ my_favorite_number' – AbM

+2

đó là phương thức getter, nếu chúng ta có phím tắt để thực hiện điều này, ví dụ: attr_reader: my_favorite_number –

4

Elixir module có thể có liên quan đến siêu dữ liệu. Mỗi mục trong siêu dữ liệu được gọi là thuộc tính và được truy cập theo tên của nó. Bạn xác định nó bên trong một mô-đun bằng cách sử dụng @name value. Và được truy cập dưới dạng @name

defmodule Example 
    @site 'StackOverflow' #defining attribute 

    def get_site do 
    @site #access attribute 
    end 
end 

Điều này chỉ hoạt động ở cấp cao nhất của mô-đun và bạn không thể đặt thuộc tính mô-đun bên trong định nghĩa chức năng.

7

Một cách tiếp cận khác để xác định hằng số là phương pháp mà tôi đã thực hiện với các tệp tiêu đề wxErlang. Tức là, bạn có thể chỉ định nghĩa một hàm dòng đơn trả về giá trị hằng số cho bạn. Cũng giống như vậy:

def wxHORIZONTAL, do: 4 
    def wxVERTICAL, do: 8 
    def wxBOTH, do: (wxHORIZONTAL ||| wxVERTICAL) 

và đây là một ví dụ khác từ cùng một mã nguồn:

# From "defs.h": wxDirection 
    def wxLEFT, do: 16 
    def wxRIGHT, do: 32 
    def wxUP, do: 64 
    def wxDOWN, do: 128 
    def wxTOP, do: wxUP 
    def wxBOTTOM, do: wxDOWN 
    def wxNORTH, do: wxUP 
    def wxSOUTH, do: wxDOWN 
    def wxWEST, do: wxLEFT 
    def wxEAST, do: wxRIGHT 
    def wxALL, do: (wxUP ||| wxDOWN ||| wxRIGHT ||| wxLEFT) 

Như bạn có thể nhìn thấy nó làm cho nó dễ dàng hơn một chút để xác định một hằng số về liên tục khác. Và khi tôi muốn những hằng số trong một mô-đun khác nhau, tất cả những gì tôi cần làm là require WxConstants ở đầu mô-đun. Điều này giúp xác định một hằng số ở một nơi dễ dàng hơn và sử dụng nó ở một số nơi khác - giúp rất nhiều với DRY.

Nhân tiện, bạn có thể xem repo here nếu bạn tò mò.

Như tôi đã nói, tôi thêm câu trả lời này chủ yếu vì mục đích hoàn chỉnh.

+0

Điều đó thật tuyệt, nhưng đôi khi tôi muốn một hằng số được tính toán giá trị, mà dường như dẫn xuống lỗ thỏ của chức năng ghi nhớ http://stackoverflow.com/questions/35465306/how-to-create-a-global-variable-in-elixir-module/35468186#35468186. Hữu ích để biết về trường hợp cần thiết. –

+0

Tôi không chắc chắn những gì bạn có nghĩa là _computed_value _-- sự khác biệt giữa những gì bạn có nghĩa là bằng giá trị tính toán và, ví dụ, 'wxALL' ở trên? –

+0

'wxALL' là một OR của hằng số, trong khi những gì tôi đã nghĩ đến là một cuộc gọi phương thức, nói như' Time.now'. –

1

tôi muốn thêm làm thế nào tôi đã bắt đầu làm hằng, đó là tương tự như câu trả lời @Onorio Catenacci của, nhưng sử dụng trích dẫn:

defmodule IbGib.Constants do 

    @doc """ 
    Use this with `use IbGib.Constants, :ib_gib` 
    """ 
    def ib_gib do 
    quote do 
     defp delim, do: "^" 
     defp min_id_length, do: 1 
     # etc... 
    end 
    end 

    @doc """ 
    Use this with `use IbGib.Constants, :error_msgs` 
    """ 
    def error_msgs do 
    quote do 
     defp emsg_invalid_relations do 
     "Something about the rel8ns is invalid. :/" 
     end 
     # etc... 
    end 
    end 

    @doc """ 
    When used, dispatch to the appropriate controller/view/etc. 
    """ 
    defmacro __using__(which) when is_atom(which) do 
    apply(__MODULE__, which, []) 
    end 
end 

Và sau đó bạn sử dụng nó như thế này ở phía trên cùng của module, nơi bạn muốn tiêu thụ chúng:

use IbGib.Constants, :ib_gib # < specifies only the ib_gib constants 
use IbGib.Constants, :error_msgs 

# ... then in some function 
Logger.error emsg_invalid_relations 

Tôi nhận được điều này với cách Phoenix nhập khẩu/sử dụng mệnh đề với MyApp.Web. Tôi không ở đâu gần một chuyên gia Elixir, nhưng với phương pháp này, bạn có thể nhập chỉ những hằng số mà bạn muốn và bạn không cần phải thêm tiền tố cho chúng với bất kỳ sự sắp xếp/sắp xếp tên nào. Bằng cách này, bạn có thể chọn và chọn từng nhóm hằng số một cách dễ dàng.

Với các hàm thẳng, (tôi nghĩ) bạn sẽ phải chia chúng thành nhiều mô-đun và sau đó nhập mô-đun.

Tôi không biết các chi nhánh tối ưu hóa này vs chức năng mô-đun trực tiếp, nhưng tôi nghĩ rằng nó là khá gọn gàng - đặc biệt đối với thực tiễn giữa các cách khác nhau để "nhập khẩu" những điều trong Elixir (import, use, alias, require là rất khó hiểu với tư cách là người mới bắt đầu đến từ các ngôn ngữ khác, đây là một tuyên bố đơn using hoặc import).

CHỈNH SỬA: Tôi đã thay đổi các khai báo def không đổi thành defp. Điều này là do khi nhiều mô-đun import tệp hằng số, có một xung đột mơ hồ. Thay đổi chúng thành các chức năng riêng lẻ để tránh xung đột này. Vì vậy, mỗi mô-đun có "bản sao riêng" của chính nó cùng một hằng số.

2

Có lẽ bạn định nghĩa một tập tin hằng mô-đun và trong đó bạn có thể định nghĩa các macro cho điều này như vậy

defmodule MyApp.Constants do 
    defmacro const_a do 
    quote do: "A" 
    end 
end 

Bạn sử dụng nó bằng cách nhập nó vào bất kỳ mô-đun khác

defmodule MyApp.ModuleA do 
    import MyApp.Constants 

    def get_const_a do 
    const_a() 
    end 
end 

Lợi ích cũng là bạn không phải chịu bất kỳ chi phí thời gian chạy nào cũng như lợi thế của việc sử dụng nó trong trường hợp phù hợp với

case something do 
    const_a() -> do_something 
    _ -> do_something_else 
end 
Các vấn đề liên quan