Fork me on GitHub
#clojure-russia
<
2017-06-14
>
artemyarulin04:06:16

> (reduce inc 10 (range 5))
15
все ок

artemyarulin04:06:30

Даже чтоб понятней:

cljs.user=> (reduce #(do (println "NUM:" %) (inc %)) 10 (range 5))
NUM: 10
NUM: 11
NUM: 12
NUM: 13
NUM: 14
15

ilevd05:06:33

cljs.user 😐

ilevd05:06:35

По закону так: (reduce (fn [res _] (inc res)) 10 (range 5))

artemyarulin05:06:25

ааа, что-то ваша жвм кложа не динамичная совсем troll

artemyarulin05:06:18

(nth (iterate inc 10) 5)

artemyarulin05:06:30

iterate
function
Usage: (iterate f x)
Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects
Added in Clojure version 1.0
помнил же что есть чота похожее 🙂

ilevd05:06:03

(let [r (volatile! 10)]
  (dotimes [n 5]
    (vswap! r inc))
  @r)

ilevd09:06:20

(as-> 10 % (iterate inc %) (nth % 5)) что-то с макросом как-то не очень)

ilevd09:06:51

Может какой-нибудь такой сделать (%-> 10 (iterate inc %) (nth 5)) :thinking_face:

ilevd09:06:52

Или так (%->> 10 (iterate inc) (nth % 5))

misha10:06:02

Слишком редкий юзкейс, луковицы там достаточно

misha10:06:10

Кстати, итерейт наверное при первой реализации сделает 32 вызова, из которых ты только 5ый возьмешь, @artemyarulin

artemyarulin10:06:50

ааа, а я то думал почему в доке аж написано f must be free of side-effects. хотя вроде не

ilevd10:06:56

Нет, ну вообще, иногда бывает все укладывается хорошо в -> или ->>, а какой-нибудь один вызов нет

artemyarulin10:06:06

