Real World OCamlを読んでLispと協調してみた

2,532 views

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,532
On SlideShare
0
From Embeds
0
Number of Embeds
504
Actions
Shares
0
Downloads
11
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Real World OCamlを読んでLispと協調してみた

  1. 1. Real World OCaml読んでみた感想 Lisp Meet Up Presented by Shibuya.lisp #14 κeen(@blackenedgold) #lispmeetup 2014-02-26
  2. 2. 自己紹介 ● Twitter: κeen(@blackenedgold) ● Github: KeenS ● ブログ: κeenのHappy Hacκing Blog ● 東大数学科の三年生 ● 就活中! ● Lisp, Ruby, シェルスクリプトが好き ● CIMの開発してます
  3. 3. 話の流れ ● OCamlと周りの環境の紹介(軽く) ● Real World OCamlの紹介 ● OCamlの機能をLispに取り込んでみた ボツ編 ● OCamlの機能をLispに取り込んでみた
  4. 4. OCamlと周りの環境 の紹介
  5. 5. OCamlについて 名古屋の方は黙って見てて下さい ML方言のCamlにオブジェクト指向を加えたもの ● 強い静的片付け ● 強力な型推論 ● フランスのINRIA研究所で開発されている ●
  6. 6. OCamlについて 名古屋の方は黙って見てて下さい ● 関数型 ● 値は基本変更不可 ● 関数はカリー化されている
  7. 7. OCaml サンプルコード let rec quicksort = function | [] -> [] | pivot :: rest -> let is_less x = x < pivot in let left, right = List.partition is_less rest in quicksort left @ [pivot] @ quicksort right Racket (define quicksort (match-lambda ['() '()] [(cons pivot rest) (let ([lessp (lambda (x) (< x pivot))]) (let-values ([(left right) (partition lessp rest)]) (append (quicksort left) (list pivot) (quicksort right))))]))
  8. 8. OCaml サンプルコード 再帰関数定義 リストリテラル let rec quicksort = function コンス演算子によるマッチング | [] -> [] | pivot :: rest -> let is_less x = x < pivot in let left, right = List.partition is_less ローカル関数定義 rest in quicksort left @ [pivot] @ quicksort right Racket タプルリテタルによる (define quicksort 変数の分配束縛 モジュール関数呼び出し (match-lambda ['() '()] append演算子 [(cons pivot rest) (let ([lessp (lambda (x) (< x pivot))]) (let-values ([(left right) (partition lessp rest)]) (append (quicksort left) (list pivot) (quicksort right))))]))
  9. 9. OCamlをとりまく環境 ● Jane Streetという金融会社が業務で使用 ● 標準ライブラリにツッコみどころがある – – ● Jane StreetのライブラリCoreで補う 標準ライブラリを上書きしてる ライブラリマネージャ、バージョンマネージャ完 備 ● 推奨エディタがEmacs ● 日本だと名古屋が拠点
  10. 10. Real World OCamlの紹介
  11. 11. Real World OCamlの紹介 http://realworldocaml.org ● ベータ版は↑から無料で読める ● 英語版はオライリーより$44くらい ● 510p (cf. Land of Lispは480p) ● 著者は OMakeの開発者 XenをOCamlで開発した人 Jane Streetの中の人 ●
  12. 12. Real Wold OCamlの紹介 ● Jane StreetのCoreを前提 ● 言語の基礎からコンパイラプラグインまで ● ● プログラミングの知識はあるが関数型は初めて の人対象 一冊読めば入門からReal Worldまでいけると思 います
  13. 13. 目次 ● はじめに ● 第1部 言語の概念 ● 1 マップ及びハッシュテーブル 3. 1 コマンドラインのパース 4. 1 ひとめぐり . 15. JSONデータの扱い 2. 変数と関数 16. OCamllex及びMenhirによるパース 3. リストとパターン 17. S式によるデータシリアライゼーション 4. ファイル、モジュール、プログラム 5. レコード 18. Asyncによる並行プログラミング ● 6. バリアント 第3部 ランタイムシステム 1 外部関数の呼出し(FFI) 9. 7. エラーハンドリング 20. 値のメモリ表現 8. 命令型プログラミング 21 ガーベジコレクタを理解する . 9. ファンクタ 22. コンパイラフロントエンド:パース及び 型チェック 1 第一級​モジュール 0. 23. コンパイラバックエンド:バイトコード 及びネイティブコード 1 .オブジェクト 1 1 クラス 2. 第2部 ツール及びテクニック ● 索引
  14. 14. 目次 ● はじめに ● 第1部 言語の概念 ● 1 マップ及びハッシュテーブル 3. 1 コマンドラインのパース 4. 1 ひとめぐり . 15. JSONデータの扱い 2. 変数と関数 16. OCamllex及びMenhirによるパース 3. リストとパターン 17. S式によるデータシリアライゼーション 4. ファイル、モジュール、プログラム 5. レコード 18. Asyncによる並行プログラミング ● 6. バリアント 第3部 ランタイムシステム 1 外部関数の呼出し(FFI) 9. 7. エラーハンドリング 20. 値のメモリ表現 8. 命令型プログラミング 21 ガーベジコレクタを理解する . 9. ファンクタ 22. コンパイラフロントエンド:パース及び 型チェック 1 第一級​モジュール 0. 23. コンパイラバックエンド:バイトコード 及びネイティブコード 1 .オブジェクト 1 1 クラス 2. 第2部 ツール及びテクニック ● 索引
  15. 15. ボツ編
  16. 16. モジュール分割 let rec quicksort = function | [] -> [] | pivot :: rest -> let is_less x = x < pivot in let left, right = List.partition is_less rest in quicksort left @ [pivot] @ quicksort right
  17. 17. モジュール分割 let rec quicksort = function | [] -> [] | pivot :: rest -> let is_less x = x < pivot in let left, right = List.partition is_less rest in quicksort left @ [pivot] @ quicksort right List.map Array.map String.map …など
  18. 18. モジュール分割 原案 (list:map #'1+ '(1 2 3)) ;=> (1 2 3) (vector:map #'1+ #(1 2 3)) ;=> #(2 3 4) (string:map (lambda (x) (code-char (1+(char-code x)))) "abc") ;=> "bcd"
  19. 19. モジュール分割 原案 (list:map #'1+ '(1 2 3)) ;=> (1 2 3) (vector:map #'1+ #(1 2 3)) ;=> #(2 3 4) (string:map (lambda (x) (code-char (1+(char-code x)))) "abc") ;=> "bcd" CLer「名前空間は機能を分割するためのもので型を ディスパッチするものではない」 CLer「ハンガリアン記法で区別可能。よって却下」
  20. 20. モジュール分割 原案 (list:map #'1+ '(1 2 3)) ;=> (1 2 3) (vector:map #'1+ #(1 2 3)) ;=> #(2 3 4) (string:map (lambda (x) (code-char (1+(char-code x)))) "abc") ;=> "bcd" CLer「名前空間は機能を分割するためのもので型を ディスパッチするものではない」 CLer「ハンガリアン記法で区別可能。よって却下」 ボツ
  21. 21. local use-package let average x y = x Int64.(+) y Int64.(/) Int64.of_int 2;; open Int64;; let average x y = x + y / of_int 2;; let average x y = let open Int64 in x + y / of_int 2;; let average x y = let module I = Int64 in x I.(+) y I.(/) I.of_int 2;;
  22. 22. local use-package (defun average (x y) let average x y = (int64:/ (int64:+ x y) x Int64.(+) y Int64.(/) Int64.of_int 2;; (int64:of-int 2))) open Int64;; let average x y = x + y / of_int 2;; let average x y = let open Int64 in x + y / of_int 2;; let average x y = let module I = Int64 in x I.(+) y I.(/) I.of_int 2;; (use-package :int64) (defun average (x y) (/ (+ x y) (of-int 2)))
  23. 23. local use-package (defun average (x y) let average x y = (int64:/ (int64:+ x y) x Int64.(+) y Int64.(/) Int64.of_int 2;; (int64:of-int 2))) open Int64;; let average x y = x + y / of_int 2;; (use-package :int64) (defun average (x y) (/ (+ x y) (of-int 2))) (defun average (x y) let average x y = (with-use-packages (:int64) let open Int64 in (/ (+ x y) (of-int 2)))) x + y / of_int 2;; let average x y = (defun average (x y) (with-package-nicknames let module I = Int64 in x I.(+) y I.(/) I.of_int 2;; ((i int64)) (i:/ (i:+ x y) (i:of-int 2))))
  24. 24. local use-package ● シンボルの解決はリード時 ● マクロの展開はコンパイル時
  25. 25. local use-package ● シンボルの解決はリード時 ● マクロの展開はコンパイル時 オワタ(^o^)/
  26. 26. local use-package ● シンボルの解決はリード時 ● マクロの展開はコンパイル時 オワタ(^o^)/ ボツ
  27. 27. 普通編
  28. 28. Variantとパターンマッチ let rec quicksort = function | [] -> [] | pivot :: rest -> let is_less x = x < pivot in let left, right = List.partition is_less rest in quicksort left @ [pivot] @ quicksort right type 'a list = 'a :: 'a list | []
  29. 29. Variantとパターンマッチ let rec quicksort = function | [] -> [] コンパイルエラー | pivot :: rest -> let is_less x = x < pivot in let left, right = List.partition is_less rest in quicksort left @ [pivot] @ quicksort right type 'a list = 'a :: 'a list | []
  30. 30. Variantとパターンマッチ let rec quicksort = function コンパイルエラー | left , right -> left :: [right] | [] -> [] | pivot :: rest -> let is_less x = x < pivot in let left, right = List.partition is_less rest in quicksort left @ [pivot] @ quicksort right type 'a list = 'a :: 'a list | []
  31. 31. Common Lispでやってみる パターンマッチはoptimaがある 型を(defstruct)で一々定義するのは面倒 (defvariant)的な何かを…
  32. 32. Common Lispでやってみる パターンマッチはoptimaがある 型を(defstruct)で一々定義するのは面倒 (defvariant)的な何かを… やってみました
  33. 33. Common Lispでやってみた 赤黒木の例 type 'a tree = | Leaf | Red of tree * 'a * tree | Black of tree * 'a * tree (defvariant tree leaf (red tree t tree) (black tree t tree)) gist https://gist.github.com/9225141 にサンプルコードあります
  34. 34. Common Lispでやってみた 赤黒木の例 type 'a tree = | Leaf | Red of tree * 'a * tree | Black of tree * 'a * tree (defvariant tree leaf (red tree t tree) (black tree t tree)) (PROGN (DEFTYPE TREE () '(OR (MEMBER LEAF) BLACK RED)) (DEFSTRUCT (BLACK (:CONSTRUCTOR BLACK (#:TREE1014 #:T1015 #:TREE1016)) (:PRINT-OBJECT (LAMBDA (OBJ STREAM) (FORMAT STREAM "(~a ~{~a~^ ~})" 'BLACK (LIST-SLOTS OBJ '(#:TREE1014 #:T1015 #:TREE1016) (FORMAT NIL "~a-" 'BLACK)))))) (#:TREE1014 NIL :TYPE TREE) (#:T1015 NIL :TYPE T) (#:TREE1016 NIL :TYPE TREE)) (DEFPATTERN BLACK (#:TREE1014 #:T1015 #:TREE1016) (LIST 'BLACK- :TREE1014 #:TREE1014 :T1015 #:T1015 :TREE1016 #:TREE1016)) (DEFSTRUCT (RED (:CONSTRUCTOR RED (#:TREE1017 #:T1018 #:TREE1019)) (:PRINT-OBJECT (LAMBDA (OBJ STREAM) (FORMAT STREAM "(~a ~{~a~^ ~})" 'RED (LIST-SLOTS OBJ '(#:TREE1017 #:T1018 #:TREE1019) (FORMAT NIL "~a-" 'RED)))))) (#:TREE1017 NIL :TYPE TREE) (#:T1018 NIL :TYPE T) (#:TREE1019 NIL :TYPE TREE)) (DEFPATTERN RED (#:TREE1017 #:T1018 #:TREE1019) (LIST 'RED- :TREE1017 #:TREE1017 :T1018 #:T1018 :TREE1019 #:TREE1019))) gist https://gist.github.com/9225141 にサンプルコードあります
  35. 35. Common Lispでやってみた やってること ● 型の定義 ● 構造体の定義 ● プリティプリント ● コンストラクタの定義 ● ● 構造体のスロットの型制 限 optimaのパターン定義 できなかったこと ● match節が必要十分 でないときのエラー
  36. 36. |> let (|>) data f = f data;; ()で囲まれてるのは中置演算子 ● 関数適用より優先度が低い ● 左結合 ●
  37. 37. |> let (|>) data f = f data;; ()で囲まれてるのは中置演算子 ● 関数適用より優先度が低い ● 左結合 ● # String.split ~on:':' "/usr/bin:/usr/local/bin:/bin:/sbin" |> List.dedup ~compare:String.compare |> List.iter ~f:print_endline ;; /bin /sbin /usr/bin /usr/local/bin unixのパイプみたいに使える!
  38. 38. Lispでやってみた Clojure ->>がある Common Lisp (defmacro ->> (data &rest funs) (reduce (lambda (x y) `(funcall ,y ,x)) funs :initial-value data)) Scheme (define (->> data . funs) (fold (lambda (x y) (x y)) data funs))
  39. 39. 以上 質問あればどうぞ

×