Fork me on GitHub
#clojure-russia
<
2016-04-13
>
maxp04:04:12

уважаемые, а кто-нибудь делал на HoneySQL запросы с case/when?

prepor08:04:57

@maxp: делал. просто в raw пихал

maxp08:04:29

в общем, такая же фигня

prepor08:04:40

source-sum
(fn [source]
  (let [case (format "case when source='%s' then 1 else 0 end" source)]
    [(sql/call :sum (sql/raw case))
     (format "source_%s" source)]))
not-sources-sum
(fn [sources]
  (let [cond (format "source is null OR (%s)"
                     (apply str (interpose " AND " (for [s sources]
                                                     (format "source<>'%s'" s)))))
        case (format "case when %s then 1 else 0 end" cond)]
    [(sql/call :sum (sql/raw case))
     "source_other"]))
data (-> {:select [:publisher_id
                   [:%count.* :count]
                   [:%sum.revenue :revenue]
                   [:%avg.revenue :mean]
                   [:%count.%distinct.customer_id :buyers]
                   [:%sum.rewards :rewards]
                   (source-sum "twitter") (source-sum "vk") (source-sum "facebook")
                   (source-sum "odnoklassniki") (source-sum "email")
                   (not-sources-sum ["twitter" "vk" "facebook"
                                     "odnoklassniki" "email"])]
          :from [:publisher_orders]
          :where [:and
                  [:>= :created_at (->sql-time from)]
                  [:< :created_at (->sql-time to)]
                  [:= :site_id (:id site)]
                  [:in :state ["new" "confirmed"]]]
          :group-by [:publisher_id]
          :order-by [[sort_by direction]]
          :limit limit}
         (?> campaign_type (sql-h/merge-where [:in :campaign_type campaign_type]))
         (jdbc/query (:db graphs)))

maxp08:04:00

и так ничего, пока туда внутрь case сильно параметры пихать не надо

prepor08:04:15

это можно и ридер-тегами делать сейчас

maxp08:04:59

в смысле что делать?

maxp08:04:54

вроде, где-то в постгресе был удобный способ нагенерить столбцов в селект

maxp08:04:29

там в новом вроде как group by cube будет, как бы из похожей области

maxp08:04:54

массивчик раскрутить по строкам вроде как unnest()

maxp08:04:59

или что-то в таком духе

prepor08:04:29

raw-объявлять. я использую функции, а можно #sql/raw

andmed08:04:49

насчет style guide который тут пробегал https://github.com/bbatsov/clojure-style-guide почему рекомендуется вместо родных джавовских функций для строк использовать клоджуровские. например, чем

(clojure.string/upper-case "bruce")
лучше
(.toUpperCase "bruce")
? массивы тоже
Avoid the use of Java arrays, except for interop scenarios and performance-critical code dealing heavily with primitive types

prepor08:04:17

1. быстрее (если сам тайп хинты не проставил) 2. кроссплатформенно (жс-генерация)

prepor08:04:57

это про строки

prepor08:04:16

а массивы ну просто потому что это убивает прелесть кложи с ее структурами )

narmaru09:04:08

3. (map clojure.string/upper-case ["bruce"]) vs (map #(.toUpperCase %) ["bruce"])

dottedmag09:04:43

(upper-case "bruce") и (.toUpperCase "bruce") неотличимы.

prepor10:04:44

в каком смысле неотличимы?

razum2um10:04:19

о. кстати, кто скажет, почему нельзя сделать map с .method это специально чтобы делали clj функции или случайно?

seryh10:04:16

а как core.async физически каналами работает? каждый канал - новый поток. или он использует некий ограниченный пул, с worker threads паттерном?

artemyarulin10:04:37

в cljs: каждый канал - свой поток trollface

delaguardo11:04:03

@razum2um: можно вот так вызывать - (map (memfn charAt i) ["fred" "ethel" "lucy"] [1 2 3])

seryh11:04:00

почитал, таки на java.util.concurrent строится. очереди блокировки и весь фарш

seryh11:04:33

на беке )

seryh11:04:07

клево. можно каналов плодить сколько угодно

prepor11:04:41

@seryh для go-макросов создается фиксированный пул воркер-тредов, для thread-коллов динамически растущий. сам канал это просто структура данных, он никакие потоки не использует

seryh11:04:43

да, точно, совсем забыл про go блоки

seryh11:04:57

а на практике имеет смысл использовать блоки thread? go блоков вроде вполне хватает для любых задач

prepor11:04:00

нет, не для любых ) если ты собираешься делать долгие блокирующие операции в рамках го-макроса, то, скорее всего, лучше этого не делать

prepor11:04:26

"блокирующие" в смысле именно весь тред

seryh11:04:40

ага, процес будет заблокирован и доступный пул станет меньше

seryh11:04:43

ясно спасибо

az12:04:03

@prepor: они тоже легко крутят?

az12:04:19

я про markdown + R = дашборд

az12:04:40

выглядит комбайном

prepor12:04:43

ну в jupyter маркдаун, а код в чем хочешь, в эрке, питоне, жулии

az12:04:33

