valvallowさんを真似て、github使ってみようかな、と。
まあ、単に今のままでは、ブログにコード貼り付けると、<pre>タグ使っててもインデントがズレて嫌なわけですよ。どうにかなんねえのかな、とか思ってて。
んで、valvallowさんがgist使ってうまい具合にやってるんで、それを真似してみよう、って思ったわけです。で、まあ、gitそのものは要らなかったよね(笑)。gistとgitって違うみてえ(笑)。レポジトリ、なんて作らんで良かった、って話なんですが(笑)。単にアカウント取れば良かっただけの話、と言うオチ(笑)。
それはさておき。LOLをvalvallowさんに続いて読んでるわけですが。他の人の意見はともかくとして読みづれえ。
いや、地の文体がどーの、って話じゃないです。単にコードが読みづらいって話なんだよな(苦笑)。精読試みると引っかかっていけねえや。
第3章、リードマクロからもうこれが破壊的操作の嵐でさ(苦笑)。こんなんここまでやる必要あんのか?とかぶっちゃけ思ってしまいました。もちろん、効率性考えれば必要になるケースってのがあるんですが、僕が思うトコ、この著者って美的観点ってのが全くねえんじゃねえの、とか思ってるのです(笑)。不遜ですけどね。
いやね、実際問題。無頓着にコード書いてるようにしか見えないし、心情的にはSchemerの筈のポール・グレアムも「こりゃあねえだろ」と思うんじゃねえのかな、と(笑)。そこまでいかんでも、ここに列挙されてるコードを他の言語のユーザーが見たら
「不必要に括弧が多すぎ!これだからLisperはよお。」
とか思うんじゃねえのか、と(笑)。ケンケンガクガクですよ(笑)。マジな話でさ。
リードマクロって考え方自体は単純ですよね。単に関数書いてやって、それを
set-dispatch-macro-character
で文字指定してやってその関数と関連付けちゃえばおしまい、です。普通にマクロ書くよりラクかもしれませんね。set-dispatch-macro-character
って長ったらしい名前もEmacs + SLIMEだったらEsc-Tabで補完しちゃえばラクラク記述可能です。Viva! Emacs!問題はその関数の書き方だ。個人的には川合史朗さんが何でも再帰で記述してたような「ローカル関数を設計」してやった方が見た目スッキリすんじゃねえの?とか思うんですけどねえ。生粋のCLerだと違うのかな。
do
は副作用使う時は確かに便利なんですけど、このケースじゃそんなの多用する必然性がそんなねえんじゃねえの、って思いました。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; SHARP-DOUBLE-QUOTE | |
;; Scheme-style | |
(defun |#"-reader| (stream sub-char numarg) | |
(declare (ignore sub-char numarg)) | |
(labels ((iter (chars prev) | |
(let ((curr (read-char stream))) | |
(if (and (char= prev #\") (char= curr #\#)) | |
(reverse chars) | |
(iter (cons prev chars) curr))))) | |
(coerce (iter nil (read-char stream)) 'string))) | |
(set-dispatch-macro-character | |
#\# #\" #'|#"-reader|) |
まず最初。LOLのSHARP-DOUBLE-QUOTEを書き直したものです。多分Schemeやってる人はこっちの方が見やすいのでは、と思います。オリジナルのコードは破壊的操作しまくりですが、そのテの操作は一切止めています(笑)。
そもそも、Doug Hoyteって人は
defun
の「暗黙のprogn
」アテにし過ぎだろ、って気もしますしね。これは本読むと、結局欲しいのは(coerce (nreverse chars) 'string)
なんですけど、これは単にdo
の返り値にした方がいいんじゃねえの、って謎がまずあって。要するにオリジナルのコードはchar
を破壊的にdo
で弄くっていって、それはそれでほっといて、最後に(coerce (nreverse chars) 'string)
なわけですよ。何じゃそりゃ、とか思って(笑)。Lispがどうの、って以前にそれじゃあ手続き型言語のfor
文の書き方だろ(笑)。一方、
ignore
はCLHS見ても良く分かんなかったんで、そのまま挿入しています。ロジック考えると必ずしも必要である、とは思えないんですけどね。多分。ま、いいや、その辺はCLの流儀、と言う事で。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CL-USER> #" " と \. を含みます。"# | |
" \" と \\. を含みます。" | |
CL-USER> |
ってな感じで「Schemeっぽく」書いても問題なく動きますね。では次。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; SHARP-GREATER-THAN | |
;; Scheme-style | |
(defun |#>-reader| (stream sub-char numarg) | |
(declare (ignore sub-char numarg)) | |
(labels ((foo (chars curr) | |
(if (char= #\newline curr) | |
(reverse chars) | |
(foo (cons curr chars) (read-char stream)))) | |
(bar (curr pattern pointer output) | |
(if (null pointer) | |
(reverse (nthcdr (length pattern) output)) | |
(bar (read-char stream) pattern | |
(if (char= (car pointer) curr) | |
(cdr pointer) | |
pattern) (cons curr output))))) | |
(let ((pattern (foo nil (read-char stream)))) | |
(coerce (bar (read-char stream) pattern pattern nil) 'string)))) | |
(set-dispatch-macro-character | |
#\# #\> #'|#>-reader|) |
これも原版のコード見ても何が何だか……(苦笑)。いやあ、凹みましたよ(笑)。これもDoug Hoyte氏の手癖か何だか知らないんですが、やっぱり
defun
の暗黙のprogn
頼みのコードで。かつ破壊的操作をしまくりなんで、何が目的でどう操作してるのか、流れが掴み辛い。あんなにインデントが深くなる必要って全然ない、と思うんですけど。これも再帰に書き換えて、引数内処理した方がスッキリ決まるんじゃないか、って思いました。暗黙の
progn
頼みが何なのか、と言うと。要するに、データをループ回して操作して。それを置き去りにしてまた別にデータ持ってきてループ回してるわけです。それを逐次処理するってのがオリジナルのコードの狙いなわけですが。必要か、それ?とか思ってさ(笑)。しかも脱出条件が良く分からん。何で
(null pointer)
が二ヶ所に渡って分散してんだか、皆目見当が付かなかった(笑)。「何じゃこりゃ?」ってのが正直なトコで。破壊的操作を無自覚に使ってるからそーなるんだとしか思えなかった(笑)。そこで、上の関数ではローカル関数
foo
とbar
を二つ作って凌いでいます。根本的に、この二つの関数って「独立」で構わないんですよ。オリジナルのコードでも最初のループって、結局一種のフラグ作りなんですよね。本当にやりたい事は後者のループが握ってるんです。だから、シンプルにfoo
でフラグを作って、bar
で本操作をする、って設計にしました。やりようによってはもっとシンプルに書けるやもしれません。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CL-USER> #>END | |
ここには何でも置けますよ: "、\、"#、や ># だって | |
置けちゃう。この文字列の読み込みを終わらせるには...END | |
"ここには何でも置けますよ: \"、\\、\"#、や ># だって | |
置けちゃう。この文字列の読み込みを終わらせるには..." | |
CL-USER> |
RSS にコードが含まれなくなってしまうのが残念な感じです。
返信削除