(defn re-seq-loc [re s]
(let [m (re-matcher re s)]
((fn step []
(when (. m (find))
(cons {:start (.start m)
:end (.end m)
:match (re-groups m)} (lazy-seq (step))))))))
Если взять за основу https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L4821-L4824
Ну я посмотрел в re-seq
и какое-то оно непонятное.
Мой вариант читабельнее IMHO.
Вместо (take-while some? %)
нет ничего в стандартной библиотеке?
кмк в этом варианте не хватает тайпхинтов в определении find-match-loc
ну или еще лучше объявить ее локально как анонимную функцию в re-seq-loc, тогда тайпхинты не нужны
Интересно, даже без тайпхинтов *warn-on-reflection*
не приводит к предупреждению.
Как бы понять, почему?
у меня приводит. 1.8
3 ворнинга, на .find, .start и .end
1.9, гм
% clj
Clojure 1.9.0
user=> (require 'mg.dt.accounting.util)
nil
user=> (set! *warn-on-reflection* true)
true
user=> (mg.dt.accounting.util/re-seq-loc #"." "abcdef")
({:start 0, :end 1, :match "a"} {:start 1, :end 2, :match "b"} {:start 2, :end 3, :match "c"} {:start 3, :end 4, :match "d"} {:start 4, :end 5, :match "e"} {:start 5, :end 6, :match "f"})
user=>
так оно ворнинги кидает при компиляции и не при выполнении
опс
Да, действительно.
Спасибо.
(defn re-seq-loc [re s]
(let [m (re-matcher re s)]
(for [_ (range) :while (.find m)]
{:start (.start m)
:end (.end m)
:match (re-groups m)})))
Если что, можно :index добавить)
Тогда уж
(defn re-seq-loc [re s]
(let [m (re-matcher re s)]
(for [found (repeatedly #(.find m)) :while found]
{:start (.start m)
:end (.end m)
:match (re-groups m)})))
Что-то мне подсказывает, что здесь ленивые последовательности могут что-то сломать.
https://stuartsierra.com/2015/08/25/clojure-donts-lazy-effects
Вообще, конечно, да, шляпно, лучше даже (repeatedly #(.find m)) не делать, вдруг захочется/нужно будет обернуть в (map или еще как-нибудь
Хотя бы уж в одном блоке .find / .end / .start
Как изначально было
конкретно в этом случае может глукануть из-за того, что (range) это chunked-seq
Тут из-за stateful объекта сам собой напрашивается императивный подход, создать transient [], в конце, (persistent), как на питоне бы делали. А чтобы их не городить - рекурсия, как в исходниках re-seq.
Проще на ее основе сделать и забыть)
а transient то зачем?
Ну чтобы conj! 🙂
ну тут выигрышь по скорости будет.. эм.. не очень большой 😃
Ну это я привел пример как звено через которое можно прийти к рекурсии и тому что написано в re-seq 🙂
Потому что да, увидеть transient/persistent в коде это странно)