#clojure log - Aug 26 2014

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

0:00 justin_smith: and you can keep adding or adjusting at the end of that ->> thread to narrow down the data you are looking for

0:05 also the magic first / second - the first is to get just one of the contacts, the second is to get the :raw

0:05 since it was a [] instead of {}

0:06 sarcher: That makes sense.

0:06 I'm going to have to play around with this a bit and see what I can come up with.

0:06 it's a very different way of thinking about things haha

0:06 thanks again for the help!

0:06 justin_smith: np

0:07 the general pattern with what data.xml returns is to filter for the right :tag then probably grab the :content

0:07 you'll see yourself doing that over and over

0:08 danielcompton: Does leiningen check for snapshots every time you run it?

0:10 justin_smith: https://raw.githubusercontent.com/technomancy/leiningen/master/sample.project.clj looks like you can set that explicitly

0:11 danielcompton: link to the relevant line https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L90

0:12 danielcompton: justin_smith: thanks!

0:13 which is the default?

0:13 justin_smith: danielcompton: looking for that now

0:15 https://github.com/technomancy/leiningen/blob/ad65195f40c2a1eeffd31401942cd8111c5de7ff/src/leiningen/deps.clj#L111 once every 24 hours

0:15 finally found it

0:15 sm0ke: if find doing this very often (if x (f y) y) can this be expressed any better/shorter?

0:15 danielcompton: ahaha https://github.com/technomancy/leiningen/blob/2cfca444fe37135637a4efbe9f004d4ce5fe51c7/leiningen-core/src/leiningen/core/main.clj#L13

0:16 justin_smith: rofl

0:16 nice to know it is friendly to the germans

0:16 sm0ke: leiningen was a german

0:16 danielcompton: justin_smith: where does it take :update?

0:16 justin_smith: see my link to project.clj above

0:16 it is the sample project.clj, it shows the syntax / where the key is expected

0:17 danielcompton: justin_smith: I mean where in deps.clj does :update change things?

0:17 looking at deps.clj I can't see :update at all

0:17 technomancy: danielcompton: use `lein -U ...`

0:18 danielcompton: technomancy: where does https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L90 take effect?

0:18 justin_smith: danielcompton: I bet it happens in classpath/resolve-dependencies

0:18 technomancy: inside pomegranate/aether

0:18 danielcompton: ah, it all becomes clear

0:18 er

0:19 thanks!

0:19 justin_smith: danielcompton: https://github.com/technomancy/leiningen/blob/ad65195f40c2a1eeffd31401942cd8111c5de7ff/leiningen-core/src/leiningen/core/classpath.clj#L122

0:19 yup, I was right

0:19 (or close enough to get real close :))

0:21 danielcompton: (inc justin_smith)

0:21 lazybot: ⇒ 67

0:21 danielcompton: (inc technomancy)

0:21 lazybot: ⇒ 132

0:21 danielcompton: (dec so)

0:21 lazybot: ⇒ -33

0:24 justin_smith: $karma karma

0:24 lazybot: karma has karma 1.

0:24 catern: (dec karma)

0:24 lazybot: ⇒ 0

0:24 catern: all is in balance

0:24 justin_smith: $karma karma karma karma karma chameleon

0:24 lazybot: karma has karma 0.

0:24 justin_smith: :P

0:51 sm0ke: core.async is like a playground right now, i hope some of these days the devs make a 0.1.x release with limitled stable features as people are already beginning to use it

0:54 rhg135: justin_smith: now it's in my head, damn it :P

0:55 pmonks: G’day everyone, potentially dumb n00b question here…

0:55 I’m working on wrapping a Java API in idiomatic Clojure, and one ubiquitous type in that API I feel is best represnted by keywords on the Clojure side.

0:56 I can manually translate between instances of this class and keywords, but is there a way to tell Clojure how to do the type conversions, and then just handle them wherever needed?

0:56 The type is used throughout the API, and manually translating everywhere (while technically possible) sounds like a lot of donkey work.

0:56 rhg135: Implicit casing yikes

0:57 pmonks: Yah that was my reaction. :D

0:57 sm0ke: ##(bean (java.util.Date.))

0:57 lazybot: ⇒ {:seconds 14, :date 26, :class java.util.Date, :minutes 57, :hours 4, :year 114, :timezoneOffset 0, :month 7, :day 2, :time 1409029034220}

0:58 pmonks: Thing is, this type maps beautifully to keywords (though it’s not symetrical - while all instances of the class can be mapped to keywords, the reverse isn’t true).

1:02 rhg135: I usually have a function, usually a map, to convert it at every at user interaction point

1:03 pmonks: And you then call that function internally before interoping with Java, or simply let users of the API choose to use it or not?

1:03 rhg135: Internally

1:05 pmonks: hmmm…….in the Java API I’m wrapping there are approximately 215 classes that use this particularly type, many of which offer numerous methods that have it somewhere...

1:06 (not that I’m wrapping all of them up front…)

1:06 rhg135: Hmm

1:06 pmonks: I guess I have to do work to nicely wrap all that garbage anyway - might as well add in conversion calls as a nice convenience. ;-)

1:07 Particularly since it’s only a subset of that API that’s the “80% sweet spot” for callers.

1:07 Well thanks @rhg135 - you answered my question!

1:08 rhg135: Np

1:08 pmonks: I was wondering for a minute if Clojure might have opened the Pandora’s Box of Scala-style implicits (which seem like a capital-N nightmare).

1:10 rhg135: Lol

1:10 * rhg135 shivers

1:11 TEttinger: I haven't learned all of Scala's implicit stuff, but all I can tell is it's complicated

1:14 rhg135: Reminds me of c++

1:15 Trying to fix c/java

1:15 sm0ke: its stupid

1:15 and dangerous

1:15 rhg135: Very

1:15 sm0ke: they admit that it wasa bad design choice

1:17 i think most of the scala dev abstain from using implicits, they prefer to do conversion manually where required

1:17 TEttinger: I don't even know how implicit really works, I used it to imitate extension methods in C#

1:19 I'm wondering if there's some way to get idiomatic clojure closer to java speed

1:19 sm0ke: how is that realted to implicit conversion?

1:20 TEttinger: sm0ke, implicit has multiple meanings in scala

1:20 rhg135: Don't think there is

1:20 TEttinger: and the clojure comment is because I'd really prefer to use clojure over scala

1:20 rhg135: Java is always lower level

1:20 TEttinger: but scala's performance is much better

1:23 sm0ke: better than java?

1:23 TEttinger: no, than clojure

1:23 sm0ke: idimomatic scala ?

1:24 TEttinger: not sure what that really is. I haven't really needed to optimize my scala but desperately needed to for clojure

1:24 both soft-real time, JVM games using the same lib, libgdx

1:24 sm0ke: http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=clojure&lang2=scala&data=u64q

1:25 TEttinger: sm0ke, I don't think microbenchmarks of optimized code are the best reference here

1:26 yeah, uh I do not consider this idiomatic clojure http://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=clojure&id=1

1:26 sm0ke: TEttinger: for that libgdx comment, it seems absurd

1:26 doesnt it uses native libs under the hood?

1:27 neither is the scala port

1:28 http://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=scala&id=1

1:28 TEttinger: yes, the problems weren't in graphics (the same needs, approximately, for both), but in logic. I may have been doing substantially more logic in clojure, but it was just plain hard to debug

1:28 err

1:28 profile

1:29 and that scala looks fairly reasonable, but I do not see definterface in most clojure code

1:30 and you have stuff like this in the clojure, ^{:unsynchronized-mutable true :tag double} x

1:30 sm0ke: :p

1:30 pmonks: “Moore’s Law will make all this moot anyway. What’s that you say? It’s been rescinded?? DOH!!!”

1:30 sm0ke: immutability is the agenda remember?

1:31 TEttinger: what kind of glue code are you writing in clojure thats so slow?

1:31 even high end games use something like lua for similar purpose

1:31 i dont really see how the microssec diff between clojure and scala is critical here

1:31 TEttinger: glue code? I didn't write any of it, like I said the issue was with logic code

1:32 and more importantly, the issue was with how hard it was to optimize the clojure vs. scala

1:32 sm0ke: my point is, either you write it in C or dont write it at all

1:33 TEttinger: ugh. I'm not writing games that need extreme 3d performance, both of these are small 2d games

1:33 sm0ke: i am totally agreeing with clojure being harder to profile and slower than scala

1:34 so your game is needs like what 6000 fps?

1:34 TEttinger: it was getting closer to 15

1:34 in clojure

1:34 sm0ke: for a 60 fps game you get, ###(/ 1000000 60) ; millis for evey frame

1:34 lazybot: ⇒ #<sandbox5671$eval16962$fn__16963 sandbox5671$eval16962$fn__16963@23827d2a>

1:34 TEttinger: the bigger problems were with input lag

1:34 sm0ke: ugh ##(/ 1000000 60)

1:34 lazybot: ⇒ 50000/3

1:35 sm0ke: lol

1:35 TEttinger: ,(/ 1000.0 60)

1:35 clojurebot: 16.666666666666668

1:35 TEttinger: you're doing microseconds I think

1:36 sm0ke: yep so even if you loose like 3 millis to clojure, you have 95% of same time

1:36 TEttinger: I'm just saying my experience writing the game

1:36 I spent personally about half the time on the game trying to optimize it

1:37 stuff like ztellman's primitive-math helped

1:37 sm0ke: TEttinger: i may be plain wrong, but it think you would be equally disappointed if you port it entirely to scala

1:38 TEttinger: oh, I scrapped the game and started a different one. it is faster in scala, but does different stuff

1:38 ztellman: sm0ke: disagree, a lot of games is math, and Clojure can disappoint you on that count

1:38 I had to write a custom vector math library for http://ideolalia.com/creating-a-simple-game-in-clojure/

1:39 sm0ke: is scala that much faster in math? my original point was to write heavy stuff in C

1:39 ztellman: things have progressed since then, but using the typical numerical stack is more or less comparable

1:43 TEttinger: well I used a lot of native arrays in clojure, which I don't consider idiomatic at all and it didn't feel easy. I eventually rewrote most of the game in the higher-level lib play-clj (which itself wraps what I was using before, libgdx), and the game surprisingly had better performance. it turned out primitive object arrays are not fast at all and collections are better for objects

1:44 sm0ke: i personally think clojure is horribly slow, but i still dont buy it that moving same code to scala got you to 60 fps from 15

1:44 TEttinger: and I had a major part of the render loop use an array of Images

1:44 sm0ke, oh, I don't think so either, I think I wrote better code this time

1:45 but it was easier to write fast code I think

1:45 sm0ke: TEttinger: you gave Scala the nicest punchline ever "Scala makes it easier to write fast code"

1:45 :D

1:45 TEttinger: well compared to java yes

1:46 I just wonder about stuff like oxcart

1:47 sm0ke: nah

1:47 wont work for you, you need low level stuff

1:48 i dont thing oxcart can make any difference to math operations being slow

1:48 imho

1:50 TEttinger: it possibly could, if it can compile it down to primitive math

1:50 arrdem: I like this commit message https://github.com/oxlang/oxcart/blob/953187d447ee70168105f48f5ed5d666b7d3e187/src/bench/clojure/test/vars.clj

1:52 sm0ke: hurm interesting

1:53 i am not sure how defining same `+` operations 500 times is helping though

1:54 TEttinger: it's a test

1:58 sm0ke: oxcart is exciting work though

2:28 bars0: Hi all! Is there some clojure channel for newbies? If not: could someone point me to the documentation/blog how to build functins with required/default/optional parematers in clojure way. This is what I've wrote, but I know this is wrong: http://pastebin.com/AR7XgkWK

2:33 Kneiva: bars0: I just read this (4 years old post) which is related I think: http://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure

2:35 bars0: Lisphttp://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure

