# #clojure log - Jul 25 2015

The Joy of Clojure
Main Clojure site
IRC
List of all logged dates

0:00 TEttinger: I can kinda tell what's going on

0:00 ,(let [o *] (Math/floor (o (o (o 1/2)))))

0:00 clojurebot: 0.0

0:00 TEttinger: ,(let [o /] (Math/floor (o (o (o 1/2)))))

0:00 clojurebot: 2.0

0:02 TEttinger: so it either repeats 0 times for *

0:02 err

0:02 repeats n times for *

0:02 or n + 2 times for /

0:03 justin_smith: yup

0:03 that's so we get the right answer no matter which one gets picked

0:04 TEttinger: ,(/ (/ 3))

0:04 clojurebot: 3N

0:04 TEttinger: ,(* (* 3))

0:04 clojurebot: 3

0:05 kavkaz: How do I calculate the sqare root of a number in Clojure?

0:05 justin_smith: ,(Math/sqrt 2)

0:05 clojurebot: 1.4142135623730951

0:05 TEttinger: kavkaz: typically you use the built in stuff in Java's Math class

0:05 like justin_smith demonstrated

0:05 justin_smith: TEttinger: remember reduce supplies two args - that's the last bit to solving the whole thing

0:05 TEttinger: Math does not have a cube root, but it does have pow

0:06 kavkaz: Oh I see, thanks justin_smith, TEttinger

0:06 I thought I tried the same thing before, but trying it again in the REPL showed me i had a typo

0:06 TEttinger: ,(reduce * [2 2])

0:06 clojurebot: 4

0:07 TEttinger: ,(reduce / [2 2 2 2])

0:07 clojurebot: 1/4

0:07 TEttinger: ah

0:07 justin_smith: and there you have it

0:07 TEttinger: ,(/ (reduce / [2 2 2 2]))

0:07 clojurebot: 4N

0:07 TEttinger: ,(* (reduce * [2 2]))

0:07 clojurebot: 4

0:07 TEttinger: neat

2:44 justin_smith: re: core.matrix I think it's a great idea but I don't know how it interops with existing java code that produces 2d primitive arrays?

2:45 justin_smith: TEttinger: it's a protocol, at least one of the backing implementations uses jblas

2:48 crocket: Is clojurescript ok for making command line apps?

2:51 TEttinger: hm. vectorz has an impl for double arrays (1D I think) being "vectorizable"

3:19 crocket: Does clojurescript run on node.js without much hassle?

3:38 Reader monad can pass log config data down to the function at the bottom of a call stack without adding the log config to every function in the middle.

3:47 xtrntr: hi, i tried this example on rosetta code

3:47 it doesn't work

3:47 "could not locate quil/core_init.class or quil/core.clj on classpath" it says

3:50 i followed the instructions on the quil homepage too, met with the same problem

4:00 oddcully: xtrntr: have you started with the lein template as described here: https://github.com/quil/quil/wiki/Installing ?

4:43 xtrntr: oddcully: sorry for the late reply

4:43 i saw that page and yea it works for me now :)

4:49 the example on the page works, not the rosetta code snippet

4:49 will -try- at it

5:21 kwladyka: i stack during write algorithm, i recursive problems :P Do you know good pattern or best practice to write complex algorithms? I don't know, like draw this on paper or something. I am looking new creative things which will help me solve it.

5:52 crocket: How do I pass log config to every log function concisely?

5:53 log/info(log-config "ok, log this")?

5:53 This is not working well.

5:53 You're going to use a global object, or pass log-config everywhere.

5:53 What else do we have in clojure?

5:55 TEttinger: you may be able to set a log-config as a default? what logger are you using?

6:06 crocket: TEttinger2, I currently use tools.loggin and unilog.

6:06 I even contribute to unilog.

6:06 It uses logback.

6:06 It's not going to work on clojurescript.

6:28 kwladyka: it is maybe stupid question, but i am totally confuse now... When use for and when use loop with recur? i have some situations where i am not sure which one should i use in algorithm.

6:29 i need to build tree of solutions, like backtracking

6:30 and some of branch will fail so shouldn't be show as result

6:30 but some will pass

6:31 oh... it is just complex :)

6:31 maybe i will find something in the Internet

