Erlangメモ１


`handle_info/2`
> If the gen_server should be able to receive other messages than requests, the callback function handle_info(Info, State) must be implemented to handle them. Examples of other messages are exit messages, if the gen_server is linked to other processes (than the supervisor) and trapping exit signals.

```erlang
handle_info({'EXIT', Pid, Reason}, State) ->
    ..code to handle exits here..
    {noreply, State1}.
```
---
io_lib:format, float_to_listを使って小数をフォーマット

```erlang
6> F = 5/3.
1.6666666666666667
7> io_lib:format("~.1f", [F]).
["1.7"]
8> io_lib:format("~.2f", [F]).
["1.67"]
9> io_lib:format("~.3f", [F]).
["1.667"]
10> F1 = 5/2.
2.5
11> io_lib:format("~.3f", [F1]).
["2.500"]
14> float_to_list(223.665, [{decimals, 0}]).
"224"
15> list_to_integer(float_to_list(223.665, [{decimals, 0}])).
224
16> float_to_list(223.665, [{decimals, 2}]).
"223.67"
17> float_to_list(5/2, [{decimals, 2}]).
"2.50"
18> list_to_integer(float_to_list(5/2, [{decimals, 0}])).
3

```

----
`mnesia:create_table(employee,[{disc_copies, [node()]}, {attributes, record_info(fields, employee)}])`

テーブルはdisc_copiesと定義される場合，アプリケーション再起動するときにディスクからデータをロードしたいときにwait_for_tables/2を使います．

```erlang
$ erl -mnesia dir '"./Mnesia.Company"'
4> mnesia:start()
5> mnesia:wait_for_tables([employee, dept, project, manager, at_dep, in_proj], 5000).
6> company:select_gender(male).
```

----
`calendar:datetime_to_gregorian_seconds(DateTime) -> Seconds`
> This function computes the number of gregorian seconds starting with year 0 and ending at the given date and time.

```erlang
3> calendar:datetime_to_gregorian_seconds({{2015, 2, 9}, {16,32, 12}}).
63590718732

4> calendar:datetime_to_gregorian_seconds({{2015, 2, 9}, {16,32, 14}}).
63590718734

11> calendar:datetime_to_gregorian_seconds({{0, 1, 1}, {0,0, 1}}).
1

12> calendar:datetime_to_gregorian_seconds({{0, 1, 1}, {0,1, 0}}).
60

13> calendar:datetime_to_gregorian_seconds({{0, 1, 1}, {1,0, 0}}).
3600
```



--------
`lists:subtract(List1, List2) -> List3`

> lists:subtract(A, B) is equivalent to A -- B. Returns a new list List3 which is a copy of List1, subjected to the following procedure: for each element in List2, its first occurrence in List1 is deleted.

```erlang
1> lists:subtract("123212", "212").
"312"
```
---
dict:fetch_keysは辞書の中のすべてのkeyをリストとして返す

```erlang
1> D = dict:from_list([{k1,v1}, {k2, v2}, {k3, v3}]).
{dict,3,16,16,8,80,48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
      {{[],
        [[k1|v1]],
        [[k2|v2]],
        [[k3|v3]],
        [],[],[],[],[],[],[],[],[],[],[],[]}}}
3> L = dict:fetch_keys(D).
[k1,k2,k3]
4> L.
[k1,k2,k3]
```

---
`timer:sleep(Time|infinity) -> ok`
> Suspends the process calling this function for Time amount of milliseconds and then returns ok, or suspend the process forever if Time is the atom infinity. Naturally, this function does not return immediately.

---
ファイルの中の日本語を読み出す

```erlang
$ erl +pc unicode
1>  {R, Data} = file:open("file", [read, {encoding, utf8}]).
{ok,<0.35.0>}
2> io:get_line(Data, "").
"こんにちは\n"
3>
```

---
string:to_integer(String) -> {Int, Rest} | {error, Reason}
> tupleを返すことに注意

```erlang
3> {I1, Is} = string:to_integer("33+22").
{33,"+22"}
4> {I2, I3} = string:to_integer(Is).
{22,[]}
5> f().
ok
6> {I1, Is} = string:to_integer("33/22").
{33,"/22"}
7> {I2, I3} = string:to_integer(Is).
{error,no_integer}
```

----
Sub protocols are used for creating new types of handlers that provide extra functionality in a reusable way. Cowboy uses this mechanism to provide its loop, REST and Websocket handlers.
To switch to a sub protocol, the init/2 callback must return the name of the sub protocol module. Everything past this point is handled by the sub protocol.

```erlang
init(Req, Opts) ->
    {cowboy_websocket, Req, Opts}.
```
---
dict:from_list(L)
> Key-Value形のリストを辞書に変換する

dict:append(Key, Value, Dict1) -> Dict2