вот бы переписать d3 на ocaml

dottedmag12:04:49

@prepor: В эстетическом

dottedmag12:04:05

@razum2um: Это ж макро, поэтому и нельзя

fxposter13:04:50

это не макрос simple_smile

fxposter13:04:28

а разница в том, что clojure-fn это по-факту обьект который можно референсить с точки зрения java, а метод - нет.

fxposter13:04:27

причины, почему нельзя конвертировать их автоматически в методы, если они используются не первым аргументом функции наверное можно было бы, но решили не делать

serioga13:04:04

> а на практике имеет смысл использовать блоки thread? go блоков вроде вполне хватает для любых задач правило простое: - CPU-bound tasks — в go - IO tasks — в thread

prepor13:04:07

какое странное правило )

prepor13:04:32

вот если все делать наоборот, тогда еще может быть

artemyarulin13:04:13

все в го - нынче время асихнронщины, нода, коллбеки, кумунизм!

fxposter13:04:06

ну на самом деле ты не будешь в обычном go-блоке делать busy read из сокета в канал simple_smile

fxposter13:04:27

поэтому IO действительно выносится за пределы core.async-а

dottedmag13:04:41

@fxposter: Да, не макро, а специальная форма. А #() -- макро чтения, вот и не стыкуется. Такие дела.

serioga13:04:21

> ну на самом деле ты не будешь в обычном go-блоке делать busy read из сокета в канал даже чтение из базы может оказаться busy

fxposter13:04:22

прости, но что значит “ДАЖЕ"

serioga13:04:26

смысл в том, что IO операции не паркуются, а прелесть go в парковке без утилизации полноценных тредов

fxposter13:04:27

это и есть чтение из сокета

serioga13:04:18

непонятно было, чем busy read из сокета отличается от просто чтения из сокета — в контексте обсуждения core.async

serioga13:04:25

я когда в прошлом разбирался, что такое длительные операции ввода-вывода, у меня тоже было представление, что это как-то связано с длительностью операции

fxposter13:04:41

> связано с длительностью операции IO по определению длительное simple_smile

narmaru13:04:09

паркуются же только асинхронные операции с каналами, типа >!, <!, все остальное будет блокировать тред, не важно CPU или IO

fxposter13:04:59

тред заблокированный на IO ничего не делает, тред не блокируется на CPU

prepor13:04:10

> смысл в том, что IO операции не паркуются асинхронные IO операции прекрасно паркуются

prepor13:04:12

и IO bounded операции как раз, как правило, хорошо делать асинхронными (если речь идет про сеть)

fxposter13:04:36

(но как правило апи все же синхронные в джаве) simple_smile

andre16:04:16

https://www.youtube.com/watch?v=Fh529ExAtjI @asolovyov в прямом эфире про реакт на серверсайд

sasha16:04:19

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

serioga17:04:58

> асинхронные IO операции прекрасно паркуются для вызывающей стороны это уже не IO simple_smile создание тредов уходит на сторону, обеспечивающую асинхронность каюсь, речь шла именно о блокирующем IO

serioga17:04:03

> и IO bounded операции как раз, как правило, хорошо делать асинхронными (если речь идет про сеть) поэтому и есть thread simple_smile

serioga17:04:40

> (но как правило апи все же синхронные в джаве) иногда асинхронность не нужна превращать асинхронный код в синхронный — получается перебор

artemyarulin17:04:57

React Native приходит на венду, ееее simple_smile

artemyarulin18:04:03

Вобщем RN это новый QT https://ericroz.wordpress.com/2016/04/11/f8-app-on-windows-10-mobile/ ну ништяк ащще, пойду линкедИН обнволю 😄

potapenko19:04:23

Зашибись!

andfadeev19:04:35

@sasha: ~/.m2 ну или где у тебя локальная репа мавена, у меня был пример где-то, но я щас не с компа

asolovyov19:04:06

@andre: если б еще микрофон не колбасило )

andre19:04:04

@asolovyov: да, к сожалению на самых интересных местах вырубало :(так и не понял как же все это работает

asolovyov19:04:21

а по слайдам непонятно? simple_smile

asolovyov19:04:34

я еще буду пост в блог писать, наверное

asolovyov19:04:39

но могу и тут объяснить в двух словах

andre19:04:47

если не сложно simple_smile

andre19:04:51

было бы круто

asolovyov19:04:30

у тебя макрос defc когда компилируется в JS, то в конце выдает код с (js/React.createClass (преобразовать миксины, имя, аргументы и бади в объект для реакта))

asolovyov19:04:51

а когда в Clj, то выдает код (fn [props] (отрендерить body относительно props))

asolovyov19:04:56

ща покажу прям места где это происходит

asolovyov19:04:44

https://github.com/tonsky/rum/blob/gh-pages/src/rum/core.clj#L39 - смотри, вот -defc это функция, которая собственно мясо макроса defc

asolovyov19:04:03

и она у тебя возвращает в коде rum.core/build-class, так?

asolovyov19:04:22

и если мы щас в cljs, то вот этот build-class - https://github.com/tonsky/rum/blob/gh-pages/src/rum/core.cljs#L16

asolovyov19:04:37

(эти превью иногда задалбывают)

asolovyov19:04:05

просто юзаются две разные реализации в зависимости от окружения

asolovyov19:04:26

и на сервере это просто функции, которые принимают пару аргументов и возвращают hiccup-о-подобную структуру данных

asolovyov19:04:34

норм объяснил?

andre19:04:46

вроде да, т.е. это только для первого рендера при инициализации страницы?

andre19:04:55

на сервере рендерится

asolovyov19:04:00

остальное все на клиенте

asolovyov19:04:04

т.е. это честный SPA

asolovyov19:04:12

но initial render - на сервере

andre19:04:15

супер

asolovyov19:04:24

тебе никто не мешает js не генерировать и не отдавать, конечно, и все рендерить на сервере simple_smile

fxposter19:04:36

ребят, а мне вот интересно, на фронтенде кто-то пробовал component юзать?

asolovyov19:04:24

кто-то говорил об этом

asolovyov19:04:32

я даже подумывал, но не нашел причины )

