SlideShare uma empresa Scribd logo
1 de 13
Baixar para ler offline
java, scalaをやってきてgoに思うこと
- golangで末尾再帰最適化は使えるか?-
2017/6/23 株式会社AJA 森 拓真
階乗
6! = 6 * 5 * 4 * 3 * 2 * 1 = 720
5! = 5 * 4 * 3 * 2 * 1 = 120
4! = 4 * 3 * 2 * 1 = 24
3! = 3 * 2 * 1 = 6
2! = 2 * 1 = 2
1! = 1 = 1
末尾再帰最適化
どんな風に書けばいいの?
末尾再帰 -> 関数の最後の呼び出しが自身の呼び出しになっていれば良い
再帰関数(スタックオーバーフローが起きる)
末尾再帰関数 (スタックオーバーフローが起きないように最適化可能)
再帰の場合
5!
コールスタック
4!
3!
2!
1!
return 1
return 2 * 1 = 1
return 3 * 2 = 6
return 4 * 6 = 24
func fact (5)
return 5 * 24 = 120
末尾再帰の場合
fact (4, 5)
コールスタック
fact(3, 20)
fact(2, 60)
fact(1, 120)
fact(0, 120)
return 120
return 120
return 120
return 120
func fact (5, 1)
return 120
n = 5 - 1 = 4
result = 5 * 1 = 5
n = 4 - 1 = 3
result = 5 * 4 = 20
n = 3 - 1 = 2
result = 20 *3 = 60
n = 2 - 1 = 1
result = 60 * 2 = 120
n = 1 - 1 = 0
result = 120
Scalaコンパイラの最適化って実際何してるの?
classファイルをjadで逆コンパイルした結果
階乗を求める末尾再帰な関数
末尾再帰最適化の対応状況
言語 対応状況 備考
java × 非対応
scala ◯ 対応 デフォルトで有効。
@tailrecアノテーションで、非末尾
再帰関数をコンパイルエラーにでき
る
ruby △ 対応 デフォルトでは無効。
tailcall_optimizationオプションを有効にすると利用
可能
javascript △ 対応 ES6からは、実装仕様として要求
Babelではトランスパイル時に最適化するようになっ
ている
Golangで末尾再帰最適化は使えるの?(1/5)
Golangで末尾再帰最適化は使えるの?(2/5)
特定の数までの足し上げる(ex: 5 + 4 + 3 + 2 + 1)末尾再帰関数
StackoverFlow
Golangで末尾再帰最適化は使えるの?(3/5)
BenchmarkRecursive-4 5000000 349 ns/op
BenchmarkRecursiveIteration-4 30000000 56.0 ns/op
BenchmarkTailRecursive-4 5000000 316 ns/op
パフォーマンス計測してみた
Golangで末尾再帰最適化は使えるの?(4/5)
go build -gcflags -S recursive.go &> assembly_code.txt
Golangで末尾再帰最適化は使えるの?(5/5)
● 使えない
まとめ
● golangでは末尾再帰は最適化されない。末尾再帰はfor, goto
を利用した記述方法に変更する。
● 今後も追加される気配は無い。

Mais conteúdo relacionado

Mais procurados

日本語テストメソッドについて
日本語テストメソッドについて日本語テストメソッドについて
日本語テストメソッドについて
kumake
 

Mais procurados (20)

JIT のコードを読んでみた
JIT のコードを読んでみたJIT のコードを読んでみた
JIT のコードを読んでみた
 
競プロでGo!
競プロでGo!競プロでGo!
競プロでGo!
 
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みSAT/SMTソルバの仕組み
SAT/SMTソルバの仕組み
 
Tackling Complexity
Tackling ComplexityTackling Complexity
Tackling Complexity
 
Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析Goでかんたんソースコードの静的解析
Goでかんたんソースコードの静的解析
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml
 
PHPの今とこれから2023
PHPの今とこれから2023PHPの今とこれから2023
PHPの今とこれから2023
 
日本語テストメソッドについて
日本語テストメソッドについて日本語テストメソッドについて
日本語テストメソッドについて
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
私とOSSの25年
私とOSSの25年私とOSSの25年
私とOSSの25年
 
型安全性入門
型安全性入門型安全性入門
型安全性入門
 
Monad tutorial
Monad tutorialMonad tutorial
Monad tutorial
 
Parser combinatorってなんなのさ
Parser combinatorってなんなのさParser combinatorってなんなのさ
Parser combinatorってなんなのさ
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
マイクロサービスにおける 非同期アーキテクチャ
マイクロサービスにおける非同期アーキテクチャマイクロサービスにおける非同期アーキテクチャ
マイクロサービスにおける 非同期アーキテクチャ
 
React(TypeScript) + Go + Auth0 で実現する管理画面
React(TypeScript) + Go + Auth0 で実現する管理画面React(TypeScript) + Go + Auth0 で実現する管理画面
React(TypeScript) + Go + Auth0 で実現する管理画面
 
ワタナベ難読化シェル芸
ワタナベ難読化シェル芸ワタナベ難読化シェル芸
ワタナベ難読化シェル芸
 
GoでMinecraftっぽいの作る
GoでMinecraftっぽいの作るGoでMinecraftっぽいの作る
GoでMinecraftっぽいの作る
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 

goで末尾再帰最適化は使えるか?