ZACKY こと山崎進です。
今回は少し脱線して,Elixir のビット列について調べてみます。将来C言語との特に構造体によるインタフェースを考える上で重要になってきます。
ところで 菊池 豊さん @kikuyuta の記事を書くペースが半端ないですね! 今回の記事でささやかながら対抗してみたいと思いますw
さっそく iex の実行結果を見てみましょう
$ iex
Erlang/OTP 21 [erts-10.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> bs = << 3 :: size(2) >>
<<3::size(2)>>
iex(2)> is_bitstring(bs)
true
iex(3)> is_binary(bs)
false
iex(4)> byte_size(bs)
1
iex(5)> bs = << 0 :: size(2), 1 :: size(2), 2 :: size(2), 3 :: size(2)>>
"\e"
iex(6)> is_bitstring(bs)
true
iex(7)> is_binary(bs)
true
iex(8)> byte_size(bs)
1
iex(9)> << head :: size(2), tail :: bitstring >> = bs
"\e"
iex(10)> head
0
iex(11)> tail
<<27::size(6)>>
iex(12)> << head :: size(2), tail :: bitstring >> = tail
<<27::size(6)>>
iex(13)> head
1
iex(14)> tail
<<11::size(4)>>
iex(15)> << head :: size(2), tail :: bitstring >> = tail
<<11::size(4)>>
iex(16)> head
2
iex(17)> tail
<<3::size(2)>>
iex(18)> << head :: size(2), tail :: bitstring >> = tail
<<3::size(2)>>
iex(19)> head
3
iex(20)> tail
""
iex(21)> << head :: size(2), tail :: bitstring >> = tail
** (MatchError) no match of right hand side value: ""
(stdlib) erl_eval.erl:450: :erl_eval.expr/5
(iex) lib/iex/evaluator.ex:250: IEx.Evaluator.handle_eval/5
(iex) lib/iex/evaluator.ex:230: IEx.Evaluator.do_eval/3
(iex) lib/iex/evaluator.ex:208: IEx.Evaluator.eval/3
(iex) lib/iex/evaluator.ex:94: IEx.Evaluator.loop/1
(iex) lib/iex/evaluator.ex:24: IEx.Evaluator.init/4
何をしたか解説します。
iex(1)> bs = << 3 :: size(2) >>
<<3::size(2)>>
10進数で3,2進数で11の値を持つ2ビット列 bs
を定義してみました。
iex(2)> is_bitstring(bs)
true
iex(3)> is_binary(bs)
false
iex(4)> byte_size(bs)
1
ビット列は is_bitstring
で true
,is_binary
で false
になります。byte_size
は1バイトです。
iex(5)> bs = << 0 :: size(2), 1 :: size(2), 2 :: size(2), 3 :: size(2)>>
"\e"
それぞれ 0, 1, 2, 3 の2ビットの値を4つ持つビット列 bs
を定義してみました。2進数で 00011011,16進数で1bですから,UTF-8 で ESC "\e" になります。
iex(6)> is_bitstring(bs)
true
iex(7)> is_binary(bs)
true
iex(8)> byte_size(bs)
1
8ビット充足すると is_binary
も true になります。
iex(9)> << head :: size(2), tail :: bitstring >> = bs
"\e"
iex(10)> head
0
iex(11)> tail
<<27::size(6)>>
ビット列もリストのように head
と tail
に分解できます。これはなかなか強力な操作です。
iex(12)> << head :: size(2), tail :: bitstring >> = tail
<<27::size(6)>>
iex(13)> head
1
iex(14)> tail
<<11::size(4)>>
iex(15)> << head :: size(2), tail :: bitstring >> = tail
<<11::size(4)>>
iex(16)> head
2
iex(17)> tail
<<3::size(2)>>
iex(18)> << head :: size(2), tail :: bitstring >> = tail
<<3::size(2)>>
iex(19)> head
3
iex(20)> tail
""
空になるまで分解してみました。
iex(20)> tail
""
iex(21)> << head :: size(2), tail :: bitstring >> = tail
** (MatchError) no match of right hand side value: ""
(stdlib) erl_eval.erl:450: :erl_eval.expr/5
(iex) lib/iex/evaluator.ex:250: IEx.Evaluator.handle_eval/5
(iex) lib/iex/evaluator.ex:230: IEx.Evaluator.do_eval/3
(iex) lib/iex/evaluator.ex:208: IEx.Evaluator.eval/3
(iex) lib/iex/evaluator.ex:94: IEx.Evaluator.loop/1
(iex) lib/iex/evaluator.ex:24: IEx.Evaluator.init/4
空になってなおパターンマッチしようとすると MatchError
になります。
次回ですが, @Tsuyoshi84 さんが素敵な記事「OKを使ってElixirの :ok, :error タプルをエレガントに処理」を書いてくれたので,それに刺激を受けて「ZEAM開発ログ v.0.4.6 OKを使ってNIFのエラー処理をエレガントに書いてみる」をお送りします。お楽しみに!
お知らせ:Elixirもくもく会(リモート参加OK、入門トラック有)を9月28日に開催します
「fukuoka.ex#14:Elixir/Phoenixもくもく会~入門もあるよ」を2018年9月28日金曜日に開催します
前回は,ゲリラ的に募った「Zoomによるリモート参加」を,今回から正式に受け付けるようになりましたので,福岡以外の首都圏や地方からでも参加できます(申し込みいただいたら、追ってZoom URLをconnpassメールでお送りします)
また,これまではElixir/Phoenix経験者を対象とした,もくもく会オンリーでしたが,今回から,入門者トラックも併設し,fukuoka.exアドバイザーズ/キャストに質問できるようにアップグレードしました
私,山崎も参加します! この記事の延長線上のものを作ろうと思っています。
お申込みはコチラから
https://fukuokaex.connpass.com/event/100659/