#clojure log - Aug 20 2015

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

2:49 mdallastella: 'morning

3:40 Olajyd: Hi, TEttinger

3:43 TEttinger: hey Olajyd

3:44 Olajyd: Great to have you around

3:45 TEtinger say given a date string, I want to be able to add days to it, I’m kinda lost on how to go about it

3:47 TEtinger, some of the use cases: 365 will add one year, -7 will subtract one week. 0.5 will add half a day, and 0.04 will add a little less than one hour (57 minutes and 36 seconds).

3:48 Kneiva: Olajyd: https://github.com/clj-time/clj-time

3:49 Olajyd: aite Kneiva

3:54 Olajyd_: Kneiva, what should i bee lookiing for

3:56 Kneiva: Olajyd_: that's a clojure wrapper to yoda time library, that does pretty much what you want: manipulate dates and times

3:56 (t/plus (t/date-time 1986 10 14) (t/months 1) (t/weeks 3))

3:56 => #<DateTime 1986-12-05T00:00:00.000Z>

3:59 Olajyd: hmmm Kneiva, say the date sting is 2014-05-12 Do I have to split the string to be in the form of “2014 05 12”

4:01 TEttinger: (inc Kneiva)

4:02 Olajyd: Kneiva: or parse the date string

4:05 TEttinger: Olajyd: clj-time.format has what you need I think.

4:05 (formatter "yyyy-MM-dd")

4:06 should be the format you want, if it's month then day

4:06 gilliard: If that's May 12th then the built-in formatter will get it.

4:07 ,(clj-time.format/parse "2012-05-12")

4:07 clojurebot: #error {\n :cause "clj-time.format"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clj-time.format"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n [java...

4:08 Olajyd: I’m assuming that the format is going to be in "2012-05-12" format

4:08 gilliard: If the "05" is the month part (not the day-of-month) then that's iso8601 format so the default parser will work without a custom format.

4:16 TEttinger: oh nice

4:31 Olajyd: So what do you think?

4:31 sorry I got disconnected from the rom for a while

4:31 *room

4:32 TEttinger, any other suggestions

4:33 TEttinger: Olajyd: I think gilliard is right on here. 05 is may, right? and 12 is the 12th day?

4:33 Olajyd: Yes exactly

4:33 TEttinger: yeah then the code gilliard gave should work just fine: (clj-time.format/parse "2012-05-12")

4:34 with a dependency on clj-time in your project.clj

4:34 Olajyd: TEtitinger, ok

4:34 what else

4:34 gilliard: Works for me (tm) - I suppose clojurebot is missing that dependency

4:34 Olajyd: ok

4:34 and work with Kneiva, solutions right?

4:35 *solution

4:35 TEttinger: yeah, that should give you a date in the clj-time format, you should be able to use Kneiva's suggestions just fine

4:35 Olajyd: ok

4:35 TEttinger: Kneiva had required clj-time as t

4:35 Olajyd: Thanks

4:35 TEttinger: (inc Kneiva)

4:35 lazybot is down again :)

4:38 gilliard: Ooh - can we require stuff into clojurebot? Or is that Kneiva-only?

4:39 Olajyd: Kneiva, where art thou?

4:40 :)

4:46 Kneiva: gilliard: My example was just a copy paste from the library readme.

4:46 Does clojurebot support requiring stuff on the fly?

4:49 amalloy: Kneiva: try it and see

4:56 gilliard: ,(require '[clj-time.format :as f])

4:56 clojurebot: #error {\n :cause "Could not locate clj_time/format__init.class or clj_time/format.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate clj_time/format__init.class or clj_time/format.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure ...

4:56 Kneiva: could not get it to require anything

4:58 amalloy: it won't dynamically go and download jars off the internet for you. but neither will any clojure repl; you'd need to change your project.clj to get lein to pre-download that stuff before starting your program

4:59 anything that is actually on the classpath, clojurebot will require, eg (require '[clojure.string :as s])

4:59 gilliard: ,(t/in-hours (t/days 1)) ; good

4:59 clojurebot: #error {\n :cause "No such namespace: t"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: No such namespace: t, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "No such namespace: t"\n :at [clojure.lang.Util runtimeException "Util.java" 221]}]\n :trace...

5:02 Kneiva: amalloy: Using this would make it possible I guess: https://github.com/cemerick/pomegranate

6:53 Olajyd: HI

6:55 I want to add 0.4 days to a particular clojure date which is equivalnent to (57 minutes and 36 seconds). I tried (t/plus (tf/parse (tf/formatter "yyyy-MM-dd") date-string) (t/days d)), any suggestion as to why this is so

6:55 gilliard: (t/days) only takes integers

6:55 Olajyd: (t/plus (tf/parse (tf/formatter "yyyy-MM-dd") “2014-05-12”) (t/days 0.4))

6:56 gilliard: You need to do (t/hours (* 0.4 24)) or something like that.

6:56 Olajyd: Hi, gilliard, :)

6:56 hmmm

6:58 gilliard, so I wan to implement the function in such a way that all that will bw passed in to the function is just date strin and the number of days

6:58 forgive my typos I’m trying to get used to touch typing :)

6:59 gilliard: If you need non-integer number of days, I don't think clj-time will do that. I raised https://github.com/clj-time/clj-time/issues/192 but it was closed straight away :)

7:01 Olajyd: gilliard, you are `mjg123` that raised th issue right?

7:03 gilliard: yep

7:04 * gilliard goes afk

7:05 Olajyd: gilliard, so what do you advise I do in such a way that it handles both days in integers (7) and floats (0.5)?

7:14 TEttinger: Olajyd: you could probably get the timespan of 1 day in milliseconds, which is some very large number, multiply that by 0.4, and then convert back to a datetime

7:15 Olajyd: ok

