22
美しいlispの書きかた ~コーディングルール事始め~

kyotolisp#1 LT3 美しいLispの書き方 (1)

Embed Size (px)

DESCRIPTION

kyotolisp#1 (kyotolisp.github.com) で発表した内容です。スライドは(2)に続きます。

Citation preview

Page 1: kyotolisp#1 LT3 美しいLispの書き方 (1)

美しいlispの書きかた

~コーディングルール事始め~

Page 2: kyotolisp#1 LT3 美しいLispの書き方 (1)

自己紹介

ます。github.com/insanityです。ときおりWiki{pedia,books}に出没し

得意な方言はSchemeです。

今年で使い初めてから4年目です。

Gaucheが便利過ぎてしねる。

レンダリングされています。ちなみにこのスライドもlibcairo on Gauche with c-wrapper で

er で晒してます。現状カオスなコードですが一応 github/insanity/lightcontain

Page 3: kyotolisp#1 LT3 美しいLispの書き方 (1)

自己紹介 (続き)エディタはいつもvimを使っています。

える作りが好きなのです。.el を書くまでもなく、その場のコマンドで定型作業をサクッと終

ないです。というわけで、今回の話はemacsに全部お任せでOKという結論では

Page 4: kyotolisp#1 LT3 美しいLispの書き方 (1)

今日の話題

せっかくなら、読みやすいlispを書きたい。

マクロ展開形やVMの中間表現を少しでも読みやすく表示したい。

過去に書きなぐったコードを、見栄えだけ良くしたい。

元ネタ

Riastradh's Lisp Style Rules by Taylor R. Campbell

(http://mumble.net/~campbell/scheme/style.txt)

Page 5: kyotolisp#1 LT3 美しいLispの書き方 (1)

名前づけ

Page 6: kyotolisp#1 LT3 美しいLispの書き方 (1)

常識ですが...

variable-with-long-name

をハイフンを割り当てると便利です。(linuxならxmodmap)

Lispの変数はハイフンでつなぎます。日本語キーボードで変換キー

*global-variable*

かもしれない、という警告の意味で(多分)、強調します。

グローバル変数です。グローバル変数は副作用によって変更される

と思います。

定数を表すときもあります。SOME-CONSTANTよりかは読みやすい

+some-constant+と書く流派もあるようです。

Page 7: kyotolisp#1 LT3 美しいLispの書き方 (1)

コードレイアウト (スペースの入れ方)

Page 8: kyotolisp#1 LT3 美しいLispの書き方 (1)

はじめに

ます。

S式のコードの見た目は、スペースと改行の入れ方でほとんど決まり

だから、スペースと改行の入れ方は大事です。

Page 9: kyotolisp#1 LT3 美しいLispの書き方 (1)

タブか、スペースか

すすめです。

lispではインデント揃えを使うので、タブ幅で悩まないスペースがお

どうしてもタブがいい人は、タブ幅を書いてくれると(僕が)うれしい

; -*- tab-width: 8 -*- ; vim:ts=8

Page 10: kyotolisp#1 LT3 美しいLispの書き方 (1)

ネスト(cdr (assq 'banana '( (banana . 138) (apple . 80))))

普通、括弧はまとめて閉じます。

Page 11: kyotolisp#1 LT3 美しいLispの書き方 (1)

インデント量はスペース1つでも大丈夫ですが,

(インデント量が

(多すぎると、

(すぐに

(横幅を

(使い切ってしまい

(困ります))))))

そもそも読みにくいと思います。

Page 12: kyotolisp#1 LT3 美しいLispの書き方 (1)

ネスト (続き)

項目の一覧表では、

((item "banana") (item "apple") (item "orange") )

と閉じ括弧だけの行を残すと、項目の追加がやりやすくなります。

見栄え的にはちょっと微妙ですが。

Page 13: kyotolisp#1 LT3 美しいLispの書き方 (1)

ネスト (続き)

誤解のおそれのないときは、深さを省略しても大丈夫です(多分)。

(define (get-continuaction) (call/cc (lambda (cont) (cont cont))))

くなるのでちょっと横着しています。

Schemeではlambdaをやたらめったら使うので、ネストがすぐに深

方が読みやすい。

mapfor-eachでは、手続きとリストを区別するために、省略しない

Page 14: kyotolisp#1 LT3 美しいLispの書き方 (1)

閉じ括弧を優雅に見せようとして、

(define (any pred lst) (cond ((null? args) #f) ((pair? args) (or (pred (car lst)) (any pred (cdr lst)))) ) )

います。(なのでemacsマクロが必須だとか。

と書く人[Gassanenko,2001]もいるそうですが、論理的に矛盾して

るのがベストと思っています。

視覚的情報は括弧に頼らず、インデントの深さで判断するようにす

Page 15: kyotolisp#1 LT3 美しいLispの書き方 (1)

縦モードと横モード

横モード

普通は横につなげて書きます。

(map * '(1 2 3) (iota 3 2 0.1))

縦モード

括弧の中身が長くなったときは、括弧の中身を縦につなげます。

(map * '(1 2 3) (iota 3 2 0.1))

Page 16: kyotolisp#1 LT3 美しいLispの書き方 (1)

縦モードと横モード (続き)

横モード → 縦モードへの移行は可ですが、それ以外は不可です。

Page 17: kyotolisp#1 LT3 美しいLispの書き方 (1)

例(let1 ht (make-hash-table) body ...)

(if (not (is-a? language 'lisp)) (error "Please speak it in Lisp!.") (eval input env))

;XXX(http-post http-client server port path `((id ,(sanitize (get-config 'user-id)) '((timeout 2000) (follow-redirect #f))

Page 18: kyotolisp#1 LT3 美しいLispの書き方 (1)

の多いS式は、最初から縦モードで書くのがおすすめです。

平行四辺形コードは、上から下へ流れるように読めるので、ネスト

例外

に並べたほうが見やすいです。

:keyword value の組や、arc のように括弧が書略されている時は横

Page 19: kyotolisp#1 LT3 美しいLispの書き方 (1)

深さインデントと、揃えインデント

深さインデントは、純粋に括弧の深さでスペースの量を決めます。

(define (is-a? obj type) (eq? (car obj) type))

(defun is-a? (obj type) (eqp (car obj) type))))

Page 20: kyotolisp#1 LT3 美しいLispの書き方 (1)

わせる方式です

揃えインデントは、第一引数の位置に、それ以後の引数の位置を合

(list (apply average lis) (apply min lis) (apply max lis))

さインデントが好みです。

するとコードがすぐに右へ飛んでいってしまうので、個人的には深

揃えインデントの方をCanonicalとみなす人が多いようですが、多用

letの束縛部、and, or, list, 四則演算に限って使うことにしています

Page 21: kyotolisp#1 LT3 美しいLispの書き方 (1)

cond, caseの書きかた

条件部を見やすく揃えるのが大事です。

(cond ((pred a) ...) ((pred b) ...)(cond ((pred a) ... ... ) ((pred b) ... ... ))

どちらかに統一するといい感じです。

Page 22: kyotolisp#1 LT3 美しいLispの書き方 (1)

空行

に空行を入れるのはありだと思います。

にのみ使います。ただし、「手続き型」の関数で、コメント行の前

基本的には、トップレベル定義の区切り、internal defineの区切り

(define (test) (define (test-aux-1) ... )

(define (test-aux-2) ... )

body ... )