```erlang
1> L = [{keyA, "A"}, {keyB, "B"}, {keyC, "C"}].
[{keyA,"A"},{keyB,"B"},{keyC,"C"}]

3> D = dict:from_list(L).
{dict,3,16,16,8,80,48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
      {{[],
        [[keyA,65]],
        [[keyB,66]],
        [[keyC,67]],
        [],[],[],[],[],[],[],[],[],[],[],[]}}}

4> D1 = dict:append(keyD, "D", D).
{dict,4,16,16,8,80,48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
      {{[],
        [[keyA,65]],
        [[keyB,66]],
        [[keyC,67]],
        [[keyD,"D"]],
        [],[],[],[],[],[],[],[],[],[],[]}}}


---
How to get N bits from binary
> You'll need to use bitstring as the type as it will not be a multiple of 8 bits anymore (which the binary type requires). Rest is now 6 bits.

```erlang
23> <<B:2, Rest/bitstring>> = <<2#11000101>>.
<<"Å">>
24> B.
3
25> Rest.
<<5:6>>
```

---
`binary:match(Subject, Pattern) -> Found | nomatch`
> 戻り値に示しているように結果のoffsetは0から始まる

```erlang
6> binary:match(<<"/etc/nginx/nginx.conf">>, <<"etc/">>).
{1,4}
7> binary:match(<<"/etc/nginx/nginx.conf">>, <<"etc//">>).
nomatch
```
----

 `e(-1)` 
> reexecute expression on previous line

```erlang
29> L = filename:split("local/bin").
["local","bin"]
30> e(-1).
["local","bin"]
```

---
```erlang
9> filename:split("/usr/local/bin").
["/","usr","local","bin"]

10> filename:split("/usr/local/bin/").
["/","usr","local","bin"]

11> filename:split("local/bin").
["local","bin"]

12> filename:split("local/bin/").
["local","bin"]

14> filename:split("local/bin/foo").
["local","bin","foo"]
```

---
filename:absname(Filename)
> Converts a relative Filename and returns an absolute name. No attempt is made to create the shortest absolute name,
because this can give incorrect results on file systems which allow links.

```erlang
1> pwd().
/home/ec2-user
ok

2> filename:absname("foo").
"/home/ec2-user/foo"
3> filename:absname("../X").
"/home/ec2-user/../X"
4> filename:absname("/").
"/"

5> cd("/etc").
/etc
ok
6> filename:absname("foo").
"/etc/foo"

7> X= <<"foo">>.
<<"foo">>
8> filename:absname(X).
<<"/etc/foo">>
```


---
```erlang
19> base64:encode_to_string("wang zhijun").
"d2FuZyB6aGlqdW4="
20> base64:encode_to_string(ab).
** exception error: no function clause matching
                    base64:encode_to_string(ab) (base64.erl, line 46)

21> base64:encode_to_string(<<"wang zhijun">>).
"d2FuZyB6aGlqdW4="

23> base64:encode_to_string(crypto:rand_bytes(32)).
"h46fo7CSL4Q/94Ji7664Txpw++mgWsnZ2W9TR0tZdSc="
```

-------------
```erlang
8> lists:nth(5, [1,2,ab, "mike", <<"binary">>]).
<<"binary">>
9> lists:nth(0, [1,2,ab, "mike", <<"binary">>]).
** exception error: no function clause matching
                    lists:nth(0,[1,2,ab,"mike",<<"binary">>]) (lists.erl, line 168)

10> lists:nthtail(0, [1,2,ab, "mike", <<"binary">>]).
[1,2,ab,"mike",<<"binary">>]
11> lists:nthtail(2, [1,2,ab, "mike", <<"binary">>]).
[ab,"mike",<<"binary">>]
12> lists:nthtail(5, [1,2,ab, "mike", <<"binary">>]).
[]
```


----
`crypto:rand_bytes(N).`
> rand_bytes(N) -> binary()
Generates N bytes randomly uniform 0..255, and returns the result in a binary. Uses the crypto library pseudo-random number generator.

```erlang
6> crypto:rand_bytes(64).
<<90,108,103,210,241,40,111,211,250,40,227,216,56,149,110,
  182,219,237,182,157,194,81,207,85,121,56,224,201,18,...>>
7> length(binary_to_list(crypto:rand_bytes(64))).
64
8>
```

----
't' 
> is the Unicode translation modifier

's' 
> Prints the argument with the string syntax. 
The argument is, if no Unicode translation modifier 
is present, an iolist(), a binary(), or an atom(). 
If the Unicode translation modifier (t) is in effect, 
the argument is unicode:chardata(), meaning that binaries are in UTF-8. 

```erlang
1> Bin = <<"こんにちは"/utf8>>.
<<227,129,147,227,130,147,227,129,171,227,129,161,227,129,
  175>>
