Fork me on GitHub
#clojure-russia
<
2016-04-03
>
andmed03:04:49

@maxp: абстрактно-теоретически я тоже к этому склоняюсь, но думал вдруг есть неочевидный практический довод simple_smile потом же, "свой велосипед" на ум приходит и все такое

rm05:04:32

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

rm05:04:21

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

artemyarulin06:04:03

https://news.ycombinator.com/item?id=11405239 тут конечно в основном US и стартапчики, но кложуры довольно много (31 совпадения против например 50 скалы, JavaScript 130)

andre07:04:16

@artemyarulin: ты теслу 3 уже предзаказал? simple_smile

misha07:04:55

@andmed можешь их из rum компонентов собирать и рендерить им же (если тебе вдруг по-пути на шаг дальше хиккапа)

andmed08:04:02

@misha: спасибо интересно. я вообже cljs пока не рассматривал, наверное зря.

andmed08:04:53

вот жеж.... А как в repl напечатать строку без nil и без кавычек?

artemyarulin08:04:36

@andre: Ну вот я уже на 4 главе Real World Haskell, т.е. я уже почти элита, тесла уже на подоходе 😄

andmed08:04:53

@artemyarulin: возможно ты тогда знаешь как в repl напечатать строку без nil и без кавычек simple_smile

artemyarulin08:04:15

@andmed: Фу-фу, это сайд эффект 😄

artemyarulin08:04:49

не понял, а зафега? У тебя лист или чо?

andmed08:04:31

задача экстраординарная: сделать readline и тут же напечатать. Hello World такой. На hackerrank типа контеста. Это первая задача simple_smile

artemyarulin08:04:27

user=> "aa" "aa" user=> 'aa aa

artemyarulin08:04:55

(symbol "aa") aa

artemyarulin08:04:57

вот так тада

andmed09:04:51

@artemyarulin: 🤓 работает! а как перевод строки сделать в конце? (newline) тоже nil дает

artemyarulin09:04:19

чота кая-то странная у тебя задача прям, оооочень

artemyarulin09:04:21

user=> (symbol "aa") (symbol "") aa user=>

andmed09:04:24

@artemyarulin: ништяк. а я вот не догадался, всякие \n подсовывал

artemyarulin09:04:59

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

andmed09:04:48

Вот эта гигантская задача Ж-)

Input Format

A single line of text denoting inputStringinputString (the variable whose contents must be printed).

Output Format

Print Hello, World.Hello, World. on the first line, and the contents of inputStringinputString on the second line.

Sample Input

Welcome to 30 Days of Code!
Sample Output
Hello, World. 
Welcome to 30 Days of Code!

andmed09:04:31

я с do сделаю

artemyarulin09:04:43

ааа дак неа

artemyarulin09:04:48

смотри когда ты сделать (print “HELLO”) то в консоль выведется HELLO, но так как ты в репле то будет сайд эффект (HELLO в данном случае) + то что вернула функция print, а данном случае nil

andmed09:04:26

так я с do, последняя будет symbol, выведет строку и всепучком

andmed09:04:52

или do даст nil....

artemyarulin09:04:00

