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
540
scheme-small-linter.pdf
Niyarin
April 30, 2020
Tweet
Share
More Decks by Niyarin
See All by Niyarin
Scheme用nREPLの開発(エラー出力の改善)
niyarin
0
150
bel lispの紹介
niyarin
0
730
nanopass-compiler-frameworkを使ってみました
niyarin
0
420
Gorgos-parser-combinator-written-in-scheme
niyarin
0
390
outputting-beautiful-s-expression
niyarin
0
380
Serialisp
niyarin
1
660
Mongo DBとS式検索
niyarin
0
310
goodbye-python-repl
niyarin
0
350
SchemeのEphemeronとWeak Pairの説明
niyarin
0
1k
Other Decks in Programming
See All in Programming
Result型で“失敗”を型にするPHPコードの書き方
kajitack
4
260
datadog dash 2025 LLM observability for reliability and stability
ivry_presentationmaterials
0
110
deno-redisの紹介とJSRパッケージの運用について (toranoana.deno #21)
uki00a
0
140
技術同人誌をMCP Serverにしてみた
74th
0
280
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
170
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
45
30k
Blazing Fast UI Development with Compose Hot Reload (droidcon New York 2025)
zsmb
1
190
git worktree × Claude Code × MCP ~生成AI時代の並列開発フロー~
hisuzuya
1
420
A comprehensive view of refactoring
marabesi
0
970
Railsアプリケーションと パフォーマンスチューニング ー 秒間5万リクエストの モバイルオーダーシステムを支える事例 ー Rubyセミナー 大阪
falcon8823
4
910
VS Code Update for GitHub Copilot
74th
1
300
「Cursor/Devin全社導入の理想と現実」のその後
saitoryc
0
140
Featured
See All Featured
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
RailsConf 2023
tenderlove
30
1.1k
How to Think Like a Performance Engineer
csswizardry
24
1.7k
Balancing Empowerment & Direction
lara
1
360
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Building Applications with DynamoDB
mza
95
6.5k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
How to Ace a Technical Interview
jacobian
277
23k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
48
5.4k
The Invisible Side of Design
smashingmag
299
51k
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