2> lists:keyfind(encoding, 1, io:getopts()).
{encoding,unicode}
3> io:format("~ts~n", [Bin]).
こんにちは
ok
4>
```

---
mnesia:delete_object(Record) -> transaction abort | ok

```erlang
Delete=#user{first_name = "ryan", _ = '_'},
Fun = fun() ->
              List = mnesia:match_object(Delete)
              lists:foreach(fun(X) ->
                                    mnesia:delete_object(X)
                            end, List)
      end,
mnesia:transaction(Fun).
```
 
---
employeeテーブルのEnoレコードに対して、読み込みを行った後、updateを行いたい場合
 mnesia:read/3の三つ目のパラメータにwriteロックを掛ける

 ```erlang
 raise(Eno, Raise) ->
     F = fun() ->
                 [E] = mnesia:read(employee, Eno, write),
                 Salary = E#employee.salary + Raise,
                 New = E#employee{salary = Salary},
                 mnesia:write(New)
         end,
     mnesia:transaction(F).
 ```


---
mnesia:create_tableはデフォルトでram_copiesのテーブルを作成します。
最初に作成されたschemaはdisc_copies

```erlang
$ erl -mnesia dir '"/tmp/funky"'
1> mnesia:create_schema([node()]).
ok
2> mnesia:start().
ok
4> mnesia:create_table(funky, []).
{atomic,ok}
5> mnesia:info().
---> Processes holding locks <---
---> Processes waiting for locks <---
---> Participant transactions <---
---> Coordinator transactions <---
---> Uncertain transactions <---
---> Active tables <---
funky          : with 0        records occupying 282      words of mem
schema         : with 2        records occupying 506      words of mem
===> System info in version "4.12.1", debug level = none <===
opt_disc. Directory "/tmp/funky" is used.
use fallback at restart = false
running db nodes   = [nonode@nohost]
stopped db nodes   = []
master node tables = []
remote             = []
ram_copies         = [funky]
disc_copies        = [schema]
disc_only_copies   = []
[{nonode@nohost,disc_copies}] = [schema]
[{nonode@nohost,ram_copies}] = [funky]
3 transactions committed, 0 aborted, 0 restarted, 2 logged to disc
0 held locks, 0 in queue; 0 local transactions, 0 remote
0 transactions waits for other nodes: []
ok

```

---
**filelib:is_dir(Name) -> boolean()**
> The is_dir/1 function returns true if Name refers to a directory, and false otherwise.

```erlang
AirBox:Desktop wzj$ erl
1> filelib:is_dir("~/Desktop").
false
2> filelib:is_dir("/Users/wzj/Desktop").
true
3> filelib:is_dir(".").
true
5> filelib:is_dir("..").
true
```
---
`lists:keyfind(Key, Nth, Tuplelist) -> Tuple | false`
Searches the list of tuples TupleList for a tuple whose Nth element compares equal to Key. Returns Tuple if such a tuple is found, otherwise false.

---
iolist_to_binaryの例

```erlang
1> Bin1 = <<1,2,3>>.
<<1,2,3>>
2> Bin2 = <<4,5>>.
<<4,5>>
3> Bin3 = <<6>>.
<<6>>
4> B = iolist_to_binary([Bin1, 1, [2,3,Bin2], 4  | Bin3]).
<<1,2,3,1,2,3,4,5,4,6>>
5> B = iolist_to_binary([Bin1, 1, [2,3,Bin2], 4  | 9]).
** exception error: bad argument
     in function  iolist_to_binary/1
        called as iolist_to_binary([<<1,2,3>>,1,[2,3,<<4,5>>],4|9])
7> C = iolist_to_binary([Bin1, 1, [2,3,Bin2], 4  | <<9>>]).
<<1,2,3,1,2,3,4,5,4,9>>
```

---
list_to_binaryの例

```erlang
2> list_to_binary(["abcdefg", $h]).
<<"abcdefgh">>
3> list_to_binary(["abcdefg" | <<"h">>]).
<<"abcdefgh">>
4> list_to_binary(["abcdefg" | $h ]).
** exception error: bad argument
     in function  list_to_binary/1
        called as list_to_binary(["abcdefg"|104])
5> list_to_binary(["abcdefg" | <<66>> ]).
<<"abcdefgB">>
```

---
list comprehensionの中に複数のステートメントを実行します。beginとendを使用

```erlang
1> [begin erlang:display(N), N*10 end || N <- lists:seq(1,5)].
1
2
3
4
5
[10,20,30,40,50]
```

---
Erlangのrun time systemの中にどんなアプリケーションが動いているかを調べるには下のコマンドを使用する

```erlang
6> application:which_applications().
[{rpn,"Reverse Polish Notation","1"},
 {stdlib,"ERTS  CXC 138 10","2.1"},
 {kernel,"ERTS  CXC 138 10","3.0.1"}]
```
---
アプリケーションの開始と停止はstartとstopで制御する
`application:start(ApplicationName).`
`application:stop(ApplicationName).`

```erlang
1> application:start(rpn).
{local,rpn_sup} (<0.37.0>) starting...
ok
2> rpn_server:cal_rpn("2 3 4 5 6 sum").
20
3> application:stop(rpn).
ok
4>
=INFO REPORT==== 30-Dec-2014::11:20:14 ===
    application: rpn
    exited: stopped
    type: temporary