нене, тебе нужно просто (print "Hello, World.\n” inputStringinputString)

andmed09:04:58

неа. дает в одну строку и с nil

andmed09:04:28

нет. две строки, но nil все равно

artemyarulin09:04:08

нене, все будет пучком. Репл != консоль. В репле у тебя выводиться standard output + доп фигня от кложуры, такое как возврат из функций

andmed09:04:37

увы. у них там как-то через репл 😞 я это сразу написал. ругается....

artemyarulin09:04:46

как задача наывается на hackerrank?

artemyarulin09:04:28

дай ссылу на нее

andmed09:04:13

очевидное

(print "Hello, World.\n" (read-line))
сбой в форматировании дает, не принимает

artemyarulin09:04:49

хм, не могу открыть 404

andmed09:04:18

ой да у них туда надо заходить через https://www.hackerrank.com/calendar

andmed09:04:46

Your Output (stdout)
Hello, World.
 Welcome to 30 Days of Code!
Expected Output
Hello, World.
Welcome to 30 Days of Code!

artemyarulin09:04:09

ну, пробел лишний

artemyarulin09:04:51

а пажди, может (printline “Hello, World.”) (read-line) ?

andmed09:04:52

стримим щас

artemyarulin09:04:28

println точнее

andmed09:04:07

ок. спасибо. попробую сам помучаться. должно же получиться!

dottedmag14:04:24

Этот auth-token со временем экспайрится, и его нужно обновлять, поэтому сделать вместо атома Delay не получится.

dottedmag14:04:41

Так бы можно было сделать (delay ...)

dottedmag14:04:17

Можно, конечно, запихнуть в атом Delay, когда токен экспайрится -- заменять его на новый Delay и получать значение через @@auth-token, но это как-то уж слишком извращённо.

fxposter14:04:47

(do-auth) возвращает функцию?

fxposter14:04:25

иначе оно работать не будет simple_smile

dottedmag14:04:43

do-auth возвращет новый токен.

dottedmag14:04:15

#(token) - это же лямбда-функция, которая возвращает константу token.

dottedmag14:04:48

Пардон, это я сломал.

kronos_vano14:04:48

а он когда экспайрится в nil превращается?

dottedmag14:04:18

Вот, я подправил сниппет.

dottedmag14:04:40

@kronos_vano: Нет. это в другом месте обрабатывается.

dottedmag14:04:53

Эта штука только нужна для того, чтобы при первом обращении сделать (do-auth)

dottedmag14:04:02

А дальше выдавать кэшированное значение.

dottedmag14:04:27

В другом месте тоже (swap!) сейчас.

fxposter14:04:40

#(token) - это же лямбда-функция, которая возвращает константу

fxposter14:04:46

юзай (constantly token)

fxposter14:04:00

но в твоем случае лучше юзать reset

dottedmag14:04:02

@fxposter: см. исправленный сниппет :)

fxposter14:04:17

тоже неправильно

dottedmag14:04:17

А, ну да, это чуть лучше. Спасибо.

fxposter14:04:20

скобочек много simple_smile

kronos_vano14:04:21

А почему тут (constantly (token)) а не просто token

kronos_vano14:04:29

объясните мне)

fxposter14:04:39

(constantly token) правильно

dottedmag14:04:40

@kronos_vano: Потому что swap! принимает функцию.

fxposter14:04:49

(constantly token) == (fn [] token)

dottedmag14:04:28

Да, я опечатался там.

dottedmag14:04:38

См. исправленный сниппет :)

fxposter14:04:41

можно сразу возвращать то что возвращает reset

fxposter14:04:48

он вернет тот же токен

dottedmag14:04:01

Вот, это то, что я смотрю следующим :)

fxposter14:04:14

в остальном норм

dottedmag14:04:39

Спасибо, с reset! стало всё нормально.

fxposter14:04:54

дальше - если тебе не нужны всякие функции атома

fxposter14:04:06

типа “retry в случае с concurrency"

fxposter14:04:17

(которых ты с reset! все равно не получишь)

fxposter14:04:25

то ты можешь юзать volatile

fxposter14:04:45

ссылочки с “!” в конце слак воспринимает неправильно simple_smile

dottedmag14:04:03

Гм, у меня тогда байда какая-то.

dottedmag14:04:19

Эта штука сохраняет токен доступа к Google Cloud Storage.

dottedmag14:04:30

Несколько потоков могут поюзать её одновременно.

fxposter14:04:44

это неважно

dottedmag14:04:48

Но обновлять этот токен нужно только одному потоку, остальные должны ждать, если кто-то её обновляет.

fxposter14:04:52

volatile можно юзать

fxposter14:04:07

суть в том, что reset! просто перетрет значение в атоме

dottedmag14:04:25

Ну вот ситуация - токен заэкспайрился, три потока долбятся, решили обновить и втроём на неё vreset!.

dottedmag14:04:28

И всё сдохнет.

dottedmag14:04:40

Надо будет что-нибудь другое придумать.

fxposter14:04:40

т.е. если ты get-auth вызовешь в нескольких потоках - у тебя каждый поток получит свой токен и будет гонка

fxposter14:04:54

что в текущей версии, что с volatile

dottedmag15:04:16

Угу. Значит нужная какая-то другая конструкция.

fxposter15:04:46

@(swap! auth-token (fn [delayed-token] (if delayed-token delayed-token (delay (do-auth)))))

fxposter15:04:08

обсуждали пару месяцев назад

dottedmag15:04:02

А вот compare-and-calc-fn-and-set! нету.

fxposter15:04:03

delay тут нужен, потому что swap может вызвать do-auth несколько раз, в случае когда несколько потоков паралельно делают swap

dottedmag15:04:33

