Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Scheme用Linterの改良 (マクロ逆展開を可能なかぎりやる?) Niyarin
Slide 2
Slide 2 text
Scheme用Linter、Red-parenについて ○パターン列挙型のLinter Red-paren (apply append (map some-proc (foo x))) ソースコード ((apply append (map f ls …)) (append-map f ls …)) … 略) パターン(rules+) (append-map some-proc (foo x)) と書けるよ niyarin/red-paren
Slide 3
Slide 3 text
Red-parenのちょっとした問題 ○マクロに対して弱い 例) threading macro (ネストした式を平らにする) (->> some-list (filter (λ (x) (not (some-pred? x))) ) … ) (->> some-list (remove some-pred?) …) と動いてほしい (filter (lambda (x) (not (pred x))) ls) このマクロを使うとremoveのルールにマッチしない removeのルール
Slide 4
Slide 4 text
マクロが問題になるケースは多いのか? 普通のマクロは問題ない ○ 問題の原因の多くは手続き適用を壊すマクロ ・ threading macro ・ condp ○レアケースと思って良さそう(たぶん) ※これらが悪だとは言っていない(私はcondpが好きです)
Slide 5
Slide 5 text
マクロ展開→ Lint適用 (->> some-list (filter (λ (x) (not (some-pred? x)))) なにか1 なにか2 なにか3) (なにか3 (なにか2 (なにか1 (remove some-pred some-list)))) マクロ展開+Lint ○ マクロを使うとすり抜けるのでマクロ展開してからLintを書けてみる ☓ これは求めていたものとは違う(ちょっと不親切)
Slide 6
Slide 6 text
マクロを逆展開する機構が欲しい (->> some-list (remove some-pred) なにか1 なにか2 なにか3) (なにか3 (なにか2 (なにか1 (remove some-pred some-list)))) ○ マクロを逆展開する操作があれば理想的な指摘コードが得られる マクロ逆展開 前ページの例の続き
Slide 7
Slide 7 text
syntax-rulesって逆にしても使え”そう” Schemeの標準(R7RS)のマクロシステム ○ let → lambdaの例 lambda → let も逆からマッチさせることでできそう (syntax-rules () ((let ((name val) ...) body1 body2 ...) ((lambda (name ...) body1 body2 ...) val ...)))
Slide 8
Slide 8 text
syntax-rulesって逆にしても使え”そう” そう簡単にはいかない (1) ruleに同じ変数を含んではいけない → これは同じ変数が同じものにマッチしているならよいことにする (2) 2回以上のellipsis → backtrack+最短マッチで妥協する? (3) ruleだけに存在する変数や_ → あきらめる(ほとんどないケースだと思う) (4) ruleは上からマッチする仕様だが、逆は必ずしもそうではない → 次のページ (5) hygenic性とか先頭がsymbolでないことも目をつぶる
Slide 9
Slide 9 text
復元できそうなものを全列挙する (->> (a b) c) (->> (->> (a b) c)) (->> b a c) (->> b (a) c) 決定的に出せないので全列挙 → どれか1つが理想的なもの
Slide 10
Slide 10 text
逆展開例 (->> なにか1なにか2 (なにか3 なにか4) (filter (lambda (x) (not (some-pred? x)))) なにか5) (->> なにか1 なにか2 (なにか3 なにか4) (remove some-pred?) なにか5) (->> なにか5 (->> (remove some-pred? (なにか3 なにか4 (なにか2 なにか1))))) (->> なにか1 (なにか2) (なにか3 なにか4) (remove some-pred?) なにか5) 理想 不自然なコード(正しく動作はする) 理想と近いが正しく動作しない 元のコード
Slide 11
Slide 11 text
どのように理想的なコードを見つけるのか 適当な評価式を与えて最もポイントが高いのを選択する ○ (同じ要素が同じ順序で含む数 , - 最大の深さ , - 式の長さ ) ・一応、threadingマクロ例の理想コードはこれでとれはする 理想:(5 -2 -6) 不自然なコード:(1 -5 -3) 動作しないコード:(4 -2 -6) ・てきとうなので改良はいる
Slide 12
Slide 12 text
sexp-diffとかもよいかもしれない ・Racket系のs式diff #:newと#:oldを付けて差分が分かる > (sexp-diff '(->> some1 some2 (some3 some4) (filter (lambda (x) (not (some-pred? x)))) some5) '(->> some1 some2 (some3 some4) (remove some-pred?) some5)) '((->> some1 some2 (some3 some4) #:new (remove some-pred?) #:old (filter (lambda (x) (not (some-pred? x)))) some5))
Slide 13
Slide 13 text
Red-parenに組み込む ・マクロ情報をユーザが渡さないと使えない → 名前空間からマクロを得る部分が必要 というわけで組み込むのはまだ先 ・マクロ逆展開は実装済み ・信頼性は落ちるのでなんらかのタグをつける
Slide 14
Slide 14 text
おわり