Real World OCamlを読んでLispと協調してみた
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 1,044 views

 

Statistics

Views

Total Views
1,044
Views on SlideShare
758
Embed Views
286

Actions

Likes
3
Downloads
8
Comments
0

6 Embeds 286

http://keens.github.io 266
http://feedly.com 8
https://twitter.com 5
http://www.slideee.com 5
http://localhost 1
http://www.feedspot.com 1

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

  • Real World OCaml読んでみた感想 Lisp Meet Up Presented by Shibuya.lisp #14 κeen(@blackenedgold) #lispmeetup 2014-02-26
  • 自己紹介 ● Twitter: κeen(@blackenedgold) ● Github: KeenS ● ブログ: κeenのHappy Hacκing Blog ● 東大数学科の三年生 ● 就活中! ● Lisp, Ruby, シェルスクリプトが好き ● CIMの開発してます
  • 話の流れ ● OCamlと周りの環境の紹介(軽く) ● Real World OCamlの紹介 ● OCamlの機能をLispに取り込んでみた ボツ編 ● OCamlの機能をLispに取り込んでみた
  • OCamlと周りの環境 の紹介
  • OCamlについて 名古屋の方は黙って見てて下さい ML方言のCamlにオブジェクト指向を加えたもの ● 強い静的片付け ● 強力な型推論 ● フランスのINRIA研究所で開発されている ●
  • OCamlについて 名古屋の方は黙って見てて下さい ● 関数型 ● 値は基本変更不可 ● 関数はカリー化されている
  • 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))))]))
  • 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))))]))
  • OCamlをとりまく環境 ● Jane Streetという金融会社が業務で使用 ● 標準ライブラリにツッコみどころがある – – ● Jane StreetのライブラリCoreで補う 標準ライブラリを上書きしてる ライブラリマネージャ、バージョンマネージャ完 備 ● 推奨エディタがEmacs ● 日本だと名古屋が拠点
  • Real World OCamlの紹介
  • Real World OCamlの紹介 http://realworldocaml.org ● ベータ版は↑から無料で読める ● 英語版はオライリーより$44くらい ● 510p (cf. Land of Lispは480p) ● 著者は OMakeの開発者 XenをOCamlで開発した人 Jane Streetの中の人 ●
  • Real Wold OCamlの紹介 ● Jane StreetのCoreを前提 ● 言語の基礎からコンパイラプラグインまで ● ● プログラミングの知識はあるが関数型は初めて の人対象 一冊読めば入門からReal Worldまでいけると思 います
  • 目次 ● はじめに ● 第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部 ツール及びテクニック ● 索引
  • 目次 ● はじめに ● 第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部 ツール及びテクニック ● 索引
  • ボツ編
  • モジュール分割 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
  • モジュール分割 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 …など
  • モジュール分割 原案 (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"
  • モジュール分割 原案 (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「ハンガリアン記法で区別可能。よって却下」
  • モジュール分割 原案 (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「ハンガリアン記法で区別可能。よって却下」 ボツ
  • 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;;
  • 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)))
  • 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))))
  • local use-package ● シンボルの解決はリード時 ● マクロの展開はコンパイル時
  • local use-package ● シンボルの解決はリード時 ● マクロの展開はコンパイル時 オワタ(^o^)/
  • local use-package ● シンボルの解決はリード時 ● マクロの展開はコンパイル時 オワタ(^o^)/ ボツ
  • 普通編
  • 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 | []
  • 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 | []
  • 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 | []
  • Common Lispでやってみる パターンマッチはoptimaがある 型を(defstruct)で一々定義するのは面倒 (defvariant)的な何かを…
  • Common Lispでやってみる パターンマッチはoptimaがある 型を(defstruct)で一々定義するのは面倒 (defvariant)的な何かを… やってみました
  • 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 にサンプルコードあります
  • 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 にサンプルコードあります
  • Common Lispでやってみた やってること ● 型の定義 ● 構造体の定義 ● プリティプリント ● コンストラクタの定義 ● ● 構造体のスロットの型制 限 optimaのパターン定義 できなかったこと ● match節が必要十分 でないときのエラー
  • |> let (|>) data f = f data;; ()で囲まれてるのは中置演算子 ● 関数適用より優先度が低い ● 左結合 ●
  • |> 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のパイプみたいに使える!
  • 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))
  • 以上 質問あればどうぞ