#clojure log - Aug 30 2014

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

0:29 justin_smith: jkj: does using lein clean effect this at all?

0:57 BAMbanda: I would like to develop a new web presence for a very young educational institutue, please suspend judgements and lets talk tech

0:57 its www.alhudauniversity.org and is currently hosted on wordpress

0:58 I don't like it at all, horrible design, and overall not appealing for a hacker to work on, so I want to do a complete overhaul, internal and external. I know it will take time, the main concern is the ease of updating content for non techy people

0:59 the appeal of wordpress is how easy it is to maintain for small to even large organizations. What options do I have for having an admin interface for adding course descriptions and the like?

0:59 arrdem: 85% probability of having to roll your own

1:00 BAMbanda: Do you think I should look at how wordpress is built and just translate code to ruby? Potentially kickstarting a rails like wordpress variant?

1:04 arrdem: why are you asking about ruby and php in #clojure? #ruby is a /join away

1:05 andrewchambers: or #clojurescript

1:05 for frontend

1:06 BAMbanda: woops, i thought I switched!

1:06 Sorry guys :/

1:08 arrdem: np

1:24 andrewchambers: BAMbanda: it might be a bit of an undertaking in any language, you gotta do the tradeoff analysis

1:24 thats all

1:25 arrdem: read soem of your blog, cool stuff

1:26 that thing about startup secrecy is true

1:27 arrdem: yeah don't get me started on that

1:28 "I'm doing a startup because I have an idea and money and I can so I'm hiring a technical contractor because no skillz" people can go die

1:28 andrewchambers: haha, I wanted to do a startup, but I'm not the web programming type of person. I always liked compilers etc.

1:29 and hardware

1:30 I havent really had the problem of people asking me to write software for their next big idea luckily :P

1:31 arrdem: I'm fine with people who have ideas... the nontechnical founder thing is just a huge warning light to me.

1:32 glorbon: hey um.. does clojure compile to byto-code or to java?

1:32 arrdem: glorbon: jvm bytecode

1:32 glorbon: any good resources on that

1:32 arrdem: glorbon: and "compile" is generous. AOT compilation of Clojure is rare, 99% of the time Clojure is dynamically compiled.

1:32 glorbon: depends on what you're interested in.

1:32 glorbon: good enough for me

1:33 im just interested in compilation of functional langs to assembler-like languages

1:33 arrdem: hum...

1:33 there's really not a whole lot that's interesting (IMO) to say about Clojure

1:34 most of it's implementation is driven by JVM details

1:34 frankly I'd probably find a simpler language with better implementation docs because clojure literally has none.

1:34 and I say that having built a compiler for Clojure this summer

1:35 glorbon: I suspected as much

1:36 arrdem: I mean... abstractly "compiling" a lisp to a stack oriented architecture or to a dependency graph representation like LLVM ASM is a trivial depth-first traversal

1:36 technically a reverse order one...

1:37 (emit args) (emit op) ...

1:37 glorbon: will this be optimized enough thou?

1:37 arrdem: depends on your definition of optimisation

1:37 glorbon: Im wondering like which tricks the hakell/julia/SBCL ppl are using

1:37 arrdem: different program transforms are visible at different levels of abstraction

1:38 a typical "real" compiler will have three or four entire intermediary languages or "representations" with different properties

1:38 each designed to enable some specific class of transformation

1:38 glorbon: example?

1:39 arrdem: a lambda calculus representation for typechecking and typecheck removal

1:39 an ASM representation for stack management and register spilling

1:39 note that neither of these two is possible (or at least reasonable) at the other's level of abstraction

1:40 glorbon: got any resources?

1:40 arrdem: nope. all this shit is implementation/language specific.

1:40 the GHC folks have a huge collection of papers

1:40 BAMbanda: andrewchambers, web programming is much more loose and easier to see fruits

1:41 if you understand compilers, and you appreciate type inference from languages like clojure, you'll do fine

1:41 what industry is your startup seeking to be a part of?

1:41 arrdem: BAMbanda: wat we don't have any type inference. Literally everything is dynamically checked.

1:41 core.typed has zero impact on emitted bytecode

1:42 BAMbanda: arrdem, ahh i guess i used the wrong terminology, so its being checked and we don't have to explicitly mention the type

1:42 arrdem: type annotations also have no impact except on code which is typed to JVM primitives (long, int, float) not to Objects (Long, Int, Float)

1:43 BAMbanda: hmmm

1:43 glorbon: arrdem: thanks

1:43 arrdem: it is rarely if ever actually checked by the Clojure language. the Clojure implementation will eventually take an object and attempt to cast it to an instance of something specific and that's what you'll see fail.

1:43 this pervasive lack of checking is done in the interests of "speed" and JIT performance.

1:44 this also means that debugging Clojure really means reading shitty stacktraces to determine what the real error was and where it occured because it isn't local to the true source.

1:50 amalloy: arrdem: do you actually know that the reason typehints are not acted on until it comes time to invoke methods is to improve speed? i always figured it was because it's easier to generate that bytecode; and i would expect the current approach to be generally slower than storing stuff with the right types all along

1:51 arrdem: amalloy: I don't to be honest. I presume it's to simplify the implementation.

1:52 amalloy: arguably it also doesn't matter before that point... the only real question is whether an invokePrimitive is legal or whether the normal invoke must be used.

1:58 Blorgon: arrdem: how did u become expert on FP compilation?

2:00 amalloy: arrdem: i hadn't actually read the backlog - are you really claiming that "type annotations also have no impact except on code which is typed to JVM primitives (long, int, float) not to Objects (Long, Int, Float)"?

2:00 obviously typehints cause non-reflective code to be emitted

2:02 arrdem: you're correct. that didn't come to mind. 90% of my work was with the calling convention which entirely ignores typehints except on primitives.

2:02 * arrdem 1am, post-drinking

2:02 * arrdem bed

2:04 andrewchambers: any clojurists here from NZ ?

4:10 noncom|2: when using clojure.java.api and invoking, for example, a (vector) IFn, then how do i work with this vector back in java ?

4:11 the "invoke" returns an Object which implies casts which imply time penalties.. am i right?

5:13 justin_smith: noncom|2: there is an overhead for downcasts (narrowing) - it always involves runtime checks iirc.

