Fork me on GitHub
#clojure
<
2018-01-10
>
seancorfield00:01:53

So ^:const is sort of "direct linking" for Var values šŸ™‚

potetm00:01:52

Oh man, that bug Stuart found is a gem.

potetm01:01:41

The kind of thing thatā€™s real easy to miss when youā€™re ā€œjust optimizingā€ things.

hiredman01:01:49

aot (a feature people don't understand and don't think through the implications of) combined with const (a feature people don't understand and don't think through the implications of)

hiredman01:01:24

(combined by different people across projects even)

fabrao01:01:16

Hello all, I've read about Jlink in Java 9 and I see a big advance about memory and performance running embedded java services. Do you think it can be used with Clojure?

ghadi01:01:27

I haven't seen much about perf + memory on jlink.

ghadi02:01:25

I've modified clojure to use modules (java.base + jdk.unsupported) and jlink'ed it into a 45MB docker image

ghadi02:01:42

but ultimately java modules are a move away from dynamicity

3Jane08:01:36

Can anyone recommend a tutorial on learning a workflow with mount and tools.namespace? Iā€™m trying to do something stupidly simple (open a db connection, run a count query, close the connection), but something (?) isnā€™t working and Iā€™m lost as to how to debug the problem

3Jane08:01:16

Using Cursive, attempting to follow this: http://grishaev.me/en/clj-sqlite except with mount-lite

3Jane08:01:23

Iā€™ve written toy Clojure before but never actually a project

3Jane08:01:50

Part of the struggle is Cursive/REPL; even if I load a file into REPL I have to manually re-require libraries to test sub parts of the file etc - Iā€™m 100% sure itā€™s possible to get more value out of REPL but I need a howto. In general itā€™s an immensely frustrating experience - every documentation or tutorial shows a piece of the puzzle, and I need to find a sustainable way to debug the project in a situation when Iā€™ve put the pieces together in the wrong way.

schmee08:01:57

tools.namespace should remove that problem (although it causes some othersā€¦)

schmee08:01:09

have you seen the mount test app? should be able to get some inspiration there: https://github.com/tolitius/mount/tree/master/dev/clj

qqq08:01:21

I use emacs/cider without mount/tools.namespace, and haven't run into these issues.

3Jane08:01:14

Iā€™ve seen this thread https://clojureverse.org/t/share-the-nitty-gritty-details-of-your-clojure-workflow/1208/23 but with my current state of knowledge itā€™s too much disparate input ĀÆ\(惄)/ĀÆ

qqq08:01:27

My basic strategy is: 1. write short functions 2. write unit tests (clojure.test/is ...) right under the functions 3. eval them in the repl

3Jane08:01:45

Iā€™m not currently using namespace; I know itā€™s meant to resolve these kinds of problems, thatā€™s why I asked. Iā€™m a beginner with Clojure - old hand otherwise, but finding it really hard to start with Clojure workflow, as I donā€™t have anyone to show me their workflow in person. I understand all people have personal habits and nobody wants to tell you The Right Way, but I have to start from something.

schmee09:01:09

@lady3janepl here is my workflow: I have this fn in my dev/user.clj

(ns user
  (:require [clojure.tools.namespace.repl :as tn]
            [io.aviso.exception :as e]))

(defn refresh []
  (let [e (tn/refresh)]
    (set! *warn-on-reflection* true)
    (if (instance? Throwable e)
      (e/write-exception e)
      e)))

schmee09:01:38

everytime Iā€™ve made a change I want to test, I run (user/refresh) in my REPL and all my code is reloaded

schmee09:01:41

thatā€™s it šŸ™‚

pasi09:01:44

I'm being a bit daft with syntax.. I have have a function that returns a vector (it maps over items and transform them a bit). Now in the end, I want [:g [item1] [item2]]. Obviously [:g [[item1] [item2]]] is easy to get but how do I "spread" the list to the vector starting with :g? I think I need apply..

pasi09:01:18

