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
450
Gorgos-parser-combinator-written-in-scheme
niyarin
0
390
outputting-beautiful-s-expression
niyarin
0
400
Serialisp
niyarin
1
680
Mongo DBとS式検索
niyarin
0
330
goodbye-python-repl
niyarin
0
370
SchemeのEphemeronとWeak Pairの説明
niyarin
0
1k
Other Decks in Programming
See All in Programming
Blazing Fast UI Development with Compose Hot Reload (Bangladesh KUG, October 2025)
zsmb
2
500
競馬で学ぶ機械学習の基本と実践 / Machine Learning with Horse Racing
shoheimitani
0
130
Phronetic Team with AI - Agile Japan 2025 closing
hiranabe
0
230
例外処理を理解して、設計段階からエラーを見つけやすく、起こりにくく #phpconfuk
kajitack
12
5.7k
オフライン対応!Flutterアプリに全文検索エンジンを実装する @FlutterKaigi2025
itsmedreamwalker
1
140
MCPサーバー「モディフィウス」で変更容易性の向上をスケールする / modifius
minodriven
7
1.4k
Eloquentを使ってどこまでコードの治安を保てるのか?を新人が考察してみた
itokoh0405
0
3.1k
『HOWはWHY WHATで判断せよ』 〜『ドメイン駆動設計をはじめよう』の読了報告と、本質への探求〜
panda728
PRO
1
460
エンジニアに事業やプロダクトを理解してもらうためにやってること
murabayashi
0
140
PyCon mini 東海 2025「個人ではじめるマルチAIエージェント入門 〜LangChain × LangGraphでアイデアを形にするステップ〜」
komofr
3
900
組織もソフトウェアも難しく考えない、もっとシンプルな考え方で設計する #phpconfuk
o0h
PRO
10
4k
イベントストーミングのはじめかた / Getting Started with Event Storming
nrslib
1
180
Featured
See All Featured
It's Worth the Effort
3n
187
28k
Raft: Consensus for Rubyists
vanstee
140
7.2k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
A Modern Web Designer's Workflow
chriscoyier
697
190k
[RailsConf 2023] Rails as a piece of cake
palkan
57
6k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.2k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
The Art of Programming - Codeland 2020
erikaheidi
56
14k
Why Our Code Smells
bkeepers
PRO
340
57k
A designer walks into a library…
pauljervisheath
210
24k
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