Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Elixir におけるリスト反転処理の実装を覗いてみよう
Search
Shohei Kajihara
July 01, 2019
Technology
0
2.3k
Elixir におけるリスト反転処理の実装を覗いてみよう
2019/07/01 【学生限定】Akatsuki Geek Live Vol.3【LT会:7/1(月)】 にて発表した資料です。
Shohei Kajihara
July 01, 2019
Tweet
Share
Other Decks in Technology
See All in Technology
Why Governance Matters: The Key to Reducing Risk Without Slowing Down
sarahjwells
0
120
from Sakichi Toyoda to Agile
kawaguti
PRO
1
100
関係性が駆動するアジャイル──GPTに人格を与えたら、対話を通してふりかえりを習慣化できた話
mhlyc
0
130
オープンソースでどこまでできる?フォーマル検証チャレンジ
msyksphinz
0
120
E2Eテスト設計_自動化のリアル___Playwrightでの実践とMCPの試み__AIによるテスト観点作成_.pdf
findy_eventslides
1
530
LLM時代にデータエンジニアの役割はどう変わるか?
ikkimiyazaki
5
1.1k
生成AIとM5Stack / M5 Japan Tour 2025 Autumn 東京
you
PRO
0
240
Optuna DashboardにおけるPLaMo2連携機能の紹介 / PFN LLM セミナー
pfn
PRO
2
920
Findy Team+のSOC2取得までの道のり
rvirus0817
0
490
動画データのポテンシャルを引き出す! Databricks と AI活用への奮闘記(現在進行形)
databricksjapan
0
160
セキュアな認可付きリモートMCPサーバーをAWSマネージドサービスでつくろう! / Let's build an OAuth protected remote MCP server based on AWS managed services
kaminashi
3
220
SoccerNet GSRの紹介と技術応用:選手視点映像を提供するサッカー作戦盤ツール
mixi_engineers
PRO
1
190
Featured
See All Featured
GraphQLとの向き合い方2022年版
quramy
49
14k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
A Tale of Four Properties
chriscoyier
160
23k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Building Applications with DynamoDB
mza
96
6.7k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
37
2.6k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
9
580
Code Reviewing Like a Champion
maltzj
525
40k
What's in a price? How to price your products and services
michaelherold
246
12k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Facilitating Awesome Meetings
lara
56
6.6k
Making Projects Easy
brettharned
119
6.4k
Transcript
Elixir における Elixir における リスト反転処理の実装を リスト反転処理の実装を 覗いてみよう 覗いてみよう 2019/07/01 Akatsuki
Geek Live Vol.3 アカツキ サーバーエンジニア 梶原星平 (@s-capybara)
⾃⼰紹介 ⾃⼰紹介 2017 年 アカツキに新卒⼊社(3 年⽬) Elixir でゲームサーバーを書いています
今⽇の⽬的 今⽇の⽬的 Elixir の紹介 プログラミング⾔語の中⾝の学び⽅
Elixir とは Elixir とは プログラミング⾔語 関数型 動的型付け 不変性 (immutability) Erlang
VM 上で動作 並⾏性 (concurrency) 耐障害性 (fault-tolerance) Erlang の関数を呼び出せる
不変性 不変性 予想外の値変更による実装ミスが起きにくくなる defmodule Sample do def foo() do bar
= 1 if :rand.uniform() > 0.5 do bar = 2 IO.puts("Modified bar to 2!") end bar end end iex(1)> Sample.foo() Modified bar to 2! 1
List List iex(2)> numbers = [1, 2, 3] [1, 2,
3]
List の基本操作 List の基本操作 Lisp と同じく Car, Cdr, Cons 処理ができる
Car: リストの先頭を取り出す Cdr: リストの残り部分を取り出す Cons: リストの先頭に要素を⾜す iex(3)> [head | _] = numbers iex(2)> head 1 iex(4)> [_ | tail] = numbers iex(4)> tail [2, 3] iex(5)> [0 | numbers] [0, 1, 2, 3]
Enum.reverse Enum.reverse リスト(など)を反転する関数 標準の関数が⾼速なので、 ⾃前実装は NG と⾔われている iex(6)> Enum.reverse(numbers) [3,
2, 1]
気になるところ 気になるところ 1. リストはどういうデータ構造なのか? 2. 標準の関数はなぜ⾼速なのか?
解決策1: 本を読む 解決策1: 本を読む The Beam Book ( ) Erlang
VM の中⾝が紹介されている (プロセス、スケジューラ、型システム、... ) 無料で読める(ただし英語) 書籍は著者視点による説明 説明の順序にストーリーがあるので⼊⾨に最適 公式ドキュメントなどより先に書籍にあたるのが おすすめ https://github.com/happi/theBeamBook
Erlang VM の型システム Erlang VM の型システム 64 ( または32) bits
で 1 word 末尾 2 bits ( あるいはもっと) で型を表現 リストは「アドレス + 01 」という形の 1 word 00 Header (on heap) CP (on stack) 01 List (cons) 10 boxed 00 11 Pid
単⽅向リストの実体 単⽅向リストの実体 リストはポインタであり、 参照先の隣のアドレスがまたポインタになっている
解決策2: ソースコードを 解決策2: ソースコードを 読む 読む Elixir: Erlang: https://github.com/elixir-lang/elixir https://github.com/erlang/otp
Enum.reverse/1 の実装 Enum.reverse/1 の実装 簡単なやつだけ Elixir レイヤーで定義 結局、Erlang のコードを呼び出している @spec
reverse(t) :: list def reverse([]), do: [] def reverse([_] = list), do: list def reverse([element1, element2]), do: [element2, element1] def reverse([element1, element2 | rest]), do: :lists.reverse(rest, [element2, element1])
lists:reverse/2 の実装 lists:reverse/2 の実装 結局、C ⾔語実装の Built in Funciton (BIF)
を呼び出し ている %% Shadowed by erl_bif_types: lists:reverse/2 -spec reverse(List1, Tail) -> List2 when List1 :: [T], Tail :: term(), List2 :: [T], T :: term(). reverse(_, _) -> erlang:nif_error(undef).
lists_reverse_2 lists_reverse_2 erts/emulator/beam/erl_bif_lists.c というそれっぽい名前のファイルに lists_reverse_2 というそれっぽい名前の関数を発⾒
lists_reverse_2 ( 抜粋) lists_reverse_2 ( 抜粋) CAR, CDR, CONS をやっているらしい
(説明は後で図⽰) while (alloc_top < alloc_end) { // リストをポインタ化する Eterm *pair = list_val(list); // 確保したヒープ領域の先頭を [ リストの先頭 | 反転済みリスト ] に tail = CONS(alloc_top, CAR(pair), tail); // 続きは Cdr から list = CDR(pair); ASSERT(is_list(list) || is_nil(list)); // 2 words 分ヒープ領域のへのポインタを進める alloc_top += 2; }
リスト操作のマクロ リスト操作のマクロ CAR, CDR, CONS の定義(説明は割愛) #define TAG_PRIMARY_LIST 0x1 //
01 の⾜し算でポインタをリストに、引き算でリストをポインタに #define _unchecked_make_list(x) ((Uint)(x) + TAG_PRIMARY_LIST) #define _unchecked_list_val(x) ((Eterm*) ((x) - TAG_PRIMARY_LIST) // ポインタの指すアドレスに値を仕舞ったのちリストにする #define CONS(hp, car, cdr) \ (CAR(hp)=(car), CDR(hp)=(cdr), make_list(hp)) // ポインタの指すアドレスが CAR, その隣が CDR #define CAR(x) ((x)[0]) #define CDR(x) ((x)[1])
lists_reverse_2 の概観 lists_reverse_2 の概観 (1/4) (1/4)
lists_reverse_2 の概観 lists_reverse_2 の概観 (2/4) (2/4)
lists_reverse_2 の概観 lists_reverse_2 の概観 (3/4) (3/4)
lists_reverse_2 の概観 lists_reverse_2 の概観 (4/4) (4/4)
標準の関数は 標準の関数は なぜ速いのか? なぜ速いのか? そもそも C ⾔語なので速い 不変性を保つ必要がない result は
C ⾔語上のローカル変数
結局、理解できて 結局、理解できて 何が嬉しいのか? 何が嬉しいのか? すぐに役⽴つわけではないが... 「この⾔語ではどういう操作のコストが⾼いの か?」など理解したうえでコードが書けるようにな る(かも) トラブルシューティングに強くなる(かも)
まとめ まとめ まず本を読み、その後ソースコードを読もう すぐには役に⽴たないが、中⾝を知っておいた⽅が 安⼼