clojure-russia

Работа и релокейт: #jobs-rus | #clojure-russia-offtop Телеграм-чат https://t.me/clojure_ru
ilevd 2018-08-02T06:50:18.000086Z

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

ilevd 2018-08-02T06:51:04.000107Z

Если взять за основу https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L4821-L4824

dottedmag 2018-08-02T11:10:43.000197Z

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

dottedmag 2018-08-02T11:10:53.000146Z

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

dottedmag 2018-08-02T11:12:11.000249Z

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

anjensan 2018-08-02T11:13:52.000073Z

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

anjensan 2018-08-02T11:14:39.000117Z

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

dottedmag 2018-08-02T11:16:42.000080Z

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

dottedmag 2018-08-02T11:16:47.000057Z

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

anjensan 2018-08-02T11:17:33.000037Z

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

anjensan 2018-08-02T11:18:25.000271Z

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

dottedmag 2018-08-02T11:19:33.000098Z

1.9, гм

dottedmag 2018-08-02T11:19:35.000112Z

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

anjensan 2018-08-02T11:19:51.000291Z

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

dottedmag 2018-08-02T11:19:58.000240Z

опс

dottedmag 2018-08-02T11:20:16.000140Z

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

dottedmag 2018-08-02T11:20:36.000105Z

Спасибо.

ilevd 2018-08-02T11:54:36.000367Z

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

ilevd 2018-08-02T11:56:05.000264Z

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

dottedmag 2018-08-02T14:02:03.000315Z

Тогда уж

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

dottedmag 2018-08-02T14:02:42.000410Z

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

ilevd 2018-08-02T15:11:51.000534Z

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

ilevd 2018-08-02T15:12:57.000430Z

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

ilevd 2018-08-02T15:13:02.000425Z

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

anjensan 2018-08-02T15:13:20.000453Z

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

ilevd 2018-08-02T15:16:25.000319Z

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

ilevd 2018-08-02T15:16:48.000582Z

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

anjensan 2018-08-02T15:17:21.000156Z

а transient то зачем?

ilevd 2018-08-02T15:17:58.000539Z

Ну чтобы conj! 🙂

anjensan 2018-08-02T15:18:41.000222Z

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

ilevd 2018-08-02T15:19:25.000142Z

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

ilevd 2018-08-02T15:20:25.000509Z

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