4> rpn_server:cal_rpn("2 3 4 5 6 sum").
** exception exit: {noproc,
                       {gen_server,call,
                           [rpn_server,{cal_rpn,"2 3 4 5 6 sum"}]}}
     in function  gen_server:call/2 (gen_server.erl, line 182)
```
---
string:to_lower(String) -> Result

```erlang
2> string:to_lower("STRING").
"string"
3> string:to_lower("STRIこんにちは").
[115,116,114,105,12371,12435,12395,12385,12399]
```

---
lists:zip(List1, List2) -> List3
"Zips" two lists of equal length into one list of two-tuples
返すリストの中の要素はtupleであることを注意

```erlang
2> lists:zip([1,2,3], [4,5,6]).
[{1,4},{2,5},{3,6}]
3> lists:zip([1,2,3], [4,5,6,7]).
** exception error: no function clause matching lists:zip([],[7]) (lists.erl, line 385)
     in function  lists:zip/2 (lists.erl, line 385)
     in call from lists:zip/2 (lists.erl, line 385)

```
---
**mnesia:read({Tab, Key}) -> transaction abort | RecordList**
Invokes mnesia:read(Tab, Key, read).
主キーがKeyに一致するレコードを返す。ets:lookup/2と同様にリストを返す。
set のテーブルのように主キーに一致する結果が絶対に1つしかないようなテーブル
でもリストを返します。 レコードが見つからない場合は、空のリストが返されます。

---
行を削除するには表のオブジェクトID(OID)が必要になる．OIDはテーブル名と主キーの値で構成される．

**delete({Tab, Key}) -> transaction abort | ok**

Invokes mnesia:delete(Tab, Key, write)

```erlang
remove_shop_item(Item) ->
    Oid = {shop, Item},
    F = fun() ->
        mnesia:delete(Oid)
        end,
    mnesia:transaction(F).
```

---
データベースのデータの追加

```erlang
add_shop_item(Name, Quantity, Cost) ->
    Row = #shop{item=Name, quantity=Quantity, cost=Cost},
    F = fun() ->
        mnesia:write(Row)
    end,
    mnesia:transaction(F).
```
実行

```erlang
1> test_mnesia:do_this_once().
stopped

=INFO REPORT==== 25-Dec-2014::23:25:19 ===
    application: mnesia
    exited: stopped
    type: temporary
2>
2> test_mnesia:start().
ok
3> test_mnesia:reset_tables().
{atomic,ok}
4> test_mnesia:demo(select_shop).
[{shop,potato,2456,1.2},
 {shop,apple,20,2.3},
 {shop,orange,100,3.8},
 {shop,pear,200,3.6},
 {shop,banana,420,4.5}]
5> test_mnesia:add_shop_item(orange, 236, 2.8).
{atomic,ok}
6> test_mnesia:demo(select_shop).
[{shop,potato,2456,1.2},
 {shop,apple,20,2.3},
 {shop,orange,236,2.8},
 {shop,pear,200,3.6},
 {shop,banana,420,4.5}]
```

---
qlc:q()で問い合わせるときに簡単のjoinの例をしたの図で示している

![5.png](https://qiita-image-store.s3.amazonaws.com/0/54698/4eaf0d43-9b04-8711-b05c-a7f1fe7efcd9.png)

----
改めて用意されているテーブルのデータをmnesiaに書き込みたいときに、下のやり方で

```erlang
 start() ->
     mnesia:start(),
     mnesia:wait_for_tables([shop,cost], 20000).

 example_tables() ->
     [%% The shop table
      {shop, apple,   20,   2.3},
      {shop, orange,  100,  3.8},
      {shop, pear,    200,  3.6},
      {shop, banana,  420,  4.5},
      {shop, potato,  2456, 1.2},
      %% The cost table
      {cost, apple,   1.5},
      {cost, orange,  2.4},
      {cost, pear,    2.2},
      {cost, banana,  1.5},
      {cost, potato,  0.6}
     ].

 reset_tables() ->
     mnesia:clear_table(shop),
     mnesia:clear_table(cost),
     F = fun() ->
         foreach(fun mnesia:write/1, example_tables())
     end,
     mnesia:transaction(F).