7:23 noncom|2: justin_smith: thanks :)

8:33 clojer: This list comp: (for [l list-of-lists plan (keyword (first l)) deg (Integer/parseInt (second l)) sign (signs (keyword (first (rest (rest l))))) min (Integer/parseInt (second (rest (rest l)))) long (Float/parseFloat (last l))] {plan {:sign sign :deg deg :min min :long long}})

8:34 ... keeps giving me an error : "Don't know how to create ISeq from: clojure.lang.Keyword"

8:34 ... but all the bindings work when I test them in the repl

9:12 justin_smith: $ping

9:13 ,:ping

9:13 clojurebot: :ping

9:54 martinklepsch: When making a library it's probably good to keep dependencies as minimal as possible. Now I need a date like "2014-01-02T00:00:00.000Z" and could use regular Java stuff or clj-time

9:55 justin_smith: martinklepsch: meaning a string like that from a date, or a date like the one that string represents?

9:55 ,(java.util.Date.)

9:55 clojurebot: #inst "2014-08-30T13:55:18.770-00:00"

9:55 martinklepsch: justin_smith: a string like that

9:56 justin_smith: ,(str (java.util.Date.))

9:56 clojurebot: "Sat Aug 30 13:55:45 UTC 2014"

9:56 justin_smith: hrm

9:56 ,(pr-str (java.util.Date.))

9:56 clojurebot: "#inst \"2014-08-30T13:55:53.569-00:00\""

9:56 martinklepsch: (from a date created like this: new Date(System.currentTimeMillis()+5*60*1000))

9:57 justin_smith: martinklepsch: isn't that the same thing the constructor gives you for no argument?

9:57 (as in my above examples)

9:58 shiranai_: justin_smith: with no args it's equivalent to System.currentTimeMillis

9:58 (or what am i missing here? :p)

9:58 martinklepsch: ,(java.util.Date. (.currentTimeMillis System))

9:58 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: currentTimeMillis for class java.lang.Class>

9:58 justin_smith: shiranai_: got it, my reading comprehension fail

9:59 martinklepsch: static method

9:59 martinklepsch: justin_smith: I need the string of a time n minutes from now

9:59 shiranai_: alrighty :p

9:59 justin_smith: ,(java.util.Date. (+ (System/currentTimeMillis) (* 5 60 1000)))

9:59 clojurebot: #inst "2014-08-30T14:04:25.795-00:00"

10:00 shiranai_: martinklepsch: can you use a SimpleDateFormat, for example? (java.util.SimpleDateFormat "dd.MM.yyyy") .. then (.format simpleDF (Date. <millis>)) .. ?

10:00 justin_smith: the thing is, the default print method for #inst is the format he wants

10:00 isn't it?

10:00 shiranai_: i'm not sure :)

10:01 justin_smith: I mean minus the #inst part

10:01 shiranai_: but at least by explicitly using a DateFormat, he can get exactly the format he wants

10:01 justin_smith: true that

10:02 anyway, this is definitely all doable without any libs, just using a small amount of interop

10:02 shiranai_: yeah

10:02 Java

10:02 lkasjdsd

10:02 Java's got quite a few batteries included :p

10:03 there was some new Date stuff in Java 1.8, i think

10:03 justin_smith: yup

10:24 martinklepsch: justin_smith, shiranai: thanks a lot, found a neat solution with your help I think

10:29 shiranai_: martinklepsch: kein problem :p

10:31 martinklepsch: https://gist.github.com/3bec2f54456a2bcd274b

10:31 shiranai_: danke sehr

10:31 :)

10:32 shiranai_: :P

10:33 hmm.. i didn't know "danke sehr" was an expression in German.. but either it is, or i was mistaken about you being German-speaking :P

10:33 but yeah, it looks like you found a solution :)

10:34 (my German is very poor anyway :p)

10:34 martinklepsch: shiranai_: it's old-school german. the type of german things you say when you want it to sound very german

10:34 shiranai_: ohh, ok :p

10:34 so it's like Sehr-Hoch Deutsch or something.. ? :P

10:36 martinklepsch: I guess you could say so. It's "altbacken".

10:36 (another great german word)

10:40 I'm trying to build a library for clojurescript that helps you with uploading files to S3 right from the browser. It consists of one function you plug in somewhere in your ring app and some clojurescript handling change events on the input and signing/uploading of files.

10:41 I use core.async a bit but don't feel like I really understood it yet and so I'm wondering what might be the best API to expose that sort of functionality. it's embedded in Om right now but that's probably not necessary

10:41 here is some of the code including my amateur core.async usage: https://gist.github.com/mklappstuhl/4d731346e7693b6401a3

10:42 any code review or advice would be greatly appreciated

10:47 justin_smith: martinklepsch: in your timestamp function, couldn't the second let binding be moved into the function body since it is only there for side effects anyway?

10:47 I mean now-plus

10:49 oh, I was about to edit it and see it is changed already :)

10:49 martinklepsch: justin_smith: yeah just did it :)

10:50 I thought it looks nice because I was thinking that I'd have to integrate it into the second form but you're right, since it's just for side effects I can just rely on (do ... )

10:50 *looks better

10:55 shiranai_: martinklepsch: btw, i may be missing something here, but it might be a good idea to leave out setting the timezone to GMT.. afaik it's easier to work with dates if you handle timezones when *displaying* dates, not when manipulating them

10:55 ohhh.. and GMT is just UTC anyway.. so i'm not sure if that even changes anything :P

