スキームにおけるパターンマッチングのためのドット付き対アナログ(及びCL)はcons
た細胞の両方の要素が明示的に指定されて点在対(例えば(1 . 2)
)はなく、暗黙的により(例えば(1 2)
(1 . (2 . nil))
として読み出されます)。Clojureの
私は例えば、点線のペアが一致しているオブジェクトにリストの最後尾をキャプチャするためにパターンマッチングに使用されている。このpuzzle出くわし:
(pmatch '(foo . (? pvar)) '(foo bar baz))
;; => ((pvar bar baz))
ここ'(foo . (? pvar))
がパターンであると'(foo bar baz)
がオブジェクトでありますパターンと一致する。パターン内のfoo
はリテラルですが、(? pvar)
は(bar baz)
に一致するパターン変数であり、その一致にシンボルpvar
をバインドします。 pmatch
関数は、パターン変数とバインドされた一致の関連リストを返します。
パターンが'(foo (? pvar))
の場合、baz
はパターン内の何も一致しないため、一致は失敗します。
私はClojureでパズルを実装しました。JRMのテストケースのすべてをドットペアのものから分離しています。私はおそらくドットペアパターンもサポートする方法を理解しようとしています。
は、ここに私の現在のソリューションです:
(defn pattern-variable? [pv]
(when (seq? pv)
(let [[qmark var] pv]
(and (= (count pv) 2)
(= qmark '?)
(or (symbol? var)
(keyword? var)))))
(defn pattern-variable [pv]
(second pv))
(defn pmatch
([pat obj] (pmatch pat obj {}))
([pat obj binds]
(cond (not (coll? pat))
(when (= pat obj) binds)
(pattern-variable? pat)
(assoc binds (pattern-variable pat) obj)
(seq? pat) (let [[pat-f & pat-r] pat]
(when (seq? obj)
(when-let [binds (pmatch pat-f (first obj) binds)]
(pmatch pat-r (next obj) binds))))
:else nil)))
それでは、どのように私は、ドット付きペアなしのClojureでのオブジェクトの残りの部分に一致するパターンをサポートすることができますか?
ニースの仕事!マルチメソッドはコードを明確にします。私は同じパターン変数の以前の束縛を探している場所で 'pmatch *' ':walk'にバグがあると思います。 '' if-let [[_ xs](find bs(var-name bs) – liwp
また、質問を書いている間、私は '.'や'& 'を区切り記号として使うことを考えました。(区切り記号としては、' .bs(var-name p)パターン変数は区切り文字の後ろにあるオブジェクトの末尾にマッチしますが、 '〜'と '〜@'を使うのがはっきりしていますが、もう一つ心配しておいたのは、 '(foo。(?var)bar)'は違法であるべきで、これはあなたの解決策においても問題が残っていると思うのに対し、Schemeでは読者がそれを世話するだろうと考えています。 – liwp
ああ、また、 '(foo。(?var)bar)'スタイルパターンについて合意しました;私は ':walk'に特別なチェックを追加して、そのようなパターンとのマッチを常に失敗させました。 –