#clojure log - Dec 13 2013

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

0:00 rovar: the comment ;; This is a bit like Mult + Multimethods helps quite a bit

0:01 bbloom: whoa lots of stuff totally gonna have to soak this stuff in a bit

0:02 rovar: got it.. makes a ton more sense now. I must say the docs for pub left me more confused than when I started.

0:37 nmccarty: alright, so im having a bit of an issue debugging something that uses a couple java timers

0:38 somewhere along the line, a function is being passed the wrong number of arguments

0:38 but since it snakes through every structure in the program, its a bit difficult to tell were

0:39 anyone got any ideas as to how i should go about finding where the bug is located?

1:04 also: what's the right way to do this:

1:04 ,(.indexOf "ab" \b 1)

1:04 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: indexOf for class java.lang.String>

1:05 arrdem: ,(.indexOf "ab" \b)

1:05 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: indexOf for class java.lang.String>

1:06 TEttinger: also: what's the 1 for?

1:06 also: it's the fromIndex

1:07 guns: also: that version of indexOf expects an int as the first argument, so you have to cast it

1:07 TEttinger: or string

1:07 ,(.indexOf "ab" "b" 1)

1:07 clojurebot: 1

1:10 also: ah, http://dev.clojure.org/jira/browse/CLJ-445

1:10 thanks!

1:10 TEttinger: np. javadocs are handy.

1:11 http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

1:11 also: yeah, it would have worked in java, and will in clojure after CLJ-445 is fixed, if I'm understanding correctly

1:14 TEttinger: hm? there's no char argument version of .indexOf

1:14 just int and string

1:14 also: char is widened to int

1:15 dnolen: om gets really a sophisticated batching algorithm https://github.com/swannodette/om/commit/ec5f7890d85295e8ffc942c2c873b55e5080dc96

1:15 j/k, but with trivial change 10X faster

1:16 TEttinger: I'm honestly not sure how chars work on the JVM. I know they aren't an 8-bit equivalent to byte like in C, but UCS-16 might coerce to short.

1:17 also: TEttinger: http://docs.oracle.com/javase/specs/jls/se5.0/html/conversions.html

1:17 TEttinger: indeed, "char to int, long, float, or double"

1:17 ,(float \a)

1:17 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number>

1:18 TEttinger: hm, boxed by default

1:25 arrdem: TEttinger: what with multibyte wierdness in UTF8 that makes sense...

1:25 ,(float (Byte. 4))

1:25 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Byte>

1:26 arrdem: ,(doc byte)

1:26 clojurebot: "([x]); Coerce to byte"

1:29 bitemyapp: arrdem: you missed out man.

1:29 arrdem: bitemyapp: wat

1:29 bitemyapp: arrdem: hackin' and discussin' Haskell with noprompt!

1:29 arrdem: I explained functors :D

1:29 (kind oF)

1:29 (I didn't explain the laws. sssshhhh)

1:29 arrdem: up for a game?

1:30 arrdem: bitemyapp: noice. iff you do resume diff feedback.

1:30 bitemyapp: diff feedback?

1:31 harja: Hi guys, what's the preferred way of using the master branch of clojurescript on github in a project?

1:38 seangrove: dnolen: Is there a reason that the react/om components have to mutate state in-place rather than typical clojure functions?

1:41 dnolen: seangrove: given how om works I don't really see this as a problem as you may have multiple components that share the same app state atom

1:42 seangrove: also w/o the atom it's trickier to do simple optimizations with high value - like batched updates

1:42 seangrove: dnolen: Hrm, interesting. I'm slightly dubious, but I'll try it out more first.

1:50 dnolen: seangrove: the alternative is more complicated, less flexible, and it doesn't really buy you anything - the state of your application is already pretty trivial to reason about in om because the entire state is available all the time

2:05 noprompt: good times

2:11 pmap: back again

2:12 I know there's usually no reason to cast types in clojure

2:12 but I think I actually have a legitimate need to

2:12 is it possible to cast to arbitrary classes in clojure?

2:12 noprompt: dnolen: is this library ready for use?

2:12 pmap: I can't find anything on google other than "clojure doesn't need casting"

2:13 dnolen: noprompt: definitely not :) working through TodoMVC to so I can tune the perf and find bugs

2:13 noprompt: dnolen: looks exciting.

2:15 dnolen: noprompt: it's getting there, it's tree oriented system so you always have to pass the current data node and path into the tree along - so far the repetition doesn't outweigh the benefits

2:16 noprompt: I may collapse data and path into one value if benchmarks show that it doesn't hurt perf

2:17 jasonjckn: pmap: a casting is just an assignment + instanceof check, after an object is casted it hasn't changed in anyway

2:17 pmap: so in clojure you can do instanceof with instance?

2:18 perhaps you're trying to cause reflection lookups to be done with a different static type

2:18 pmap: oh, nevermind

2:18 I just found another method which will return the type I need

2:19 I needed it to be a WritableRaster instead of a Raster, so I could call the .setPixels method on it

2:19 I was going to use buffered-image's .getData method to get a Raster

2:19 and then cast that to a WritableRaster

2:20 but BufferedImages also have a .getRaster method

2:20 which returns a WritableRaster

2:20 jasonjckn: either the object is a WritableRaster, in which case doing (.setPixels o) will work, or it isn't a WritableRaster in which case you can't downcast a Raster to something it isn't

2:20 noprompt: dnolen: ah, i see there's a new version of cljs. excellent. is the #js reader macro new?

2:21 pmap: I was just following a java code snippet I found on the web

2:21 dnolen: noprompt: no new release yet, yes #js literal is new

2:21 pmap: it did: WritableRaster raster = (WritableRaster) bufferedimage.getData();

2:21 is that not valid?

2:22 jasonjckn: yes so the equivilent clojure code would be (.setPixels (.getData bufferedimage))

2:22 you don't need to cast in clojure ;)

2:22 noprompt: dnolen: that's going to clean up so much ugly clj->js code. when's it coming?

2:22 jasonjckn: pmap: (add in appropriate arguments for setPixels)

2:22 dnolen: noprompt: probably pretty soon, couple other patches I'd like to get in

2:23 pmap: but how will it know I need to cast it to a WritableRaster?

2:23 is it not conceivable that some other class would also have a .setPixels method?

2:23 noprompt: dnolen: that's what you said last week :-P

2:24 dnolen: i'm just excited for this release. :-)

2:24 jasonjckn: pmap: sure that's possible, it's using reflection to enumerate through all the different methods of whatever object is passed to .setPixels, so as long as it finds a signature match it will invoke that function

2:24 dnolen: noprompt: heh, k I might push it out tomorrow

2:25 pmap: but Rasters don't have a .setPixels method

2:25 only their sub-type, WritableRasters do

2:25 noprompt: dnolen: ah, i was just giving you a hard time. just looking forward to the new patches.

2:26 jasonjckn: pmap: bufferedimage.getData() is returning an object which is instance of WritableRaster (or some child of it), inspite of the signature of getData being Raster, if that wasn't the case the java code wouldn't work, the cast would fail

2:28 pmap: but WritableRaster is a subclass of Raster

2:28 jasonjckn: yah i know

2:29 pmap: and according to the javadocs, .getImage returns type Raster

2:29 err, .getData

2:29 how can it be the case that it's returning an instance of WritableRaster then?

2:31 jasonjckn: pmap: it's an instance of WritableRaster that was casted to Raster that's what's being returned

2:31 pmap: oh

2:31 ok then

2:32 jasonjckn: if that wasn't the case you wouldn't be able to cast it to WritableRaster

2:32 pmap: I see

2:32 jasonjckn: casting is not some kind of "morph type X into Y"

2:32 it's very 'dumb'

2:32 pmap: I have very little experience with java, or statically typed languages in general

2:33 so I always thought casting just meant "morph type X into Y"

2:33 jasonjckn: i wish because then i would morph my user input into the program output

2:33 pmap: so then (long 3.0) isn't the same as java's (long)3.0 ?

2:33 jasonjckn: there is a library like that https://github.com/twitter/bijection

2:34 pmap: because (long 3.0) actually creates a different type?

2:34 jasonjckn: casting primitive types is a special case in java

2:35 pmap: oh

2:35 jasonjckn: that's more like morphing

2:35 the example you gave

2:35 pmap: well I think I've actually only ever casted primitives in my experience

2:35 so I didn't realize there was a difference3

2:35 jasonjckn: I think if you try Long l = (Long)new Double(3.0); it'll fail

2:35 pmap: in fact, I didn't even realize you could cast non-primitives

2:35 jasonjckn: to illustrate my point

2:36 pmap: until today

2:36 and I thought you couldn't because it wouldn't make sense to be able to "morph" different classes

2:36 but I guess there's really just 2 different types of casting, to address that issue

2:45 seriously_random: a bit silly question regarding speed: http://pastebin.com/a29vhaqh

2:52 SegFaultAX: seriously_random: Well in the second case the REPL is forcing the evaluation of the filtered seq.

2:52 jasonjckn: seriously_random: if your list was larger then yes

2:53 seriously_random: filter returns a lazyseq, if you call first on that, then pos? is only called once basically

2:54 SegFaultAX: jasonjckn: They will be the same as long as the entire seq in the second case isn't realized.

2:59 bitemyapp: mumble?

3:22 * ucb waves

3:23 bitemyapp: ucb: howdy!

3:23 ucb: bitemyapp: hiya!

3:24 I decided this morning I'm going to invest some time into trying a few simple approaches at time series second guessing. I predict this will all end in nothing and that my frustration/rage levels will be high.

3:24 bitemyapp: ucb: I've had a fun day, did some learning and hackin' with noprompt earlier.

3:24 ucb: </youve_been_warned>

3:24 bitemyapp: ucb: time series second guessing?

3:24 ucb: ooh, any new shinys came out of your haxxoring?

3:25 bitemyapp: ucb: no, slow progress, was getting noprompt bootstrapped into some Haskell enlightenment :)

3:25 ucb: bitemyapp: I explicitly avoided the word "predicting" to dodge the adjective "lunatic" being thrown at me.

3:25 bitemyapp: I had a ton of fun though.

3:25 ucb: bitemyapp: awesome. Haskell is something I'm going to invest in next year.

3:25 bitemyapp: ucb: ping me when you're ready to begin, I can put you on the golden path for that -- at least at first :)

3:26 ucb: bitemyapp: is the start to that path the learn you a haskell book?

3:26 bitemyapp: nope.

3:26 ucb: great then!

3:26 bitemyapp: I disliked LYAH

3:27 ucb: oh?

3:30 bitemyapp: ucb: I found it tedious and boring, but a decent reference.

3:31 ucb: gotcha

3:31 I've tried following (a few times already) the building a scheme doc.

3:31 but every time I find other clojure shinies to play with and get distracted

3:32 bitemyapp: ucb: the building a scheme thing is decent but only appeals in certain situations

3:32 ucb: yeah

3:47 incanter is full of gold

3:51 arcatan: is incanter alive? i wouldn't mind having some data analysis tools in clojure

3:51 (currently i'm generating data with clojure and then graphing it with R or Python)

3:52 bitemyapp: Incanter works fine

3:56 ucb: yeah, incanter works fine. Don't know about dev now, but whatever's there is stable/good enough for me :)

3:58 harja: are there good libraries for working with js/Dates in clojurescript?

4:00 arcatan: clearly i should try out incanter, then.

4:00 somehow i thought it was so dead that it does not even work anymore

4:46 seriously_random: a bit confused about 'first': http://pastebin.com/Bey6iqVR

4:47 pjstadig: seriously_random: i think you are confused about filter

4:47 pisketti: (first [2]) vs. (first 2)

4:48 divyansr: ,(first '(1 2 3))

4:48 clojurebot: 1

4:49 seriously_random: right

4:53 harja: where do the foreign libs have to be in order for cljsbuild to find them? I tried both relative path and file:// -url. The error is java.lang.IllegalArgumentException: No implementation of method: :make-reader of protocol: #'clojure.java.io/IOFactory found for class: nil

4:56 I've been reading http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html this

4:57 piranha: harja: IIRC path should be relative to your 'project.clj'

4:58 yeah, just checked

5:00 harja: Yeah, I got it working now. I included the actual file in the index.html and just added reference to it in :externs as-is

5:00 I removed the reference from :foreign-libs alltogether

5:52 cYmen: Who's writing imperative code in infinite let expressions again?

6:04 darkest_pod: Hey everyone. I have a question about leiningen and custom exception printing. There is this library that allows nice colored clojure exceptions, called pretty https://github.com/AvisoNovate/pretty

6:05 The problem is - instructions provided for leiningen does not seem to work. Same thing for clj-stacktrace library https://github.com/mmcgrana/clj-stacktrace/issues/29

6:06 Did something change in the last two years in leiningen exception handling?

6:27 seriously_random: I suppose there is no visualizer for clojure like there is for python? http://www.pythontutor.com/visualize.html

6:53 clgv: seriously_random: very likely not

6:54 justin_smith: you shouldn't expect lein plugins at runtime

6:54 lein is a tool that finds your deps and starts your project

6:54 if you want it at runtime, you want it as a dep, not a plugin

6:55 oh, don't mind me, you did have it as a dep

6:57 seriously_random: I think that let block needs to be in `` delimiters?

6:57 err I mean preceded by `

6:57 my brain is scrambled, I should shut up

7:06 fizruk_: hi guys! is there a short variant for this? http://pastebin.com/sZQ2XTva

7:07 it is pretty much like cond->, yet each predicate uses previous result

7:07 clgv: how do I get the result of a background shell execution with "conj"?

7:07 logic_prog: anyone managed to compile emacs to javascript?

7:07 clgv: args

7:07 "conch"

7:09 Raynes: ping

7:09 justin_smith: fizruk (as-> x1 x (if (f1 x) (g1 x) x) (if (f2 x) (g2 x) x) (if (f3 x) (g3 x)) (if (f4 x) (g4 x) x))

7:13 fizruk_: justin_smith: thanks! can is there an even shorter version (I think specifically for (if (f x) (g x) x) )

7:13 s/can//

7:16 justin_smith: (defmacro f+g [f g x] `(if ~(f x) (~g ~x) ~x))

7:16 (f+g even? inc 4)

7:18 more succinct? yes. Worth it? dunno

7:18 also f+g is a terrible name