2:35 Kneiva: ok, thanks, I'll read this

2:39 arrdem: TEttinger: lol

2:40 TEttinger: yeah... that "benchmark" is me being as mean as I can imagine how to be comparing Oxcart vs. clojure.core

2:43 totally open to ideas for other test programs

3:34 TEttinger: $mail sm0ke having thought about it, most of my performance improvements in the Scala code would be just as applicable in Clojure. I may write my next game with Clojure if this works...

3:34 lazybot: Message saved.

3:41 clgv: TEttinger: what did you write?

3:52 TEttinger: clgv: I wrote part of a roguelike dungeon-crawly game in clojure a while ago. I got tired of the constant optimizing I needed to do to get multiple monsters to act as soon as the player pressed a button, and I eventually stopped working on that one for unrelated reasons (the design wasn't very clear from the start).

3:53 I later started making my own art using a C# program that parsed voxel models (bindings existed for C# and C, not anything JVM), and that parser got out of hand and turned into a demo, then a game

3:53 lvh: TEttinger: huh; so the issue was it was too slow?

3:53 TEttinger: I'm interested in writing some simultaneous turn based games

3:53 TEttinger: lvh, I think I could manage to get it to be faster these days

3:54 lvh: performance not as big a deal there :)

3:54 more of a deadline scheduler style thing ;)

3:55 clgv: TEttinger: ah interesting

3:56 TEttinger: so that C# demo used some very clojuresque featurers. it used a bit of higher-order functions, and I used a future-like use of threads to offload the slow pathfinding code onto another core. but it also used IKVM so I could use the java lib, libgdx, that I was used to, and have it work from C# where I already had a codebase form the voxel renderer

3:56 clgv: I use some semi-immutable datastructures to get java performance in an algorithm

3:57 TEttinger: IKVM doesn't work well on mono, at least any newer versions

3:57 so I was stuck with windows only and slow (IKVM turned out to have major performance issues)

3:58 I tried to port to Java 8, but lambdas are no substitute for real HOFs. they aren't actually closures, so I couldn't use them in the same way as in C#

3:58 clgv: and then you did a scala implementation?

3:58 Java lambdas do not close of the used variables?

3:59 TEttinger: so I stuck to Scala, and found that it was a simple port (similar features in scala and C#), and without IKVM was much faster

3:59 clgv: or values of the variables...

3:59 TEttinger: clgv, you can't change outer state

3:59 in lambdas in java 8

3:59 clgv: TEttinger: for referenz types?

4:00 TEttinger: it's a restriction on lambdas in general

4:02 clgv: TEttinger: can you be more precise on "can't change outer state"? I mean if I close over a double value, I know that I wont see any change in the variable that held the value outside the lamda

4:04 I guess you meant Java lambdas do only close over "final" local variables?

4:05 TEttinger: clgv, I will try to find an article explaining the issue, but in my C# code I could have a method of ClassA that changes a static public member of ClassA be passed somewhere else, be called in a method of ClassB, and it would change ClassA. not so in Java

4:10 SagiCZ1: hi, can i attach metadata to a function from within the function? thus aquiring something akin to regular stateful object?

4:10 TEttinger: clgv, I encountered this same issue http://stackoverflow.com/questions/17204279/does-java-8-support-closures?rq=1

4:11 (doc meta)

4:11 clojurebot: "([obj]); Returns the metadata of obj, returns nil if there is no metadata."

4:11 TEttinger: (doc with-meta)

4:11 clojurebot: "([obj m]); Returns an object of the same type and value as obj, with map m as its metadata."

4:12 TEttinger: it seems that it wouldn't be the same reference, SagiCZ1

4:12 ,(let [a {:a 1 :b 2}] (= a a))

4:12 clojurebot: true

4:12 TEttinger: ,(let [a {:a 1 :b 2} b (with-meta a {:blah true})] (= a b))

4:12 clojurebot: true

4:12 TEttinger: huh

4:12 maybe...

4:14 clgv: SagiCZ1: what's your exact use case? you seem to head into a strange direction

4:14 TEttinger: they are equal, thats the point of metadata - but the objects are not identical

4:15 TEttinger: ,(let [a {:a 1 :b 2} b (with-meta a {:blah true})] (identical? a b))

4:15 clojurebot: false

4:16 clgv: SagiCZ1: if you want function local data that can be mutated, then just close over an atom

4:19 ,(let [create-counter (fn [] (let [cnt (atom 0)] (fn [] (swap! cnt inc))), counter (create-counter)] (repeatedly 10 counter))

4:19 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

4:19 dawkirst: asked this yesterday too, but just want to get a varied opinion: Programming Clojure or Clojure Programming for a newcomer to Clojure and FP?

4:19 clgv: ,(let [create-counter (fn [] (let [cnt (atom 0)] (fn [] (swap! cnt inc)))), counter (create-counter)] (repeatedly 10 counter))

4:19 clojurebot: (1 2 3 4 5 ...)

4:20 clgv: dawkirst: depends on what style of writing you like

4:20 dawkirst: clgv: how do the styles differ?

4:20 rhg135: Do you even need a book with a repl?

4:21 clgv: dawkirst: "Programming Clojure" (2nd edition) is more like "these are the facts" and imho "Clojure Programming" is more narrative

4:21 rhg135: They're great but repls are awesome for learning

4:21 clgv: rhg135: yes, I'd recommend one for every newcommer. the repl is an awesome feature to try out the book example

4:21 dawkirst: clgv: narrative in the sense that they explain underlying rationales more?

4:22 rhg135: I guess not, but at the moment I'm just floating around in the ether: I need a bit of theoretical grounding

4:22 rhg135: Clgv, they do go well together

4:22 clgv: dawkirst: no, not necessarily. I wanted to describe the wrinting style by that

4:22 dawkirst: clgv: ok

4:22 clgv: dawkirst: afaik they both have example chapters

4:22 dawkirst: just read those and decide based on that

4:23 dawkirst: clgv: that's probably not a bad idea, thanks

4:23 rhg135: thoughts on Light Table as a REPL? Is it permissible?

4:23 clgv: dawkirst: personally I read "Programming Clojure" (1st edition) - the other one didnt exist at that time ;)

4:23 rhg135: It's incredible

4:24 Especially for cljs

4:24 clgv: dawkirst: Light Table as a repl for learning should work pretty well

4:24 dawkirst: rhg135: awesome :) I think so too.

4:25 rhg135: Anyway it's 3am here, I should look at the clock more often lol

4:26 Piece.

4:26 Grr

4:26 Peace**

4:26 clgv: good sleep ;)

4:27 it's 10:26 am over ehre

4:34 adding to the book topic: did anyone read the Joy of Clojure Second Edition and can comment on the changes?

4:40 SagiCZ1: clgv: thanks for the answer earlier.. i will try it with the atom

4:42 clgv: SagiCZ1: maybe you should describe your problem, anyway? I was just guessing what you are trying to achieve ;)

5:06 lvh: hm

5:07 I'm writing a protocol for a simple kv store. is shadowing "get" ok? the error message seems to imply regular get will stop working (which makes sense, I guess; the existing get doesn't use protocols probably, and it's not like I'm extending the protocol for an exisitng type)

5:14 clgv: lvh: what you should do is the following? in the implementing namespace use (:refer-clojure :exclude [get]) and in namespaces where you want to use it, you shoud use an alias, e.g. myproto, and refer to the method like (myproto/get ...)

5:14 delete the "?" ;)

5:15 maybe "myproto" is misleading, imagin "myns" in the above example

5:18 lvh: similar to what is done here https://github.com/ztellman/primitive-math/blob/master/src/primitive_math.clj

5:20 lvh: clgv: oh, durr; that makes sense

5:20 clgv: I actually replaced it with create/retrieve, which is marginally better because create implies that overwriting an existing key is an error (and it is)

5:23 clgv: lvh: if you have better verbs, you should definitely use those. but you can't always avoid collision ;)

5:24 lvh: clgv: yeah, absolutely

5:24 CompilerException java.lang.IllegalArgumentException: No single method: retrieve of interface: icecap.storage.core.Store found for function: retrieve of protocol: Store, compiling:(/private/var/folders/dd/lh02zlnn1hg7cgs85w8qq6c00000gn/T/form-init939129485929514517.clj:1:1)

5:25 oh... don't have two jvms up

5:26 I couldn't figure out why I was seeing stale code in my repl :)

5:26 clgv: yeah, for development a switch "always compile the clojure code and do not dare to load *.class files" would be nice sometimes

5:36 lvh: clgv: Hm. That wasn't it, though: https://gist.github.com/lvh/949692f88bf1634a967d

5:57 noniwoo: hi. why this one gives me original vector without 19? (replace {0 19} [1 2 3 4 5])

6:02 clgv: lvh: you forgot about the "this" pointer

6:02 lvh: clgv: Just adding "this" in front of everything gives me a different exception though

6:02 clgv: lvh: it needs to be in the argument list for protocols, reify and deftype

6:03 mpenet: noniwoo: it takes the key as value to be replaced in the vector

6:03 ,(replace {0 19} [0 0 2 3 4 5])

6:03 clojurebot: [19 19 2 3 4 ...]

6:03 lvh: Can't define method not in interfaces: create_BANG_

6:03 clgv: (goes away without this, leading me to believe that it's convinced that method with that arity doesn't exist)

6:04 clgv: lvh: do you have the first param for "this" in the protcol and the reify?

6:04 lvh: clgv: Nope, just the reify

6:04 clgv: it should be in both?

6:04 clgv: lvh: yes

6:04 lvh: clgv: I don't understand why; I don't actually care about the "this"

6:05 clgv: lvh: for deftypes you sometimes do care

6:05 lvh: you can return the object itself without modification via "this"

6:05 lvh: hm, okay

6:05 noniwoo: mpenet: oh, I thought it is position. thanks

6:06 lvh: clgv: but if I'm writing code like mem-store that doesn't care, that doesn't mean I'm doing something wrong?

6:07 clgv: lvh: it's the contract of defprotocol and the others that you include that param. proxy is an exception from that with implicit definition of "this"

6:08 lvh: clgv: Aha; so maybe I want proxy? :-)

6:08 clgv: ah right, and definterface is an exception as well

6:08 lvh: no not really if reify does what you want

6:09 lvh: you just want to do (reify Store (create! [_, key, value] ...) ...)

6:09 lvh: clgv: Okay, thanks :)

6:11 clgv: lvh: in the defprotocol you probably want (create! [store, key, value]) for documentation purposes

6:12 lvh: clgv: right; maybe I should come up with a different name for that local in mem-store

6:12 since this != store :)

6:12 (store being an atom there)

6:13 clgv: lvh: yeah, I just meant that you dont use "this" or "_" there but a name associated with that protocol

6:13 lvh: right :)

6:13 thanks!

6:14 clgv: anytime

6:14 lvh: I'm going to replace "key" and "value" with more use-case-specific terms as well

6:16 amitayh: ?

6:17 dawkirst: what does #'some-symbol mean?

6:18 lvh: dawkirst: that's a var quote

6:18 clgv: dawkirst: reference to the variable and not the value of the symbol

6:18 lvh: dawkirst: #'sym == (val sym)

