#clojure log - May 15 2015

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

1:45 shalom1024: does have any ideas about a most convenient way to display an incanter graph in a seesaw app?

2:38 oddcully: tieTYT: it has. try youtube-dl to fetch it (unless you meant blocked blocked)

3:11 myguidingstar: tieTYT, you can use this to download from infoq https://github.com/myguidingstar/infoq-downloader

3:42 escherize: is there a trick to using dedupe on a channel?

3:44 Basically, I am using a pipeline with a chan like (chan 1 (dedupe)) and it's not working. I'm pretty sure I'm doing something wrong

8:18 sw1nn: escherize: (unique (chan)) ?

8:35 piranha: hey all! So I have this base64 value, which I can't decode properly with data.codec: http://paste.in.ua/10729/ - any ideas what's going on here?

8:41 hyPiRion: piranha: I guess you should remove the newlines in the base64 value

8:41 piranha: oh

8:41 where they came from!

8:42 hyPiRion: yeah, that helped

8:42 hyPiRion: no idea. Weird that b64 doesn't complain about that though

8:43 piranha: carmine gave me newlines inside of a value

8:43 why'd it do that to me :(

8:44 oh, newlines are there in the first place, ok

8:44 that seems like a feature of python's base64

8:45 hyPiRion: Yeah, most base64 decoders seems to skip whitespace

8:47 piranha: hyPiRion: thanks! :-)

9:41 Chauncey: Has anyone an idea what might cause a (defrecord Foo ..) to define a my-ns/->Foo instead of a my-ns/Foo ?

9:43 luxbock: Chauncey: it should define both

9:43 ->Foo is a constructor function that gets defined for each record you define

9:44 there's also map->Foo

9:44 Chauncey: aha, interesting, never knew that

9:44 But the original Foo is missing Oo

9:45 I had it in a different namespace before, where I could create records that the other namespace would later complain about as not implementing the protocols I made them implement

9:48 xeqi: Chauncey: are you `:import`ing Foo?

9:49 Chauncey: xeqi: no, the namespace in question only has quil and ... stacktraces required..

9:51 it does have [quil.core :refer :all], but I don't see how that could be a problem

9:52 Also, there are two records that have only these constructor methods available

9:52 So if it was shadowing, it'd be a pretty large coincidence

9:58 anyone? I am really confused, and not making any progress

10:01 TimMc: Chauncey: You need to (:import other.ns.Foo), not just (:require other.ns)

10:01 chouser_log: (defrecord Foo) doesn't define a var named Foo, but a class named your.namespace.Foo

10:01 TimMc: Very common mistake. Require'ing the ns loads the defrecord and creates the class, but to *refer to* the class as Foo you need to import it.

10:01 ^ ANd that, yeah -- Foo isn't a var.

10:02 Chauncey: ok, I see, thanks

10:02 That clears that up... So if I have a main drawing quil namespace with a drawable protocol, and I implement the protocol in another namespace, do I need to import that namespaces record into the quil ns too to make it know about it?

10:03 for some reason that doesn't work either

10:05 fourq: morning all

10:05 Chauncey: fourq: Morning

10:05 Does namespace loading order have anything to do with the quil thread knowing about implementations?

10:13 TimMc: It shouldn't!

10:13 Unless the Quil thread uses reflection to load it, like Class/forName.

10:14 If the ns block requires the ns that has the defrecord, you should be fine.

10:14 Chauncey: well, if it does I didn't write that :)

10:14 hmm

10:14 weird

10:15 xeqi: Chauncey: so you have a quil ns that defines the protocol. You have a second namespace that defines a record that implements the protocol. Which one is creating the instance of the record?

10:15 TimMc: You only need to require or import where you're going to reference something. (Exception: Making sure protocols and multimethod implementations get loaded.)

10:15 Chauncey: TimMc: yeah, that's what I expected too

10:15 xeqi: I create the instances in the other, non-quil ns that defines them

10:16 I tried moving them around, that's when the missing Foo occured ;)

10:18 well, I moved everyhing into the ns defining the protocol and imported it into the other, that seems to have done the trick

10:18 Still confused though

10:19 Thanks for your help guys! Moving on...

10:19 xeqi: Chauncey: were you reloading the file with the `defprotocol`? That would redefine it and make it so any instances of it before redefinition were invalid

10:20 Chauncey: xeqi: I noticed that too, but I changed the code to recreate the instances after reloading

10:21 there is basically one test function that does all the setup (conj drawables into an atom which is in the quil state)

10:29 luxbock: are there any other attributes besides :pre and :post that are used?

10:37 timvisher: am i supposed to use extend or extend-protocol to extend a protocol to a new type?

10:42 puredanger: extend should be considered low-level and not used directly

10:42 use extend-protocol to extend a protocol to one or more new types

10:42 use extend-type to have a type extend one or more protocols

10:43 if you have 1 type and 1 protocol then flip a coin :)

10:45 gfredericks: (defmacro extension-roulette [one-thing another-thing & methods] (if (zero? (rand-int 2)) `(extend-protocol ~one-thing ~another-thing ~@methods) `(extend-type ~one-thing ~another-thing ~@methods)))

10:47 Chauncey: gfredericks: that is a little buggy, but I like it :D

10:48 TimMc: gfredericks: Would you accept a PR moving the if expression into the head of the extension call?

10:48 Chauncey: also on of your things is a protocol and the other is a type, so one-thing can't always be first

10:49 but apart from that, it's core-worthy :D

10:50 gfredericks: @TimMc I think everything that can reasonably vary should vary

