Upgrade to Pro — share decks privately, control downloads, hide ads and more …

red-paren-scheme-rev-macro.pdf

 red-paren-scheme-rev-macro.pdf

Niyarin

May 28, 2020
Tweet

More Decks by Niyarin

Other Decks in Programming

Transcript

  1. Scheme用Linterの改良
    (マクロ逆展開を可能なかぎりやる?)
    Niyarin

    View Slide

  2. 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

    View Slide

  3. 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のルール

    View Slide

  4. マクロが問題になるケースは多いのか?
    普通のマクロは問題ない
    ○ 問題の原因の多くは手続き適用を壊すマクロ
    ・ threading macro
    ・ condp
    ○レアケースと思って良さそう(たぶん)
    ※これらが悪だとは言っていない(私はcondpが好きです)

    View Slide

  5. マクロ展開→ Lint適用
    (->> some-list
    (filter (λ (x) (not (some-pred? x))))
    なにか1
    なにか2
    なにか3)
    (なにか3 (なにか2 (なにか1 (remove some-pred some-list))))
    マクロ展開+Lint
    ○ マクロを使うとすり抜けるのでマクロ展開してからLintを書けてみる
    ☓ これは求めていたものとは違う(ちょっと不親切)

    View Slide

  6. マクロを逆展開する機構が欲しい
    (->> some-list
    (remove some-pred)
    なにか1
    なにか2
    なにか3)
    (なにか3 (なにか2 (なにか1 (remove some-pred some-list))))
    ○ マクロを逆展開する操作があれば理想的な指摘コードが得られる
    マクロ逆展開
    前ページの例の続き

    View Slide

  7. syntax-rulesって逆にしても使え”そう”
    Schemeの標準(R7RS)のマクロシステム
    ○ let → lambdaの例
    lambda → let も逆からマッチさせることでできそう
    (syntax-rules ()
    ((let ((name val) ...) body1 body2 ...)
    ((lambda (name ...) body1 body2 ...) val ...)))

    View Slide

  8. syntax-rulesって逆にしても使え”そう”
    そう簡単にはいかない
    (1) ruleに同じ変数を含んではいけない
    → これは同じ変数が同じものにマッチしているならよいことにする
    (2) 2回以上のellipsis
    → backtrack+最短マッチで妥協する?
    (3) ruleだけに存在する変数や_
    → あきらめる(ほとんどないケースだと思う)
    (4) ruleは上からマッチする仕様だが、逆は必ずしもそうではない
    → 次のページ
    (5) hygenic性とか先頭がsymbolでないことも目をつぶる

    View Slide

  9. 復元できそうなものを全列挙する
    (->> (a b) c)
    (->> (->> (a b) c)) (->> b a c) (->> b (a) c)
    決定的に出せないので全列挙
    → どれか1つが理想的なもの

    View Slide

  10. 逆展開例
    (->> なにか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)
    理想
    不自然なコード(正しく動作はする)
    理想と近いが正しく動作しない
    元のコード

    View Slide

  11. どのように理想的なコードを見つけるのか
    適当な評価式を与えて最もポイントが高いのを選択する
    ○ (同じ要素が同じ順序で含む数 , - 最大の深さ , - 式の長さ )
    ・一応、threadingマクロ例の理想コードはこれでとれはする
    理想:(5 -2 -6)
    不自然なコード:(1 -5 -3)
    動作しないコード:(4 -2 -6)
    ・てきとうなので改良はいる

    View Slide

  12. 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))

    View Slide

  13. Red-parenに組み込む
    ・マクロ情報をユーザが渡さないと使えない
    → 名前空間からマクロを得る部分が必要
    というわけで組み込むのはまだ先
    ・マクロ逆展開は実装済み
    ・信頼性は落ちるのでなんらかのタグをつける

    View Slide

  14. おわり

    View Slide