(i.e. I'm calling [:g (func-that-returns-said-vector)])

3Jane09:01:44

and vector is [item1 item2 ā€¦] ?

schmee09:01:45

user=> (into [:g] [[:item1] [:item2]])
[:g [:item1] [:item2]]

3Jane09:01:01

(cons :g (map vector [:e1 :e2]))
=> (:g [:e1] [:e2])

3Jane09:01:32

oh, into works better than cons in this case šŸ™‚

pasi09:01:48

you know, I'm actually using into [] elsewhere and the thought of trying it did cross my mind.. dunno why I didn't.

pasi09:01:54

but that works superbly, many thanks!

pasi09:01:03

it actually works beautifully here because I can just (->> (fetch-orig-array) (map my-transform) (into [:g]))

schmee09:01:00

this also works

user=> `[:g ~@[[:item1] [:item2]]]
[:g [:item1] [:item2]]
but donā€™t do that šŸ˜‰

pasi09:01:15

worry not šŸ˜›

nblumoe11:01:10

I have a map with a stateful resource in it (a process actually) and would like to use that via with-open. What is the best way to do that? The map so far of course does not have a .close method to be called by with-open.

qqq11:01:53

is it a bad idea to use (gensym) when I need to generate unique keys for an add-watch ?

schmee12:01:42

I think your best bet is to look at the source for with-open and implement something similar: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L3797-L3816

schmee12:01:52

you can make a Closeable protocol and make your map a record that implements said protocol + combine it with a modified with-open macro

MarĆ­liaMJ12:01:33

Hello everyone

MarĆ­liaMJ12:01:44

I'm new to the clojureu community

MarĆ­liaMJ13:01:28

Does anyone have experience using swagger in clojure apis?

nblumoe13:01:45

Thanks @schmee. I am quite surprised. But yeah, I will go with my own try/finally block then. Was already starting off with then but then realised there are more resources which could be handled by with-open and thus wanted to try that. Oh well, back to start then. šŸ™‚

MarĆ­liaMJ13:01:39

Nice, @manuel I've been following that link but still a little bit confused with my error messages šŸ˜• I'm a JS developer and used swagger quite a lot, usualy ina yaml file; the structure in clojure projects is still new to me šŸ˜›

manuel13:01:28

ok, sorry, I have no experience with yaml files for Swagger. Only used Swagger with compojure-api to be honest šŸ™‚

MarĆ­liaMJ13:01:42

I see. Is there any particular way to build thte structure? I realized it was written in the handler.clj file usually

manuel13:01:40

this is how I did it in one of my projects: https://github.com/manuel-uberti/boodle/blob/master/src/clj/boodle/api/handlers.clj#L15 Pretty much followed compojure-api docs though

ikitommi13:01:10

There is a also nice full demo app at https://github.com/yogthos/memory-hole

MarĆ­liaMJ13:01:36

Pretty cool! thanks a bunch, @manuel , @ikitommi

timvisher14:01:50

i'd like to count the number of times a given dependency is used in a project. i.e.

{:org.clojure/java.jdbc 75, :korma 10, ā€¦}
anything exist that would help me do that?

timvisher14:01:51

it would also be acceptable to do this based on namespaces

timvisher14:01:14

but i'd prefer the actual dependency to be the unit

timvisher14:01:43

tools.namespace and tools.deps.alpha both seem potentially relevant but without batteries.

darnok15:01:00

Hi, Iā€™ve create a simple two utils for Clojure CLI. They allow you to run nrepl server and run tests. https://github.com/mrroman/devtools/

noisesmith18:01:59

vec forces lazy sequences

noisesmith18:01:13

~you canā€™t wrap something that produces a vector and make the thing inside the vector lazy`

noisesmith18:01:33

oh - I misunderstood, neverm ind

manutter5118:01:54

what about (take 1 (repeatedly next-page)) ?

tdavis18:01:21

the start needs to change after each page

noisesmith18:01:36

each next-page call is ten items though, so you need to lazily consume the contents of each call

manutter5118:01:28

Ah right, missed that start takes an arg

noisesmith18:01:55

@tdavis (apply concat (map (comp next-page #(* 10 %)) (range)) - will consume 1 result at a time, but only realize 10 at a time

manutter5118:01:01

(take 2 (map vec (partition 10 (range))))
=> ([0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19])

noisesmith18:01:25

or actually (mapcat (comp next-page #(* 10 %)) (range))

noisesmith18:01:34

but, using laziness to control side effects is always a bit weird and tricky - it can improve things if you produce the input lazily, and do side effects eagerly, then piping into your data oriented code with an explicit boundary

noisesmith18:01:53

(eg. delivering onto a queue and blocking until previous results are consumed)

tdavis18:01:22

i'm not trying to control side-effects, it's just db paging. i can't read a million rows at once so i wanna read 100 at a time, but scrolling through results requires knowing some column value for the last result in the previous iteration. and that lazy million-row query is mapped over.

tdavis18:01:57

i always find it trivial to express in java or python or anything with stateful iterators or generator-type functions, but really trips me up in clojure for some reason

manutter5118:01:21

Reading from a db is a side-effect

hiredman18:01:23

oh man, have I got a ticket for you

hiredman18:01:00

you want unfold

manutter5119:01:04

I typically cheat on things like DB paging and just hold on to the current page number in an atom or similar

manutter5119:01:48

makes it easier to do things like jump-to-first, jump-to-last, jump-to-page-n

manutter5119:01:40

Since db paging is inherently a stateful side-effecting operation, itā€™s not un-Clojure-y to bring in the state management functions of Clojure.

pasi19:01:08

hm, if I need to iterate a list (vector) and each item needs to know a value from last item (specifically, distances. Each item needs to know previous one's x coordinate so it can do previous x + its distance), is there a "common" clojure pattern for this?

pasi19:01:10

I could use reduce I guess

noisesmith19:01:55

(map f (partition 2 1 coll))

noisesmith19:01:14

f will get a collection of two items, x and next-x

noisesmith19:01:40

well - kind of - something like (map f (partition 2 1 (cons ::first coll))) is sometimes more useful, just make sure f does the right thing when it detects the ā€œprevious itemā€ is the keyword ::first (or nil or any other placeholder, depends on your algorithm surely)

edwaraco20:01:41

You can use cycle function and having some like:

(let [triangle [[1043 770] [551 990] [681 463]]]
  (println (reduce + (map distance triangle (rest (cycle triangle))))))