10:51 * TimMc sends a PR that does this but also changes whitespace all over the project

10:52 Chauncey: haha, you evil, evil man

10:53 gfredericks: good morning everybody

10:54 xeqi: does cider have a load this file into the repl, and any files that :require it command?

10:56 TimMc: xeqi: As in, reload this file and all dependants?

10:56 xeqi: yes

10:57 cfleming: ^ that is what cursive's" Load file in REPL" does right?

10:58 or am I reading https://cursiveclojure.com/userguide/repl.html backwards

11:01 crocket: clojure for the brave doesn't explain destructuring comprehensively.

11:01 Does anyone knk

11:02 Does anyone know a better learning material?

11:03 gfredericks: irc is pretty good

11:03 because destructuring isn't too complicated

11:04 so if you just ask questions about whatever info you're missing it'll probably be comprehensive pretty quick :)

11:04 TimMc: crocket: I don't know why it's on this page, but here's something: http://clojure.org/special_forms#binding-forms

11:06 puredanger: ^ I'm guessing destructuring used to be part of the compiler and was later moved to the destructuring macro?

11:06 puredanger: dunno, predates me :)

11:08 crocket: gfredericks : I will not know what I miss.

11:09 puredanger: http://blog.jayfields.com/2010/07/clojure-destructuring.html is pretty good

11:10 crocket: Du....

11:15 TimMc: puredanger: Oh, I'm in the comments there, being an adorable Scheme immigrant!

11:16 puredanger: welcome to our land of many types of brackets

11:16 mdrogalis: puredanger: Predates almost everyone https://twitter.com/chrishouser/status/599221332715307008

11:16 crocket: braveclojure.com doesn't explain :or keyword in destructuring.

11:16 alexbaranosky999: dumb question guys: I thought in cider on Emacs I could M-. into a jar and compile changes in it. Is that true?

