Injecting imports vs function definitions through `__using__/1`

For some reason I can’t understand the two following paragraphs from the docs:

Finally, developers should also avoid defining functions inside the __using__/1 callback, unless those functions are the default implementation of a previously defined @callback or are functions meant to be overridden (see defoverridable/1 ). Even in these cases, defining functions should be seen as a “last resort”.

In case you want to provide some existing functionality to the user module, please define it in a module which will be imported accordingly; for example, ExUnit.Case doesn’t define the test/3 macro in the module that calls use ExUnit.Case , but it defines ExUnit.Case.test/3 and just imports that into the caller when used.

Is it saying it’s better to inject imports rather than full function definitions?

In both cases it doesn’t prevent naming clashes with functions having same name in the caller, right? What is the difference?

I think if you do an import, your stacktraces will be trivially correct? And you’re also not “actually duplicating the code”. If you do hot code reloading (might sound obscure but I think this might be relevant for the hot refresh for phoenix dev mode), if you do an import, it will “do the right thing” and with an import you’re doing a foreign call so it won’t hold on to the old module.

1 Like

One of the reasons not to define a function inside the __using__/1 function is that if you then use that definition 100 times, you will have 100 functions. Whereas if you imported the function there would only be one definition.

1 Like

@axelson What would actually be the negative consequence of this? Code is not duplicated so it is not necessarily a bad design in that sense, but it’s true that functions will be repeatedly created for each use. Are we then talking concretely about memory consumption? Isn’t that insignificant?

I’m not really sure but one drawback that comes to mind would be for example that the project would take longer time to compile?