Fork me on GitHub
#clojure
<
2017-07-12
>
lwhorton02:07:33

does anyone have experience with clojure.walk/postwalk? it says it walks on each form but sometimes there’s strange vectors showing up where there should be maps.. not really sure how to write what I’m trying to write

lwhorton02:07:54

looking for a generic way to walk a structure and convert something like

{:a 1 :b {:c {:d 2}}}
into 
{:a 1 :b {:c {:d 2 :id :c} :id :b}}

lwhorton02:07:24

but to do this seems like postwalk needs some sort of “look back”

noisesmith02:07:00

@lwhorton hash-maps are made of two element vectors (entries) - you can see it if you call seq on one

mpenet10:07:08

technically they are clojure.lang.MapEntry instance, and you can check for it via map-entry?

mpenet10:07:22

they inherit from the .toString of vectors

noisesmith16:07:39

@U050SC7SV they will not be MapEntry instances when processed in postwalk, postwalk returns vectors

noisesmith16:07:49

and vector? returns true for instances of MapEntry

noisesmith16:07:45

now, there are definitely cases where I changed my algorithm so I could use prewalk instead just because prewalk gives you MapEntry instead of vector

noisesmith02:07:06

you can do that transform above by checking for hash-maps inside each hash-map, and updating them to include their id key before returning it

noisesmith02:07:46

so your conditional would check if the arg was a map, then if it is check for maps in vals of the map, and update those vals

mattgeb02:07:56

I have a stupid question. I want to make a project with a different project as a foundation - is there a simple way to get Lein to do that so I don't have to manually edit a bunch of files? Sorry if there's something obvious, Google did not yield results

noisesmith02:07:45

why not just recursively copy the old project then edit?

noisesmith02:07:06

it's possible to make your own template, but that seems like overkill to make one project

mattgeb02:07:51

the project has a bunch of files, and I'm messing with something new (importing React components into Reagent), so mostly I just wanted to avoid the risk of forgetting something.

mattgeb03:07:00

buuut it shouldn't be too bad. Thanks!

lwhorton03:07:24

thanks @noisesmith ill work on that

srinidagda06:07:59

I have defined logger format in log4j.properties and the file is kept inside resource folder in clojure api. But logs is not getting displayed in given in log4j.properties. Logs getting displayed on console in this [qtp681891967-13] INFO clojure-dauble-business-api.core - Function begins from here.

srinidagda06:07:51

I also specified log4j.properties path in project.clj with this line :profiles {:dev {:resource-paths ["resources"]}}

srinidagda06:07:30

As per log4j.properties logs should be append to app.log file. It is not happening. Where I am doing wrong? Can anybody help me out?

srinidagda07:07:46

I figured out solution to the logging issue. Dependency [org.slf4j/slf4j-simple "1.7.12"] overriding log4j.properties configurations.

ajs09:07:19

i've been trying for a couple days to resolve this problem when i run lein repl: Error loading clojure.tools.nrepl.server: Could not locate clojure/tools/nrepl/server__init.class or clojure/tools/nrepl/server.clj on classpath

ajs09:07:52

i cannot figure out how this dependency works and how to resolve it

hmaurer10:07:03

@ajs is your code accessible publicly on github?

hmaurer10:07:53

@ajs could you push it to github? I am happy to take a look

ajs10:07:09

@hmaurer thanks, and i wish i could. it's a company project

ajs10:07:46

@hmaurer i'm trying various things, i should be able to get to the bottom of it.

ajs10:07:16

it's due to one of those sticky situations in clojure where sometimes building a project depends on the actual editor used by the developer. give the project to another developer with a different IDE and it blows up

ajs10:07:48

i think it's the only language i've used where a project's build process can be coupled with the code editor

rauh10:07:47

@ajs I'd first inspect the classpath and see if you have the nrepl jar on there

hmaurer10:07:03

@ajs try lein deps :tree

ajs11:07:35

@hmaurer @rauh i managed to resolve the problem by installing and using cider. not my preference but it's a quick solution for now

didibus16:07:09

You were simply missing a dependency on nrepl. Cider jack in injects a few repl only dependencies. Not all editors do this.

ajs18:07:33

How would I add this dependency without using cider? Where would be the best place?

hmaurer11:07:09

@ajs odd… glad it worked though

ajs11:07:47

are environment variables cached somehow. I removed one that was set in my project.clj, and instead put it in a separate profiles.clj. Even after a lein clean and restart of cider, calling the environ function to read an environment variable reveals the old value that was removed.

