Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
scheme-small-linter.pdf
Search
Niyarin
April 30, 2020
Programming
0
550
scheme-small-linter.pdf
Niyarin
April 30, 2020
Tweet
Share
More Decks by Niyarin
See All by Niyarin
Scheme用nREPLの開発(エラー出力の改善)
niyarin
0
160
bel lispの紹介
niyarin
0
750
nanopass-compiler-frameworkを使ってみました
niyarin
0
440
Gorgos-parser-combinator-written-in-scheme
niyarin
0
390
outputting-beautiful-s-expression
niyarin
0
390
Serialisp
niyarin
1
680
Mongo DBとS式検索
niyarin
0
320
goodbye-python-repl
niyarin
0
370
SchemeのEphemeronとWeak Pairの説明
niyarin
0
1k
Other Decks in Programming
See All in Programming
株式会社 Sun terras カンパニーデック
sunterras
0
170
Web技術を最大限活用してRAW画像を現像する / Developing RAW Images on the Web
ssssota
2
1.1k
Advance Your Career with Open Source
ivargrimstad
0
230
Server Less Code More - コードを書かない時代に生きるサーバーレスデザイン / server-less-code-more
gawa
5
1.9k
defer f()とdefer fの挙動を 誤解していた話
kogamochiduki
2
160
Local Peer-to-Peer APIはどのように使われていくのか?
hal_spidernight
2
420
Repenser les filtres API Platform: une nouvelle syntaxe
vinceamstoutz
2
160
実践AIチャットボットUI実装入門
syumai
7
2.4k
Reduxモダナイズ 〜コードのモダン化を通して、将来のライブラリ移行に備える〜
pvcresin
2
650
Model Pollution
hschwentner
1
180
プログラマのための作曲入門
cheebow
0
510
Web フロントエンドエンジニアに開かれる AI Agent プロダクト開発 - Vercel AI SDK を観察して AI Agent と仲良くなろう! #FEC余熱NIGHT
izumin5210
2
300
Featured
See All Featured
Building Applications with DynamoDB
mza
96
6.6k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.7k
Designing for Performance
lara
610
69k
Reflections from 52 weeks, 52 projects
jeffersonlam
352
21k
A designer walks into a library…
pauljervisheath
208
24k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
YesSQL, Process and Tooling at Scale
rocio
173
14k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
36
2.5k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1.2k
Transcript
Scheme Linterを作る Niyarin
Linter for Scheme ・作法に反するコードを教えてくれるやつ (if (not (some-pred? a)) (write ‘hello))
Linter 「 に変更しよう」 (unless (some-pred? a) (write ‘hello)) → 例 ・(捕捉)Schemeコーディングスタイル派閥 関数定義(define (foo arg) ...) VS (define foo (lambda (arg) …) あとはifを使わずcond+else勢とか ・Schemeは決まったコーディングスタイルは特にないが、 明らかに冗長なものは潰せる 1
Linter実装方針 kibit/kibit/src/kibit/rules/control_structures.clj ・パターンベースのやつ → ユーザがルールを追加しやすい S式言語はこういうの楽で良いね ・ClojureのKibitもそういう方針 core.logicベース 2
作ったもの ・プロトタイプとしてRed-parenという小さいLinterを作った → syntax-rulesライクなルール記述ができる 行数取得とかできるreaderがないので入出力が未完全 ・没案としてmini-kanrenとかの利用も検討していた → Kibitがcore.logic使っているようだったので ・syntax-rulesライクなパターンマッチング(のようなことをする)ライブラリ
・rules (最初に作ったやつ) ・rules+ (記述力が弱かったので↑を拡張した) niyarin/red-paren niyarin/rules 2
最初に作ったライブラリ、Rules ・rulesの例 実質syntax-rulesの関数版のようなもの inputが第一引数にマッチしたなら第二引数に展開される ・schemeでschemeを書く時にsyntax-rulesの実装にも役立つ er-macro/ir-macro(ハイジニックな評価を使うマクロ)があればすぐ実装できる ・あまり強力ではなかった ・型の判定等は苦手 定数(0,#t,#fなど)の判定はできるが、
数値かどうかの判定などはできない ・繰り返し記号の1listに1回だけという制約 (match-expand (when (not pred) body ...) (unless pred body ...) input) 3
rulesの繰り返し記号の制約 ・1つのリストに繰り返し記号2回使うルールが書けない 0を含む+演算 (syntax-rulesでは再帰的にマクロルールを書くことで対処している) ・メリットとしては計算は少なくてすむ ・バックトラックしなくて良い 繰り返し回数が(入力リストの長さ - 非繰り返し記号)で定まる (+
num1 … 0 num2 ...) (a b c … d e)に(1 2 3 4 5 6)を入力した場合、 入力長6からa,b,d,eの4つを引く 4
rulesの実装は必要だったのか ・syntax-rulesのような操作を関数実行時に行う一番楽な方法 ・ほとんど使われないのに必要な時に忘れられるeval ・10行足らずで書けてしまったよ (define (match-expand rule template input) (eval
`(let-syntax ((expand (syntax-rules () ((_ ,rule) (quote ,template)) ((_ _ …) #f)))) (expand ,input)) (environment '(scheme base)))) 5
rules+ (1) 繰り返し数の制限を無くした ・ … 記号は最長マッチの繰り返しとして扱うように変更した ・継続でバックトラックするだけなのでそれほど労力はかからなかった。 6 (or (call/cc
(lambda (break) 繰り返しにもう一回マッチする)) 繰り返しおわり、次に進む) (break #f) マッチ失敗した場合
rules+ (2) 述語埋め込み 述語を埋め込めるようにした 挙動 ・述語に入力を適用して#tならば述語:入力の連想リストで登録される ・複数回使う場合はラップして別ポインタに配置される必要がある 手続きのポインタ配置は仕様の外なので コンパイラの最適化にひっかからないようにする `((assv
(quote ,symbol?) als) (assq (quote ,symbol?) als)) (let ((symbol1? (lambda (x) (and (symbol? x) 1))) (symbol2? (lambda (x) (and (symbol? x) 2)))) `((some-rule ,symbol1? ,symbol2?) (some-template ,symbol1? ,symbol2?))) 7
Red-parenの実行例 ---------- (if (not (and (> x 0) (= (modulo
(+ x y) 2) 0))) (display (car (car y)))) => (unless (and (> x 0) (= (modulo (+ x y) 2) 0)) (display (car (car y)))) ---------- (> x 0) => (positive? x) ---------- (= (modulo (+ x y) 2) 0) => (even? (+ x y)) ---------- (car (car y)) => (caar y) (if (not (and (> x 0) (= (modulo (+ x y) 2) 0))) (display (car (car y)))) > gosh rparen.scm badcode1.scm 結果 入力 8
Red-parenのチェック項目例 ・SRFI/R7RS large用のリストとか append-map、concatenate、remove `((apply append (map f ls ...))
(append-map f ls ...)) ((apply append list-of-list) (concatenate list-of-list)) ((filter (lambda (x) (not (pred x)) body) ls) (remove pred ls))) 9
おわり/あとでやること 今後実装する手続き(ライブラリ) ・行数とか頭の空白情報を保持するreader ・いいかんじに成形するwriter 出力のフィルタリング やってみたいこと ・初心者が書いたSchemeコードを入力してみたい AtcoderとかQiitaに転がってそう 典型的な冗長なコードからチェックパターンを増やせると思う
10