Your SlideShare is downloading. ×

Lispmeetup14-05-30

3,516
views

Published on

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
3,516
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Picrin Scheme びず@wasabiz
  • 2. 自己紹介 • Yuichi Nishiwaki • @wasabiz • 大学3年生です • CL使いでした。 • 英語版スライドは用意してません(ゴメンネ)
  • 3. Picrin Scheme 今日のおはなし • Scheme処理系Picrinについて • ライブラリ機構 • レコード機構 • マクロシステム びず@wasabiz
  • 4. Picrin Scheme • 名前だけでも覚えて帰ってください∼ びず@wasabizPicrin Scheme
  • 5. Picrinについて(1/3) • R7RS(ほぼ)完全準拠のScheme処理系 • 2013/9∼ • ポータビリティを意識した極めてシンプルな設計 • VMは並列動作可能 • JITコンパイルは実験中(jit branch) びず@wasabizPicrin Scheme
  • 6. Picrinについて(2/3) • ホスティングはgithub • pull-reqベースの開発 • C99 + POSIX(optional) • cmakeによるビルド • sphinxを使ったドキュメンテーション びず@wasabizPicrin Scheme
  • 7. Picrinについて(3/3) • R7RS + α • できるだけR7RSの思想を尊重 • コアに手を入れず、可能な限りライブラリ・マクロで実現 • ないもの:optional argument, keywords • あるもの:regexp, delimited continuation びず@wasabizPicrin Scheme
  • 8. R7RS • Picrinのコア言語 • R5RSからの新機能: • ライブラリ機構 • ユーザー定義レコード • unicode • 例外機構 びず@wasabizPicrin Scheme
  • 9. R7RS: ライブラリ機構 ! ! ! ! びず@wasabizPicrin Scheme ! (define-library (picrin my-lib) (import (scheme base)) ! … ! (export foo bar))
  • 10. R7RS: ライブラリ機構 • (define-library <name> <program>) • <name>はシンボルのリスト • (import <spec> …) • 高機能 • <spec> ::= (prefix …) ¦ (rename …) ¦ … • キモい びず@wasabizPicrin Scheme
  • 11. import文 • 例:「(scheme base)ライブラリのcarとcdrをlist- car, list-cdrとしてインポートしたい」 ! ! ! • キモい びず@wasabizPicrin Scheme ! (import (rename (scheme base) (car list-car) (cdr list-cdr)))
  • 12. キモいimport文 • 極端に高機能 • それ、命名規則でできるよ • 言語機能がこなれてない • 本当は
 (import (scheme base) :rename (car list-car))
 と書きたい びず@wasabizPicrin Scheme
  • 13. キモいdefine-library • ML系に特徴的な「モジュール全体をブロックで包む」スタ イル • 伝統的なLisp流のin-packageを使った逐次スタイルとは 対照的 • マクロ・リーダーマクロ・REPLとの相性が最悪… ! びず@wasabizPicrin Scheme
  • 14. キモいdefine-library • ライブラリ名の付け方も不思議 • loadとimportは別なのでさらに問題はややこしい • R7RSでは(import (picrin foo))とすると(load picrin/foo.ss ) するように推奨しているが… • /usr/share/picrin/lib/picrin/foo.ssのこと? • ${HOME}/picrin/foo.ssのこと? • ${PWD}/picrin/foo.ssのこと? びず@wasabizPicrin Scheme
  • 15. Picrinでの保守的解決法 • 最大公約数を取る • 高機能にしてキモくなるなら単純性を取る • import文はライブラリを単純に読み込む場合のみサポート。 • (import (prefix …))や(import (rename …))は使えません。 • 使いたくなるコードはダメなコード • exportも同様 びず@wasabizPicrin Scheme
  • 16. Picrinでの保守的解決法 • ライブラリ名はどんな式でもOK • 例えば#fとか123とかも正当なライブラリ名です • 典型的には文字列を与える場合を想定 • loadとimportは完全に分離 • 標準ライブラリを読み込むときに問題になるので、
 それらは文字列化して実行バイナリに埋め込み、実行前に自動ロー ド びず@wasabizPicrin Scheme
  • 17. library introspection/intercession • とはいえprefixed importがないのは問題になりうる • cf. CLのpackage nickname地獄 • first-class libraryを用意することも視野に。 • ライブラリを(コンパイル時に)動的に生成→export table を書き換えでprefixed importをエミュレート • C++のTMPやOCamlのsignatureのような何か。 びず@wasabizPicrin Scheme
  • 18. ライブラリ機構まとめ • R7RSの規定するライブラリ機構はプリミティブ としてはやや巨大すぎる • Picrinでは制限付きdefine-library/import/ exportで全体を簡素化している • 将来的にfirst-class libraryが入るかも びず@wasabizPicrin Scheme
  • 19. マクロシステム
  • 20. R7RSのマクロ • syntax-rulesによる • パターンマッチベース • 高レベルマクロ • これだけを直接実装するのは難しい • 通常、別の低レベルマクロの上に構築する びず@wasabizPicrin Scheme
  • 21. Picrinのマクロ • 開発初期 • 伝統的なマクロ • gensym + 通常の式 • 開発中期 (pre-VM) • syntactic closures (今でもサポート) • ∼現在 (post-VM) • explicit renaming macros / implicit renaming macros びず@wasabizPicrin Scheme
  • 22. Picrinのマクロ展開器 • 自動リネーミング • 解決したいこと: • 展開後の識別子同士の衝突を防ぎたい • 解決策: • 全ての識別子を一意なシンボルにリネーム • 衝突は発生しない(はず?) びず@wasabizPicrin Scheme
  • 23. Picrinのマクロ展開(もといコンパイラ) • 実際のコンパイルの流れ • macroexpand • analysis • codegen • そしてVMへ… ! びず@wasabizPicrin Scheme
  • 24. Picrinのコンパイラ • 元の式 ! ! ! ! びず@wasabizPicrin Scheme ! (let ((a 1)) (+ a 2))
  • 25. Picrinのコンパイラ • 1. macroexpand ! ! ! ! • 識別子 a が a@1726 にリネームされている びず@wasabizPicrin Scheme ! ((lambda (a@1726) (+@83 a@1726 2)) 1)
  • 26. Picrinのコンパイラ • 2. analysis ! ! ! ! • 末尾呼び出しやreturn、変数参照がASTレベルで明示された びず@wasabizPicrin Scheme ! (tail-call (lambda #f (a@1726) () #f () (return (+ (lref a@1726) ‘2))) ‘1)
  • 27. Picrinのコンパイラ • 3. codegen ! ! ! ! • VMの命令列にコンパイル(no-optimization) びず@wasabizPicrin Scheme ! ## irep 0x7fcc0206e380 [clen = 3, argc = 1, localc = 0, capturec = 0] 00 [20] OP_LAMBDA 0 01 [ 5] OP_PUSHINT 1 02 [18] OP_TAILCALL 2 ! ## irep 0x7fcc0206dd00 [clen = 4, argc = 2, localc = 0, capturec = 0] 00 [10] OP_LREF 1 01 [ 5] OP_PUSHINT 2 02 [25] OP_ADD 03 [19] OP_RET 1
  • 28. Picrinの評価器 • 4. VM • シンプルなスタックマシン • レジスタマシンにしなかったのはJIT搭載を見越して • token-threaded VM (computed gotos) • closure by lazy tear-off びず@wasabizPicrin Scheme
  • 29. マクロ展開の話(つづき) • 自動リネームで健全性が確保されたように見える • でも微妙に落とし穴が… ! ! びず@wasabizPicrin Scheme
  • 30. マクロの健全性条件 ! 「自動生成された識別子で、展開後のプログラムで 実際の束縛になるものは、同一の転写段階で 生成された変数だけを束縛しなければならない。」 ! http://www.katch.ne.jp/ leque/translations/srfi-93/srfi-93j.html
  • 31. マクロ展開の話(つづき) • どういうことか? • 再帰的展開 + 変数の束縛 
 
 を行うマクロが問題になる • 例:destructuring-bindマクロ びず@wasabizPicrin Scheme
  • 32. マクロ展開の話(つづき) ! ! ! びず@wasabizPicrin Scheme ! (destructuring-bind ((a b) . c) '((1 2) 3 4 5) (list a b c)) ! ; => (1 2 (3 4 5))
  • 33. マクロ展開の話(つづき) ! ! ! ! • 一時変数evaluatedが全ての展開でevaluated@605に リネームされてしまい、動かない びず@wasabizPicrin Scheme ! ((lambda (evaluated@605) ((lambda (evaluated@605) ((lambda (a@617) (begin ((lambda (evaluated@605) ((lambda (b@619) (begin (begin ((lambda (c@620) (begin (list@19 a@617 b@619 c@620))) (cdr@9 evaluated@605))))) (car@8 evaluated@605))) (cdr@9 evaluated@605)))) (car@8 evaluated@605))) (car@8 evaluated@605))) (quote ((1 2) 3 4 5)))
  • 34. 解決策? • リネーム時にもう一つ変数を増やす • a → a@34:58 • 展開器が複雑になりすぎる • できれば避けたい… びず@wasabizPicrin Scheme
  • 35. Picrinの解決策 • 命名規則による解決策 • ユーザーのしごと • マクロの展開結果中で変数を束縛したい場合は#でsuffix • マクロ以外で#でsuffixされた名前を定義しない • リネーマーのしごと • bound var → そのリネームに解決 • unbound var → 新たなリネームを作り、同展開中ではそれを使い まわす びず@wasabizPicrin Scheme
  • 36. Picrinの解決策 ! ! ! ! ! • 命名規則によってtmp#は常にunboundなので展開ごとに一意な シンボルが生成される びず@wasabizPicrin Scheme ! (define-syntax swap! (ir-macro-transformer (lambda (form inject compare) (let ((a (car (cdr form))) (b (car (cdr (cdr form))))) `(let ((tmp# ,a)) (set! ,a ,b) (set! ,b tmp#))))))
  • 37. マクロまとめ • 健全なマクロはとても難しい • 健全なマクロはとても難しい (大事なことなので) ! • Picrinは健全性条件を捨てる代わりに命名規則を導入した • 普通にマクロが使いたいだけならsyntax-rulesでおk びず@wasabizPicrin Scheme
  • 38. その他 • レキサージェネレータつかってますよーとか • string I/Oを実装するためにファイル構造体から 作りましたよーとか • 文字列処理の効率化のためにrope表現をつかい ましたよーとか びず@wasabizPicrin Scheme
  • 39. 今後 • JIT • 非同期I/O びず@wasabizPicrin Scheme
  • 40. 非同期プロミス • 非同期I/Oをプロミスにマッピング • プロミスがモナドになる • then :: Promise a -> (a -> Promise b) -> Promise b • 限定継続 + マクロで非同期処理を逐次的に記述 びず@wasabizPicrin Scheme
  • 41. 非同期プロミス • 例1 ! ! ! • url-1とurl-2を同期的に取得して結合 びず@wasabizPicrin Scheme ! (async (let ((a (await (http-get-async url-1))) (b (await (http-get-async url-2)))) (string-concat a b)))
  • 42. 非同期プロミス • 例2 ! ! ! ! • 任意の数のurlを非同期的に取得して結果を結合 びず@wasabizPicrin Scheme ! (define (http-get-urls urls) (promise-join (map http-get-url urls)) ! ! (async (let ((pages (await (http-get-urls urls)))) (fold string-append pages)))
  • 43. コールバックvsプロミス • libuv/libevのようなコールバックベースのC APIベース • コールバックベースの処理はschemeのシンタックスには合わない • ネストがひどい • コールバックベースのAPIをプロミスでラップすると少し楽 • 更に限定継続とマクロを使うとすごく楽 • async/awaitは銀の弾丸に成り得る びず@wasabizPicrin Scheme
  • 44. 最後に
  • 45. Picrinは開発者を募集中! • Githubにホストされてます • プルリクください • 今swank-picrinを作ると神になれます びず@wasabizPicrin Scheme
  • 46. https://github.com/wasabiz/picrin