6:18 clgv: ,(meta #'map)

6:18 clojurebot: {:ns #<Namespace clojure.core>, :name map, :added "1.0", :file "clojure/core.clj", :static true, ...}

6:18 clgv: ,(meta map)

6:18 clojurebot: nil

6:18 clgv: ,(map type [map, #'map])

6:18 clojurebot: (clojure.core$map clojure.lang.Var)

6:19 dawkirst: awesome, thanks!

6:22 SagiCZ1: what type is lazy seq? seq or list?

6:23 ,(map identity (drop 5 (range 10)))

6:23 clojurebot: (5 6 7 8 9)

6:24 SagiCZ1: ,(type (map identity (drop 5 (range 10))))

6:24 clojurebot: clojure.lang.LazySeq

6:24 SagiCZ1: ,(list? (map identity (drop 5 (range 10))))

6:24 clojurebot: false

6:24 SagiCZ1: why is it printed as list when its not a list

6:24 TEttinger: ,(seq? (map identity (drop 5 (range 10))))

6:24 clojurebot: true

6:24 TEttinger: because seqs and lists print the same

6:25 clgv: SagiCZ1: it is sequential - why do you ask?

6:25 SagiCZ1: ,(seq? '(1 2 3))

6:25 clojurebot: true

6:25 clgv: ,(sequential? (iterate inc 0))

6:25 clojurebot: true

6:25 SagiCZ1: i have this expression.. i need it to return [[coll1] [coll2]].. how do i simplify it?

6:25 (vector (vec <some-non-vec-coll>)) (vec <some-non-vec-coll>)))

6:26 clgv: mapv + vec

6:26 SagiCZ1: (doc mapv)

6:26 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a vector consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

6:26 clgv: ,(mapv vec (parition-all 2 (range 10))

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

6:26 clgv: ,(mapv vec (parition-all 2 (range 10)))

6:26 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: parition-all in this context, compiling:(NO_SOURCE_PATH:0:0)>

6:26 clgv: ,(mapv vec (partition-all 2 (range 10)))

6:26 clojurebot: [[0 1] [2 3] [4 5] [6 7] [8 9]]

6:28 SagiCZ1: this doesnt work (mapv vec (drop-last x coll) (take-last x coll))

6:29 TEttinger: clgv showed a way, SagiCZ1

6:29 replace (range 10) with your coll

6:29 SagiCZ1: but i dont want partition

6:30 TEttinger: what is your input like?

6:30 SagiCZ1: 1 [:a :b :c :d] ==> [[:a] [:b :c :d]]

6:30 i am reimplementing split

6:32 this works too: (mapv vec (list (drop-last x coll) (take-last x coll)))

6:32 TEttinger: ,(let [splitter 1 coll [:a :b :c :d] ] (mapv vec [(take splitter coll)(drop splitter coll)]))

6:32 clojurebot: [[:a] [:b :c :d]]

6:33 TEttinger: ,(let [splitter 2 coll [:a :b :c :d] ] (mapv vec [(take splitter coll)(drop splitter coll)]))

6:33 clojurebot: [[:a :b] [:c :d]]

6:33 SagiCZ1: ok

6:33 thank you

6:34 TEttinger: no prob

6:35 SagiCZ1: ,(= [[:a :b][:c :d]] ((:a :b)(:c :d)))

6:35 clojurebot: #<NullPointerException java.lang.NullPointerException>

6:36 SagiCZ1: ,(= [[:a :b][:c :d]] '((:a :b) (:c :d)) )

6:36 clojurebot: true

6:36 TEttinger: need to quote the lists

6:36 you got it

6:37 SagiCZ1: yeah ok.. so i actually didnt need the vectors.. i forgot that = checks the contents.. well nevermind it was an exercise :)

7:11 martinklepsch: is there a subset? for maps where (subset? {:a 1} {:b 2 :a 1}) would be true?

7:16 clgv: martinklepsch: no but you can build it via select-keys, keys and =

7:16 ,(defn subset? [sub, super] (= sub (select-keys super (keys sub))))

7:16 clojurebot: #'sandbox/subset?

7:16 clgv: ,(subset? {:a 1} {:b 2 :a 1})

7:16 clojurebot: true

7:17 clgv: ,(subset? {:a 1} {:b 2 :a 5})

7:17 clojurebot: false

7:17 clgv: ,(subset? {:a 1 :c 9} {:b 2 :a 1})

7:17 clojurebot: false

7:17 martinklepsch: clgv: ah, that sounds good. I was going to do some: for each mapentry in the subset check if it exists in the other map

7:18 clgv: martinklepsch: that's a highlevel implementation above. in case this happens to be a bottleneck you might change to something low level via reduce or loop/recur

7:21 martinklepsch: clgv: ok, thanks :)

7:21 once you see the solution it always seems so obvious

7:26 clgv: martinklepsch: in this case the solution was to turn around the question: >how do I get a "subset" of a hashmap in clojure?<

7:26 martinklepsch: clgv: (= super (merge super sub)) — am I overseeing something or is this also a solution?

7:26 clgv: martinklepsch: schould be yes

7:27 martinklepsch: but here, the order of the maps is important. "sub" must be in second position such that it overrides the values in "super"

7:27 martinklepsch: yup

9:14 tsdh: Hi. Is it possible to attach metadata to letfn-bound functions? Or well, it is, but is there a way to access it from the letfn's other fndecls and its body?

9:15 clgv: tsdh: why?

9:16 tsdh: whatever you want to do sounds pretty complicated

9:17 ,(let [f (with-meta #(inc %) {:awesome true})] (meta f))

9:17 clojurebot: {:awesome true}

9:17 tsdh: clgv: I have a macro that expands into a letfn form, and I'd like to annotate the functions with some metadata for implementing black magic. ;-)

9:17 clgv: tsdh: you might need to move back to `let` if letfn wont let you do that

9:18 tsdh: clgv: let+fn won't do the trick because the individual functions may call each other.

9:18 clgv: ,(letfn [(^:awesome f [x] (inc x))] (meta f))

9:18 clojurebot: nil

9:18 tsdh: clgv: I.e., they may be mutual recursive.

9:18 gfredericks: does anybody know why it would ever be helpful to `ln -s src/data_readers.clj data_readers.clj`?

9:18 clgv: ,(letfn [(f {:awesome true} [x] (inc x))] (meta f))

9:18 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Parameter declaration {:awesome true} should be a vector, compiling:(NO_SOURCE_PATH:0:0)>

9:18 tsdh: clgv: Yeah, that's what I tried, too.

9:19 clgv: tsdh: yeah but it's the wrong one anyway. that metadata is likely lost after compilation

9:19 tsdh: clgv: I only need it during macro expansion time.

9:19 clgv: tsdh: well then you have it on the symbol `f` in the above example

9:20 tsdh: clgv: But (identical? 'foo 'foo) ;=> nil

9:20 clgv: Ah, not nil but false.

9:20 clgv: ,(-> "(^:awesome f [x] (inc x))" read-string first meta)

9:20 clojurebot: {:awesome true}

9:23 tsdh: clgv: Hm, thinking about it, I could pass along a set of function names (with metadata), so (this-set 'f) would return the symbol f with the metadata...

9:45 justin_smith: lvh: get is based on an interface that you can implement

9:45 lvh: justin_smith: Oh, cool.

9:45 justin_smith: (regarding some scrollback)

9:46 most of the core of clojure is programmed in terms of interfaces rather than classes, so you can use the core functions on your own datatypes as long as they implement the appropriate interfaces

9:47 I don't know of an authoritative doc about what those interfaces are - but they are all in one place as protocols in cljs https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L201

9:48 I think that for get you need ILookup (and maybe IAssociative too?)

9:48 martinklepsch: I want to load 4gb of maps into memory and filter/query/transform them. Is an atom appropriate if I want to later-add data?

9:50 justin_smith: martinklepsch: it seems like all this would be much simpler with a proper database

9:50 not to say you can't do 4gb immutible datastructures

9:54 gfredericks: martinklepsch: it doesn't sound like a use case for state

9:54 but that's hard to evaluate without knowing your application architecture

9:55 lvh: are test names typically CamelCase or lispy-case?

9:55 (I appear to be seeing both)

9:56 gfredericks: names of tests?

9:56 like (deftest ILikeCamels ...)?

9:56 I've never seen that

9:56 justin_smith: CamelCase is for things that are directly created on a jvm level (protocols become interfaces, records / deftypes become classes, etc.) it should be avoided otherwise

9:56 martinklepsch: justin_smith: the querying I want to do would require a complex database setups (compared to reading just from files on disk) and so I thought it's fine to just run map/filter etc on one big data structure

9:58 justin_smith: martinklepsch: OK, if the structure is not uniform enough for a db to make sense than don't use one, it just seemed like "controlled mutation? huge dataset? why isn't this a db?"

10:03 martinklepsch: the information about mutations isn't very important I to be able to manage how much data is loaded/load more

10:04 milos_cohagen: i've been haunted the past couple of weeks ever since i spent a day trying to understand implementing foldl in terms of foldr in haskell. thoughts of comparing clojure's lazy-seqs versus haskell's lazy evaluation. need to focus on my day job writing js!

10:06 justin_smith: martinklepsch: yeah, you can do that via a global atom in a def, or via args to a recursive function, or the carried state argument of a reduce...

10:08 martinklepsch: consider that a global atom can be used to parallelize in one way, while local / recursive bindings parallelize in another way entirely

10:10 martinklepsch: justin_smith: I don't really know what you mean by recursive binding

10:11 can you maybe point me to an example?

10:12 justin_smith: martinklepsch: think along the lines of a reduce on a line-seq

10:12 though you wouldn't be doing that, I am sure

10:13 reduce on a line seq is an alternative to slurping the whole text document, and in some cases lets you get the same work done with less resource usage

10:17 (reduce (fn [m w] (update-in m [w] (fnil inc 0))) {} (line-seq (clojure.java.io/reader (.getBytes "hello\nworld"))))

10:17 ,(reduce (fn [m w] (update-in m [w] (fnil inc 0))) {} (line-seq (clojure.java.io/reader (.getBytes "hello\nworld"))))

10:17 clojurebot: {"world" 1, "hello" 1}

10:21 bulters: g'day all! Can someone here perhaps shed some light on how [{:keys [...]}] destructuring actually works? It seems a bit like a magical built in to be

10:22 which - considering how the rest of clojure is designed - doesn't ring too well with me :P

10:23 justin_smith: it's something called destreucture, which is called by fn and let

10:23 *destructure

10:24 https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4160 source is here

10:24 bulters: that's one helluva function

10:24 just found it :P

10:25 justin_smith: so that is called, inside the let macro

10:25 and also gets invoked eventually in the expansion of fn (though that is less clear to be sure)

10:28 bulters: justin_smith: probably the reason i didn't find it "in fn"

10:28 didn't think of looking into let, hindsight: much easier to find

10:29 justin_smith: or loop even :)

10:29 bulters: true, though I don't really use loop that often :P

10:29 so that would have been my last guess so to say

10:30 justin_smith: to be fair, "destructure" should have been the first thing to search for - it is the most intuitive name :)

10:32 bulters: just to show of my inexperience: I didn't actually think it was a 'dedicated function'; more like some magical construct I overlooked somewhere

10:32 justin_smith: in clojure a magical construct will often be a function

10:32 bulters: TIL!

10:33 justin_smith: the set of special forms is pretty short, after that you have functions and macros

10:33 *(and reader macros...)

10:35 bulters: but let is mentioned as a special form... still it's also implemented as a macro in core.clj

10:35 justin_smith: let* is the true special form

10:35 bulters: ah

10:35 justin_smith: let is a macro wrapping it

10:36 (and that macro gets a :special-form metadata...)

10:36 similar to fn and fn*

10:36 scriptor: it's a fairly simple macro, too

10:37 justin_smith: basically all it does is implement the destructuring before let* is invoked

10:37 scriptor: all it does is destructure the bindings you pass and then call let*

10:37 justin_smith: right

10:37 which brings this all full circle

10:37 bulters: I love this sh*t

10:38 scriptor: destructure, on the other hand, is a bit more hairy :)

10:38 http://clojuredocs.org/clojure_core/clojure.core/destructure

10:38 justin_smith: yup

10:39 bulters: scriptor: I'm blankly staring at it right now...

10:40 but it's really nice to see that magic is just functions all the way down :P

10:40 justin_smith: mostly - until you hit java and / or directly generated byte code...

11:05 sdegutis: What's a good project management online service that lets me organize and categorize tasks and put estimates on them?

11:06 cbp: a jira server

11:06 * cbp runs

11:06 sdegutis: Is that a bad thing?

11:06 Why run?

11:08 ephemeron: sdegutis: For generic tasks/management? Many people seem to like Trello, or Asana.

11:08 sdegutis: Thanks.

11:08 ephemeron: Other people would just look at you sternly and whisper "orgmode".

11:19 michaniskin: cemerick: do you know of any nrepl middleware example that adds things to stderr? i'm working on a job control thing, and i'd like to be able to notify the user about completed background jobs when the prompt is printed, like bash does

11:30 cemerick: michaniskin: not off the top of my head, but that should be straightforward. A broadcast to all sessions would be way easier than trying to confine the messages to only the session that started the job(s), certainly.

11:30 michaniskin: cemerick: i'd be tagging onto the :eval op, i guess?

11:31 cemerick: michaniskin: sounds complicated. These jobs presumably have many ways to report status/progress/completion? If so, adding an implementation that spams all connected nREPL sessions should be simple.

11:32 If "jobs" == arbitrary futures, etc., then that's way more subtle.

11:32 michaniskin: cemerick: the jobs themselves add their completion status to a queue, it's just a matter of doseq prn on the queue

11:33 the middleware wouldn't need to know anything about the jobs themselves

11:33 just check the queue any time something is evaled

11:33 and print the contents and empty it

11:33 like a flash message, kinda

11:33 cemerick: Even better, then. I thought you wanted to analyze the :code sent for eval to identify jobs being started, etc

11:34 michaniskin: processes can add messages to the flash queue, and they're popped and printed any time the prompt is printed

11:34 cemerick: So, yes, you can use :eval ops passing by as a trigger.

11:34 michaniskin: is there a key in the message for stderr or stdout?

11:34 cemerick: Might be nicer to just poll every N seconds, just so you aren't evaling stupid stuff to know when a job finishes tho.

11:34 csd_: What is the easiest way to take a seq of vector in the form of [-1] [0] [1] ... and a seq of related sets in the form #{-2} #{-1} #{0} and to create a map with the vectors as keys, the sets as values, and the understanding that if a key already exists that the additional value be joined to an existing set?

11:35 azizur: hello everyone is there anyone from http-kit.org on there?

11:35 michaniskin: cemerick: the job control is working nicely without middleware, but the notification of completed jobs is being printed async, which is a pain

11:35 i just need to be notified when the prompt is being printed i guess

11:36 cemerick: michaniskin: no, write to the writer in each session mapped to #'*err* https://github.com/clojure/tools.nrepl/blob/master/src/main/clojure/clojure/tools/nrepl/middleware/session.clj#L121

11:36 Prompt stuff is strictly a client-side tooling concern

11:36 Some tools don't have prompts.

11:36 michaniskin: so i can write to *err* in my middleware?

11:38 ok i now compute some code :)

11:38 thanks cemerick!

11:39 cemerick: michaniskin: Yeah, sessions are just maps of vars -> bindings; deref and be merry

11:40 #'clojure.tools.nrepl.middleware.session/session, or whatever

11:40 sessions*

11:42 TimMc: csd_: Something like (apply merge-with set/union (map hash-map vec-keys set-vals))

11:43 csd_: TimMc: thank you!

11:45 TimMc: &(apply merge-with clojure.set/union (map hash-map [:a :c :d :c] [#{1} #{2} #{3} #{4}]))

11:45 lazybot: ⇒ {:a #{1}, :c #{2 4}, :d #{3}}

11:55 azizur: is it possible to write a fully non-blocking application with http-kit and luminus framework?

11:56 gtrak: azizur: pedestal is made for this

11:56 virmundi: azizur: I don’t know about liuminus, but have you looked at Pulsar (https://github.com/puniverse/pulsar)

11:56 gtrak: compojure/ring don't give you as much flexibility

11:57 virmundi: the nice thing about pulsar is that Parallel Universe is trying to make a ring adapter for it.

11:57 ohpauleez: +1 for Pedestal :)

11:58 justin_smith: pulsar also tries to replace core.async, right?

11:59 virmundi: kinda, it complementary with an Actor model

11:59 doctorm: Can someone recommend an article on debugging in Clojure? Mainly I’m interested in the best way to get some insight into what third party programs are doing

11:59 third party libs* that is

11:59 justin_smith: doctorm: core.trace is really useful for that

11:59 gtrak: doctorm: conveniently you can eval in any namespace, I redefine things often.

12:00 doctorm: justin_smith: thanks, I’ll check it out

12:00 gtrak: directly from a cider jar buffer

12:00 though it throws an error about saving read-only files or somesuch :-)

12:00 justin_smith: doctorm: also, if you need a finer level of granularity than function arg and return values, you can redefine things as gtrak says

12:01 langmartin: I'm doing it right now!

12:01 justin_smith: gtrak: well, directly from any repl, no need to drag cider into that :)

12:01 gtrak: in principle, yea, that's just how I happen to do it

12:02 doctorm: I’m new, what do you mean by redefine? Like, if I want to get a tracer into a library I’m using so I can watch a value as the function runs, how would I go about it?

12:02 justin_smith: doctorm: core.trace is made for that - it has a function to trace every funciton in a given ns, or to trace a specific function

12:02 gtrak: (in-ns 'that-ns), (def blah __)

12:02 it's convenient to have the existing source handy

12:02 doctorm: Alright, thank you, I’ll experiment for a bit

12:02 justin_smith: doctorm: or you can do as gtrak says if you want to simply redefine the functions in that ns

12:03 gtrak: with clojure you always have the existing source

12:03 ,(doc source)

12:03 clojurebot: "([n]); Prints the source code for the given symbol, if it can find it. This requires that the symbol resolve to a Var defined in a namespace for which the .clj is in the classpath. Example: (source filter)"

12:04 justin_smith: doctorm: oh man, why did I call it core.trace? it's tools.trace https://github.com/clojure/tools.trace

12:04 doctorm: justin_smith: I figured you meant that, found it thanks :)

12:04 justin_smith: the functions you want are trace-ns and trace-vars

12:08 Pupeno: At the last Clojure meetup, a lot of people were using a new nice editor on mac, but I forgot its name... what could it be?

12:08 TimMc: trace-ns may or may not still have a bug where it tries to trace things like (def foo {})

12:08 arrdem: emacs, light table and sublime text could all fit the bill...

12:08 Atom maybe

12:08 justin_smith: intellij idea + cursive

12:09 Bronsa: cursive++

12:09 Pupeno: light table

12:09 That's.

12:09 * Pupeno personally likes Cursive.

12:14 imanc: is cursive a jetbrains product?

12:14 justin_smith: https://cursiveclojure.com/

12:15 sdegutis: I think I'm settling on using Trello.

12:16 justin_smith: imanc: I think it's a third party plugin, with the aims of eventually being a commercial standalone ide (right now it is a free preview)

12:16 pmonks: +1 to Trello - it’s great

12:18 stuartsierra: azizur: It is possible to write fully non-blocking applications in Clojure, but it can be hard to find every possible case of blocking I/O in every third-party dependency. Even Java libraries which claim to be "non-blocking" may sometimes do blocking operations. That's one reason Netflix wrote Hystrix, I believe.

12:18 Pupeno: Yes, it's a third party plugin for Jetbrains, free for now.

12:20 doctorm: I’m getting “Parameter declaration trace-vars should be a vector” doing (trace-vars exec-raw), which was the nearly the same error message I was trying to debug. What does that message usually indicate?

12:20 justin_smith: doctorm: can you paste the code that provoked that error?

12:21 TimMc: ~paste

12:21 clojurebot: paste is not gist.github.com

12:21 TimMc: Thanks, clojurebot.

12:21 ~paste

12:21 clojurebot: paste is not gist.github.com

12:21 justin_smith: doctorm: refheap.com is good for pasting

12:21 TimMc: clojurebot: forget paste |is| not gist.github.com

12:21 clojurebot: I forgot that paste is not gist.github.com

12:21 doctorm: justin_smith: sure, it’s a little weird because it’s in a migration file with drift, but I will

12:21 TimMc: clojurebot: forget paste |is not| gist.github.com

12:21 clojurebot: I forgot that paste is not gist.github.com

12:22 justin_smith: doctorm: that error means that it thinks the call to trace-vars should have been the parameter declaration for an fn (or maybe a binding form for a loop)

12:22 doctorm: https://www.refheap.com/89490

12:22 justin_smith: but with some context we can see the issue

12:22 doctorm: defn needs a vector

12:22 doctorm: ah of course it does, thanks

12:23 justin_smith: parameter declaration must come before the body

12:23 also, down needs a parameter vector

12:23 it can be an empty vector if it takes no args

12:26 doctorm: Interestingly, trace-var causes a NullPointerException to be thrown once I fix the function vector problem

12:29 csd_: Is it possible to represent an empty vector [] as a different arity than [1 2 ...] either using destructuring or otherwise?

12:29 justin_smith: csd_: wat

12:30 llasram: csd_: Yeah, gonna need a bit more there :-)

12:30 justin_smith: vectors don't have arities, and I have no idea what you mean by [1 2 ...]

12:31 csd_: I want to write a multi-variadic function where if I pass [] then the function just returns an empty [], but if the vector has values it evaluates the vector. I just want to write this in the multivariadic idiom

12:31 hope that makes sense

12:31 justin_smith: csd_: destructuring is not pattern matching

12:31 llasram: csd_: You can either `apply` the vector, or use pattern matching via core.match

12:32 csd_: how would i do this using apply

12:32 mdeboard: arity dispatch is pattern matching, kinda

12:32 (apply foo [])

12:32 llasram: csd_: Er, I meant `apply` a function to the vector

12:32 justin_smith: mdeboard: but he wants dispatch on the content of a vector

12:33 mdeboard: o

12:33 use erlang

12:33 problem solved

12:33 llasram: csd_: Which will dispatch based on the number of elements in the vector

12:33 csd_: oh i get you

12:35 martinklepsch: I have a list that contains a few elements less when making it into a set. I'd like to know the duplicates but a function like dups [see link] doesn't return anything: http://stackoverflow.com/questions/8056645/returning-duplicates-in-a-sequence

12:36 (it returns nil to be precise)

12:36 hiredman: (doc group-by)

12:36 clojurebot: "([f coll]); Returns a map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll."

12:37 llasram: ,(->> (concat (range 10) (range 5)) (frequencies) (filter (comp pos? dec val)))

12:37 clojurebot: ([0 2] [1 2] [4 2] [3 2] [2 2])

12:37 justin_smith: ,(reduce (fn [[found dups] e] (if (contains? found e) [found (conj dups e)] [(conj found e) dups])) [#{} #{}] [0 1 2 1 2 1 3 4])

12:37 clojurebot: [#{0 1 4 3 2} #{1 2}]

12:38 milos_cohagen: martinklepsch: use the set as predicate on list after you create the set?

12:38 hiredman: guys, group-by

12:39 justin_smith: oh yeah, the keys give you the set, the vals tell you how many times each came up

12:39 but why not just frequencies?

12:39 dnolen_: thheller: ping

12:41 hiredman: justin_smith: sure frequencies too, all that other stuff is ridiculous

12:41 llasram: ,((fn step ([coll] (step #{} coll)) ([seen? coll] (when-let [[x & coll] (seq coll)] (if (seen? x) (cons x (step seen? coll)) (step (conj seen? x) coll))))) [0 1 2 1 2 1 3 4])

12:41 clojurebot: (1 2 1)

12:41 llasram: That one's lazy!

12:41 Er

12:41 Or would have been if I'd remembered the `lazy-seq`

12:41 hiredman: hah

12:44 martinklepsch: justin_smith: using your suggestion the second set (which seems to contain the dupes) is printed as #{...} — could that be related me doing: (set! *print-length* 50)

12:46 justin_smith: I think? I'm often unsuer about *print-length* and related stuff

12:49 martinklepsch: hm. just set it to false and still get #{...} — it's not a map literal right?

12:50 Bronsa: martinklepsch: try to set *print-level* to nil

12:51 martinklepsch: Bronsa: I tried false and nil

12:52 justin_smith: martinklepsch: and it definitely isn't just ##'#{...} ?

12:52 lazybot: ⇒ #{...}

12:52 Bronsa: martinklepsch: *print-level*, not *print-length*

12:53 TimMc: ,[*print-level* *print-length*]

12:53 clojurebot: [10 5]

12:53 TimMc: &[*print-level* *print-length*]

12:53 lazybot: ⇒ [nil nil]

12:54 alandipert: Raynes, is there a quick way with conc to stream a processes's err to out? trying to drive/see rsync stderr

12:54 *conch that is

12:55 (i tried (proc ... {:err *out*}) to apparent effect

12:59 martinklepsch: Bronsa: oh, sorry. print-level set to nil didn't change it. It works fine for a seq like [1 1 2 3 4 4 5] but with my 12000 elem seq it doesn't

13:01 dnolen_: sritchie: ping

13:01 sritchie: hey

13:01 dnolen_: sritchie: http://dev.clojure.org/jira/browse/CLJS-839

13:01 attached a possible patch, if you could test that would be awesome

13:02 sritchie: dnolen_: I was actually about to fix my issue by upgrading beyond 2261

13:02 dnolen_: sritchie: the patch simply keeps Math.imul polyfill out of advanced compilation hopefully that's all that's needed

13:02 sritchie: it looks like you added the shim imul implementation after the version I’d been using

13:02 dnolen_: sritchie: ah yeah, there was *another* Safari imul bug that we addressed too

13:02 thheller: also ^

13:02 sritchie: :)

13:03 Raynes: alandipert: I thought that was a thing you can do, but it doesn't look like it.

13:03 Certainly a patch I'd take. Otherwise, you can always pass the :verbose option to get back a map with both types of output.

13:05 schmee: dnolen_: hey, I was looking at core.match today, and I was wondering if it contains any form of exhaustiveness or reachability checking of the patterns?

13:06 dnolen_: schmee: it errors out if you there's not a corresponding match, precise exhaustiveness doesn't mean much in a dynamically typed context

13:06 schmee: dnolen_: yeah, I figured as much

13:07 but computing reachability should be possible, in some sense at least?

13:07 dnolen_: schmee: I don't see how that's possible except for trivial cases

13:08 schmee: and those will get picked up by Google Closure anyhow

13:09 schmee: dnolen_: aight!

13:09 thanks for your great work and presentations btw, really inspiring!

13:10 dnolen_: schmee: your welcome and thank you for saying so.

13:10 mdeboard: please, you'll embarass him

13:11 schmee: imo people spend to much time calling out stuff they don't like instead of the stuff they actually like

13:11 credit where credit is due! :)

13:12 mdeboard: he's doing it all for the nookie

13:12 alandipert: Raynes, thanks i may

13:12 Raynes: alandipert: I'm super shocked I never implemented that functionality, fwiw.

13:13 Surprised that I didn't need it myself

13:13 hlprmnky: dnolen_ : hear, hear! Your recent talk gave me the grasp of core.async I needed to tackle a fun little project at work.

13:13 dnolen_: hlprmnky: cool!

13:14 hlprmnky: my first actual soup-to-nuts Clojure “app”, actually, as opposed to maintenance and extension on someone else’s work. Feels good, man.

13:28 jakecraige: Are there any good blog posts on stucturing a web app written in clojure? Just getting the handler file is a start but I'm not sure what other folders I might need. I guess a good example app would be nice as well

13:29 or should i be using some sort of web framework for clojure

13:30 technomancy: jakecraige: https://github.com/technomancy/syme is a small nontrivial sample app you could read for guidance/samples

13:33 jakecraige: technomancy: thanks, I'll check it out

13:33 technomancy: in particular I would recommend using the strategy there for DB migrations

13:39 |xk05|: on 'lein repl' in a terminal, i get Exception in thread "nREPL-worker-0" java.lang.NoSuchMethodError: clojure.tools.nrepl.StdOutBuffer.length()I

13:41 technomancy: |xk05|: yeah, this is a known bug; need to work inside a project or fall back to 2.4.2 until 2.4.4 is released

13:41 |xk05|: technomancy, ok

13:45 TimMc: Augh, what.

13:45 OK, so I have a project depending on rxjava-clojure, which has a dependency on org.clojure/clojure "1.4.+", which is some Gradle nonsense.

13:46 This obviously breaks various lein tasks that try to fetch the nonexistent version.

13:47 I've used :exclusions on my lib (project #1), but project #2 depends on #1 and keeps trying to fetch Clojure 1.4.+. :-(

13:47 Is there some way to stop this madness?

13:48 technomancy: TimMc: exclusions in #2 don't work?

13:49 TimMc: Oh, I need both?

13:49 technomancy: TimMc: not sure; worth trying though

13:51 TimMc: OK, in retrospect that makes sense, in a certain twisted way.

13:51 Works, thanks.

13:51 technomancy: cool

13:51 TimMc: Now I'm back to my original error. Whee.

13:53 hiredman: http://dev.clojure.org/jira/browse/CLJ-1512 I really really want to put a comment on here "if only clojure had some way of defining inlinable functions..." but I won't

13:54 llasram: buuuurn

13:55 Actually -- manually setting `:inline` metadata totally works. It's just `definline` which is insane for no reason

13:55 hiredman: also, "updates are racy, but access is controlled"

13:56 llasram: Yeah. It's too bad the JVM doesn't have some sort of support for local per-thread mutable state

13:56 amalloy: hiredman: sounds like the paywall page for a premium cable channel

13:57 technomancy: bahaha

13:57 hiredman: hah

13:59 Bronsa: hiredman: if you won't, I will (leaving aside the sarcastic tone) I wouldn't be happy with vswap! being a macro

14:00 hiredman: Bronsa: it would be interesting to see how swap! would perform if inlined (get rid of the use of apply)

14:02 Bronsa: hiredman: can apply really be a bottleneck?

14:02 hiredman: I have no idea

14:02 I have a vague notion that apply is really slow

14:02 amalloy: Bronsa: yes, it could be

14:02 mostly because you have to build an argseq, not because apply itself is slow

14:03 although a fair number of my uses of swap! aren't inlinable, with stuff like (update-in my-app [:state] swap! assoc :done true)

14:03 hiredman: alex's "benchmark" there doesn't show a huge difference, but then again it is using dotimes

14:04 TimMc: criterium or nothing

14:04 amalloy: speaking of core not using criterium, do they use lein yet, these days?

14:04 TimMc: technomancy: I guess this means that every project needs to document its exclusions. :-(

14:04 Bronsa: amalloy: ah, that might make sense

14:05 hiredman: a lot of contrib has a project.clj checked in

14:05 technomancy: TimMc: every project that transitively includes brokenness, sure

14:05 TimMc: blerg

14:05 technomancy: it's pretty rare to come across version ranges these days

14:06 amalloy: yeah, but it's not "official", right. they all have to use a pom for releases and so on

14:06 Bronsa: yes

14:06 hudson uses the pom.xml

14:06 amalloy: technomancy: it's not even version ranges that are the problem; it's the totally made-up "1.4.+" syntax that lein/maven can't understand at all

14:06 they can't process the exclusion for it because it's not a real thing

14:06 technomancy: amalloy: yeah, but version ranges are a lot more common

14:06 and are worked around the same way

14:07 amalloy: well so what? they won't cause the problem TimMc has

14:07 you can just fight a version range by adding one of your own on a specific version

14:07 technomancy: amalloy: adding your own version range?

14:07 amalloy: [org.clojure/clojure "[1.6.0]")

14:07 technomancy: that works for applications but is a bad idea for libraries

14:07 amalloy: sure

14:08 but the solution you proposed doesn't really work for libraries either. he has to exclude it in his app

14:08 or else it sneaks in transitively

14:10 technomancy: gotcha, yeah

14:10 the real solution is to report it as a bug upstream and squash it

14:11 TimMc: I've already opened a ticket for it, yeah. https://github.com/ReactiveX/RxClojure/issues/2

14:11 amalloy: "bug: uses gradle"

14:11 technomancy: be the change you want to see in the world

14:12 amalloy: TimMc: "occasionally"? i can't imagine why it wouldn't be every time

14:13 technomancy: amalloy: it might be that ranges have the same daily caching logic as snapshots

14:13 and failures are cached, which is almost always the wrong thing, but could accidentally be helpful in this situation

14:15 TimMc: That's my best guess, although it will also happen multiple times in the same day (sometimes.)

14:15 joshuafcole: Why does the transitive dependency happen in the first place? Are there cases where that is a useful behavior?

14:16 technomancy: joshuafcole: sure, like ... every time there's not a version range, basically?

14:18 joshuafcole: Sorry, maybe I'm using the wrong terminology (or am misunderstanding the problem). but is sounds like if B depends on A, excluding x from A, and C depends on B, then C gets x as a dep regardless of B's exclusion?

14:19 technomancy: oh, yeah I'm not sure about that

14:19 tac: Does Clojure merely require the JRE? (and not the JDK?)

14:19 technomancy: we get a whole bunch of behaviour from aether that is 95% golden, and there is the occasional questionable decision thrown in.

14:20 they're rare enough that it's not worth the headache of diverging from their implementation, but they do crop up every once in a while.

14:20 tac: correct

14:21 seangrove: technomancy: I've been looking at Mirage and Halvm for fun recently - have you found OCaml's type system to be useful at all?

14:21 joshuafcole: Ah I see. I'll look into Aether. I'm just trying to examine the turtles beneath my feet now, so if the tower teeters on me later I'll know which direction to move in. :)

14:21 technomancy: seangrove: yeah, it is wonderful.

14:22 csd_: How do I easily convert from hash-set (#{1} #{2} #{3}) to list (1 2 3) ?

14:23 amalloy: apply concat

14:23 seangrove: ,(apply concat (hash-set #{1} #{3} #{2}))

14:23 clojurebot: (3 2 1)

14:24 seangrove: As per amalloy's frighteningly quick suggestion

14:24 amalloy: frighteningly quick is at least like twice as fast. that took almost a minute

14:25 csd_: amalloy: thanks thats useful, but is there a way that shows the behinds the scenes of how to convert the type from one form to the other?

14:25 joshuafcole: Frighteningly quick is at least 30 seconds.

14:25 noted

14:27 imanc: newb question, but why doesn't that result in '(#{1} #{2} #{3}) ?

14:27 amalloy: imanc: it's the difference between apply concat vs just concat

14:27 technomancy: seangrove: I was super impressed with ocaml's types; they never got in the way and always pointed me at places where I made actual mistakes.

14:27 seangrove: the one exception (to never getting in the way) was code that dealt with serialization; you do need to do more spoon-feeding there if you're not working against a schema.

14:28 seangrove: technomancy: I've been playing around with Haskell a bit, and I haven't found the types to be a bother really, once I got past the syntax

14:28 tac: technomancy: The amazing thing is when you go to refactor typed code. You spend an hour or two fixing type errors, then it mostly just works after it compiles again :D

14:28 technomancy: tac: the codebase I was working on was pretty tiny (under 1kloc) so it's not really representative, but I found that to be mostly true

14:29 also ocaml is super easy to pick up if you know clojure

14:29 you can be relatively productive in a week

14:29 turbofail: clearly we need a hybrid of the two. clojaml

14:29 technomancy: as long as you're willing to just spam your code with moar parens when you can't figure out the precedence rules

14:29 justin_smith: csd_: regarding "behind the scenes", most sequence operations call seq on their arguments ##(map seq [[1 2 3 4] '(1 2 3 4) #{1 2 3 4} {1 2 3 4}])

14:29 seangrove: That was definitely one of the bigger annoyances, I mised sexp's

14:29 lazybot: ⇒ ((1 2 3 4) (1 2 3 4) (1 2 3 4) ([1 2] [3 4]))

14:30 technomancy: seangrove: yeah, but I was surprised that I didn't miss macros. just the regularity and predictability.

14:30 tac: the one and only thing that keeps me from seriously looking into ocaml is that silly GIL

14:31 it sounds like they are working to fix that, though

14:31 technomancy: tac: I find that just makes it complementary to Clojure.

14:31 justin_smith: my ocaml variant idea is ocalm - it's the lazy ocaml

14:31 turbofail: huh. why would ocaml need a GIL?

14:31 seangrove: tac: Which language are you comparing it to?

14:31 technomancy: if you need something big and beefy with concurrency, it's not a great fit for ocaml; if you need something small and lightweight, it's not a great fit for clojure.

14:31 turbofail: for the GC

14:31 turbofail: do they use reference counting or something?

14:31 tac: turbofail: probably multithreaded programming just wasn't a priority

14:31 Bronsa: when I first started learning lisp, macros were the thing I was most excited about. Now I find myself trying to avoid using them as much as possible

14:32 tac: seangrove: I use mostly Haskell and Python.

14:32 justin_smith: and backporting concurrency to something not designed with concurrency in mind is usually a huge PITA

14:32 technomancy: actual concurrent production GC is incredibly difficult to do well. afaik it's only been implemented 5 times or so total.

14:32 tac: Trying to get clojure installed and running atm so I can go visit a Clojure meetup in town tomorrow night

14:32 justin_smith: tac: don't install clojure -install lein

14:32 tac: I'm slowly learning this

14:33 technomancy: like, in the entire world.

14:33 tac: I installed lein (not sure what it's for), and did a ./lein new hello

14:33 justin_smith: tac: lein is the build tool and dependency manager. One of the dependencies it handles is clojure itself

14:33 tac: oh, and I can apparently run it

14:33 neat

14:33 is lein a clojure thing, then?

14:34 justin_smith: yes, and it's one of the best things about clojure IMHO

14:34 turbofail: there's still a big difference between a not-quite-concurrent GC and a language runtime with a GIL

14:35 tac: why is it annotated -main instead of main?

14:35 justin_smith: tac: that's how gen-class works

14:35 -foo is the method foo

14:35 tac: ah

14:35 justin_smith: main needs to be a method

14:35 amalloy: tac: because main is a special case of gen-classing, which uses - as a prefix to say "this should be a generated method"

14:36 tac: and there's no compile cycle in clojure (by default)?

14:36 I just run my project with lein?

14:36 justin_smith: tac: every clojure statement is compiled when evaluated

14:36 there is the possibility of doing an uberjar / jar package - but that's more about packaging than compiling usually

14:37 amalloy: tac: i don't actually run with lein very often. either i'm developing, in which case i do everything from the repl; or i'm releasing/deploying, in which case i build a jar

14:37 justin_smith: unless you use :aot - but :aot is very unpopular and a huge source of bugs

14:37 tac: gotcha. so you can ship jars to Corporatus, and they don't need to ask any questions about which technology you wrote your middlewarez in

14:37 amalloy: how do you launch the repl then?

14:37 justin_smith: tac: so you can run your code on the prod server without installing anything but a jvm on the other end

14:38 amalloy: well, really i do it from emacs, with lein jack-in

14:38 technomancy: justin_smith: AOT during development, specifically

14:38 amalloy: but you can use lein repl if you aren't ready to figure out editor tooling

14:38 justin_smith: technomancy: sure - but even in production how often is it really useful?

14:38 technomancy: justin_smith: depends on whether you care about startup time

14:38 tac: ah, lein repl does the trick

14:39 I don't think i need to be at a point tomorrow where I'm shipping code. But just knowing basic basic syntax would help me mingle with the Clojure crowd

14:39 technomancy: justin_smith: it's also a decent sanity check that everything actually compiles if you haven't bothered to set up a proper ci->deploy pipeline

14:39 justin_smith: tac: if you had created the project with lein new app hello you could also use "lein run" (though the changes needed to make a "lein new" project runnable are pretty minor too)

14:40 technomancy: good point, I usually use "lein do check test" for that

14:40 celwell: Should I use buddy or friend for my authentication needs?

14:40 justin_smith: that's "lein do check, test" of course

14:40 technomancy: justin_smith: IMO `lein compile :all` is better than check unless you're hypersensitive to reflection.

14:41 justin_smith: technomancy: what's the improvement?

14:42 technomancy: justin_smith: less noisy, speeds up boot

14:42 it's minor though

14:43 amalloy: celwell: i've never heard of buddy. it sounds like it must be based on friend

14:43 tadni: Hrm, cider doesn't seem to be opening an nrepl conncetion.

14:43 turbofail: hm. http://www.ocamljava.org/ is a thing

14:43 technomancy: I'm not convinced check is worth including as its own task tbh; it's just compiling with warn-on-reflection, and then discarding the class files

14:44 it would be better expressed as a composition of existing tasks

14:44 celwell: amalloy: I think it's relatively new https://github.com/niwibe/buddy

14:44 technomancy: turbofail: wow

14:45 wait, both implementations are made by different people named Xavier?

14:45 weird

14:45 turbofail: if it actually works it seems like it'd be a great replacement for scala

14:45 justin_smith: turbofail: my thoughts exactly

14:49 turbofail: hm. looks like it still needs some work

14:49 still interesting though

14:51 technomancy: similar to erjang

14:51 it's pretty amazing how much progress that project was able to make as a one-man-show

14:51 especially compared to jruby, which basically didn't get close until it had corporate backing

14:51 drguildo: does anybody have any advice for debugging a process that hangs?

14:54 aperiodic: drguildo: check to make sure all your loop/recurs terminate

14:54 that's usually the problem if the process sits there spinning without blowing stack

14:54 drguildo: aperiodic, there are none

14:54 mdrogalis: drguildo: Check out jstack

14:55 You can see what a running pid is up to

14:56 drguildo: mdrogalis, thanks

14:56 tac: I saw on a video the other day that 'nil' signals the end of an iterator

14:56 mdrogalis: drguildo: Np

14:56 tac: Just to be sure, that means you can't have nils present anywhere in your iterator stream, right?

14:57 (unless you box them somehow)

14:57 turbofail: iterators? we don't really do iterators in this part of town

14:58 tac: whatever the proper name for them is

14:58 seq's

14:58 turbofail: you can have a nil in a seq just fine

14:58 mdrogalis: tac: Need a little more context. Maybe you're thinking of something with core.async?

14:58 turbofail: (take 10 (repeat nil))

14:58 tac: oh, is it that if the tail of a seq is nil, then the sequence is over?

14:59 turbofail: yeah, either nil or the empty sequence '()

14:59 tac: gotcha

14:59 turbofail: usually you query for that using empty?

14:59 mdrogalis: tac: I think you saw something pretty specific that doesn't extend to a larger context.

15:00 tac: I think it was Rich Hickey for Lisp Programmers

15:00 mdrogalis: Eh, that guy doesnt know what he's talking about.

15:00 schmee: how do I implement a custom `println` for a record?

15:00 mdrogalis: Kidding. Yeah, not sure what he'd be referencing there.

15:01 |xk05|: ok, lesson #1, start LightTable in a different terminal tab than the one you will be using lein in

15:01 tac: ,(1 . 2)

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

15:01 tac: Does Clojure not have dotted cells like in some lisps?

15:01 turbofail: nope

15:01 technomancy: tac: correct

15:01 turbofail: good riddance if you ask me

15:02 tac: I agree

15:02 Does the tail always have to be a list, then?

15:02 dnolen_: tac: a seq

15:02 tac: gotcha

15:02 dnolen_: or nil

15:02 technomancy: unlike CL, the empty list is distinct from nil

15:02 but they are related in ways that are somewhat surprising

15:03 ,(seq ()) ; kind of makes no sense, but there you have it

15:03 clojurebot: nil

15:03 tac: seq there is just doing a coercion?

15:03 from the empty list to a sequence?

15:03 technomancy: I'm not sure what it's doing =)

15:04 nil is not a sequence

15:04 tac: well, it's Java's null

15:04 so it's whatever type you want

15:04 technomancy: anyway all that to say there are some behaviours that are simply arbitrary that you have to memorize

15:05 TimMc: ~seqs and colls

15:05 clojurebot: seqs and colls is http://www.brainonfire.net/files/seqs-and-colls/main.html

15:05 tac: gotcha

15:05 technomancy: yeah, that's a good guide

15:05 tac: Out of curiosity, does anyone here go to the Chicago Clojure meetup?

15:06 turbofail: hm. i don't think i've ever bothered memorizing that

15:07 technomancy: turbofail: not necessarily all the charts there, but the (seq? (seq ())) ; -> false weirdness at least

15:08 turbofail: i didn't know that one either. it's never come up

15:08 i don't think i typically call seq at all really

15:08 technomancy: you see seq used as a predicate for non-emptiness a lot in the wild IME

15:08 turbofail: hm

15:08 technomancy: the official style guide even says to prefer it to (not (empty? ...))

15:08 turbofail: i always use not-empty for that

15:08 technomancy: (which I think is silly, but hey)

15:09 joshuafcole: I find it interesting that (seq? nil) is false but (map fn nil) is valid. Do you guys know the reasoning behind (seq? nil) being false?

15:10 technomancy: turbofail: hm; actually I'm not seeing it on the wiki, but I know Rich has said it several times.

15:10 stuartsierra: joshuafcole: nil is a sequence terminator

15:11 technomancy: joshuafcole: I think the simplest way of explaining it is that map, etc simply accept anything you can safely pass to seq

15:11 turbofail: though not-empty basically just delegates to seq

15:11 lol

15:11 stuartsierra: technomancy: It's in the docstring for `empty?` :)

15:12 joshuafcole: Interesting, gotcha

15:12 technomancy: stuartsierra: hah, there you go. oddly enough not in the doc for not-empty though.

15:12 http://p.hagelb.org/mystery.gif

15:12 tac: the binding keyword creates dynamically-scoped variables. is that right?

15:13 technomancy: tac: no, it doesn't create them

15:13 it just binds them to new values

15:17 tac: oh hm

15:17 so binding mutates a global variable, and then when the scope ends, it mutates it back?

15:17 technomancy: vars are mostly created by def and the macros that expand to them

15:18 tac: s/global/thread-local

15:18 technomancy: technically it's just pushing a new value onto a stack, bit it's similar to mutation.

15:18 *but

15:18 tac: right right

15:19 so operationally, they work like implicit parameters that get threaded through your function calls

15:19 technomancy: vars are neat... they are deceptively similar to concepts in other languages but have their own semantics which IMO are a lot nicer than what you usually see

15:19 yup

15:19 tac: I guess that's a lot like the reader monad

15:20 stuartsierra: The effect of `binding` isn't global, though, it's local to a thread.

15:20 tac: yeah

15:20 virmundi: where should I put documentation for a configuration object in a library I'm making like clojure.java.jdbc? Should it go in the read me? I've sprinkled pertinent parts of the configuration at various api points.

15:21 tac: if it were global, you'd have some janky semantics because of the changing values

15:22 the docs mention a clj command line tool

15:22 if i'm using lein, I just ignore clj.. right?

15:22 turbofail: it's basicallly just running `java -cp clojure-x.x.jar clojure.main'

15:23 tac: I'm not even sure where lein puts the clojure jar

15:23 stuartsierra: tac: What docs? There's no "official" clj command-line executable.

15:23 justin_smith: tac: under ~/.m2

15:24 tac: http://java.ociweb.com/mark/clojure/article.html

15:24 you can CTRL+f for the clj instance I'm referring to

15:24 "$ clj vars.clj

15:24 "

15:25 oh, and I'm hopping around, so many it was defined earlier and I missed it

15:25 justin_smith: "use the shell script for executing Clojure files described earlier"

15:25 tac: How are sets typically implemented?

15:26 turbofail: http://en.wikipedia.org/wiki/Hash_array_mapped_trie

15:27 stuartsierra: justin_smith, tac: there doesn't appear to be any description of a `clj` executable earlier on the page. Maybe a relic of something older.

15:27 tac: very likely, probably!

15:28 So to put something into a set, it needs to be hashable and support equality comparison

15:28 justin_smith: tac: luckily, all java objects support that

15:28 and all primitives are trivially coercible to object form

15:30 will2357: Hey all, I'm fairly new to Clojure, and I was wondering if anyone has any suggestions for a fault tolerant messaging system/framework for clojure. I've seen Langohr, which runs on RabbitMQ, but as they say it is not an "API for task queues that hides all the AMQP machinery from the developer". Anyone know of a simple API for task queues?

15:30 That happens to be fault-tolerant (i.e., can't lose a message due to a handler crash)?

15:31 SagiCZ1: how about oracles activeMQ with clojures java interop?

15:32 tac: justin_smith: I think I'm thinking with my haskell glasses on again, thinking to myself "function objects are incomparable"

15:33 justin_smith: tac: they aren't ordered, but they can be equal or not (in clojure)

15:33 SagiCZ1: clgv: are you here by any chance?

15:33 justin_smith: ,(= rand #(rand)) ; tac

15:33 clojurebot: false

15:33 justin_smith: ,(= rand rand) ; tac

15:33 clojurebot: true

15:34 justin_smith: ,(hash rand)

15:34 clojurebot: 2416519

15:35 justin_smith: ,(isa? (class rand) Object)

15:35 clojurebot: true

15:35 tac: but

15:35 ,(= rand (fn [] (rand)))

15:35 clojurebot: false

15:36 justin_smith: yes, it is a weak equality

15:36 and #(rand) is just a fancy way of saying what you did above

15:37 or maybe we could call it a conservative equality, that misses many chances to label equivalent objects as equal

15:37 ,(= #(rand) #(rand))

15:37 clojurebot: false

15:38 tac: sets, arrays, lists, and maps are all immutable, right?

15:38 justin_smith: arrays are mutible

15:38 vectors are immutible

15:38 tac: gotcha

15:39 can vectors change length? Or is it just their cells can be repointed at other things?

15:39 justin_smith: they can't change, they are immutible

15:40 tac: err

15:40 hmm

15:40 I didn't read that carefully enough

15:40 justin_smith: though you can create a new one that appends to an old one efficiently

15:40 arrays cannot change length either

15:40 schmee: when implementing a protocol on a record, can the functions in the protocol call each other?

15:40 I'm getting some errors and I'm not sure if that's the issue, or something else...

15:41 justin_smith: tac: and yeah, cells in an array can be reassigned

15:42 tac: [a b c] is array syntax right?

15:42 and (a b c) is.... vector?

15:42 justin_smith: no

15:42 [a b c] is a vector

15:42 (a b c) is calling a on the args b and c

15:42 '(a b c) is a list literal

15:43 there is no literal notation for arrays, they are an underlying jvm construct

15:43 tac: ahh ok

15:43 so they are less "blessed" in clojure, right?

15:43 justin_smith: ,((juxt identity type) (into-array [1 2 3]))

15:43 clojurebot: [#<Long[] [Ljava.lang.Long;@17e1dd2> [Ljava.lang.Long;]

15:45 justin_smith: tac: right - they are one of the primitive things defined by the jvm, and they underly other types

16:00 stuartsierra: tac: Clojure tests equality by value for immutable data structures and by identity for everything else, which includes most Java objects.

16:00 tac: I figured that's probably how it worked

16:00 although functions are immutable ;P

16:02 stuartsierra: Yes but (compiled) functions are not data structures as far as Clojure is concerned.

16:03 technomancy: stuartsierra: I don't think that's accurate re "most Java objects"

16:03 stuartsierra: sadly = will return true for two different HashMaps

16:04 turbofail: really?

16:04 oh right it dispatches to the equalTo method if it has one

16:04 technomancy: ,(let [a (doto (HashMap.) (.put "a" "a")), b (doto (HashMap.) (.put "a" "a"))] (= a b)) ; oops

16:04 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: HashMap, compiling:(NO_SOURCE_PATH:0:0)>

16:04 technomancy: aw come on

16:05 ,(let [a (doto (HashMap.) (.put "a" "a")), b (doto (java.util.HashMap.) (.put "a" "a"))] (= a b)) ; oops

16:05 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: HashMap, compiling:(NO_SOURCE_PATH:0:0)>

16:05 technomancy: ,(let [a (doto (java.util.HashMap.) (.put "a" "a")), b (doto (java.util.HashMap.) (.put "a" "a"))] (= a b)) ; oops

16:05 clojurebot: true

16:05 technomancy: third time's the charm

16:05 anyway, clojure.core/= is not to be trusted with arbitrary java objects

16:05 stuartsierra: Yes, technomancy is right. Clojure's = falls back to Java Object.equals, which can be fishy.

16:05 tac: is the / to denote a namespace?

16:07 technomancy: yeah

16:07 * tac learns

16:07 tww: newbie questions: creating a hash-map from a list of key,values. what's the preferred way: (apply hash-map (list :a :apple :b :banana :p :peach)) OR (eval (cons hash-map (list :a :apple :b :banana :p :peach))) OR something else?

16:07 tac: eval is only one-letter off from evil

16:08 At least, that's what I've been trained to think ;)

16:08 technomancy: ,(let [a (doto (java.util.HashMap.) (.put "a" "a")), b (doto (java.util.HashMap.) (.put "a" "a"))] (try (= a b) (finally (.put a "a" "b")))) ; better yet

16:08 clojurebot: technomancy: Gabh mo leithscéal?

16:08 technomancy: oh, does the bot block try/catch? boo.

16:10 amalloy_: technomancy: well, blocks catch

16:10 amalloy: and finally, i guess, right? so catch is allowed but not if you use it for anything

16:10 ,(try 1 (finally 2))

16:10 clojurebot: amalloy: Titim gan éirí ort.

16:11 technomancy: ,(let [a (doto (java.util.HashMap.) (.put "a" "a")), b (doto (java.util.HashMap.) (.put "a" "a"))] (future (Thread/sleep 100) (.put a "a" "b")) (= a b)) ; fun times

16:11 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

16:11 technomancy: drat

16:12 amalloy: tww: apply hash-map would be the way to go, although why do you have such a weird list instead of something like [[a apple] [b banana] [c peach]] is a consideration too - usually it's nice if each item in a list represents the same sort of thing

16:14 ,(try 1)

16:14 clojurebot: 1

16:14 tww: amalloy: thanks. i do have a sane list of lists for my hash-map

16:15 amalloy_: i appreciate the help

16:24 schmee: is it possible to use loop/recur when implementing protocols?

16:25 razum2um: can I conditionally require some code like (ns some (if cond (:require [lib])))) ?

16:26 joegallo: razum2um: require is available at runtime

16:26 gfredericks: razum2um: you can do (ns some) (if cond (require '[lib]))

16:26 joegallo: so, outside of the ns form

16:27 razum2um: ok, thanks

16:36 virmundi: justin_smith: is there a short way to conditionally add a key/value to a map if the value is not nil?

16:39 justin_smith: the best I can figure is (merge {…} (if (cond?) {..}))

16:41 mpenet: ,(doc update-in)

16:41 clojurebot: "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

16:45 gfredericks: ,(defn assoc-when [m k v] (cond-> m v (assoc k v)))

16:45 clojurebot: #'sandbox/assoc-when

17:11 pvinis: i set up a project with lein.

17:11 hi

17:11 i set up a project with lein.

17:11 justin_smith: congratulations

17:11 pvinis: i set up a project with lein.

17:12 i set up a project with lein.

17:12 i set up a project with lein.

17:13 i want to have a repl and do like (add-person "guy"), and then have the repl ask me, "age?" and i put 30, and then it constructs a record with all info, or just run (add-person {:name "guy" :age 30}).

17:13 is this interactive adding of people possible?

17:13 justin_smith: pvinis: sure, using an atom for example

17:15 ,(do (def people (atom [])) (defn add-person [name age] (swap! people conj {:age age :name name})) (add-person "guy" 30) @people)

17:15 clojurebot: [{:age 30, :name "guy"}]

17:15 justin_smith: ,(add-person "doll" 42)

17:15 clojurebot: [{:age 30, :name "guy"} {:age 42, :name "doll"}]

17:15 justin_smith: pvinis: maybe something like the above

17:16 aperiodic: pvinis: if you're asking about how to get the input then you probably want to look at ##(doc read-line)

17:16 lazybot: ⇒ "([]); Reads the next line from stream that is the current value of *in* ."

17:16 pvinis: aha. i will try that. thanks justin_smith

17:16 gtrak: what's the difference between clj-oauth vs oauth-clj?

17:17 pvinis: aperiodic: i probably need to get the input as well. ill check it. thanks

17:18 justin_smith: one gotcha: with print, you will also need to call (flush) if you want a prompt to show up without a newline

17:19 technomancy: gtrak: M-t+

17:19 ?

17:19 gtrak: there are two libs that do basically the same thing afaict, clj-oauth is more relied-on in clojuresphere.

17:25 pvinis: can i get a repl when i do lein run? like get a repl as my main loop of the app?

17:27 justin_smith: pvinis: lein repl

17:27 technomancy: pvinis: check out the tools.nrepl repo if you want a repl server embedded in your actual main

17:27 justin_smith: or use clojure.tools.nrepl

17:28 pvinis: cool. thanks

17:28 justin_smith: https://github.com/clojure/tools.nrepl

17:29 pvinis: im trying to learn clojure by making an app. its interesting, but can be a bit confusing

17:29 arohner: woohoo: "java(5182,0x1297e6000) malloc: *** error for object 0x8280400: pointer being freed was not allocated"

17:29 justin_smith: woah

17:29 arohner: did you call a private method somewhere to make that happen?

17:29 if not, congrats!

17:29 if so, that's cheating

17:29 arohner: justin_smith: nope. Playing NIO & byte buffers

17:31 pvinis: thats another thing.. if something is not right and needs debugging, you get a whole sea of seemingly random errors. for a noob, thats too much

17:31 too much unknown stuff early on

17:32 amalloy: justin_smith: sounds more like a native method than a private method

17:32 technomancy: pvinis: yeah, the error messages from clojure are pretty bad. Usually it helps to isolate things where you can call lower-level functions directly from the repl and work your way out to bigger things till you can identify the problem.

17:32 justin_smith: pvinis: yeah, the depth of the stack by the time an error is found is definitely not a n00b friendly aspect of clojure

17:32 amalloy: i've certainly gotten jvm segfaults as a result of native code i edited

17:32 technomancy: pvinis: don't underestimate the power of having interactive access plus immutable data structures that you can copy/paste

17:33 pvinis: on that note, tools.trace can be really helpful too.

17:34 pvinis: i saw that there is a c compiler for clojure. is there a "native" c lisp?

17:34 ill check out tools.trace

17:35 schmee: pvinis: the errors were the biggest hurdle for me when starting out with clojure as well... after some time they start to make more sense, but at first it is very frustrating

18:10 danielcompton: is it possible to explore dependency jars in emacs like you can from IntelliJ?

18:11 technomancy: danielcompton: M-. works from cider sessions to do this, yeah

18:11 you can even edit them if you're insane

18:11 danielcompton: woah this is awesome

18:11 * amalloy has done that. can confirm: you need to be insane

18:14 danielcompton: technomancy: which symobls does it show?

18:14 it doesn't seem to be all of the ones required in my namespace?

18:16 if I `use` a library it shows it as a var, if I require it then I can't see the prefixed namespace/symbol

18:16 technomancy: not sure what you mean; it's always worked for me

18:18 danielcompton: In my :require I have [plumbing.core :refer [dissoc-in]]. I can M-. and see dissoc-in, but no other vars from plumbing.core

18:18 technomancy: oh, sure

18:19 danielcompton: is that expected/is there any way to M-. on a namespace?

18:20 amalloy: danielcompton: M-. only lets you look up vars which are valid in the current ns

18:21 danielcompton: amalloy: isn't plumbing.core/assoc-when a valid var in a ns?

18:21 amalloy: in the *current* ns. you only referred dissoc-in

18:22 technomancy: danielcompton: if you fully-qualify the var, M-. will work.

18:23 danielcompton: can you explain what you mean when you say fully-qualify?

18:23 amalloy: danielcompton: type the following: plumbing.core/assoc-when

18:23 and then press M-. while pointing at it

18:24 danielcompton: oh wow, I was only running it from the minibuffer, I thought I could only pick vars that were in the minibuffer selection list

18:25 *movie voice* Cider: This changes everything, again.

18:27 justin_smith: "In a world where stability is only a legend, and new user's are funneled to snapshot versions - one project will change the way you think about clojure, and emacs, forever"

18:27 rated nc-17

18:28 *users

18:29 danielcompton: contains intense themes, aerial battle sequences and strong language

18:29 technomancy: fact: aerial battle sequences are the best battle sequences.

18:30 mdeboard: The Little Mermaid had a really great one

18:31 Aerial was all like, "No, evil queen octopus lady!" then shoots her voice at her

18:31 Really great Aerial battle

18:31 Wild_Cat: technomancy: the entirety of Macross Plus shows that statement to be absolutely correct.

18:32 justin_smith: Wild_Cat: I am disappointed that you did not attempt a macro themed pun

18:32 technomancy: >_<

18:32 Wild_Cat: justin_smith: I'm still a Clojure noob. :p

18:36 justin_smith: (defmacross valkyrie [] ...)

18:46 danielcompton: mdeboard: just got that, I was thinking for a while how you have an aerial battle underwater

18:47 mdeboard: danielcompton: :P

18:54 If I'm reading the source right, nrepl clients handle creation of nrepl server instances?

18:57 justin_smith: mdeboard: huh? you use clojure.tools.nrepl.server/start-server to start listening to connections

18:57 the client doesn't make new instances

18:57 do you mean sessions?

18:57 elben: Anyone find themselves always reaching for core.async/thread instead of jvm threadpools to build N processor, M consumer systems because it’s so easy?

19:00 mdeboard: justin_smith: No, I'm looking at https://github.com/technomancy/leiningen/blob/master/src/leiningen/repl.clj#L243-L246

19:01 and the `lein repl' command itself

19:01 justin_smith: lein creates the server and also attaches a client for the user to interact with

19:02 that's not the same as a client being in charge of creating server instances

19:02 you can start-server without ever spawing a client

19:03 or maybe I am misunderstanding you

19:17 mdeboard: justin_smith: No, I think you're udnerstanding me ok. I'm just trying to internalize how it works.

19:17 so I'm probably not saying what I mean

19:18 justin_smith: so, the code you linked to invokes reply

19:18 reply in turn invokes nrepl

19:18 you can use nrepl to create a client or a server within your process - leiningen happens to do both (but via reply)

19:20 nhanH: Is "lein repl" supposed to ignore the user-wide profiles in ~/.lein/profiles.clj ?

19:20 justin_smith: no, those should get merged into your settings

19:22 nhanH: so, apparently when I run "lein repl", the user-wide profile is being ignored, do you have any suggestion on how to find out what's wrong?

19:22 justin_smith: can you paste your profiles.clj and describe the symptom (what you expect, and what you get instead)

19:23 paste in a site like refheap.com that is, of course

19:23 nhanH: I use environ to read out the setting, to make it short, if I copy the profiles.clj into the project folder, I can call env to get the setting in repl

19:24 but if the profiles.clj is only in ~/.lein, then I can't

19:24 http://pastebin.com/J764GanH the profiles.clj file

19:25 justin_smith: does your project.clj have an :env key that would override that maybe?

19:26 nhanH: here http://pastebin.com/chuCzjuS

19:26 I don't think there is anything to override

19:27 so I'm using lein-environ to generate .lein-env to be used by environ

19:27 that file has an empty map if I don't have a profiles.clj under my project folder

19:27 justin_smith: yeah, that should be working

19:29 nhanH: any suggestion?

19:29 justin_smith: nhanH: actually - looking at the environ docs, environ does not get the bindings from lein

19:30 nhanH: "lein test" work properly with the user-wide profiles though

19:30 wait actually hmm

19:30 let me see

19:30 justin_smith: I think it loads the project.clj itself - and the docs mentions a profiles.clj in your repo, but does not mention anything about getting stuff from your main profiles.clj

19:32 nhanH: hmm, I just checked, and apparently "lein test" does run and get the main profiles.clj properly

19:32 so environ can get the bindings from lein

19:32 it just doesn't do it for the repl

19:44 jds_: does anyone here have experience using flambo with apache spark? i'm having some issues trying to use a non-local spark master, i believe related to serialization

20:00 sritchie: anyone know the API call to query clojars for a project’s most recent version?

20:44 danielcompton: Microsoft sharing the love for immutable objects http://www.freepatentsonline.com/y2014/0196008.html

20:48 nullptr: danielcompton: microsoft has an immutable collections impl for .net http://msdn.microsoft.com/en-us/library/dn385366(v=vs.110).aspx

20:53 razum2um1: why does lein uberjat complains about Don't know how to create ISeq from: java.util.regex.Pattern though in docs it's possible?

20:53 btw, how to compile :all except one ns

20:55 danielcompton: nullptr: and it looks like they have a patent for it too

21:05 celwell: Hello, I can't figure out how to escape a string properly. I can do it fine with certain characters, but quotes and double-quotes are giving me problems. Here is what I have: (clojure.string/escape sql-value {\' "\'" \" "\""})

21:07 danielcompton: ,(clojure.string/escape sql-value {\' "\'" \" "\""})

21:07 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported escape character: \'>

21:14 bluesnow: Hi, I'm confused about the difference between (repeatedly 10 (partial rand-int 50)) and (repeatedly 10 (fn [] (rand-int 50)))

21:15 The book Clojure Programming uses the first, but doesn't rand-int only take one argument? So I don't understand the use of partial

21:15 danielcompton: ,(doc rand-int)

21:15 clojurebot: "([n]); Returns a random integer between 0 (inclusive) and n (exclusive)."

21:16 celwell: danielcompton: so, Unsupported escape character, is actually a different error than the one I got, but any ideas

21:17 bluesnow: danielcompton: Uh, I still don't see it. For example, when I do (rand-int 10 50), I get an ArityException

21:18 so why is the book using partial in the expression, instead of just fn?

21:18 aperiodic: ,((partial rand-int 50))

21:18 clojurebot: 15

21:19 bluesnow: Ah I see. So they just use partial to define the function instead of using fn, since the function definition using partial is shorter..

21:19 danielcompton: bluesnow: I'm not quite sure how to describe the difference between the two, they both return a function

21:19 bluesnow: but partial curries the arguments (I think)

21:19 bluesnow: danielcompton: Right. But in the case of the repeatedly + partial/fn rand int expression, it's the same, right?

21:20 because rand-int only takes one arg anyway

21:20 so there's nothing to curry / no extra argument that can be passed

21:20 danielcompton: partial returns a function taking a variable number of arguments. So the result is the same but they're not the same function

21:20 bluesnow: danielcompton: Right.

21:20 Ok, I get that.

21:21 Thanks, was just wondering why they would use partial, since rand-int can only take one argument. So it can't take advantage of any other variable args

21:25 danielcompton: bluesnow: I would say it's to show different ways of doing the same thing?

21:26 good question

21:27 bluesnow: danielcompton: Yeah, probably. It just seemed like a weird use of partial, since I usually associate a use of partial with the need for currying / passing a variable number of args later.

21:39 irctc: hey hey

21:40 how do i get UserDefinedFileAttributeView to work from clojure (noob here)

21:40 is this close? (java.nio.file.Files/getFileAttributeView (.toPath (java.io.File. "/etc/hosts")) (java.nio.file.attribute.UserDefinedFileAttributeView) (java.nio.file.LinkOption/NOFOLLOW_LINKS))

21:43 TEttinger: irctc, well to start you'd probably want to import some of those long java names

21:43 save some typing

21:44 irctc: i think i don't know how to do this: UserDefinedFileAttributeView.class in clojure

21:44 TEttinger: uh, is it a class defined inside another class?

21:44 irctc: it's an interface

21:45 TEttinger: oh ok, so you need to get the Class from that?

21:46 irctc: here's the java: UserDefinedFileAttributeView view = file.getFileAttributeView(UserDefinedFileAttributeView.class);

21:47 TEttinger: well I think you can still do (.class UserDefinedFileAttributeView), not sure -- I deal with interfaces rarely

21:49 irctc: yeah can't get that to work

21:49 figured i would try asking for help

21:51 looks like it's just (class xyz) vs (.class xyz)

21:54 TEttinger: irctc, (class java...blahView) gives me java.lang.Class , which I don't think is what you want

21:55 TimMc: (dec AOT)

21:55 TEttinger: try entering just: java.nio.file.attribute.UserDefinedFileAttributeView

21:55 lazybot is out

21:55 TimMc: :-(

21:56 How am I supposed to formally register diapproval, then?

21:56 TEttinger: irctc: using java.nio.file.attribute.UserDefinedFileAttributeView without parentheses should be the actual class

22:01 irctc: that got me farther along thx

22:11 Lanny: spectral == know-nothing nigger

22:12 TimMc: plonk

22:18 beamso: i'm attempting to share some validation errors between a parent om form component and child components. is the best way to do this through the central app state or through the state that can be associated with the component through IRenderState?

23:34 celwell: How can I escape double-quotes and single-quotes in a string? I have this, but it doesn't work: (clojure.string/escape sql-value {\' "\'" \" "\""})

23:42 beamso: celwell: {\' "\\'" \" "\""} ?

23:43 celwell: beamso: thank you.

23:44 beamso: try calling str on the output to test it

23:44 i didn't test escaping '"'

23:48 celwell: beamso: Yeah, that doesn't work for '"', but I got it to work with this: {\' "\\'" \" "\\\""}

23:50 amalloy: yikes, celwell, automatically escaping sql strings is playing with fire

23:50 are you sure you can't use parameterized queries with fixed sql?

23:50 celwell: amalloy: I wish I could do what I need with just clojure.java.jdbc

23:51 amalloy: I need to wrap values in AES_ENCRYPT()

23:52 I would probably have to back out of jdbc completely if I wanted to still use java's parameterization

23:53 danielcompton: Emacs plugins: http://3.bp.blogspot.com/-WtKPYcpHxh8/UcdueZEQYpI/AAAAAAAAAJc/3-muBcjfBUk/s1600/world+war+z+4.jpg

23:54 celwell: Hmm... now that I think about it, maybe I can just construct the INSERT string and put AES_ENCRYPT(?), AES_ENCRYPT(?), etc.

23:54 talios: danielcompton - looks like an eclipse plugin to me.

Logging service provided by n01se.net