```

実行すると

```erlang
1> test_mnesia:start().
ok
2> test_mnesia:reset_tables().
{atomic, ok}
```
**mnesia:transaction(Fun) -> {aborted, Reason} |{atomic, Value}.** This function executes one transaction with the functional object Fun as the single parameter.

---
mnesiaを使う前に一回やっておくことはあって、
スキーマを作ってからmnesiaをスタートさせる
そして、テーブルを作って、mnesiaをストップ

![4.png](https://qiita-image-store.s3.amazonaws.com/0/54698/89894c8c-6b56-0041-1b76-337684db97bd.png)



---
__mnesia:is_transaction() -> boolean__

When this function is executed __inside a transaction context__ it returns **true**, otherwise false.
例

```erlang
traverse_table_and_show(Table_name)->
    Iterator =  fun(Rec,_)->
                    io:format("~p~n",[Rec]),
                    []
                end,
    case mnesia:is_transaction() of
        true -> mnesia:foldl(Iterator,[],Table_name);
        false -> 
            Exec = fun({Fun,Tab}) -> mnesia:foldl(Fun, [],Tab) end,
            mnesia:activity(transaction,Exec,[{Iterator,Table_name}],mnesia_frag)
    end.
```

mnesia:foldl(Function, Acc, Table) -> NewAcc | transaction abort 
Iterates over the table Table and calls Function(Record, NewAcc) for each Record in the table. The term returned from Function will be used as the second argument in the next call to the Function.

__foldl returns the same term as the last call to Function returned.__

----
ファイルを作成してから，書き込む

```erlang
7> {ok, S} = file:open("/Users/wzj/testfile", [write]).
{ok,<0.40.0>}
8> io:format(S, "~s~n", ["Hello world from wang"]).
ok
9> io:format(S, "~s~n", ["sorry for the delay"]).
ok
10> file:close(S).
ok
```


---
mnesia:write(Record) -> transaction abort | ok 

write/1はmnesia:write(Tab, Record, write)関数を呼び出している

![Screen Shot 2014-12-22 at 1.12.09 PM.png](https://qiita-image-store.s3.amazonaws.com/0/54698/467c5c0b-349c-fd81-4835-9d3a2e6f7e82.png)

clear_table(Tab) -> {aborted, R} | {atomic, ok}
clear_tableはテーブルのすべてのエントリを削除する

---
qlcはMnesiaデータベースのデータをアクセスするために使うモジュールの一つである．

```erlang
qlc:q([X || X <- mnesia:table(shop) ])
```
上のコードはshopというMnesiaデータベースから取って来たXを要素とするリスト，Xの値はErlangのshopレコードになる


---
mnesiaのqlc:q()関数を呼び出すには下のヘッダーファイルをインクルードする必要がある

```erlang
-include_lib("stdlib/include/qlc.hrl").
```
---
A common mistake is to have a unique gen_server to handle queries from many processes. This generally becomes the biggest bottleneck you'll want to fix. You should try to avoid relying on a single process, using a pool if you can.

---
**Defining a Schema**
The configuration of a Mnesia system is described in the schema. The schema is a **special table** which contains information such as the table names and each table's storage type, (i.e. whether a table should be stored in RAM, on disc or possibly on both, as well as its location).

it is possible to move a table and simultaneously perform write operations to the same table. This feature is essential for applications that require continuous service.

---
stringモジュールのstr関数
str(String, SubString) -> Index
SubStringがStringの中に現れる最初のIndexを返す
Indexが1から始まる。存在しない場合は0を返す

```erlang
1> string:str(" Hello Hello World World ", "Hello World").
8
2> string:str(" Hello Hello World World ", "not exist").
0
```

----
ets:new(Name, Options) -> tid() | atom()
Optionsの中にアクセス権限をコントロールするpublicオプションがあって
すべてのプロセスがこのテーブルに対して，readとwriteが可能

![Screen Shot 2014-12-21 at 12.46.24 PM.png](https://qiita-image-store.s3.amazonaws.com/0/54698/5fa10d77-eb96-9b57-ba5d-56573c76dbb2.png)


---
record_info(fields, Record) -> [Field]
test.erlを作成して，record_infoの使い方をテストする

```erlang
-module(test).
-record(paint, {index, artist, title}).
```
実行する

```erl
$ erlc test.erl
test.erl:2: Warning: record paint is unused
$ erl
1> rr(test).
[paint]
2> record_info(fields, paint).
[index,artist,title]
3> record_info(size, paint).
4
```

---
create_table(Name, TabDef) -> {atomic, ok} | {aborted, Reason}
mnesiaモジュールのcreate_table関数が成功すると{atomic, ok}が戻り値として，返される
二個目の引数TabDefは{Item, Value}で構成されているリスト.
[例](https://github.com/ColdFreak/Web-Programming/blob/master/Erlang/art.erl)

![Screen Shot 2014-12-21 at 11.47.56 AM.png](https://qiita-image-store.s3.amazonaws.com/0/54698/4d864cd4-e1e0-7a2f-e959-eb5156f5edea.png)

{disc_copies, Nodelist}, where Nodelist is a list of the nodes where this table is supposed to have disc copies. If a table replica is of type disc_copies, all write operations on this particular replica of the table are written to disc as well as to the RAM copy of the table.

----
process_flag(Flag :: trap_exit, Boolean) -> OldBoolean
When trap_exit is set to **true**, exit signals arriving to a process are **converted to {'EXIT', From, Reason} messages**, which can be received as ordinary messages.

---
ets:info(Tab) -> InfoList | undefined
テーブルが定義されていないときにundefinedが返す

```erlang
56> ets:new(ingredients, [set, named_table]).
ingredients
57> ets:info(ingredients).
[{compressed,false},
 {memory,305},
 {owner,<0.93.0>},
 {heir,none},
 {name,ingredients},
 {size,0},
 {node,nonode@nohost},
 {named_table,true},
 {type,set},
 {keypos,1},
 {protection,protected}]
