Fork me on GitHub
#clojure-russia
<
2018-08-02
>
ilevd06:08:18

(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))))))))

dottedmag11:08:43

Ну я посмотрел в re-seq и какое-то оно непонятное.

dottedmag11:08:53

Мой вариант читабельнее IMHO.

dottedmag11:08:11

Вместо (take-while some? %) нет ничего в стандартной библиотеке?

anjensan11:08:52

кмк в этом варианте не хватает тайпхинтов в определении find-match-loc

anjensan11:08:39

ну или еще лучше объявить ее локально как анонимную функцию в re-seq-loc, тогда тайпхинты не нужны

dottedmag11:08:42

Интересно, даже без тайпхинтов *warn-on-reflection* не приводит к предупреждению.

dottedmag11:08:47

Как бы понять, почему?

anjensan11:08:33

у меня приводит. 1.8

anjensan11:08:25

3 ворнинга, на .find, .start и .end

dottedmag11:08:35

% 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=>

anjensan11:08:51

так оно ворнинги кидает при компиляции и не при выполнении

dottedmag11:08:16

Да, действительно.

dottedmag11:08:36

Спасибо.

ilevd11:08:36

(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)})))

ilevd11:08:05

Если что, можно :index добавить)

dottedmag14:08:03

Тогда уж

(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)})))

dottedmag14:08:42

Что-то мне подсказывает, что здесь ленивые последовательности могут что-то сломать.

ilevd15:08:51

Вообще, конечно, да, шляпно, лучше даже (repeatedly #(.find m)) не делать, вдруг захочется/нужно будет обернуть в (map или еще как-нибудь

ilevd15:08:57

Хотя бы уж в одном блоке .find / .end / .start

ilevd15:08:02

Как изначально было

anjensan15:08:20

конкретно в этом случае может глукануть из-за того, что (range) это chunked-seq

ilevd15:08:25

Тут из-за stateful объекта сам собой напрашивается императивный подход, создать transient [], в конце, (persistent), как на питоне бы делали. А чтобы их не городить - рекурсия, как в исходниках re-seq.

ilevd15:08:48

Проще на ее основе сделать и забыть)

anjensan15:08:21

а transient то зачем?

ilevd15:08:58

Ну чтобы conj! 🙂

anjensan15:08:41

ну тут выигрышь по скорости будет.. эм.. не очень большой 😃

ilevd15:08:25

Ну это я привел пример как звено через которое можно прийти к рекурсии и тому что написано в re-seq 🙂

ilevd15:08:25

Потому что да, увидеть transient/persistent в коде это странно)