6:49 wasamasa: crocket: stuart sierra's component library gives you dependency injection to solve that problem

6:55 xtrntr: i get this error when following the clojurescript tutorial

6:55 Error: Could not find or load main class clojure.main

6:55 when i try to run java -cp cljs.jar:src clojure.main build.clj in termianl

6:56 using os X

6:56 anyone knows why?

7:34 jaarod: hi.. if you are typed clojure user, are you using it everywhere in your new code?

7:35 xtrntr: oh :(

7:49 If a library uses clojure 1.6 and another uses 1.7, will there be a problem?

8:23 stian: crocket: clojure rarely breaks backward compatibility, 99% of the time stuff just works after an upgrade without any changes.

8:25 crocket: If A requires clojure 1.6 and B requires 1.7 and C requires A and B, C will end up requiring 1.6 and 1.7.

8:26 JVM wasn't known to handle multiple versions of the same dependency well.

8:27 stian, ^^

8:28 justin_smith: "If A requires clojure 1.6 and B requires 1.7 and C requires A and B, C will end up requiring 1.6 and 1.7." - no, this is 100% wrong

8:28 crocket: Then, what

8:28 justin_smith: one of the versions is picked, the logic for picking one is up to the tool (likely lein in your case)

8:29 the primary job of lein is to take your project.clj and build a classpath. Only one of those deps will end up in the classpath it generates.

8:29 crocket: If 1.6 and 1.7 are incompatible, what happens?

8:29 justin_smith: crocket: then you are fucked. But they are compatible, so you are fine.

8:29 stian: crocket: afaik, it will use the clojure version defined in your project, not the one defined in the library.

8:30 justin_smith: stian: yes, if you explicitly have a top level dep, it will override transitive deps (with some caveats)

8:30 crocket: I don't like this.

8:31 justin_smith: crocket: feel free to find a language ecosystem where libs don't have versions.

8:31 crocket: justin_smith, I think it makes sense to be able to load two versions of the same dep.

8:31 npm does that.

8:31 justin_smith: and it sucks

8:32 crocket: note that with clojure on node, you can't have two versions of the same namespace

8:32 crocket: Is it ok to use OSGi to load multiple versions of the same dep?

8:32 Ah, right

8:32 justin_smith: crocket: it's possible, and it sucks.

8:33 crocket: namespace doesn't support versions.

8:33 justin_smith: right

8:33 crocket: This is very common.

8:33 A depends on logback 0.9, and B depends on logback 1.3.3.

8:34 logback 0.9 is incompatible with 1.3.3

8:34 Then, I can't depend on both A and B.

8:34 justin_smith: there's an experimental version of clojure from rritoch that supports multiple versions of a namespace via osgi, but I don't really think the result is worth the complexity

8:35 crocket: I wish Rich Hickey solved that problem up front.

8:35 justin_smith: he did, the solution is not to support multiple versions of one namespace

8:36 crocket: That's not a solution

8:37 It amounts to declaring that it's a non-problem.

8:37 no problem, no solution.

8:37 justin_smith: there's no way of allowing multiple versions of a namespace in one process that is better than not having the feature

8:46 crocket: I don't think Rich Hickey would accept OSGi...

8:46 He tries to be conservative.

8:46 bruncol, You just sent me a spam message.

8:47 Are you on windows?

9:09 justin_smith: I'm familiar with these concepts to various degrees...

9:10 in clojure we use protocols and multimethods instead of typeclasses

9:12 crocket: typically when I think I need a monad what I end up with is an extra parameters or bindings map that each "monadic" function takes and passes to other functions

9:15 crocket: Passing log-config to every function that doesn't need to log is not right.

9:15 I'm not sure how reader monad is different from dependency injection like component.

9:15 I'll have to learn.

9:16 justin_smith: it is a form of dependency injection, but used in a different way of course

9:17 crocket: so the alternative to passing the logging config to every function is to use a monad which lifts every function into a thing that holds the logging config?

9:18 crocket: could be

9:18 My guess

9:18 I'll soon start learning those tools

9:19 justin_smith, What do you think is the best way to handle log config without introducing impurity?

9:19 A global var doesn't sound right

9:19 justin_smith: crocket: one problem with monads in clojure is that unlike haskell, clojure is a very naive compiler, so monads are inevitably slow because they replace the call stack with a less efficient abstraction

9:19 crocket: does the log config change during one runtime?

9:19 crocket: yes

9:19 justin_smith, Refer to timbre

9:19 justin_smith: then it's impure

9:19 crocket: timbre has a mutable var.

9:19 timbre has a mutable *log-config*

9:20 justin_smith: right, yes it does

9:20 crocket: It is even dynamic.

9:20 I currently use unilog.

9:20 logback has a similar approach.

9:20 It is worse.

9:21 Plus, monad seems to intertwine every function it touches.

9:21 Like, a phase transition.

9:21 Just like any dependency injection framework.

9:21 justin_smith: yes, once you use a monad everything using that feature has to be lifted into monad-world

9:22 crocket: justin_smith, What is your suggestion?

9:22 It is hard to avoid a global state and a global function signature change at the same time.

9:23 justin_smith: crocket: if you want something to change, and thus alter how everything works, that is a global state, no matter what fancy technique you wrap on top of it

9:24 so why not accept that it's global state and manage global state in a reasonable way.

9:24 crocket: I use timbre with the per-namespace configs

9:26 crocket: justin_smith, Just do keep in mind that the current timbre maintainer is a tyrant.

9:26 He blocks people who want changes.

9:27 How do you apply per-namespace config?

9:27 By the way, unilog maintainer is open to changes....

9:27 justin_smith: crocket: it's a documented feature of the config

9:41 cmarques: I am trying to run tests from my editor, which is connected to a repl. My tests depend on things defined in the :test environment, however the repl is running with :dev profile. Is there any way to change the current profile when I execute the tests in a test namespace? Thanks!

9:43 justin_smith: cmarques: perhaps you could create a repl using the :test profile

9:44 cmarques: you can't change profiles at runtime, the profile isn't a thing that exists by the time your code is loaded - it's used to create the classpath / prep tasks / etc. that are used to launch your code

9:44 perhaps what you want is a runtime mechanism that changes some of the things your profile is controlling?

9:44 cmarques: justin_smith yeah, I thought about it, but then I'll need two instances of my editor running, one for each profile. It would be nice if there was a way to force the profile to be :test when I load a test file, like (load-profile :test) or something

9:45 justin_smith: cmarques: what editor? emacs at least can be connected to multiple repls

9:45 cmarques: like I said, the profile ceases to exist by the time your code is loaded

9:45 cmarques: justin_smith I guess that's the problem, I am using Vim with vim-fireplace

9:45 justin_smith: cmarques: what about the profile is different in your repl with :test ?

9:46 cmarques: justin_smith database connection urls

9:46 for example

9:46 justin_smith: cmarques: I'd use a mechanism that allows runtime update - look into env for example

9:46 cmarques: justin_smith cool, I'll have a look. Thanks!

9:47 justin_smith: cmarques: my typical approach is to have separate edn files for each config, and some code that loads one of the configs when bootstrapping the code

9:47 cmarques: then, I can still load another config at runtime, regardless of my initial config

9:48 this mixes well with stuartsierra/component

9:48 cmarques: justin_smith Hum... I am trying to use environ, which seems to be doing to much magic

9:48 justin_smith looks like your approach offers more control

9:49 justin_smith: cmarques: environ is miniscule (check out the source, there's hardly anything there) - I use environ to guide loading my defaults, but have a function that can still be used at runtime

9:49 flor-bcn: sorry, got disconnected. Asking the same question again, so I have two vectors of equal size, representing questions and answers. How do I merge the two vectors into a vector of hasmaps, something like [{:question "from v1" :answer "from v2"}] ?

9:51 justin_smith: ,(map merge [{:question "from v1"}] [{:answer "from v2"}])

9:51 clojurebot: ({:question "from v1", :answer "from v2"})

9:52 justin_smith: or ##(map (fn [q a] {:question q :answer a}) ["from v1"] ["from v2"])

9:52 lazybot: ⇒ ({:question "from v1", :answer "from v2"})

9:53 flor-bcn: justin_smith: I need each :question and :answer to come from a respective item in the vector. So first item in both vector produces {:question "my question" :answer "first answer"}, second item in both vector produces {:question "second question" :answer "second answer"}, etc

9:53 justin_smith: depending on what your input looks like

9:53 flor-bcn: that's what both those examples do

9:53 cmarques: justin_smith thanks for your help, I'll have a look at environ's source and see if I can come up with a way of redefining some of the values at runtime

9:53 justin_smith: ,(map (fn [q a] {:question q :answer a}) ["from v1" "also from v1"] ["from v2" "also from v2"])

9:53 clojurebot: ({:question "from v1", :answer "from v2"} {:question "also from v1", :answer "also from v2"})

9:54 justin_smith: cmarques: like I said it's pretty bare bones, I just use it to generate the default initial argument eg. :staging or :dev, that drives the real config

9:55 flor-bcn: v1 = ["q1" "q2" "q3"] , v2 = ["a1" "a2" "a3"] . Required result: [{:question "q1" :answer "a1} {:question "q2" :answer "a2"}....]

9:55 justin_smith: flor-bcn: that is what that code does!

9:55 ,(map (fn [q a] {:question q :answer a}) ["q1" "q2" "q3"] ["a1" "a2" "a3"])

9:56 jaarod: hi.. if you are typed clojure user, are you using it everywhere in your new code?

9:56 snowell: Wrap it in (vec) or (into []) if you really need a vector

9:56 flor-bcn: justin_smit: you're right, thank you so much !

9:56 jaarod: or just in certain parts of your code (which?)

9:57 justin_smith: snowell: s/map/mapv for that, of course

9:57 snowell: Heh, I always forget that exists

10:10 jaarod: ,(map inc "hi123")

10:10 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number>

10:10 jaarod: ,(inc '1')

10:10 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

10:10 justin_smith: ,(apply str (map (comp char inc int) "hi123")

10:10 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

10:10 justin_smith: ,(apply str (map (comp char inc int) "hi123"))

10:10 clojurebot: "ij234"

10:11 jaarod: comp char inc int?

10:11 justin_smith: characters are not numbers, but "int" will return a number when given a character

10:11 jaarod: ,(map (comp char inc int) "hi123")

10:11 clojurebot: (\i \j \2 \3 \4)

10:11 jaarod: I see

10:11 justin_smith: (comp char inc int) returns a function that applies int, then applies inc to the result, then finally applies char

10:12 jaarod: ,(str (map (comp char inc int) "hi123"))

10:12 justin_smith: it's equivalent to (fn [c] (char (inc (int c))))

10:12 jaarod: ah

10:12 justin_smith: jaarod: apply str uses each element of the coll as an argument

10:13 as opposed to str which simply looks at the coll itself. Because lazy-seqs are potentially unlimited, str does not look at their contents

10:13 but apply gets around that

10:14 Bronsa: justin_smith: it actually realized the collection anyway :/

10:14 ,(str (range))

10:14 clojurebot: "(0 1 2 3 4 ...)"

10:14 Bronsa: damned clojurebot

10:14 justin_smith: ,(str (map pr (range)))

10:14 Bronsa: ,(def a (str range))

10:14 clojurebot: #'sandbox/a

10:14 Bronsa: wat

10:14 clojurebot: eval service is offline

10:14 Bronsa: ,(def a (str (range)))

10:14 clojurebot: #'sandbox/a

10:14 Bronsa: :|

10:14 ,*clojure-version*

10:14 clojurebot: {:major 1, :minor 7, :incremental 0, :qualifier "master", :interim true}

10:15 justin_smith: Bronsa: the eval service offline was in response to me

10:15 oh, you mean the def a returning immediately?

10:15 Bronsa: yeah

10:16 justin_smith: ,(def b (map identity (str (range))))

10:16 clojurebot: #'sandbox/b

10:16 justin_smith: ,(def b (str (map identity (range)))

10:16 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

10:16 Bronsa: ,(def a (str (iterate inc 0)))

10:16 clojurebot: #'sandbox/a

10:16 Bronsa: wtf

10:16 justin_smith: well try that in your repl

10:17 no idea how clojurebot works

10:18 jaarod: I like comp, first time I see it

10:18 is it a function or a macro?

10:18 Bronsa: a function

10:18 justin_smith: a function, a very nice one

10:19 jaarod: see also, juxt - if you like comp you'll likely like juxt too

10:19 ,(map (juxt dec identity inc) (range))

10:19 clojurebot: ([-1 0 1] [0 1 2] [1 2 3] [2 3 4] [3 4 5] ...)

10:21 crocket: justin_smith, Is it with_config that you use in timbre?

10:23 justin_smith: crocket: I misremembered, I was actually just using the :ns-blacklist feature to turn off logging in some overly chatty namespaces at runtime

10:23 s/runtime/dev time

10:24 Bronsa: yeah, clearly I thought clojure was being smarter than it actually was

10:25 Bronsa: I mean the intuitive thing is that if a lazy-seq is not printed readably, that's to avoid realizing it...

10:25 Bronsa: justin_smith: there's no good reason for the toString of lazyseqs to be the way it currently is :/

10:25 justin_smith: (inc Bronsa)

10:25 lazybot: ⇒ 116

10:25 justin_smith: always with the facts!

10:33 crocket: I'm back.

13:06 smandy: hi I've got a java8 class that takes a lambda - can I call it from clojure? i.e is there some sugar in clojure to let me create the expected SAM implementation?

13:16 foos

14:40 arkh: smandy: i think you would do this through normal clojure<->java interop

14:49 smandy: nevermind - I just looked into it and wonder the same thing now

14:50 amalloy: you can just reify an interface

15:30 iamjarvo: if one wanted to run this snippet of code how would one go about it? http://pastie.org/private/bsmntfmjesikndoruxdksa my thought process now is i can use lein exec and execute the script or create a lein project. any thing simpler?

15:34 justin_smith: iamjarvo: java -cp <class path goes here> clojure.main -e '(load-file "path/to/that/file.clj")'

15:34 class path would hold any jars needed

15:34 if generating a classpath is complicated, then use a proper lein project and lein will do it for you

15:37 iamjarvo: justin_smith thanks

15:45 justin_smith: also, for a script, you can potentially create a project, use `lein cp` to output a classpath, and just run java directly when invoking the script

15:45 though uberjar might make more sense

15:51 Fare: I'm trying to reexport a var from one ns into another. That used to work, but I recently updated to 1.7.0 and it doesn't seem to work anymore

15:54 I get this error: java.lang.IllegalStateException: apropos already refers to: #'pyjure.debug/apropos in namespace: pyjure.core

16:01 justin_smith: sounds like you re-exported it already?

16:07 Fare: justin_smith, but no, I only re-exported it once

16:07 if I remove that re-export, the code loads, but the function is not exported.

16:14 xeqi: Fare: are you requiring pyjure.debug with a :refer?

16:14 wasamasa: pyjure??

16:14 lazybot: wasamasa: What are you, crazy? Of course not!

16:26 Fare: xeqi: as a :use

16:31 bcham: I'm using the monger client at http://clojuremongodb.info/ and if I don't have an instance running on my local machine, I can't uberjar my app.

16:32 For some reason the connection is being called but I don't have it in a def or anything

16:32 justin_smith: bcham: move your db connection into a function called in -main instead of doing it at the top level

16:32 bcham: clearly something is trying to connect while you are building, right? that means it's happening in a top level call somewhere.

16:33 bcham: justin_smith: that's what I figured it was and that's what I had done, I thought but I guess I'll double check. Just wanted to make sure there wasn't something else I wasn't thinking about.

16:33 Yeah I'm with you thank you.

16:37 Yup got it, there was just one little thing that I hadn't looked at. Thanks justin_smith.

16:37 FWIW I'd really like to thank this IRC channel, always super helpful and nice.

16:38 justin_smith: thanks, it's great to hear that

17:59 ed-g: What do people use for web-application user login?

18:03 justin_smith: ed-g stored bcrypt hash, and a signed token that the client provides with each request (so that one of the load-balanced servers can verify not only the token, but also the contents)

18:09 ed-g: justin_smith, that sounds good. did you follow a tutorial or docs to set it up, or just dive in and experiment with libraries such as Friend. I'd like to use them but I haven't found examples of working applications, it isn't clear to me which parts of the authentication I am supposed to write versus what the libraries provide.

18:10 justin_smith: ed-g: by the time I figured out enough so friend would make sense I already had my own solution

18:12 ed-g: yeah it's weird to me that no examples ever actually show a login page, or a complete web application. glad it's not just me.

18:14 is the login portion of your application open-source, would you mind if I used it as an example?

18:16 justin_smith: not the one I'm describing, no

19:27 peat: Hello everyone. Clojure noob here. I have a pretty common pattern, but I'm not finding a clean way to address it -- most likely because I don't know what the name is. I created a gist to try and explain what I'm after. Thanks for your advice! https://gist.github.com/peat/982ad29845bfb003845b

19:32 scriptor: peat: that's an essential idea behind monads, actually

19:33 I'm not sure what the idiomatic way to to it in clojure is

19:33 peat: scriptor: Right. :) I'm wary of using the word "monad" because strictly speaking it's not, and people get a little bent out of shape about such things. ;)

19:34 scriptor: I'm tempted to spend the evening hacking on the thread-first macro to get out a proof of concept, but ... I didn't want to re-invent the wheel if it's already been done.

19:34 ... granted, I might do it anyway just to learn me a Clojure the hard way.

19:35 scriptor: peat: yeah, I purposely avoided saying that's what a monad was, just that it's an important idea

19:35 crazydiamond: Hi. Are there any tools for Clojure, that take e.g. two pure functions, and extract common piece of code? Or refactor it to provide maximum entropy/minimum entropy/maximum of nested levels etc, whatever applicable?

19:36 peat: scriptor: :)

19:36 scriptor: peat: https://clojuredocs.org/clojure.core/some-%3E

19:37 peat: Yes!

19:37 scriptor: Thank you! I can run with that.

19:37 scriptor: peat: no prob! For future reference I just looked at the related functions of --> on clojuredocs

19:38 peat: ... and it looks like there is a cond-> ... literally re-inventing the wheel over here. Haha.

19:38 amalloy: cond-> is a pretty different thing from what you asked for

19:38 peat: ... although it's conditional at each step

19:38 amalloy: Yup, it allows for a custom test at each form, which is pretty nifty. :)

19:39 Alright, I'm a happy camper. Thanks scriptor.

21:03 arrdem: Silly question that shows how long it's been since I've touched Java... what's a good example of a class with a public static mutable field?

21:04 justin_smith: /win 8

21:06 arrdem: lols

21:10 amalloy: arrdem: System.out?

21:11 justin_smith: oh yeah, and the properties list exposed by System/getProperty

21:12 amalloy: i think that's not mutable without reflection cheats?

21:12 oh, no

21:12 setProperties indeed

21:12 justin_smith: right

21:14 arrdem: hum looks like System/out is not directly assignable

21:15 I should probably just add a test class.

21:17 justin_smith: and System/getProperty System/getProperty is still a getter / setter pair not an exposed mutable field...

21:17 arrdem: right.

21:17 I'm trying to test TEMJVM's mutable field setter

21:17 test coverage was pretty bad, I've dragged it up to about 79%, trying to get it to 90.

21:34 Seylerius: There any easy way to turn 5.597661 days into a clj-time interval?

21:35 arrdem: Seylerius: do you have that number as days or are you sourcing it as milli/microsecond

21:35 *ds

21:36 Seylerius: arrdem: I have a function that takes that number in days.

21:36 A math formula, rather.

21:38 Actually, thought of a way around it.

21:39 arrdem: That's probably for the best... I didn't want to reccomend anything with a loss of precision.

21:52 Seylerius: Okay, what's the clojurish way to take the first entry of an infinite, lazy seq that satisfies a function?

21:52 justin_smith: (comp first (partial filter pred))

21:53 ,((comp first (partial filter even?)) [1 3 5 8 7 12 3])

21:53 clojurebot: 8

21:53 Seylerius: justin_smith: That returns a transducer that eats colls?

21:53 justin_smith: it returns a function

21:53 Seylerius: Wait, yeah.

21:54 And that whole process is lazy?

21:54 justin_smith: not quite - when called it will evaluate items in the input until one of the items is returned by filter

21:55 but yeah, it is lazy enough not to consume a huge indefinite sequence

21:55 Seylerius: Lazy enough.

21:57 arrdem: You could make it lazier with memoize...

Logging service provided by n01se.net