Does Elixir support introspection to show the origin of the function?

If the import module has several other modules, it may not be obvious where this function came from. For instance:

 defmodule Aimable do import Camera import Gun def trigger do shoot # which import brought it in? end end 

I know that there are ways to minimize such confusion: good names, targeted modules, target imports such as import Gun, only: [:shoot] , etc.

But if I come across such code, is there a way to check Aimable and see the start of the shoot function?

+5
source share
4 answers

You can do it directly:

 # from inside the module; IO.inspect(&Aimable.shoot/0) reveals nothing IO.inspect &shoot/0 #=> &Gun.shoot/0 

check this

Also remember that you cannot have the same function names with the same logic in two different modules and import them as in another module. This will result in an ambiguity error when calling this function.

Another painful way. You can use function_exported? / 3. . Specifications:

function_exported?(atom | tuple, atom, arity) :: boolean

Returns true if the module is loaded and contains a public function with the specified arity, otherwise false.

Examples:

 function_exported?(Gun, :shoot, 0) #=> true function_exported?(Camera, :shoot, 0) #=> false 
+5
source

Use __ENV__

As I found out on another issue , __ENV__ macros provide access to various environmental information , including __ENV__.functions and __ENV__.macros .

__ENV__.functions returns a list of tuples of modules and a list of functions that they provide, for example:

 [{Some.module, [do_stuff: 2]}, {Other.Module, [a_function: 2, a_function: 3]}] 

You can visually view this for shoot or write code to search for it.

+3
source

I am using Elixir 1.1.0, and what you are describing seems to be not allowed. Here is the script (in aimable.ex):

 defmodule Gun do def shoot do IO.puts "Gun Shot" end end defmodule Camera do def shoot do IO.puts "Camera Shot" end end defmodule Aimable do import Camera import Gun def trigger do shoot end end 

Now when I run iex aimable.ex , I get a CompileError

Erlang / OTP 18 [erts-7.1] [source] [64-bit] [smp: 4: 4] [async-threads: 10] [hipe] [kernel-poll: false] [dtrace]

** (CompileError) aimable.ex: 18: the shoot / 0 function is imported from both the camera and Gun, the 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

+1
source

Another potential method (added for completeness):

 defmodule Aimable do import Camera, :only [shoot: 0] import Gun #etc. 

or

 defmodule Aimable do import Camera import Gun, :only [shoot: 0] # etc. 

Then see which one will not compile correctly.

Another way to achieve this.

0
source

Source: https://habr.com/ru/post/1238455/


All Articles