@fxposter: Кстати, так тоже не годится.

dottedmag15:04:28

Поток 1 делает deref(), f.invoke(v). Поток 2 делает deref(), f.invoke(v). У обоих v -- это null.

dottedmag15:04:12

Потом первый делает CAS, меняет. Второй делает CAS, обламывается, делает deref(), f.invoke(v) уже с ненулевым аргументом и выходит.

dottedmag15:04:18

Но коллбэк оба вызовут.

fxposter15:04:36

конечно оба

fxposter15:04:47

для этого есть (if delayed-token delayed-token …)

dottedmag15:04:55

См. выше.

dottedmag15:04:11

В том случае оба потока получат delayed-token равный nil

fxposter15:04:27

погоди

fxposter15:04:39

оно возвращает новое значение

fxposter15:04:44

а не старое

dottedmag15:04:50

Тут же нет нигде блокировки, поэтому второй поток может вызвать deref() до того, как первый сделает state.compareAndSet.

fxposter15:04:04

у первого потока delayed-token будет nil и он проставит новое значение

dottedmag15:04:24

А у второго потока delayed-token будет не-`nil` только после того, как первый вызовет state.compareAndSet

fxposter15:04:27

у второго - сфейлится CAS, а на второй попытке уже delayed-token будет non-nil

dottedmag15:04:49

Но CAS сфейлится уже после того, как будет вызван f.invoke с нулевым аргументом.

fxposter15:04:57

погоди

fxposter15:04:02

CAS успешен будет только в одном потоке

dottedmag15:04:14

Но коллбэки с нулевым будут вызваны в двух потоках.

fxposter15:04:23

в том, в котором он будет успешен - возвратится non-nil

fxposter15:04:31

там цикл

fxposter15:04:40

cas во втором потоке свалится

fxposter15:04:46

и уйдет ЕЩЕ раз вызывать коллбек

fxposter15:04:54

на этом вся кложура и построена

dottedmag15:04:57

Трейс простой: #1 Object v = deref(); #2 Object v = deref(); #1 Object newv = f.invoke(v); #2 Object newv = f.invoke(v);

dottedmag15:04:17

Вот, здесь два потока, оба вызывают deref(), оба получают nil, оба вызывают коллбэк.

fxposter15:04:35

Миша, они оба вызовут

dottedmag15:04:35

Дальше один успешно выполнит CAS, другой нет, но коллбэк уже вызван.

fxposter15:04:41

оба с нулем

fxposter15:04:47

это нормально

dottedmag15:04:47

Т.е. сайд-эффект случится два раза.

fxposter15:04:56

так для этого и нужен delay

fxposter15:04:07

@(swap! auth-token (fn [delayed-token] (if delayed-token delayed-token (delay (do-auth)))))

fxposter15:04:18

(delay (do-auth)) вернет нечто - что при deref-е вызовет функцию

dottedmag15:04:43

А! Допёрло. Пардон.

dottedmag15:04:19

Я как раз про это писал, но не дошло, что без этого не обойтись https://clojurians.slack.com/archives/clojure-russia/p1459694477002286

fxposter15:04:22

если бы не было сайд-эффектов - можно было бы не юзать delay

dottedmag15:04:48

Ну, значит не обойтись.

razum2um15:04:01

@(swap! auth-token (fn [delayed-token] (if delayed-token delayed-token (delay (do-auth)))))
чет мне грустно от этого почему такая нередкая задача как сделать некоторое io единожды конкурентно решается так хитро?

razum2um15:04:30

такое ощущение, что с обычным try-lock-finally-release оно как бы проще или дело привычки?

fxposter15:04:48

и платил бы за локи даже когда они не нужны simple_smile

fxposter15:04:00

а еще поимел бы дедлоки в теории

d-side15:04:31

Ну, можно чуть сократить, заменив if на or, но в остальном выглядит не так уж хитро.

artemyarulin15:04:43

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

andfadeev16:04:23

подскажите плз, у меня из бд прилетает такая струкутра [{:t1_id 1 :t2_id 1} {t1_id 1 :t2_id 2}] (one to many relation), я хочу это переколбасить в [{:t1_id 1 :t2 [{:t2_id 1} {t2_id 2}]}], как это сделать по нормальному?

andfadeev16:04:30

юзаю honeysql

konukhov17:04:29

