#clojure log - Feb 25 2016

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

0:03 tolstoy: I imagine the botnet folks have something special.

1:44 adamz: Hi. Is there anyway to improve the performance of instanciating Java classes from clojure? Im calling `(java.util.Data. etime)` > 30k/s. running VisualVM against the clojure VM process shows that `java.lang.Class.forName()` is the most expensive method. To me, that sounds like Clojure is looking up the class on every invocation.

1:45 sorry, `(java.util.Date etime)`

1:46 jeaye: instantiate

1:52 hiredman: adamz: there are things you could look at to speed that up, but it would be way better to just not allocate all those new data objects, are you sure you can't get by with a long?

2:14 adamz: hiredman: unfortunatly, im passing them onto a libaray (the DataStax Cassandra driver) which /expects/ Date objects — i’ve looked at ways to avoid passing Date and insted just long, but it’s not possible without modifying the driver code :(

2:37 Vishal_: any1 active?

2:40 any1 familiar with atoms and their usage?

2:41 mange: Vishal_: anything in particular?

2:50 paul_muadib666: can someone recommend a clojure web app tutorial that covers datomic and compojure. I found one but its out of date and it uses this compojure-api library that I'm having issues with..

3:10 Vishal_: Link: https://gist.github.com/longdongjohn/5bdbada220b2e4a2bb06 ; I keep getting a Null pointer Exception on the atom variable temp3, which i have initialised... Any suggestions?

3:14 hiredman: Vishal_: this code is poorly formatted, and is full of mistakes

3:14 def always creates a global, don't use it inside a function

3:15 every time you wrap something in () parens that means a function call

3:15 TEttinger: Vishal_: (prn temp3) returns nil

3:17 and yeah, hiredman's right about def especially, it looks like you're using (def m2_flag 0) where you should use let

3:20 for someone whose nick on github is longdongjohn he doesn't seem to take criticism well...

3:25 somename: nope..... i went for lunch... and the channel pinged out

3:25 thanks for the input anyways

3:27 Vishal_: Thanks for the input btw

3:28 TEttinger: I was wondering what happened! there's a few quick things to try

3:29 def should be changed to let, like this

3:29 Vishal_: i can't use let because I'm trying use that value in another function

3:29 TEttinger: ah, that's bad. that sounds like m1_flag and m2_flag should be atoms if they're changing

3:29 Kneiva: Is there better way to transform [[:a [1 2]] [:b [3 4]] [:c [5 6]]] into {:keys [:a :b :c], :values (1 2 3 4 5 6)} than https://www.refheap.com/115180 ?

3:29 TEttinger: currently they're var, which is kinda mutable

3:30 (gt) on its own seems like it may be a bug

3:31 Vishal_: that's what i tried ...but i get a null pointer exception at the location of temp3 in the code

3:32 https://gist.github.com/longdongjohn/2b274f1b6d786ce07373

3:32 thats the complete fiel

3:33 TEttinger: ,(let [coll [[:a [1 2]] [:b [3 4]] [:c [5 6]]] ks (map first coll) vs (mapcat second coll)] {:keys ks :values vs})

3:33 clojurebot: {:keys (:a :b :c), :values (1 2 3 4 5 ...)}

3:33 TEttinger: ,(let [coll [[:a [1 2]] [:b [3 4]] [:c [5 6]]] ks (mapv first coll) vs (mapcat second coll)] {:keys ks :values vs}) ; to be exact

3:33 clojurebot: {:keys [:a :b :c], :values (1 2 3 4 5 ...)}

3:35 Kneiva: Ah, right. That's more readable, I think. Thanks.

3:35 TEttinger: I am sure someone more experienced than I could clean it up even more!

3:36 cpu_threshold is undefined, thus nil, Vishal_

3:37 I think the error may be in an odd place and getting bad info

3:37 Vishal_: its part of the includes "globals.clj"

3:37 TEttinger: ah I was wondering what that was

3:39 Vishal_: ill try changing the m1 and m2 flags as atoms and run it... will let you know of the changes

3:40 TEttinger: I wonder if (prn temp3) is the issue, should that be (prn @temp3)

3:41 ,(def temp3 (atom 0))

3:41 clojurebot: #'sandbox/temp3

3:41 TEttinger: ,(prn temp3)

3:41 clojurebot: #object[clojure.lang.Atom 0xcaf670e {:status :ready, :val 0}]\n

3:42 TEttinger: Vishal_: I think where you have (prn temp3) should actually be (fn [& children] (prn @temp3))

3:43 since in all other cases you have a fn and onlythat case evaluates to nil

3:43 Vishal_: will try it now

3:51 TEttinger: https://gist.github.com/longdongjohn/2b274f1b6d786ce07373 this is the updated code.. Im getting an exception long cannot be cast to IFn on line 42

3:54 somename: asd

3:55 TEttinger: let's see...

3:57 ,(doc reset!) ; let me refresh my memory

3:57 clojurebot: "([atom newval]); Sets the value of atom to newval without regard for the current value. Returns newval."

3:58 Vishal_: ok will check it out

4:00 TEttinger: Vishal_: the long to IFn thing usually means that a number is at the start of a parenthesized call, like (1) will throw that

4:00 ,(1)

4:00 clojurebot: #error {\n :cause "java.lang.Long cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval47 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval47 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval47 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]...

4:01 TEttinger: if it's the other way around, IFn cannot be cast to long, that's usually because you have a fn by name in the middle of a math thing like (+ 1 inc)

4:01 ,(+ 1 inc)

4:01 clojurebot: #error {\n :cause "clojure.core$inc cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.core$inc cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers add "Numbers.java" 128]}]\n :trace\n [[clojure.lang.Numbers add "Numbers.java" 128]\n [clojure.lang.Numbers add "Numbers.java" 3640]\n [sandbox$eval71 invokeStatic "NO_SOURCE_FILE" 0]...

4:01 TEttinger: hm different error, same sort of thing

4:03 ohhhhh

4:03 ,(def temp3 (atom 0))

4:03 clojurebot: #'sandbox/temp3

4:03 TEttinger: ,(reset! temp3 20)

4:03 clojurebot: 20

4:03 TEttinger: those reset calls are returning Long numbers

4:03 you may need to pass a fn to where

4:05 I don't know what "where" does or from which lib it's from

4:06 Vishal_: its part of riemann

4:06 and ill try passing a function to where

4:06 getting into a meeting ...will be afk for 15 mins

4:08 solatis: ok, i'm looking for someone with an opinion on data/type validation in clojure and when to do it

4:08 i am used to languages with strong types (e.g. Haskell and C++) that validate as early and as often as possble

4:08 however, I don't think that's an optimal approach for Clojure / LISP

4:09 i am thinking that the best fit for Clojure would be to validate as late as possible, but let the error "bubble back up", to provide accurate feedback on what/where it went wrong

4:09 is that a reasonable approach?

4:09 * n0lan waves hello

4:10 solatis: case in point: using some REST api, do i validate the data before I send it, or do I just let remote server generate an error in case the function was called with incorrect data

4:11 TEttinger: n0lan: are you the typed clojure ninja-in-chief :)

4:11 MJB47: solatis: i like to do both

4:11 client side validation is much faster and gives the user a better experience

4:11 but cant be trusted

4:12 n0lan: no I was bored looking for "popular" IRC channels on google, lol

4:14 solatis: MJB47: right, but in this case it's for internal code

4:14 and speed is not really a concern

4:15 and i don't like to do things twice, that means that when there's a change, i need to change my validation code twice :)

4:15 MJB47: maybe not with reader conditionals

4:17 solatis: let me look that up

4:17 that looks scary