11:17 TimMc: puredanger: I remember finally realizing that let and let* did not mean the same thing as in Scheme. (I think let* allows multiple bindings? I've forgotten by now.)

11:18 puredanger: alexbaranosky999: I think you can M-. into a jar and change .clj files (which I think is pretty evil actually)

11:20 arohner: alexbaranosky999: puredanger: both are true

11:20 TimMc: Can confirm, have done this on a running server and reloaded the code.

11:20 arohner: you can edit files in the jar, and you can also C-c C-k the modified source file, w/o saving

11:20 TimMc: Have not needed to do this on a production server, thank goodness.

11:29 ("What do you think this is, an Erlang shop?")

11:35 alexbaranosky999: puredanger: arohner: I thought so, thanks. I need to basically debug a jar we're using, and wasn't seeing my changes reflect when compiling

11:35 In general I agree, it's a little evil

11:35 arohner: not something you should make a habit of, but it can be a lifesaver

11:36 puredanger: it's ok if you actually notice you're doing it. I've done it accidentally before though and really caused myself some head-scratching later.

11:36 alexbaranosky999: arohner: as you an see I haven't done it in so long, I forget if it is possible! :)

11:38 TimMc: puredanger: Oh yikes, hadn't thought about the implications of M-. specifically. I don't have that integration running most of the time, so I just open the jar file directly and find the appropriate .clj.

11:38 I can totally see doing it by accident.

11:38 puredanger: I've had that happen where we had a multi-module project so I was still in "our" code, just different "project"

11:40 alexbaranosky999: puredanger: yeah if you don't notice, that can be a big-time pain later to figure out

12:09 crocket: Does anyone know a better book than braveclojure.com ?

12:10 pbx: crocket, i'm enjoying the o'reilly book

12:10 aka http://shop.oreilly.com/product/0636920013754.do

12:10 wasamasa: crocket: living clojure is cool

12:11 TimMc: crocket: Better in what sense? Is the style just not matching? Too fast? Too slow?

12:11 ~books

12:11 clojurebot: books is http://www.pragprog.com/titles/shcloj/programming-clojure

12:11 TimMc: among others

12:13 crocket: TimMc, braveclojure didn't mention :or keyword when describing destructuring maps.

12:14 mp: .wc

12:26 crocket: I think braveclojure is ok in overall, but I'm afraid that it might be missing important details.

12:26 tmarble: macro help needed! I want to create a defrecord with type hints http://paste.debian.net/plain/177667 (but as real ^String not "^String")??

12:26 lazybot: tmarble: What are you, crazy? Of course not!

12:26 puredanger: no one resource covers 100% of the details

12:27 sdegutis: When is Clojure 1.7.0 expected?

12:27 puredanger: braveclojure is a great fun introduction that covers lots of useful stuff. I would augment with at least one more to get more complete coverage.

12:28 sdegutis: at this point, I think there is maybe 1 or 2 items that need attention. assuming no other reports from beta 3, I'm hoping we can do rc1 next week and then it's just a matter of getting enough feedback that we feel ok cutting a release

12:28 crocket: puredanger, one more book?

12:28 sdegutis: Nice.

12:28 crocket: duh

12:28 sdegutis: puredanger: thanks

12:28 crocket: Do people use :or keyword in destructuring maps?

12:28 puredanger: crocket: yes, for defaults

12:29 crocket: puredanger, defaults?

12:29 puredanger: we actually cover that use case in "Clojure Applied"

12:29 crocket: puredanger, We?

12:29 puredanger: like: I get a map of options, but want to supply defaults if some options aren't supplied

12:29 "we" = me and Ben Vandgrift, as authors

12:30 In https://pragprog.com/book/vmclojeco/clojure-applied

12:31 crocket: Which book do I better read after 'braveclojure?

12:31 chouser: tmarble: maybe ~@(map #(vary-meta % assoc :tag 'String) args)

12:31 puredanger: that book is designed as an *intermediate* book btw, and is use-focused (I need to do X) rather than feature-focused. it intentionally leaves out lots of features.

12:32 crocket: if you want other intro books, I think the O'Reilly and Pragmatic ones are also pretty thorough. Programming Clojure and Clojure Programming, whichever matches those correctly. :)

12:33 it's pretty old now, but I like the treatment of certain subjects a lot in Practical Clojure by Apress too.

12:34 crocket: I don't see a difference between clojure's built-in repl and lein repl.

12:34 lein repl seems to use nREPL which just looks like clojure's built-in repl.

12:36 zerokarmaleft: crocket: it also incorporates REPL-y, which provides some niceties summarized at the top of the README https://github.com/trptcolin/reply

12:41 crocket: zerokarmaleft, How do I get lein repl outside leiningen?

12:42 verma: hey, in cursive, is there a quick way to reformat a form, like the Meta-q stuff in emacs?

12:43 I see some talks/screencasts that seem to do it, but I am not sure how that is done

12:45 fourq: How is the addition symbol considered a truthy value? Just because it's not a false/nil value?

12:45 ;; Return value of "or" is first truthy value, and + is truthy

12:45 (or + -)

12:45 tmarble: chouser: thx, but I get (clojure.core/defrecord fred [a b]) ;; this is a real brain teaser!

12:45 fourq: since (or - +) returns -

12:48 zerokarmaleft: crocket: I'm not sure I understand your question...you can run `lein repl` independent of any particular project

12:53 gfredericks: tmarble: you do need vary-meta

12:54 tmarble: try (set! *print-meta* true) at the repl, then inspect the output again

12:54 tmarble: the ^String syntax sets metadata on the symbol, and metadata normally isn't printed

12:54 tmarble: gfredericks: ok, i'll try that

12:55 gfredericks: you and chouser are correct! thank you!

12:55 gfredericks: (inc me-and-chouser)

12:55 lazybot: ⇒ 1

12:56 TimMc: $karma zerokarmaleft

12:56 lazybot: zerokarmaleft has karma 1.

12:56 TimMc: hmmm

12:58 justin_smith: (identity justin_smith hyPiRion)

12:58 lazybot: justin_smith hyPiRion has karma 1.

12:59 justin_smith: (identity hyPiRion justin_smith)

12:59 lazybot: hyPiRion justin_smith has karma 1.

12:59 justin_smith: symmetry

13:00 crocket: http://shop.oreilly.com/product/0636920013754.do contains 630 pages, and https://pragprog.com/book/shcloj2/programming-clojure contains a lot less pages.

13:00 Does it mean the former has a lot more details?

13:00 Or, is it just verbose?

13:01 TimMc: (identity gfredericks and chouser)

13:01 lazybot: gfredericks and chouser has karma 0.

13:02 gfredericks: (identity me-and-chouser)

13:02 lazybot: me-and-chouser has karma 1.

13:02 gfredericks: woooh

13:09 m1dnight1: guys, im having some issues importing a java class in clojure. I have done it before and I think i have reproduced everything I had to, but its giving me "no such namespace"

13:10 What I have done so far is: add :java-source-paths ["interop"] to my project.clj, give the class the packagename "actors", and then in my code I do: (:import [actors BlockingStore]))

13:10 when I do lein run, it compiles the java class. so thats good, I guess.

13:12 the parts in my source are literally copy pasted from my other project, so i dont see whats wrong. the only difference now is that the class that is trying to import it is not in my "root" namespace, it is in projectname.foo.bar

13:12 crocket: Should I read http://shop.oreilly.com/product/0636920013754.do or https://pragprog.com/book/shcloj2/programming-clojure ?

13:14 zerokarmaleft: crocket: I've read both...you won't regret reading either of them

13:16 crocket: zerokarmaleft, It seems I better read the larger book...

13:16 One book to rule clojure.

13:17 As I guessed, the larger book goes very deep.

13:48 andyf: gfredericks: I see you did some changes to dynalint a while back, and I think you noted that lein-dynalint seems to be giving warnings for the Leiningen JVM. Do you know if it gives warnings for both Leiningen JVM and project JVM, or only Leiningen JVM?

13:53 irctc: Is there a core function to test if a String contains a number? (numeric? "-0.3") ; true (found one here as a backup: http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Clojure)

14:01 andyf: irctc: Only Java interop available, or a sufficiently complex regular expression and re-match

14:02 irctc: Java's parseDouble may be what you want: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#parseDouble(java.lang.String)

14:03 irctc: andyf: thanks. I'll use the rosettacode for now, which of course uses interop.. True, I could try to proactively parseDouble and catch the exc, but generating a stack trace is too costly.

14:04 andyf: irctc: There is no need to generate a stack trace if you catch the exception, yes?

14:05 irctc: andyf: the act of throwing an Java exception creates a stack trace in the exception object. Not talking about printing it.

14:06 andyf: in other words when a Java exception is thrown the stack is captured and stored in the exception in case you need it.

14:06 andyf: irctc: I was not aware of that. Out of curiosity, have you measured performance impact of that?

14:07 irctc: andyf: this is how you can ask the exception object later to print the trace.

14:09 andyf: not with this particular issue. There's a lot on the topic. For instance. http://stackoverflow.com/questions/299068/how-slow-are-java-exceptions

14:09 andyf: bottom line, if performance matters don't throw exceptions.

14:09 tcrayford____: Not always though

14:10 Some exceptions don't have stacktrace said after getting JITd

14:10 Which makes for fun debugging :/

14:10 irctc: tcrayford: Yes, I suppose there are always *exceptions* to the rule. :/

14:11 tcrayford____: See http://yellerapp.com/posts/2015-05-11-clojure-no-stacktrace.html

14:11 There's links to good references on the perf side in there

14:12 irctc: tcrawford: Thanks for the link. They mention, "perf implications" for turning stack trace generation.

14:13 tcrayford____: (I wrote that post)

14:13 irctc: tcrawford: ... on

14:13 gfredericks: andyf: I don't recall, but if I had to guess it would be lein-vm-only

14:13 seems more complicated to somehow end up doing both

14:13 tcrayford____: There are references in it to real perf posts on the topic

14:14 irctc: tcrawford: sweet!

14:14 tcrayford____: See http://shipilev.net/blog/2014/exceptional-performance/

14:14 andyf: gfredericks: So lein-dynalint isn't terribly useful as is now, then?

14:14 tcrayford____: And http://normanmaurer.me/blog/2013/11/09/The-hidden-performance-costs-of-instantiating-Throwables/

14:15 gfredericks: andyf: that sounds right

14:16 andyf: gfredericks: Have you learned of any simple way to use dynalint to check for errors in your own project's code?

14:16 irctc: andyf: this is the performance hit when throwing, Throwable.fillInStackTrace(). It walks up the stack.

14:16 andyf: irctc: Makes sense.

14:16 gfredericks: andyf: my wording in the issues "just lint the leiningen process" backs up my previous guesses

14:17 andyf: I haven't been using it personally, but your question is confusing -- isn't that the entire point of using it?

14:18 andyf: gfredericks: Definitely it is the entire point. If lein-dynalint doesn't do it, is the only out-of-the-box way to use dynalint on your own project's code to invoke the documented commands in a REPL session?

14:19 gfredericks: andyf: being totally ignorant I imagine some sort of lein alias could accomplish it as well

14:19 or `lein run` command rather

14:19 (which could be aliased)

14:20 andyf: gfredericks: I'm being a bit lazy by asking you, sorry. I can figure it out given enough time. Just checking what you recalled off the top of your head.

14:23 gfredericks: no problem

14:28 borkdude: do you guys ever feel the urge to refactor something you think can be better, outside work hours without getting paid for it by the customer?

14:28 brucehauman: borkdude: yep

14:29 gfredericks: I try to resist though

14:29 borkdude: I thought about it all day while I'm having a vacation...

14:29 brucehauman: borkdude: I feel like its a natural response, but yeah, you should probably not do it, unless it will make your life that much better

14:30 borkdude: you can sometimes get paid fo rthis down the line

14:31 borkdude: but you are much better off selling it and getting paid for it

14:31 gfredericks: I at least put refactoring ideas in comments so they don't get completely lost when I forget about them

14:31 wink: borkdude: I can easily reist this. but what I have done was "we need to do x" - "we can only do this if there's an opensource lib for it" .. next day "here look, I found this open source lib [in my github account...]"

14:32 brucehauman: lol

14:32 borkdude: wink :)