а как у тебя прилетает [:t1_id, :t2_id]? simple_smile у меня точно такая же проблема была недавно. только мне прилетало [:id_1 :id_2]. clojure.java.jdbc, если повторяется имя поля, просто индекс добавляет же.

konukhov17:04:29

круто, если бы туда можно было передавать функцию от metadata для того, чтобы кастомные ключи делать, типа [:table_name :column_name], а по ним уже группировать.

andfadeev17:04:53

да не, я опечатался

andfadeev17:04:10

прилетает все как надо, у меня джойн на вторуют таблицу

andfadeev17:04:46

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

konukhov17:04:33

я для этого накидал такую штуку, но это сыро и только one-to-one – https://gist.github.com/konukhov/0c45001270ef7c76f3d6a062b32ebe0f

konukhov17:04:26

а недавно видел в гугл группе, чувак сделал маппер тоже. но мне не нравятся все эти defentity, как в korma, и так далее. ща попробую найти ссылку

andfadeev17:04:38

да я либы видел

andfadeev17:04:45

но вроде как отказался от кормы

konukhov17:04:28

ну она очень хочет на active_record какой-то быть похожей, что кажется неправильным – можно проще

konukhov17:04:14

а в jdbc вот где проблема – https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L376 дали бы возможность сюда кастомные штуки передавать, было бы намного проще

konukhov17:04:40

а, вот эта либа. https://github.com/netizer/relational_mapper. опять же, навязывает использовать все эти find-all, а хочется чистый jdbc. @niquola писал, что honeysql использует – ты как эту проблему решаешь?

fxposter17:04:30

о, раз уж @niwinz позвали - а кто где реально использует http://funcool.github.io/cats/latest/?)

niwinz17:04:28

we already using it internally in some projects (not all features)

niwinz17:04:52

and some projects are just splitted from it and now are separated packages

niwinz17:04:04

funcool/lentes funcool/promesa

niwinz17:04:10

are great examples of that

fxposter17:04:17

я просто никак не могу понять, как понимание всяких моноидов, монад и семигруп помогает в реальном мире. да, у нас есть future/promise и другие вещи, которые концептуально похожи на монады или функторы и т.д, но когда ты пишешь код - ты реально думаешь - “а здесь я сделаю свою монаду”?

fxposter17:04:27

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

niwinz17:04:53

you are right, and I agree with you.

niwinz17:04:24

monads are more usefull in haskell. In clojure is mostly a "generic abstraction"

niwinz17:04:41

(as is in cats)

niwinz17:04:03

that provides some sugar syntax and protocol based abstraction for monadic abstraction

fxposter17:04:45

I just wonder - whether understanding of the core principles behind all those abstractions would really make me a better developer simple_smile

niwinz17:04:47

that you may use or just learn

fxposter17:04:00

I see that those concepts came from math and in theory you can make some proofs or rely on other proofs about that when you are building an app, but is there anything else that I’m missing? simple_smile

niwinz17:04:49

No, it is so. Some languages enforces some things that makes mandatory using monads (haskell) but other not.

niwinz17:04:19

You can learn from them, understand new forms of composition

niwinz17:04:09

that later you will use that knowlege for other thing coding it in less generic way....

niwinz17:04:05

I learn a lot from writing that, and now in most of my projects I'm using only the needed part (usually not including cats as a library) but just use the concepts when I need them

fxposter17:04:16

I see, thanks

fxposter17:04:38

I’ve talked to a lot of scala devs and usually I get similar responses - “I feel that they are useful, but I can’t tell you why” or “I justr truly believe, they are very useful, but in reality I can point only to some concrete cases - like Optional or Future"

niwinz17:04:49

This is not right at least not completly right. More advanced monad/free monad abstractions allow create very interesting compositions

niwinz17:04:58

just take a look funcool/urania

niwinz17:04:04

is a great example of that

niwinz17:04:40

the category theory abstractions are useful but them have they niche

niwinz17:04:56

they are not silver bullet 😄

fxposter17:04:18

I’ll look at it, thanks again!

razum2um17:04:11

@niwinz: heh, saw the talk about Muse, and see Alexey Kachayev in contributors. what did you do differently from muse?

fxposter17:04:21

urania is based on the initial work on Muse by Alexey Kachayev. It is also heavily inspired by:

razum2um17:04:44

yup, want to hear, what’s the difference

niwinz18:04:08

different internals

niwinz18:04:11

many bug fixes

niwinz18:04:20

native support for error handling

niwinz18:04:35