7:22 (defmacro f+g [f g x] `(let [x# ~x] (if (~f x#) (~g x#) x#)))

7:22 the other version was wrong

7:26 fizruk_: thank you, I'll think about that a bit more

7:26 clgv: using "conch 0.6.0" {:background true} programs' futures remain :pending forever... :(

7:35 sm0ke: is dont get logs for a console appender in log4j on the repl

7:35 is there a workaround for this?

7:35 i dont think there should be a repl appender

7:38 justin_smith: sm0ke: as I understand it the problem is that the log4j output is defined before the nrepl process rebinds *out*

7:38 it is the classic problem with vars declared :dynamic

7:38 in a new thread it does not see the binding

7:38 so it uses the old one

7:39 s/new/any other/

7:39 log4j being an older thread that does not see the new binding

7:41 sm0ke: justin_smith: can this be worked around?

7:41 justin_smith: from the repl, you could try using alter-var-root on *out* to be the repl's version of *out*

7:41 I don't know if this would help

7:43 sm0ke: there should be a clojure repl appender for log4j

7:43 justin_smith: imho timbre is more compatible with clojure ways of doing things than log4j (ie. being oriented for runtime rebinding, using edn for its config)

7:43 sm0ke: i really dont like timbre, i think log4j is capable enough and much more flexible

7:44 justin_smith: can you access the log4j object to set it's output stream? you could tell it to use the value of *out* as seen in the repl as its stream

7:44 sm0ke: tools.logging is the best which worked for me

7:45 justin_smith: hmm i am using tools.logging

7:45 there is no log4j object

7:45 i mean not in a way i can control it

7:46 justin_smith: I think part of this is it is considered a security thing

7:46 if someone is hacking your system, one of the first things they will want is to rebind / take over logging config

7:47 so they intentionally keep such functionality out of the design

7:48 https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/WriterAppender.html you could try to find the instance of WriterAppender and call its setWriter method?

7:48 if I was wrong above

7:48 seriously_random: anyone using light table? how to quit infinite loop in instarepl?

7:51 justin_smith: have you tried control-c? I would try that, control-d, escape, control-g

7:51 those are all common enough

7:54 sm0ke: justin_smith: ok this is kind of embarassing, but i had root logger set to warn and was logging an info msg

7:54 justin_smith: log4j already seems to be logging to repl

7:54 justin_smith: lol

7:55 congrats

7:55 sm0ke: heh

7:56 justin_smith: sometimes it is reassuring to realize the problem was pebkac

7:56 sm0ke: :D pebkac

8:11 jph-: newbie question, i have a map with numeric values as strings... how can i apply something like read-string to generate a new map with integer vals?

8:15 solussd: good morning clojurians, does anyone have any recommendations for working with complex numbers in clojure? I kind of expected a Complex type to be in Clojure.math* by now. :)

8:16 mdrogalis: jph-

8:16 ,(into {} (map (fn [[k v]] {k (Integer/parseInt v)}) {:a "1" :b "2"}))

8:16 clojurebot: {:a 1, :b 2}

8:17 jph-: mdrogalis: cheers, lemme give that a try

8:17 i knew it was possible, i just didnt know the right building blocks to get it working

8:18 mdrogalis: jph-: Everyone wants a sort of map function that takes a hashmap and returns a hashmap. But it never seems to make it into core.

8:18 jph-: yeh

8:18 im dealing with shitty json apis

8:19 mdrogalis: jph-: I feel that. D:

8:20 jph-: uppercase keys, floats as strings

8:20 * jph- is not happy

8:20 solussd: ,(reduce (fn [a [k v]] (assoc a k (Integer/parseInt v))) {} {:a "1" :b "2"})

8:20 clojurebot: {:b 2, :a 1}

8:21 mdrogalis: Yeah, normalize that all out first.

8:21 Oh yeah, solussd reminds me.

8:21 ,(doc reduce-kv)

8:21 clojurebot: "([f init coll]); Reduces an associative collection. f should be a function of 3 arguments. Returns the result of applying f to init, the first key and the first value in coll, then applying f to that result and the 2nd key and value, etc. If coll contains no entries, returns init and f is not called. Note that reduce-kv is supported on vectors, where the keys will be the ordinals."

8:21 solussd: :)

8:21 jph-: mdrogalis: also noticed fmap here https://github.com/clojure/algo.generic/blob/master/src/main/clojure/clojure/algo/generic/functor.clj

8:22 smiler: bostad. De ska inte vara där.." x~~~~~~

8:22 mdrogalis: jph-: Yep, that's a thing too. Take your pick. :)

8:22 smiler: Ops, missclick

8:23 jph-: so a few minutes ago i had no options

8:23 now i have 3

8:23 * jph- hits the books

8:23 mdrogalis: Rule of life: You always have outs.

8:23 jph-: yeh

8:23 clojure kinda feels like unix

8:24 you know there's some awesome utility to do what you ened

8:24 need

8:24 but if you dont know about it

8:24 you're kinda stuck

8:24 i know i can do what i want in an ugly way... but im forcing myself to learn the clojure way

8:24 heh

8:26 there's like all these handy functions hidden away in libraries

8:26 ooh i know

8:26 i can benchmark these

8:28 cursork: " Things to 2-indent in Clojure. i.e. Midje, Compojure

8:28 let g:clojure_fuzzy_indent_patterns += ["GET", "POST", "PUT", "PATCH", "DELETE", "context"]

8:28 let g:clojure_fuzzy_indent_patterns += ["facts\?"]

8:28 Sorry!

8:40 pazustep: Hello, people.

8:40 mdrogalis: Morning, pazustep

8:41 pazustep: I'm learning Clojure, and I wonder if anyone could do a quick review of 10 lines of code: https://gist.github.com/pazustep/d6cea23f43e0faceaeb9

8:41 logic_prog: in develpping typical web apps in clojurescript,

8:41 or in javascript, is there any time when one really needs vectors rather than lists?

8:42 pazustep: I wanna know if this looks like idiomatic clojure or if my past OO experience is holding me back.

8:42 logic_prog: for web apps, the more I think about it, the more I'm convinced all we need is just linked lists, not vectors

8:43 pazustep: logic_prog: I'm not the expert, but… 1) vectors have different performance characteristics (fast random access) and 2) vectors aren't evaluated

8:45 logic_prog: absolutely, vectors have O(1) rnadom access

8:45 while for lists, it's possibly O(n), and possibly with worse constants if one has to chase the "next" field of elements

8:45 however, in web apps, I can't think of a single situation where I need O(1) access

8:45 err, where I need _random_ access

8:46 whereas I do randomly have shit like "insert this after this element", "delete that element" which seems to work better with doubly linked lists

8:47 pazustep: true, unless you're dealing with *a lot* of data, performance is probably not going to matter much.

8:48 jph-: sweet, clojure cookbook 50% off at oreilly today

8:48 pazustep: how about some fns working only on vectors, like subvec?

8:51 I haven't done any clojurescript yet, but when doing client-side js, I often keep a representation of my data in arrays and render that to a table or something; events on each table row will use an index to retrieve the original data.

8:51 am I making sense?

8:57 logic_prog: oh shit

8:57 the clojure book is finished

8:57 ?

8:58 mdrogali`: logic_prog: Yes.

8:58 logic_prog: there goes my wallet

8:58 ddellacosta: which one, the 2nd edition of Joy of Clojure?

8:59 mdrogalis`: ddellacosta: Cookbook.

8:59 ddellacosta: mdrogalis`: ah, cool.

9:00 logic_prog: where is the TOC?

9:00 it's still pre-order on amazon

9:01 mdrogalis`: Hm, maybe I mispoke. Perhaps it's not out-out.

9:02 logic_prog: mdrogalis`: are you part of some secret clojure inner circle that gets books pre-pub ?

9:03 https://github.com/clojure-cookbook/clojure-cookbook does not seem very insightful

9:03 can you post the TOC somewhere?

9:03 jph-: logic_prog: you can get early access to joy of cloj 2

9:03 logic_prog: jph-: what's new?

9:03 jph-: is it an update, or is it a series of new chapters?

9:03 jph-: no idea, i havent read the first one

9:04 logic_prog: I've often found the delta from first to second is often trivial

9:04 jph-: i just picked up the early access to #2

9:04 and you get #1 free when you do that

9:04 logic_prog: the toc looks simiilar to joy of clojure 1

9:05 tomc: is anyone aware of whether the form (ns whatever (:require [parent [sub :as sub] [other-sub :as other]])) that we have in jvm clojure is available in cljs as part of a lib? Or whether there's plans to support it in the compiler at any point?

9:10 borkdude: I asked this in ##java but no one answers there, so excuse me that I'm trying here: Would anyone know how to use build time openjpa enhancement in Intellij unit test running?

9:24 schaueho: the java.jdbc docs say that sqlingo.vo would produce compatible sql statements, is this still true?

9:24 cause I'm getting syntax errors (from mysql)

9:35 Profpatsch: I want do define a function `rand` that takes a seed and an optional keyword switch :paranoid. How would I do that?

9:37 (defn rand [seed & {:keys [paranoid]}] …) would mean :paranoid needed a value, wouldn’t it?

9:37 tomc: @Profpatsch: you can use :or in that form to supply defaults.

9:37 Not sure of the exact syntax, but it shouldn't be hard to find.

9:38 Profpatsch: The one above says I’m missing a value when I do (rand 234 :paranoid)

9:39 CookedGryphon: there's a couple of things you could do, if you want a single flag, you can do either: (defn rand [seed & flags])

9:39 and check if (contains? (set flags) :paranoid)

9:39 that's the best way, in case you want to add new flags in the future

9:39 joegallo: Profpatsch: that's because {& :keys ...} turns the extra arguments into a map behind the scenes

9:39 CookedGryphon: or, if you just want to check if it's there or not, you could do (defn rand [seed & [paranoid?]] ...)

9:39 joegallo: so it's for :paranoid true :extra-neat true :coolness-level 5

9:39 Bronsa: Profpatsch: (defn rand ([seed] (rand seed nil)) ([seed paranoid?] ..)) is probably the best you can do

9:40 binski: is it possible to recompile src/java into a running REPL session?

9:40 CookedGryphon: then paranoid? will be either :paranoid (truthy) or nil (falsey)

9:40 joegallo: just paranoid by itself doesn't make sense...

9:40 CookedGryphon: but joegallo's solution of having it as a map :paranoid true makes more sense in case you want to add more options in teh future

9:40 Profpatsch: Bronsa: Oh, that’s neat.

9:42 logic_prog: does clojure support persistentn red-black trees as a primitive?

9:42 I know there are lists, maps, vectors, sects

9:42 but I want to know if clojure has primitive red black trees

9:43 Bronsa: logic_prog: a sorted-map is a persistent rb tree if that's what you're asking

9:44 Profpatsch: Bronsa: Hm, but then I don’t have the :paranoid in the method call. So I guess I go with CookedGryphon’s first solution

9:44 logic_prog: Bronsa: https://github.com/clojure/clojure/blob/c6756a8bab137128c8119add29a25b0a88509900/src/clj/clojure/core.clj#L376

9:44 what protocols does sorted-map satisfy?

9:45 Bronsa: logic_prog: It's a PersistentTreeMap, it's implemented in terms of java interfaces like all Clojure collections, not in terms of protocols

9:47 Profpatsch: you can still do (rand w/e :paranoid)

9:48 Profpatsch: my approach and CookedGryphon work essentially the same, except with his you can do (rand w/e :paranoid :foo :baz) and :foo :baz will get ignored

9:49 Profpatsch: Bronsa: Ah, okay. But with yours the user can do (rand 234 'baz) and the second will be called.

9:49 Bronsa: Profpatsch: that's the same with CookedGryphon's one

9:49 Profpatsch: So I’d have to check anyway.

9:50 But can’t expand the interface afterwards.

9:50 Bronsa: Profpatsch: yeah, if you really want to constraint to :paranoid there's no way to do that destructuring the args, you have to do a check

9:56 silasdavis: is there a 'point free' alternative to ->

9:57 so instead of (fn [x] (-> x f g h)) I can write (magic-> f g h)?

9:57 Bronsa: silasdavis: comp

9:57 ,((comp inc inc inc) 1)

9:58 clojurebot: 4

9:58 silasdavis: I want to thread into first argument, and go in that order

9:58 so I should have said

9:58 Bronsa: silasdavis: note that (-> x f g h) is ((comp h g f) x) though

9:58 silasdavis: (-> x (f y) (g z) h)

9:58 for example

9:59 CookedGryphon: silasdavis: you'd need to make function rather than a macro

9:59 coventry: (defn rcomp [& args] (->> args reverse (apply comp))) maybe?

9:59 Bronsa: silasdavis: not that I know then, you can get away with comp+partial for ->> but not for ->

10:01 CookedGryphon: (defmacro magic-> [& body] `(fn [x] (-> x ~@body)))

10:05 dnolen: ClojureScript 0.0-2120 going out

10:06 coventry: Maybe (defn magic-> [fns] (fn [x] (reduce #(-> %1 %2) x fns)))?

10:06 Hmm, still doesn't get the arguments. You definitely need a macro.

10:07 silasdavis: if I have some latitude in my argument order, do you think I should prefer partial'ised comp'ositions over threading?

10:07 I can probably rejiggle things to achieve that...

10:07 coventry: silasdavis: Have you considered as->?

10:08 silasdavis: no what is that

10:08 cna't find docs

10:09 you don't mena -?>

10:09 coventry: ,(doc as->)

10:09 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

10:09 coventry: Helps you avoid rejiggering the signatures.

10:12 gdev: dnolen, just in time for the holidays =D

10:20 silasdavis: coventry, oh nice, like accumulated passed between lexical scopes

10:20 yes that will help, thanks

10:24 xeqi: dnolen: hurray

10:32 cemerick: did you get notices for my piggieback/austin PRs while you were away?

10:33 koalallama: How do I apply a fn to a map without creating a new collection? E.g, similar to map fn list, but I just want fn to run on list, without creating a whole new list with the result of fn

10:33 apply fn to a list*

10:33 cemerick: xeqi: I did. Scrambling a.t.m. to burn through the backlog. :-)

10:33 seangrove: poor tim visher, dnolen constantly teases him with mentions of new cljs release, before they're available

10:34 xeqi: cemerick: np, figured you had a loooong "back from away time" queue

10:34 cemerick: xeqi: the heap is sorted by complexity / time to review/fix tho, so yours may be one of the last bits I look at :-(

10:34 Yeah, it's pretty deep. Doesn't help that I'll be traveling next week as well.

10:35 xeqi: koalallama: ##(doc doseq)

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

10:35 xeqi: &(doseq [r (range 10)] (prn r))

10:35 lazybot: ⇒ 0 1 2 3 4 5 6 7 8 9 nil

10:35 S3thc0n: Yay! I think i kind of got monads.

10:35 koalallama: xeqi: thank you, I was looking for an alternative to doseq, but I guess not

10:36 xeqi: koalallama: what would it do differently?

10:36 koalallama: xeqi: run in parallel

10:37 I know map doesn't, but I was hoping to get to pmap eventually

10:37 xeqi: something like `(doseq [r (range 10)] (future (prn r)))` ?

10:38 though a good implementation reuires thoughts on workloads and chunking

10:39 cemerick: let me know if you have any questions to speed up the process

10:40 S3thc0n: I really do not get what the fuss is all about. They seem simple to me. But now that i try to say what they are, I notice - it is damn hard to explain.

10:45 TimMc: S3thc0n: What path did you take to enlightenment, at least so far?

10:45 cemerick: xeqi: sure

10:46 oh, the piggieback patch is smaller than I thought it was. That may bump it up the queue a bit :-)

10:46 coventry: S3thc0n: You're right, there's not much to fuss over.

10:47 S3thc0n: I first watched a video using F# (which i do not know, but that did not matter much) by Brian Beckman, and just now read http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html which confirmed my understanding.

10:49 brainproxy: S3thc0n: I agree.. they're all about relationships between values and functions, which for some devs is a less "tangle" thing than an object or an object's api

10:49 S3thc0n: And you do not have to know any theory at all. Basically you make functions pure by actually extracting any side-effects, and put them in a wrapper which uses those additional data for the actual side-effect and removes it for the next function. No need for so much theory at all.

10:49 brainproxy: *tangible

10:49 S3thc0n: If I got it right.

10:51 What confused me a lot was people not really clarifying the purity aspect , as I read a lot they make functions pure (period). Having side-effects and being pure? Can't be, what the heck is this.

10:52 murtaza52: tbaldridge: here is a snippet of code that I found which is using core.async with http-kit - http://pastebin.com/2ZxiSvrv

10:53 I know that http-kit returns futures. The above code is just gathering them and conj ing them into a vector

10:53 tbaldridge: murtaza52: take a look at this : https://github.com/halgari/clojure-conj-2013-core.async-examples/blob/master/src/clojure_conj_talk/core.clj#L290

10:53 brainproxy: dnolen: what's the usual turn around time on your making a cljs release and it being available on maven central?

10:53 murtaza52: the real blocking will happen when I try to deref each future to use it. So what is the real use of the above code ?

10:54 looking at the link u sent

10:55 tbaldridge: murtaza52: the code I sent returns a channel, so it doesn't use futures. From that you can use clojure.core.async/merge and async/take to combine the results into vector

10:56 *vectors

10:56 murtaza52: I do something like that here: https://github.com/halgari/clojure-conj-2013-core.async-examples/blob/master/src/clojure_conj_talk/core.clj#L341

10:57 murtaza52: however httpkit returns futures, so wont the blocking call be when u try to use the returned result ?

10:59 tbaldridge: don't use the return value, use the callback version and put! the value into the channel (see the http-get function in the link above)

11:01 mdrogalis: Remembering to use put! and take! rather than go/>!/<! is the hardest part of core.async :P

11:02 `cbp: curse python and its unicode crap t.t

11:02 pepijnd: `cbp?

11:02 murtaza52: tbaldridge: thanks that is brilliant, I dont know why I couldnt put it together !

11:03 mdrogalis: a stupid question, what is the difference between put! and >!

11:03 `cbp: er sorry i just chose this channel to vent :P

11:03 mdrogalis: put! can be used outside of a go block, where otherwise you'd need go with >!

11:04 Definitely not a stupid question, murtaza52.

11:04 tbaldridge: murtaza52: and if there aren't any readers >! will park the go. put! will just put the value into the channel and move on. So put! is most useful at the edges of your system (eg with java interop)

11:05 mdrogalis: tbaldridge: What happens if the channel is full? Thread blocks?

11:06 murtaza52: yes I remember from rich hickey's talk that there all buffers have to have a size, there wont be any infinite ones. So does that mean we start loosing data ?

11:06 coventry: murtaza52: By default putting on a channel blocks when it's full.

11:07 sw1nn: murtaza52: you can choose what do do. (chan 10) vs (chan (dropping-buffer 10)) vs (chan (sliding-buffer 10))

11:08 tbaldridge: murtaza52: no data is lost unless you use something like dropping buffer

11:08 murtaza52: if you do 1024 put! and you have no takers the 1025th put! will throw an exception. This is very very rarely a problem, and the exception is there to keep you from writing bad programs.

11:09 murtaza52: that is if I have a (chan 1024) …

11:09 coventry: Oh. When I experimented with async my puts were blocked once the channel had 1024

11:09 elements in it.

11:09 tbaldridge: murtaza52: no, that's by default. if you do (chan 1024) then you can have 2048 pending puts

11:10 murtaza52: there are 3 "queues" in channels. The buffer (the number you give to chan), the pending reads and the pending writes. Thus if there are no takers, puts go into the pending writes, and vice versa.

11:11 The pending writes and pending reads are both hard-coded to 1024. The buffer can be any size you want.

11:12 sw1nn: tbaldridge: After seeing your talk at codemesh last week, I got my data pipeline app working well with core.async that evening, it's been downloading data pretty much ever since. thanks!

11:12 tbaldridge: awesome!

11:12 murtaza52: why have a separate pending queue when you can set the buffer to any size ?

11:12 is that talk recorded ?

11:13 sw1nn: murtaza52: code linked earlier is a goldmine of info...

11:13 murtaza52: yes let me mine it :) ….

11:14 tbaldridge: murtaza52: it has to do with what you want to happen to writers. If a writer can put a value into a buffer then that writer go/thread can continue on executing. If there is no room left in the buffer, then the go/thread blocks and waits. So the buffer is a knob to set how far you want producers to get ahead of consumers.

11:14 koalallama: so I guess calling (future somefn) where somefn calls java code may not be completely safe.

11:20 murtaza52: I understood how buffer helps me tune that. However what is the purpose of the pending queue ? If I understand correctly the pending write acts as a holding place before writing to the buffer. If the buffer is full then the writes start queuing up in the pending writes. Once the pending writes is full, then an exception is thrown. This is the case in put!. In >! it would just block once the buffer is full, irrespective of the pending writes queue.

11:21 tbaldridge: >! puts a callback into the pending writes queue

11:22 and yeah, as mentioned, it can be helpful to run through that walkthrough I linked above. Perhaps some day my video from the Conj/CodeMesh will be on InfoQ.

11:22 murtaza52: tbaldridge: thanks

11:22 it was very helpful

11:32 radix: I have googled a bit and can't find any; has anyone implemented a clojure-formatting tool that rewrites code to conform to a coding convention while also maintaining comments?

11:35 technomancy: radix: I think everyone just uses emacs =)

11:40 TimMc: radix: I recall someone playing with emacsclient to automate the use of emacs as a formatter.

11:40 hyPiRion: I wish there were some formatting tool, but alaz

11:40 alas*

11:42 S3thc0n: radix: It should not be too hard to write one yourself, I guess.

11:42 radix: S3thc0n: yeah?

11:42 technomancy: pprint has a code-dispatch mode

11:42 radix: right, but, comments

11:42 technomancy: but it's not great.

11:42 yeah, it's tricky

11:42 S3thc0n: Depending on what you mean by 'coding conventions'

11:42 technomancy: sjacket can do reading in a comment-preserving way

11:43 radix: S3thc0n: you know, the ones everyone uses.

11:43 technomancy: but I don't think anyone's hooked it up to output

11:43 radix: technomancy: I also saw rewrite-clj

11:44 S3thc0n: radix: If it is simple replacement it would work well. But if you have to replace unidiomatic code it would get quite complex, i think.

11:44 radix: S3thc0n: hmm, not sure what you mean

11:45 indigo: Ah, I love 4clojure

11:45 Especially when seeing that my 6 line solution could be done with two functions :P

11:45 mdrogalis: indigo: Yeah, I really enjoy that site.

11:45 radix: hmm, I guess unidiomatic newlines is a problem nobody's solved

11:47 S3thc0n: Let me make an example: If you only want to convert camel casing to '-'-separation, that is one thing. The next step would be adding a ? to (I'll call hem boolean functions, forgot the proper name). And then you can also try to convert checks within a function to :pre and :post statements.

11:47 radix: S3thc0n: oh, yeah, I only meant whitespace

11:48 indigo: mdrogalis: I'm up to problem 40

11:48 radix: basically, I want the equivalent of "gofmt" for clojure (I think, I've never actually used gofmt)

11:48 mdrogalis: indigo: Sweet good stuff.

11:48 radix: actually, I guess gofmt does a good bit more than whitespace.

11:48 but I only care about whitespace :)

11:49 S3thc0n: radix: I think you might be able to just traverse your code using a macro. Which uses a (or everal) regex patterns to match and replace, or even more advanced logic.

11:49 justin_smith: radix: consider that many macros imply specific formatting for their semantics

11:49 since the point of the macro is to introduce a syntax

11:50 radix: justin_smith: yep, I realize that

11:50 justin_smith: though in practice I let emacs decide how things indent

11:50 radix: right, and emacs has special cases for a bunch of different forms.

11:50 justin_smith: but I decide where newlines go (based on semantics, and often related to macro usage)

11:50 yeah, it does

11:51 radix: maybe I should just use emacs in a script. I assume it's not *too* hard to run it headless to just process a file..

11:51 S3thc0n: And then print the new code. Great thign with LSP is that code is data. Means you can even convert to :pre and :post checks easily without writing half of an interpreter as an external tool.

11:51 justin_smith: I wish emacs highlighted #_ properly btw

11:51 radix: S3thc0n: comments :)

11:51 scottj: are there docs on #js? (cljs data reader)

11:51 justin_smith: radix: yeah, there is emacs as a batch job

11:51 S3thc0n: radix: Right, forgot about that...

11:51 justin_smith: it starts up pretty fast when you are not using the gui

11:52 S3thc0n: If you don't care about ugly replace them with symbols ahead of converting it and then turn it back afterwards.

11:53 radix: I think using emacs in batch mode is probably the quickest thing to do (e.g. for a CI tool to check or rewrite code)

11:53 S3thc0n: So code -> string -> code -> string -> code

11:53 radix: and then maybe rewrite-clj for more interesting things perhaps

11:53 S3thc0n: radix: Yes, considering you onyl want to manipulate whitespace it surely is.

11:53 dav: shouldn't this work? => (defmacro blah [x] (list x)) (blah 1)

11:54 justin_smith: radix: yeah, I think you could just load clojure mode, set region to start/end of buffer, and run indent-region

11:54 radix: it's too bad clojure-mode won't insert newlines where necessary ,but it's a start

11:54 justin_smith: dav that is basically '

11:54 dav oh, never mind, it is not

11:55 radix: I bet there is a config or mode for that

11:56 radix: hmm, I'm skeptical, but looking

11:56 I've used emacs a bunch and I've never seen a mode that would actually redo your newlines

11:57 justin_smith: radix: try calling fill region

11:57 before indent region

11:57 fill-region / indent-region that is

11:57 radix: oh, huh

11:58 justin_smith: hmm no

11:58 fill-region is not smart enough

11:58 dnolen: brainproxy: supposedly up to 24 hours but in my experience just a couple of hours.

11:58 radix: ok. I use fill-region for prose a lot and mostly what I remember is that if I accidentally did it on code it would mess everything up :)