58> ets:info(nonexist).
undefined
```

---
io:get_line(IoDevice, Prompt) -> Data | server_no_data()

```erlang
53> {ok, IoDevice} = file:open("event.erl", [read]).
{ok,<0.96.0>}
54> io:get_line(IoDevice, "").
"-module(event).\n"
55> io:get_line(IoDevice, "").
"-compile(export_all).\n"
```
---
uniform/0関数は0.0~1.0範囲内の少数を返す

```erlang
26> random:uniform().
0.989293905914232
```

uniform(N) -> integer() >= 1
1より大きい整数を渡すと1~4範囲内の整数を返す

```erlang
32> random:uniform(4).
1
33> random:uniform(4).
4
```

---
file:open(File, Modes) -> {ok, IoDevice} | {error, Reason}
file:open/2関数は成功するときに{ok, IoDevice}を返します。失敗するときに {error, Reason}を返します。例

```erlang
file:open(Fname, [read, raw, binary])
```

file:read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason}
file:read/3関数の戻り値は三つのパターンがあります。{ok, Data}、 eof と {error, Reason}です。例

```erlang
file:read(Fd, 1024)
```

---
listsモジュールのflatmap/2の動きは下のようになる

```erlang
flatmap(Fun, List1) ->
    append(map(Fun, List1)).
```
例

```erlang
4> lists:flatmap(fun(X) -> [X, X] end, [1,a, "abc"]).
[1,1,a,a,"abc","abc"]
```
---

stringモジュールのto_float関数で文字列をfloatに変更するときに、失敗すると
{error, Reason}が返される
この関数の形としては

to_float(String) -> {Float, Rest} | {error, Reason}

```erlang
13> {Float, Rest} = string:to_float("1.12e2X").
{112.0,"X"}
14> f().
16> {Float, Rest} = string:to_float("a+b").
{error,no_float}
```
最後のXが変換できないので、Restとして保存される

----
stringモジュールのtokens/2関数
tokens(String, SeparatorList) -> Tokens

Stringに対して、SeparatorListに含まれている文字で区切られるリストを返す

```erlang
4> string:tokens("abc defxxghix jkl", "x ").
["abc","def","ghi","jkl"]
5> string:tokens("10 4 3 + 2 * -", " ").
["10","4","3","+","2","*","-"]
```

---
gen_server:handle_call(Request, From, State)関数はgen_server:call/2,3のリクエストに対して，処理を行う関数．
Request = term()
From = {pid(), Tag}
戻り値として，
{reply,Reply,NewState} | {reply,Reply,NewState,Timeout}などが返される．
下は例

![Screen Shot 2014-12-20 at 1.54.45 PM.png](https://qiita-image-store.s3.amazonaws.com/0/54698/51db67ae-714d-9819-5365-b44f8e0f9fbf.png)

---
gen_server:start_link/3,4が呼ばれると，init(Args)関数が実行される．initの戻り値として，{ok, State}, {ok, State, TimeOut}あるいは{ok, State, hibernate}が返される

---
join(StringList, Separator) -> String
Returns a string with the elements of StringList separated by the string in Separator.

```erlang
5> string:join(["This","is","a","string","list"], ", ").
"This, is, a, string, list"
```

---
ローカルnodeの中に存在しているプロセスのリストを取得して、一個一個のプロセスに対して、情報を取得する

```erlang
3> erlang:processes().
[<0.0.0>,<0.3.0>,<0.6.0>,<0.7.0>,<0.9.0>,<0.10.0>,<0.11.0>,
 <0.12.0>,f<0.13.0>,<0.14.0>,<0.15.0>,<0.16.0>,<0.18.0>,
 <0.19.0>,<0.20.0>,<0.21.0>,<0.22.0>,<0.23.0>,<0.24.0>,
 <0.25.0>,<0.26.0>,<0.27.0>,<0.28.0>,<0.29.0>,<0.33.0>]
4> erlang:process_info(pid(0,33,0)).
[{current_function,{erl_eval,do_apply,6}},
 {initial_call,{erlang,apply,2}},
 {status,running},
 {message_queue_len,0},
 {messages,[]},
 {links,[<0.27.0>]},
 {dictionary,[]},
 {trap_exit,false},
 {error_handler,error_handler},
 {priority,normal},
 {group_leader,<0.26.0>},
 {total_heap_size,3196},
 {heap_size,1598},
 {stack_size,24},
 {reductions,49451},
 {garbage_collection,[{min_bin_vheap_size,46422},
                      {min_heap_size,233},
                      {fullsweep_after,65535},
                      {minor_gcs,30}]},
 {suspending,[]}]