4:41 adamz: Hi. Is there anyway to improve the performance of instanciating Java classes from clojure? Im calling `(java.util.Date. etime)` > 30k/s. running VisualVM against the clojure VM process shows that `java.lang.Class.forName()` is the most expensive method. To me, that sounds like Clojure is looking up the class on every invocation.

4:46 amalloy: adamz: because the clojure compiler doesn't know what type you expect etime to be, and Date has multiple constructors

4:46 try (java.util.Date. ^long etime) or whatever type is appropriate

4:46 adamz: cool. i’ll give that a shot. thanks!

5:00 yup. that certainly made a difference! thanks amalloy :)

5:03 magopian_: hello there :) Can someone tell me what is ^{} ?

5:03 eg: ^{:key timestamp}

5:03 it looks like a map, but what is the "^" for?

5:05 qsys: it's meta-data

5:07 http://xahlee.info/clojure/clojure_metadata.html

6:08 edmondo1984: Hello, anyone could help a Clojure newbie to tackle one of the exercise of Clojure for the brave and the true? Quite a basic one

6:13 paul_muadib666: edmondo1984: i maybe can, whatsup?

6:19 magopian_: thanks qsys :) (and sorry for the lag ;)

6:44 edmondo1984: so I need to write a function to update a nested hash

6:44 something that you can write like this

6:44 (update-in :key1 :key2 value {} )

6:44 and would result in { :key1 { :key2 value } }

6:45 TEttinger: typically you'd have keys in a vector

6:45 paul_muadib666: so reimplementing update-in?

6:45 TEttinger: ,(update-in {} [:key1 :key2] :value)

6:45 clojurebot: {:key1 {:key2 nil}}

6:45 TEttinger: ,(update-in {} [:key1 :key2] (constantly :value))

6:45 clojurebot: {:key1 {:key2 :value}}

6:46 TEttinger: edmondo1984: is the task to reimplement the built-in update-in fn?

6:49 ,(defn build-nested [v & ks] (update-in {} ks (constantly v)))

6:49 clojurebot: #'sandbox/build-nested

6:49 TEttinger: ,(build-nested 1 :a :b :c)

6:49 clojurebot: {:a {:b {:c 1}}}

6:53 edmondo1984: how do you make the clojure bot evaluate?

6:53 TEttinger: comma prefix

6:53 edmondo1984: , (update-in {} [:key1 :key2] "hello")

6:53 clojurebot: #error {\n :cause "java.lang.String cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to clojure.lang.IFn"\n :at [clojure.core$apply invokeStatic "core.clj" 641]}]\n :trace\n [[clojure.core$apply invokeStatic "core.clj" 641]\n [clojure.core$update_in invokeStatic "core.clj" 5950]\n [clojure.core$update_in doInvoke "c...

6:54 edmondo1984: , (update-in {} [:key1 :key2] (constantly "hello"))

6:54 clojurebot: {:key1 {:key2 "hello"}}

6:54 TEttinger: ,(defn build-nested [& args] (update-in {} (butlast args) (constantly (last args))))

6:54 clojurebot: #'sandbox/build-nested

6:54 TEttinger: ,(build-nested :a :b :c )

6:54 clojurebot: {:a {:b :c}}

6:54 edmondo1984: ok got it the third parameter is a function

6:54 TEttinger: yep!

6:54 edmondo1984: now the problem is that I have to reimplement updatein

6:54 luma: ,(assoc-in {} [:key1 :key2] "hello")

6:54 clojurebot: {:key1 {:key2 "hello"}}

6:54 TEttinger: why though?

6:55 ah

6:55 forgot about that one, (inc luma)

6:55 luma: there's get and get-in, assoc and assoc-in, update and update-in

6:55 edmondo1984: I am learning Clojure and I come from a non lisp background

6:56 let me find my wannabe-implementation that doesn't work

6:57 TEttinger: I would suspect that being able to reimplement the -in group of fns might be best done later

6:57 I imagine the core implementations of them are a little complex

6:57 edmondo1984: (defn assoc-in "Associate a key inside a nested map" [m [k & ks] v] ((loop [mymap {} ] (if (empty ks) (assoc m k v))) ((recur (assoc-in m ks v) [m ks v]) mymap)) )

6:58 http://paste.ofcode.org/WdwLuA3cgBdaegQgzPzAg

6:58 this stuff obviously rdoesn't work

6:58 TEttinger: the two parens seems like a problem

6:59 "((loop"

6:59 that calls the result of loop as if it is a fn

6:59 edmondo1984: and loop is not a fun ?

6:59 fn

6:59 TEttinger: same with recur, looks like a bug

6:59 edmondo1984: is a macro?

6:59 TEttinger: loop is a macro but it doesn't return a callable thing

7:00 you need one paren to call

7:00 another paren if you want to call what the first call returned

7:00 ,(+ 1 2)

7:00 clojurebot: 3

7:00 TEttinger: ,(constantly (+ 1 2))

7:00 clojurebot: #object[clojure.core$constantly$fn__4614 0x246ee771 "clojure.core$constantly$fn__4614@246ee771"]

7:00 TEttinger: ,((constantly (+ 1 2)))

7:01 clojurebot: 3

7:01 TEttinger: the first calls +

7:01 the next calls constantly and gives it as an arg 3

7:01 and you can see that prints a messy fn

7:01 since constantly returns a fn

7:01 the last calls the fn constantly returns

7:02 make sense?

7:02 parens don't do grouping in lisps

7:03 you can't just stick more in like in C or Java

7:03 edmondo1984: not sure I understood

7:04 TEttinger: uh hm.

7:04 so you understand that fns are values and can be passed as arguments and returned from other fns and macros, right?

7:05 ,(map inc [1 2 3])

7:05 clojurebot: (2 3 4)

7:05 TEttinger: inc is a fn and we can pass it as an arg to map

7:05 edmondo1984: yes

7:05 TEttinger: there's a bunch of fns in clojure's core lib that return other fns

7:06 constantly, comp, and juxt are good examples

7:06 edmondo1984: what do comp and juxt do?

7:06 TEttinger: comp composes multiple fns

7:06 edmondo1984: ah comp is composed

7:06 right

7:06 luma: ,((comp inc :foo) {:foo 3})

7:06 clojurebot: 4

7:06 luma: ((juxt :foo :bar) {:foo 1, :bar 2})

7:07 ,((juxt :foo :bar) {:foo 1, :bar 2})

7:07 clojurebot: [1 2]

7:07 edmondo1984: so juxt take an array of function and applies it

7:07 TEttinger: ,(map (comp inc inc) [1 2 3])

7:07 clojurebot: (3 4 5)

7:07 edmondo1984: just a second

