Fork me on GitHub
#clojure
<
2016-12-23
>
noprompt00:12:20

actually you probably don’t even need the thunks

noprompt00:12:44

(let [form '((nil? x) a b)
      [g if-t if-f] form]
  `(let [ret# ~g]
     (if (boolean? ret#)
       (if ret#
         ~if-t
         ~if-f)
       (ret# ~if-t ~if-f))))

noprompt00:12:44

it’d be a good exercise in macro writing.

nikki00:12:50

hmm my background so far is lisp and not totaly familiar with the ~ # stuff yet

nikki00:12:52

like common lisp

nikki00:12:58

where you gensym manually or do with-gensyms etc.

noprompt00:12:10

it’s always fun to explore stuff like this even if the premise is questionable.

nikki00:12:37

yeahhh 😄

nikki00:12:57

i feel like it's ok to assume 'faulty' premises if you work inside, like how you are given params in a spec/function and work inside it

gfredericks00:12:59

questions should mention if something is for production or just for YOLO purposes

nikki00:12:04

you can then repurpose the func for different situations

nikki00:12:13

so maybe you can replace the premise with something more applicable later of similar spec

nikki00:12:35

haha unfortunately my production role is also sort of YOLO atm

noprompt00:12:06

YOLO macro writing is good for your programmer soul.

noprompt00:12:02

i have a folder full of random YOLO code. last year i wrote a clojure to ruby compiler in ruby. i called it “risk”. 😄

noprompt00:12:57

i should actually rewrite it in clojure and make it a serious project though.

noprompt00:12:16

metaprogramming++

nikki00:12:07

@noprompt do you eval at macrotime to see if it's a boolean or not

nikki00:12:08

it seems you do

nikki00:12:19

oh wait no u don't

nikki00:12:43

but this macro needs to exist at every possible (op a b) form lol

nikki00:12:27

so @noprompt seems like the macro needs to be like (the-macro (... all ur code here ...))

nikki00:12:33

and it walks the AST and replaces with ur thing above

rcanepa00:12:41

Hi everyone... I have a web application backend that makes use of java code, which I added from an external repository (not from Clojars). My backend works well when I start it through lein repl or lein run, however, it doesn't work from an uberjar. It fails on starting a component which use the java code I mentioned before. Shouldn't be the context/environment of those types of execution equal?, could be a difference between the java class path on them?

gfredericks00:12:35

you can debug the classpath using lein classpath

rcanepa00:12:51

I am a bit lost. Any pointer to the right direction would be very appreciated.

rcanepa00:12:35

Ok, and print the java.class.path from the uberjar too? to compare them

gfredericks00:12:54

yeah, anything of that sort

gfredericks00:12:14

lein classpath helps you run the code without leiningen being involved, which eliminates a lot of possibilities

gfredericks00:12:54

how does it fail, exactly?

rcanepa00:12:15

lein classpath only printed the classpath... it didn't start the application.

rcanepa00:12:29

First, I get some warning messages. Like this: WARNING: Required dependency 'org.pentaho.reporting.engine.classic.core.ClassicEngineCoreModule' for module 'org.pentaho.reporting.engine.classic.core.modules.gui.common.GuiCommonModule not initializable.

gfredericks00:12:36

I know, I'm saying you can call java yourself using the output of lein classpath

noprompt00:12:52

@nikki i’d recommend clojure.walk/postwalk for that.

gfredericks00:12:06

that way you have a raw java command that may or may not have the same problem

nikki00:12:14

@noprompt interesting, thanks will take a look!

rcanepa00:12:16

Then it throws a java.lang.IllegalStateException

rcanepa00:12:22

SEVERE: class org.pentaho.reporting.engine.classic.core.ClassicEngineBoot failed to boot: java.lang.IllegalStateException: Booting the report-engine failed.

gfredericks00:12:25

rcanepa you could call java with the clojure.main class if you want and it would start a repl

rcanepa00:12:24

Ok. I will try to do that

gfredericks00:12:42

wow I did the @ completely wrong there

nooga00:12:18

(deref gfredericks) yeah, looks like it

rcanepa00:12:49

@gfredericks if I understood you well, I should start my application using java (without leiningen) and see what happens, right?

rcanepa00:12:08

I used java with clojure.main and the classpath provided by lein classpath. I started the application and it didn't throw any error.

rcanepa00:12:54

This means that the classpath is the problem?

gfredericks01:12:21

smells like leiningen is the problem

gfredericks01:12:17

probably the next step is figure out exactly what java command leiningen is running when you do lein run

gfredericks01:12:37

I'm not quite sure how to convince leiningen to tell you that but maybe somebody else knows

rcanepa01:12:27

ps aux | grep java? ... it shows /usr/bin/java -classpath <insert huge class path here> <insert java variables> clojure.main -i /private/var/folders/nf/gvk9h4953097hspqvpdrrh300000gn/T/form-init5259320840110875260.clj

rcanepa01:12:21

I printed the java.class.path from the uberjar and I got one reference to the .jar file.

gfredericks02:12:22

all the stuff in the /private/...clj file can be important

gfredericks02:12:35

likely difficult to read though; depends on how motivated you are

rcanepa02:12:01

super motivated... I want to solve this

gfredericks02:12:09

oh another thing to try is LEIN_NO_USER_PROFILES=1 lein run

gfredericks02:12:13

if you have a user profile

gfredericks02:12:33

and/or deleting any extraneous libraries/plugins from your project.clj

rcanepa02:12:30

Ok... I will try that too. Also, the only library or piece of code which is giving me troubles are these java classes from an external repo. In order to add those dependencies I had to add this keyword :repositories [["pentaho" ""]] to my project.clj

richiardiandrea02:12:46

Is there a way to convert an Exception to a stringy format (in order to be passed as message over the wire) and keep the stacktrace info as well?

mss04:12:26

@richiardiandrea having the same problem myself. if you generate exceptions with ex-info and consume them with ex-data, they are more easily serializable. unfortunately doesn’t help for java exceptions/errors. if you find anything that solves your problem would love to hear it

mss04:12:48

yep, and the root-cause one is interesting

richiardiandrea04:12:06

Yeah I am trying those now 😀

mss04:12:00

Throwable->map

bleadof09:12:19

How do I define a schema where I have non-empty vector of type? If I do

[(s/one s/Str)]
, it only allows one, but I’d like to have one or more, like + in regular expression? (cross posting from #schema)

bleadof10:12:43

[(s/one s/Str :errors.select-one) s/Str] seems to work

igrishaev10:12:35

@bleadof

(s/defschema NonEmptyList
  (-> [s/Int]
      (s/constrained not-empty)))

bleadof10:12:39

Oh, that works? I tried that without defschema 😄

igrishaev10:12:36

@bleadof you may declare it in place: (s/constrained [s/Int] not-empty)

bleadof10:12:24

Hmh, I remember getting class cast exception, maybe there was some other error with it...

bleadof10:12:28

I’ll try.

bleadof10:12:43

@igrishaev Thanks, I don’t know what I did wrong when I tried that last.

bleadof10:12:41

Ah, yeah, I think it’s because my type is an enum and causes a bug somewhere else enum schema.core.EnumSchema cannot be cast to clojure.lang.Named

tdantas12:12:09

what is the best way to generate that output input: “olivia” output ( “o” “ol” “oli” “oliv” “olivi” “olivia”) I’m trying to use partition / partition-by but not getting correct output 😞

bronsa12:12:40

(rest (reductions str "" "olivia"))

lvh12:12:28

Is clojure.java.browse always loaded? I just the-ns ‘d it, and I was expecting that to fail.

lvh12:12:44

I am writing a test for a fn that is like the-ns, except it will require the ns first, so that it always succeeds.

lvh12:12:57

(I am trying to find a ns that probably isn’t around yet for the test.)

lvh12:12:30

maybe I can remove-ns it

lvh13:12:43

nope: can’t remove-ns it. Once remove-ns’d, never comes back

lvh13:12:59

payne.core-test> (the-ns 'clojure.java.browse)
java.lang.Exception: No namespace: clojure.java.browse found
payne.core-test> (require 'clojure.java.browse)
nil
payne.core-test> (the-ns 'clojure.java.browse)
java.lang.Exception: No namespace: clojure.java.browse found

lvh13:12:51

StackOverflow suggests (require ‘sym :reload), but that didn’t work:

lvh13:12:01

payne.core-test> (require 'clojure.java.browse :reload)
nil
payne.core-test> (the-ns 'clojure.java.browse)
java.lang.Exception: No namespace: clojure.java.browse found

lvh13:12:08

clojure.java.browse is in (loaded-libs) — I was hoping that’s what :reload would address.

lvh13:12:58

I guess I’m calling clojure.tools.namespace/remove-lib

lvh13:12:32

Got it! looks like it’s a clojure.* specific behavior.

andmed13:12:28

Hi All. I am trying to call clj -main method from Java (via bazel). If I just load a clj script with RT, I get into that script's namespace. If I invoke only -main method, however, I remain in clojure.core namespace. Cant google much help on how to do both: switch to the clj namespace and call a method there, from java

lvh13:12:09

When I attach metadata to a var like so:

^{:reason "General market metadata, not security-relevant"}
    #'amazonica.aws.ec2/describe-spot-price-history
Where does the metadata go? (Clearly not on the var.)

hlolli14:12:05

(meta var) ?

lvh14:12:25

@hlolli No, that has the usual var metadata, not :reason.

andmed14:12:38

oh, this seems to work

RT.var("clojure.core", "require").invoke(Symbol.intern(main));
        Var.pushThreadBindings(RT.map(RT.var("clojure.core", "*ns*"), main));
        RT.var(main, "-main").applyTo(RT.seq(args));
hope, its OK

kah0ona14:12:58

hello, if i do, (drop-last [1 2 3]), it becomes a list (ie. vector? on the results returns false). how can i keep it a vector?

kah0ona14:12:08

wrapping it in a (vec ..) might be inefficient?

kah0ona14:12:51

i have a reduce fn where i occasionally need to return a (drop-last my-accumulated-result), where my-accumulated-result is (and should stay) a vector

sveri14:12:42

From: http://insideclojure.org/2015/01/07/vec-perf/ "A 1024 element vector drops from 14 microseconds to 8 nanoseconds - 1000x improvement"

kah0ona14:12:15

aah thanks!

lvh14:12:22

kah0ona: subvec also may do what you want

lvh14:12:37

possibly not a vector in the first place

sveri14:12:39

subvec expects a vec as apram

lvh14:12:07

Isn’t that what kah0ona is asking? they have a vec and they would like it to remain a vec

sveri14:12:58

Then I may have misunderstood it

kah0ona14:12:21

my reduce-fn now returns a list sometimes

kah0ona14:12:38

i was wondering if calling (vec ..) before returning would be a significant perf impact

lvh14:12:25

kah0ona: always measure

kah0ona14:12:33

because basically each iteration of the reduce i do a drop-last (which stops it being a vec), and then making it a vec again with (vec ..)

kah0ona14:12:39

i thought that would be a bit slow 🙂

lvh14:12:40

kah0ona but if you want an alternative that preserves vec-iness, subvec does what you want

lvh14:12:05

kah0ona if all you do all the time is drop-last, maybe you just don’t want a vec to begin with, iunno

sveri14:12:05

Sounds like premature optimization to me 🙂

kah0ona14:12:17

yeah fair point 🙂

kah0ona14:12:24

yeh probably sveri 🙂

kah0ona14:12:34

ok i'll just 'make it work' then first 🙂

kah0ona14:12:37

thanks anyways

lvh14:12:47

kah0ona there are good reasons for caring about the type

kah0ona14:12:04

i have a csv file which i need to process

lvh14:12:08

e.g. if you care about something being on the front or the back, conj will do the opposite on a vec vs a seq

kah0ona14:12:17

yeah i need conj to go on the back

kah0ona14:12:23

so if figured a vector would suit me

lvh14:12:34

kah0ona: what are you trying to accomplish with the csv file

kah0ona14:12:35

but if i use subvec instead of drop-last

kah0ona14:12:56

reducing it to some other datastructure (ie. grouping rows)

kah0ona14:12:44

the csv is already in chronological order (i have a csv file of electrical current peak readouts, each row is a time stamp and a power (watts) integer)

kah0ona14:12:07

i'm trying to make some sense of it, but it's a daemon that does this for lots of potential sources that produce these csv's

lvh14:12:11

grouping rows because of their order relative to one another, or based on some data in the individual rows

kah0ona14:12:23

well ok, so

lvh14:12:24

What’s the grouping? by wattage bucket or by time bucket?

kah0ona14:12:31

bij peak size

kah0ona14:12:37

so it might be that it's like 5second peak of 1000

kah0ona14:12:42

then 3 seconds peak of 100

kah0ona14:12:47

i want then two rows in my result

lvh14:12:06

is there a per-second measurement or something?

kah0ona14:12:16

[{duration 5s :amplitude 1000} {:duration 3s :amplitude 100}]

kah0ona14:12:22

yeah it's timestamped

kah0ona14:12:31

but it might be that a few timestamps in a row

lvh14:12:36

how do you know that a peak ends?

kah0ona14:12:37

have the same (range) of peaks

kah0ona14:12:49

well i classif y it

kah0ona14:12:56

ie. range x to y is peak type A

kah0ona14:12:05

range z to a is peak type B

lvh14:12:24

Have you considered making your reduction accumulator being [peaks current-peak] instead of peaks where the last one is a peak in progress?

lvh14:12:04

(You can destructure in the reducing fn, but maybe you don’t need reduce in the end after all, although it sounds probable)

kah0ona14:12:58

i have yeah, basically there's multiple ways to do it

kah0ona14:12:10

reduce is kinda natural to me in my brain 🙂

lvh14:12:21

(fn [[peaks current-peak] measurement] (if part-of-peak? [peaks (conj current-peak measurement)] [(conj peaks current-peak) []]))

lvh14:12:26

something like that

kah0ona14:12:28

so i just figured, peek the previous one (since it's a vec its fast)

kah0ona14:12:14

well i might as well show it what i've got atm 🙂

kah0ona14:12:19

(defn reduce-fn
  [result-vec current]
  (let [previous (peek result-vec)
        current-peak (abs (second current))
        previous-peak (abs (peek (:peak previous)))
        current-class (classify current-peak) ; we need 2nd column
        previous-class (if previous 
                         (classify previous-peak)
                         nil)
        
        current-timestamp (parse-timestamp (first current))]


    ;if previous is nil, it's the first item, add it
    (cond
      (or 
        (nil? previous)

        ;not the same? we now have a new peak, build a new record to be conj'd to the result-vec vector
        (not= current-class
              previous-class)) (conj result-vec 
                                     (build-new-record 
                                       current 
                                       current-class 
                                       current-peak))

      ;same, extend the end-time of the peak
      (= current-class 
         previous-class) (-> result-vec 
                             (vec)
                             
                             ;add updated version with new timestamp
                             (conj (update-record 
                                     previous 
                                     current-timestamp 
                                     current-peak))))))

kah0ona14:12:39

my result will be a vector of maps

lvh14:12:56

you can do things in more than one step

kah0ona14:12:59

and a new record (2nd param to the reduce-fn is [timestamp amount]

lvh14:12:04

group measurements, then translate that to the maps

lvh14:12:23

I mean, you can do it in one go, that’s fine

lvh14:12:39

but I would strongly recommend keeping your peak-in-progress separate and using destructuring as I mentioned above

kah0ona14:12:41

i can't just bucket it though, because i need to retain info about sequential ordering of peaks

kah0ona14:12:58

but the resulting datastructure eases my processing further on, so for now i'll stick with this

lvh14:12:09

to rephrase, I consider your problem to be a category error about adding incomplete data to a set that’s mostly-complete data

lvh14:12:25

I’m not suggesting you bucket, the reduce is fine

kah0ona14:12:31

so what exactly do you think is 'wrong' is my approach?

lvh14:12:01

Exactly what I just said: it’s annoying to have special treatment for the last value

lvh14:12:10

and the reason you have special treatment is because that last value doesn’t belong (yet)

lvh14:12:19

you can fix that by destructuring the accumulator

lvh14:12:37

it removes all of the special cases I can see there

lvh14:12:48

you always have a peak-in-progress; maybe empty

kah0ona14:12:06

ok i see yeah it removes the 'special case' entirely

lvh14:12:13

gotta go

kah0ona14:12:16

only add it when a peak is 'complete'

kah0ona14:12:18

thanks 🙂

lvh14:12:20

veel geluk, prettige feesten &zoverder

kah0ona14:12:25

ja van hetzelfde

tankthinks16:12:58

thanks @luke … hope I captured the main points

tankthinks16:12:38

I have to be honest, coming from a Java background … when you mentioned app via configuration I had flashbacks of spring xml configuration

tankthinks16:12:40

but I think the idea of application level concepts as configuration is revolutionary

kwladyka17:12:01

what do you use to transform data from one data data structure to another and in the way back? Just imagine two systems with products data represented in different data structure. I am looking simple small solution. I can always do it manually, but maybe somebody did something interesting.

Emma18:12:22

Hi, I have a question. I'm building an app in Clojure and I want it to display a splash screen while app starts. This means, that I need it to load before Clojure.core is loaded. Thus, it should, probably, work from Java land. (start main function in Java. It shows splash screen, while Clojure main function is loading). So, what is the best way to organise it? (The easiest, of course, is to have a .sh startup script which starts SplashScreen.jar and waits for MainApp.jar to load. Thanks.

bfabry18:12:21

@mik starting two jars seems not amazing, I would write a java class that is the main entry point for your application, runs the splashscreen and then runs your clojure code using Clojure.var

bfabry18:12:06

of course clojure.core would have to be loaded for that, but clojure.core actually loads very fast

Emma19:12:02

@bfabry Well, then the question at this point becomes: "Can lein build uberjar with entry point in Java"?

bfabry19:12:39

yup, no worries at all

bfabry19:12:15

probably the only caveat is it will default the repl namespace to :main unless you specify something else, which will muck things up if :main is a java class. so make sure you add a :repl-options {:init-ns user} as well

Emma19:12:59

@bfabry thanks. Will try.

bfabry19:12:08

you probably want to consider just doing it in clojure first though btw, just loading core is really not slow

11326-storage:link_account_exporter bfabry$ time java -jar ~/.m2/repository/org/clojure/clojure/1.9.0-alpha12/clojure-1.9.0-alpha12.jar -e "(println \"hello, world\")"
hello, world

real	0m1.367s
user	0m1.582s

bfabry19:12:12

there's plenty of situations out there where 1.5s is an age, but I don't think one where you're showing a splashscreen is one of them 🙂

Emma19:12:08

well, that may work too.

endsbeginnings20:12:21

Hi - I am experimenting with using Apache Kafka and Clojure. Was thinking of using Java's Executors and running each Kafka producer on a separate thread. I am wondering if anyone in the community has suggestions on whether this is a good approach in terms of scalability, maintainability ...

rratliff20:12:13

I have a project i just generated with Leiningen, and when I run “lein repl” inside it, I’m noticing that I get the user namespace as the prompt. Is there anything I need to do differently to get my project’s namespace? Is it perhaps because I have a compojure project w/ Jetty so there’s no main method I have defined?

bfabry20:12:43

@rratliff the leiningen repl will be :repl-options {:init-ns} or :main or user

bfabry20:12:59

so if you don't want it to be user you should specify :main or :init-ns

rratliff20:12:09

cool, thanks

rratliff21:12:27

Why are my compojure routes not matching? I tried fiddling around with the middleware, but when I browse to http://localhost:3000/documents, I just get “not found”

(defroutes app-routes
           (GET "/documents" [] (get-all-documents))
           (POST "/documents" {body :body} (create-new-document body))
           (GET "/documents/:id" [id] (get-document id))
           (PUT "/documents/:id" {id :id, body :body} (update-document id body))
           (DELETE "/documents/:id" [id] (delete-document id))
           (route/not-found "Not Found"))

(def app (wrap-params app-routes))

rratliff21:12:19

never mind, my get-all-documents function was returning nil

rratliff21:12:38

ok, so this is more of a beginner question, why does this return nil?

(defn get-all-documents [] ({:name "Test document 1" :body "Test body 1"}
               {:name "Test document 2" :body "Test body 2"}))

sveri21:12:28

@rratliff It does not return a response

sveri21:12:34

Look here if you want to return json: https://github.com/ring-clojure/ring-json

rratliff21:12:42

is the ({:name "Test document 1" :body "Test body 1"} {:name "Test document 2" :body "Test body 2”}) expression creating a list of maps? but not in the valid response structure for ring?

rratliff21:12:53

I found if I prefix it with a single quote it does work.

rratliff21:12:01

work as in, the route matches.

sveri21:12:10

like this, it tries to execute it as a function

sveri21:12:40

and applies the second map to the first one. So it looks for a key in the first map that is similar to the second map

sveri21:12:07

'() turns it into a seq

rratliff21:12:18

ok, so in my defroutes when I say (get-all-documents) I’m not actually calling that function, I’m just telling it here is a function to use to pass in a request and it returns a response.

rratliff21:12:19

I’m following a Compojure tutorial that has me doing DB setup right away, and I figured I’d try to get it working with static values first, just to focus on the Compojure concepts first.

rratliff21:12:38

so more abstractly, the single quote tells clojure, don’t evaluate these forms?

sveri21:12:13

I am not sure if that is true for all the cases. But it is true for lists. So while (foo) will be evaluated, '(foo) does not

sveri21:12:21

and instead it turns it into a sequence

sveri21:12:53

(first '(1 2)) returns 1

bfabry22:12:39

the single quote is syntax sugar for the special form quote so '(1 2) is equivalent to (quote (1 2)), which yields the unevaluated form http://clojure.org/reference/special_forms#quote

lspector22:12:26

Does anyone know of an implementation of statistical tests like a t-test that's NOT in incanter? I'm having confusing dependency clash issues (?) with incanter and I just want a t-test (or maybe another test like an f-test), either in a simpler and more recently updated library or just a bit of source code I could copy/paste. Web searches haven't found it for me yet and I'd rather not code from scratch...

bfabry23:12:05

@lspector when I can't find a maintained clj lib for stuff like that I reach for java. this looks pretty good https://commons.apache.org/proper/commons-math/javadocs/api-3.6/org/apache/commons/math3/stat/inference/TTest.html

lspector23:12:32

Thanks @bfabry! The rub for me will be figuring out how to get that into my clojure project... as I generally live in pure clojure and don't do interop.

lspector23:12:19

I assume I need something in project.clj, something in my ns declaration, and then maybe something to massage arguments and return value so that I can make a function that I give two vectors and returns a p-value...

bfabry23:12:31

you'll need to add the dep to your project.clj same as you did with incanter, like here https://mvnrepository.com/artifact/org.apache.commons/commons-math3/3.2 (click on leiningen tab)

bfabry23:12:47

then you'll need to :import the TTest class

lspector23:12:11

Ah -- beautiful.

bfabry23:12:46

then you'll need to do something like

(let [v1 [1.2 1.4]
      v2 [1.6 1.7]
      new-t (TTest.)]
  (.t new-t (double-array v1) (double-array v2))

lspector23:12:43

Oh that's great! One missing piece (for me :-), is what goes in the ns declaration

bfabry23:12:05

in the ns decl you'll need (:import (org.apache.commons.math3.stat.inference TTest))

lspector23:12:18

Awesome! I'll give this all a try. Thanks!

bfabry23:12:39

clojure interop with java is really great because it gives you access to tons of libraries already written in java

lspector23:12:17

I realize that in principle, but not knowing my way around java it has always been a bit mysterious too, especially because I didn't previously know how to include dependencies not on clojars... but I'm working through the changes you suggested and about to test them, and this may be the dawn of a new day 🙂

bfabry23:12:25

leiningen should check both clojars and maven central by default, so anything on maven central (basically the whole java ecosystem) should just work

lspector23:12:02

I didn't previously know how to get the thing to put in project.clj if it wasn't in clojars...

bfabry23:12:26

ahhh yeah well you can click on the leiningen tab to get that. it also pays to just switch between leiningen and maven and see how the xml translates to the vector

lspector23:12:01

Cool. I didn't even know about http://mvnrepository.com, to say nothing of that tab. Probably obvious if you come from the Java world, but I come from the Lisp world...

lspector23:12:20

BTW I do think it's working, although I see that I need to use .pairedTTest rather than .t

lspector23:12:26

Or actually, I think I should use .tTest (not .pairedTTest), but that's a stats issue not a software issue!