10:56 (unless there's a system setting for another time-zone and that gets used without specifying a timezone separately, etc)

10:56 martinklepsch: shiranai_: I needed the time as a string in GMT (see here: http://aws.amazon.com/articles/1434/?tag=vig-20 search for "GMT")

10:57 Date. gives you the current timezone and that wasn't what S3 required

10:57 shiranai_: martinklepsch: yeah i guess that would be the system timezone then

10:58 i seemed to remember UTC being the default.. i think that's what the "Z" signifies in the date string

10:58 but alright :p

11:06 justin_smith: TimMc: were you the one with the easier to use frontend to clojure.reflect?

11:18 nomad111: hi folks, trying to start using clojure. I would like to use it to build distributed computation workflow. Currently I am only aware of Apache Storm that is tailored to do this. Are there any libs or frameworks in the Clojure ecosystem that I should also consider?

11:19 justin_smith: nomad111: I talked to some folks that were running clojure on hadoop

11:19 nomad111: my understanding is that hadoop is intended for large workloads

11:20 justin_smith: nomad111: clojure can use anything made for the jvm

11:20 or maybe it would be better to say anything made for the jvm can use clojure

11:20 nomad111: yes im aware of this, my problem with storm is the lack of documentation to get started with clojure

11:20 bbloom_: technomancy: was it you i was discussing semver with? or maybe i was just generally bitching about it in here... anyway, i laughed hard at this: https://gist.github.com/jashkenas/c71021bba8ee580ded92

11:21 justin_smith: nomad111: have you seen this? http://storm.incubator.apache.org/documentation/Clojure-DSL.html

11:21 storm explicitly supports clojure

11:21 nomad111: ye that’s basically the only docco there is

11:21 and some sample code on github

11:21 referenced in that article

11:22 justin_smith: OK - I can't help you with anything more specific, maybe someone else here can

11:22 nomad111: all good. only looking to have some more options to evaluate

11:23 justin_smith: https://github.com/yieldbot/marceline ahh - the people I was talking to about hadoop also made this

11:23 memory finally clicking...

11:23 you should probably look at all yieldbot's projects actually

11:23 nomad111: brilliant, thanks!

11:24 justin_smith: nomad111: they had great things to say about the massive amounts of data and low latencies they were getting with this setup

11:25 and looking at their people, it was specifically Soren Macbeth

11:27 dawkirst: from a newcomer's

11:28 perspective: Programming Clojure or Clojure Programming?

11:39 lgrapenthin: dawkirst: Programming Clojure

11:52 martinklepsch: Is there some rule of thumb about the number of go blocks one should use for a given problem? I want to do something like (listen to events, asynchronously run functions with events as args (pipeline-like), return results)

11:53 justin_smith: martinklepsch: for that, I would say N g blocks grabbing events and running functions, and one collecting results

11:53 N is determined based on whether the task is IO vs. CPU bound, how many CPUs you have, etc.

11:53 martinklepsch: so with one event type that would make 2 go blocks?

11:53 io-bound (uploading files)

11:53 justin_smith: the adding of events to the queue doesn't need to be in a block, of course

11:54 yeah, if you are io-bound, two blocks should suffice (unless you are hitting multiple hosts or whatever)

11:55 martinklepsch: one host. when there are a lot of events I'd like to parallelize stuff but I guess that's not of interest right now

12:12 lgrapenthin: martinklepsch: justin_smith: Shouldn't the amount of cores only factor in when using threads?

12:27 jeffterrell: rkneufeld: Thanks for the lein-try plugin. Pretty useful!

12:50 Rapp: hi everybody

12:50 i am fairly new to clojure. i have produced something of this kind: #<String[] [Ljava.lang.String;@6bb7b3fb>

12:50 i think this is supposed to be some kind of string array?

12:52 i produced it like this: (-> "a b c" .toUpperCase (.replace "C" "X") (.split " ") )

12:53 bbloom_: ,(into-array String ["yup" "like" "this"])

12:53 clojurebot: #<String[] [Ljava.lang.String;@e2a718>

12:53 bbloom_: ,(class (into-array String ["yup" "like" "this"]))

12:53 clojurebot: [Ljava.lang.String;

12:53 bbloom_: at that point, normal java operations can be applied to strings

12:53 Rapp: thanks bbloom_

12:53 i was wondering if i could continue the -> threading afterwards.

12:54 however, trying to do a (map println) failed.

12:54 however, i could wrap (map println ...) around the whole form

12:54 bbloom_: Rapp: you can also use http://clojure.github.io/clojure/clojure.string-api.html for more portable, clojure-ish string operations

12:54 Rapp: bbloom_: thanks for the hint. i am more trying to understand core clojure concepts, like the -> macro in this case

12:55 so actually, my question is: why does this work:

12:55 (map println (-> "a b c" .toUpperCase (.replace "C" "X") (.split " ") ))(map println (-> "a b c" .toUpperCase (.replace "C" "X") (.split " ") ))

12:55 sorry. twice pasted

12:55 and not this:

12:55 bbloom_: a few things

12:55 1) map is lazy and pritnln is an effect

12:55 ,(do (map print (range 10)) nil)

12:55 clojurebot: nil

12:56 bbloom_: ,(do (take 2 (map print (range 10))) nil)

12:56 clojurebot: nil

12:56 Rapp: (-> "a b c" .toUpperCase (.replace "C" "X") (.split " ") (map println ))

12:56 bbloom_: ,(take 2 (map print (range 10)))

12:56 clojurebot: (0123456789nil nil)

12:56 Rapp: ah yes...

12:56 of course

12:56 bbloom_: Rapp: -> threads to the *first* argument, so you're writing (map XXX println)

12:56 not (map println XXX)

12:57 Rapp: if you want to traverse a sequence for effects, use doseq

12:57 Rapp: bbloom_: first argument... yes, it says so in the docs... of course...

12:57 bbloom_: (doc doseq)

12:57 clojurebot: "([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."

12:57 bbloom_: Rapp: there's also ->>

12:57 Rapp: allright! thanks!

12:57 bbloom_: but you're better off using let bindings when things get hairy in a long chain

12:57 Rapp: yes, i saw that, but have not read the docs yet ;)

12:57 bbloom_: there's also ##(doc ..) for interop with jvm objects

12:57 (doc ..)

12:58 clojurebot: "([x form] [x form & more]); form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand."

12:59 Rapp: (doseq [x (-> "a b c" .toUpperCase (.replace "C" "X") (.split " "))] (println x))

12:59 this works nice :)

13:00 thanks bbloom_! learned a lot already!

13:00 bbloom_: ,(into [] (-> "a b c" .toUpperCase (.replace "C" "X") (.split " "))) ; if you need the values out

13:00 clojurebot: ["A" "B" "X"]

13:00 bbloom_: or just:

13:01 ,(seq (-> "a b c" .toUpperCase (.replace "C" "X") (.split " "))) ; seq works on arrays

13:01 clojurebot: ("A" "B" "X")

13:01 bbloom_: ,(-> "a b c" .toUpperCase (.replace "C" "X") (.split " ") seq) ; to continue the chain