14:32 in my case it's more about a database schema. it now uses "table per concrete type" while things would be more simple with "table per type"... 2 days work probably

14:33 wink: it was a simple ragel parser for js. I couldn't just let them eval() userr input

14:33 I did for the greater good :|

14:33 borkdude: as long as it's fun to do (researching a new library or technology) I don't mind it

14:33 gfredericks: I once had to deal with a legacy project that used a many-to-many join table to model a one-to-many relationship

14:34 but it was too legacy/complicated to refactor it

14:34 all that could be done was regular weeping

14:34 Seylerius: Do most win7 machines already have a JVM that can tolerate clojure?

14:35 And we can use java GUI kits from clojure, right?

14:35 andyf: Seylerius: You mean for Clojure development, or deploying some kind of application?

14:35 Seylerius: andyf: deployment.

14:36 I'm dev'ing on my linux box. Just want to know that if I drop properly compiled bytecode on 'em, it'll work.

14:36 brucehauman: borkdude: yeah database refactors … that desn’t sound like it could get out of control.

14:36 borkdude: brucehauman joking or serious?

14:37 brucehauman: borkdude: joking, sarcasm

14:37 borkdude: depends on the project size right?

14:38 borkdude: or rather the surface area that interacts with the data layer

14:39 borkdude: brucehauman right, I'll probably better make an inventory of changes before naively starting this

14:40 kaiyin: does the counts of s1 and s2 really matter here? https://github.com/clojure/clojure/blob/master/src/clj/clojure/set.clj#L37-L43

14:41 it's basically a nested loop over s1 and s2 anyways.

14:42 andyf: kaiyin: One way of doing it is linear time in size of s1, the other way linear time in the size of s1 (times the log of the other for each contains? call, but I'm leaving that out)

14:42 oops, 'other ... s2' is what I meant.

14:44 kaiyin: andyf: you mean contains? is way faster than reduce in this case.

14:44 andyf: kaiyin: reduce is doing a linear iteration over elements of s1 there.

14:45 kaiyin: ok, i see.

14:45 andyf: kaiyin: contains? is log time

14:45 kaiyin: contains? is probably traversing over some kind of tree structure.

14:46 that could "return early".

14:46 andyf: Or as some Clojure folks like to call it, "effectively O(1)" :)

