Fork me on GitHub
#clojure-russia
<
2017-01-17
>
dottedmag07:01:57

Смотрите, какая штука: https://lwn.net/Articles/655437/ -- структуры данных Clojure на неё идеально ложатся.

dottedmag08:01:20

@yogthos Из Closure Library тебе что-нибудь пригодилось? Или там только client-side штуки?

a.espolov08:01:44

Отдельное спасибо Николаю за его упорство в развитии комьюнити и всем участникам хенгаута

artemyarulin08:01:24

>Когнитект куплен гуглом? оракл купил датомик, во былоб круто doge

dottedmag08:01:19

За две недели все догадки уйдут за горизонт событий Слака.

kronos_vano08:01:04

Рич женился

dottedmag08:01:19

Как, опять?

kronos_vano08:01:30

а он уже?

kronos_vano08:01:34

чорт, шутка не зашла

andre09:01:02

через две недели выйдет сюрвей просто и там кложаскрипт выстрелил 🙂

kronos_vano09:01:23

а просто кложу закрывают?

andre09:01:00

ага 🙂

andre11:01:15

(deftype RAtom [^:mutable state meta validator ^:mutable watches]
   IDeref
  (-deref [this]
    (notify-deref-watcher! this)
    state)

andre11:01:31

подскажите плиз начинающему , для чего ^:mutable

andre11:01:47

и почему -deref с черточкой

misha11:01:05

с черточкой, потому что

(defprotocol IDeref
  "Protocol for adding dereference functionality to a reference."
  (-deref [o]
    "Returns the value of the reference o."))

misha11:01:31

а почему там с черточкой - наверное по конвенции, типа "приватный", как в питоне и _

andre11:01:25

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

andre11:01:56

(defn deref
  "Also reader macro: @var/@atom/@delay. Returns the
   most-recently-committed value of ref. When applied to a var
   or atom, returns its current state. When applied to a delay, forces
   it if not already forced. See also - realized?."
  [o]
  (-deref o))

misha11:01:12

ну он не приватный, это же не defn-

andre11:01:41

все я понял

andre11:01:43

спасибо

andre11:01:02

а ^:mutable ?

misha11:01:14

это 100% стилистическое, найти бы только обосновывание

y.khmelevskii11:01:00

если сильно захотеть то можно и так почитать 🙂 https://clojurians-log.clojureverse.org/clojure-russia/2017-01-10.html

andre11:01:48

The leading dash is a convention in two places:

- gen-class methods implemented by Clojure functions (e.g. -main)

- low-level method implementations of built-in protocols in ClojureScript

The dash has no special significance as far as the compiler is concerned, it's just part of the name.

andre11:01:22

подскажите плиз начинающему , для чего ^:mutable

misha11:01:28

подозреваю, что это хинт для транзиентов, но не нашел пока подтверждения

misha11:01:41

@andre

(deftype ES6Iterator [^:mutable s]
  Object
  (next [_]
    (if-not (nil? s)
      (let [x (first s)]
        (set! s (next s))
        #js {:value x :done false})
      #js {:value nil :done true})))

andre11:01:51

может это просто автор реагента делает для себя, (def ^{:private true :const true} cache-key "reagReactionCache")

andre11:01:54

вот такое есть например

andre12:01:31

кстати прикольно он хранит в js обеъкте функции кеш по этому ключу 🙂

andre12:01:33

(aset o cache-key (assoc m k r)) где о - (fn o [] ())`

maxp12:01:40

подскажите, уважаемые, какой-нибудь нормальный способ делать из последовательности вида [A B B A A B A B]

maxp12:01:48

разбивку

maxp12:01:10

разбивку [[A] [B B A] [A} [B A] {B}]

maxp12:01:10

другими словами, к элементу А присоединяются предшествующие элементы Б

maxp12:01:13

можно примерчик?

misha12:01:22

хитрый какой

artemyarulin12:01:41

я думаю loop/recur + связку take-while #(= % A) take-while #(= % B)

maxp12:01:48

с циклом и transient аккумулятором в енм я сделал, но как-то все это коряво

artemyarulin12:01:29

а, так если А есть то просто сплитить по ним, вот и получатся группы

maxp12:01:57

group-by не разбивает A A

maxp12:01:20

или это partition-by точно не помню 🙂

maxp12:01:58

в регексах будет что-то вроде

maxp12:01:33

(B*A)(B)

artemyarulin12:01:00

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

misha13:01:34

(reduce
  (fn [r i]
    (cond
      (not (seq r))
      (conj r [i])

      (and (seq r)
           (= :A (last (last r))))
      (conj r [i])

      :else
      (let [idx (-> r count dec)]
        (update r idx conj i))))
  []
  [:A :B :B :A :A :B :A :B])

misha13:01:46

[[:A] [:B :B :A] [:A] [:B :A] [:B]]

misha13:01:57

[:A :B :B :A :A :B :A :B :A :B :A :B :B :B :A :A :B]
->>
[[:A] [:B :B :A] [:A] [:B :A] [:B :A] [:B :A] [:B :B :B :A] [:A] [:B]]

maxp13:01:50

хотелось бы для последовательностей

maxp13:01:39

не для векторов last может быть весьма затратен

misha13:01:59

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

misha13:01:23

ты ж на векторах вопрос задал

maxp13:01:52

кстати, да

maxp13:01:57

может так и ловчее будет

maxp13:01:42

хотя у меня через loop recur почти так же

maxp13:01:50

можно сказать, я успокоился 🙂

maxp13:01:46

спасибо за участие

misha14:01:36

а есть какой-нибудь алгоритм, чтобы посчтитать количество комбинаций монет дающих определенную сумму? 1. есть определенный пулл монет: [1 1 5 5 5 10 10 25 25 25 25 50] 2. есть число: x 3. нужно получить все комбинации монет из пула, в сумме дающие <= x

misha14:01:53

можно

(let [coins [1 1 5 5 5 10 10 25 25 25 25 50]
      x 26]
  (->> (range (count coins))
    (mapcat #(clojure.math.combinatorics/combinations coins (inc %)))
    (filter #(->> % (apply +) (>= x)))))

;;=> ((1) (5) (10) (25) (1 1) (1 5) (1 10) (1 25) (5 5) (5 10) (10 10) (1 1 5) (1 1 10) (1 5 5) (1 5 10) (1 10 10) (5 5 5) (5 5 10) (5 10 10) (1 1 5 5) (1 1 5 10) (1 1 10 10) (1 5 5 5) (1 5 5 10) (1 5 10 10) (5 5 5 10) (1 1 5 5 5) (1 1 5 5 10) (1 5 5 5 10))
а может что-то чётче есть?

misha14:01:41

а то если монет много, а x - маленький - куча вычислений зря

dottedmag14:01:38

knapsack problem же, NP-полный.

dottedmag14:01:07

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

dottedmag15:01:08

@misha Просто перебором с мемоизацией. комбинации-монет[x, [1 1 5 5 5 10 10 25 25 25 25 50]] = [50]∗комбинации-монет[x-50, [1 1 5 5 5 10 10 25 25 25 25]] ∪ [25]∗комбинации-монет[x-25, [1 1 5 5 5 10 10 25 25 25]] ∪ [25]∗комбинации-монет[x-25, [1 1 5 5 5 10 10 25 25]] ∪ ... ∪ [1]∗комбинации-монет[x-1, [1]] ∪ [1]∗комбинации-монет[x-1, ∅]. Второй аргумент - это всегда subrange от начала до N, так что его можно закодировать числом. ∗ означает "прицепить префикс слева ко всем последовательностям справа".

misha15:01:32

кароче перехачивать clojure.math.combinatorics/combinations для поддержки мемоизации?

dottedmag15:01:03

Комбинаций будет 2^N, а здесь меньше, и решается просто по алгоритму выше рекурсивной функцией.

misha15:01:34

ща перепишу, чтобы в глаза помещалось

dottedmag15:01:53

Z[x, [a1 a2...aN]] = [aN]∗Z[x-aN, [a1 a2...aN-1]] ∪ [aN-1]∗Z[x-aN-1, [a1 a2...aN-2]] ∪ ... ∪ [a2]∗Z[x-a2, [a1]] ∪ [a1]∗Z[x-a1, ∅]

dottedmag15:01:07

Идея очень простая: есть рюкзак размера N. Есть вещи. Мы берём вещь a1, и решаем задачу "есть рюкзак размера N-a1, как туда можно остальное поместить?", после чего приписываем к результату a1. После этого вещь a1 выкидываем, берём вещь a2, и решаем задачу "есть рюкзак размера N-a2, как туда можно остальное поместить?"...

misha15:01:17

слушай, а combinations не так сделаны? там правда только 1 длинны комбинации, значит оно не умеет переиспользовать длинне/короче посчитанные комбинации

dottedmag15:01:42

Нет, combinations сделаны не так.

dottedmag15:01:54

Это просто из комбинаторики следует 🙂

dottedmag15:01:37

combinations - это решение той же задачи, где рюкзак бесконечного размера.

dottedmag15:01:44

Поэтому они всегда выдадут 2^N вариантов.

misha15:01:55

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

dottedmag15:01:18

Эээ. Как определяется длина?

misha15:01:23

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

misha15:01:17

в моем случае есть вообще 3 измерения: ширина, вес, максимаьное количество

dottedmag15:01:44

Тогда смотри выше определение Z. Если менять пул, то тогда сделать оптимизацию "второй аргумент - число" не получится, но мемоизированный результат можно использовать.

misha15:01:12

а не как с монетками - только 2: максимальное количество и вес

misha15:01:27

ок, а есть у этого какое-то название выделенное?

misha15:01:43

почитать

dottedmag15:01:53

Это всё knapsack-like problems.

dottedmag15:01:19

Не в оригинальном виде, а какой-то вариант, да.

misha15:01:38

о, ништяк, спасибо

dottedmag15:01:38

См. Multi-dimensional knapsack problem там в конце.

misha15:01:09

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

misha15:01:26

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

misha15:01:12

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

misha15:01:54

The target is to maximize the sum of the values of the items in the knapsack so that the sum of weights in each dimension {\displaystyle d} d does not exceed {\displaystyle W_{d}} W_{d}.

misha15:01:01

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

misha15:01:57

1. есть сет P = [1 2] 2. нужно получить все уникальные комбинации длинной 1- (count P) (без учета порядка [1 2] = [2 1]): [[1][2][1 2]] 3. можно ли получить комбинации для нового сета P1 = [1 1 2] дешевле, чем заново всё пересчитать? [[1][2][1 1][1 2][1 1 2]]

dottedmag15:01:11

Можно, если заполнять мапу. [N [1 2]] -> #{#{1} #{2} #{1 2}}, [N [1]] -> #{#{1}}.

dottedmag15:01:36

Тогда при подсчёте [1 1 2] можно взять уже готовое значение для [N [1 2]]

dottedmag15:01:18

Мапа раздуется со временем, правда. Зато быстро будет.

misha15:01:34

ну тут без раздутия не обойтись, да.

dottedmag15:01:12

Внутри сета не сеты, если можно повторять. Но это уже детали.

andmed16:01:55

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

yogthos16:01:01

@dottedmag I think I used b64 serializer from it

dottedmag16:01:22

@andmed функция Z выше с мемоизацией - это классический DP-алгоритм.

andmed16:01:47

ну да.

andmed16:01:55

скажем больше примитивный dp алгоритм

andmed16:01:32

самая что ни на есть стейтная императивщина, которая проходит незамеченной потому как в core))

dottedmag16:01:52

почему императивщина, когда это обычная свёртка?

dottedmag16:01:55

Рекурсивная.

andmed16:01:58

разве стейт в функции не хранится?

dottedmag16:01:34

Технически - да, а фактически это всего лишь вычисление чистой функции Z(x, y).

dottedmag16:01:59

Т.е. существенно умный компилятор (tm) такое может сам реализовать.

dottedmag16:01:07

Кэширование результатов чистой функции - не императивщина, так как нет способа различить наличие и отсутствие кэша, кроме как по количеству тепла, выделенному компьютером при вычислении.

andmed17:01:34

эм.. не уверен что понял что ты сказал)) но когда я смотрел алгоритмы DP то как раз обратил внимание по подходу это принцип противоположный FP: как раз вводится общий стейт для рекурсивной процедуры, как раз то от чего FP вроде как абстрагируется

dottedmag17:01:48

Это один из возможных вариантов реализации.

dottedmag17:01:56

Табличку нарисовать и заполнять её.

dottedmag17:01:16

Но даже так -- это всего лишь мемоизация значений чистой функции.

dottedmag17:01:06

Например, несколько потоков может эту табличку заполнять совместно, и ничего не сломается, пока каждая операция обновления ячейки атомарна.

dottedmag17:01:31

Так что императивного ужаса – shared mutable state – не наблюдается.

dottedmag17:01:50

Есть shared accreting state, а это совсем другое дело.

andmed17:01:22

ну собственно несколько месяцев назад я сюда постил кложе код решающий задачу упаковки методом DP. жаль архива нет (его ведь нет?) посмотреть нельзя. но помню меня поразил он. потом гуглил автора: русский, сейчас в панасонике чтото-там волновое на функциональщине пишет.. во как

andmed17:01:17

ой. спасибо тебе!

dottedmag19:01:53

Хаха, они делают суперкомпиляцию. Привет РЕФАЛу.

artemyarulin19:01:40

может через 2 недели как раз анонсируют CLJ <> C муахаха, вот будет тема. Хотя хз зачем :thinking_face:

dottedmag19:01:05

Версии множатся 🙂

a.espolov19:01:16

Был же проект clojurec

a.espolov19:01:38

Типа даже компилилось под айос и под андроид было в планах

misha19:01:44

Ричу со Стю больше нечем нас порадовать harold

a.espolov20:01:47

Ни приходилось сталкиваться с задачей сохранения позиции скроллирую в компонентах контейнера при переходе назад(по истории переход юзера)

a.espolov20:01:21

Такой болезнью много аппов реактовских страдает

a.espolov20:01:52

Что подсказывает, что придется писать ручками

artemyarulin20:01:28

>Такой болезнью много аппов страдает fixed

dragoncube21:01:35

Clojure on Go VM

dottedmag22:01:51

У Go есть VM?!

dragoncube22:01:15

> Michael Nygard ‏@mtnygard Jan 16 > Oh man... cool stuff coming but I can't announce it for 2 weeks. Aargghh. > Michael Nygard ‏@mtnygard 6h6 hours ago > I’m having fun getting fitted for a kilt and jacket. All new to me.