Elixirの対話モードでIEx Helpersの動作を確認してみた

# 概要
Elixirの対話モードでIEx Helpersの動作を確認してみました。以下のページを参考にしました。

https://elixirschool.com/ja/lessons/basics/iex_helpers

# 対話モードで実行
以下のコマンドを実行しました。
```
$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Map.
...(1)> Map
Map       MapSet    
...(1)> Map.[TABを押下]
delete/2             drop/2               equal?/2             
fetch!/2             fetch/2              from_struct/1        
get/2                get/3                get_and_update!/3    
get_and_update/3     get_lazy/3           has_key?/2           
keys/1               merge/2              merge/3              
new/0                new/1                new/2                
pop!/2               pop/2                pop/3                
pop_lazy/3           put/3                put_new/3            
put_new_lazy/3       replace!/3           replace/3            
split/2              take/2               to_list/1            
update!/3            update/4             values/1             

...(1)> Map.
```

以下のファイルを作成しました。
```.iex.exs
defmodule IExHelpers do
  def whats_this?(term) when is_nil(term), do: "Type: Nil"
  def whats_this?(term) when is_binary(term), do: "Type: Binary"
  def whats_this?(term) when is_boolean(term), do: "Type: Boolean"
  def whats_this?(term) when is_atom(term), do: "Type: Atom"
  def whats_this?(_term), do: "Type: Unknown"
end
```

