Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir without prefixing functions with module?

Tags:

elixir

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?

like image 958
Alexey Petrushin Avatar asked Jul 28 '26 07:07

Alexey Petrushin


1 Answers

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
like image 139
coderVishal Avatar answered Aug 03 '26 16:08

coderVishal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!