5>
```
----
リストの中にユニークの要素をソートする

```erlang
2> lists:usort([2,1,3,4,2,3,8,9,[a,c,q,m,x],a,v,c]).
[1,2,3,4,8,9,a,c,v,[a,c,q,m,x]]
```


----
Concatenates the text representation of the elements of Things. The elements of Things can be atoms, integers, floats or strings.
concat(Things) -> string()

```erlang
1> lists:concat([doc, '/', file, '.', 3]).
"doc/file.3"
```
---
ファイルパスを組み立てる

```erlang
29> filename:join(["/usr", "local", "bin"]).
"/usr/local/bin"
```

---
ネットワークインターフェースを取得する

```erlang
19> inet:getifaddrs().
{ok,[{"lo",
      [{flags,[up,loopback,running]},
       {hwaddr,[0,0,0,0,0,0]},
       {addr,{127,0,0,1}},
       {netmask,{255,0,0,0}},
       {addr,{0,0,0,0,0,0,0,1}},
       {netmask,{65535,65535,65535,65535,65535,65535,65535,
                 65535}}]},
     {"eth0",
      [{flags,[up,broadcast,running,multicast]},
       {hwaddr,[10,150,197,9,125,48]},
       {addr,{172,31,21,248}},
       {netmask,{255,255,240,0}},
       {broadaddr,{172,31,31,255}},
       {addr,{65152,0,0,0,2198,50687,65033,32048}},
       {netmask,{65535,65535,65535,65535,0,0,0,0}}]}]}
```

---
'=:=' と '=='の区別

```erlang
16> 1 =:= 1.0.
false
17> 1 == 1.0.
true
18> [65] =:= "A".
true
```

---
folds関数
foldl(Fun, Acc0, List) -> Acc1

```erlang
2> lists:foldl(fun(X, Sum) -> X+Sum end, 3, [2,4,6,8]).
23
```
後ろのリスト一個一個のの要素に対して、関数を適応して行く
2番目のパラメータは3という初期のアキュミュレーター指定している

---
priv_dir(Name)はlib_dir(Name, priv)と一緒でライブラリNameのprivディレクトリを返す

```erlang
11> code:lib_dir(mnesia, priv).
"/usr/local/lib/erlang/lib/mnesia-4.12.1/priv"
12> code:priv_dir(mnesia).
"/usr/local/lib/erlang/lib/mnesia-4.12.1/priv"
13> code:priv_dir(eunit).
"/usr/local/lib/erlang/lib/eunit-2.2.7/priv"
14> code:priv_dir(kernel).
"/usr/local/lib/erlang/lib/kernel-3.0.1/priv"
```

---
tupleのサイズはtuple_size/1で取得する
element/2でtupleのn個目の要素を取得する。

```erlang
3> Tuple1 = {number, 42}.
{number,42}
4> tuple_size(Tuple1).
2
5> element(1, Tuple1).
number
6> element(2, Tuple1).
42
7> setelement(2, Tuple1, 43).
{number,43}
8> Tuple1.
{number,42}
9> Tuple2 = setelement(2, Tuple1, 43).
{number,43}
10> Tuple2.
{number,43}
```

---
K1の一個一個のtupleに対して、
keysearch()の場合は2個目の要素はk2とマッチングしていれば返す。

```erlang
12> K1 = [{a, k1, a}, {b, k2, b}, {c, k3, c}, {e, k5, e}].
[{a,k1,a},{b,k2,b},{c,k3,c},{e,k5,e}]
13> lists:keysearch(k2, 2, K1).
{value,{b,k2,b}}
15> lists:keydelete(k3, 2, K1).
[{a,k1,a},{b,k2,b},{e,k5,e}]
16> lists:keyreplace(k1, 2, K1, {new, tuple}).
[{new,tuple},{b,k2,b},{c,k3,c},{e,k5,e}]
```

----
listsモジュールのsplit/2関数split(N, List1) -> {List2, List3}
List1の前N個と残りの要素、この二つのリストをtupleとして、返す

```erlang
1> L = ["This","is", "a", "list"].
["This","is","a","list"]
2> lists:split(3, L).
{["This","is","a"],["list"]}
```

---
function_exported/3関数の意味はModuleはロードされて、そして、エクスポート（パラメータ数Arity)されている関数Fucntionがあれば、trueを返して、それ以外はfalseを返す
        
        erlang:function_exported(Module, Function, Arity) -> bool()
----
timerモジュールのsend_interval/3関数

        send_interval(Time, Pid, Message) -> {ok, TRef} | {error, Reason}

Time時間過ぎると

        Pid ! Message

を定期的に実行する。send_interval/2の場合はsend_interval(Time, self(), Message).と一緒である

---
一週間の間の曜日を調べるにはcalendarモジュールのday_of_the_week()関数を使う

```erlang
1> calendar:day_of_the_week({2014,12,17}).
3
```

----
ETSテーブルはtupleを保存する。テーブルをスタートさせるためにets:new/2を使う
オプションの中にsetが使われているので、keyは重複しないテーブルを使う
tupleの一部だけを調べるときにlookup_element()関数を使う
下の例だとorangeはkeyではないのでクラッシュする

```erlang
1> ets:new(ingredients, [set, named_table]).
6> ets:insert(ingredients, {orange, good, nice, delicious}).
7> ets:lookup_element(ingredients, orange, 2).
good
8> ets:lookup_element(ingredients, orange, 3).
nice
9> ets:lookup_element(ingredients, orange, 4).
12> ets:lookup_element(ingredients, orange, 1).
** exception error: bad argument
     in function  ets:lookup_element/3
        called as ets:lookup_element(ingredients,good,1)