7:15 TEttinger, thanks :)

7:16 TEttinger: I'm checking the API to see how to do that

7:16 Olajyd: ok, will really appreciate it

7:22 TEttinger: (clj-time.coerce/from-long (long (* 0.4 (clj-time.coerce/to-long (clj-time.core/days 1))))) ; not sure how well this works

7:23 but that would I think get a DateTime that is basically 0.4 of a day. I don't know what would be needed to convert that to a period again

7:24 getting late here, good luck Olajyd!

7:33 Olajyd: hahah thought as much, thanks TEttinger, catch ya tomorrow :)

7:40 ,(clj-time.coerce/from-long (long (* 0.4 (clj-time.coerce/to-long (clj-time.core/days 1)))))

7:40 clojurebot: #error {\n :cause "clj-time.coerce"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clj-time.coerce"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n [java...

8:25 jweiss: if I have a set of functions that all take a first arg foo, what's the best way to get a set of functions that close over foo (and take one less argument)? I know i could make a map of them, but then things get awkward-looking like ((:f m) bar)

8:25 i thought of just dynamically creating a new namespace

8:25 but i have never seen that done anywhere else.

8:26 (sorry what I meant earlier is "get a set of functions that close over a particular value of foo"

8:39 opqdonut: jweiss: how about using a dynamic var for foo and then having (with-foo [the-foo] ... (function 1 2 3) ...)

8:39 maybe separate (function foo 1 2 3) and (function* 1 2 3) variants or something

8:44 jweiss: opqdonut: yeah, i know i can do that, then the functions aren't functional anymore :)

8:47 opqdonut: then just return a map I guess?

8:56 jasonx2: clojure has dynamic variables? like common lisp?

8:56 isn't that rather unfunctional?

8:59 novak`: What to use for Redis? I found that there is Aleph but can't find any exapmles

9:13 chouser: jasonx2: most variables are lexical in Clojure. Dynamic ones are available, and yes that's not very functional in the modern sense of the word.

9:27 pepijndevos: Is rand-nth constant time for vectors?

9:30 gilliard: It's the same as element access time which is O(log32 N), which is often referred to as effectively constant time.

9:31 (same as nth)

10:50 futuro: Is there a general preference for private functions and defs in clojure?

10:51 so far I've used the non-private versions, but I've seen the private ones pop up here and there

10:52 stuartsierra: futuro: private defs are basically a form of documentation: "This is not a public API, don't call it from other namespaces"

10:53 futuro: So clojure doesn't stop you from using or importing private defs?

10:58 stuartsierra: futuro: The compiler will throw an error if you try to call a private function from another namespace, but you can always work around it with the var-hack: @#'the-namespace/the-var

10:59 futuro: neat. That's good to know if I ever need that.

10:59 Thank you for the clarification

11:01 stuartsierra: you're welcome

11:16 pflanze: Is there a function that takes two (or n) lists, and compares all items in them with a given comparison function, and returns true if the comparison function returned true for all elements and both lists are of the same length? (Stopping early in the false case.)

11:17 justin_smith: ,(map > [1 2 3 4] [0 3 1 2] [-1 -1 -1 -1])

11:17 clojurebot: (true false true true)

11:17 justin_smith: it could be I misunderstood your question

11:17 pflanze: ,(every true? (map > [1 2 3 4] [0 3 1 2] [-1 -1 -1 -1]))

11:17 clojurebot: #error {\n :cause "Unable to resolve symbol: every in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: every in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: every in this...

11:18 justin_smith: ,(every? true (map > [1 2 3 4] [0 3 1 2] [-1 -1 -1 -1]))

11:18 clojurebot: #error {\n :cause "java.lang.Boolean cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Boolean cannot be cast to clojure.lang.IFn"\n :at [clojure.core$every_QMARK_ invokeStatic "core.clj" 2553]}]\n :trace\n [[clojure.core$every_QMARK_ invokeStatic "core.clj" 2553]\n [clojure.core$every_QMARK_ invoke "core.clj" -1]\n [sandbox$eval72 invoke...

11:18 justin_smith: one more time...

11:18 ,(every? true? (map > [1 2 3 4] [0 3 1 2] [-1 -1 -1 -1]))

11:18 clojurebot: false

11:18 justin_smith: ,(every? true? (map > [1 2 3 4] [0 0 1 2] [-1 -1 -1 -1]))

11:18 clojurebot: true

11:19 jasonx2: is there a function that does this? (1 2 3) and "foo" to ((1 'f') (1 'o') (1 'o') (2 'f') (2 'o') (2 'o') (3 'f') (3 'o') (3 'o'))

11:19 pflanze: justin_smith, is this lazy? I guess no since those are vectors?

11:19 justin_smith: ,(map list [1 2 3] "foo")

11:19 clojurebot: ((1 \f) (2 \o) (3 \o))

11:19 justin_smith: pflanze: yes it is lazy, every? stops at the first false result

11:20 pflanze: Yes, but will map produce a 4-item list in any case?

11:20 justin_smith: pflanze: regardless of the input types, map and every? are lazy

11:20 so no, it is not eager

11:20 pflanze: ok

11:20 Thanks!

11:20 jasonx2: just_smith in case it is isn't obvious, thats not the same :)

11:20 scriptor: yep, the call to every? will stop consume the result of map if it hits a false

11:20 justin_smith: jasonx2: iow "yes, except 'f' is not a clojure thing"

11:21 jasonx2: ??

11:21 clojurebot: ? is suddenly

11:21 justin_smith: jasonx2: oh, wait :)

11:21 ,(for [x [1 2 3] y"foo"] (list x y))

11:21 clojurebot: ((1 \f) (1 \o) (1 \o) (2 \f) (2 \o) ...)

11:21 justin_smith: that's your answer (except it's \f not 'f' because 'f' is not clojure)

11:22 jasonx2: oh right. i actually know that

11:23 justin_smith: ,'f' - exists, but is not what you might expect

11:23 clojurebot: f'

11:23 justin_smith: it's the symbol f'

11:26 pflanze: ,(every? true? (map > [1 2 3 4] [0 0 1 2] [-1 -1 -1]))

11:26 clojurebot: true

11:26 pflanze: Hm, actually it doesn't qualify for my given requirement.

11:26 justin_smith: ,(symbol "'f'")

11:26 clojurebot: 'f'

11:26 pflanze: (Unequal list lengths.)

11:26 justin_smith: the lists are of equal length

11:26 hyPiRion: pflanze: what should it do if the lists are unequal?

11:27 justin_smith: oh no they are not

11:27 pflanze: hyPiRion, return false

11:27 Or give an exception which I could turn into a false.

11:28 jasonx2: ,(every? true? (map > [1 2 3] [0 1 2 3 4 5]))

11:28 clojurebot: true

11:28 pflanze: I guess we're reaching the point where I'm going to write a function from scratch.

11:28 justin_smith: ,(let [ls [[1 2 3 4] [0 0 1 2] [-1 -1 -1]]] (and (apply = (map count ls)) (every? true? (apply map > ls)))

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

11:28 justin_smith: ,(let [ls [[1 2 3 4] [0 0 1 2] [-1 -1 -1]]] (and (apply = (map count ls)) (every? true? (apply map > ls))))

11:28 clojurebot: false

11:29 justin_smith: much uglier, but it works

11:29 only use that if you won't get indefinite length input

11:29 otherwise you'll want something that doesn't use count

11:30 pflanze: Of course, I can't compare infinite lists definitely.

11:30 justin_smith: or count them

11:30 jasonx2: ,(length (range))

11:30 clojurebot: #error {\n :cause "Unable to resolve symbol: length in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: length in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: length in t...

11:30 jasonx2: ,(count (range))

11:30 pflanze: I was really expecting some (list-compare compare? l1 l2)

11:31 clojurebot: Execution Timed Out

11:31 justin_smith: pflanze: yeah, you can use compare, but that compares the lists, not the items

11:31 ,(compare [1 2 3] [0 0 0 0])

11:31 clojurebot: -1

11:31 justin_smith: ,(compare [1 2 3 4] [0 0 0])

11:31 clojurebot: 1

11:32 justin_smith: s/lists/sequential things

11:32 pflanze: ,(compare [1 2] [0 0])

11:32 clojurebot: 1

11:32 pflanze: ,(compare [1 2] [1 2])

11:32 clojurebot: 0

11:32 pflanze: Yes, now a variant that takes a predicate.

11:32 justin_smith: ,(doc compare)

11:32 clojurebot: "([x y]); Comparator. Returns a negative number, zero, or a positive number when x is logically 'less than', 'equal to', or 'greater than' y. Same as Java x.compareTo(y) except it also works for nil, and compares numbers and collections in a type-independent manner. x must implement Comparable"

11:33 jasonx2: would you say clojure is closest to scheme, common lisp or haskell?

11:34 justin_smith: jasonx2: probably I'd put them in that order (most similar to scheme, etc.)

11:41 jasonx2: ,(cycle '(1 2 3))

11:41 clojurebot: (1 2 3 1 2 ...)

11:41 jasonx2: function names, though, seem to match those in haskell often. i can just guess many, having dabbled in haskell before

11:41 justin_smith: ,(shuffle (take 300 (cycle [1 2 3])))

11:41 clojurebot: [2 3 2 2 3 ...]

11:42 scriptor: those function names tend to be common in functional programming in general

11:42 rather than a haskell-specific thing :)

11:42 justin_smith: scriptor: well, haskell was invented as a coming together of all the functional langs

11:42 jasonx2: map is common. I can't say take or cycle are

11:43 ML?

11:43 scriptor: possibly from ML

11:43 justin_smith: haskell came from clean, miranda, ml, some others whose names I am forgetting

11:44 hiredman: http://www.amazon.com/Clojure-Bookshelf/lm/R3LG3ZBZS4GCTH

11:44 justin_smith: there were a bunch, a lot of them were closed source, it fragmented the pl research community in the '80s, so they got a conference together and invented haskell

11:45 scriptor: ah, didn't know that

11:45 did ocaml come about after haskell was conceived?

11:45 justin_smith: hmm - now I wonder

11:46 scriptor: caml (without the o) is from '85

11:46 justin_smith: scriptor: https://en.wikipedia.org/wiki/Haskell_(programming_language)#History https://en.wikipedia.org/wiki/OCaml 1990 vs. 1996

11:48 vs. 1985 for the original caml, as you mention

11:49 pepijndevos: Halp. I refactored som Cljs code, and now it's way slower. At the top of Chome's profile is cljs$core$pr_writer_impl

11:49 I'm not even printing anything.

11:50 jasonx2: how does ocaml compare to haskell, other than the obvious things (strict vs lazy evaluation)

11:51 scriptor: pepijndevos: does the profile show what is callingit?

11:52 pepijndevos: scriptor how do I tell? Further down there is cljs$core$print_map

11:52 justin_smith: jasonx2: in general haskell attempts to get speed via "cleverness" in the compiler and advanced static analysis, while OCaml attempts to get runtime performance via a simple and relatively uncomplicated compiler. The fascinating thing is they are not much different in performance.

11:54 pepijndevos: hmmm cljs.core.PersistentVector.toString

11:55 justin_smith: pepijndevos: could all this toString and pr_writer_impl stuff be invoked as a side effect ofthe profiling? it would be ironic...

11:55 jasonx2: justin what about language srmantics

11:56 justin_smith: jasonx2: like you mention, it's mainly about lazy vs. strict, though haskell tends to be more academic and experimental (this is their intended niche after all)

11:56 pepijndevos: ahhhh, I mismatched some parameter which instead of throwing a type error got turned into a string somewhere.

11:56 Not yet sure where, but setting the correct parameter order brings back the speed.

11:57 justin_smith: I guess that would do it...

11:57 pepijndevos: It's way faster even.

12:25 zxc: hey, can someone help me with lazy seqs? or should I go to #clojure-beginners?

12:25 justin_smith: zxc: you can go ahead and ask your question

12:25 Olajyd: zxc, sorry i just joined, whats your question

12:25 Hi, justin_smith

12:26 zxc: I just need someone to explain them to me, I read chapter about them in brave clojure and I understand nothing

12:26 Olajyd: sorry for what? :)

12:26 justin_smith: zxc: that's kind of broad - do you have specific concrete questions maybe/

12:27 zxc: justin_smith: I get that they don't process every value until I need it, but I don't understand this 32 value thing

12:28 Olajyd: zxc: sorry I thought u asked a question on lazy seqs? I just went through the chat history and saw your question

12:28 zxc: (I'm coming from haskell world btw)

12:28 Olajyd: no, I've just joined

12:28 Olajyd: ok

12:28 justin_smith: zxc: I assume "32 value thing" is something that demonstrating chunking - that is, you can't assume that values not yet used are not produced

12:29 zxc: if you use lazily produced values in a "pure" way it's nothing to worry about

12:29 zxc: " In reality, Clojure "chunks" lazy sequences, realizing 32 members at a time"

12:29 that's the sentence I have problems with

12:29 justin_smith: zxc: but a lazy function is allowed to produce values before you need them

12:29 zxc: it's an implementation detail

12:29 some things chunk, some don't

12:29 zxc: so it produces 32 values and wait till I need 33th?

12:30 justin_smith: ,(take 2 (map println (into [] (range 100))))

12:30 clojurebot: (0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\nnil nil)

12:30 zxc: or just not to worry about that and use it as I would use a lazy structure

12:30 Olajyd: zxc : lazy-seq was introduced to make it possible to postpone any computation until data is needed

12:30 justin_smith: zxc: if you don't care about the side effects, it doesn't matter

12:31 zxc: but if you care about side effects, laziness is not the way to manage them

12:31 because chunking

12:31 zxc: it's my second day with clojure, I don't really now

12:31 justin_smith: see the map println example above

12:31 zxc: I've only implemented fizzbuzz

12:31 justin_smith: looked, thanks

12:32 and another question - I have this program in haskell and I want to rewrite it in clojure to see the difference

12:32 but how to measure performance?

12:32 jvm is so slow to start

12:33 hello world takes 1.2 sec, my haskell program did all computations in like 3 seconds, so it would be a big difference in time

12:33 noncom: first start the repl, them try (time (your-function))

12:33 don't take the jvm startup time into account..

12:34 zxc: noncom: so, in repl? thanks a lot!

12:34 noncom: I just thought I need to fire up jar every time

12:34 noncom: no way!

12:34 lisps are all about repl

12:34 get yourself an IDE and work inside it

12:34 don't work with the bare clojure jar

12:34 zxc: I'm working in spacemacs with cider

12:35 noncom: oh, that's fine

12:35 zxc: and repl in other window

12:35 noncom: also, bear in mind that thanks to jvm jit, your 10th run of a function can take 10 times less! (a little over-generalized and exaggerated example, but just to make the point)

12:36 zxc: and final question - I don't have to know java to use their libraries, right? it's an awful language

12:36 noncom: I'll write that down in my notebook!

12:36 noncom: well.. java.. it depends on how much and what library you're using.

12:36 ofcourse you do not have to program java in clojure

12:37 but some libraries may inforce this or that architecture and stuff

12:37 but in the end it all boils down to creating objects and calling methods on them...

12:37 often there are clojure wrappers for many java libraries where it is worth and people took time to make them

12:38 zxc: let's say I want to create a simple game (not a gamedev type of programmer, just for example)

12:38 noncom: okay, so

12:38 zxc: does clojure provide all the important stuff?

12:38 gui and others?

12:38 noncom: umm, clojure is a language, you'll have to use a game engine of sorts.. which is a library

12:38 for example, i am using JMonkeyEngine 3

12:38 zxc: "simple" - tic tac toe or something

12:39 noncom: ah, i see

12:39 take a look at seesaw

12:39 akabander: The seesaw samples include a Conway's Life example that includes a basic GUI

12:40 noncom: google "seesaw gui"

12:40 seesaw is a swing wrapper

12:40 zxc: and I can use it without months of reading poorly written documentation?

12:41 akabander: That's a pretty subjective question

12:41 We don't know how fast you read

12:42 zxc: I learn and read pretty fast, I just have bad memories with gui (trying to use library with no documentation and one crappy tutorial)

12:42 noncom: zxc: yes

12:42 zxc: noncom: darn, clojure rocks

12:42 noncom: no, just try seesaw

12:42 zxc: thank you all :)

12:42 hanate_monsta: hello, beautiful clojuristas, question : which is the equivalent to a sparse array in clojure?

12:42 noncom: if anything, ask here. many ppl had some experience with it

12:42 akabander: If you know anything about Swing, seesaw will be easy

12:42 You could use a map for a sparse array

12:42 zxc: akabander: you mean dancing?

12:43 noncom: and swing is not much different from any other modern gui system in its terms

12:43 swing is one of java gui systems

12:43 hanate_monsta: akabander: example of thee?

12:43 zxc: oh, I don't know java, it scared me to the bone

12:44 hanate_monsta: zxc: Is so easy to learn, nothing to be scare

12:44 noncom: don't be afraid. just know one thing: java for jvm is like c for metal

12:44 in clojure you won't have to work with much java anyway (in most cases)

12:44 hanate_monsta: zxc: the thing is is verbose and mudane as oppose to clojure

12:44 akabander: I would use a map and just use the index values for keys.

12:45 hanate_monsta: akabander: Thank you

12:45 zxc: hanate_monsta: I know it's easy, I just want to cry seeing all these classes and privates and inheritances

12:45 akabander: (def sparse-array {})

12:45 (merge sparse-array { 0 12, 1 13 }

12:45 )

12:46 Then you can just do (sparse-array idx) to get the value at idx.

12:46 noncom: zxc: then you're in the same boat as rich hickey - the creator of clojure. he does not like oop either :)

12:46 zxc: noncom: I also look like him, which is funny

12:46 akabander: OOP is a straightjacket -- useful when you have to work with insane people.

12:47 hanate_monsta: noncom: is not that he doesn't like, he is just tired of using it

12:47 noncom: wow :)

12:47 zxc: I think we all have functional souls

12:47 noncom: yeah )

12:48 zxc: and final final question - are there any better error messages? or do I have to get used to them?

12:48 I get 20 lines or so when I forget to close parens

12:48 hanate_monsta: zxc: But some people like to objectify bodies (specially womans bodies) (o-^)

12:49 fantazo: btw. what is the current hotness in clojure webdev?

12:49 still noir and compojure?

12:49 hanate_monsta: I actually like to use immutant

12:49 with compojure and ring

12:49 hlship: zxc: io.aviso/pretty exists to clean up the stack traces; part of what it does is hide frames that aren't going to be helpful, such as anything in the clojure.lang package.

12:50 zxc: hanate_monsta: but treating women like objects isn't nice

12:50 hanate_monsta: zxc: I know, never done that.

12:50 just saying

12:51 zxc: hlship: and just add this as a package?

12:52 hanate_monsta: my c++ friend does this all the time, which is also funny

12:52 hanate_monsta: but enough non-clojure stuff for now!

12:53 hlship: zxc: see the docs; there's an explicit function to call that goes all alter-var-root! on some key clojure.main and clojure.repl functions to hook in better exception reporting.

12:53 https://portal.aviso.io/#/document/open-source/pretty/Current

12:53 zxc: hlship: thank you, have a great day :)

13:22 Acug: Hello

13:24 justin_smith: zxc: yeah, the error messages really don't get a lot better (though aviso and such can help) - clojure doesn't abstract over the jvm's call stack, which is great for performance but bad for things making any sense when an error happens

13:32 zxc: justin_smith: is it possible to actually read something from this madness after few months or so?

13:33 justin_smith: zxc: sure - it's a call stack, which means that if you go far enough up you'll find either a) your code which invoked this crazy deep stack of calls or b) a mechanism like core.async or some other threaded or async pipeline that runs code for you

13:34 zxc: justin_smith: thank you!

13:34 justin_smith: zxc: complecting factors here is that clojure has little to no defensive code, so call stacks go pretty deep before errors are found usually

13:34 zxc: justin_smith: defensive code?

13:35 justin_smith: zxc: input validation

13:35 pre-conditions

13:35 type checks

13:35 etc.

13:36 zxc: justin_smith: oh, okay. but being dynamic isn't a huge pain, right?

13:38 fantazo: we all just want to have very strict type checks, right? no?

13:39 akabander: <-- does not want unrequested type checks

13:39 zxc: in haskell everything was pure and strict and strongly typed, so I don't know how it is working with dynamic lang

13:41 akabander: Being passed a "wrong" type is typically the result of a logic error... If it's easy to reason about your logic, type errors become harder to commit.

13:42 But I'm naive, and use maps a lot. If something doesn't have the key I need, I just stop processing it.

13:43 justin_smith: akabander: zxc: yeah, regardless of our value judgments etc. I think the factual statement "there is little to no defensive coding in clojure" is something we can agree on (except for explicit exceptions like core.typed or prismatic/schema of course)

13:44 zxc: original point being that lack of defensive coding means an error gets pretty far down the call stack into internals before being reported. A natural correlary to this of course is that if you code defensively, you can cause the resulting call stack to be shorter and hey you even have the option of providing a sensible message.

13:45 akabander: I feel like I trip over strict type enforcement more often than I screw up due to dynamic persmissiveness. This may be a problem that will go away as I get better with Clojure...

13:45 zxc: justin_smith: okay, thanks for explaining

13:46 rhg135: Too bad preconditions don't let you specify the exception

13:46 akabander: Yeah the explanation is enlightening

13:47 justin_smith: rhg135: asserts do though (assert (OK) "well this time it was not OK")

13:47 akabander: It's not an exception, it's a ValueError, right?

13:47 justin_smith: assertionerror

13:47 akabander: <-- missed it by " much

13:47 rhg135: Yup

13:48 justin_smith: rhg135: something I am fond of nowadays (assert (OK input) (str "input was not OK:" (pr-str input)))

13:48 rhg135: Pres are nice in theory

13:48 justin_smith: the pr-str is useful for disambiguating some types of input data in a way that str alone won't

13:49 rhg135: I see

13:49 pepijndevos: Erm, my Clojurescript code doesn't work with advanced optimisations turned on. Do I need to tell it to not remove certain parts?

13:50 justin_smith: ,(print {:a 0 "b" 1 'c 2 'd "3 :a 0"})

13:50 clojurebot: {:a 0, b 1, c 2, d 3 :a 0}

13:50 rhg135: ~Externs

13:50 clojurebot: Pardon?

13:50 rhg135: Meh

13:50 justin_smith: ^ that print is extremely misleading

13:51 ,(print {:a 0 "b" 1 'c 2 'd "3, :a 0, :even worse"})

13:51 clojurebot: {:a 0, b 1, c 2, d 3, :a 0, :even worse}

13:51 akabander: justin_smith: Add a comma in that quoted string and you'll have a winner

13:51 justin_smith: right

13:51 ,(prn {:a 0 "b" 1 'c 2 'd "3, :a 0, :even worse"})

13:51 clojurebot: {:a 0, "b" 1, c 2, d "3, :a 0, :even worse"}\n

13:51 justin_smith: pr-str does the same magic as pr / prn

13:57 rhg135: That's great for confusing people

13:59 justin_smith: rhg135: yeah, that's why I use pr-str whenever I print any data

15:14 sdegutis: How long has {:arglists ...} been accepted before any function definitions in `defn`?

15:14 I've never seen this until now. What's the purpose of it? Just for documentation only?

15:14 justin_smith: sdegutis: to get away with filthy lies

15:15 sdegutis: Yes understood, but I meant technically.

15:16 Anyway, I upgraded from Ring 1.2.1 to Ring 1.4.0 and everything's broken.

15:16 justin_smith: it's for things like macros - to give some of them doc strings that make sense

15:16 sdegutis: wrap-reload seems to completely not work at all anymore, my own wrap-error is ignored in favor of Jetty showing its very own exception handler somehow, etc

15:17 justin_smith: sdegutis: the actual number of args a macro gets when invoked internally is greater than the documented arg list, and some macros are "bootstrapped" from normal function definition

15:17 sdegutis: justin_smith: this is in a defn as mentioned, not defmacro

15:18 justin_smith: sdegutis: I'm not telling you why ring is lying, I am describing why it has to be possible for clojure to make sense

15:18 sdegutis: ok

15:18 justin_smith: iirc Bronsa and arrdem had some choice words on the habit of arglist hacking

15:19 Bronsa: hate whoever does that with a passion.

15:19 sdegutis: :)

15:19 TIL Bronsa hates weavejester with a passion https://github.com/ring-clojure/ring/commit/3c55e006f816d0e971bf671eede9729137a46329

15:20 but only started hating him on May 18 last year so that's not as bad

15:21 Whoa:

15:21 ,(:foo {} :missing)

15:21 clojurebot: :missing

15:21 sdegutis: did not know

15:21 ,({} :foo :missing)

15:21 clojurebot: :missing

15:21 sdegutis: haha

15:21 stupid clojure always being way more pragmatic than is necessary

15:27 sdegutis_: back

15:30 {blake}: arglist hacking?

15:30 sdegutis_: Is there a way within an uberjar to find all namespaces matching a given prefix before any of them are loaded?

15:31 And then load them?

15:39 {blake}: I can't even. Though we do some dynamic namespace loading, it's all external to the JAR being run.

15:40 sdegutis_: oh?

15:40 how's that?

15:46 AHA just figured out the reloading issue

15:48 See, when you have namespace A with (def a [B/foo]) and namespace B with (def b [C/bar]) then it doesn't matter if you (require 'C :reload), because A/a will still be [[C/bar]] with the old version of C/bar, not the new reloaded one.

15:48 So it turns out my bug is a Clojure namespace issue, right?

15:53 Clojure is not dynamic and should stop pretending to.

15:59 hiredman: when you don't know where you are, what is around the bend is always a surprise

16:00 sdegutis_: hi hiredman

16:03 i didnt know u were buddhist

16:08 {blake}: sdegutis_: So...reload A & B, too, right?

16:10 It seems like you're asking for EXTREME mutability. In which case, I recommend Smalltalk.

16:12 sdegutis_: {blake}: I found this bug using Ring's wrap-reload middleware which is pretty popular so it's not some obscure wishlist.

16:12 Clojure's (require foo :reload) is inherently unreliable as of Clojure 1.7

16:12 It will reload the namespace, but if anyone already held some of its vars, what they now hold is up for grabs.

16:13 If only Clojure's issue tracker was hosted on Github, I could report this to them and they might be able to fix it. Oh well.

16:14 bendlas: sdegutis_: ring's bug tracker is on github, they will pass it on, if it's actually a language bug

16:15 srruby: I'm puzzled by *1 (yes that is the digit 1). It evaluates to nil in the repl. Anyone know why?

16:15 sdegutis_: bendlas: I've put it there. I doubt they'll pass it on but hope you're right.

16:15 srruby: it's a fake var that always evaluates to the result of the last entered expression

16:15 srruby: thks

16:15 Bronsa: ,#'*1

16:15 clojurebot: #'clojure.core/*1

16:16 Bronsa: srruby: *1 is a clojure.core var that holds the last expression evalauted at the repl

16:16 there's also *2 and *3

16:16 sdegutis_: srruby: *2 is second-to-last etc

16:16 {blake}: I'm not asking for extreme mutability. Just wishing (require ... :reload) didn't have so many caveats/bugs as to make it unusable.

16:16 Bronsa: and *e holding the last exception

16:16 hiredman: http://clojure.org/repl_and_main#toc3

16:16 sdegutis_: Oh wow I didn't realize *1 was in clojure.core

16:16 sick

16:17 bendlas: sdegutis_: can you post a test case? vars are supposed to be reload-stable.

16:17 sdegutis_: I can try to make one.

16:18 bendlas: sdegutis_: please do, if your observation is correct, that would be a serious bug

16:19 sdegutis_: will do

16:19 {blake}: Is (require ... :reload) how "lein ring server" reloads detected changes?

16:19 bendlas: sdegutis_: I suspect that the stale thing you end up holding onto isn't actually the var anymore, but an old value that it used to hold

16:20 i.e. the result of dereferencing it

16:20 e.g. when you start a ring server you usually pass the #'handler var, to make it reloadable

16:21 sdegutis_: bendlas: ah probably yes

16:21 In my real life usecase, it was a nested set of defroutes

16:21 Which creates a var to a function, which I then nest by resolving the var in the typical way (foo)

16:23 bendlas: sdegutis_: look out for cases of (let [foo the-var] (fn [_] (foo))), here the fn calls the already dereferenced value

16:24 sdegutis_: Right.

16:33 So in this case, it's not really a bug.

16:33 I just need to always write #'foo instead of foo if I ever want dynamic code reloading to work.

16:33 Right?

16:36 Makes sense.

16:38 bendlas: sdegutis_: only for higher-order functions, i.e. when you get a function value

16:38 for normal var usage like (foo), the var is dereferenced every time, implicitly

16:38 sdegutis_: Why not also for data like vectors?

16:38 Um..

16:38 So only in defroutes then?

16:39 Compojure is so stupid, I should just make the jump to Silk or Bidi now and get it over with.

16:39 bendlas: not even there for most cases

16:39 hm, cgrand's moustache is also pretty cool

16:40 sdegutis_: I don't remember much about it except that when I compared it with the others a year ago it seemed like a terrible option.

16:42 bendlas: sdegutis_: I like it, because it facilitates writing small, focussed handler fns + it has a syntax slot for middleware

16:43 sdegutis_: I prefer lists of routes like [request-type route-string handler-fn] and to just use string comparison to find a match.

16:44 This option much more sense to me.

16:44 spieden-: +1 bidi last i looked

16:51 sdegutis_: lazybot: wake up

16:51 no, dont do this.. wake up.. you're just sleeping lazybot

16:51 you're just sleeping. its gonna be alright. everythings gonna be alright, just open your eyes, wake up

16:52 please, please just wake up lazybot? please?

16:54 DomKM: sdegutis_: Both Silk and Bidi are great options. I'm happy to help with any questions you might have about Silk.

16:54 sdegutis_: DomKM: which one did you make? i forget

16:54 oh sorry

16:54 DomKM: Silk

16:54 sdegutis_: silk. right.

16:57 DomKM: I gave my feedback a while ago https://github.com/DomKM/silk/issues/14

16:57 DomKM: In the end I ended up with Bidi because I couldn't really figure out how to use Silk from the readme

16:57 But basically they seemed like nearly identical projects.

17:01 DomKM: sdegutis_: I agree with your complaint about the readme. The issue is still open and unresolved. I just haven't had time to do it and haven't prioritized it because I am rewriting most of Silk. If you're interested, you can follow along in the `fsm` branch.

17:01 sdegutis_: DomKM: not really but thanks for the offer

17:01 im not opposed, just no compelling reason anymore since bidi works fine

17:03 DomKM: sdegutis_: In terms of differentiation, Silk used to be the only routing library that was compatible with both Clojure and ClojureScript. Now that Bidi supports ClojureScript, you're right that they are very similar. I think the next version of Silk will provide a very compelling reason to choose it but for now I think that your assessment is correct.

17:03 sdegutis_: DomKM: dont just tease, what will be compelling about it?

17:04 DomKM: heh

17:06 spieden: fsm.. it's a finite state machine!?

17:07 DomKM: sdegutis_: Yeah. I ported Automat (https://github.com/ztellman/automat) to ClojureScript. I'm using it, instead of regexes, for matching. It is far more composable and way faster.

17:07 spieden: sweet

17:08 DomKM: sdegutis_: Got a meeting now. Be back soon.

17:08 sdegutis_: oh man

17:08 * spieden reaches for instaparse more often than regex these days.

17:08 sdegutis_: all these puns

17:08 its 2 much 4 me

17:08 Automat

17:08 clojurebot: Cool story bro.

17:08 spieden: except for some little ones sprinked into productions for the character classes

17:08 sdegutis_: he should have named it "Pun A".

17:08 the next guy to name a library something with a pun should name it "Pun B"

17:08 thatll save us all some time

17:09 or Untitled

17:09 and Untitled 1

17:09 etc

17:11 justin_smith: sdegutis_: I think we should outsource this request, I know a good contracting company in Punjab

17:11 sdegutis_: oh man

17:11 my side

17:11 it hurts

17:11 from the cancer

17:11 not from laughing dont get me wrong

17:11 jk i dont have cancer yet

17:13 justin_smith: RIP in peace sed utils

17:15 t0by: IANAD but you may have cancer of the sense of humor.

17:15 It's a serious condition.

17:16 bendlas: cool puns, you've got there, people. would be bad if something came to parse with them.

17:28 sdegutis_: justin_smith: finally someone says my name right

17:28 the g is for gnu

17:28 and the gnu is for ngnu which is short for "not gnu because gnu sucks" - its a backronym

17:28 srlsy tho stallman should be fired

17:31 justin_smith: sdegutis_: Mallory Ortberg suggests that the best way to deal with trolls is to address them as Steven.

17:31 sdegutis_: she reports that calling them Stephen also works.

17:31 sdegutis_: nobody knows who this lady you made up is go home troll 2/10

17:32 am i doing a good Bronsa impersonation?

17:33 justin_smith: sdegutis_: https://twitter.com/mallelis/status/634077312854720513

17:34 sdegutis_: wow she knows her stuff

17:34 whoa

17:34 You are blocked from following @mallelis and viewing @mallelis's Tweets. Learn more

17:35 so im guessing this mallory lady doesnt support peoples rights to sexually identify as attack helicopters?

17:35 cant see any other reason id be "blocked"

17:53 lazybot: wake up this isnt funny

17:53 lazybot: dont, just dont, stop pretending, you're just sleeping i know it I KNOW IT

18:05 Or1Equals1--: How is everyone doing today?

18:10 spieden: good you?

18:13 rhg135: lazybot is dead mate, just let him go

18:20 sdegutis_: NOOOOOOOOOOOOOO.com

18:20 spieden: it can't be. must be live lock

18:21 sdegutis_: ugh https://github.com/weavejester/clj-aws-s3/issues/83

18:21 ugh ugh ugh

18:30 gfrederi`: sdegutis_: have you done `lein clean`?

18:30 sdegutis_: yes

18:31 gfrederi`: I would add more information to the ticket if you want to get help with it

18:32 sdegutis_: I added lots more.

18:32 Just now.

18:43 rhg135: huh the title is quite long

18:47 sdegutis_: yeah its got all those more information

18:48 Shortened it.

18:55 whoa

18:55 what the heck, you cant even do (import com.amazonaws.ClientConfiguration) now?

18:55 this just started happening.

18:55 todya.

18:56 {blake}: Is it possible to force a lazy-seq to realize item by item (rather than in chunks of 32)?

18:56 sdegutis_: why?

18:56 clojurebot: why not?

18:56 sdegutis_: ,(import com.amazonaws.ClientConfiguration)

18:56 clojurebot: #error {\n :cause "com.amazonaws.ClientConfiguration"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "com.amazonaws.ClientConfiguration"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged ...

18:57 justin_smith: {blake}: if you google for "unchunk" you'll find the magic. Then you should ask yourself why you are relying on lazy results for side effects and probably stop doing that.

18:57 {blake}: Reazlizing the chunk creates an error--I'm reading a database--and I can't figure out which database record is actually causing the problem.

18:57 justin_smith: yeah, there are various versions of unchunk out there, all the ones I have tried work

18:57 maybe someone has one in a util lib

18:58 {blake}: justin_smith: It's Monger. I'm not...doing any of that stuff you say. =P

19:00 justin_smith: {blake}: sorry, I was being a bit glib. Unchunk will prevent the chunking related problems. So would passing (take N input) to monger instead of your input

19:00 unless this problem is internal to monger -in which case, fork mongo?

19:00 *monger that is

19:01 {blake}: justin_smith: It's internal to mongo, comes from the Java driver, and I'm not sure if you mean "fork" euphemistically or literally.

19:01 justin_smith: well, change its internals, right?

19:01 because you can't make its input not chunk from the outside...

19:02 {blake}: justin_smith: Grrr. Yeah.

19:08 Am I misunderstanding something? If I'm realizing a sequence of records and one record in a chunk causes an exception, and this isn't in my code, I really can't handle that exception at all, right? I mean, not in the sense of skipping that problematic record and moving on.

19:09 justin_smith: not really, I don't think so

19:10 {blake}: So that's a legitimate issue with monger. And something to be avoided if you're writing your own library.

19:10 justin_smith: I guess so - is this like a corrupt record or something?

19:13 {blake}: justin_smith: I =think= so. I don't know what else it could be. And I'm not the only one to run into it. But I can't locate it. I've heard one suggestion it was just missing data, but that shouldn't be an issue.

19:21 WickedShell: I'm slowly leaking memory that leads to an eventual crash, and every GC the metaspace grows in size (JDK 1.8.0_20) I'm having trouble tracking down what is causing the leak. Does anyone have a good tutorial for finding these/looking through a heap dump? I can't figure out how to trace the char[] byte[]'s etc to where they are created

19:22 Bronsa: WickedShell: what clojure version are you using out of curiosity?

19:22 WickedShell: 1.7

19:22 {blake}: OK, I think I just need to use find instead of find-map. Which I guess is a "duh".

19:22 WickedShell: No, wait 1.6.... Not sure why actually

19:23 Bronsa: WickedShell: ok, just asking because there are suspicions of a memory leak introduced with one of the new 1.8 alphas

19:32 WickedShell: I think I could trace it through the current heap dumps I'm getting if I could figure out how to trace allocations back to my code/see what causes objects to be allocated, but I can't figure out how to do that

19:37 amalloy: i don't think heap dumps have that information unless you have a profiler attached and enable allocation profiling

19:54 sdegutis_: ,(import '[com.amazonaws ClientConfiguration])

19:54 what am i doing wrong

19:54 clojurebot: #error {\n :cause "com.amazonaws.ClientConfiguration"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "com.amazonaws.ClientConfiguration"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged ...

19:57 justin_smith: sdegutis_: well for starters that jar isn't on the classpath for clojurebot

19:57 * sdegutis_ tries `rm -rf ~/.m2`

19:58 justin_smith: sdegutis_: mv ~/.m2 ~/.old-m2 effectively does the same thing, but it easier to undo if it didn't help

19:58 unless your network is super fast, or you like watching jars download

19:58 sdegutis_: 75mbps or something

19:58 so meh

19:59 still downloading....

19:59 * sdegutis_ wonders what this 'clojure-complete' is

19:59 justin_smith: it's the magic behind tab-completion in the repl

19:59 usually some plugin for nrepl pulls it in

19:59 sdegutis_: oh

19:59 reply

19:59 thanks trptcolin

20:00 wherever u be

20:00 yep i can officially no longer use clj-aws-s3

20:00 :'(

20:00 something is major broken

20:00 cant figure out where or what

20:01 justin_smith: any snapshots?

20:01 any major plugin version changes?

20:01 or just plain dep changes? because without those things shouldn't be different

20:03 sdegutis_: shoooooot

20:04 it was the datomic upgrade.

20:04 just confirmed.

20:04 using the latest datomic peer client clojure lib breaks amazon's s3 jar completely

20:05 i had no suspicion datomic was using s3, should have known

20:05 justin_smith: oh, incompatible versions?

20:08 sdegutis_: no clue

20:08 ill try excluding their version or something

20:37 phew fixed. just had to downgrade to weavejester's older version of clj-aws-s3

Logging service provided by n01se.net