以下のコマンドを実行しました。
```
$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> IExHelpers.whats_this?("a string")
"Type: Binary"
iex(2)> IExHelpers.whats_this?(%{})
"Type: Unknown"
iex(3)> IExHelpers.whats_this?(:test)
"Type: Atom"
iex(4)> 


iex(4)> h Enum

                                      Enum                                      

Provides a set of algorithms to work with enumerables.

In Elixir, an enumerable is any data type that implements the Enumerable
protocol. Lists ([1, 2, 3]), Maps (%{foo: 1, bar: 2}) and Ranges (1..3) are
common data types used as enumerables:

    iex> Enum.map([1, 2, 3], fn x -> x * 2 end)
    [2, 4, 6]
    
    iex> Enum.sum([1, 2, 3])
    6
    
    iex> Enum.map(1..3, fn x -> x * 2 end)
    [2, 4, 6]
    
    iex> Enum.sum(1..3)
    6
    
    iex> map = %{"a" => 1, "b" => 2}
    iex> Enum.map(map, fn {k, v} -> {k, v * 2} end)
    [{"a", 2}, {"b", 4}]

However, many other enumerables exist in the language, such as MapSets and the
data type returned by File.stream!/3 which allows a file to be traversed as if
it was an enumerable.

The functions in this module work in linear time. This means that, the time it
takes to perform an operation grows at the same rate as the length of the
enumerable. This is expected on operations such as Enum.map/2. After all, if we
want to traverse every element on a list, the longer the list, the more
elements we need to traverse, and the longer it will take.

This linear behaviour should also be expected on operations like count/1,
member?/2, at/2 and similar. While Elixir does allow data types to provide
performant variants for such operations, you should not expect it to always be
available, since the Enum module is meant to work with a large variety of data
types and not all data types can provide optimized behaviour. 

Finally, note the functions in the Enum module are eager: they will traverse
the enumerable as soon as they are invoked. This is particularly dangerous when
working with infinite enumerables. In such cases, you should use the Stream
module, which allows you to lazily express computations, without traversing
collections, and work with possibly infinite collections. See the Stream module
for examples and documentation.

iex(5)> h Map

                                      Map                                       

Maps are the "go to" key-value data structure in Elixir.

Maps can be created with the %{} syntax, and key-value pairs can be expressed
as key => value:

    iex> %{}
    %{}
    iex> %{"one" => :two, 3 => "four"}
    %{3 => "four", "one" => :two}

Key-value pairs in a map do not follow any order (that's why the printed map in
the example above has a different order than the map that was created).

Maps do not impose any restriction on the key type: anything can be a key in a
map. As a key-value structure, maps do not allow duplicated keys. Keys are
compared using the exact-equality operator (===/2). If colliding keys are
defined in a map literal, the last one prevails.

When the key in a key-value pair is an atom, the key: value shorthand syntax
can be used (as in many other special forms):

    iex> %{a: 1, b: 2}
    %{a: 1, b: 2}

If you want to mix the shorthand syntax with =>, the shorthand syntax must come
at the end:

    iex> %{"hello" => "world", a: 1, b: 2}
    %{:a => 1, :b => 2, "hello" => "world"}

Keys in maps can be accessed through some of the functions in this module (such
as Map.get/3 or Map.fetch/2) or through the map[] syntax provided by the Access
module:

    iex> map = %{a: 1, b: 2}
    iex> Map.fetch(map, :a)
    {:ok, 1}
    iex> map[:b]
    2
    iex> map["non_existing_key"]
    nil

To access atom keys, one may also use the map.key notation. Note that map.key
will raise a KeyError if the map doesn't contain the key :key, compared to
map[:key], that would return nil.

    map = %{foo: "bar", baz: "bong"}
    map.foo
    #=> "bar"
    map.non_existing_key
    ** (KeyError) key :non_existing_key not found in: %{baz: "bong", foo: "bar"}

> Note: do not add parens when accessing fields, such as in data.key(). If
> parenthesis are used, Elixir will expect data to be an atom representing a
> module and attempt to call the function key/0 in it.

The two syntaxes for accessing keys reveal the dual nature of maps. The
map[key] syntax is used for dynamically created maps that may have any key, of
any type. map.key is used with maps that hold a predetermined set of atoms
keys, which are expected to always be present. Structs, defined via
defstruct/1, are one example of such "static maps", where the keys can also be
checked during compile time.

Maps can be pattern matched on. When a map is on the left-hand side of a
pattern match, it will match if the map on the right-hand side contains the
keys on the left-hand side and their values match the ones on the left-hand
side. This means that an empty map matches every map.

    iex> %{} = %{foo: "bar"}
    %{foo: "bar"}
    iex> %{a: a} = %{:a => 1, "b" => 2, [:c, :e, :e] => 3}
    iex> a
    1

But this will raise a MatchError exception:

    %{:c => 3} = %{:a => 1, 2 => :b}

Variables can be used as map keys both when writing map literals as well as
when matching:

    iex> n = 1
    1
    iex> %{n => :one}
    %{1 => :one}
    iex> %{^n => :one} = %{1 => :one, 2 => :two, 3 => :three}
    %{1 => :one, 2 => :two, 3 => :three}

Maps also support a specific update syntax to update the value stored under
existing atom keys:

    iex> map = %{one: 1, two: 2}
    iex> %{map | one: "one"}
    %{one: "one", two: 2}

When a key that does not exist in the map is updated a KeyError exception will
be raised:

    %{map | three: 3}

The functions in this module that need to find a specific key work in
logarithmic time. This means that the time it takes to find keys grows as the
map grows, but it's not directly proportional to the map size. In comparison to
finding an element in a list, it performs better because lists have a linear
time complexity. Some functions, such as keys/1 and values/1, run in linear
time because they need to get to every element in the map.

Maps also implement the Enumerable protocol, so many functions to work with
maps are found in the Enum module. Additionally, the following functions for
maps are found in Kernel:

  • map_size/1

iex(6)> h i

                              def i(term \\ v(-1))                              

Prints information about the data type of any given term.

If no argument is given, the value of the previous expression is used.

## Examples

    iex> i(1..5)

Will print:

    Term
      1..5
    Data type
      Range
    Description
      This is a struct. Structs are maps with a __struct__ key.
    Reference modules
      Range, Map

iex(7)> t Map
@type key() :: any()

@type value() :: any()

iex(8)>
```

# まとめ
何かの役に立てばと。