14:46 kaiyin: cool.

14:48 borkdude: brucehauman thanks for the talk at clojure/west btw, I recently watched it

14:48 devn: +1

14:49 (inc brucehauman)

14:49 lazybot: ⇒ 1

14:49 andyf: Fine print: contains? can be linear time, but only if you use a hash set and work reasonably hard to pick many set elements that collide to same hash value

14:49 brucehauman: borkdude devn thanks, you guys are too kind, it was a lot more fun than I expected it to be

14:55 devn: brucehauman: all about your delivery man

14:55 well done :)

14:55 also, from where i was sitting i thought maybe you were wearing a smoking jacket, which made it even cooler

15:03 kaiyin: a function working on maps is sitting in set.clj: https://github.com/clojure/clojure/blob/master/src/clj/clojure/set.clj#L77-L86

15:04 hkjels: I'm getting a really vague error-message without line-num etc. Even with DEBUG env. Is there a way to get an even more verbose error-output?

15:05 The error is : Error: clojure.lang.PersistentVector cannot be cast to clojure.lang.Named

15:06 devn: hrm

15:06 i need a project to tinker with

15:07 amalloy: hkjels: are you in the stock clojure repl? you can get a real stacktrace with (.printStackTrace *e *out*)

15:08 anyway, the error means you have a vector where a keyword/symbol/string is expected, of course. i'd guesss this is in your ns form

15:09 epichero: any suggestions for working with websockets?

15:10 hkjels: amalloy: That's the one place I haven't looked :) One sec

15:23 amalloy: Nope, LGTM. I'm running `lein garden` when the error appears. I've now tried my styles-file with the stock repl without errors, so the problem lies elsewhere

15:28 * gfredericks styles file-pile Lyle

15:29 andyf: kaiyin: Yes, that function has been in clojure.set namespace for a long time. I doubt it will move.

15:30 kaiyin: There are several functions for working on sets of maps with identical keys to each other, i.e. relations, in clojure.set namespace.

15:30 kaiyin: andyf: yeah, I am reading them.

15:46 cfleming: verma: You can select the form and then reformat, and it will format the selection. I'm planning to add a "reformat top form" action

15:47 kaiyin: is there something similar to peek for a set?

15:47 cfleming: xeqi: Right. AFAIK to get that in Emacs you need to use tools.namespace

15:49 andyf: kaiyin: No. peek is only implemented for data structures with a notion of order. Sets and maps are unordered.

15:50 Oh, well, I guess there are sorted sets and maps, too, but they also do not implement peek.

15:50 So, peek for list, vectors, queues, I think lazy sequences, too.

15:50 kaiyin: I think peek can be useful in both scenarios.

15:51 andyf: What would you want peek on a set to do?

15:51 kaiyin: well, to have a peek at it.

15:51 :)

15:51 andyf: You mean, return an arbitrary element of the set?

15:51 (first (seq my-set)) may do what you want

15:52 kaiyin: ah, i see.