mpenet11:07:51

Check if you have a . lein-env file in the root of the project

ajs11:07:24

thanks. my probably was actually resolved after a reboot of the machine

dpsutton11:07:32

@ajs not sure how that's working but i can wager a guess. Emacs starts up with an environment and its possible that this process, since it is spawning the others, is preserving that environment you started with. perhaps restart emacs and see if the environment is updated then

slpssm13:07:47

Is there a function to process the values of a map and get back a map with the original keys and updated values? A mapmap function? I find myself doing this a lot and use reduce like:

(defn process-map
  [m]
  (reduce #(let [v (get m %2)
                 new-v (some-processing-here v)] (assoc %1 new-v)) {} (keys m)))
but seems like this is a useful method to have built in.

madstap16:07:38

There's the map-vals function from https://github.com/weavejester/medley

jsa-aerial19:07:17

wouldn't merge-with suffice for this? possibly a bit obscure looking:

jsa-aerial19:07:14

(mege-with (fn[_ v] (some-processing v)) m m)

schmee13:07:40

there is no built-in for that

schmee13:07:08

with Specter: (transform MAP-VALS your-fn your-map)

shidima_13:07:36

I have an atom with a vector with an map, how would I update the value :done of one item?

[{:id "1", :title "Learn Clojure", :done "active"} {:id "2", :title "Learn ClojureScript", :done "active"}]

schmee13:07:55

which item?

schmee13:07:08

by index or by id?

shidima_13:07:48

if possible

shidima_13:07:57

Pasted the wrong code 😐

schmee13:07:23

