Flat namespace but separate files ?

637 views
Skip to first unread message

mraptor

unread,
Oct 6, 2015, 6:05:17 PM10/6/15
to elixir-lang-talk
Is there a way to define a module in multiple files, so that I have "flat"-namespace, but split the code in different files.
I'm talking something along the lines of simple include, where the files are just concatenated before compilation.

"import" wont work because it introduces dependencies/structure. "use" is from what it seems for manual importation via __using__. "require" is primary for macros. "alias" don't alias afaik to the host-module-name itself.

PS>
I have been always confused by the import/use/require semantics in Elixir. (I'm not saying they are wrong, just I've been confused because I come from Perl, where do/require/use:import() seemed to me very natural grading from simple to more complex behaviour in Elixir they seem sematically different).

Ben Wilson

unread,
Oct 6, 2015, 6:42:59 PM10/6/15
to elixir-lang-talk
Pretty sure the answer is no, modules are only always defined in a single file. Macros (often __using__) can be used to inject additional content inside a module at compile time, but you would not want to split up a module in that fashion.

If your module is too large or complicated to fit in a single module consider splitting it up into additional modules according to some logical subset of functionality. Also note you can do

defmodule Bar do
  def baz(), do: "baz"
end

defmodule Foo do
  defdelegate baz(), to: Bar
end

Now you can call Foo.baz(). Still, I wouldn't break up a big module into 3 modules and stick a ton of defdelegate calls at the top.

WRT the import/use/require:

`import Foo`: Allow some subset of the functions exported by foo (adjustable with arguments) to be called without needing to specify the module. Foo.bar() calls become simply bar().

`use Foo`: This calls the __using__ macro defined inside Foo. This gives you quite a lot of options, as you're basically just injecting content into the module body.

`require Foo`: Allows you to explicitly call macros defined in Foo. You cannot make Foo.bar() calls anywhere in the current module without requiring or importing Foo.

Booker Bense

unread,
Oct 6, 2015, 9:24:22 PM10/6/15
to elixir-lang-talk


On Tuesday, October 6, 2015 at 3:05:17 PM UTC-7, mraptor wrote:
Is there a way to define a module in multiple files, so that I have "flat"-namespace, but split the code in different files.
I'm talking something along the lines of simple include, where the files are just concatenated before compilation.


No, there's no straightforward way to do this. I can think of a couple evil ways. 

As far as import, require, use here's the way I think of it. 

import Foo - You're importing the name space, you're going to call Foo.func1 as func1 in your code. 

require Foo - You need the Foo module to be loaded into the BEAM for your code to work, you're going to use Foo.func1 in your code. 
                      if Foo.func1 is a macro, you definitely need to require it. Mix does all of this for you at runtime for regular functions,
                     but at compile time,( when you use macros) it has to be specified. 

use Foo -  Does the same thing as require Foo, but also calls the __using__ macro in the module you are using. This is to
                 define code IN THE CALLING module from the called module. 
 

                 The closet analogue to this I can think of is Ruby modules that consist of just functions that you can include in 
                  any object, but it's not exactly the same. 

- Booker c. Bense

hen...@nyh.se

unread,
Oct 14, 2015, 4:32:01 PM10/14/15
to elixir-lang-talk
On Wednesday, October 7, 2015 at 3:24:22 AM UTC+2, Booker Bense wrote:
use Foo -  Does the same thing as require Foo, but also calls the __using__ macro in the module you are using. This is to
                 define code IN THE CALLING module from the called module. 
 

                 The closet analogue to this I can think of is Ruby modules that consist of just functions that you can include in 
                  any object, but it's not exactly the same. 

If you want a Ruby analogue (though the original poster mentioned Perl), Elixir's "use" is quite similar to Ruby's "Module.included": http://ruby-doc.org/core-2.2.0/Module.html#method-i-included
Reply all
Reply to author
Forward
0 new messages