2015-11-05 77 views
3

我看了一些藥劑項目,看到這樣的代碼:Elixir無模塊前綴函數?

value = Dict.get(options, :key) 

有沒有辦法把它縮短,並充分利用 調度/協議?似乎在Elixir中有一些陳述如 import,use,require

所以它看起來像它應該是可以寫的短代碼,讓 編譯器弄清楚應該用它Dict.get或String.get:

import Dict, String 

# Getting :key from the Dict. 
value = get options, :key 

# Getting the second char from the String 
char = get "some-string", 2 

難道這樣的做法在工作仙丹?即是否有可能寫短 和緊湊的代碼,而不是長的完全前綴名稱,如 A.B.C.do_something

+0

你想要的是類型推斷。即使在支持這種語言的語言(主要是ML族語言)中,類型註釋有時也是必需的。我的意思是說,即使是在類型推斷的語言中,你可能不得不做類似於Dict.get或String.get的事情。而且,雖然較短的代碼是一個很好的目標,但其他開發人員能夠閱讀代碼也是一個重要目標。從這個角度來看,強制消歧並不完全是一件壞事。 –

回答

3

您可以使用別名來確定地寫出短而緊湊的代碼。只要確保你不會迷惑自己。檢查offical documentation

iex(1)> alias Enum, as: E 
nil 
iex(2)> E.reduce [1,2,3,4], &(&1+&2) 
10 

至於你的問題的第一部分。當您導入模塊,衝突會顯示曖昧error.For例如

iex(1)> import Map, only: [delete: 2] 
iex(5)> delete %{a: 4,b: 5}, :a 
iex(6)> import List, only: [delete: 2] 
iex(8)> delete %{a: 4,b: 5}, :a  
** (CompileError) iex:8: function delete/2 imported from both List and Map, call is ambiguous 
    (elixir) src/elixir_dispatch.erl:111: :elixir_dispatch.expand_import/6 
    (elixir) src/elixir_dispatch.erl:82: :elixir_dispatch.dispatch_import/5 

所以確保你從一個module.using的only關鍵字僅導入有用的功能。另一個好的選擇是利用import中的詞彙範圍。您可以在哪裏指定要使用導入的位置,並且只有該部分會生效。下面是一個例子

defmodule Math do 
    def some_function do 
    import List, only: [duplicate: 2] 
    duplicate(:ok, 10) 
    end 

    def other_function do 
    duplicate(:ok, 10)#this will show error since import is only present inside some_function 
    end 
end 

或者protocol可能是你正在尋找for.The文檔會告訴你,你需要知道的事情,i'l提出了一個簡短的總結在這裏。

defprotocol Get do 
    @doc "Returns the data,for given key" 
    def get(data,key) 
end 

然後就可以實現它爲任何類型你需要

defimpl Get, for: Map do 
    def get(data,key), do: Map.get(data,key) 
end 

defimpl Get, for: Keyword do 
    def get(data,key), do: Keyword.get(data,key) 
end 

defimpl Blank, for: Any do 
    def blank?(data,key), do: raise(ArgumentError, message: "Give proper type for key") 
end 
+0

很傷心,我擔心它會這樣。 '別名'不能解決問題,我想要使用多態(或者在FP中調用方法調度/協議)。重要的是,如果我應該從Enum(或E)或Dict(或D)中獲得「get」方法,我希望免於回憶。 –

+2

我很確定,因爲它是一種動態類型的語言,所以在elixir中不會有可能,所以Elixir中的所有類型都是在運行時推斷出來的。但有些東西叫做協議,它可以工作。 http://elixir-lang.org/getting-started/protocols.html – coderVishal

+0

謝謝,我會檢查出來。雖然人們不使用Protocols ...似乎很奇怪,但我已經檢查過幾個存儲庫,並且似乎所有人都使用'A.B.C.some_function'表達式。 –

2

您也可以使用進口的組合:只與進口:除了讓你正在尋找的行爲。查詢here瞭解更多詳情。


編輯:

另一種可能的方法發生在我身上。你也可以通過匿名函數創建一個較短的名字。事情是這樣的:

dget = &(Dict.get/2) 

sget = &(String.get/2) 

那麼你的示例代碼應該是這樣的:

value = dget.(options, :key) 

char = sget.("some-string", 2) 

儘管這當然會工作,我認爲它可能仍然不是你要找的東西。我將其添加到我的答案中,僅供其他可能遇到此問題的人解答,以幫助提供有關可能替代方案的更全面答案。