@shidima_ again, with Specter: (setval [ATOM ALL :id #(= your-id %)] :your-value your-atom)

henrik13:07:17

I’d like a version of empty? that doesn’t throw on numbers (etc), but simply informs me that, no, the number 9 (for example) is not empty, whereas "" is empty. What’s the least unintelligent way to achieve this?

henrik13:07:34

(my current method is quite unintelligent)

schmee13:07:41

can you post it?

henrik13:07:31

Basically a protocol that dispatches on type. Seqs and strings, return empty, java.lang.Object: return false.

shidima_13:07:43

tnx @schmee didnt know about Specter

schmee13:07:12

give it a try, it’s made exactly for these kinds of problems!

schmee13:07:47

@henrik maybe just catch Exception and return false if it throws?

schmee13:07:55

certainly not the prettiest method either

henrik13:07:03

True, but perhaps better than straining the input to empty? through a protocol and hoping that I’m not straining too aggressively. Or not aggressively enough.

arohner16:07:27

Is classlojure the best way to have multiple clojure runtimes in the same JVM?

ghadi16:07:48

probably shimdandy @arohner

ghadi16:07:18

@tcrawley or jim crossley are the experts there

arohner16:07:34

@ghadi I’m writing a library where I won’t have control over how the JVM is started up. Does shimdandy still work there? From the readme it looks like it wont

ghadi16:07:44

not sure what boot uses but they do it too

juhoteperi16:07:22

Boot uses shimdandy

tcrawley16:07:34

@arohner meaning you can't control the classpath?

arohner16:07:01

I’m working on https://github.com/arohner/spectrum. Spectrum uses tools.analyzer. Tools.analyzer uses eval, which breaks defrecords and protocols when files are reloaded. I’m looking for a way to isolate the code reloading

tcrawley16:07:59

Ah, a library, so you can't keep clojure.jar off of the cp

tcrawley16:07:23

yeah, shimdandy won't work for you there

bronsa16:07:50

@arohner could you try maybe isolating the classloader that t.a uses?

arohner16:07:46

AIUI, it’s compiler.java that’s creating new classes via eval, so it’s the compiler’s classloader that matters?

lwhorton16:07:03

how is one supposed to use loop/recur to reduce a nested collection?

given {:children {1 {:children {3 {:children {}} 2 {:children {}}

(defn recurse-children [acc root]
  (reduce (fn [a node] 
    (if (empty? (:children n)) 
      (do-accumulation acc node)
      (map #(recurse-children a %) (:children n)))))
^ this is what I want to do, but I know that will result in an overflow

bronsa16:07:36

I think if we provided a custom classloader that extends DynamicClassLoader we could be able to isolate the evaluation that happens through tools.analyzer and the clojure runtime

lwhorton16:07:55

except if I try to rewrite that in loop/recur, i will end up with some sort of (map #(recur acc %) (:children n)) at some point, which I know isn’t valid either

bronsa16:07:05

don't have time right now but if you're stuck on it I can give it a try this weekend

arohner16:07:34

@bronsa I’m happy to work on it now, but I’m not following yet. which behavior in the CL needs to change?

noisesmith16:07:11

@lwhorton it can be done breadth first if you add an extra accumulator for nested children, so you process items if leaves, or append to the accumulator if branches, then recur on the vector of branches

bronsa16:07:17

DCL has a map that goes classname -> class, and that's how the Compiler resolves classes, if analyze+eval did evaluation using a different classloader using a different class cache, it might not impact the regular evaluation context (so no redefining of defrecords)

bronsa16:07:32

I've literally given it just 20 seconds of thought tho, it might not work

noisesmith16:07:56

@lwhorton that said, the result often looks weird enough that it’s worth just using non-optimized recursion until you know you have inputs too big for that

bronsa16:07:18

in particular there might be some more issues to solve around namespaces

lwhorton16:07:52

as always, a big help @noisesmith .. dont think I’ll hit that limit for quite some time

arohner16:07:01

The most recent thing I tried doing was 1) grabbing the current classpath. 2) creating a new URLClassLoader using the current classpath URLs, but setting the parent classloader to (.getParent (.getClassLoader clojure.lang.RT)). 3) Using classlojure to eval-in in that supposedly isolated classloader.

slpssm16:07:32

@schmee Thanks for the pointer to Specter. Looks useful beyond my use case. 🙂

arohner16:07:13

hrm, using (.getParent (clojure.lang.RT/baseLoader)) seems to work

bronsa16:07:06

@arohner what's the issue specifically btw? something we have to fix in t.a.jvm?

axl31616:07:07

How do you load a local jar in a clojure project? Is there a lein way?

bronsa16:07:38

ideally t.a.jvm/analyze-ns shouldn't behave differently than normal clojure namespace reloading

arohner16:07:42

@bronsa still trying to figure it out 🙂 not sure if it’s user error or bug

arohner16:07:08

I’m also trying to get analysis for e.g. clojure.core, so normal reloading is not good enough

bronsa16:07:12

I've cried many many tears trying to make that the case and I thought that's how it behaved now

bronsa16:07:24

yeah that might cause some issues

bronsa16:07:12

altho with clojure.core you should be able to avoid eval

bronsa16:07:16

as everything is already evaluated

arohner16:07:05

oh, so write an analyze-ns that doesn’t call analyze+eval?

bronsa16:07:27

either that or wait for me to add a :no-eval option to analyze-ns :)

bronsa16:07:58

but yeah you can try that for the time being

bronsa16:07:15

hm, deftypes might get corrupted as t.a.jvm does an internal eval to set up reflection contexts :( so not as easy as just not using eval

bronsa16:07:35

I have to go now but I'll think about it. I'm sure there's a way to make this less painful

noisesmith17:07:23

@aymat316 the easy way is to install that jar in your local cache (which is lein install for lein projects) then you can just add it to your deps

noisesmith17:07:43

though when you deploy you’ll probably need to make sure the deployed jar can find the artifact

noisesmith17:07:55

which might mean deploying the jar to clojars (for open source you want to share) or might mean building an uberjar on your local machine or hosting a secure private maven repo of your own

grav18:07:00

In Datomic, I can test my queries on an inline datastructure, like (d/q '[:find ?e :in ...], [[123 :att :val] [[456 :att :val]]) Does something similar exist for SQL tables, so that I do not have to spawn a real database for integration tests?

hiredman19:07:45

there are file back and memory backed sql databases, but none of them are entirely compatible with the popular client/server sql dbs

hiredman19:07:37

generally, the way I deal with wanting to run things entirely in memory is I create a protocol that represents a set of queries, and then have some kind of in memory store that satisfies that protocol, a long with something that satisfies the protocol for storing in a database, and swap one for the other in tests or whatever

robert-stuttaford19:07:28

@grav did you try the code sample you shared? it should work 🙂

spieden21:07:42

@grav there tend to be enough vendor specific differences between SQL databases that @hiredman’s solution is the only one i’ve had success with

spieden21:07:14

worked on a codebase that tried to do sqlite tests with postgres prod and bugs persistently crept in

donaldball21:07:54

You go to production with the isolation level you have, not the isolation level you want to have.

mccraigmccraig22:07:42

@grav docker compose offers a decent way of running integration tests against a throwaway copy of your actual db

jgeraert07:07:54

You can even map the directory of your db to a tmpfs speeding it up massively.