the same behavior in clj and cljs

artemyarulin18:04:14

http://www.javaworld.com/article/2078610/java-concurrency/functional-programming--a-step-backward.html

Unless you've been living under a rock, you know functional programming is all the rage among the so-called alpha geeks. 
Вона кто мы, прям альфа-самцы почти 😄

artemyarulin18:04:51

Ну вообще так то в тему:

Any halfway decent programmer can quickly glean the general intent of most imperative code -- even in a language he or she has never seen. While you can certainly figure out what functional routines do by looking at them, it may not be possible in a glance. Unlike imperative code, functional code doesn't map to simple language constructs. Rather, it maps to mathematical constructs.

fxposter19:04:18

по поводу "functional code doesn't map to simple language constructs"

fxposter19:04:40

A component that can contain other components is constructed with the parentComponent function: type ParentComponentSpec s s' f f' g p = { render :: s -> ParentHTML s' f f' g p , eval :: Natural f (ParentDSL s s' f f' g p) , peek :: forall x. Maybe (ChildF p f' x -> ParentDSL s s' f f' g p Unit) }

az19:04:02

@dottedmag:

wrk -c 10000 -t 10 -d 60  
Running 1m test @ 
  10 threads and 10000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   304.49ms  117.47ms   1.31s    80.86%
    Req/Sec   177.81    146.39     1.03k    70.34%
  92827 requests in 1.00m, 1.28GB read
  Socket errors: connect 8991, read 1200, write 1, timeout 33
Requests/sec:   1545.17
Transfer/sec:     21.82MB

az19:04:25

как определить, что что-то там лочится?

az19:04:03

я и так и сяк нагружаю сервак, он как пушка

az19:04:15

когда оно начнёт воспроизводиться?

dottedmag19:04:48

@az: Отдавай картинки по писят мегабайт каждая, тогда будет заметно.

dottedmag19:04:08

И это ведь скрипт эту wow.png выдаёт, да?

dottedmag19:04:28

Сделай в этом скрипте sleep(1s) перед завершением, и посмотри.

dottedmag19:04:52

Если лочит, то результат будет ужасен. Если не лочит, то результат будет ок.

artemyarulin19:04:44

@fxposter: Интересная либа, юзаешь где? Похоже на ом

artemyarulin19:04:33

кстати - а можете накидать истинно функциональные UI фреймворки на подобие этого? У меня зачесалось и захотелось осчастливить этот мир еще одним наиболее православным подходом к построению UI

artemyarulin19:04:52

наподобие вот этого мож чо есть https://www.youtube.com/watch?v=ajX09xQ_UEg ?

fxposter20:04:58

@artemyarulin: оно скорее похоже на Elm, и оно все на базе virtual dom, так что они все по одному принципу построены… почти. за исключением того, что у типизированных ФПшных вариантов куча ограничений, которые меня чутка пугают simple_smile я вот думаю для одного проекта на работе попробовать поюзать cljs или elm или purescript. хочется elm или purescript, но страшно в эти дебри залазить

artemyarulin20:04:47

elm мне чем не нравиться - вроде бы язык, но в тоже время Elm Architecture и вроде фреймворк, слишком много из коробки и сразу, all in

fxposter20:04:20

что? elm-html нет в core вообще. это отдельная библиотека. не хочешь - не юзай simple_smile

fxposter20:04:52

в каком-нибудь re-frame ЗНАЧИТЕЛЬНО больший all-in simple_smile

artemyarulin20:04:09

ааа, ну ок - не прально понял значит

artemyarulin20:04:24

а в чем разница тада elm VS pureScript?

artemyarulin20:04:58

и какой-нить vs GHCJS вообще?

fxposter20:04:06

elm - более “человечный"

fxposter20:04:15

purescript - более хаскелеподобный

fxposter20:04:14

не знаю, что такое GHCJS, но “хаскель для JS” - это в принципе “чужеродная” штука, а elm/purescript делаются с мыслью о взаимодействии с JS

artemyarulin20:04:52

а можно сказать что это диалекты хаскеля? Как понимаю языки то похоже?

fxposter20:04:28

я бы сказал нет, они не стараются быть “копиями хаскеля для фронтенда"

fxposter20:04:37

но синтаксис у обоих “хаскелеподобный"

artemyarulin20:04:37

у нас в конторке все помещански - взяли TypeScript и пишут в жава стайле, класики, синглтоны, сервисы и моки, грусть-печаль