12:00 dav: justin_smith: so, any ideas why it doesn't work?

12:01 justin_smith: ugh, there is no emacs comment-defining rule that matches the behavior of #_

12:01 dav what do you expect it to do?

12:01 dav: justin_smith: return (list 1)

12:02 justin_smith: dav: a macro causes its expansion to be run

12:02 (list 1) expands to (1)

12:02 you cannot call a number

12:02 (defmacro blah [x] `(list ~x))

12:03 quasi-quote is made for this kind of thing

12:03 ('list x) would also work

12:03 if list is quoted it is returned and used in the code, not in generating the code

12:04 oh ('list x) would not work, because that is the symbol list, not the binding :)

12:05 ,('list 1)

12:05 clojurebot: nil

12:05 justin_smith: ,('list '{list :ok})

12:05 clojurebot: :ok

12:05 radix: justin_smith: found a nice recipe: http://www.cslab.pepperdine.edu/warford/BatchIndentationEmacs.html

12:06 justin_smith: oh sweet

12:06 we should totally have a clojure-set-style function, and one of the styles could auto-indent

12:06 *auto-newline / fill I mean

12:15 eigenrick: I just came here to express my undying love for merge-with

12:18 hyPiRion: it's a pretty thing

12:18 ,(merge-with merge {:foo {:a :b}} {:foo {:b :c} :bar {:g :e}})

12:18 clojurebot: {:bar {:g :e}, :foo {:b :c, :a :b}}

12:19 justin_smith: (inc merge-with)

12:19 lazybot: ⇒ 1

12:19 dav: justin_smith: thanks a lot, that worked.

12:19 justin_smith: np

12:21 brainproxy: dnolen: cool, thanks

12:31 coventry: I wrote a silly implementation of group-by using core.async a few months ago. It hangs after splitting {1, ..., 2048} into odd and even, and I thought that was because the receiving channel for the evens group had 1024 elements in, it, but apparently that's not the case. Any suggestions for why it's hanging? I tried to come up with simpler examples, but they've all worked the way I expected. https://www.refheap.com/21730

12:32 Actually, it's hanging after splitting {0, ..., 2047}, but anyway.

12:49 TimMc: hyPiRion: That only does two levels. Can you combine merge-with and merge in a way that does arbitrary depth maps?

12:49 hyPiRion: TimMc: I made Fairbrook for that purpose quite a while ago, but I'm not satisfied with its API. It's too DSLy.

12:50 TimMc: but you can make a recursive function for that purpose, sure thing

12:50 TimMc: Can you do it just with merge-with, merge, and various combinators?

12:51 I guess partial isn't a combinator.

12:51 hyPiRion: I think I didn't manage to do so with merge-with and merge.

12:51 amalloy: TimMc: (defn merge-in [a b] (merge-with merge-in a b))?

12:51 TimMc: No wait... yes it is? I dunno, bad with these definitions.

12:51 CookedGryphon: is there a way to check if a channel is closed in core.async without actually reading the value off?

12:51 amalloy: i haven't been totally following this discussion but that sounds like what you're talking about

12:52 doesn't really work, i guess

12:53 TimMc: &((-> merge-in #(merge-with merge-in % %2)) {:a {:b {:c {:d 4 :e :hi}}} :f 5} {:a {:b {:c {:d 400}}} :f 60})

12:53 amalloy: there's https://github.com/flatland/useful/blob/develop/src/flatland/useful/map.clj#L148, which probably doesn't meet your requirements for "using only merge and merge-with"

12:53 lazybot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long

12:54 TimMc: Probably only works with infinitely deep maps. :-P

12:54 hyPiRion: TimMc: well no, works fine when no nonmap values collide

12:55 TimMc: &((fn merge-in [a b] (merge-with merge-in a b)) {:a {:b {:c {:d {} :e :hi}}} :f {}} {:a {:b {:c {:d {{}{}}}}} :f 60})

12:55 lazybot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long

12:55 TimMc: &((fn merge-in [a b] (merge-with merge-in a b)) {:a {:b {:c {:d {} :e :hi}}} :f {}} {:a {:b {:c {:d {{}{}}}}} :f {}})

12:55 lazybot: ⇒ {:a {:b {:c {:d {{} {}}, :e :hi}}}, :f {}}

12:55 hyPiRion: The vararg version would be (defn merge-in [& maps] (apply merge-with merge-in maps)) I guess

12:58 sw1nn: mdrogalis: that lein deploy -> s3 repo 'lots of 307's error from yesterday went away so looks like an AWS 'feature'. All working fine now. thks

13:12 brainproxy: dnolen: after bumping to cljs 2120, I'm getting an exception re: reducers.cljs line 301, but there's no stacktrace, only the message "Uncaught TypeError: Cannot read property 'prototype' of undefined"

13:12 dnolen: brainproxy: need a lot more information

13:12 brainproxy: I can submit a ticket, but wasn't sure if you're aware of it; also, I'm not using the reducers library as far as I know

13:13 well this is an unoptimized build, so I'm getting all the cljs pieces via goog.require, even if I'm not using some of them

13:13 dnolen: brainproxy: no ticket until some basic investigation has been done - I've been using 2120 for a while now with different libs and I haven't seen this

13:14 brainproxy: did you run a clean build?

13:15 brainproxy: ah, it goes away if I don't require mori

13:15 I'm bundling mori in my build

13:15 S3thc0n: I wonder if it is generally preferred to accept an arbitrary number of arguments over a collection as input for a function. For example (+ [3 4]) vs (+ 3 4). Both has (dis)adavantages, but basically it results in a question of convention and where to cast the types.

13:18 But from basic function I would guess after thinking a bit about it that an arbitrary number is preferred (except you want to operate on a collection, obviously).

13:19 seancorfield: clojure.java.jdbc 0.3.0-rc1 available on maven central... for all you folks slaving away over a traditional database :)

13:19 bbloom: S3thc0n: just think about the most common use cases that caused you to create the function in the first place

13:20 S3thc0n: bbloom: Good idea - didn't think of that as I am one who likes to postulate general rules. But it really is as obvious (objectively, not for me apparently) as it is useful.

13:20 bbloom: S3thc0n: what do you want the typical call site to look like? If the common case is (f x y) or (f coll), then the uncommon case is (apply f coll) and (apply f [x y]) respectively

13:23 metellus: wouldn't that last one just be (f [x y])

13:23 bbloom: metellus: er yeah, of course. sorry

13:26 S3thc0n: Also one more thing about conventions: Vectors are usually used for readbility when defining collections, but as they behave differently I wonder if that is always smart (especially as long as people rely on conj order -.-). Is there a neat way to define a functions expected type and automatically cast the argument to it without doing it explicitly within the function (for example for performance reasons (which can be avoided by us

13:26 ...function or just writing two))?

13:27 Loads of questions, i hope they aren't overly stupid or annoy people. i just want to do things correct from the beginning.

13:27 tbaldridge: S3thc0n: who really relies on conj order? I think most of the time APIs either explicitly work with seqs unless you need random access, then the doc strings will say "given a vector..."

13:28 idk, conj ordering bugs are pretty rare in my experience.

13:28 S3thc0n: tbaldridge: I've seen quite a few people do it, unfortunately, as they prefer converting and then casting conj instead of doing it semantically correct.

13:29 bbloom: the only time i've run in to conj bugs is when i was first learning & had not internalized the fact that all collection functions produce lazy seqs

13:29 like i knew it on the surface, but my brain was just so used to operating on arrays in rb, js, etc

13:30 S3thc0n: I understand what you mean.

13:30 bbloom: also, until you learn about ##(conj {} [:x 1]) you tend to read conj as "append" which is just plain wrong :-P

13:30 lazybot: ⇒ {:x 1}

13:30 S3thc0n: I come from that background, too. Even heavier, as my first language was C++ :b

13:30 bbloom: i do think that clojure is missing a push function

13:31 or whatever the non-polymorphic appending function would be called

13:31 but it hasn't ever been a problem for me

13:31 S3thc0n: bbloom: Exactly my thoughts! Yesterday I complained, actually noticed cause the 4clojure problems rely on conj ordering *cringe*.

13:32 bbloom: well, frankly, push would be conj for sequences, since peek/pop work on seqs & vecs

13:32 S3thc0n: I love clojure for it's (also or even especially logical) beauty, but using conj for appending just feels terrible.

13:32 bbloom: but not maps, sets, etc

13:32 tbaldridge: why not use cons for appending?

13:32 bbloom: tbaldridge: cons is a constructor call

13:32 essentially

13:33 tbaldridge: yep, but it always append to the front of a seqable

13:33 S3thc0n: tbaldridge: because cons prepends afaik? I mean you can cast the type, but... BTW, How expensie are type casts between vectors and lists anyway in Clojure?

13:33 tbaldridge: S3thc0n: there are no typecasts between the two

13:33 S3thc0n: tbaldridge: We are talking about 'adding to the right end', i think.

13:34 tbaldridge: S3thc0n: a vector can be converted into a VectorSeq or a list can be converted to a vec via O(n) copying

13:35 I know what I'm about to say will mark me as a jerk, but here it is: you shouldn't try to make code foolproof. If people put garbage into a fn, give them garbage out. "Appending to the right" or "appending to the left" in a polymorphic way in Clojure is utter nonsense.

13:35 S3thc0n: tbaldridge: Yeah, no other means due to immutability ofc (or are there? Wondering if immutability still applies to objects having no symbol / being used nowhere else.)

13:36 bbloom: dnolen: https://github.com/swannodette/om/blob/master/src/om/dom.cljs#L29-L34 nice. see what i meant about the #js literal being like half the battle?

13:36 dnolen: that just *feels* better, even tho it's really no different lol

13:36 tbaldridge: instead, teach people to understand how their datastructures work internally and issues like polymorphic conj no longer matter.

13:36 dnolen: bbloom: no argument, I like #js and I think a lot of people will

13:36 S3thc0n: tbaldridge: DOn't exactly get what you're trying to say.

13:37 nDuff: Hrm.

13:37 dnolen: bbloom: so I think I have a design for om that doesn't suck now that avoids extra arguments and avoids dynamic binding

13:37 bbloom: tbaldridge: i agree, although i think that there is a bit of a layering violation in some of the polymorphic bits of clojure. ie you should build polymorphic things out of monomorphic things

13:37 dnolen: bbloom: I think the data at every level of the tree should get metadata with the state atom, path, and owning node

13:37 * nDuff eyes clj-json's binary Java 7 dependency warily.

13:37 dnolen: bbloom: so always accessible

13:38 bbloom: and you don't run afoul of losing the context under asynchronous actions

13:38 bbloom: dnolen: well you want to store MOST of your data entirely externally & then thread limited data around the tree. like for example i might want to have {:user-id 5 ...} but not actually put the user there

13:38 tbaldridge: S3thc0n: your original question was about if there was a way to have a function automatically convert args to vecs or seqs. My reply is, don't try to do that. Write your function to take vecs, and if someone hands you garbage, give them garbage back.

13:39 S3thc0n: I would avoid at all costs doing something like clojure.core/nth. That function is O(log32) on vecs, and O(n) on seqs. And that's just wrong, IMO.

13:39 dnolen: bbloom: sure this is just about trying to get rid of explicitly passing stuff like owner and path around

13:40 bbloom: you don't care about that stuff when you don't need it

13:40 bbloom: dnolen: why did you separate out all of those different lifecyclic protocols? why not just have one w/ default impls that are no-ops?

13:40 S3thc0n: tbaldridge: Hm. Especially if doing recursive sequence manipulations (if you end up ever doing that instead of using a core function), I think you start out with a vector but get a list after the first one.

13:40 bbloom: then you don't need the satisfies checks everywhere

13:41 dnolen: also, you should totally check in an example or test case or something :-)

13:41 S3thc0n: Since I did not do a lot of practical CLojure yet I can not say to what extend you actually end up doing this.

13:41 dnolen: bbloom: I don't see anything wrong with the satisfies checks and I prefer protocols w/ 1 method

13:41 bbloom: yeah not there yet, I wanna kill this path and owner crap

13:42 S3thc0n: But I think especially since vectors are jsut stated as a prettier way to write collections often, you should be ready handling both, as often generating functions return sequences, don't they?

13:43 [I really need to stop using the word 'return' in Clojure context...]

13:43 bbloom: S3thc0n: your base assumption is wrong

13:43 tbaldridge: S3thc0n: So in most cases I work with seqs, until I need random access, and then I convert it to a vec. And yes, most of clojure.core seq functions just call seq on any argument they are given. This is a no-op on a seq, so there's no cost involved.

13:43 bbloom: S3thc0n: vectors are not and never were a "prettier way" to write collections

13:43 pjstadig: S3thc0n: i don't use vectors for pretiness

13:43 bbloom: S3thc0n: the defining motivation was to decomplect between "evaluates as function calls" and "evaluates as data"

13:43 pjstadig: they are for declarative data where you don't want the first thing to be executed as a function

13:43 bbloom: S3thc0n: that's why we have keywords too

13:43 pjstadig: and for building things front to back instead of back to front like lists

13:44 bbloom: S3thc0n: keywords are self-evaluating symbols, just like vectors are element-evaluating collections instead of function evaluating

13:44 Osum: hi, why can't I use this

13:44 user=> (def c {:a 1 :b.c 3 :d 3})

13:44 #'user/c

13:44 user=> (let [{:keys [a b.c]} c])

13:44 CompilerException java.lang.ClassFormatError: Illegal field name "b.c" in class user$eval8321, compiling:(/private/var/folders/zl/zbg23pfs2n1d8qpmzq1j1_fjygxdw8/T/form-init7645801555683632848.clj:1:1)

13:44 tbaldridge: although one could argue that [1 2 3] is prettier than '(1 2 3), but perhaps that's just me

13:44 Osum: are the keys not supposed to have '.' in the names ?

13:44 S3thc0n: bbloom pjstadig: I agree, but you could also use (quote data), which is why I said vectors are mainly used for prettyness.

13:45 bbloom: S3thc0n: no. because quote is different thing

13:45 TimMc: Osum: Symbol literals can't have . in their names.

13:45 bbloom: S3thc0n: quote stops all evaluation, vectors only prevent function calling

13:45 tbaldridge: Osum: , (let [{foo :b.c} {:b.c 42}] foo)

13:45 bbloom: compare:

13:45 S3thc0n: bbloom: I see....

13:45 bbloom: ,(quote [(+ 5 1)])

13:45 tbaldridge: ,(let [{foo :b.c} {:b.c 42}] foo)

13:45 clojurebot: [(+ 5 1)]

13:45 42

13:45 bbloom: er rather i mean:

13:45 hiredman: TimMc: no

13:46 TimMc: &'foo.bar

13:46 lazybot: ⇒ foo.bar

13:46 bbloom: ,'((+ 5 10) (+ 2 3))

13:46 clojurebot: ((+ 5 10) (+ 2 3))

13:46 hiredman: it is a repl / compiler issue

13:46 bbloom: ,[(+ 5 10) (+ 2 3)]

13:46 clojurebot: [15 5]

13:46 TimMc: Oh, I', wrong!

13:46 bbloom: S3thc0n: the fact that vectors have nice syntax is totally orthogonal

13:46 hiredman: if you look at the actually exception it is a problem with the generated bytecode

13:46 hyPiRion: ,((fn a.b [] a.b))

13:46 clojurebot: #<sandbox$eval122$a_DOT_b__123 sandbox$eval122$a_DOT_b__123@8643e3>

13:47 bbloom: S3thc0n: rich could have very easily added a special to do that. clojure.core/vector is a function, but you could have some special symbol chagne evaluation rules just like quote does

13:47 S3thc0n: bbloom: Thank you for clarifyig, did not realize before. As most tutorials just say: Yeah, you could use '() but [] is nicer, as they use literals for the introduction.

13:47 hiredman: but I don't see how the code Osum pasted would generate that error

13:47 so either whatever repl he is using is rewriting code in a weird way, or he didn't share it exactly

13:49 S3thc0n: But is it not kind of strange to use the vector and sequence/list difference on the one hand for storage implementation, and on the other for (restricting) evaluation?

13:49 Seems kind of unrelated to me.

13:49 hiredman: ,(let [b.c 1] (fn [] b.c))

13:49 Osum: hiredman: I did share the whole thing

13:49 clojurebot: #<CompilerException java.lang.ClassFormatError: Illegal field name "b.c" in class sandbox$eval173$fn__174, compiling:(NO_SOURCE_PATH:0:0)>

13:49 bbloom: S3thc0n: so now you're getting in to the INTERESTING part :-)

13:49 S3thc0n: Oh wait.

13:50 hiredman: Oh

13:50 huh

13:50 ,(let [b.c 1] b.c)

13:50 clojurebot: #<CompilerException java.lang.ClassFormatError: Illegal field name "b.c" in class sandbox$eval222, compiling:(NO_SOURCE_PATH:0:0)>

13:50 S3thc0n: I think, I might have just gotten it wrong. The correct way to use a list is not '(data-to-be-evaluated) but (seq data-to-be-evaluated)

13:50 hiredman: Osum: right, I just didn't expect let to throw an error about field names like that

13:50 bbloom: S3thc0n: also consider: lazy sequences. they have the same syntax & evaluation rules as lists, but are very different in representation

13:51 Bronsa: hiredman: locals are compiled unmunged by Compiler.java

13:51 amalloy: hiredman: the compiler doesn't munge names for locals like it does for record fields

13:51 hiredman: sure

13:51 but locals aren't "fields" in the class sense

13:51 bbloom: S3thc0n: unlike most other lisps, clojure's SYNTAX is polymorphic. { ... } may give you a persistent *array* map or *hash* map depending

13:51 Osum: hiredman: so what's the solution ? I have this DS that comes like that from json ?

13:51 and I need to extract a field that has a '.' in name

13:51 hiredman: in fact locals don't even have names, they are addressed via numerica slots, the only place the names for locals are emitted is in the debugging information

13:51 amalloy: Osum: give it a local name that's not silly

13:52 (let [b_c (:b.c m)] ...)

13:52 hiredman: Osum: the issue isn't the name in the name, the issue is the local name you are trying to bind a value to

13:52 hyPiRion: amalloy: b-c works too, but I he's working with Datomic

13:52 S3thc0n: Hm...

13:53 hyPiRion: *I guess

13:53 Bronsa: hiredman: that name is still stored in ghe class though

13:54 Osum: amalloy: that works, except it can get very verbose really fast 'cause there are a lot of filds like that

13:54 hiredman: Bronsa: where? outside of the debugging symbol table

13:54 S3thc0n: ,(quote [(+ 1 2)]

13:54 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

13:54 S3thc0n: Oops

13:55 amalloy: so? (let [[x y z] (map m [:b.c :q.m :foo.bar])])

13:55 S3thc0n: ,(quote [(+ 1 2)])

13:55 clojurebot: [(+ 1 2)]

13:55 Osum: amalloy: got it

13:55 S3thc0n: ,(seq (+ 1 2))

13:55 clojurebot: #<ExceptionInfo clojure.lang.ExceptionInfo: Don't know how to create ISeq from: java.lang.Long {:instance 3}>

13:55 S3thc0n: ouw

13:55 amalloy: S3thc0n: you mean (list (+ 1 2))

13:56 bbloom: S3thc0n: this is why i provide some good advice: go write a lisp interpreter :-) you'll learn a lot!

13:56 S3thc0n: Yeah. Too easily confuse the two.

13:56 ,(list (+ 1 2))

13:56 clojurebot: (3)

13:57 hyPiRion: ,(list? (list* 1 2 '(3 4)))

13:57 clojurebot: false

13:57 hyPiRion: Clojure and consistency.

13:57 S3thc0n: So list is the correct way. Actually i wonder if the compiler just ignores all cast hints and only does those necessary. As in if I have a list, make it a vetor for some reason without changing it afterwards and then give that to a function actually making it a sequence/list again, it could just stay one internally?

13:57 technomancy: clojurebot: lol

13:57 clojurebot: I don't understand.

13:57 bbloom: hyPiRion: heh, oh yeah the list vs seq dichotomy is fun times

13:58 amalloy: S3thc0n: you should stop thinking of these as casts

13:58 S3thc0n: But as interfaces?

13:58 amalloy: there have not been any casts in any of these examples; they are all conversions

13:58 ivan: after ClojureScript is self-hosting, will the non-macro reimplementations of everything go away?

13:58 hyPiRion: bbloom: "fun times"

13:58 amalloy: casting is only relevant in a statically-typed language like java or c

13:58 S3thc0n: That is why i said I find it kind fo strange to associate a way of storage with it.

13:59 hiredman: casting in java is very different animal from casting in c too

13:59 dnolen: ivan: what do you mean?

14:00 bbloom: S3thc0n: it actually makes a lot of sense when you think about function application as going from something like (f x y) to splitting off the head and giving you [f (list x y)]

14:00 S3thc0n: Maybe it should have been different (IMHO which is based on probably barely any information), and [] should just be a way of writing a collection, with the difference between list and vector under the hood, dynamically converted to achieve good performance.

14:00 bbloom: S3thc0n: there can be no good performance with dynamic magic conversions

14:01 b/c it would be O(N)

14:01 S3thc0n: maybe you should spend a little more time with it before you recommend how it SHOULD be

14:03 ivan: dnolen: I was thinking about CLJS' two namespaces for macros and functions, and why this isn't needed in Clojure proper, and was wondering if having compile phase available any time would reduce the need for two implementations, but my thought was not fully baked

14:03 bbloom: ivan: your intuition is good, but there are a lot of subtle things to consider

14:04 dnolen: ivan: the CLJS way has some advantages it's unlikely to change even if we bootstrap because it would be a lot more work.

14:04 S3thc0n_: Sorry, disconnected. Did not get anything after my own last message. I think I really need a bouncer.

14:05 insejn: I have this `with-url` macro in tentacles library https://github.com/Raynes/tentacles/blob/master/src/tentacles/core.clj#L148. Is there a way to make the binding work for all the functions in a file? Or do I have to call `with-url` in every function?

14:05 bbloom: [14:00:22] <bbloom> S3thc0n: there can be no good performance with dynamic magic conversions

14:05 [14:00:26] <bbloom> b/c it would be O(N)

14:05 [14:00:43] <bbloom> S3thc0n: maybe you should spend a little more time with it before you recommend how it SHOULD be

14:05 ivan: I wonder if Rich would take a patch to have dual namespaces in Clojure as well ;)

14:07 dnolen: bbloom: I do see your point about side information, for example in TodoMVC they put the handlers in the props, and in om I would want that to be part of the data

14:07 bbloom: I'm thinking pure should take a map, one represents the actual data, the other is side information

14:07 s/would/would not

14:07 bbloom: right b/c functions have object equality, which is problematic if they are closures

14:08 as opposed to resolved from vars or whatever

14:08 it would weaken props equality

14:08 Bronsa: hiredman: it looks like it's only stored in the LocalVariableTable indeed

14:08 dnolen: bbloom: not for us, since we provide our own shouldComponentUpdate

14:09 Bronsa: hiredman: from the spec: [..] representing a valid local variable name stored as a simple name

14:09 bbloom: dnolen: no i'm saying that if you put an fn in to a map & then you re-create that map each frame then you have a freshly allocated fn in each new version, even if various subtrees of that map are identity-equal, the fn won't be

14:10 dnolen: bbloom: oh right, sorry I see you were agreeing w/ my point above them about keeping them separate

14:10 bbloom: I think this will work out nicely, data, and extra stuff

14:10 and data hold import tree context information as metadata

14:11 bbloom: i have some alternative ideas, but i'll refrain from sharing to see how your approach turns out

14:11 dnolen: important

14:11 bbloom: b/c i considered something very similar to that, but went a different way in my notes. curious to see what you come up with

14:11 dnolen: bbloom: feel free to share if you think it's significantly better this is like version 4/5 for me.

14:12 bbloom: dnolen: i'd rather you get something done with callbacks than wind up doing some architecture astronauting with me :-)

14:13 dnolen: bbloom: heh, right :)

14:13 S3thc0n: I hope it is a bit more stable now.

14:13 Sorry again. So, why would performance be worse than with explicit conversions?

14:13 dnolen: bbloom: re callbacks, I was thinking about sending down channels in the side information part of props

14:13 bbloom: S3thc0n: you're proposing strong AI :-P

14:14 S3thc0n: Sorry that it ain't obvious to me.

14:14 dnolen: bbloom: probably won't use that approach initially, but I think the design allows it

14:14 S3thc0n: Yes I am. Is that bad?

14:14 If we are compiling anyway, why not use that?

14:14 pl6306: I have a simple question. I want to find the all index (i.e. numeric position) of "<c>" with in "<S> <C> <C> <C> <C> <C> <C> <C> <C> <C> <C> <C>". There has got to be an easy way to do this in clojure. Thanks in advance for the help.

14:15 bbloom: S3thc0n: the first sentence in the wikipedia article on strong AI uses the word "hypothetical" :-)

14:15 dnolen: yeah, channels have their own issues as far as UIs go too

14:15 S3thc0n: Wait a moment. You mean that literally.

14:15 bbloom: dnolen: probably will need some macros for putting together the lifecycle states, etc

14:16 dnolen: bbloom: definitely, but I don't know if you've looked at React TodoMVC and how they communicate between app and todo item, a bit too much coupling for my tastes.

14:16 bbloom: dnolen: like i said, rock & roll w/ the "side data" idea & see where you land

14:16 S3thc0n: Why would it have to be strong? Many other languages do implicit 'casting', conversion for us if I may.

14:17 Kind of the same as it is right now with PersistentArrayMap and HashMap.

14:17 eigenrick: p16306, find replace all <C> with C, then load into an array, then count all instances of C

14:17 bbloom: S3thc0n: it would require an O(N) copy and deciding when it's OK to add a copy like that without killing perf is a bad idea

14:17 pl6306: I just want to know what is the index of the instances of <C> when the string is treatetd as a char array

14:17 llasram: S3thc0n: Maybe what you're missing is ##(seq? []) ?

14:17 lazybot: ⇒ false

14:17 nDuff: pl6306: If you can't think of a native algorithm, I'd start by thinking about how you'd do it in Java.

14:18 pl6306: ...if the relevant Java standard library bits (String, Matcher, Pattern) have what you need (hint: they do), that at least gives you a fallback position.

14:19 S3thc0n: I do not see why there has to be a real difference between a list and a vector, so why a vector cannot be a sequence. What do whe even need them for except different storage (which can be abstracated away)?

14:19 *abstracted

14:19 pl6306: ok I will look into that

14:19 hyPiRion: pl6306: Use .indexOf from the String class

14:19 bbloom: S3thc0n: they are wildly different data structures

14:20 hyPiRion: ,(.indexOf "foo bar <C>" "<C">)

14:20 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: indexOf for class java.lang.String>

14:20 nDuff: S3thc0n: abstracting away details which have huge performance impact is a Very Bad Idea.

14:20 bbloom: S3thc0n: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentList.java and https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentList.java

14:20 pl6306: Yes but how do I do .indexOf repeatly whill feeding in the result of the first call

14:20 hyPiRion: clojurebot: what drugs are you taking, man?

14:20 clojurebot: Excuse me?

14:20 bbloom: S3thc0n: sorry make that second link https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java

14:21 nDuff: S3thc0n: One of Clojure's big goals is being a highly practical language. Doing expensive, slow things without being explicitly told to is not conducive to practicality.

14:21 llasram: pl6306: `iterate`!

14:21 ,(let [f (fn [s] (->> (iterate #(.indexOf s "<C>" (inc %)) -1) (drop 1) (take-while (complement neg?))))] (f "la la la <C> la la <C> <C> foo <C>"))

14:21 clojurebot: (9 19 23 31)

14:21 rrc: hi everyone, how might you go about looping when you need to recur from the body of a catch?

14:22 S11001001: rrc: trampoline

14:22 rrc: perfect, thanks!

14:22 pl6306: iterate look promising thanks!

14:23 nDuff: S3thc0n: ...it's one thing to have constant-factor performance penalties, but silently doing O(n) things which would otherwise be O(log32 n) is a whole different ballpark.

14:23 S3thc0n: nDuff: What I do not see is why it should be slower than currently, where vectors are often just used for the square brackets and then converted to a seq.uence. But maybe I'll have to read more on the datatypes.

14:24 bbloom: S3thc0n: because vectors are immutable, converting to a seq is a O(1) operation

14:24 brainproxy: trampoline is one of my fav "tricks" of late :D

14:24 S3thc0n: bbloom: And I guess that 1 is not a lot? That solves the whole thing kind of.

14:26 bbloom: S3thc0n: it's quite clear that you don't have a strong enough understanding of this subject to make recommendations on how to address any perceived problems. that's not an insult, that's a recommendation to go try to write some bigger things with clojure & learn as you go. if you get curious, check out the clojure source code, it's quite approachable

14:26 eigenrick: haha

14:27 I love that trampoline is less like the os/kernel definition of the term, and much more like a real trampoline

14:27 it keeps bouncing...

14:28 S3thc0n: Yeah, no offense taken. Actually that is what I thought is the reason for my suggestion from the very beginning. As I highly doubt everyone designing and using the language has overlooked something like that, especially since everything else (and that too as my assumption is wrong) is so perfect.

14:28 bbloom: Mention did no fit in there anymore.

14:29 I was rather trying to get where my current misunderstanding is.

14:30 bbloom: S3thc0n: it will become very apparent after more practice, i promis eyou

14:34 Morgawr: dnolen: is there a changelog for the new clojurescript release? Someplace I can browse?

14:34 S3thc0n: I think I made a big mistake as in that I thought (seq [something]) was kind of like (into '() [something]) (ignoring that the order is different due to conj instead of our suggested 'push')

14:34 Memo: Sequences /= lists

14:35 A list is just very close, which confused me. Is at least this assumption right?

14:35 technomancy: S3thc0n: IIRC a list is a seq, but not all seqs are lists because lists aren't lazy.

14:37 divyansr: In this code snnipet http://nakkaya.com/2010/02/10/a-simple-clojure-irc-client/ author used ref. Can atom be used there since there is no coordinated change going on ? or I am missing something

14:37 TimMc: Lists happen to implement ISeq, but it might help to pretend (seq some-list) actually returns soemthing else.

14:37 dnolen: Morgawr: my post the Clojure/ClojureScript ML

14:38 Morgawr: otherwise - http://build.clojure.org/job/clojurescript-release/54/

14:38 Morgawr: dnolen: alright, thanks!

14:39 zerokarmaleft: S3thc0n: dspiewak gave a great talk at conj '12 on underlying data structures: http://www.youtube.com/watch?v=pNhBQJN44YQ

14:39 S3thc0n: TimMc: This is what I thought, too. It just happens that sequences are printed as lists.

14:39 eigenrick: divyansr: it seems like atom would work there with swap!

14:39 S3thc0n: zerokarmaleft: Thanks.

14:40 divyansr: eignerick : Thanks. Of late I am reading lots of code where atom is sufficient. Is ref overused in clojure ?

14:41 eigenrick: divyansr: I can't comment on the performance characteristics of either, maybe it's underutilized :)

14:45 technomancy: divyansr: most synchronization problems grow to a larger scope than a single node, so the sweet spot for refs is somewhat narrow

14:47 S3thc0n: Damn it. The Scala in that talk makes me realize I am already turning in what is called a 'LISP snob', if I am correct....

14:47 Even though having done so little in it.

14:49 divyansr: :technomancy you mean sweet spot of atom is narrow.

14:49 technomancy: divyansr: no, atoms are for when you don't have any synchronization

14:50 which is more common than synchronization that's limited to one node

14:50 hiredman: technomancy: coordination

14:51 atoms are synchronized, but you cannot coordinate changes to a group of atoms easily

14:51 technomancy: right, sorry

14:51 hiredman: http://wiki.gungfu.de/uploads/Main/clojure-conc.png

14:52 divyansr: hiredman: Yup I find people using ref when atom is sufficient. May be atom are under utilized.

14:53 technomancy: it is common in very old code (swank-clojure) because atoms were introduced after refs =)

14:54 bbloom: i'm amused when i see these code bases with AST.ext that are thousands of lines of code long & then think about cljs which just sticks some shit in a map & gets the job done

14:56 koalallama: fixed my first Java threading / clojure bug today. Feel like Leo DiCaprio on the Titanic

14:56 bitemyapp: koalallama: :)

14:56 technomancy: clojurebot: near, far, where ever you are...

14:56 clojurebot: Pardon?

14:59 SegFaultAX: clojurebot: Every form you eval, every macro you expand, I'll be watching you...

14:59 clojurebot: No entiendo

15:00 koalallama: was calling a function via a future, but was getting same result. second call to deref the future would either block or throw NPE. Issue was the Java object was being created in a def. Moving it to a let within the function fixed it

15:01 SegFaultAX: koalallama: You were def'ing in a future?

15:01 TEttinger: bbloom, to be fair, cljs is probably thousands of lines of code too.

15:02 koalallama: SegFaultAX: some code I was using was ;)

15:03 SegFaultAX: future would call a function and that function would use def to bind some Java objects

15:04 bitemyapp: koalallama: that is terrible.

15:04 koalallama: where does this code live?

15:07 koalallama: bitemyapp: https://github.com/jlbfalcao/clojure-snmp

15:07 URL of source file is: https://github.com/jlbfalcao/clojure-snmp/blob/master/src/main/clojure/clojure/snmp.clj

15:07 bbloom: TEttinger: i'm referring specifically to declaration of the AST

15:07 bitemyapp: koalallama: this code was written 4 years ago and hasn't been touched since

15:07 bbloom: TEttinger: we just *don't do that* :-P

15:07 koalallama: bitemyapp: yup

15:08 bitemyapp: koalallama: don't...do that.

15:08 koalallama: (it's not my code)

15:08 bitemyapp: koalallama: fork it and fix it.

15:08 koalallama: who gives a shit? fix it.

15:08 that code is fuck-awful and not even formatted correctly

15:08 this person didn't understand Clojure at all. my fucking god.

15:08 devn: please chill.

15:09 koalallama: It's on my list. I'm not even 2 weeks into clojure.

15:09 bitemyapp: koalallama: it's a few lines, you could rewrite with an internal ns

15:09 koalallama: then vendor or make your own library later.

15:09 tbaldridge: koalallama: don't worry, bitemyapp is a bit...abrasive at times.

15:09 bitemyapp: koalallama: so you

15:09 bbloom: TEttinger: analyzer.clj + compiler.clj is less than 2500 lines. that's dramatically different than many compiler projects that have over 3k lines of AST definitions

15:09 bitemyapp: are somewhat fortunate here.

15:09 TEttinger: wow

15:09 koalallama: tbaldridge: no worries ;)

15:10 S3thc0n: Ouw.

15:10 bbloom: bitemyapp: the trailing )s are a dead give away

15:10 bitemyapp: bbloom: yep.

15:10 bbloom: don't even need to read th e rest of the code to see the way defs are used *cringe*

15:10 TEttinger: ##(+ 1 2 3))))))))))))))))))))))))))))))))))

15:10 lazybot: ⇒ 6

15:11 S3thc0n: Oooh. Thanks again, zerokarmaleft. This cleared it up.

15:11 Bronsa: TEttinger tools.analyzer's analyzer is even more compact: ~600 lines of analyzer + ~400 of passes

15:11 TEttinger: neat

15:12 koalallama: bitemyapp: I'm reading Clojure Programming now. When I'm done with it, then I'll feel more comfortable making changes ot other people's code. But I can obviously tell this code has major issues

15:13 bbloom: yeah, and that can shrink dramatically if we used some kind of parser library rather than the adhoc parsing that does on for def and try/catch and all that jazz :-P

15:13 which is like half of this file: https://github.com/clojure/tools.analyzer/blob/master/src/main/clojure/clojure/tools/analyzer.clj

15:13 heh

15:14 Bronsa: bbloom: wanna talk about 'ns parsing in clojurescript? that's painful.

15:14 jonasen: Bronsa: talking about tools.analyzer... What does an ':op :host-interop'? When the ast is produced with tools.analyzer.jvm/analyze?

15:14 bbloom: yeah. i've been meaning to rewrite that. afaict, it's a regular language, not context free or anything. should be easy to do with a hand-coded state machine

15:14 jonasen: sorry... what does :host-interop refer to?

15:15 Bronsa: jonasen: it's a (.foo bar) form that we don't know if it's a method call or a field access

15:15 bbloom: Bronsa: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/analyzer.clj#L500-L513 <- like that

15:15 eggnoggin: I still can't tell the difference

15:15 jonasen: Bronsa: ah, ok. So it must be determined at runtime?

15:15 eggnoggin: between when to use - and . in cljs

15:16 Bronsa: jonasen: yeah, it's like not :validated :instance-field/etc but we don't eve know if it's a field or a method

15:16 bbloom: eggnoggin: it's confusing, but dash on it's own doesn't mean anything. dot means call method and dotdash means get property

15:16 that's the whole rule

15:16 Bronsa: bbloom: now that I look at it, looks like dnolen already refactored that a bit, looks nicer than what I remember

15:17 bbloom: Bronsa: that was me :-P

15:17 dnolen: ok this is getting awesome - https://gist.github.com/swannodette/7915826, using om from master now

15:17 Bronsa: bbloom: oh, sorry :)

15:17 dnolen: no more pushing path around, nor more magic *state* dyn var, and pure can takes opts

15:18 bbloom: Bronsa: no worries. dnolen is always a good initial guess for who wrote any of that, heh

15:18 jonasen: Bronsa: what's the difference between :var and :the-var?

15:18 bbloom: Bronsa: in any case, my point is that we can/should do stuff like that in more places

15:18 eggnoggin: bbloom: but what about stuff like https://github.com/swannodette/om/blob/master/src/om/dom.cljs#L45

15:18 Bronsa: jonasen: :var is +, :the-var is #'+

15:18 dnolen: bbloom: ha! untrue, most a lot of analysis stuff predates me

15:19 bbloom: dnolen: you're still a good guess for last person to show up in a git blame situtation :-)

15:19 eggnoggin: that's the confusing part. it's just a convention for private protocol implementations

15:19 Bronsa: bbloom: agreed

15:19 bbloom: eggnoggin: dash means nothing on it's own

15:19 eggnoggin: the convention is -foo is the protocol method and you'd expect there to be a regular foo var

15:19 eggnoggin: ah okay so it is just a naming convention like *var*

15:19 bbloom: yeah

15:20 unfortunately, it predates the .- syntax

15:20 eggnoggin: dnolen: om looks awesome btw

15:20 was pleasantly surprised that I could read and understand the entire implementation

15:20 Bronsa: jonasen: so :the-var means (var something), :var means a symbol that resolves to a var

15:20 bbloom: eggnoggin: the exception to the rule however is this: https://github.com/swannodette/om/blob/master/src/om/dom.cljs#L43

15:20 the .. macro cheats a bit and parses the symbol

15:20 dnolen: eggnoggin: it's changed a bit, but it's still pretty straight forward

15:20 bbloom: i guess technically that works with . too: (. this -props)

15:21 but the rule still applies: - means nothing on it's own, it's only when combined with .

15:21 jonasen: Bronsa: got it. var is a special form which translates to an {:op :the-var} in the ast

15:21 eggnoggin: hah, interesting

15:21 thanks bbloom

15:21 bbloom: np

15:21 i wish we had another character to use :-/

15:21 Bronsa: bbloom: huh?

15:21 user=> (deftype x [a])

15:21 user.x

15:21 user=> (. (x. 1) -a)

15:21 eggnoggin: bbloom: I met you at clj-west last year btw :)

15:21 Bronsa: 1

15:22 bbloom: eggnoggin: if you don't tell me who you are, that just sounds creepy ;-)

15:22 eggnoggin: we had food truck eats together

15:22 Bronsa: oh, sorry, I misunderstood what you were saying

15:22 bbloom: ah, i recall that, what's your name again?

15:22 eggnoggin: Thomas

15:22 anyhow, just a hat tip, thanks again

15:22 bbloom: cheers

15:23 Bronsa: jonasen: I gotta go now, I'll be back in a couple hours, if you have any more questions query me and I'll reply when I come back

15:23 Osum: what am I doing wrong here

15:23 user=> (defn myf #_=> [ m funs ] #_=> (loop [ ds m fun ( first funs) acc [] ] #_=> (if(empty? funs) #_=> acc #_=> (recur ds (rest funs) (cons acc (fun ds))) #_=> )))

15:24 #'user/myf

15:24 user=> (myf '(1 2 3) [a b])

15:24 ClassCastException clojure.lang.PersistentList cannot be cast to java.lang.Number clojure.lang.Numbers.minus (Numbers.java:135)

15:24 or is there a better way to do this

15:24 S3thc0n: bbloom: Ok, I think I see now.

15:24 Osum: I would like to apply a set of functions to a datastructure and obtain a concatenated list of the results

15:24 bbloom: the first thing you're doing wrong is pasting unformatted blobs of code in to irc :-)

15:24 llasram: Osum: Well, first, use refheap.com or another paste service so we can see what you're doing

15:24 Osum: bblom : besides that :P

15:24 user=> (defn myf

15:25 nDuff: Osum: how does this differ from juxt?

15:25 coventry: Osum: You need to recur on (rest funs), and take (first fun) inside the loop.

15:25 Osum: https://gist.github.com/fr0stbyte/7950783

15:26 bbloom: dnolen: why dyou need the ref "add" ?

15:26 dnolen: bbloom: oops I don't that was just testing ref capability

15:26 bbloom: dnolen: gotcha

15:26 dnolen: really good solve the array problem :-)

15:26 S3thc0n: bbloom: By the way I really admire you helping everybody and having so much patience. :) Not to say others don't (thanks to those, too), I just have seen you hang around here quite a bit.

15:27 Osum: nDuff: juxt ?

15:27 bbloom: S3thc0n: i think you're the first/only person to ever describe me as having much patience

15:27 dnolen: bbloom: yep gonna put together an Iterator/PureIterator patch together for React

15:27 coventry: ,(doc juxt)

15:27 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

15:27 nDuff: Osum: http://clojuredocs.org/clojure_core/clojure.core/juxt

15:27 coventry: ~juxt

15:27 clojurebot: juxt is the bestest option though if it doesn't weird you out

15:27 bbloom: dnolen: you gonna make the patch yourself? w00t

15:27 dnolen: bbloom: then we can just send sequences to React and om will wrap then in an iterator

15:27 bbloom: I will yes when I get some time

15:28 Osum: nDuff : it's not . I didn't know about juxt

15:29 bbloom: dnolen: is data required to be a map?

15:29 dnolen: bbloom: no

15:29 bbloom: dnolen: well it has to support metadata, right?

15:29 dnolen: bbloom: it has to be IMeta

15:29 bbloom: ok

15:30 dnolen: IWithMeta

15:30 Osum: nDuff : thanks, that works exactly like I needed to

15:30 bbloom: loving the #js

15:30 dnolen: bbloom: :)

15:31 bbloom: dnolen: i don't see where you do any dissoc-in or anything of the sort. how are you handling when stuff exists the dom?

15:31 clojurebot: Cool story bro.

15:31 S3thc0n: bbloom: I now get why my entire point was completely invalid. If I undersood this correctly, the rest of a sequence of a vector will not be a list (that'd be so very unperformant).

15:31 dnolen: bbloom: what do you mean?

15:32 bbloom: like removing stuff from the dom by dissoc-ing?

15:32 or filtering something out?

15:32 bbloom: dnolen: i mean consider a path like [:counters 5]

15:32 oh, those are atoms in the metadata

15:32 hm

15:32 i see

15:32 interesting

15:33 sorry, i thought you had a global state tree, but you have local state attached to the values

15:33 not sure how i feel about that

15:33 dnolen: bbloom: it's not local, that is the global atom

15:33 bbloom: oh, yeah then ok you have a memory leak :-P

15:33 dnolen: bbloom: by putting in the metadata we avoid dynamic binding and passing it around explicitly

15:33 bbloom: sure, but you need to handle lifetime of that data

15:34 consider if i make 1M counters, then delete them all

15:34 you'll have 1M counter states in your global atom

15:34 this is the lifetime management problem that react solves with state

15:35 dnolen: bbloom: I don't follow, if you delete something it will get collected

15:35 everybody shares the same atom

15:35 this is a DAG

15:36 S3thc0n: bbloom: If I am right all this casting I was thinking about never happens; and I maybe should just return the type I was given (vector -> vector, list -> list) (except if for performance reasons I would operate on a specific one of the two)?

15:36 dnolen: bbloom: we always rerender from the root, dead stuff gets blown away

15:38 bbloom: dnolen: oh sorry, i misread some of this a bit. thought the data had parallel state

15:39 s/parallel/isomorphic

15:40 S3thc0n: I have one question about Clojure datastructures left: What happens if no reference exists and that structure is then manipulated? Is a new one returned and the old one GCed (more in line with normal behaviour and simpler, maybe not as effective) or (ignoring immutability since it probably wouldn't grant any benefit) the old changed?

15:41 coventry: S3thc0n: Start here: http://hypirion.com/musings/understanding-persistent-vector-pt-1

15:41 technomancy: S3thc0n: what?

15:42 bbloom: S3thc0n: no, better yet, start here: http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey

15:42 technomancy: if no reference exists who's manipulating it?

15:42 S3thc0n: Yeah, sorry. I'll giev an example fo what I mean.

15:42 *give

15:42 coventry: He means what happens to the old copy when you do something morally equivalent to update in place.

15:43 nDuff: S3thc0n: when that optimization is needed, it's available via transients.

15:43 S3thc0n: Imagine (map inc [1 2 3]): Does [1 2 3] still exist alongside with [2 3 4] until GC gobbles it up or does [1 2 3] turn to [2 3 4] (I know there's also lazyness).

15:43 nDuff: So not by default, but still possible?

15:43 technomancy: some manipulations share structure. map doesn't.

15:43 bbloom: S3thc0n: GC gobbles it up. the more interesting question is what happens when you (assoc (vec (range 10000)) 50 :x))

15:44 S3thc0n: it's called structural sharing. watch the rich hickey video ^^

15:44 S3thc0n: bbloom: I know about that.^^ What i meant that you do not need the old structure if it is not known to anything else.

15:44 bbloom: S3thc0n: yeah, that's kinda the entire point of GC

15:45 nDuff: S3thc0n: ...right, and transients give you that, while doing some checking to ensure that there aren't any cross-thread references.

15:45 S3thc0n: Nice, thanks for that info :)

15:45 You guys are great!

15:46 nDuff: S3thc0n: while dalvik is pretty awful at GCing lots of very small objects, the JVM is good enough at it that in a lot of common cases this isn't a pain point.

15:47 S3thc0n: nDuff: Yeha, I definitely won't employ it if I don't have to. Just was interested in that as a consequence of that 'new' (to me) immutability construct.

15:50 nDuff: S3thc0n: *nod*. The way things are implemented, one isn't copying (and discarding) big objects even when changing small parts of a large map or vector, so it stays pretty well within the JVM's sweet spot.

15:51 expez: Why can a deref inside a transaction trigger a transaction retry?

15:51 nDuff: expez: if you deref something, and it changes before you're committed, then your result isn't necessarily valid.

15:51 expez: ...since it's based on the old value.

15:52 expez: how does altering the min-history and max-history change that situation?

15:52 nDuff: Ahh.

15:53 S3thc0n: Right now and very often I think it is amazing how perfect CLojure fits the JVM. Oracle should just make Clojure the new main language of the JVM and make the resources becoming available available to Rich Hickey :b

15:53 nDuff: That's a different case.

15:54 expez: if your transaction is anchored in an older version of state that isn't available any longer...

15:54 hyPiRion: Well, the JVM spec isn't that good for Clojure, really. The JVM implementations are, though.

15:54 Although faster boot would be lovely.

15:55 expez: nDuff: the chapter in clojure programming makes it sound like the stm forgets the value at the start of the transaction and then offers the solution to keep all the states of the ref throughout the transaction. Why not just keep the first value which we need for camparison when committing?

15:56 S3thc0n: hyPiRion: There might come a time where a JVM will be permanently running anyway, and if you then precompile it should be quite fast, shouldn't it?

15:57 hyPiRion: yeah, but reality is that when you're developing, you end up having to reload the JVM from time to time.

15:57 also Leiningen

15:57 nDuff: expez: I actually don't want to answer that one without checking against reference material; I'm not comfortable enough in my mental model to pretend to be authoritative.

15:57 hyPiRion: For long-living processes, the boot times doesn't matter

15:57 expez: nDuff: aight, I can appreciate that. Thanks anyway!

15:58 graue: hi clojurists, what's a good way to read a binary file into memory in its entirety as a byte array? like 'slurp' for binary data

15:58 S3thc0n: hyPiRion: see what you mean, guess that is the price we got to pay for all the goodness^^

15:58 graue: every suggestion i can find is either very low level and requires manually looping and reading in blocks; or refers to old stuff in clojure.contrib.io that doesn't seem to be around anymore

15:58 ivan: S3thc0n: all three approaches to changing Java code on the JVM (classloaders + class unloading, bytecode rewriting aka jrebel, DCE) have their problems

15:59 technomancy: graue: c.j.io/copy from an input-stream to a baos

16:01 hyPiRion: S3thc0n: Yeah, the JVM was the optimal choice because it's a good platform to bootstrap on (libraries, good perf). My comment related to Clojure being the main language of the JVM would certainly imply faster boot times for Clojure, but the underlying VM design isn't an "excellent" fit

16:01 graue: technomancy: thanks, assuming baos = ByteArrayOutputStream? will try

16:01 hyPiRion: Granted, no VM would be excellent except one designed for Clojure, so there's that.

16:03 tbaldridge: hyPiRion: and with a custom VM you loose one of the best JITs and GCs

16:03 technomancy: graue: yeah

16:03 clojurebot: baos is ByteArrayOutputStream

16:03 clojurebot: 'Sea, mhuise.

16:08 hyPiRion: tbaldridge: yeah, if not _the_ best JITter

16:09 Well, I'd guess some JS impl could be faster?

16:09 dsrx: luaJIT is supposed to be pretty good

16:11 andonilsson: Emacs question: Is there a good way to get auto-complete work in clojure-mode?

16:11 Cider gives me great auto-completion in the repl, and I would like the same in my source files. Googling "clojure auto completion in emacs" just gives me links about the repl, and not about the source files.

16:12 sritchie: andonilsson: ac-mode works well, I think

16:13 do you guys have any clue why "lein test" seems to be executing every test twice?

16:16 hiredman: sritchie: do you have symlinks?

16:16 I dunno, I guess that wouldn't do it

16:16 sritchie: what makes you think they are running twice?

16:16 sritchie: do you have some crazy fixtures?

16:16 sritchie: hiredman: I have a fixture in one spot, for schema

16:17 I'm seeing printlns twice in a bare file

16:17 the real issue I'm debugging is this:

16:17 Caused by: java.lang.ClassNotFoundException: taoensso.carmine.protocol.IRedisArg

16:17 about a protocol,

16:17 and I'm worried that the tests are eval-ing a protocol twice

16:17 let me try removing that fixture

16:18 hiredman: sritchie: is the file being loaded and run twice? or is it just each test running twice?

16:18 sritchie: it's a bare println, so the file's being loaded and run twice

16:19 cmiles74: andonilsson: I think ac-nrepl is what you're looking for. https://github.com/clojure-emacs/ac-nrepl

16:19 sritchie: also, midje's future-fact forms are printing twice

16:19 cmiles74: andonilsson: It uses nrepl to build of the auto-complete list and then auto-complete to display the choices.

16:20 coventry: sritchie: Did you use :reload in any of your ns forms?

16:20 dsrx: I've gotta try ac-nrepl again

16:20 sritchie: nope, nowhere

16:21 andonilsson: cmiles74: and that should work, not only in the repl-window, but also in my source-buffer? I have it installed already, but in that case I probably haven't configured it properly...

16:22 sritchie: coventry: it only seems to happen before the tests start running

16:22 cmiles74: andonilsson: I believe it will *omly* work in the source files. It's using Cider to build up the list of completion options that it displays in your source code buffer.

16:23 sritchie: coventry: one of them might make sense, since two namespaces require the namespace with hte println

16:23 but not the second call to future-fact

16:24 cmiles74: andonilsson: Do you have auto-complete installed? Like many bits of Emacs, it's spread all over. Cider for the options, ac-nrepl to supply the options to auto-complete and then auto-complete to display them.

16:24 andonilsson: cmiles74: yes, auto-complete is installed. adding some stuff to my .emacs right now. let's see if things get better...

16:26 technomancy: sritchie: midje has some weird behaviour where stuff runs at compile time

16:26 not a fan

16:27 sritchie: I'm running the facts as "lein test", though

16:27 hiredman: sritchie: oh, there is your problem, midje

16:28 cmiles74: anondilsson: It's working for me... It's been a while since I set it all up. Here's a link to me configuration on the off chance it's helpful in some way.

16:28 S3thc0n: In 'Are We There Yet' Rich Hickey talks about possibly linking I/O to STM, is there anything in sight for that (either I am abd at googling or nothing is to be found), for example using STM to access an external database?

16:29 sritchie: hiredman: even without the midje runner,

16:30 you think midje is double requiring my files?

16:30 coventry: S3thc0n: STM hasn't turned out to be as big a deal as he expected back then. His talk "The Language of the System" talks about cross-machine co-ordination, though.

16:30 hiredman: sritchie: I wouldn't put it past midje

16:30 sritchie: haha

16:30 S3thc0n: coventry: Great, I'm minutes before starting that one. :)

16:30 sritchie: hiredman: I like midje for the mocking… is there a better lib I should be checking out?

16:30 andonilsson: cmiles74: thx for the help! got it working now. I was missing the setup of ac-nrepl in my .emacs

16:31 hiredman: sritchie: I dunno, I just use clojure.test

16:31 technomancy: clojurebot: mocking?

16:31 clojurebot: Titim gan éirí ort.

16:31 cmiles74: andonilsson: Good deal! You are welcome. :-)

16:31 sritchie: haha, I knew it

16:31 technomancy: clojurebot: with-redefs?

16:31 clojurebot: with-redefs is useful for mockin...

16:31 cemerick: sritchie: It's mocking you? And you like it?

16:31 hiredman: yeah lots of with-redefs

16:32 sritchie: midje dogpile

16:34 tbaldridge: (inc clojure.test)

16:34 lazybot: ⇒ 1

16:35 technomancy: (inc *1)

16:35 lazybot: ⇒ 1

16:35 technomancy: doh

16:35 (inc clojure.test)

16:35 lazybot: ⇒ 2

16:36 coventry: lein test actually does a (require :reload) for each test namespace, so if the test namespaces are requiring each other, you could get duplicate evaluation from that.

16:37 hyPiRion: technomancy: you could implement (inc *1) for lazybot, that would save me a couple of characters from time to time

16:38 amalloy: but what if someone wants to give a karma boost to the *1 feature, hyPiRion?

16:38 hyPiRion: then I'm sorry for their loss

16:39 amalloy: (inc '*1), clearly

16:49 justin_smith: (inc clojure.test)

16:49 lazybot: ⇒ 3

16:51 bitemyapp: ~midje is :(

16:51 clojurebot: 'Sea, mhuise.

16:55 bitemyapp: ~midje

16:55 clojurebot: midje is :(

16:55 bitemyapp: good. GOOD.

16:56 brainproxy: ~shared mutable state

16:56 clojurebot: shared mutable state is http://image.slidesharecdn.com/concurrencygotchas-100408105435-phpapp01/95/slide-7-728.jpg

16:56 bitemyapp: brainproxy: <3

16:57 brainproxy: alex miller (puredanger) put that together, but it makes me chuckle every time

17:07 TimMc: (inc midje) ;; sometimes

17:07 lazybot: ⇒ 1

17:13 sritchie: coventry: okay, that might be it

17:13 yeah, I do

17:14 coventry: any way to turn that off?

17:14 logic_prog: is there any "minimal apl written in clojure" blog post?

17:14 sritchie: maybe I can refactor

17:15 bitemyapp: TimMc: o_o

17:24 sritchie: coventry: ugh, didn't help. still the double require.

17:24 hmm

17:27 technomancy: is there an easy way to get leiningen to run tests on all tests in a subdirectory?

17:27 "lein test some-glob", vs specifying thenamespaces directly?

17:27 technomancy: sritchie: only if the subdirectory is a classpath root

17:28 sritchie: okay

17:28 technomancy: you can write test selectors

17:28 but they won't prevent the tests from being loaded, just run

17:28 and iiuc with midje it's the loading that's problematic

17:29 sritchie: just trying to narrow down the file that's doing this double loading

17:38 technomancy: odd - the double printlns don't happen if I manually include every single test namespace

17:38 but lein test by itself double-requires

17:41 TimMc: bitemyapp: I like some of the mocking in midje, and there are some nice destructuring matchers.

17:41 bitemyapp: TimMc: *grumble should be just libraries grumble missing the grumble grumble point of Clojure grumble*

17:42 TimMc: Yeah, I'd definitely be happier if it were more composable.

17:45 sritchie: technomancy: I think I know what's happening

17:45 coventry: technomancy: I'm specifying my test-paths in the dev profile

17:45 and I think lein test is merging the default test-paths with my specified ones

17:46 technomancy: sritchie: yeah, you can use :test-paths ^:replace [...] if you don't want it to merge

17:47 sritchie: okay, that was it

17:47 technomancy: nice object lesson in why it's nice to avoid side-effects at compile time though

17:48 sritchie: :)

17:49 coventry: sritchie: Maybe you could figure out what's requiring what by outputting a stack trace where your printlns are.

17:49 sritchie: coventry: the issue was that leiningen was merging the default test-paths with my develop test paths;

17:49 and then not unique-ing

17:50 technomancy: would unique-ing make sense?

17:50 technomancy: sritchie: inside the test task, sure

17:51 happy to take a patch for that

17:52 sritchie: https://github.com/technomancy/leiningen/pull/1399

17:52 technomancy: lightning fingers!

17:53 merged

17:53 hyPiRion: I was sort of hoping Michael Klishin would come in and merge it in front of your eyes

17:54 amalloy: (inc hyPiRion)

17:54 lazybot: ⇒ 26

17:54 technomancy: hehe

17:54 sritchie: haha

17:54 fastest merge in the west

17:55 technomancy: github isn't showing enough granularity in timestamps to see if it was under 60s or not

17:56 apparently it was

17:57 51s ± timestamp skew

18:02 sritchie: :)

18:04 technomancy: does that earn me a sticker?

18:04 technomancy: sure thing

18:04 sritchie: boom

18:04 years-long dream accomplished!

18:10 eggnoggin: dnolen: where can I find org.clojure/clojurescript "0.0-2120" that om depends on?

18:11 dnolen: eggnoggin: it takes up to 24 hours to hit Maven Central

18:11 eggnoggin: ah, okey dokes

18:12 it's a real dep tho right? the older ones won't have the js reader literal?

18:12 https://github.com/swannodette/om/blob/master/src/om/dom.cljs#L29

18:17 dnolen: eggnoggin: yes real dep, first release w/ js reader literal

18:18 eggnoggin: awesome, thanks

18:26 dnolen: last dynamic var purged from om, life cycle methods now take the pure component as second argument

18:42 augustl: what am I doing wrong? https://www.refheap.com/21738 According to the reflection, the method exists.

18:43 hiredman: augustl: check the flags

18:44 augustl: ah, it's a java type builder, and in java you can invoke static methods on instances directly. I guess you need to do something special to do that with Clojure?

18:44 that = invoke a static method on an instance

18:45 according to the docs, you can do this in Java. OptionBuilder.withArgName("n").withDescription("Whatever").create()

18:45 not sure how it actually manages to chain that to build it up when invoking static methods..

18:46 hiredman: well, withArgName most likely returns something that is not an OptionBuilder

18:46 so that .create() isn't a static method

18:46 augustl: withArgName returns an OptionBuilder instance

18:47 according to the javadoc, they're all static methods

18:47 http://commons.apache.org/proper/commons-cli/javadocs/api-release/org/apache/commons/cli/OptionBuilder.html

18:47 hiredman: Oh, weird

18:47 augustl: I agree :)

18:48 hiredman: that must be terribly thread unsafe

18:48 http://stackoverflow.com/questions/12466955/java-apache-cli-optionbuilder-not-working-as-builder-pattern

18:49 it just mutates all these static fields

18:49 http://www.docjar.com/html/api/org/apache/commons/cli/OptionBuilder.java.html

18:49 augustl: hmm, the best I can think of now is harblfjgjgjgjgjgjg

18:50 hiredman: friends don't let friends, etc

18:52 bitemyapp: I find that Java code is either not thread-safe, or the whole goddamn class is @synchronized and will choke your damn threads.

18:53 I blame JCIP.

18:55 and sometimes it'll end up not being thread-safe anyway because the authors didn't understand how synchronize works.

18:55 justin_smith: worst of both worlds

18:56 bitemyapp: if you deploy performance/latency sensitive Clojure apps, as often as not, it'll be the Java code you're scrutinizing for thread starvation.

18:56 technomancy: clojurebot: j.u.c.?

18:56 bitemyapp: Not the Clojure code. Unless you do something dumb.

18:56 clojurebot: Excuse me?

18:56 technomancy: aw come on clojuprebot

18:57 bitemyapp: technomancy: https://www.google.com/search?q=java.util.concurrent&oq=java.util.c&aqs=chrome.0.0l3j69i57.2490j0j1&sourceid=chrome&ie=UTF-8

18:57 technomancy: clojurebot: juc?

18:57 clojurebot: Titim gan éirí ort.

18:57 technomancy: argh

18:57 bitemyapp: technomancy: juc is half the reason people use Java.

18:57 technomancy: clojurebot: java.util.concurrent?

18:57 clojurebot: java.util.concurrent is "When I find myself in times of trouble / Prof. Doug Lea comes to me / Coding lines of wisdom / j.u.c."

18:57 technomancy: bots are hard

18:57 bitemyapp: ...

18:58 technomancy: I didn't keep you out too late Weds did I?

18:58 technomancy: bitemyapp: haha nah; got a good workout in while watching 70s doctor who

18:58 bitemyapp: cool.

18:59 technomancy: 80s doctor who, I guess

18:59 how time flies

19:07 Profpatsch: Can you import this dependency: http://search.maven.org/#search%7Cga%7C1%7Cmason ?

19:08 I’m getting Could not find artifact gnujaxp:gnujaxp:jar:1.0.0 in central (http://repo1.maven.org/maven2/)

19:08 mrcheeks: Profpatsch: is it there?

19:09 Profpatsch: Well, mason downloaded without problem in Java & Intellij/Eclipse

19:09 hyPiRion: Profpatsch: Did you add [edu.gmu.cs/mason "14.0"] into your dependency list?

19:09 Profpatsch: [edu.gmu.cs/mason "14.0"]

19:09 Yeah, exactly like that.

19:10 When I comment it out with #_, there is no error, so it has to be this one.

19:11 hiredman: Profpatsch: it sounds like they published a library to central with a dependency on something that is not in central, which is sad

19:12 Profpatsch: try adding replacing [edu.gmu.cs/mason "14.0"] with [edu.gmu.cs/mason "14.0" :exclusions [gnujaxp]]

19:12 mrcheeks: not a clojure, but can't you exclude that transitive dependency?

19:12 Profpatsch: what hiredman said ^^

19:12 hiredman: gnujaxp is most likely not something you should have an explicit dependency on anyway

19:13 mrcheeks: indeed

19:13 Profpatsch: And Intellij IDEA is too stupid to notice?

19:13 mrcheeks: not really about Intellij..

19:13 hiredman: the devs of edu.gmu.cs/mason must have put a dependnecy on it

19:13 hyPiRion: If the error persists, JFreeChart is the one with the transitive dependency. I would guess updating the JFreeChart dependency may solve the issue too

19:13 Profpatsch: Just imported it again, no errors, no warnings http://i.imgur.com/M2C72c8.jpg

19:14 hiredman: hyPiRion: weird

19:14 hyPiRion: Although the JFreeChart guys say it's not them putting up stuff on the Mave Central, so

19:14 dav: ALL - any reason why this doesn't work? (defmacro blah! [x] (swap! x conj "yo")) (def y (atom [])) (blah! y) ; getting ClassCastException clojure.lang.Symbol cannot be cast to clojure.lang.Atom clojure.core/swap!

19:14 hyPiRion: http://www.jfree.org/phpBB2/viewtopic.php?f=7&t=26653 <- from 2009

19:15 hiredman: oh, yeah, so a really old version of jfreechart

19:15 technomancy: dav: macros must return a list

19:15 justin_smith: dav: macros are about building the list you need

19:15 hiredman: technomancy: that is not true

19:15 technomancy: hiredman: it's a convenient lie

19:15 dav: technomancy: list meaning code?

19:15 justin_smith: that code can just be a function, but to make it a macro you need to build the list that becomes the code

19:15 dav: justin_smith: ok thx

19:16 justin_smith: (doc `)

