Можете ли вы привести мне несколько реальных примеров использования макроса ->?
Вопрос
Кажется, это мощный макрос, но я не могу применить его ни к чему, кроме глупых примеров.Можете ли вы показать мне, как это можно использовать на самом деле?
Спасибо!
Решение
Сравнивать:
user> (:baz (:bar (:foo {:foo {:bar {:baz 123}}})))
123
user> (java.io.BufferedReader. (java.io.FileReader. "foo.txt"))
#<BufferedReader java.io.BufferedReader@6e1f8f>
user> (vec (reverse (.split (.replaceAll (.toLowerCase "FOO,BAR,BAZ") "b" "x") ",")))
["xaz" "xar" "foo"]
к:
user> (-> {:foo {:bar {:baz 123}}} :foo :bar :baz)
123
user> (-> "foo.txt" java.io.FileReader. java.io.BufferedReader.)
#<BufferedReader java.io.BufferedReader@7a6c34>
user> (-> "FOO,BAR,BAZ" .toLowerCase (.replaceAll "b" "x") (.split ",") reverse vec)
["xaz" "xar" "foo"]
->
используется, когда вам нужен краткий способ вложения вызовов.Он позволяет вам перечислять вызовы в том порядке, в котором они будут вызываться, а не в порядке их вызова, что может быть более читабельным.В третьем примере обратите внимание, какое расстояние между некоторыми аргументами и функцией, которой они принадлежат; ->
позволяет более четко группировать аргументы и вызовы функций.Поскольку это макрос, он также работает для вызовов Java, и это приятно.
->
это не так уж и мощно, просто время от времени экономит вам несколько пар паренков.Использовать его или нет — вопрос стиля и читабельности.
Посмотрите на нижнюю часть Clojure.zip для крайних примеров того, как это полезно.
(-> dz next next next next next next next next next remove up (append-child 'e) root)
Другие советы
Взято из Вики Я всегда находил этот пример впечатляющим:
user=> (import '(java.net URL) '(java.util.zip ZipInputStream))
user=> (-> "http://clojure.googlecode.com/files/clojure_20081217.zip"
URL. .openStream ZipInputStream. .getNextEntry bean :name)
Как сказал Брайан, это не столько "полезно", сколько "отличается стилем".Я нахожу для всех взаимодействий Java такую форму "начните с X", затем выполните Y и Z...более читабельно, чем делать от Z до Y из X.
В принципе, у вас есть 4 варианта:
; imperative style named steps:
(let [X something
b (Y X)
c (Z b)] c)
; nested calls
(Z (Y X))
; threaded calls
(-> X Y Z)
; functional composition
((comp Z Y) X)
Я нахожу, что -> действительно подходит для взаимодействия с java, но избегайте его в другом месте.
(defn search-tickets-for [term]
(-> term search zip-soup first :content
((partial filter #(= :body (:tag %)))) first :content
((partial filter #(= :div (:tag %))))
((partial filter #(= "content" ((comp :id :attrs) %))))
((partial map :content)) first ((partial map :content))
((partial map first)) ((partial filter #(= :ul (:tag %)))) first :content
((partial map :content))
((partial map first))
((partial mapcat :content))
((partial filter #(= :h4 (:tag %))))
((partial mapcat :content))
((partial filter #(= :a (:tag %))))
((partial mapcat :content))))
Clojurebot из #clojure использует это для поиска билетов на ассемблу.