29

I can define named functions in modules just fine, but I haven't yet got the hang of it for use in the iex> or ex> consoles.

I keep getting the following error when I try to run the def command:

(ArgumentError) cannot invoke def/2 outside module

pprime.exs

IO.puts "initial division test"

defmodule Expand do
    def transform(myvar) do
        8 * myvar + 3;
    end
end

div2 = fn inputnum ->
  [:a, inputnum/2.0, inputnum/3, inputnum/5.0, inputnum/7]
end

output = div2.(20.1)

I can run this with elixir just fine, as follows:

$ elixir pprime.exs

However, in the console, I can't seem to do any such thing:

Erlang/OTP 17 [erts-6.3] [source] [64-bit] [async-threads:10] [kernel-poll:false]

Interactive Elixir (1.0.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> def transform(myvar) do 8 * myvar + 3; end
** (ArgumentError) cannot invoke def/2 outside module
    (elixir) lib/kernel.ex:3556: Kernel.assert_module_scope/3
    (elixir) lib/kernel.ex:2816: Kernel.define/4
    (elixir) expanding macro: Kernel.def/2
    (elixir) iex:1: :elixir_compiler.__FILE__/2

How can I define a named function in the Elixir console?

Is this even possible?

Do I need to create a special module for using in the Elixir console?

Nathan Basanese
  • 8,475
  • 10
  • 37
  • 66

2 Answers2

33

You can't define a named function in the Elixir console.

At least not without wrapping it in a defmodule. See greggreg's alternative answer

Long answer: All code in Elixir exist inside modules since many Elixir features, like hot code swapping, relies on having modules as the code container. That's why you can't define functions outside modules (there is no global, mutable namespace they could be added to).

An alternative would be to use an anonymous function which does not need a module:

mylambda = fn(x) -> x + 1 end

And then calling it like mylambda.(2) resulting in 3. Remember the dot.

voxobscuro
  • 2,132
  • 1
  • 21
  • 45
José Valim
  • 50,409
  • 12
  • 130
  • 115
27

You could define the module in iex. Copy and paste works just fine:

iex(1)> defmodule Expand do
...(1)>     def transform(myvar) do
...(1)>         8 * myvar + 3;
...(1)>     end
...(1)> end
iex(2)> Expand.transform(12)
99
iex(3)> defmodule Expand do
...(3)>     def transform(myvar) do
...(3)>         3 * myvar + 5
...(3)>     end
...(3)> end
iex:3: warning: redefining module Expand
iex(4)> Expand.transform(12)
41
greggreg
  • 11,945
  • 6
  • 37
  • 52
  • 18
    Or if you don't want to define entire module, you can use anonymous functions: `transform = fn(myvar) -> 8 * myvar + 3 end` and then `transform.(5)` – tkowal Feb 11 '15 at 13:35