19:16 hyPiRion: dav: the values given to a macro is not evaluated, it actually tries to swap! on the quoted symbol y

19:16 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

19:16 dav: fixed it thanks all

19:16 (defmacro blah! [x] `(swap! ~x conj "yo")) (def y (atom [])) (blah! y)

19:16 justin_smith: still doesn't need to be a macro, but sure

19:17 dav: yes I know I need it to be a macro for other reasons

19:17 thanks for the help

19:22 Profpatsch: hiredman: Thanks, it seems that worked

19:22 amalloy: i feel like if you're asking why that macro doesn't work, it's not 100% clear that you're right about whatever other thing needing to be a macro for other reasons

19:23 Profpatsch: hiredman: How would I refer to it? (:require [mason.foobar]) or (:require [edu.gmu.cs.mason.foobar])?

19:23 dav: amalloy: I need to traverse code and modify it in some other part of the macro..

19:24 hiredman: Profpatsch: the maven artifact name has little to do with what namespace / classes are there to use

19:24 bitemyapp: noprompt: you still have a shirt sitting on my office desk.

19:24 hiredman: Profpatsch: so check the docs or crack open the jar

19:25 hyPiRion: Profpatsch: additionally, if the dependency is a java dependency, you should use `import` instead of `require`

19:25 Profpatsch: hyPiRion: I can only require clojure namespaces, right?

19:25 hyPiRion: right

19:29 Profpatsch: hiredman: Hm, I don’t get it. Here’s the packages in mason: http://i.imm.io/1mdIZ.jpeg

19:30 hiredman: e.g. there is sim.engine.SimState

19:30 hiredman: What do I have to specify to import that Class?

19:32 hiredman: Profpatsch: have you read an introductory clojure material?

19:32 http://clojure.org/jvm_hosted

19:33 Profpatsch: Yes, but it didn’t seem to work. But I guess I made a mistake in evalling that namespace.

19:35 hiredman: Shouldn’t that be good: (:import sim.engine.SimState)

19:36 ClassNotFoundException sim.engine.SimState java.net.URLClassLoader$1.run (URLClassLoader.java:366)

19:36 hyPiRion: Profpatsch: example here https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/eval.clj#L12-L13

19:36 hiredman: Profpatsch: depends on how you are doing it

19:37 if that is in (ns … …) it should, if not, then you would get that exception

19:42 Profpatsch: UUUUUGGGGHHH. Simple solution: I had to restart my repl after doing `lein deps`.

19:42 hiredman: yep

19:42 Profpatsch: Something with the classpath I guess. Is there a way to do this without restarting?

19:43 amalloy: Profpatsch: no, although you don't really have to run lein deps

19:43 Profpatsch: I don’t?

19:43 llasram: Profpatsch: https://github.com/pallet/alembic ?

19:43 hyPiRion: Profpatsch: lein fetch dependencies and add them to the classpath automatically

19:44 bitemyapp: https://github.com/clojuredocs/guides/issues/153

19:44 amalloy: you really never need to run lein deps. it's like the Door Close button on elevators: just there to make you feel better

19:44 hyPiRion: It is possible to add deps through e.g. pomegranate, although you rarely add dependencies to a project

19:45 Profpatsch: Well, since I’m starting out and experimenting a lot, it is really discouraging if stuff doesn’t work and I have no idea why.

19:45 bitemyapp: hyPiRion: alembic is nicer than pomegranate for that.

19:45 I have a macro for injecting: "(require '[alembic.still :as alembic]) (alembic/load-project)"

19:52 noprompt: http://chimera.labs.oreilly.com/books/1230000000929/index.html

20:02 logic_prog: is there a nice way to use nrepl, clojure, and clojure.tools.reload in the folowing sitatution: the source code is stored on machine "laptop"; the clojure server is running on machine "server"; the source code is only stored on "laptop" and not on "server"

20:07 justin_smith: logic_prog: what I do in that case is put source on server, and edit from laptop via tramp

20:08 tramp works nice, if you can handle emacs

20:08 otherwise there is also sshfs

20:11 logic_prog: justing_smith: yes, I'm using emacs + tramp, however I want to check my code into git

20:11 justin_smith: and I'm not sure I want to put git credentials on this particular server

20:11 justin_smith: you can use git in password mode

20:13 also, this is weird, but you could rsync from remote, then check it into git locally

20:13 no reason that would not work, though it is an odd workflow

20:14 or do it the other way, pushing the code to server with rsync

20:14 but I don't see how running code not on the machine would work

20:15 logic_prog: nrepl-send buffer

20:15 allows me to send a buffer to the nrepl server

20:15 justin_smith: for the entire codebase?

20:15 I guess

20:15 logic_prog: so if the nrepl server is running on a remote machine, it's fine

20:16 coventry: You could also have credential-free git on the server, then when you want to publish git clone that on the laptop, and git push from there.

20:16 justin_smith: logic_prog: the problem there is the require statments, you would need to reverse engineer the deps

20:17 logic_prog: justin_smith: you're right

20:17 I'm being an idiot, rever sengineering the deps would be messy

20:17 I'll just send code to the server and live code there.

20:17 you know what else would be badass? reverse ssh

20:17 err. reverse sshfs

20:17 if I can publish a local directory (on "laptop") to a directory (on "server") over ssh

20:18 justin_smith: you could also have the repo in a mounted encrypted image on remote

20:18 logic_prog: but it's 'rever sshfs" since the ssh server is running on "server" and the ssh client is on "laptop"

20:18 justin_smith: mount -o loop etc.

20:18 logic_prog: justin_smith: mounted encrypted image on remote? how does that work?

20:19 justin_smith: http://www.techrepublic.com/blog/linux-and-open-source/create-encrypted-loopback-filesystems-on-linux/

20:19 a random file can act as a disk image, which is encrypted

20:19 and you can mount it wherever, use it as if it were an external device, unmount when done

20:19 if your concern is about what you store on the server

20:20 by random file I mean a large enough file to emulate all the storage for a block device, it is not file by file encryption

20:44 coventry: In the "reverse sshfs" category, you could make a local webdav server, forward that over ssh to the server and mount it there. There might even be a way to tell it not to publish .git directories.

20:44 Anyway, not clojure anymore.

22:02 sritchie: bitemyapp: so, QQ -

22:03 bitemyapp: about logging and monitoring zen :)

22:10 devn: The wu wei.

22:32 Osum: how do I use clojure.contrib.math in my project ?

22:32 adding [org.clojure/clojure.contrib.math "1.1"] to project.clj results in a bunch of errors

22:37 guns: Osum: http://dev.clojure.org/display/doc/Clojure+Contrib+Libraries

22:37 -> https://github.com/clojure/math.numeric-tower

23:32 cljr: wow, once you get used to threading swquences through multiple functions using 0> it gets hard to use any other languages...sounds stupid, but it is so simple but powerful

23:32 0> i mean

23:32 -> ....

23:34 ivan: http://stackoverflow.com/questions/4961017/clojure-style-function-threading-in-python

23:34 Raynes: cljr: Doesn't sound stupid at all. I've wanted it in both Go and Python on several occasions.

23:34 what

23:34 ivan: It's like you read my mind.

23:35 cljr: it is just refreshing to get away from dealing with objects and really just getting to something akin to pipes

23:35 ivan: you'll be f1(f2(f3'ing for a long time if your Python code is being read by anyone else

23:35 ToBeReplaced: ivan: not quite what you want but hy does this

23:35 cljr: going from one value to another, each step just applying a different function

23:36 ivan: ToBeReplaced: yeah, saw that in hy a while ago

23:37 https://github.com/hylang/hy/blob/master/hy/core/macros.hy#L82

23:42 cljr: Ok, im a bit stuck here

23:43 ,0xff

23:43 clojurebot: 255

23:43 cljr: ,0x00

23:43 clojurebot: 0

23:43 cljr: ,(char 0x00)

23:43 clojurebot: \

23:43 cljr: ,(char 0xff)

23:43 clojurebot: \�

23:44 cljr: ,(apply str (repeat 10 (char 0xff)))

23:44 clojurebot: "����������"

23:44 cljr: ,(apply str (repeat 10 (char 0x00)))

23:44 clojurebot: "

23:47 ivan: poor clojurebot can't send a NULL over IRC

23:47 clojurebot: Huh?

23:53 cljr: hmm, does anyone know how i can go from "127" to 0x7f

23:54 i though i had it with (Integer/parseInt "127 16), but nope

23:54 amalloy: cljr: to 0x7f the byte value, or "0x7f" the string?

23:54 cljr: byte value

23:55 ivan: ,(= 0x7f (Integer/parseInt "127"))

23:55 amalloy: then...that's just 127

23:55 clojurebot: true

23:55 cljr: jesus

23:55 amalloy: 0x7f is not different in any way

23:55 cljr: im not sure why i was doing what i was doing

23:56 amalloy: thanks for your work on the aleph docs, btw

23:56 guns: ,2r01111111

23:56 clojurebot: 127

23:56 amalloy: oh, you're welcome. i didn't think i had actually done very much

23:56 just a bit on the query language thingy

23:57 cljr: Ok, you are just the most recent edit i guess, your name is at the bottom of quite a few of the pages

Logging service provided by n01se.net