7:07 ,((juxt str #(+ 1 %) [ 2 3] ))

7:07 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: sandbox/eval194/fn--195"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: sandbox/eval194/fn--195"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [clojure.core$juxt$fn__4744 invoke "core.c...

7:08 edmondo1984: ,((juxt str #(+ 1 %)) [ 2 3] )

7:08 clojurebot: #error {\n :cause "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers add "Numbers.java" 128]}]\n :trace\n [[clojure.lang.Numbers add "Numbers.java" 128]\n [clojure.lang.Numbers add "Numbers.java" 3640]\n [sandbox$eval221$fn__2...

7:08 luma: juxt takes any number of functions and returns a function that calls all those functions on its parameter and returns a vector of the results

7:08 TEttinger: vector, not array, but essentially yes. and it doesn't exactly apply

7:08 edmondo1984: ,((juxt str #(+ 1 %)) 2 )

7:08 clojurebot: ["2" 3]

7:08 edmondo1984: gooot it!

7:08 I don't know how I could have survived without Clojure

7:08 TEttinger: there's also partial, which is handy

7:08 luma: so basically ((juxt :foo :bar) param) => [(:foo param) (:bar param)]

7:09 TEttinger: ,(map (partial * 2) [1 2 3])

7:09 clojurebot: (2 4 6)

7:09 edmondo1984: what's the benefit of using partial with respect of an anonymous function?

7:09 TEttinger: ,(map (juxt identity (comp (partial * 2) inc)) [1 2 3])

7:09 clojurebot: ([1 4] [2 6] [3 8])

7:09 edmondo1984: is partial a macro that gives you a better syntax?

7:09 (partial * 2) is equal to #( * 2 % ) right?

7:09 TEttinger: they're very similar. partial works for any number of arguments

7:10 edmondo1984: got it

7:10 hyPiRion: partial is just a function afaik

7:10 $source partial

7:10 TEttinger: ,((partial *) 1 2 3)

7:10 clojurebot: 6

7:10 TEttinger: lazybot ded

7:10 edmondo1984: got it

7:10 hyPiRion: sad times

7:11 edmondo1984: so now what about loop and recurse?

7:12 TEttinger: ,(loop [a 0] (if (>= a 5) a (recur (+ a (rand-int 5)))))

7:12 clojurebot: 6

7:13 TEttinger: ,(loop [a 0] (if (>= a 5) a (recur (+ a 1))))

7:13 clojurebot: 5

7:13 luma: recur is a special form that recurses to loop (or the top of the function if there's no loop)

7:13 and loop is a special form that's just like let, but also serves as a recursion point

7:13 edmondo1984: so loop sets the recursion point

7:14 TEttinger: and what you change between recursion

7:14 like I set "a" to 0

7:14 edmondo1984: the a variable gets bound to the argument of recur

7:14 TEttinger: when I recur, I specified I wanted a different value for a, (+ a 1)

7:15 and you can use the name a throughtout the loop body

7:15 edmondo1984: so loop [ variable initialAssignment] (recur (+ variable 1 )

7:15 TEttinger: like it's used when we stop recurring to get the last value

7:15 edmondo1984: it just recur infinitely increasing variable of 1

7:15 starting from initialAssignment

7:15 TEttinger: yes

7:15 edmondo1984: good

7:15 now what about the paranthesis around loop?

7:15 loop return a function right, I need to evaluate it?

7:15 TEttinger: no

7:16 loop doesn't return a fn, it returns whatever the last statement is in the loop that didn't recur

7:16 edmondo1984: so loop evaluates the loop

7:16 is not lazy somehow

7:16 TEttinger: so in my second loop example, it returned 5

7:16 edmondo1984: got it

7:16 TEttinger: clojure defaults to not lazy

7:16 edmondo1984: now

7:17 right

7:17 so now I think I have all the elements except aybe the recursive call

7:18 TEttinger: yeah, loop/recur is a tricky thing and examples help

7:18 it's after 4 AM here, I should *head hits keyboard, instantly snoring*

7:19 edmondo1984: ok I still can't write the assoc-in

7:20 (defn assoc-in "Associate a key inside a nested map" [m [k & ks] v] (loop [mymap m ] (if (empty ks) (assoc mymap k v)))

7:21 this part looks reasonable right? If in the loop I have no other keys (ks), I just associate the current value to the current key and return the map

7:21 luma: right

7:25 edmondo1984: what's the recursive part now

7:26 can I assign two values in the loop recursion?

7:26 can I do something like loop [myvar1 initialVal1 myVar2 initialVal2] ?

7:26 luma: sure

7:26 it's just like let

7:27 edmondo1984: what's the syntax?

7:28 loop [myvar1 myvar2 initialval1 initialval2] or

7:28 loop [myvar1 initialVal1 myVar2 initialVal2]

7:30 MJB47: second

7:31 same with all similar constructs (let, for, doseq etc)

7:35 edmondo1984: MJB47 maybe you can point me to a page where it explain the syntax for all those construct?

7:36 MJB47: i suppose https://clojuredocs.org/clojure.core/let is a good start

7:38 edmondo1984: ok let uses pairs in vector

7:38 reading the documentation can be very useful

7:39 now getting back to my recursion problem in assoc-in

7:53 hello, is anyone here who can help me re-write assoc in?

8:47 Leonidas: edmondo1984: I would check whether there is just one element and then do the assoc

8:59 renl: hi aside from play-clj are there any recommended clojure libraries for doing visualization?

9:35 Empperi: I've got a strange problem with clojure regular expressions

9:36 got this regexp (escaped): #"[^\\s()\"]+\\*"

9:36 ,(re-matches #"[^\\s()\"]+\\*" "foo")

9:36 clojurebot: "foo"

9:36 Empperi: that shouldn't match as far as I understand

9:36 and if I run that against plain java that is the case

9:36 foo* should match

9:37 I'm guessing I should apply some flag to make it work like I want it to but...

9:37 oh

9:37 remove one backslash before the asterisk

9:38 and it works better :)

9:38 nevermind!

9:38 (complaining in IRC, best way to solve problems)

9:41 mpenet: you can use (re-pattern "") if you insist on escaping stuff

9:41 <Empperi> ,(re-matches (re-pattern "[^\\s()\"]+\\*") "foo")

9:41 Empperi: no I don't insist :)

9:41 mpenet: :>

10:17 sdegutis: Do you keep ~/.emacs.d/elpa/ under version control along with its parent directory? If not, how do you ensure that you can quickly and easily get your packages back when cloning your emacs configs?

10:17 Sorry wrong dir.

10:26 Oops I meant wrong channel.

10:26 But I guess it still kind of applies here.

10:26 amalloy_: what's your solution to this? Do you use cask, or do you keep ./elpa/ under version-control, or something else?

10:34 free_beard: sdegutis: just use the package.el api man, :))

10:34 sdegutis: free_beard: thanks bbl

10:46 TimMc: sdegutis: The only thing I gitignore there is .emacs.d/auto-save-list/*

10:51 aurelian: is there a way to go over a list with reduce for example but to know the index? I need to transform the list into another data structure

10:52 like map-indexed but with reduce or something

10:52 https://www.refheap.com/115194

10:53 so, if the index is even add to the first vec, if odd to the second

10:53 sdegutis: TimMc: Hmm my .gitignore has /auto-save-list /backups /autosaves /eshell /tramp /ac-comphist.dat /url/cookies *.elc /ido.last

10:59 TimMc: sdegutis: I suppose if I used those features I would probably ignore those as well. :-)

11:02 sdegutis: ok

11:12 aurelian: partition-by with index would be nice :|

11:14 ToxicFrog: aurelian: isn't that just (map-indexed vector ...) + (partition-by (comp partitioner second)) ?

11:15 aurelian: hmm

11:15 that would go over the coll twice

11:18 maybe I just don't have data in best format

11:19 the amount of clojure functions with index makes me wonder if this is a good idea

11:53 TimMc: aurelian: Your accumulator could include an index that you increment.

11:53 or just use loop :-)

11:54 aurelian: that could also do it

11:54 I ended up with something like this: (partition (/ (count data) 2) (map #(-> (:pace %)) (sort-by #(-> (:race %)) data)))

11:54 is a list of lists

11:55 potentially I can have the data already sorted by race

11:56 I'll always have 2 races that's why the partition in the middle

12:00 is basically comparing results of bunch of runners over 2 different races, but the sort was by runner, turns out sorting by race simplifies it a lot

12:17 justin_smith: aurelian: resisting the urge to make some sort of "race condition" pun here

12:17 aurelian: xD

12:17 j-pb_: justin_smith: without the context I am not sure wether they are talking about continuous integration stuff or about on which olympic runner to place their sport bets...

12:18 aurelian: second

12:20 j-pb_: I think in the last two olympics there were only black athletes qualified for the 100m sprint, so sorting by race is pretty useless

12:20 justin_smith: aurelian: you may be aware, #(-> (:pace %)) is just :pace but with an arity restriction

12:21 same with #(-> (:race %)) and :race

12:21 aurelian: I'm still learning

12:21 justin_smith: aurelian: np

12:21 just an fyi

12:21 aurelian: what's a better way to do that?

12:22 justin_smith: (map :pace (sort-by :race data))

12:22 aurelian: cheers

12:22 justin_smith: like I said, #(-> (:pace %)) is just :pace with an arity restriction, and the arity restriction didn't help you there :)

12:22 marcfontaine: trying to find a way to use a macro with a def on a set of values

12:22 (defmacro t [val] `(def ~(symbol val) ~val))

12:22 user> (t “a”)

12:22 #'user/a

12:22 user> a

12:22 "a"

12:22 (doseq [v ["b" "c" "d"]] (t v))

12:22 user> b

12:22 CompilerException java.lang.RuntimeException: Unable to resolve symbol: b in this context

12:23 aurelian: justin_smith got it. thanks!

12:23 justin_smith: marcfontaine: macros cannot use data that is not present when the form is compiled

12:24 that doseq hides the argument from the macro, the macro just sees "v"

12:24 err, just sees v, the symbol

12:25 at the time of compilation it does not run the macro on the args it would see at runtime - just the literal args in the form

12:25 marcfontaine: a macro is a function that takes a form as an argument and returns a new form. That form is compiled. Only later is anything run.

12:26 marcfontaine: I don’t follow, if I do (t “a”) that works if I do (doseq [v [“a”]] (t v)) that doesn’t work the only difference is that it’s in a doseq

12:26 justin_smith: marcfontaine: if you use intern instead of def you don't need to mess with macros, it's much simpler

12:26 marcfontaine: the difference is that the argument is v not "a"

12:27 marcfontaine: macros only run before compilation, and they are functions that transforms forms, macros do not see runtime data.

12:27 if you use a function instead of a macro, and the function uses intern, this is much easier. Just use intern instead of def.

12:28 ,(doc intern)

12:28 clojurebot: "([ns name] [ns name val]); Finds or creates a var named by the symbol name in the namespace ns (which can be a symbol or a namespace), setting its root binding to val if supplied. The namespace must exist. The var will adopt any metadata from the name symbol. Returns the var."

12:29 justin_smith: ,(intern 'sandbox 'a "foo")

12:29 clojurebot: #'sandbox/a

12:29 justin_smith: ,a

12:29 clojurebot: "foo"

12:32 justin_smith: ,(doseq [v ["b" "c" "d"]] (intern 'sandbox (symbol v) v))

12:32 clojurebot: nil

12:32 justin_smith: ,b

12:32 clojurebot: "b"

12:32 justin_smith: ,c

12:32 clojurebot: "c"

12:32 justin_smith: ,d

12:32 clojurebot: "d"

12:48 rhg135: I love cljs

12:49 marcfontaine: justin_smith I need this for clojurescript and intern is not implemented

12:56 justin_smith: marcfontaine: oh, that's rough, because that also rules out eval (the only way to use def with a name only known at runtime)

12:56 marcfontaine: what about using a hash-map with keys instead of defs in a namespace?

12:59 marcfontaine: oh, the other option is the fact that "def" doesn't create vars in js, it just creates js variables. So you could just use interop on the namespace or on the window itself

13:00 marcfontaine: it’s for using bootstrap classes from reagent https://gist.github.com/marcandrefontaine/c32b566b2e981d867967 right now I have to do them one by one, I am trying to rewrite the macro by passing it all the class names but I can’t figure it out.

13:03 justin_smith: marcfontaine: yeah, macros can't use runtime data. What about just using aset? aset does in cljs what intern does in clj, considering that vars don't exist in cljs.

13:04 otherwise you could make a macro that expands to all the def calls in one body - eg. you would pass all the names to the macro, rather than calling the macro inside a doseq, the macro would have a for or map inside it to do all the defs

13:05 marcfontaine: yes that’s what I was trying to do with a doseq in the macro which didn’t work at all I’ll try with the for/map

13:07 justin_smith: marcfontaine: yeah, doseq is totally useless in a macro - a macro must return the form you want to evaluate

13:09 ,(defmacro defs [& bindings] (cons 'do (for [[sym value] (partition 2 bindings)] (list 'def sym value)))) ; marcfontaine

13:09 clojurebot: #'sandbox/defs

13:09 justin_smith: ,(defs a "a" b "b" c "c" z "z")

13:09 clojurebot: #'sandbox/z

13:09 justin_smith: ,[a b c z]

13:09 clojurebot: ["a" "b" "c" "z"]

13:10 justin_smith: marcfontaine: the above should work in cljs

13:12 marcfontaine: beautiful

13:16 rhg135: Actually, I'm pretty sure vars exist in some form on cljs so def would be the way to go

13:28 justin_smith: rhg135: no, they explicitly do not exist in cljs

13:29 rhg135: unless the clojurescript wiki is severely out of date

13:29 https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure#vars-and-the-global-environment

13:32 rhg135: oh, my bad, the wiki is out of data

13:32 *date

13:32 sdegutis: Is there a more convenient way to use clojure.data.csv than (write-csv) with a temporary java.io.StringWriter which you just call (str) on afterwards in order to get the CSV as a string?

13:32 Please tell me the answer is yes, because I'm certain it'sn o.

13:32 justin_smith: rhg135: if vars exist, then it should have intern :(

13:34 rhg135: They usually don't at runtime

13:35 justin_smith: rhg135: ahh, so vars are a thing but only in the compiler, not in the runtime

13:35 ick

13:35 rhg135: sdegutis: with-out-str

13:35 justin_smith: rhg135: it doesn't print anything interesting

13:36 sdegutis: rhg135: Oh right! Why didn't I think of that? Actually, I remember thinking of that, and it for some reason not being viable in this usage.

13:36 rhg135: Oh, then no

13:36 sdegutis: I can't remember why I thought so. Hmm.

13:36 justin_smith: rhg135: the issue is that instead of returning or printing a string, it wants an arg it can write to, which means making a stringwriter

13:36 matthavener: anyone know how to get leiningen to copy CSS files from a cljsjs package into my resources dir?

13:36 sdegutis: Oh right, that's why.

13:36 I should probably just sign the dang CSV or whatever it's called, and send a PR through Jira.

13:37 puredanger: sdegutis: http://clojure.org/community/contributing

13:39 sdegutis: Yeah that.

13:40 puredanger: if I go through all this hassle do you think there's a chance that I could get clojure.data.csv fixed to not be so inconvenient?

13:40 puredanger: sure - what's the issue again?

13:40 sdegutis: (The beautiful thing about Github Issues and PRs is that it's really quick/easy to figure that question out.)

13:41 puredanger: write-csv is inconvenient when all you want is a string

13:41 puredanger: you have to create your own StringWriter and then call (str) on it and discard it. 3 lines to do something that should take 1.

13:41 rhg135: (defn as-str [f] (str (doto (StringWriter.) (f))))

13:41 sdegutis: puredanger: not the end of the world obviously, but not as convenient as it should be.

13:41 rhg135: yes I have that now, and I only use it for this one use-case and would like to get rid of it

13:41 puredanger: what would you propose?

13:42 sdegutis: puredanger: this function be inlined as a convenience function called csv-to-string or something that just wraps write-csv with a StringWriter and returns the inner string

13:43 puredanger: seems like a reasonable request to me

13:43 sdegutis: puredanger: (defn csv-to-string [x] (let [out (java.io.StringWriter.)] (write-csv out x) (str out)))

13:43 Okay. Then I'll do it!

13:43 * sdegutis whips out the fricken scanner :/

13:43 puredanger: it's an e-form, no scanner required

13:44 sdegutis: Woo!

13:45 puredanger: see http://dev.clojure.org/display/community/Developing+Patches for making patches

13:45 I need to move that stuff onto clojure.org

13:45 sdegutis: puredanger: Am I right to understand that it's common to not need to fill out the top three fields (and in fact you can't) in the e-form? Or am I totally misunderstanding this thing?

13:46 puredanger: yeah, those populate based on later fields

13:46 which is weird, but I can't change it

13:47 sdegutis: Ok just checking thanks alex :)

13:48 puredanger: woo signed and verified! thanks for the link

13:48 puredanger: I see it! :)

13:49 sdegutis: :D

13:49 * sdegutis reads the patch instructions and gets ready to sign up for JIRA

13:50 puredanger: http://dev.clojure.org/jira/secure/Signup!default.jspa

13:50 TimMc: Oh, how the process has changed.

13:50 A couple years back I would *not* have seen a ":D" anywhere near a discussion around the contributer agreement. :-P

13:51 justin_smith: haha

13:51 TimMc: I had to walk uphill both ways in the snow to get to the snail mail

13:51 TimMc: I had to hand crank the fax machine all night in case something came through.

13:51 puredanger: hey, there's still a filing cabinet somewhere with printed versions of all these :)

13:51 justin_smith: maybe I shouldn't ever quote a cosby joke ever again, now that I consider it

13:53 TimMc: justin_smith: Because stuff?

13:53 justin_smith: TimMc: stuff pretty much - I don't like the idea of repeating his jokes any more, after hte other stuff he did. I dunno, maybe it's no big deal.

13:55 TimMc: No one is all good or all bad. I think it's fine.

13:56 but I hear you

14:00 * sdegutis is running tests on data.csv

14:04 sdegutis: Tests pass!

14:07 puredanger: I hope so. :) CI runs them all the time so it would be surprising if they did not.

14:11 sdegutis: puredanger: so, the instructions I'm following say to include the JIRA ticket's number in the commit, so I'm creating a JIRA ticket before committing.. but the JIRA ticket says it requires a patch, and I have no idea how to create patch files but I have a commit prepared (all except the name). I feel kind of stuck on how to move forward.

14:11 puredanger: create the ticket. create the patch. add the patch to the ticket.

14:11 * sdegutis looks up how to create patch files

14:11 rcassidy: sdegutis: git format-patch -1 HEAD

14:11 If HEAD is the commit with what you wanna make a patch based on

14:11 sdegutis: rcassidy: thanks!

14:11 rcassidy: np

14:11 and that's a 1 (one) not L

14:11 sdegutis: I just copy/pasted it ;)

14:11 Wow, I have a newfound appreciation for GitHub's Pull Request based workflow.

14:11 puredanger: if you do it like 20 times a day for a few years, it gets really easy

14:11 sdegutis: Haha.

14:11 ToxicFrog: sdegutis: yeah, this is why I never submit patches to clojure and only rarely to bup

14:12 sdegutis: Creatd!

14:12 Woo!

14:14 puredanger: are the appropriate people notified when I create a ticket including a code/test patch like I just did?

14:14 puredanger: usually, although you created it in the wrong project (CLJ not DCSV)

14:14 I moved it

14:15 sdegutis: Dang, sorry. Thanks puredanger.

14:16 puredanger: Jonas Enlund is the project owner so you could ping him too

14:16 sdegutis: puredanger: Okay now I see how to find the right project and create it there.

14:16 puredanger: I think it should be set up so that happened on creation, but not positive (not all of the contribs are set up the same)

14:18 sdegutis: Wow Jira is something else.

14:18 How do you @ping someone in a comment, the @at syntax isn't pulling up a dropdown list of names?

14:19 puredanger: Jonas is "jonas" on slack if you're ever on there or @jonasenlund on twitter

14:20 in jira, I forget - you can look it up in the formatting instructions

14:21 sdegutis: Phew glad that's done with.

14:22 TimMc: HAHAHA it has only just begun

14:22 sdegutis: Thanks puredanger for all your help with this process, and you have my condolences that you have to go through that every day.

14:22 puredanger: it's really not that bad

14:22 if you don't hear from Jonas in the next week, ping me

14:23 sdegutis: puredanger: nah don't worry about it, he'll see it when he sees it

14:41 justin_smith: I was pretty convinced you were right about the with-out-str thing not working, but now I don't remember why, and it's the thing Jonas is proposing as to why the helper function isn't necessary.

14:42 Hmm. It does in fact work.

14:42 justin_smith: sdegutis: oh does it like use *out* by default and I forgot it did that?

14:42 sdegutis: justin_smith: yeah

14:42 justin_smith: wait the CSV lib? no

14:42 justin_smith: sdegutis: oh so you pass in *out* and surround that with with-out-string ?

14:42 sdegutis: ,(do (require 'clojure.data.csv) (with-out-str (clojure.data.csv/write-csv *out* [["a" "b"] ["c" "d"]])))

14:42 clojurebot: #error {\n :cause "Could not locate clojure/data/csv__init.class or clojure/data/csv.clj on classpath."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate clojure/data/csv__init.class or clojure/data/csv.clj on classpath."\n :at [clojure.lang.RT load "RT.java" 456]}]\n :trace\n [[clojure.lang.RT load "RT.java" 456]\n [clojure.lang.RT load "RT.java" 419]\n [clojure.co...

14:42 justin_smith: OK right

14:43 sdegutis: However, I thought one was a printer and one was a writer.

14:43 So I thought it just simply wouldn't work.

14:43 justin_smith: sdegutis: is that really that much better than a StringWriter?

14:43 sdegutis: No, I personally think it's still worth a patch.

14:43 But it's a harder argument to make.

14:47 amalloy: i think c.d.csv does the right thing already, by working with streams (or writers, i forget) and *not* encouraging you to turn a csv into one giant string

14:48 you already can do it if you want to, quite easily, with with-out-str, but you usually shouldn't, so there's no convenient shortcut for it. just like there's no dissoc for vectors because it's expensive to remove elements from the middle

14:48 justin_smith: that's a good point

14:48 sdegutis: amalloy: very good point

14:49 amalloy: how do you return a CSV from a Ring handler function without turning it into a string first?

14:49 rhg135: ,(dissoc '[a b c] 1)

14:49 clojurebot: #error {\n :cause "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap"\n :at [clojure.lang.RT dissoc "RT.java" 848]}]\n :trace\n [[clojure.lang.RT dissoc "RT.java" 848]\n [clojure.core$dissoc invokeStatic "core.clj" 1462]\n [clojure.c...

14:49 rhg135: cool

14:49 amalloy: sdegutis: ring accepts a lot of things other than strings

14:50 notably, a lazy seq of strings

14:50 so you can stream the response

14:50 sdegutis: amalloy: But still, what do you create and use as the out-param?

14:51 I've closed the issue so this isn't an argument in favor of the stringifying function. I'm just curious what's a better output writer than StringWriter.

14:51 amalloy: ring will also accept an InputStream, i believe; one option would be to use a pipedinputstream/pipedoutputstream pair

14:51 but that's a bit clunky

14:52 does c.d.csv have a row->string function or something?

14:52 unhelpfully, it has that function but marks it private

14:54 hiredman: ~private

14:54 clojurebot: not even once

14:54 justin_smith: yeah, I think the piped stream combo is actually the whizbang thing

14:54 hiredman: ~o/

14:54 clojurebot: \o ... High five!

14:54 amalloy: personally i would just not use c.d.csv because it's just getting in the way. {:status 200, :body (interpose "\n" (for [row csv] (interpose "," row)))}

14:54 this of course has the problem that it doesn't handle cell data with commas

14:55 which would be easy to fix if c.d.csv exposed its functions for working with data smaller than a whole file

14:55 sdegutis: amalloy: right quoting is a nice behavior of this lib

14:55 amalloy: you know, I was actually thinking "why don't I just write this myself, it's not that fricken hard of a data format" but then I was like "no, no, I should be using the appropriate libs for things like this, that's the Right Way™" and decided to keep using this lib

14:56 amalloy: yeah, i agree with you on that, it really sucks to reimplement it

14:56 sdegutis: But you're right. In this case, I only use the lib in exactly one route, and in that case, there are no quoting issues and never will be.

14:56 amalloy: i think a much better PR to c.d.csv would be to make its private functions mostly public

14:56 and then you could actually use it to stream to ring pretty easily

14:56 or, as i said, you could dedicate a thread to streaming the response using piped io and the existing api

14:56 sdegutis: Meh, I'd actually much prefer a CSV API similar to clojure.pprint/print-table

14:57 justin_smith: ,(let [o (java.io.PipedOutputStream.) i (java.io.PipedInputStream. o)] (.write o (.getBytes "hello\n")) (.close o) (slurp i))

14:57 clojurebot: "hello\n"

14:57 sdegutis: Where you give it the keys and a seq of maps and it just spits out the right CSV. That's a sweeter API.

14:57 ,(clojure.pprint/print-table [{:a 1 :b 2} {:a 3 :b 4}])

14:57 clojurebot: #error {\n :cause "clojure.pprint"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clojure.pprint"\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.n...

14:57 amalloy: actually, something i just remembered: compojure (or maybe it's ring?) has a helper function for creating a piped io pair out of a function

14:57 makes it super easy

14:57 justin_smith: amalloy: oh, nice

14:57 sdegutis: ,(do(require'clojure.pprint)(clojure.pprint/print-table [{:a 1 :b 2} {:a 3 :b 4}]))

14:57 clojurebot: #error {\n :cause "require'clojure.pprint"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: require'clojure.pprint, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.ClassNotFoundException\n :message "require'clojure.pprint"\n :at [java.net.URLClassLoader$1 run "URLClassLoade...

14:58 sdegutis: ,(do(require 'clojure.pprint)(clojure.pprint/print-table [{:a 1 :b 2} {:a 3 :b 4}]))

14:58 clojurebot: \n| :a | :b |\n|----+----|\n| 1 | 2 |\n| 3 | 4 |\n

14:58 justin_smith: amalloy: that would also be easy to implement

14:58 amalloy: https://ring-clojure.github.io/ring/ring.util.io.html#var-piped-input-stream

14:58 so it would be like: {:status 200 :body (piped-input-stream (fn [o] (write-csv o my-csv))))

14:58 modulo mismatched delimiters

14:59 hiredman: how perfect would it have been if that was also a private function

14:59 amalloy: weavejester knows better though

15:01 sdegutis: amalloy: really!?

15:01 sweet!

15:02 amalloy: it's kind of ugly though because you have to write a helper function, but still it's mostly nicer

15:02 amalloy: what helper function?

15:02 sdegutis: amalloy: on your example the (fn [o] ...)

15:02 I also like that Compojure allows you to return a variety of formats.

15:02 https://github.com/weavejester/compojure/blob/master/src/compojure/response.clj

15:03 amalloy: i think "helper function" generally means something quite different from that lambda

15:03 sdegutis: amalloy: wrapper function then

15:30 Every time I need to use defrecord and definterface I have to look them up to see which one of them takes a "self" first-param and which doesn't.

15:30 clojurebot: Gabh mo leithscéal?

15:30 sdegutis: Is there a good mnemonic for this?

15:31 ystael: sdegutis: "conj.io"

15:31 :p

15:31 sdegutis: ???

15:31 Oh https://www.conj.io/

15:31 ystael: is that your site?

15:31 ystael: which doesn't, at all, address your issue

15:31 namely having to look them up :)

15:31 no, I forget who runs it, it isn't me

15:33 Kamuela: Which is the correct answer? Which requires self?

15:34 sdegutis: Kamuela: defrecord apparently

15:34 (doc defrecord)

15:34 clojurebot: "([name [& fields] & opts+specs]); (defrecord name [fields*] options* specs*) Options are expressed as sequential keywords and arguments (in any order). Supported options: :load-ns - if true, importing the record class will cause the namespace in which the record was defined to be loaded. Defaults to false. Each spec consists of a protocol or interface name followed by zero or more method bodies: protocol-or-interface-or-Object (metho

15:35 sdegutis: "Note that a parameter must be supplied to correspond to the target object ('this' in Java parlance). Thus methods for interfaces will take one more argument than do the interface declarations.”

15:35 Kamuela: I would just repeat record yourself over and over

15:37 sdegutis: Kamuela: that didn't work for hippocampus in college

15:37 Kamuela: when I try to remember what hippocampus means, I think of a hippo standing on top of the campus building shouting

15:37 Kamuela: I have absolutely no idea what it's supposed to represent

15:38 Kamuela: Memory

15:38 sdegutis: But how does that relate to its function?

15:38 ystael: sdegutis: "horse area"

15:38 sdegutis: stupid mnemonic

15:38 Kamuela: Amygdala emotion

15:39 Cerebellum balance? Not actually sure anymore

15:42 sdegutis: see?

15:42 useless

16:05 amgarchIn9: http://pastebin.com/P8T44STu

16:06 hi, is there something wrong with snag-quotes? I see some deadlock for n = 2048. New to clojure and dont know many debug techniques.

16:07 justin_smith: amgarchIn9: "launching" is done by calling future, you don't need to mapv deref, you just need (doall q)

16:07 amgarchIn9: what happens is the next future is not even started until the previous completes, because deref blocks and for is lazy

16:08 alternatively you could do the silly (mapv identity q), but just (doall q) instead

16:09 amgarchIn9: (mapv deref (vec q)) I forced the q and the performace degraded. Chunks of 32 seem to work for arbitrary n

16:09 justin_smith: amgarchIn9: when you map deref you only start at most a chunks worth at a time, (doall q) makes all the futures start immediately

16:10 if you want only N active at a time, use a proper thread pool instead of futures

16:11 hiredman: don't do io in a go block

16:11 amgarchIn9: well, snag-futures was there as a reference. The actual problem is with snag-quotes

16:12 hiredman: what does that have to do with anything?

16:13 don't do io in a go block

16:14 you most likely should be using pipeline-blocking

16:14 https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L546-L550

16:17 amgarchIn9: thatnk, reading. (show s) was not there when the problem first occured. Without IO which (wget) also does there is no point in the excersize.

16:19 hiredman: right, so do your io, but don't use a go block

16:19 pipeline-blocking runs each blocking task on a real thread https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L497-L500

16:39 sdegutis: Oh man I already forgot when to use defprotocol vs definterface :/

16:39 Oh right. I want defprotocol.

16:40 amalloy: also don't start an unlimited number of threads to perform IO at once. you'll just DoS your system when it reaches capacity

16:40 hiredman: which is why pipeline makes you pass in a `n`

16:41 on a virtual machine a useful 'n' for io is going to be a relatively small number

17:02 amgarchIn9: that why I thout go blocks and "the state machine" on a predefined fixed size thread pool is fine. I have "netstat -aon | grep <the ip here> | wc" about 60. Fore some reason all "takes" from the channel are "delayed" (exclamation singns here http://pastebin.com/B05czQTB )

17:03 justin_smith: IO in go blocks just starves core.async's fixed size pool, use pipeline-blocking instead

17:04 ystael: justin_smith: i'm not familiar with core.async at all, is this analogous to other situations where you are doing blocking operations on a thing that needs to be a nonblocking asynchrony reactor?

17:05 justin_smith: ystael: pretty much - core.async has a state machine and runs multiple go blocks in a specialized thread pool, doing blocking IO in those go blocks subverts that design (and can lead to bad failures)

17:06 ystael: got it, i remember a similar thing from working with rxjava

17:06 justin_smith: ystael: simplified version is <! turns into a parked state meaning some other code can be run in your thread >! similarly parks but also wakes up whoever reads from the chan if they were parked

17:07 ystael: "open mouth" and "feed toddler"? :)

17:07 justin_smith: so it's a combination of coroutines and actual threading, copied from golangs goroutines

17:08 ystael: something like that - the way I remember it is (let [x (<! chan)] ...) the data is moving from chan into x

17:09 ystael: justin_smith: i tend to conceptualize all other areas of my life in terms of toddler management tasks at the moment :)

17:12 amalloy: justin_smith: <! and >! both have the same behavior re waking up other code, right?

17:13 <! will wake up anyone who was parked trying to write, and >! will wake up anyone who was parked waiting to read

17:13 hiredman: amgarchIn9: mixing blocking tasks and non-blocking tasks in the same threadpool is problematic, the blocking tasks will starve the non-blocking tasks, and the level of parallelism to get the best performance out of each type of task tends to be different

17:14 amgarchIn9: the threadpool core.async uses for go blocks is a global resource, any code libraries, whatever, you load could be using it

17:15 amgarchIn9: as a shared resource it needs to be designated for blocking or non-blocking tasks (so different people don't use it for different kinds of tasks)

17:15 it has been designated for non-blocking tasks

17:18 and, more specifically, the core.async threadpool is a forkjoin threadpool, which is designed for compute bound tasks (https://stackoverflow.com/questions/8206318/is-javas-fork-and-join-thread-pool-is-good-for-executing-io-bound-task)

17:33 amgarchIn9: thank you all. Apparently posting to a channel does not necessarily wake up the reader. But other writers in my case. I got you message, just wanted to understand what is going on here.

17:49 ashnur: on an non unrelated but distant note... check this out: https://www.youtube.com/watch?v=K4vyRvMASPU

17:55 justin_smith: amalloy: oh yes, right

18:08 sdegutis: Hello. Good afternoon and I hope you're all doing well. What is the standard way of creating a Date that's precisely 300 seconds from now, without requiring third party libraries?

18:09 justin_smith: ,(java.util.Date. (+ (.getTime (java.util.Date.)) (+ 1000 300)))

18:09 clojurebot: #inst "2016-02-25T23:09:07.031-00:00"

18:09 justin_smith: ,(java.util.Date. (+ (.getTime (java.util.Date.)) (* 1000 300))) ; OOPS

18:09 clojurebot: #inst "2016-02-25T23:14:18.314-00:00"

18:09 sdegutis: justin_smith: Thank you. Do you happen to know why some people recommend using Calendar instead of that small simple solution?

18:09 justin_smith: sdegutis: the chance of a bug like using + instead of * ?

18:10 sdegutis: justin_smith: no, they still suggest using *, so the chance is still there

18:10 justin_smith: haha, no idea then

18:12 sdegutis: justin_smith: Also why not use this?

18:12 ,(System/currentTimeMillis)

18:12 clojurebot: 1456441941419

18:12 justin_smith: sdegutis: because I keep forgetting that exists

18:12 sdegutis: ,(.getTime (java.util.Date.))

18:12 clojurebot: 1456441955900

18:12 sdegutis: Well they seem to produce different values.

18:12 justin_smith: sdegutis: time has this habit of doing things

18:12 sdegutis: Several thousand units apart, too.

18:12 justin_smith: very mutable, that time thing is

18:13 sdegutis: ,(= (.getTime (java.util.Date.)) (System/currentTimeMillis))

18:13 clojurebot: true

18:13 justin_smith: ,(- (.getTime (java.util.Date.)) (System/currentTimeMillis))

18:13 clojurebot: 0

18:13 justin_smith: well, then

18:14 sdegutis: So 1000 milliseconds = 1 seconds. Okay, will remember htis.

18:14 justin_smith: sdegutis: if our country used metric you would know by the milli prefix

18:14 maybe we need to use hogsheadseconds or something

18:15 amalloy: temporal ounces

18:17 TEttinger: time is measured by the accumulation of cheeto dust in the US department of weights and measures' trailer

18:19 rhg135: time is only an abstraction we use to explain how values succeed one another

18:20 sdegutis: ,(java.util.Date/from (.. (java.time.LocalDateTime/now) (plusMinutes 5) (atZone (java.time.ZoneId/systemDefault)) (toInstant)))

18:20 clojurebot: #error {\n :cause "java.time.LocalDateTime"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: java.time.LocalDateTime, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.ClassNotFoundException\n :message "java.time.LocalDateTime"\n :at [java.net.URLClassLoader$1 run "URLClas...

18:20 sdegutis: ,(import 'java.time.LocalDateTime)

18:20 clojurebot: #error {\n :cause "java.time.LocalDateTime"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "java.time.LocalDateTime"\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.ja...

18:20 sdegutis: ,(System/getProperty "java.version")

18:20 clojurebot: #error {\n :cause "denied"\n :via\n [{:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]\n [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkPropertyAccess nil -1]\n [java.lang.System getProperty ...

18:20 sdegutis: haha stupid clojurebot

18:21 oh that lovable rascal

18:24 That said, I like this solution best: (-> (java.time.LocalDateTime/now) (.plusMinutes 5) (.atZone (java.time.ZoneId/systemDefault)) (.toInstant) (java.util.Date/from))

18:28 rhg135: why do you need to know about tz to add 5 minutes to your time

18:28 unless minutes depend on zone

18:28 rcassidy: ,(-> (java.time.LocalDateTime/now) (.plusMinutes 5) (.atZone (java.time.ZoneId/systemDefault)) (.toInstant) (java.util.Date/from))

18:28 clojurebot: #error {\n :cause "java.time.LocalDateTime"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: java.time.LocalDateTime, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.ClassNotFoundException\n :message "java.time.LocalDateTime"\n :at [java.net.URLClassLoader$1 run "URLClas...

18:28 rcassidy: :(

18:31 sevvie: we should use french metric time.

18:32 rcassidy: also, this is confusing -- i am using a script that uses the sum of the ascii values of a IRC nick to choose chat name colors

18:32 justin_smith: rhg135: clearly, you want a different result if there's a DST change between now and 5 minutes from now

18:32 rcassidy: ,(mod (apply + (map int (seq "clojurebot"))) 256)

18:33 clojurebot: 57

18:33 rcassidy: ,(mod (apply + (map int (seq "rhg135"))) 256)

18:33 clojurebot: 218

18:33 rcassidy: ,(mod (apply + (map int (seq "sdegutils"))) 256)

18:33 clojurebot: 212

18:33 rcassidy: hmm

18:33 you all look the same color of red to me

18:34 sdegutis: rhg135: I have no idea?

18:34 rhg135: I just know you can't get an #inst without doing that

18:34 justin_smith: rhg135: minor thing, that seq call is not needed, map already calls seq

18:34 err

18:34 rcassidy: ^

18:35 rcassidy: thanks justin_smith ! still lerning that stuff

18:35 *learning

18:36 rhg135: (inc justin_smith) ; I totally forgot about DST

18:36 justin_smith: (map int "lazybot is gone now :(")

18:36 ,(map int "lazybot is gone now :(")

18:36 clojurebot: (108 97 122 121 98 ...)

18:36 rhg135: I might run that code a few minutes before the time shift

18:36 rcassidy: and I figured out it's because I'm not mod'ing by 256 in my actual irssi plugin, it's just mod'd over how many colors exist in the plugin, so maybe it isn't very many

18:36 too many collisions though

18:37 sevvie: ,(mod (apply + (map int (seq "sevvie"))) 256) ; vanity thy name is...

18:37 clojurebot: 146

18:38 justin_smith: ,(mod (transduce (map int) + "justin_smith") 256) ; yet more vanity

18:38 clojurebot: 33

18:38 sdegutis: ,(let [a (java.util.Date.) b (java.util.Date.)] [(= a b) a b])

18:38 clojurebot: [true #inst "2016-02-25T23:38:58.227-00:00" #inst "2016-02-25T23:38:58.227-00:00"]

18:39 sdegutis: ,(let [a (java.util.Date.) b (java.util.Date.)] [(= a b) a b])

18:39 clojurebot: [true #inst "2016-02-25T23:39:02.516-00:00" #inst "2016-02-25T23:39:02.516-00:00"]

18:39 sdegutis: Haha silly clojurebot.

18:39 justin_smith: rcassidy: fwiw I showed how to combine the apply and map into a single thing with transduce above

18:40 rcassidy: ah that's neat

18:40 ,(mod (apply + (map int (seq "sdegutils"))) 15)

18:40 clojurebot: 5

18:40 rcassidy: ,(mod (apply + (map int (seq "rhg135"))) 15)

18:40 clojurebot: 9

18:40 rcassidy: grrr

18:41 ,(mod (apply + (map int (seq "clojurebot"))) 15)

18:41 clojurebot: 1

18:41 rcassidy: this doesn't make sense!

18:41 justin_smith: ,(mod (transduce (map int) + 0 "clojurebot") 15)

18:41 clojurebot: 1

18:41 justin_smith: ,(mod (transduce (map int) + "clojurebot") 15) ; aha, the 0 is optional

18:41 clojurebot: 1

18:44 rcassidy: i wonder how i can make irssi tell me how many colors it's choosing from

18:44 sdegutis: Of course you can't.

18:45 rcassidy: :(

18:45 rhg135: `tput colors` can show you how many it should think to use

18:47 terminals are weird with colors

18:48 rcassidy: yeah, tput colors gives me 256

18:48 and i'm reading my irssi script, but i don't think it picks from terminal colors

18:48 looks like it picks from a list 11 items long

18:49 but my own tests with mod 11 / 10 don't work

18:49 rhg135: it's a handy feature for sure

18:49 you are yellow-orange

19:26 TEttinger: rcassidy: if you have an xterm-based terminal, it probably supports a certain escape code for 256-color selection, but almost all terminals support 16-color using a different escape code (notably windows cmd.exe doesn't support ansi escape codes)

19:28 https://github.com/shabble/irssi-docs/wiki/Notes-256-Colour

19:29 {blake}: Can laziness "get" you in React? Like, if your rendering routine contains a map or for or whatevs, will that potentially not be realized without forcing it?

19:30 'cause I got a situation where I'm changing the underlying data atom and it's not updating the screen.

19:31 But the rendering function is being called.

19:32 sdegutis: Wooo!

19:32 {blake}: Who?

19:32 sdegutis: Just replaced all our clj-aws-s3 usages with plain old aws-java-sdk Java stuff!

19:33 That was one situation where using the Java-based SDK actually resulted in fewer lines of code than using the Clojure wrapper around it.

19:34 TEttinger: wow

19:34 clojure does have durn good interop

19:35 sdegutis: Well in this case it's mainly because of the design of the wrapper.

19:36 TEttinger: yeah, I just think it's nice that wrappers aren't always needed

19:37 and you can just use the java one "just like that"

19:37 sdegutis: :)

19:42 TEttinger: hm, just curious: is cfleming or any other cursive expert around? I'm not sure if I'm experiencing a bug

19:44 this is my project.clj, very small, and cursive (but not lein) can't seem to see the deps. https://github.com/tommyettinger/squidlib-clj/blob/master/project.clj

19:44 lein runs just fine

19:54 {blake}: TEttinger: I have occasional problems with deps in cursive, also.

19:54 Sometimes I just restart IJ.

20:11 Kamuela: I actually think cider and paredit are working with Emacs. I'm just not doing well with it yet

20:22 TEttinger: {blake}, hm, I've restarted at least 3 times

20:22 {blake}: TEttinger: I'm sorry, I didn't mean to imply that it actually worked, just that I did it. =P

20:23 TEttinger: oh haha

20:23 it's odd that there's no leiningen context menu like there is for maven and gradle

20:24 {blake}: Hey, did you "lein clean"?

20:24 TEttinger: hm, no

20:25 {blake}: I've been having to do that a ton lately. Not sure what evil I'm perpetuating.

20:26 I'm thinking I don't have a handle on this whole react/reagent thing. My desire to set a defaultValue launches me into this whole world of "controlled components" where I'm now manually updating the app state.

20:26 TEttinger: also my "External Libraries" in cursive just shows leiningen and Java 8

20:27 {blake}: TEttinger: Where is that? It's not "Libraries", right?

20:29 TEttinger: not sure. http://i.imgur.com/wDJ0pOm.png

20:30 {blake}: Oh, in the project navigator thingy.

20:30 Yeah, that doesn't seem right at all.

20:30 I get carpal tunnel trying to go trhough my External Libraries.

20:30 TEttinger: I agree

20:32 it's like it isn't really a clojure project

20:32 {blake}: Oh, could that be it?

20:32 TEttinger: no idea

20:33 {blake}: I've been using Cursive for so long, I haven't checked lately as to its project generation. I always do a "lein new" from the command line.

20:33 TEttinger: there's no clojure facet I can add. I think I did lein new as well

20:33 {blake}: But trying to create a new Clojure project =inside= IJ has never worked out well for me.

20:34 TEttinger: I don't know how I made it, but I think it was "lein new"

20:35 {blake}: When I do that, I get the 1.8 JDK, clojure-complete, clojure 1.8 and nrepl, and that's it for exterinal libraries.

20:37 TEttinger: yeah, looks like that for me

20:38 how do you add deps? does adding them to project.clj automatically pop those suggestions up in sources when it's working?

20:39 {blake}: TEttinger: Yes, eventually. Sometimes it's real smooth. Other times, not so much.

20:39 Like I just added in clj.time, and it's not seeing that.

20:40 TEttinger: hm, ok

20:40 {blake}: Oh...I may also do a "lein deps" from the CL.

20:41 But I don't think that's necessary any more.

20:42 Be worthwhile to ask cfleming about: how deps get into the environment and what we're doing wrong.

20:42 TEttinger: it works in the repl in cursive but not in the editor, oddly

20:42 {blake}: Like, I just added clj-time and it didn't show up. I restarted twice, now it's in the REPL.

20:43 I've seen that, too. I've gone cuckoo trying to figure out that one.

20:44 I've got that now with my simple clj-time example. Works in REPL, editor doesn't see it.

20:49 Yeah, I don't get this thing. I've got this atom with my app data in it. I've changed it, which triggers a redraw. "Controlled components" have onChange events which...change the data in the atom, which (it seems to me) would trigger the redraw again.

20:53 TEttinger: it's definitely odd

20:53 thanks for confirming that this is not isolated to my computer, {blake}

20:53 or my miiiiiind

20:54 {blake}: It's AAALLL in your MIIIIND!

20:55 Yeah, love Cursive, but this is a weak spot.

20:57 TEttinger: I mean I'm trying to make a clojure wrapper for this java lib, and not being able to see the lib I'm wrapping is trouble

22:10 sdegutis: TIL you can't merely (import) a namespace you created containing a defprotocol, you have to (require) it first.

22:45 rhg135: Does that work with a non-aot definterface?

Logging service provided by n01se.net