clojure-russia 2018-08-02

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

а transient то зачем?

Ну чтобы conj! 🙂

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

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

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