```   


---
orddict:new()は新しいKey-Valueペアの辞書を作る
orddictの作られている辞書はソートされている。
dictと同じインターフェースを提供している

```erlang
store(Key, Value, Orddict1) -> Orddict2
find(Key, Orddict) -> {ok, Value} | error
fetch(Key, Orddict) -> Value
erase(Key, Orddict1) -> Orddict2
map(Fun, Orddict1) -> Orddict2

```
fetchの場合は

> returns the value associated with Key in the dictionary Orddict. fetch assumes that the Key is present in the dictionary and an exception is generated if Key is not in the dictionary.

findの場合

> This function searches for a key in a dictionary. Returns {ok, Value} where Value is the value associated with Key, or error if the key is not present in the dictionary.

----
日付不法であるかをチェックするためにcalendarモジュールのvalid_date()関数を使用する

valid_date(Date) -> boolean()
Date = date()

valid_date(Year, Month, Day) -> boolean()
Year = Month = Day = integer()

```erlang
11> calendar:valid_date(2014,2,28).
true
12> calendar:valid_date({2014,2,28}).
true
13> calendar:valid_date(2014,2,29).
false
14> calendar:valid_date({2014,2,29}).
false

```

----
[clash](http://erldocs.com/17.3/kernel/code.html#clash/0)関数を使って、同じ名前のモジュールが衝突しているかをチェックする

```erlang
1> code:clash().
** Found 0 name clashes in code paths
ok
```

---
code:lib_dirを使ってライブラリのパスを探す

```erlang
1> code:lib_dir(mnesia).
"/usr/local/lib/erlang/lib/mnesia-4.12.1"
2> code:lib_dir(eunit).
"/usr/local/lib/erlang/lib/eunit-2.2.7"
3> code:lib_dir(kernel).
"/usr/local/lib/erlang/lib/kernel-3.0.1"
4>
```
-include_lib()を使うときにライブラリのバージョンを指定しなくてもよい

```erlang
-include_lib("kernel/include/file.hrl").
-include_lib("eunit/include/eunit.hrl").
```
----
Erlangのバージョンを取得する方法

```erlang
5> erlang:system_info(otp_release).
"17"
```

----
バイナリデータを連結する方法

```erlang
1> B1 = <<1,2>>.
<<1,2>>
2> B2 = <<3,4>>.
<<3,4>>
3> B3 = <<B1/binary, B2/binary>>.
<<1,2,3,4>>
```
---
Erlangにreturn文がない理由

　Erlang has no statements, it only has expressions. All expressions
　return a value. So there is no need for a "return" instruction, the last
　expression executed gives the return value of the function.

----
文字列はダブルクオーテーションで囲まれて、Erlangのデータタイプではない, "hello"はただのリストである、[\$h,\$e,\$l,\$l,\$o]、つまり[104,101,108,108,111].
   
```erlang  
> integer_to_list(123).  
"123"
> is_list(integer_to_list(323)).
true

```
----

Erlangシェルの中にcdコマンドを使って、移動する. pwd()は現在の場所を調べる
        
```erlang
2> cd("/etc").
/etc
ok
3> pwd().
/etc
ok
```

----
Calling demonitor(MonitorRef, [flush]) is equivalent to the following, but more efficient:

```erlang
demonitor(MonitorRef),
    receive
        {_, MonitorRef, _, _, _} ->
            true
    after 0 ->
            true
    end
```
----
This function returns the local time reported by the underlying operating system.
[local_time()](http://www.erlang.org/doc/man/calendar.html#local_time-0) のリファレンスは
```
local_time()-> datetime()
datetime()データタイプはしたのように
datetime() = {date(), time()}
date() = {year(), month(), day()}
time() = {hour(), minute(), second()}
```

```erlang
1> calendar:local_time().
{{2014,12,16},{11,22,27}}
```
----