Proposal: Add 'export' macro

101 views
Skip to first unread message

Matt Widmann

unread,
Apr 26, 2015, 12:20:57 PM4/26/15
to elixir-l...@googlegroups.com
I find it difficult to divide my modules into different concerns without having to change client code like you would do with ActiveSupport::Concern in Ruby.

For example, if I have a main module which others use like:

defmodule MyApp do
 
def fun_1 do
   
# implementation or calling another module
 
end

 
def fun_2 do
   
# implementation or calling another module
  end

 
# ...
 
 
def fun_n do
    # implementation or calling another module
  end
end

However if I want to divide this up into separate modules to keep the internal code cleaner like:

defmodule MyApp do
 
import Functionality1
 
import Functionality2
 
import Functionality3
end

Then `MyApp.fun_1` no longer works. In order to move code out into separate modules but still have things work the same, one must do something like the following:

defmodule MyApp do
 
alias Functionality1, as: F1
 
alias Functionality2, as: F2
 
alias Functionality3, as: F3

 
@inline true
 
def fun_1(arg1, arg2, arg3) do
    F1
.fun_1(arg1, arg2, arg3)
 
end

 
@inline true
  def fun_2(arg1, arg2, arg3) do
    F2
.fun_2(arg1, arg2, arg3)
 
end

 
@inline true
  def fun_3(arg1, arg2, arg3) do
    F3
.fun_3(arg1, arg2, arg3)
 
end

end
 

But now the documentation must be here with this module instead of in the other module where the implementation is located. 

What I propose instead is simply inlining the calls to the other module and copying the documentation within an `export` macro. Like this:

defmodule MyApp do
 
export Functionality1
 
export Functionality2
 
export Functionality3
end

Then `MyApp.fun_1(1,2,3)` works as expected, `h MyApp.fun_1/3` works as expected, but I can easily divide my code into separate concerns without cluttering everything into a single module file.

Effectively, this is the opposite of the `import` functionality. Instead of making those functions available internally within the module, they are available externally through the current module.

Thoughts?



John W Higgins

unread,
Apr 26, 2015, 12:45:32 PM4/26/15
to elixir-l...@googlegroups.com
Kernel.use/2 and __using__/1 are your friends here - it may be the slightest bit more verbose then Ruby but it's certainly the exact same in terms of functionality.

John

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/681dbf0e-5958-4ca6-bfca-0d293a0dc00e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chris McCord

unread,
Apr 26, 2015, 12:49:15 PM4/26/15
to elixir-l...@googlegroups.com
Yes, this is nearly the same as having `use` inject tons of code, which is a pattern you should avoid. It will lead to less obvious and maintainable code, which is the opposite of your goals. The issues with this approach is it make it implicit what is and isn’t exposed as public functions by the module, and it goes N-levels deep. You should check out `defdelegate` as a case-by-case exposure of functions from other modules.

John W Higgins

unread,
Apr 26, 2015, 1:09:32 PM4/26/15
to elixir-l...@googlegroups.com
On Sun, Apr 26, 2015 at 9:48 AM, Chris McCord <ch...@chrismccord.com> wrote:
Yes, this is nearly the same as having `use` inject tons of code, which is a pattern you should avoid. It will lead to less obvious and maintainable code, which is the opposite of your goals. The issues with this approach is it make it implicit what is and isn’t exposed as public functions by the module, and it goes N-levels deep. You should check out `defdelegate` as a case-by-case exposure of functions from other modules.


Thanks Chris, much better answer then my heavy handed nonsense.

John

Matt Widmann

unread,
Apr 26, 2015, 3:10:00 PM4/26/15
to elixir-l...@googlegroups.com
Thanks for the pointers.

defdelegate doesn't forward the documentation. Is that a bug?

José Valim

unread,
Apr 26, 2015, 3:35:21 PM4/26/15
to elixir-l...@googlegroups.com
No, it is not a bug. defdelegate often points to internal modules with the actual implementation which should not be exposed. References the original module directly if you need to.



José Valim
Skype: jv.ptec
Founder and Lead Developer

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages