COMMON LISP JP > Archives > 2015/07/04

2015/07/04 05:07:07 UTCy2q_actionman
#
「抽象化の漏れ」って、どのような意味で定義されてるんでしょうね。Lispの構文において、defmacroで拾えない文法要素ってあったかなあと考えると・・やはり「伝統的 vs 衛生的」という環境の話になるんでしょうか。
私個人は、運用でなんとかしてるので気にならない、という感じです。名前の衝突は gensym でどうにかしていて、マクロの使い間違いとかは、"define-***" とか "with-***" とか "do-***" とか、目的と使い方に応じた名前をつけて間違いにくくすることで回避してる気がします。
#
to
#
とか思いつつ話の出元を見たら、 Racket のマクロの話だそうで。以下のリンクに、まさに「エラーメッセージをなんとかしたいんだ!」っていう例が載ってますねhttp://docs.racket-lang.org/syntax/stxparse-intro.html
2015/07/04 05:36:35 UTCy2q_actionman
#
先のリンク先の mylet の例にある問題なんて、defmacroでも問題になりそうなんですが・・
#
運用(命名)で回避してたり、defmacroの入口でしつこく入力チェックしたり、「letは特殊オペレータなんだから、丸投げしても適切なエラーメッセージ出すでしょ」と思って実際に let に投げたりとかしてる気がします。
2015/07/04 05:41:50 UTCg000001
#
なるほど、難解なエラーメッセージはracketの話なんですかね
#
lispの古典マクロでいえば、
#
(defmacro mylet (binds &body body)
  (destructuring-bind (var val) binds
    `(let ((,var ,val))
       ,@body)))

(mylet (a)
       (list a))
error while parsing arguments to destructuring-bind:  invalid number of elements in (a)
to satisfy lambda list (var val): exactly 2 expected, but got 1
#
こういうやつですかね。
#
半分冗談ですが、ある種の構文の型のようなものの実現って、
#
(deftype bind-spec ()
  `(cons symbol (cons * null)))


(defmacro mylet (binds &body body)
  (check-type binds bind-spec "binding pairs (mylet)")
  (destructuring-bind (var val) binds
    `(let ((,var ,val))
       ,@body)))


(mylet "foo"
  a)
;!> The value of binds is "foo", which is not binding pairs (mylet).
#
でも良いじゃんって感じですね。
#
マクロ展開時のdestructuring-bind絡みのエラーは自分も嫌いですね。大体は自分が手抜きしてるのが悪いんですがw
#
まあシステムでどうにかしようって話ですね。それは良いことだと思います。
#
CLerは多分、プログラマが悪いんじゃないのかなあと考えそうなので、話が噛み合わないかもしれないですね。
2015/07/04 05:57:07 UTCy2q_actionman
#
そうですね。その前者の例のような話だと思います。エラーメッセージについては、僕も「プログラマがチェックすればいい」と思っちゃいます。
#
Racket no
2015/07/04 05:58:05 UTCshiro
#
抽象化の度合いが高いDSLをマクロで実装する場合、DSL上の字面が最終的なソースのいろんなところに影響を及ぼすので、なるべく上の方のレイヤでエラーを捕まえてくれたらいいのに、と思ったことはあります。
#
CLで、バイナリの構造体を定義すると型宣言含めた高速なアクセサマクロを生成するようなシステムをいじってたことがあるんですが、構造定義がマクロ生成マクロを生成するんだったかな。つまりDSL自体はマクロ生成マクロ生成マクロ。そんで、要素に使える型とかにわりと実装上の制限があったりして、特定の組み合わせだとうまく動かない、それも実行時にSEGVする、なんてことがありました。構造定義をmacroexpandしてもそれ自体がマクロ生成マクロの定義になってるので、それによって定義されるマクロを、それが使われる場面でもう一度展開してみないと何が起きてるかわからない。
#
そのくらいレイヤを積み重ねるなら、DSLとしてのロバストネスをもうちょい考えてくれたらなと思うんですが、そのシステム自体必要にせまられてどうしても要るところから作ってた感じだったからなあ。
2015/07/04 06:05:03 UTCg000001
#
そうですね、DSLの意味の枠内でエラーも出て欲しいというのはありますね。
#
マクロ生成マクロのデバッグも大変といえば大変ですね。私は最終手段的には、全部展開して貼り付けるというのを良くやりますが、まあ、あまり褒められた方法でもないですね:)
2015/07/04 06:12:37 UTCy2q_actionman
#
(Racket の define-syntax-class は、(当然ながら)エラーメッセージの改善だけではなく、もっと面白いことが出来るそうで。エラーメッセージの話だけにすると矮小でした。横道ですみません。)
2015/07/04 06:13:53 UTCg000001
#
call-with スタイルとかいうのはどんな形式のマクロでも割とデバッグしやすそうで良いかなと思ったりしています。
#
http://google.github.io/styleguide/lispguide.xml#Macros http://random-state.net/log/3390120648.html
#
どちらかというとマクロを書かない方向ですが
#
なるほど、自分もドキュメントを読んでみたいと思います :) > もっと面白いことが出来る。