Elixirのメモ


```
iex(2)> System.cwd
"/Users/N1210A001/Playground"

iex(3)> System.get_env("HOME")
"/Users/N1210A001"

iex(7)> System.cmd("date",[])
{"2015年 6月12日 金曜日 11時18分41秒 JST\n", 0}

iex(8)> pwd
/Users/N1210A001/Playground
:ok
```
---
The `Keyword` type is an Elixir module. But it is implemented as a list of tuple. The `Keyword` module assumes that any value it works on is a list that has been structured a certain way.

```iex
iex(8)> options = [{:width, 72}, {:style, "light"}, {:style, "print"}]
[width: 72, style: "light", style: "print"]
iex(9)> Keyword.get_values options, :style
["light", "print"]
iex(10)> List.last options
{:style, "print"}
```
---
`IO.ANSI.enabled?`
> Checks if ANSI coloring is supported and enabled on this machine.

```
iex(16)> IO.ANSI.enabled?
true
```
---
`Enum.at(collection, n, default \\ nil)`
> Finds the element at the given index (zero-based).
Returns default if index is out of bounds.

```
iex(5)> Enum.at([2,4,6], 0)
2
iex(6)> Enum.at([2,4,6], 2)
6
iex(7)> Enum.at([2,4,6], 10)
nil
iex(8)> Enum.at([2,4,6], 10, :none)
:none

iex(9)> Enum.at({2,4,6}, 1, :none)
** (Protocol.UndefinedError) protocol Enumerable not implemented for {2, 4, 6}
```

`List.update_at`
> リスト特定の場所を更新する。２番目の引数はリストのインデックス範囲外の場合、元のリストを返す.インデックスは0から始まる

```
iex(1)> List.update_at([1,4,9], 1, &(&1*20))
[1, 80, 9]
iex(2)> List.update_at([1,4,9],3, &(&1*20))
[1, 4, 9]
iex(3)> List.update_at([1,4,9],-1, &(&1*20))
[1, 4, 180]
iex(4)> List.update_at([1,4,9],33, &(&1*20))
[1, 4, 9]
```

--
`Stream.with_index(Enumerable.t) :: Enumerable.t`

> Creates a stream where each item in the enumerable will be wrapped in a tuple alongside its index.

```
iex(3)> stream = Stream.with_index([1,2,3,4,5])
#Stream<[enum: [1, 2, 3, 4, 5],
 funs: [#Function<53.29647706/1 in Stream.with_index/1>]]>

iex(4)> Enum.to_list(stream)
[{1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}]

iex(5)> stream = Stream.with_index(1..10)
#Stream<[enum: 1..10, funs: [#Function<53.29647706/1 in Stream.with_index/1>]]>

iex(6)> Enum.to_list(stream)
[{1, 0}, {2, 1}, {3, 2}, {4, 3}, {5, 4}, {6, 5}, {7, 6}, {8, 7}, {9, 8},
 {10, 9}])
```
---

`IO.write(device \\ :erlang.group_leader(), item)`
> Writes the given argument to the given device.
By default the device is the standard output. It returns :ok if it succeeds.



```
iex(1)> IO.write "sample"
sample:ok
iex(2)> IO.write :stderr, "sample"
sample:ok
```
---
scpコマンドでファイルを送る

成功するときに`0`を返す

```
iex(1)> System.cmd("scp", ["attributes.exs", "aws:~"])
{"", 0}
```

失敗するときに`1`を返す

```
iex(12)> System.cmd("scp", ["attributes.exs", "aws:~/path/not/found"])
scp: /home/ec2-user/path/not/found: No such file or directory
{"", 1}
```

ElixirのTaskを利用して、ファイルを送る

```
iex(2)> task = Task.async(fn -> System.cmd("scp", ["foo", "aws:~"]) end)
%Task{pid: #PID<0.58.0>, ref: #Reference<0.0.0.97>}
iex(3)> Task.await(task, 500000)
{"", 0}
```
上のコマンドは500秒のタイムアウト時間が設定されている

---

Elixirでsshを通して，命令を実行する

```
iex(2)> {:ok, conn} = :ssh.connect('localhost', 22, [user: 'wzj', password: '123', silently_accept_hosts: true])
{:ok, #PID<0.74.0>}
iex(3)> {:ok, chan_id} = :ssh_connection.session_channel(conn, :infinity)
{:ok, 0}
iex(4)> success = :ssh_connection.exec(conn, chan_id, 'touch /tmp/elixirssh', :infinity)
:success
iex(5)>
```
---
```
defmodule MyFile do
  @file "case.ex"

  case File.open(@file) do
    { :ok, file} ->
      IO.puts "First line: #{IO.read(file, :line)}"
    { :error, reason } ->
      IO.puts "Failed to open file: #{reason}"
  end
end
```

`@file`のような書き方はElixirでは定数を表している