15:52 angusiguess: ,(first #{3 4 2 6 5 1})

15:52 clojurebot: 1

15:52 kaiyin: ,(next #{3 4 2 6 5 1})

15:52 clojurebot: (4 6 3 2 5)

15:52 andyf: oh, and of course, first calls seq on its argument, so is unnecessary in my example.

15:53 kaiyin: coll

15:53 cool

16:06 hkjels: amalloy: Found the issue. It was in my project-file

16:20 kaiyin: array-maps are automatically converted to hash-maps when it's over a certain size, right? what is that size limit if so?

16:26 justin_smith: ,(count (first (drop-while #(= (type %) clojure.lang.PersistentArrayMap) (iterate (fn [m] (assoc m (gensym) true)) {}))))

16:26 clojurebot: 10

16:26 justin_smith: kaiyin: 10

16:26 kaiyin: cool.

16:29 justin_smith: so {} is an array-map by default.

16:29 justin_smith: yes

16:29 ,(type {})

16:29 clojurebot: clojure.lang.PersistentArrayMap

16:34 kaiyin: ,(inc justin_smith )

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

16:34 kaiyin: (inc justin_smith )

16:34 lazybot: ⇒ 10

16:35 kaiyin: How do you overide this behavior then, if you want to use array map with size greater than 10.

16:38 TimMc: In 1.7 they won't be array maps, I think.

16:38 kaiyin: Why would you want to? Anyway, you can use sorted maps from some library.

16:39 kaiyin: TimMc: sorted maps aren't the same thing. I want preserve order of insertion, not by some cmp func.

16:40 TimMc: Mmmm, I see.

16:40 justin_smith: kaiyin: the number of incs of "justin_smith " is equal to the number of elements in the first hash-map that is auto-promoted from array-map

16:40 that's a nice coincidence

16:41 kaiyin: Indeed, :D

16:41 justin_smith: TimMc: clojurebot is running 1.7

16:42 kaiyin: there is an insertion-ordered map out there - maybe amalloy made it? I am forgetting right now.

16:42 whodidthis: i heard ordered map is all about that insertion order

16:42 amalloy: $google amalloy ordered

16:42 lazybot: [amalloy/ordered · GitHub] https://github.com/amalloy/ordered

16:42 amalloy: i guess i did make it!

16:43 justin_smith: (inc amalloy)

16:43 lazybot: ⇒ 268

16:43 kaiyin: (inc amalloy)

16:43 lazybot: ⇒ 269

16:43 kaiyin: amazing.

16:43 justin_smith: I'm catching up

16:43 (identity justin_smith)

16:43 lazybot: justin_smith has karma 253.

16:44 kaiyin: it's also entirely in clojure.

16:45 amalloy: it's not uploaded to clojars, though?

16:45 amalloy: of course it is

16:45 (defproject org.flatland/ordered "1.5.2" ...)

16:47 kaiyin: amalloy: https://clojars.org/ordered here it says 1.3

16:47 amalloy: kaiyin: org.flatland/ordered. it has a groupid

16:49 kaiyin: yeah, what does that have to do with the version of this package? maybe a stupid question, I don't know much about maven.

16:49 justin_smith: kaiyin: every artifact has a group and a project

16:50 kaiyin: but lein has a convenience where if you don't have a / it makes group and project the same

16:50 so asking for ordered is the same as asking for ordered/ordered

16:50 as opposed to org.flatland/ordered

16:50 kaiyin: ok.

16:51 i see, there is another one. https://clojars.org/org.flatland/ordered

16:52 this means it's been pushed twice.

16:53 whodidthis: artifacts also sound pretty cool, they are mystical and once posted on clojars under a version you cant alter them

16:54 kaiyin: amalloy: it might be nicer if you added one or two lines about how to add this dependency in a lein project, as many clojure library github pages do.

16:54 just a suggestion.

16:55 cddr: So I'm writing a with-test-logger macro that catches logs so that test code can verify they have been emitted....

16:55 I've seen people suggest this might be implemented by emitting logs to a channel

16:55 What does that buy you over just appending them to a vector?

16:57 sdegutis: ,[do (prn 1) (prn 2)] ;; why?

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

17:00 sdegutis: CLJ-1184 should have made that work

17:01 Oh wait, that's fixed. Good.

17:02 TimMc: Unfortunately. It made for some fun prank code.

17:04 justin_smith: is there any plan for cljc to support tags other than clojure implementation (:clj :cljs) ?

17:04 plus :default, of course

17:05 I see :arch/osx briefly on this page, but no explanation about how this is set up stands out http://dev.clojure.org/display/design/Reader+Conditionals

17:06 puredanger: not in 1.7

17:06 justin_smith: ahh, OK

17:07 so it's not just reading comprehension fail on my part

17:07 puredanger: custom features were there and we pulled them out

17:07 just narrowing scope

17:07 may reconsider in the future

17:07 justin_smith: cool, now the puzzle pieces fit :)

17:16 wei: Is there a data structure that’s like a 1-1 map, with two-way lookup? Alternative is to use two maps, a->b and b->a

17:16 the-kenny: wei: I'd just go with the two-map approach.

17:16 TimMc: wei: Either amalloy or ztellman has probably written a library for that. :-P

17:17 kaiyin: how do you change shift width in cursive?

17:17 amalloy: well, it's not my style. who knows, maybe zach did

17:18 justin_smith: wei: I think that's known as a bi-map

17:18 the-kenny: commons has one iirc. Non-persistent, of course

17:19 justin_smith: https://gist.github.com/semperos/3835417 here is one from cgrand

17:21 TimMc: amalloy: You're the two people who write most of the collection libs.

17:21 wei: thanks for the tips! now that I have a name for this, I also found org.apache.commons.collections.bidimap.TreeBidiMap

17:22 TimMc: (Weighted by number of references I see in IRC.)

17:22 wei: gonna test out cgrand’s implementation first though, since it supports assoc and dissoc

17:23 TimMc: wei: Yeah, TreeBidiMap is mutable, which might be a problem for you.

17:25 andyf: kaiyin: You may have already gotten your question answered, but Clojure cheat sheet has several variants of ordered maps and sets linked from there: http://clojure.org/cheatsheet but versions at "Download other versions with tooltips" link near top of that page are more up to date and have tooltips

17:28 kaiyin: andyf: you mean this one? http://jafingerhut.github.io/cheatsheet/grimoire/cheatsheet-tiptip-cdocs-summary.html

17:28 looks quite nice.

17:31 andyf: kaiyin: There are several variations depending on whether you want links to ClojureDocs or Grimoire, but yeah

17:31 kaiyin: cool

17:54 TimMc: Anyone know of a leiningen plugin to compare dependency versions across two git commit IDs?

17:54 I'll write it myself if no one has done this, but I don't want to do the work if it exists...

17:56 (When I change a dependency version, I want to see what other dependencies that has changed so I can check for potential breaking changes.)

18:23 aperiodic: hey so... I feel sorta crazy for asking, but has anyone run into a problem where leiningen's `deploy` task creates jars that... don't have any code?

18:23 when I create a jar with `lein jar` it has my code in it

18:23 but when I deploy to clojars with `lein deploy clojars`, then open up the jar that gets pushed, it contains no code

18:23 this is with leiningen 2.5.1

18:24 TimMc: aperiodic: Do you have a public project I could look at?

18:24 aperiodic: and this project.clj: https://github.com/puppetlabs/clj-ldap/blob/master/project.clj

18:26 TimMc: aperiodic: My first recommendation is to try to reproduce it with a local filesystem repo -- add :local-test "file:///home/aperiodic/tmp" to your :deploy-repositories and do lein deploy local-test

18:26 then move your lein profiles out of the way and see if it still happens.

18:28 aperiodic: TimMc: alright, I'll give that a shot.

18:29 TimMc: aperiodic: For what it's worth, when I deploy to a local repo, I see clj_ldap/client.clj in the jar.

18:32 aperiodic: well it doesn't happen an another project

18:37 yeah, I see it there too

18:39 TimMc: aperiodic: Bet it's a lein user profile.

18:42 aperiodic: TimMc: why would it only manifest in the one project?

18:43 TimMc: Hmm... another idea. Move ./target elsewhere (for forensics) and try again.

18:43 aperiodic: TimMc: yeah I still get no code in the jar that gets deployed to clojars

18:43 TimMc: Or lein clean if you just want to try and fix it and not figure out why it's busted. :-P

18:43 aperiodic: oh... I did turn off AOT in this project recently

18:44 * TimMc goes afk, wishes luck

18:44 aperiodic: thanks for your help

18:45 yup!

18:45 moving target out of the way fixed it

18:47 though there is no difference in terms of files present between the old target and the target after deploying a jar that actually had code

19:01 wei: protocol question. in cgrand’s bimap implementation (https://gist.github.com/semperos/3835417) i see that “without’ is defined as a protocol function. so why can I not call (without (bimap :a 1) 1) ?

19:07 amalloy: .without is a method in some interface from clojure.lang. it's not a protocol function

19:07 TimMc: aperiodic: /me waves hands and mumbles about timestamps

19:17 Seylerius: Grr... CIDER complains thusly on load: http://ix.io/izO

19:21 xeqi: Seylerius: add something like https://gist.github.com/xeqi/05d3e955aed4810302ca to your ~/.lein/profiles.clj

19:29 Seylerius: xeqi: That did the trick (with an additional "}"), thanks.

19:37 Can mikera's core.matrix handle 3D matrices?

20:24 Okay... clojure and 3d matrices. Anyone got some advice? Can mikera's core.matrix do it? Maybe a vector or matrices?

20:36 dmkolobov: Hi y'all. On the http://clojure.org/lazy page, the last paragraph describes a way of triggering `lazy-seq` compiler optimizations with a `filter` example. I've heard this referred to as "local clearing" before. From the example, does the function `f` have to declare `p` as one of its parameters? Will the compiler not optimize if `f` take the single argument `c`?

20:37 my bad, the function `f` is called `step` in the example

20:53 crocket: How is lein repl different from cider repl?

20:53 Are they the same?

21:15 gfredericks: crocket: cider starts its repl via leiningen I believe

21:28 crocket: It seems cider repl is lein repl.

21:28 How clever.

21:28 gfredericks: :)

21:29 TimMc: (def cider lein)

21:29 crocket: (sum 1 help)

21:29 TimMc: Fun fact: There is actually only one program in the world; it behaves differently when called by different names.

21:38 crocket: hmm......

21:40 Hell

22:15 tolstoy: (Emacs/Cider): Is it possible to re-evaluate a defmulti and have it take?

22:29 gfredericks: defmulti is inherently re-eval-hostile

22:29 one workaround is to eval (def my-multi nil)

22:29 then eval the defmulti again

22:34 tolstoy: Ah, thanks gfredericks.

22:34 gfredericks: np

22:50 tolstoy: Worked! ;)

23:00 tmtwd: hm -

23:01 clojure is interopperable with java, why do wrappers exist for java libs to interact with clojure?

23:01 ie https://github.com/pelle/bitcljoin

23:03 gfredericks: it can make things more fluent

23:03 tmtwd: i see

23:03 TEttinger: just to make it easier, really. you can do a lot with certain clojure features that often is tricky from java, like how Seesaw is a wrapper around Swing that takes anonymous fns instead of java-style anonymous inner classes (that might be possible anyway)

23:03 seesaw adds a lot of functionality, like being able to get a GUI element by an ID or selector

23:04 many wrappers try to do the same

23:04 tmtwd: Cool

23:04 devn: TimMc: how do you mean?

23:04 tmtwd: I may take a look at seesaw, since I have some experience with swing

23:05 TEttinger: some things are kinda a pain to use from clojure if they use java conventions. arrays aren't quite as easy as they could be, and varargs in java are really just an array of arguments

23:05 tmtwd: swing is so awful, I can't believe that is how I learned to program

23:05 devn: TEttinger: IIRC someone wrote a lib to make arrays a little easier to work with

23:05 tmtwd: haha

23:05 TEttinger: hiphip, yep

23:05 tmtwd: devn, java arrays?

23:05 devn: seesaw isn't so bad

23:06 tmtwd: yeah

23:06 TEttinger: yeah, that's the one

23:06 tmtwd: devn, why not just use vectors?

23:06 TEttinger: (arrays aren't preferred in idiomatic clojure because they aren't immutable and aren't persistent, etc.)

23:06 devn: tmtwd: performance

23:06 or interop related reasons

23:06 TEttinger: but yeah they do perform very well

23:06 devn: which kind of dovetail

23:06 tmtwd: interesting

23:06 devn: i mean, there is a tradeoff

23:07 TEttinger: it's harder to get highly-mutable code that uses arrays a lot to work on the first try

23:07 tmtwd: I would have thought vectors were just arrays with a different name

23:07 devn: it's why they're a little more cumbersome to use in clojure, and frankly, i appreciate that design choice

23:07 tmtwd: but I guess vectors in clojure have to conform to lisp patters or something

23:07 devn: for java programmers, they'll want to start using arrays right away, better to lead them down the path of sanity

23:07 and let them choose arrays only where they're truly necessary

23:07 gfredericks: tmtwd: they're immutable; it's a huge difference

23:07 tmtwd: gfredericks, ah of course

23:07 devn: tmtwd: are you familiar with structural sharing and all of this business?

23:08 tmtwd: but vectors are random access, no?

23:08 gfredericks: yep

23:08 devn: yeah

23:08 tmtwd: @devn no,

23:08 never heard of it

23:08 devn: vectors are very much like ArrayLists, except they're totally different

23:09 tmtwd: And the fact that vectors can't change size

23:09 devn: tmtwd: so, if you do this: (conj [1 2 3] 1)

23:09 tmtwd: (I think)

23:09 devn: do you make a copy of [1 2 3]? [1 2 3 1]?

23:10 tmtwd: not sure

23:10 is there a copy function

23:10 ?

23:10 ah

23:10 devn: tmtwd: http://en.wikipedia.org/wiki/Persistent_data_structure

23:10 "While persistence can be achieved by simple copying, this is inefficient in CPU and RAM usage, because most operations make only small changes to a data structure. A better method is to exploit the similarity between the new and old versions to share structure between them, such as using the same subtree in a number of tree structures."

23:10 "However, because it rapidly becomes infeasible to determine how many previous versions share which parts of the structure, and because it is often desirable to discard old versions, this necessitates an environment with garbage collection."

23:11 this works out on the JVM because the GC is marvelously good

23:11 tmtwd: read this also: http://hypirion.com/musings/understanding-persistent-vector-pt-1

23:12 tmtwd: very interesting

23:12 so in a naive implementation of immutability, you would just copy the old version of the data structure?

23:13 devn: that's one way, yeah

23:13 tmtwd: whereas, a better way would be with persistent data structures?

23:14 cool links

23:14 TEttinger: &(let [v [1 2 3] a (int-array [1 2 3])] (do (pr v) (print (vec a)) (print " changing values... ") (map inc v) (amap a i a2 (aset a i (inc (aget a i)))) (pr v) (print (vec a))))

23:14 lazybot: ⇒ [1 2 3][1 2 3] changing values... [1 2 3][2 3 4]nil

23:14 devn: tmtwd: i dont want to say categorically better

23:15 like everything, there are tradeoffs

23:15 TEttinger: the map on v won't change v. the map on a actually by default won't, but it can easily

23:15 tmtwd: (conj [1 2 ] 2)

23:15 TEttinger: &(conj [1 2] 2)

23:15 lazybot: ⇒ [1 2 2]

23:15 devn: tmtwd: add a , or &to the front of what you just wrote

23:15 tmtwd: &(conj [12 32 44] 4)

23:15 lazybot: ⇒ [12 32 44 4]

23:16 tmtwd: cool! I want one

23:16 devn: copy on write collections were added long ago in java

23:16 TEttinger: ,(into {} [:a 1 :b 2 :c 3 :d 4 :e 5 :f 6])

23:16 tmtwd: Oh, I already have on

23:16 devn: along with conurrent hash maps

23:16 clojurebot: #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Keyword"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: clojure.lang.Keyword"\n :at [clojure.lang.RT seqFrom "RT.java" 528]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 528]\n [clojure.lang.RT seq "RT.java" 509]\n [clojure.lang.ATransientMap conj "ATransientMap.java" 4...

23:16 devn: and this was to allow concurrent reads

23:16 but it's only decent to use it when your reads vastly outweight the number of writes

23:17 because it does a copy, with a lock

23:17 TEttinger: ,(zipmap [:a :b :c :d :e :f] [1 2 3 4 5 6])

23:17 clojurebot: {:a 1, :b 2, :c 3, :d 4, :e 5, ...}

23:17 devn: so, i have to run, but now we're kind of getting to some important bits for you to understand about clojure

23:17 TEttinger: clojurebot, which is called with comma, will cut off output

23:17 clojurebot: c'est bon!

23:17 TEttinger: &(zipmap [:a :b :c :d :e :f] [1 2 3 4 5 6])

23:17 lazybot: ⇒ {:f 6, :e 5, :d 4, :c 3, :b 2, :a 1}

23:17 devn: check out atoms, read up on persistent data structures (the link i posted above)

23:17 justin_smith: ~which,

23:17 clojurebot: Huh?

23:17 TEttinger: lazybot will not

23:18 ~which

23:18 clojurebot: which is called with comma, will cut off output

23:18 tmtwd: @devn I actually was watching a talk on persistent data structures today

23:18 didn't finish it though

23:19 TEttinger: for certain tasks they're absolutely invaluable, for the rest they're just handy

23:19 devn: they're a sensible default

23:19 IMO

23:19 TEttinger: agreed

23:19 devn: better to have the persistent immutable properties, and then flip them mutable if you need to

23:20 doing it the other way around is a true pain

23:20 tmtwd: good to know

23:20 devn: tmtwd: anyway, like i said, gotta run, but welcome!

23:20 tmtwd: thanks :)

23:21 crocket: Most mutations are bad.

23:21 devn: happy clojuring :)

23:21 crocket: The same applies to genes.

23:21 Javascript is a mutant ninja.

23:21 justin_smith: turtle with a jetpack

23:22 * devn laughs out loud

23:22 devn: okay really leaving now

23:22 later all

23:22 justin_smith: is it teenage yet?

23:22 was it made before 1992?

23:23 err wait, people born in 2002 are teenage

23:23 * justin_smith lurks off to feel old

23:23 justin_smith: anyway, definitely a teenage mutant ninja turtle

23:24 TEttinger: isn't javascript older than, or approaching, 20 years old?

23:24 tmtwd: TEttinger, today

23:24 it is 20 years old

23:25 TEttinger: wowza

23:40 justin_smith: next year we are gonna have to get javascript soooo wasted

23:47 epichero: javascript already makes me drink...

Logging service provided by n01se.net