IElixir - Elixir kernel for Jupyter Project


Google Summer of Code 2015

Developed by Piotr Przetacznik

Mentored by José Valim


References

Getting Started

Basic Types

1          # integer
0x1F       # integer
1.0        # float
true       # boolean
:atom      # atom / symbol
"elixir"   # string
[1, 2, 3]  # list
{1, 2, 3}  # tuple

Basic arithmetic


In [1]:
1 + 2


Out[1]:
3

In [2]:
5 * 5


Out[2]:
25

In [3]:
10 / 2


Out[3]:
5.0

In [4]:
div(10, 2)


Out[4]:
5

In [5]:
div 10, 2


Out[5]:
5

In [6]:
rem 10, 3


Out[6]:
1

In [7]:
0b1010


Out[7]:
10

In [8]:
0o777


Out[8]:
511

In [9]:
0x1F


Out[9]:
31

In [10]:
1.0


Out[10]:
1.0

In [11]:
1.0e-10


Out[11]:
1.0e-10

In [12]:
round 3.58


Out[12]:
4

In [13]:
trunc 3.58


Out[13]:
3

Booleans


In [14]:
true


Out[14]:
true

In [15]:
true == false


Out[15]:
false

In [16]:
is_boolean(true)


Out[16]:
true

In [17]:
is_boolean(1)


Out[17]:
false

In [18]:
is_integer(5)


Out[18]:
true

In [19]:
is_float(5)


Out[19]:
false

In [20]:
is_number("5.0")


Out[20]:
false

Atoms


In [21]:
:hello


Out[21]:
:hello

In [22]:
:hello == :world


Out[22]:
false

In [23]:
true == :true


Out[23]:
true

In [24]:
is_atom(false)


Out[24]:
true

In [25]:
is_boolean(:false)


Out[25]:
true

Strings


In [26]:
"hellö"


Out[26]:
"hellö"

In [27]:
"hellö #{:world}"


Out[27]:
"hellö world"

In [28]:
IO.puts "hello\nworld"


hello
world
Out[28]:
:ok

In [29]:
is_binary("hellö")


Out[29]:
true

In [30]:
byte_size("hellö")


Out[30]:
6

In [31]:
String.length("hellö")


Out[31]:
5

In [32]:
String.upcase("hellö")


Out[32]:
"HELLÖ"

Anonymous functions


In [33]:
add = fn a, b -> a + b end


Out[33]:
#Function<12.90072148/2 in :erl_eval.expr/5>

In [34]:
is_function(add)


Out[34]:
true

In [35]:
is_function(add, 2)


Out[35]:
true

In [36]:
is_function(add, 1)


Out[36]:
false

In [37]:
add.(1, 2)


Out[37]:
3

In [38]:
add_two = fn a -> add.(a, 2) end


Out[38]:
#Function<6.90072148/1 in :erl_eval.expr/5>

In [39]:
add_two.(2)


Out[39]:
4

In [40]:
x = 42
(fn -> x = 0 end).()
x


Out[40]:
42

(Linked) Lists


In [41]:
a = [1, 2, true, 3]


Out[41]:
[1, 2, true, 3]

In [42]:
length [1, 2, 3]


Out[42]:
3

In [43]:
[1, 2, 3] ++ [4, 5, 6]


Out[43]:
[1, 2, 3, 4, 5, 6]

In [44]:
[1, true, 2, false, 3, true] -- [true, false]


Out[44]:
[1, 2, 3, true]

In [45]:
hd(a)


Out[45]:
1

In [46]:
tl(a)


Out[46]:
[2, true, 3]

In [47]:
hd []


** (ArgumentError) "argument error"

In [47]:
[11, 12, 13]


Out[47]:
'\v\f\r'

In [48]:
[104, 101, 108, 108, 111]


Out[48]:
'hello'

In [49]:
'hello' == "hello"


Out[49]:
false

Tuples


In [50]:
{:ok, "hello"}


Out[50]:
{:ok, "hello"}

In [51]:
tuple_size {:ok, "hello"}


Out[51]:
2

In [52]:
tuple = {:ok, "hello"}


Out[52]:
{:ok, "hello"}

In [53]:
elem(tuple, 1)


Out[53]:
"hello"

In [54]:
tuple_size(tuple)


Out[54]:
2

In [55]:
put_elem(tuple, 1, "world")


Out[55]:
{:ok, "world"}

In [56]:
tuple


Out[56]:
{:ok, "hello"}

Lists or tuples?


In [57]:
list = [1|[2|[3|[]]]]


Out[57]:
[1, 2, 3]

In [58]:
[0] ++ list


Out[58]:
[0, 1, 2, 3]

In [59]:
list ++ [4]


Out[59]:
[1, 2, 3, 4]

In [60]:
File.read("LICENSE")


Out[60]:
{:ok, "Copyright 2015 Piotr Przetacznik\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n      http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n"}

