Reputation: 1351
I looked at some Elixir projects, and saw code like that:
value = Dict.get(options, :key)
Is there a way to make it shorter and leverage the
dispatching/protocols? It seems like there are some statements like
import
, use
, require
in Elixir.
So it seem like it should be possible to write short code and let the compiler to figure out should it use Dict.get or 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
Does such approach works in Elixir? I.e. is it possible to write short
and compact code instead of long fully prefixed names like
A.B.C.do_something
?
Upvotes: 3
Views: 1464
Reputation: 15293
You could also use a combination of import :only with import :except to get the behavior you're looking for. Check here for more details.
EDIT:
Another possible approach occurs to me. You could also create a shorter name via an anonymous function. Something like this:
dget = &(Dict.get/2)
sget = &(String.get/2)
Then your sample code would look like this:
value = dget.(options, :key)
char = sget.("some-string", 2)
While this would, of course, work I think it's probably still not what you're looking for. I add this to my answer solely for others who may run across this Q & A to help to give a more complete answer about possible alternatives.
Upvotes: 2
Reputation: 9079
You can definately write short,compact code using alias. Just make sure you dont confuse yourself. Check the offical documentation
iex(1)> alias Enum, as: E
nil
iex(2)> E.reduce [1,2,3,4], &(&1+&2)
10
As for the first part of your question. When you import modules, conflicts will show ambiguous error.For example
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
So make sure you import only useful functions from a module.using the only
keyword. Another good option would be to take advantage of lexical scoping in import. Where you can specify where you want to use the imports and only that part will be effected. Here is an example
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
Alternatively protocol could be thing you are looking for.The docs will tell you what you need to know, i'l put up a short summary here.
defprotocol Get do
@doc "Returns the data,for given key"
def get(data,key)
end
You can then implement it for whatever type you require
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
Upvotes: 4