13:01 clojurebot: ("A" "B" "X")

13:02 bbloom_: ,(require 'clojure.string)

13:02 clojurebot: nil

13:02 bbloom_: ,(alias 's 'clojure.string)

13:02 clojurebot: nil

13:02 bbloom_: ,(-> "a b c" s/upper-case (s/replace "C" "X") (s/split #" "))

13:02 clojurebot: ["A" "B" "X"]

13:02 bbloom_: ^^ avoiding the jvm interop

13:05 Rapp: hmhm. yes, avoiding the jvm interop seems more clojure'y :)

13:09 Bronsa: Rapp: btw map does work on arrays

13:11 ,(map identity (object-array ["foo" "bar"]))

13:11 clojurebot: ("foo" "bar")

13:14 justin_smith: Bronsa: how does object-array compare to into-array?

13:14 is it that into-array tries to make a more specific array type?

13:15 Bronsa: justin_smith: yes, into-array takes the type of the first element and uses that to construct an array

13:16 ,(class (object-array ["foo"]))

13:16 clojurebot: [Ljava.lang.Object;

13:16 Bronsa: ,(class (into-array ["foo"]))

13:16 clojurebot: [Ljava.lang.String;

13:16 justin_smith: cool

13:16 Bronsa: ,(object-array ["foo" 1])

13:16 clojurebot: #<Object[] [Ljava.lang.Object;@32177e>

13:16 Bronsa: ,(into-array ["foo" 1])

13:16 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: array element type mismatch>

13:17 Bronsa: ^ colls handed to into-array must obviously be homogeneous

13:18 bbloom_: Bronsa: into-array is poorly designed :-/

13:18 ,(class (into-array []))

13:18 clojurebot: [Ljava.lang.Object;

13:18 bbloom_: ,(class (into-array [1]))

13:18 clojurebot: [Ljava.lang.Long;

13:18 bbloom_: argh.

13:18 if not specified, array of objects is the only thing that makes sense

13:18 taking teh type of the first value is insane

13:18 justin_smith: ,(into-array Integer/TYPE [1])

13:18 clojurebot: #<int[] [I@120f5c9>

13:18 Bronsa: bbloom_: agreed

13:19 bbloom_: but it's kinda sorta convenient I guess

13:19 bbloom_: Bronsa: nope.

13:19 Bronsa: bbloom_: you can always use object-array if you actually want an Object[]

13:20 bbloom_: (doc object-array)

13:20 clojurebot: "([size-or-seq]); Creates an array of objects"

13:20 bbloom_: (doc into-array)

13:20 clojurebot: "([aseq] [type aseq]); Returns an array with components set to the values in aseq. The array's component type is type if provided, or the type of the first value in aseq if present, or Object. All values in aseq must be compatible with the component type. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE."

13:20 bbloom_: i'd just eliminate into-array/1

13:20 that overload isn't needed at all :-P

13:21 Bronsa: right, it's not needed, but I'm cool with doing (into-array [(SomeIncrediblyLongJavaClass. "foo")])

13:22 bbloom_: ,(def S java.lang.String)

13:22 clojurebot: #'sandbox/S

13:22 bbloom_: ,(into-array S ["abc"])

13:22 clojurebot: #<String[] [Ljava.lang.String;@ae15ce>

13:23 bbloom_: ,(S. "abc") ; does this work? i don't think it does...

13:23 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: S, compiling:(NO_SOURCE_PATH:0:0)>

13:23 bbloom_: yeah

13:24 justin_smith: ,(new S "hello") ; nor thing

13:24 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: S, compiling:(NO_SOURCE_PATH:0:0)>

13:24 justin_smith: *this

13:26 ,(-> [] clojure.reflect/reflect :bases) ; TIL

13:26 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.reflect, compiling:(NO_SOURCE_PATH:0:0)>

13:26 justin_smith: ,(require 'clojure.reflect)

13:26 clojurebot: nil

13:26 justin_smith: ,(-> [] clojure.reflect/reflect :bases) ; TIL

13:26 clojurebot: #{clojure.lang.APersistentVector clojure.lang.IObj clojure.lang.IEditableCollection}

13:26 Bronsa: that'd need to be compiled into a reflective call rather than using the bytecode for new

13:26 bbloom_: Bronsa: right

13:27 Bronsa: although in theory it could compile in to a reflective call if the class isn't statically known & warn like other operations

13:27 Bronsa: bbloom_: yeah

13:27 bbloom_: Bronsa: but i think there's actually a syntactic ambiguity in that case

13:27 i forget exactly, but i ran in to some weird edge case w/ package names or something

13:28 Bronsa: no I don't think so. Classes are always resolved before locals/var lookups

13:28 justin_smith: arrdem: grimoire is giving me a bad gateway error

13:28 Bronsa: ,(let [String 1] String)

13:28 clojurebot: 1

13:28 Bronsa: oh well. I'm wrong.

13:28 bbloom_: heh

13:28 Bronsa: ,(def String 1)

13:28 clojurebot: #<CompilerException java.lang.RuntimeException: Expecting var, but String is mapped to class java.lang.String, compiling:(NO_SOURCE_PATH:0:0)>

13:28 Bronsa: pff

13:28 arrdem: justin_smith: kay. I'll look into it

13:29 Bronsa: ,(intern *ns* 'String 1)

13:29 clojurebot: #<SecurityException java.lang.SecurityException: denied>

13:29 doctorm: Anyone use vim-fireplace? I’m getting a weird error “Vim(python):Traceback (most recent call last): “ instead of a clojure stack trace like described in the documentation when I evaluate a form that throws an exception.

13:29 Evaluating forms that don’t throw an error works fine

13:30 This is using cpp

13:30 arrdem: justin_smith: kicked the webserver, it's back up. looks like the JVM actually crapped out somehow

13:31 justin_smith: arrdem: interesting - with any luck you have logs

13:31 arrdem: justin_smith: not as good logs as you'd think

13:31 school work stuff to do today but 75% of the next Grimoire release is gonna be logs and stability shit

13:32 justin_smith: one of the few advantages of using a container like Tomcat - you have to work pretty hard to prevent extensive logging

13:33 arrdem: true. one issue with the 0.3.4 build is that I can't uberjar it for something like tomcat

13:33 it relies on File.exists

13:33 justin_smith: a quick hack - run from nohup with a timestamped output file name

13:33 arrdem: tomcat unzips the uberwar

13:33 arrdem: I already have logs, I just need to add a log rotation system

13:33 justin_smith: ahh

13:34 dbasch: arrdem: if you’re running on an aws micro, the kernel probably killed the jvm

13:35 arrdem: dbasch: digitalocean

13:35 dbasch: arrdem: free tier?

13:36 arrdem: dbasch: lowest paid. same node I use for this IRC connection among other things.

13:36 dbasch: arrdem: same thing then, the kernel must have killed your jvm

13:36 justin_smith: #butdoesitscale

13:36 arrdem: dbasch: the kernel shouldn't be wandering around whacking off long running pss...

13:36 dbasch: arrdem: it shouldn’t but it does

13:36 * arrdem has never seen this shit before

13:37 justin_smith: it will whack things that exceed your allocated resources, right?

13:37 arrdem: meh

13:37 dbasch: arrdem: https://www.kernel.org/doc/gorman/html/understand/understand016.html

13:37 justin_smith: for example, the kernel will overcommit, but when memory actually runs out, the program trying to access the new memory gets slain

13:38 arrdem: right. bah.

13:38 goddamnit I don't want to memory profile this shit

13:38 * arrdem checks he's not using memoize

13:38 dbasch: arrdem: just have a watcher that restarts it

13:38 arrdem: dbasch: that'd work.

13:39 justin_smith: dbasch: I know that works, but that reminds me of ruby in ways I don't like

13:39 arrdem: hum. looks like I'm memoizing the cheatsheet and the namespace pages...

13:39 those should be almost free

13:40 not like I'm caching literally every symbol

13:46 justin_smith: TIL there is such thing as a permutohedron

13:46 which makes me very happy

13:47 (graph where every node is a corner describing a polyhedron, and edges are swaps of elements to get from one permutation to the next)

13:47 s/edges/vertexes oops

14:11 teslanick: I'm trying to get a clojure app to start on heroku, but it's giving me the most useless exception ever -- has anyone ever seen this? https://gist.github.com/nhusher/fa7ed3c6a8b2f98e2352

14:12 I've run other clojure apps in heroku, and their example app starts just fine. My sailcloth app runs just fine locally (lein run / java -cp ...).

14:12 But it crashes on heroku

14:12 justin_smith: teslanick: and that's definite an uberjar?

14:13 *definitely

14:14 teslanick: Fairly sure

14:14 justin_smith: well, I guess if java -cp ... works locally

14:14 teslanick: https://gist.github.com/nhusher/fa7ed3c6a8b2f98e2352#file-z-build-log-txt - that's the result of pushing to the heroku remote

14:15 Wait a second, I think it might be building into the wrong directory

14:16 justin_smith: wouldn't java complain about the jar you specify in the path not being there?

14:16 teslanick: I would think so

14:17 justin_smith: java -jar foo.jar version => "Error: Unable to access jarfile foo.jar"

14:18 teslanick: Yeap. For whatever reason, locally it was putting the uberjar named "sailcloth-standalone.jar" into "target", but on heroku, it was putting it into "target/uberjar/..."

14:18 Thanks for being my rubber duck. :|

14:18 * justin_smith quacks.

14:19 teslanick: http://sailcloth.herokuapp.com/weather-data/44.4758/-73.2119

14:22 justin_smith: well, that sure is some weather data

14:23 teslanick: Powered by forecast.io, but the forecast.io webapp and darksky (based on the same api) both have lousy wind speed forecasts. I want something to give me a "sailing forecast" for the next 7 days.

14:24 justin_smith: cool

14:44 samflores: is there some core function that returns a coll of values from a map based on provided keys? something like (pseudo-get {:k1 1 :k2 2 :k3 3} [:k3 :k1]) ;; => [3 1]

14:46 Duke-: ,(vals (select-keys {:k1 1 :k2 2 :k3 3} [:k3 :k1]))

14:46 clojurebot: (1 3)

14:47 Duke-: hmm, wrong order...

14:47 rhg135: maps have no defined order though

14:48 i wouldn't be surprised at this behavior

14:48 Bronsa: rhg135: but the vector he's using does

14:49 Duke-: yeah I guess it should print it in the order of the select-keys vector

14:49 rhg135: true

14:49 * gfredericks hellos

14:50 Bronsa: ,(mapv {:k1 1 :k2 2 :k3 3} [:k1 :k2])

14:50 clojurebot: [1 2]

14:50 Bronsa: samflores: ^

14:50 ephemeron: samflores: Why not just map the hashmap over the keys?

14:50 …as above.

14:50 samflores: damn, I keep forgeting the keys are functions

14:51 :D

14:51 thanks

14:51 Bronsa: samflores: in this case the map is a function

14:51 gfredericks: ,((juxt :k1 :k2) {:k1 1 :k2 2 :k3 3})

14:51 clojurebot: [1 2]

14:51 Bronsa: ^ in this case the keywords are instead

14:54 samflores: didn't know juxt. very clever

15:03 avi__: ,(juxt :k1 :k2)

15:03 clojurebot: #<core$juxt$fn__4304 clojure.core$juxt$fn__4304@7d68>

15:04 avi__: ah

15:04 ,((juxt :k1 :k2) {:k1 :kv1})

15:04 clojurebot: [:kv1 nil]

15:04 avi__: nice

15:12 gfredericks: ,((juxt inc dec) 41)

15:12 clojurebot: [42 40]

15:12 gfredericks: ,(map (apply juxt (map (partial partial +) (range 5))) (range 5))

15:12 clojurebot: ([0 1 2 3 4] [1 2 3 4 5] [2 3 4 5 6] [3 4 5 6 7] [4 5 6 7 8])

15:13 gfredericks: I'm gonna try to create a variant of the lazy-seq macro that lets you refer to the seq itself

15:14 e.g., (defn cycle [coll] (rec-lazy-seq [s] (concat coll s)))

15:16 that was easier than I thought

15:18 (defn repeat [x] (rec-lazy-seq [s] (cons x s)))

15:19 (def fib (rec-lazy-seq [s] (list* 0 1 (lazy-seq (map + s (rest s))))))

15:26 doctorm: Can someone explain to me (a newbie) why when the up function is called, none of the tables are created, but when I wrap (create-all-tables spec) with (pprint (create-all-tables spec)) it works? https://www.refheap.com/89606

15:27 AimHere: doctorm, map is lazy

15:27 doctorm: AimHere, I figured it might be something like that, is there some other function I should use?

15:28 What’s the idiomatic way to say “execute this vector of function using these arguments"

15:28 AimHere: Are you actually wanting to evaluate the results of create-table-foo?

15:28 doctorm: I just need them to fire

15:28 justin_smith: doctorm: doseq if you don't need the result values

15:28 doctorm: justin_smith: great, thanks

15:28 rhg135: mapv

15:28 justin_smith: rhg135: why make a vector you will never use?

15:28 rhg135: returns a (non-lazy) vector

15:29 lazinesss justin_smith

15:29 doctorm: rhg135: Good to know though, thanks

15:29 rhg135: as in programer laziness

15:29 justin_smith: if you want the syntax of map, but without the laziness, and don't need the result, use (comp dorun map)

15:29 rhg135: don't do it though

15:29 dorun the lazyseq

15:29 justin_smith: right

15:30 but usually the syntax of doseq is easier to use anyway

15:30 rhg135: it should be a core function

15:30 would be small

15:30 just a convenience rally

15:30 jeffterrell: Wow, just found a bug in a combination of `prefer-method` and `clojure.tools.namespace.repl/refresh`: http://dev.clojure.org/jira/browse/TNS-23

15:30 rhg135: really*

15:31 justin_smith: rhg135: (def domap (comp dorun map))

15:31 rhg135: exactly

15:31 i know i've use it enough

15:32 does dorun hold the head of the seq?

15:32 justin_smith: absolutely not

15:32 it never even creates the seq

15:32 rhg135: k good, i can never remember if it's dorun or doall

15:33 justin_smith: doall holds the head, yes

15:33 and mapv is equivalent to doall map, except you also get a handy vector datatype out of the deal

15:40 rhg135: i see

15:44 justin_smith: which is even worse for heap usage than holding onto the head would be, but it's associative for lookup by index, so it's got that going for it, which is good

15:44 gfredericks: impl of rec-lazy-seq: https://gist.github.com/gfredericks/1fe70ed7cd48f31f6218

15:44 lxsameer: hey guys, is there any lib for creating a proxy server

15:47 gfredericks: I made one way back in the day but it's terrible

15:48 Bronsa: gfredericks: neat

15:49 sameerynho: hey guys, is there any lib for creating a proxy server ( sorry to re-messaged , disconnected )

15:49 Bronsa: (inc gfredericks)

15:49 :(

15:50 gfredericks: Bronsa: the one time I get karma for something other than telling jokes

15:50 justin_smith: sameerynho: wouldn't a proxy-server be more of an app than a lib? or is there really that much to customize about a proxy server that you would have a general lib for making them?

15:50 Bronsa: gfredericks: blame it on Raynes

15:52 sameerynho: justin_smith: you're right, but I have to write one

15:54 justin_smith: is there any networking lib ? like twisted of python or event machine for Ruby or even natty ?

15:55 justin_smith: sameerynho: the jvm comes with everything you strictly need, though clj-http makes it easier to use (and pulls in some apache commons libs too)

15:56 gfredericks: not going to be able to serve requests with clj-http

15:57 sameerynho: justin_smith: I'm a clojure rookie and never used jvm before, What do you suggest me ? Natty or Clj-http or anything else

15:57 justin_smith: definitely clj-http

15:58 Blorglorbon: ,(apply str (concat (drop-last "gtg") (vector "zzz")))

15:58 clojurebot: "gtzzz"

15:59 sameerynho: thanks dude

16:33 amalloy: (inc gfredericks) ; Bronsa

16:33 lazybot: ⇒ 84

16:35 Bronsa: (inc gfredericks) ; there, take an extra one

16:35 lazybot: ⇒ 85

16:36 Bronsa: also

16:36 (dec lazybot) stop being a lazy bot

16:36 justin_smith: (dec lazybot)

16:36 lazybot: ⇒ 29

16:36 Bronsa: uh

16:36 justin_smith: Bronsa, did you get ignored?

16:36 Bronsa: $karma

16:37 $karma justin_smith

16:37 lazybot: justin_smith has karma 70.

16:37 Bronsa: no

16:37 justin_smith: maybe lazybot has a throttler

16:37 justin_smith: perhaps you are restricted from using inc/dec

16:37 I think there is for karma, yeah

16:39 Bronsa: justin_smith: I just inc'd gfredericks

16:39 justin_smith: oh, I missed that

16:40 arohner: gfredericks: what are your requirements for the proxy server?

16:40 I happen to be writing one atm

16:42 amalloy: Bronsa: the parser for inc/dec is just really basic. if you have trailing stuff that isn't commented out, he doesn't like it

16:42 Bronsa: ah

17:18 benzap: so i'm trying to apply arguments to optional args area of a function, how does one do this?

17:19 like, (defn foo [& args]) (apply foo [:bar true])

17:23 ,(defn foo [& args] args) (apply foo [:bar true])

17:23 clojurebot: #'sandbox/foo

17:24 benzap: ,(apply foo [:bar true])

17:24 clojurebot: (:bar true)

17:24 benzap: so it appears my problem has something to do with clojurescript, and not clojure

17:53 avishai: using mijde, i need to make a metaconstant behave like a seq

17:53 e.g. to make (when (seq x)) happy

17:58 (seq ..m..) => (list ..m..) make midje hang

18:01 johnwalker: what is ..m.. ?

18:03 avishai: a metaconstant

18:13 gfredericks: arohner: that wasn't me

18:13 amalloy: Bronsa: thanks guys I'm gonna use the karma to help pay down my karma-mortgage

18:13 arohner: gfredericks: ah, you're right. my mistake

18:14 TEttinger: I'm a bit confused here...

18:14 ,(with-bindings {*print-length* 10} (iterate inc 0))

18:14 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Var>

18:14 amalloy: TEttinger: the binding only lasts long enough to eval it, not print it

18:14 Bronsa: TEttinger {#'*print-length 10}

18:15 TEttinger: what's the proper way to set *print-length* ?

18:15 Bronsa: set!

18:15 TEttinger: ,(do (set! *print-length* 10) (iterate inc 0))

18:15 clojurebot: (0 1 2 3 4 5 6 7 8 9 ...)

18:15 TEttinger: ##(do (set! *print-length* 10) (iterate inc 0))

18:15 lazybot: java.lang.SecurityException: You tripped the alarm! set! is bad!

18:15 TEttinger: hm

18:15 maybe not

18:17 the exact context is a way to do this on lazybot to show a way around infinite loops in languages with macros

18:18 verma: do I have to wait for CLojure 1.7 to use transducers?

18:18 Bronsa: verma: you can use the alphas

18:18 alpha1 is already out

18:19 verma: Bronsa, not sure if I should be doing that for semi-production stuff

18:19 TEttinger: clojurebot already uses it, it seems quite stable so far

18:19 Bronsa: alpha2 might come out soon according to Alex Miller

18:19 verma: alpha1 is really just 1.6 + transducers

18:19 verma: Bronsa, oh ok then, I am convinced ;)

18:19 Bronsa: the only other thing that changed is how keywords/symbols are interned, internally

18:20 fifosine: I have a list of elements with which each I perform a series of functions using doseq. I also need to perform functions *between* each element (i.e. if I'm operating on (range 3), I need to execute functions between 0 and 1 and between 1 and 2). How would I go about doing this?

18:20 Bronsa: verma: transducers might still have bugs though

18:20 verma: Bronsa, oh, are they deemed stable in clojurescript?

18:21 TEttinger: fifosine, what argument would the between function take?

18:21 0.5 ?

18:22 fifosine: TEttinger: No, the function takes no arguments.

18:22 I'm thinking about using interpose?

18:22 by creating a list of function calls

18:22 Bronsa: verma: I don't really know, but their implementation is pretty much the same as clojure's

18:23 fifosine: I'm wondering, does this require the backtick? I don't have much experience using it

18:25 Bronsa: verma: they should be stable enough though. The only bug reported until now was about comparing a lazy seq produced with a transducers with another lazy seq, a fix for that will be in the next alpha

18:25 fifosine: TEttinger: Does what I'm asking make sense? In the (range 3) example, I'm thinking of creating a list like ((func 0) (no-arg) (func 1) (no-arg) (func 2)). How do I create this list without evaluating the functions?

18:26 Bronsa: also I believe there will be performance enhancements for some transducer functions in the next alpha, there are a bunch of tickets for that on JIRA that people are working on

18:26 fifosine: And then do I use doseq to eval the list of funcs?

18:26 verma: Bronsa, hmmm, nice, thanks

18:28 fifosine: ,(doseq [foo (for [x (range 3)] `(println x))] (eval foo))

18:28 clojurebot: #<CompilerException java.lang.RuntimeException: No such var: sandbox/x, compiling:(NO_SOURCE_PATH:0:0)>

18:28 fifosine: How do I correct this mistake

18:29 TEttinger: ,(doseq [foo (for [x (range 3)] '(println x))] (eval foo))

18:29 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)>

18:29 TEttinger: hm

18:29 fifosine: While keeping the creation of a list of function calls

18:29 Bronsa: fifosine: you want ~x instead of x, but even then it won't make sense

18:29 ,(for [x (range 3)] `(println ~x))

18:29 clojurebot: ((clojure.core/println 0) (clojure.core/println 1) (clojure.core/println 2))

18:29 fifosine: And then how do you eval that list

18:29 weavejester: The function calls need to be symbols, they can’t be function objects (unless you look in the metadata I guess).

18:29 Bronsa: fifosine: why do you want to do that?

18:30 amalloy: fifosine: don't create a list and eval it; create a lambda and call it

18:31 weavejester: It also depends on whether you want this in a macro or not

18:31 fifosine: Bronsa: The original problem is: for a list of elements, I need to perform a series of functions via doseq for each element, but also I need to perform a no-arg function *between* each element. I thought I could solve this by interposing the list of fn-calls that take args with a list of the no-arg fn and then evaling the list

18:31 weavejester: Does this seems like a problem solved by a macro? I don't have experience writing them so maybe this is a good opportunity to learn

18:31 weavejester: fifosine: Oh, don’t eval - just take advantage of closures

18:31 amalloy: fifosine: no macro

18:31 weavejester: fifosine: No macro is needed

18:32 Bronsa: fifosine: using eval is rarely the right answer, close to never actually

18:32 fifosine: ok, what's the proposed solution then?

18:33 weavejester: fifosine: Just to be clear, is it the one function for all elements?

18:33 Bronsa: fifosine: you can't really do that with doseq, you need to use loop

18:34 weavejester: fifosine: e.g. (foo a) (no-arg) (foo b) (no-arg) (foo c)

18:34 fifosine: weavejester: No, ((foo1 a) (foo2 a) (no-arg)…)

18:34 weavejester: fifosine: Then (foo1 b) (foo2 b) ?

18:34 fifosine: yes

18:35 Bronsa: How will loop solve the interpose problem?

18:36 weavejester: Okay, so ((juxt foo1 foo2) a) will get you [(foo1 a) (foo2 a)]

18:36 Bronsa: fifosine: you can avoid executing no-arg if you're running over the last element

18:36 fifosine: Bronsa: How do you check for last in a loop form?

18:36 weavejester: fifosine: Do you want the no-arg function interposed, or after every set of foos? i.e. will the last form be the no-arg function, or foo2?

18:37 Bronsa: fifosine: (loop [x (range 3)] (when (seq x) (f (first x)) (let [r (rest x)] (when r (no-arg)) (recur r))))

18:37 fifosine: Bronsa: I think the way weavejester is going about it is cleaner

18:37 weavejester: interposed for each pair

18:37 The later in your question

18:38 weavejester: Okay, so… maybe you start with: (map (juxt foo1 foo2) xs)

18:38 fifosine: (foo1 a) (foo2 a) (no-arg) (foo1 b) (foo2 b)

18:38 Bronsa: fifosine: I don't think there's a better way to do it than this

18:39 other alternatives require running over the sequence more than once

18:39 weavejester: That will get you [[(foo1 x1) (foo2 x2)] [(foo1 x2) (foo2 x2)] …]

18:39 Actually… are these side-effectful functions?

18:39 fifosine: weavejester: was just gonna say, yes :/

18:39 weavejester: I had kinda assumed they were pure.

18:39 Bronsa: fifosine: e.g. you could do (doseq [x (butlast y)] (f x) (no-op)), (f (last y))

18:39 fifosine: side-effectful

18:40 Bronsa: no-arg, rather

18:40 weavejester: Oh. Then… it’s just a loop.

18:40 Or a doseq without the last element, as Bronsa mentioned.

18:41 No need to do juxt, map and mapcat interpose.

18:42 arohner: in chrome, I can run "Intl.DateTimeFormat().resolved.timeZone;", and get a value

18:42 amalloy: (doseq [f (interpose no-arg (for [[a b] (partition 2 1 coll)] #(two-arg a b)))] (f)) would be another approach, i think

18:42 arohner: in a weasel repl, I can't resolve "Intl" or (js/Intl). Is that expected?

18:42 (a weasel repl connected in the same chrome tab)

18:43 amalloy: but i confess i haven't kept up with the entire backlog

18:45 weavejester: Out of interest, does anyone happen to know much about Om?

18:45 fifosine: amalloy: Thanks! this is the solution I was looking for.

18:45 arohner: weavejester: I'm using it, but I wouldn't say I know "much" :-)

18:46 Bronsa: amalloy: neat

18:46 weavejester: I’m curious at how the component functions work. Are they called n times a second in some event loop?

18:46 I assume not :)

18:46 arohner: wdym component functions?

18:46 fifosine: amalloy: What's the function of the # symbol here?

18:46 arohner: weavejester: AFAIK, the rendering is event-driven, based on changes to your state

18:47 weavejester: arohner: The functions that return an object that has the IRender or IRenderState protocol

18:47 arohner: I'm reasonably confident they only re-render when you change state

18:48 (or force it to redraw, using low-level API calls)

18:49 weavejester: arohner: So if I change a small part of the state, is Om smart enough to not to re-render components which haven’t been passed changed state?

18:49 arohner: weavejester: I think so

18:50 weavejester: I guess it must do that with om/build combined with the cursors, then...

18:53 arohner: weavejester: yeah. this seems to explicitly say what you expected: https://github.com/swannodette/om/wiki/Cursors

18:54 weavejester: arohner: Ah, so Om constructs a tree and assigns a state cursor to each component. Okay, I think that makes sense.

18:55 Om looks a little magical at first glance. Maybe I’ll suggest to David Nolen that some docs on how Om works behind the scenes might be useful :)

18:57 arohner: yeah, the docs aren't there yet

18:57 and neither are React's

19:22 Guest33092: is there anyway to "single step" through clojure? trace seems to fail to produce output when an exception is raised ..?

19:35 TehShrike: has anyone successfully used Browserify+Clojurescript?

19:44 What's the "Eloquent Javascript" equivalent in Clojurescript?

19:45 ToBeReplaced: TehShrike: I'm not sure there is one... but dnolen's blog posts are a good starting point for cool-things-with-little-code

19:46 TehShrike: as for browserify... i don't know of anyone trying it, but i think most people would tend to avoid it in favor of alternatives

19:47 TehShrike: ToBeReplaced: thanks for the tip - what are the alternatives I should be looking at?

19:48 I'm hoping to use ClojureScript in the browser, but I can't go back to a world where I write client-side code without modules from npm

19:52 benzap: how do I convert a keyword to a string without it keeping the colon?

19:52 nvm, name

19:52 rhg135: ,(name :this)

19:52 clojurebot: "this"

19:53 rhg135: darn lag :D

19:53 ToBeReplaced: TehShrike: i would use the namespace system built in to cljs and if necessary the externs system for other libs

19:53 TehShrike: i haven't reached for npm accessible libs, so i can't comment on how to bring them in effectively

19:57 TehShrike: what do clojurescript peeps use for package management?

19:57 ToBeReplaced: TehShrike: leiningen

19:57 most people use lein-cljsbuild for cljs compilation as well

19:58 TehShrike: Cool, I guess I should get those installed

20:03 oh hey, clojars is handy

20:04 justin_smith: TehShrike: in my experience, leiningen is generally the sane dependency management system that npm could have been

20:05 also check out "lein search" to find things in all your repos, not just clojars

20:05 TehShrike: It's backed by Maven?

20:05 justin_smith: it uses some of the same libs, but it is its own stack

20:05 it uses the same apis though

20:05 TehShrike: interesting

20:06 justin_smith: iow you don't need maven installed for lein to work

20:06 but it can use maven repos, and push to them, etc.

21:22 TimMc: justin_smith: Yeah, org.timmc/handy has a (partial) reflection lib; the o.t.h.repl/show fn is great from the REPL.

21:23 (if I do say so myself)

21:23 justin_smith: ahh, I remembered correctly then

21:24 TimMc: question was brought up by this so post http://stackoverflow.com/q/25583694/2258453

21:26 best answer was iroh https://github.com/zcaudate/iroh which is kind of heavy on syntax / DSL stuff, but has some neat features

23:00 or9ob: Hello folks. I want to change a deeply nested map into a vector with the first level of map entries as entries.

23:00 So, change {:a 1 :b {:c 3 :d 4}} to [{:a 1} {:b {:c 3 :d 4}}]

23:00 This can do that: (map (fn [[k v]] {k v}) deeply-nested-map)

23:01 but I get the sense that there is a more idiomatic way.

23:01 (like using into etc.).

23:01 Any better alternatives?

23:02 TEttinger: ,(mapv hash-map {:a 1 :b {:c 3 :d 4}})

23:02 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: [:b {:c 3, :d 4}]>

23:08 or9ob: ,(format "Wow, didn't know %s can eval code here" "clojurebot")

23:08 clojurebot: "Wow, didn't know clojurebot can eval code here"

23:17 amalloy: ,(map #(into {} %) {:a 1 :b {:c 3 :d 4}})

23:17 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword>

23:17 amalloy: ,(map #(conj {} %) {:a 1 :b {:c 3 :d 4}})

23:17 clojurebot: ({:b {:c 3, :d 4}} {:a 1})

23:17 amalloy: or9ob

23:18 or9ob: Thanks @amalloy

Logging service provided by n01se.net