In [61]:
File.read("path/to/unknown/file")


Out[61]:
{:error, :enoent}

Other examples


In [62]:
0x1F


Out[62]:
31

In [63]:
a = 25
b = 150
IO.puts(a+b)


175
Out[63]:
:ok

In [64]:
defmodule Math do
  def sum(a, b) do
    a + b
  end
end


Out[64]:
{:module, Math, <<70, 79, 82, 49, 0, 0, 4, 244, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 143, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 3, 104, 2, ...>>, {:sum, 2}}

In [65]:
Math.sum(1, 2)


Out[65]:
3

In [66]:
import ExUnit.CaptureIO
capture_io(fn -> IO.write "john" end) == "john"


Out[66]:
true

In [67]:
?a


Out[67]:
97

In [68]:
<<98>> == <<?b>>


Out[68]:
true

In [69]:
<<?g, ?o, ?\n>> == "go
"


Out[69]:
true

In [70]:
{hlen, blen} = {4, 4}
<<header :: binary-size(hlen), body :: binary-size(blen)>> = "headbody"
{header, body}


Out[70]:
{"head", "body"}

In [71]:
h()


                                  IEx.Helpers                                   

Welcome to Interactive Elixir. You are currently seeing the documentation for
the module IEx.Helpers which provides many helpers to make Elixir's shell more
joyful to work with.

This message was triggered by invoking the helper h(), usually referred to as
h/0 (since it expects 0 arguments).

There are many other helpers available:

  • c/2           — compiles a file at the given path
  • cd/1          — changes the current directory
  • clear/0       — clears the screen
  • flush/0       — flushes all messages sent to the shell
  • h/0           — prints this help message
  • h/1           — prints help for the given module, function or macro
  • l/1           — loads the given module's beam code
  • ls/0          — lists the contents of the current directory
  • ls/1          — lists the contents of the specified directory
  • pwd/0         — prints the current working directory
  • r/1           — recompiles and reloads the given module's source file
  • respawn/0     — respawns the current shell
  • s/1           — prints spec information
  • t/1           — prints type information
  • v/0           — prints the history of commands evaluated in the session
  • v/1           — retrieves the nth value from the history
  • import_file/1 — evaluates the given file in the shell's context

Help for functions in this module can be consulted directly from the command
line, as an example, try:

┃ h(c/2)

You can also retrieve the documentation for any module or function. Try these:

┃ h(Enum)
┃ h(Enum.reverse/1)

To discover all available functions for a module, type the module name followed
by a dot, then press tab to trigger autocomplete. For example:

┃ Enum.

To learn more about IEx as a whole, just type h(IEx).


In [72]:
defmodule KV.Registry do
  use GenServer

  ## Client API

  @doc """
  Starts the registry.
  """
  def start_link(opts \\ []) do
    GenServer.start_link(__MODULE__, :ok, opts)
  end

  @doc """
  Looks up the bucket pid for `name` stored in `server`.

  Returns `{:ok, pid}` if the bucket exists, `:error` otherwise.
  """
  def lookup(server, name) do
    GenServer.call(server, {:lookup, name})
  end

  @doc """
  Ensures there is a bucket associated to the given `name` in `server`.
  """
  def create(server, name) do
    GenServer.cast(server, {:create, name})
  end

  ## Server Callbacks

  def init(:ok) do
    {:ok, HashDict.new}
  end

  def handle_call({:lookup, name}, _from, names) do
    {:reply, HashDict.fetch(names, name), names}
  end

  def handle_cast({:create, name}, names) do
    if HashDict.has_key?(names, name) do
      {:noreply, names}
    else
      {:ok, bucket} = KV.Bucket.start_link()
      {:noreply, HashDict.put(names, name, bucket)}
    end
  end
end


Out[72]:
{:module, KV.Registry, <<70, 79, 82, 49, 0, 0, 14, 164, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 3, 205, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 3, 104, 2, ...>>, {:handle_cast, 2}}

In [73]:
ExUnit.start()


Out[73]:
[#Function<1.26548342/1 in ExUnit.start/1>, #Function<0.16941659/1 in Mix.CLI.main/1>]

In [74]:
defmodule KV.RegistryTest do
  use ExUnit.Case, async: true

  setup do
    {:ok, registry} = KV.Registry.start_link
    {:ok, registry: registry}
  end

  test "spawns buckets", %{registry: registry} do
    assert KV.Registry.lookup(registry, "shopping") == :error

    KV.Registry.create(registry, "shopping")
    assert {:ok, bucket} = KV.Registry.lookup(registry, "shopping")

    KV.Bucket.put(bucket, "milk", 1)
    assert KV.Bucket.get(bucket, "milk") == 1
  end
end


Out[74]:
{:module, KV.RegistryTest, <<70, 79, 82, 49, 0, 0, 14, 84, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 1, 32, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 3, 104, 2, ...>>, {:"test spawns buckets", 1}}