fxposter19:04:46

потому что смотришь на все эти обертки реакта или виртуального дома - и видишь что они в плане разнесения логики на отдельные, независимые части - на уровне прошлого века

asolovyov19:04:39

а как компонент поможет?

asolovyov19:04:54

он же только менеджит старт разных частей, системы типа

asolovyov19:04:07

ну разве что с менеджментом хранилища он его сделает не глобальной переменной, конечно

asolovyov19:04:14

ну как-то хз, надо подумать еще, наверное

asolovyov19:04:28

если у тебя есть прям идеи как это сильно полечит какую-то часть жизни, я б рад послушать

fxposter19:04:41

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

asolovyov19:04:03

но меня например сча вообще всякий стартап и прочая херня вокруг него вообще минимально беспокоит; а вот тот факт, что на андроиде у меня аппа тормозит - ото да )

fxposter19:04:22

у меня есть мысли, что это может поломать весь подход с глобальным стейтом и так далее

asolovyov19:04:36

ну квери тебе к стейту надо делать все равно

asolovyov19:04:40

спускать его деревом не вариант )

fxposter19:04:24

с другой стороны - все эти flux-ы, redux-ы и прочие “архитектурные паттерны” заставляют меня плакать немного

fxposter19:04:57

пока что я вижу, что я такой чуть ли не один )

asolovyov20:04:09

ну flux/redux меня раздражает в основном из-за писанины

asolovyov20:04:22

https://github.com/krisajenkins/petrol мне вот эта бодяга как-то понравилась

asolovyov20:04:50

но я честно говоря реально не понимаю, каким образом ты противопоставляешь flux - компоненту

fxposter20:04:59

а он тебе навязывает определенный флоу того как все работает, с более-менее жесткими связями между частями simple_smile

asolovyov20:04:15

а, ну это да

fxposter20:04:47

и я даже не противопоставляю, я просто о том, что “flux и его потомки” - это теперь “венец архитектурного строения” и о “decoupled components” думать уже не надо

fxposter20:04:11

по крайней мере смотря на фреймворки появляющиеся на фронтенде - выглядит именно так

asolovyov20:04:12

та ну, просто на фронтэнде мало народу с опытом написания больших систем

asolovyov20:04:25

а те, что есть - для них фронтэнд выглядит непривычно сразу

asolovyov20:04:29

так что оно есть как есть

fxposter20:04:59

с другой стороны каких-то конкретных претензий у меня нет. скорее “общее чувство, что комьюнити что-то упускает, о чем дядя Боб уже предупреждал всех не раз"

asolovyov20:04:06

ну слушай, я вообще строил-строил архитектуру, а теперь у меня все данные получаются одним миксином: (mixins/query :name-in-state (fn [data args-of-component] (get-in data [:some :path])) и все. При этом ссылка на атом, в котором данные, забита прямо руками в mixins/query, потому что иначе (binding ...) не срабатывает, всё приложение ходит и смотрит в оригинальный атом, а мне нужен рабочий binding :-))

asolovyov20:04:34

ну и реально было бы круто декомпозировать, наверное, если б у меня было применение этой декомпозиции

asolovyov20:04:52

а у меня его нет, толку мне с декомпозиции? приложение одно, отдельные части его нигде не юзаются (и не могут юзаться)

asolovyov20:04:20

ну т.е. как-то страдать над архитектурой ради страданий... хз, я в этом место уже месяца 2-3 не заглядывал и вроде никто не напрягся ни разу

asolovyov20:04:34

но ваще более разумную заготовку для архитектуры было бы неплохо иметь, наверное

asolovyov20:04:47

i.e. если ты что-то сделаешь, то мне интересно! :))

dottedmag20:04:52

А зачем декомпозировать на клиенте? Мы ж всей этой хернёй с архитектурой страдаем только для того, чтобы удерживать сложность кода в разумных пределах (не добавлять к сложности предметной области слишком много сложности реализации). Где там серьёзная сложность на клиенте, требующая компонентизации более, чем "неймспейсы, чтобы на пятки друг другу не наступать и один атом для стейта"?