[Proposal] Kernel.is_module?/1

80 views
Skip to first unread message

t...@scalpel.com

unread,
Feb 24, 2018, 9:49:40 PM2/24/18
to elixir-lang-core
It is more difficult than you would expect to check if something in Elixir is a module. I think it is fairly reasonable to build this functionality into the language. The best way I've found to do this is to call a function on the value and rescue from the `UndefinedFunctionError`. This feels a bit hacky to me and I think there should be a more elegant solution.

rap...@eficienciafiscal.com.br

unread,
Feb 24, 2018, 9:55:18 PM2/24/18
to elixir-lang-core
What about Code.ensure_loaded/1 and Code.ensure_compiled/1? They even have versions ending in "?" that just return true/false.

t...@scalpel.com

unread,
Feb 25, 2018, 6:56:25 PM2/25/18
to elixir-lang-core
I've found that in practice both `Code.ensure_loaded` and `Code.ensure_compiled?` are both extremely slow in practice. Also it is not very intuitive that this is what you should be reaching for when attempting to check what type something is. The standard pattern that has been established is the "is_*" in the Kernel. I think we should continue that pattern with modules as well.

Ben Wilson

unread,
Feb 25, 2018, 8:03:40 PM2/25/18
to elixir-lang-core
Can you elaborate on motivating code patterns? Every instance where I've wanted to determine if a specific module is around has been a compile time question for meta-programming purposes, and the `Code.ensure_loaded?` function has worked great for that.

Paul Schoenfelder

unread,
Feb 25, 2018, 8:40:30 PM2/25/18
to elixir-l...@googlegroups.com
If you are doing this at runtime and not compile-time, going through the code server will of course be slow, as well as bottlenecked by the code server process itself, it's a bad idea to go that route. I would want to see the use case here, because I'm convinced there is a better way to solve the problem you are trying to solve.

Paul 

--
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/7e022ca7-4129-47bd-b618-121bde6cf176%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

José Valim

unread,
Feb 26, 2018, 3:04:52 AM2/26/18
to elixir-l...@googlegroups.com
I've found that in practice both `Code.ensure_loaded` and `Code.ensure_compiled?` are both extremely slow in practice. 

Yes, modules are atoms and the only way to know if an atom is actually a module during development is if you check if there is a .beam file on disk.

If you want a quick check if something is a module, then you can use is_atom. There is no way we can provide a performant is_module for development.

In production, if you do releases, then this check is faster since modules are loaded upfront.




José Valim
Founder and 
Director of R&D

On Mon, Feb 26, 2018 at 12:56 AM, <t...@scalpel.com> wrote:
I've found that in practice both `Code.ensure_loaded` and `Code.ensure_compiled?` are both extremely slow in practice. Also it is not very intuitive that this is what you should be reaching for when attempting to check what type something is. The standard pattern that has been established is the "is_*" in the Kernel. I think we should continue that pattern with modules as well.

--
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-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/9f1693ba-3d92-43e3-b48f-b92ec5e1cf8e%40googlegroups.com.

OvermindDL1

unread,
Feb 26, 2018, 5:13:16 PM2/26/18
to elixir-lang-core
For note, for a quick-check if a module exists I just do something like:

```elixir
╰─➤  iex 
Erlang/OTP 20 [erts-9.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:10] [hipe] [kernel-poll:false] 

Interactive Elixir (1.6.1) - press Ctrl+C to exit (type h() ENTER for help) 
iex(1)> function_exported?(String, :module_info, 0) 
true 
iex(2)> function_exported?(SomeModule, :module_info, 0) 
false
```

This *only* works on modules already loaded in memory (which the afore-mentioned `Code.ensure_loaded/1` and `Code.ensure_compiled/1` do in various ways), but in production running in embedded mode that's fine (it's always the case for me, but be aware of your cases).
The reason this works as that the BEAM VM requires a `module_info/0` function on the BEAM module as it uses it for various things, so it's easy just to test for the existence of this function.

You can always try calling `blahmodule.module_info()` and catch the exception if it doesn't exist, this should force loading so should be faster then the `Code.*` calls but still not as fast as `function_exported?` though.

Thomas Cioppettini

unread,
Feb 26, 2018, 5:39:15 PM2/26/18
to elixir-l...@googlegroups.com
OvermindDL1, `function_exported?` was the second method I tried, but the caveat of it needing to be loaded in memory causes too many issues IMO. That is why I settled on the current version I linked to above, which is a more direct variant of what you are suggesting.

--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/T3hCNAKmrds/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/f0514cb7-18d1-4d73-800e-35b56d4322d3%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages