clojure-russia

Работа и релокейт: #jobs-rus | #clojure-russia-offtop Телеграм-чат https://t.me/clojure_ru
akond 2018-07-15T13:48:42.000056Z

видно гитхаб не позволяет делать такие запросы

akond 2018-07-15T13:48:59.000130Z

406 всё-таки

igrishaev 2018-07-15T16:14:27.000045Z

@okilimnik Мне кажется проще завести edn-файл и постепенно наполнять данными. Если нужно много данных, посмотри либу test.check, у нее на борту хороший генератор. Он поддерживает в т.ч. генерацию связанных мам.

👍 1
dottedmag 2018-07-15T22:20:52.000007Z

Господа, а как бы вы делали такую вещь: есть у меня некий компонент (не в смысле com.stuartsierra/component) с состоянием. Чтобы его инициализировать, надо сделать три вещи по очереди (к примеру, создать директорию для временных файлов, открыть сокет к Selenium, создать в Selenium экземпляр браузера). Если какая-то из вещей ломается — надо откатить предыдущие. Если все три получились — надо компонент вернуть для вского разнообразного использования. Для деинициализации нужно все эти три вещи в обратном порядке отменить.

dottedmag 2018-07-15T22:23:28.000007Z

Т.е. хочется чего-то типа

(let [a (open-a)]
    (try
        (let [b (open-b a)]
            (try
                (let [c (open-c a b)]
                    (try
                        (do-some-stuff a b c)
                        (finally
                            (close-c c))))
                (finally
                    (close-b b))))
        (finally
            (close-a a))))

dottedmag 2018-07-15T22:25:01.000049Z

Но менее ужасное: do-some-stuff может быть асинхронным, длинным, и вообще хочется в этом месте точку возврата из функции, которая создаёт компонент.

dottedmag 2018-07-15T22:31:53.000022Z

Придумал нечто, но выглядит дико. Неужели лучше ничего не придумать?

(defn open []
    (let [a (open-a)]
        (try
            (let [b (open-b a)]
                (try
                    (let [c (open-c a b)]
                        {:a a :b b :c c})
                    (finally
                        (close {:a a :b b}))))
            (finally
                (close {:a a}))))

(defn close [{:keys [a b c]}]
    (when c
        (close-c c))
    (when b
        (close-b b))
    (when a
        (close-a a)))

;; usage
(let [session (open)]
    (try
        (do-some-stuff session)
        (finally
            (close session))))

ag 2018-07-15T22:47:51.000004Z

@dottedmag two words: "Integ" "rant" 😉

dottedmag 2018-07-15T22:50:22.000048Z

Integrant для "временной директории" как-то уж слишком монструозно.

dottedmag 2018-07-15T22:50:56.000002Z

Кроме того, у меня эти компоненты создаются и удаляются в runtime.

dottedmag 2018-07-15T22:51:05.000097Z

Открыл один, поработал с ним, закрыл, открыл другой...

ag 2018-07-15T22:54:17.000066Z

ну не знаю... imo integrant в самый раз тут

dottedmag 2018-07-15T23:01:47.000057Z

Интересно, как интегрант работает рекурсивно: получится ли создать компонент, в котором внутри делается (ig/init) / (ig/halt!)?

dottedmag 2018-07-15T23:02:51.000067Z

Да, в интегранте не видно глобального состояния никакого, можно попробовать.

ag 2018-07-15T23:11:22.000004Z

можно инитить ключи по отдельности или всю систему целиком

rustam.gilaztdinov 2018-07-15T23:36:53.000084Z

@dottedmag Мне кажется, mount отлично ляжет в задачу, он поддерживает порядок вызова, но там даже проще все, если сделать defstate зависимыми друг от друга, то порядок запуска и остановки учтется автоматически. Плюс он супер простой, буквально пару функций добавить.