[{a :a} {b :b}]
のようなバインディングフォームを指定すると、どのようにすべてのシンボルを見つけることができますか? (a b)
バインディングフォームですべてのシンボルを見つける方法はありますか?
答えて
はナイーブなアプローチは、単にいくつかのネストされたコレクションとして結合フォームを処理することで、そのコレクション内のすべてのシンボルを見つけ、それらのシンボルのシーケンスを返します:
(defn symbols [x]
(filter symbol? (tree-seq coll? seq x)))
(symbols '[{a :a} {b :b}])
;;=> (a b)
しかし、@amalloy noted、このようすべての場合に機能しません。
;; & isn't actually bound to anything
(symbols '[foo & bar])
;;=> (foo & bar)
;; duplicates
(symbols '{x :foo :or {x :bar}})
;;=> (x x)
;; keys and default values are evaluated, not bound
(symbols '{x (keyword "foo") :or {x (keyword 'bar)}})
;;=> (x keyword x keyword quote bar)
;; namespaced keywords and symbols don't work
(symbols '{:keys [::foo :bar/baz qux/quux]})
;;=> (qux/quux)
彼は代わりにビルトインdestructure
機能を使用することを提案しているが、彼は彼の答えに示されているように、これはいくつかのゴミがに表示する原因:ここではsymbols
の上記の実装は望ましくない結果を与えるいくつかの例があります結果:
(take-nth 2 (destructure '[{:keys [x]} (last y)]))
;;=> (map__10938 map__10938 x)
この技術的にている間はmap__10938
はちょうど実装の成果物であることを、Clojureのは、結合するシンボルのリストを与え、非構造言語自体とは何の関係もありません。
はありがたいことに、それは手動で結合フォームを解析し、束縛されるだろう、元の結合形式、から取られたシンボルのセットを組み立てるにはあまりにも難しいことではありません。
(require '[clojure.set :as set])
(defn symbols [binding]
(cond
(symbol? binding)
#{binding}
(vector? binding)
(apply set/union (map symbols (remove #{'& :as} binding)))
(map? binding)
(apply set/union
(for [[k v] binding]
(case k
:or #{}
:as #{v}
(:keys :strs :syms) (set (map (comp symbol name) v))
(symbols k))))))
素晴らしい、ありがとう! –
これは私にはかなり良く見えます。あなたは、 '' case k:や#{}の場合、#{v}、(:keys:strs:syms)(set ...)、(symbols k) – amalloy
@amalloyクール、ありがとう! :)私は、あなたが「ケース」でそれを行うことができるかどうかを知りませんでした。 –
はるかに良いclojure.core/destructure
を使用することで、分割される値ではなく、どのシンボルが束縛される名前であるかを理解します。たとえば、考えてみます。その意味で
(let [{:keys [x]} (last y)]
x)
を、あなたはほぼ確実にあなたがより良い非構造仕様を理解するために、これを使用していることを前提とし、シンボルのリストにlast
を含める必要はありません。そして、あなたはdestructure
を呼び出す場合、それは名前がどの値にバインドされます正確に何を説明します:
user> (destructure '[{:keys [x]} (last y)])
[map__10938 (last y)
map__10938 (if (clojure.core/seq? map__10938)
(clojure.lang.PersistentHashMap/create (clojure.core/seq map__10938))
map__10938)
x (clojure.core/get map__10938 :x)]
は今、一方では、あなたが実際に、発信者が入力したいませんでしたシンボルを取得しているが、それはおそらくですこれはlet
の式を処理するためにClojureが実際に何を行うのかを示すため、まだ便利です。左辺、つまり束縛される名前を取得するには、
(take-nth 2 (destructure '[{:keys [x]} (last y)]))
彼はバインディングの両方の半分を見ることを要求していません(例えば、 '[{:keys [x]}(last y)]');彼はバインディングの*左*側にシンボルを見つけるだけです。たとえば、式は '({[{a:{b:b}] [{:a:foo} {:b:bar}]] [ab])'のように見えるかもしれません。彼の質問だけで、彼は '[{a:a} {b:b}]'の部分でシンボルを探したいと思っています。 –
左半分しか持っていない場合でも、束縛される名前ではない記号が入っていることがあります。たとえば、 '{:keys [x]:or {x(range 10)}}' - 本当にこの関数から 'range'が返されますか? – amalloy
ああ、クール!私は[Clojure destructuring guide](http://clojure.org/guides/destructuring)に戻ってきました。私が知らなかった破壊をすることができるたくさんのものがあるようです。私はそれらの複雑さを反映するために私の答えを編集しました。 –
- 1. Herokuでメモリリークを見つける方法はありますか?
- 2. コントロールのオーナースレッドを見つける方法はありますか?
- 3. jQueryを使用して値のリストですべてのオプションを見つける方法はありますか?
- 4. 一度にプロジェクトのすべての「重複シンボル」エラーを見つける方法
- 5. カスタムmongo dbpathを見つける方法はありますか?
- 6. シンボルのリストを見つけるためのソースはありますか?
- 7. Pythonで正規表現にマッチするものをすべて見つける方法はありますか?
- 8. EclipseでJavaのすべての同期を同じモニターで見つける方法はありますか?
- 9. 1つのメインドメインの既存のサブドメインをすべて見つける方法はありますか?
- 10. 円内のすべてのブロックをグリッド内で見つける方法はありますか?
- 11. svnでファイルのすべてのコピーを見つける方法はありますか?
- 12. バイナリ検索で一致する値をすべて見つける方法はありますか?
- 13. pythonの関数のすべてのkwargをcliから見つける方法はありますか?
- 14. SVNブランチから作成されたすべてのブランチを見つける方法はありますか?
- 15. 有向グラフのノードへのすべての着信エッジを見つける方法はありますか?
- 16. 私のDelphiアプリケーション内のすべてのユニットを見つける方法はありますか?
- 17. 権限のないすべての.gitメッセージを見つける方法はありますか?
- 18. JMSトピックのすべてのサブスクライバを見つける方法はありますか?
- 19. PowerShellにディレクトリ内のすべてのファイルを見つける方法はありますか?
- 20. 地図に添付されたすべてのオーバーレイを見つける方法はありますか?
- 21. JAVAで何かを見つける方法はありますか?
- 22. AndroidアプリでChromeカスタムタブのユーザーエージェントコードを見つける方法はありますか?
- 23. タグで親オブジェクトの子オブジェクトを見つける方法はありますか?
- 24. JavaでZipFileエントリのファイルオフセットを見つける方法はありますか?
- 25. 私のプロパティでXamarin.Android v4サポートを見つける方法はありますか?
- 26. travisでホストマシンのネットワークIPアドレスを見つける方法はありますか?
- 27. Javaで変数の長さを見つける方法はありますか?
- 28. ポジションの近くでポジションを見つける方法はありますか?
- 29. C/C++でデバイスのマウントポイントを見つける方法はありますか?
- 30. Cでタップアダプタのブリッジデバイス名を見つける方法はありますか?
を '&'と '_'を数えますか? –
ああ、私はそれらを考慮していなかったが、はい、私は出力からそれらを削除することができます。 –