>(nth (iterate #(do (println "Yep") (inc %)) 10) 2)
Yep
Yep
Yep
Yep
Yep
15

razum2um11:06:21

есть какой-нибудь способ сделать stateful postwalk без атома https://gist.github.com/razum2um/b691ad0d760795efaeb886e6caf05122 ?

artemyarulin11:06:20

ну разве что тока через replace какой - обходя дерево выпиливать все что не нужно оставляя только то что ищешь чтоб в конце получить [1 2 3]

artemyarulin11:06:56

Может через

tree-seq 
Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
 branch? must be a fn of one arg that returns true if passed a node
 that can have children (but may not).  children must be a fn of one
 arg that returns a sequence of the children. Will only be called on
 nodes for which branch? returns true. Root is the root node of the
tree.
он вернет все, дальше фильтр и как раз получить что ищешь без атома

misha11:06:03

@razum2um тебе чтобы без ретраев просто?

misha11:06:32

или просто transient даже

razum2um11:06:10

@artemyarulin вот tree-seq я смотрел, но чет не осилил, не совсем то 🙂

razum2um11:06:59

@misha да нет, просто обойти дерево со стейтом без мутаций хочется 🙂

niquola13:06:52

@razum2um рекурсивный редьюс

razum2um13:06:31

@nicola да, я понимаю, что для функциональной аггрегации есть только reduce, но печалит, что надо самому повторять все ветвления из clojure.walk/walk и то, что postwalk работает по нужной схеме, прям как надо, но рядом ничего не протащить

niquola13:06:35

да ладно там 7 строчек 🙂 - скопипасти

niquola13:06:59

+ у тебя возможно своя логика обхода

niquola13:06:42

тупенький вариант

(defn reduce-walk [x acc f]
  (let [acc (f acc x)]
    (cond (map?  x) (reduce (fn [acc [k v]] (reduce-walk v acc f)) acc x)
          (coll? x)  (reduce (fn [acc v] (reduce-walk v acc f)) acc x)
          :else acc)))

(reduce-walk {:data 3 :children [{:children {:children []}}
                     {:children [{:children [] :data 1}]}
                                 {:children [] :data 2}]}
             [] (fn [acc x]
                  (if (:data x) (conj acc (:data x)) acc)))

rmuslimov13:06:34

Коллеги а посоветуйте про архитектуре приложений почитать что нибудь. У нас в проде появился SOAP сервер на clojure и вот он растет и растет и какой-то он не особо структурированный получается. Собственно я пришел с python django celery apps, там все как то просто с этим потому что фреймворк учил как организовать приложение и примеров полно. А тут как сложно мне приходится

niquola14:06:38

фишка clojure - что ты можешь структурировать под приложение - не воевать с framework - но собрать под свои нужды - о чем ваш сервис?

pavetok14:06:59

@razum2um вот тут несколько вариантов разобрано и есть пример кода для обхода со стейтом https://www.ibm.com/developerworks/library/j-treevisit/

rmuslimov14:06:11

@nicola приложение SOAP сервис который транслируются входящие запросы на другой внутренний сервис и содержит какую бизнес логику на своей стороне. Есть обработка валидация обработка ошибок и так далее

rmuslimov14:06:32

собственно проблемы начинаются с места когда в момент обработки запроса на какой то стадии мы можем решить вернуть ошибку. Или например ошибку скомбинировать с данными полученными от внутреннего сервиса

niquola15:06:19

@rmuslimov я бы на middle-ware все построил

niquola15:06:42

у тебя одни mw будут складывать в context map - другие валидировать - третьи проксировать - полный декомплект :0

rmuslimov16:06:08

@nicola звучит неплохо, буду смотреть. спасибо

andrewtropin16:06:04

Насколько оправдано писать такой макрос:

(defmacro where=
  "Add :where clause into query map if s not nil
  Will not work in case you want :where [:= :key nil]"
  [m s]
  `(cond-> ~m
     ((complement nil?) ~s) (merge-where [:= (keyword '~s) ~s])))

(defn get-list [{:keys [organization-type]
                 :as params}]
  (-> {:select :* :from :categories}
      (honey/where= organization-type)
      honey/query))

niquola16:06:23

А почему не функция?

andrewtropin07:06:49

на самом деле у меня было два варианта:

(defn where= [m params k]
  (if (contains? params k) (merge-where m [:= k (k params)])))

(defmacro where=
  "Add :where clause into query map if s not nil
  Will not work in case you want :where [:= :key nil]"
  [m s]
  `(if ~s (merge-where ~m [:= (keyword '~s) ~s])))
Вот думаю какой из них лучше. Сначала написал функцию, потом нашёл кейс, где макрос удобнее.

misha17:06:21

а почему не if?

andrewtropin07:06:43

misha: нужно было для того, чтобы ещё пару функций туда докидать, но для этого варианта хватит и ифа, верно.

andrewtropin08:06:02

А нет, обманываю. Не иф, потому что мне нужно всегда возвращать мап.

misha08:06:03

(if (nil? ~s)
  ~m
  (merge-where ~m [:= (keyword '~s) ~s])))

misha08:06:10

понятно, что если merge-where - не единственное преобразование, то cond-> - в самый раз

dragoncube17:06:52

кстати, а с cljc много граблей?

artemyarulin18:06:58

Кста интересно - кложа это лиспы, макросы ура, power! Первый урок почти везде - макросы не писать, лучше просто функции, макросы ну в ооооооочень редких случаях и даже в них лучше еще раз подумайте

dragoncube18:06:30

кложа это данные, а то что лисп - это вторично

misha19:06:42

@artemyarulin ну макросы и правда заесь, лучше только наличные© просто большинство нужных тебе макросов уже написано (->, ->>, spec, etc.), либо они нужны на уровне либы, а не аппликейшен кода

misha19:06:41

@dragoncube ни на одни грабли не наступил пока что. но и в продакшене меня пока что нет

artemyarulin19:06:46

и чо много у тебя их уже @misha ? И неужто не было проблем когда хрен макрос в рантайме заюзаешь типа (reduce and [true false true]) ;; CompilerException или вон тут даже не один раз народ и я жаловались что спека вся на макросах и хрен чего на основее ее сделаешь враппер или либу?

artemyarulin19:06:58

я их по началу тоже много писал, а счас думаю что в 99.9999% это овер инжинеринг и в оставшиеся 0.00001 помещаются всякие core.async и прочее

misha19:06:53

много кого? макросов? ниодного

misha19:06:01

.cljc - тупо всё, кроме: rum компонентов, серверных мидлварей, записи/чтения на диск, датомик-кода

artemyarulin19:06:11

аа, сори, не прально прочитал - думал у тебя там все на них 🙂

misha19:06:19

быгыгы, 1 большой макрос апп: пишешь мейн, а он тебе разворачивает сервер, реактнейтив и юай весь

misha19:06:09

ну с (reduce and ...) знать надо, конечно, это да. но кложа и так в тонусе держит с точки зрения "знать надо", так что типа ок.

misha19:06:17

(every? boolean [true false true])
=> false
(every? boolean [true true])
=> true
(every? boolean [true 1 true])
=> true

rmuslimov20:06:13

@misha рум компоненты как раз в cljc потому что server-side рендеринг

fmnoise20:06:20

(do-everything)

artemyarulin20:06:32

ну типчиков то нет, все в тонусе надо да

misha20:06:59

@rmuslimov у меня пока что нет сср, так что еще не в cljc. то я перечислял, что у меня в cljc.

dottedmag20:06:29

@artemyarulin Вот вспомни, как часто тебе нужно было разные вещи добавить в язык. Например, в джаву какую-нибудь. Вот приблизительно столько макросов тебе и надо, и они уже написаны до тебя 🙂

artemyarulin21:06:09

ну хз, мне кажется все равно macroses are overrated. Прям в любом туториале по кложе в начале списка идет этот аргумент - добавить разные вещи в язык омг, мощЪ. А на самом деле тут наверно процентов 5 кто макросы писал и из них 5% кто это делал в либах а не у себя в уютном домашнем проекте

artemyarulin21:06:25

я отлично понимаю почему and макрос, что только через них можно было core.async запилить или спеку. Но в типичных условиях - это нафег не надо.

dragoncube22:06:51

cljc удобно и для тестов, можно обычный lein test использовать без дополнительных усилий