#clojure log - Aug 23 2013

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

0:47 gdev: `cbp, couldn't reproduce it, closing the trouble ticket =/

0:51 babu`: dakrone, Any idea when you will be able to implement proxy auth for clj-http.client? I looked around and found http.async.client and converted my code to use that. But ^C^K with clj-http is instantaneous but with the async it takes several seconds.

0:52 dakrone: babu`: I will not be able to get to it tonight, but hopefully tomorrow or sometime this weekend?

0:52 I don't think it will be difficult, just requires reading docs to find out how to do it

0:55 * dakrone takes a look at it right now

0:58 kendallbuchanan: Quick question: I'm making a leiningen library, in which I'd like to bind the contents of a file in "resources" to a local var, and then access that var's value from a project depending on the library.

0:58 Basically, I want to bind the contents of a file to a var at compilation, not runtime. Any thoughts?

1:01 gdev: put the slurp in clojure file that has to be AOTd ?

1:03 kendallbuchanan: yeah

1:03 dakrone: babu`: actually, this looks pretty easy, so I'm hoping to have it done by tomorrow, the hardest part will be testing it

1:04 kendallbuchanan: I'd like a macro like "defcontents", or something: (defcontents my-file "./file.txt"), and my-file would reference the contents of "file.txt"

1:05 or, is there a way to expose the "resources" directory of the library to the hosting program?

1:05 that'd be another solution, I suppose

1:06 gdev: and this library has to have the contents of it at compile time to do its job?

1:07 kendallbuchanan: the program needs access to the contents of a file contained in the library's "resources" path

1:07 gdev: still, I think defcontents could be a normal function in a namespace that gets AOT compiled

1:07 kendallbuchanan: I'm unfamiliar with AOT… any constructs I should look up?

1:08 gdev: stands for ahead of time compile

1:09 in your project.clj you can specify what needs to be compiled

1:10 kendallbuchanan: ah, it's a compilation setting, then?

1:11 Okay, I think I understand now… thanks!!!

1:12 gdev: no problem =) glad i could help

1:14 dissipate: when is the entire java standard library going to be ported to pure clojure?

1:15 gdev: August 13 2016

1:15 mischov: And not a minute earlier.

1:16 dissipate: gdev, sweet

1:16 callen: mischov: nor later. A wizard's grimoire arrives precisely when it means to.

1:16 dissipate: mischov, if the entire java standard library was ported to clojure, no more calls to java (excepting for 3rd party libs)

1:16 think of how great that would be

1:17 mischov: It seems like it might be a tad bit slower.

1:17 callen: every new person says that.

1:17 then they learn not to care and move on.

1:18 dissipate: callen, we shouldn't care?

1:19 callen: dissipate: it doesn't really affect the day to day experience of writing Clojure.

1:19 babu`: dakrone, ok thanks, I can pull the updated version when available and run my program and see if it works.

1:19 dissipate: callen, or are you saying a new standard library should be built in pure clojure and completely discard the java standard library?

1:20 gdev: clojure in clojure is just a fantasy dreamed up by people who were just wanting to do web programming anyway

1:20 dissipate: callen, but every call to a java library function is a call that causes side effects. isn't the goal to get rid of side effects?

1:21 callen: the goal is to write nice software in a sane way.

1:21 not to engage in a religious crusade against flipping bits.

1:21 bits are gonna get flipped, one way or another.

1:22 dissipate: callen, you have never been burned by side effects in the java libs?

1:24 callen: dissipate: I roast people that ask too many questions over a spit.

1:24 * callen grins like the Sphinx

1:24 dissipate: how rude

1:25 mischov: bear with him..

1:25 callen: dissipate: but more seriously, as somebody who used to do CL before, the degree to which I am impacted by side effects in libraries, Java or otherwise, is much less substantial.

1:25 dissipate: I would advise, "chill, marinate in the parens for awhile, and enjoy" before launching any crusades.

1:25 gdev: C-x M-c M-butterfly is how I flip bits

1:26 callen: gdev: like any civilized person.

1:26 dissipate: you'll find something much more important to dislike than that Clojure is hosted in the JVM and uses Java libraries in some cases.

1:28 dissipate: callen, no, i'm glad the java libs are available. but i figured it would be good if clojure could escape the java ecosystem entirely some day.

1:28 callen: dissipate: a Clojure-on-the-LLVM project some day could be cool. I'm not really sweating it. 99% of what I do is server-side.

1:28 well, server-side or in a web browser.

1:28 dissipate: callen, actually, right now i dislike the fact that clojure isn't a replacement for scripting languages

1:29 callen: it's served fine for me there.

1:29 mischov: Clojurescript+node?

1:29 callen: mischov: some people do that. Prismatic used to do that (inadvisedly) on the backend, lol.

1:30 they use the standard backend tooling now.

1:30 mischov: dissipate: There are a number of clojure projects targeting other ecosystems. Take a look around for clojure in python, c, etc, or even clojure in clojure

1:32 dissipate: mischov, have you tried clojure on .NET?

1:33 mischov: Can't say I have.

1:52 gdev: i've yet to meet anyone who uses clojure on the CLR

1:53 i was tempted to try it out just to say i did it, but then I remembered I had a dentist appointment

2:21 [Neurotic]: Newb clojure q - looking at different testing libs. Anyone got one they love way more than another? Looking at Midje it seems quite nice. Opinions?

2:22 wink: seemed nice to me as well :)

2:23 [Neurotic]: ringingf endorsement ;)

2:28 callen: [Neurotic]: I prefer clojure.test

2:30 [Neurotic]: how come?

2:30 the repl support in midje seemed to sell me

2:44 s4muel: Oh, this chat again.

2:45 [Neurotic]: heh yeah

2:45 sorry ;)

2:47 s4muel: No, it's quite alright. I am still on the 'new' side of Clojure and expectations works for me so far.

2:50 cgag: anyone seen "peerUri is undefined" when trying to use the clojurescript browser repl?

2:50 * [Neurotic] googles 'expectations'

2:51 [Neurotic]: ah nice and minimal

3:02 futile: yo dawg

3:02 i herd u like programming languages so i put a programming language in your programming language so you can program while you program

3:02 [Neurotic]: yeah expectations is pretty sweet

3:25 dissipate: what is the difference between a 'symbol' and a 'special form'?

3:25 TEttinger: ,(class :whatamI)

3:25 clojurebot: clojure.lang.Keyword

3:26 TEttinger: dissipate, good question

3:26 I kinda would think a symbol is something like the names in let bindings, or the name after def or defn. I'm probably wrong though.

3:27 amalloy: dissipate: they're pretty big difference: they're not at all alike. a symbol is basically a name, often used to refer to an object of some kind, or to represent the program's source code

3:28 whereas a special form is like a primitive operator of the language: "let" and "fn" are two examples, as they're "function-like things" that are actually implemented as compiler specials

3:29 we can compare to java, by a somewhat questionable analogy: in the expression "int x = 5 + 2;", int and x are a little like symbols, and = and + are like special forms

3:31 dissipate: amalloy, so they are clojure's 'built ins'?

3:32 cgag: yep

3:32 dissipate: i'm looking here: http://clojure.org/special_forms

3:32 amalloy: yes. there are a smallish number of them, but of course it's a little nebulous what counts

3:32 dissipate: doesn't seem to be too many

3:33 amalloy: dissipate: that's typical of a lisp

3:33 dissipate: and it has been rigorously proven that these make clojure turing complete? i'm assuming so. :D

3:33 amalloy: dissipate: it's been rigorously proven that just (fn ...) makes a language turing complete

3:34 cgag: that's the beauty of it, so many things you need primitives for in other languages you can do as macros in lisp

3:34 dissipate: cgag, i haven't gotten to macros yet. how do the special forms relate to macros?

3:35 cgag: in most other languages, something like "or" is built into the language

3:35 amalloy: dissipate: macros act a lot like special forms, but are written by you instead of rich

3:36 cgag: a = b || c

3:36 Raynes: Lisp is fanntastic.

3:36 amalloy: you can think of them as a little like compiler extensions, except instead of hideously hairy they are pretty simple

3:36 cgag: you can't write || yourself because anything you write yourself evaluates it's arguments right away, and || is supposed to short circuit

3:36 dissipate: cgag, yes, and?

3:37 cgag: with macros, you can control when arguments get evaluated, so you can just write or as a macro on top of if

3:38 dissipate: hmm, i don't see '||' in the special forms list

3:38 amalloy: dissipate: in clojure, (and true (/ 10 0)) doesn't break (because and short-circuits as you'd expect), but it doesn't have to be a special form like it would in, say, ruby

3:38 dissipate: is it a standard macro?

3:38 cgag: it's "or" i nclojure

3:39 it's not a special form, it's just a macro in the standard library

3:39 amalloy: instead, or is written in clojure as (defmacro or [x y] `(if-let [x# ~x] x# ~y))

3:39 you don't need to worry about *how* that works, the key point is just that you can write it inside the language instead of as part of the compiler

3:39 (and of course that's a simplified version of or that only accepts two args; the real one takes arbitrarily many)

3:40 dissipate: that's pretty wild

3:40 this is a wild language

3:41 amalloy: i just noticed i accidentally switched from and to or partway through. hope the illustration still worked

3:42 dissipate: amalloy, how much contention is there over the selection of the special forms? certainly not everyone agrees on what those should be?

3:42 amalloy: wellllll, i'm not sure what you mean. nobody gets to contend, because rich already picked them to build the language from

3:43 dissipate: amalloy, right, but there are many other flavors of lisp, no?

3:44 amalloy: ah. yes, that's true, and they don't all have identical special forms. but there's a lot in common

3:44 dissipate: it's interesting that there are so few

3:46 TEttinger: dissipate, there's a famous paper that kinda lays out the basics needed to implement lisp. can't remember the name.

3:48 cgag: anyone seen "peerUri is undefined" when trying to use the clojurescript browser repl?

3:49 TEttinger: cgag, I'm afraid I don't yet use clojurescript.

3:50 amalloy: TEttinger: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.111.8833&rep=rep1&type=pdf ?

3:50 TEttinger: dissipate, http://www-formal.stanford.edu/jmc/recursive.html this paper. it's a little complex in parts, but it's amazing that the language can be defined with such a small set of forms

3:52 amalloy, did we link to the same paper?

3:52 amalloy: i won by two seconds

3:52 i was trying to find the paper you mentioned, so it's not surprising it's the same

3:52 TEttinger: heh

3:53 I was wondering if the PDF is better-formatted than the HTML version

3:53 cgag: 'night people, welcome aboard dissipate

4:18 andyfingerhut: I am trying to understand how core.clj in the Clojure source code can require clojure.java.io, which seems to be compiled later in the build. Is it difficult to explain how that works?

4:19 kral: any company here that is looking for a wannabe clojure programmer? :)

4:23 amalloy: andyfingerhut: i don't know what you mean by "later in the build". the compiler evals 90% of clojure.core, recurses into clojure.java.io at the request of clojure.core, and then goes back to clojure.core

4:24 ie, compiling a file isn't an atomic operation, and it can be interrupted to go compile another one partway through

4:25 andyfingerhut: amalloy: Don't be surprised if I am missing something very basic here. If you build Clojure source code using 'ant', for example, the build.xml file invokes the compiler on a sequence of namespaces that starts with clojure.core, and much later in the list it explicitly calls out clojure.java.io as well. Is that clojure.java.io perhaps unnecessary?

4:26 amalloy: welllllll, i'm not so sure about that part

4:27 andyfingerhut: I guess I can try an experiment to see.

4:27 amalloy: it may be the case that Compile/main needs to be passed a list of all namespaces that will be turned into classfiles

4:28 with other namespaces that are required being only "temporarily" compiled

4:29 but i think it's probably the case that you could omit some of those args and they would still be compiled

4:31 andyfingerhut: Deleting the occurrence of clojure.java.io from that list of namespaces in build.xml causes the ant build to fail when it reaches clojure.java.shell (or near there), probably when it tries to do a :use of clojure.java.io.

4:36 amalloy: Do you have a technical meaning of "only temporarily compiled" in mind?

4:37 amalloy: e.g. a compilation that does not cause .class files to be written to disk, perhaps?

4:37 amalloy: andyfingerhut: i meant in the way that compilation happens when you're not doing AOT: just to classes defined in memory via the DynamicClassLoader

4:44 hiredman: that seems unlikely

4:45 andyfingerhut: hiredman: Was that in reference to something I said?

4:50 hiredman: to amalloy's explanation, because non-transitive aot is something people have wanted for a long time

4:51 but I guess that isn't really non-transitive aot because it is still broken

4:52 amalloy: yeah, i think it's pretty clear that's not what's going on, just from andyfingerhut's one experiment. if it were, the compiler would work as usual on other files but not output a .class for clojure.java.io

4:57 turbopape: hi everybody,

4:57 hiredman: I suspect it is a classloader issue, the compiler is generating classes using a dynamic classloader, but once compilation finishes the classloader is popped before the next namespace is compiled

4:58 turbopape: where is the link for lighttable 0.5? I only find the linkg for .4.11,

4:58 and whenever I hit update It tells me that I am on the last version ...

4:59 Ah, I actually needed to refresh my browser...

4:59 never mind ...

5:29 NeedMoreDesu: I've written fast version of lazy-shuffle on vectors. http://www.everfall.com/paste/id.php?slhnb97yha7q

5:30 Sad story is, it's not that lazy if you need to get vector first lol.

5:38 Wow thats odd. Why my (vec (lazy-shuffle ...)) works 8 times slower that (vec (list (lazy-shuffle ...))) ?

5:38 TEttinger: NeedMoreDesu, that will blow the stack.

5:39 (on large collections)

5:39 you are recursing without using an explicit recur, and clojure will just go on creating call frames until it blows the stack

5:40 NeedMoreDesu: Im not recursing, it's lazy collections.

5:40 It wont blow stack.

5:40 TEttinger: (defn lazy-shuffle... (lazy-shuffle

5:40 NeedMoreDesu: (lazy-seq (lazy-shuffle ..))

5:41 that makes difference

5:41 TEttinger: ok, didn't see that part

5:41 I've always been nervous about recursion on JVM

5:41 NeedMoreDesu: I found out why (vec (list ..)) is faster lol

5:42 TEttinger: I'm curious. pop?

5:43 NeedMoreDesu: http://clojuredocs.org/clojure_core/clojure.core/subvec

5:43 subvec is O(1)

5:43 So I think pop is O(1) too

5:44 persistent vectors is just awesome thing.

5:47 andyfingerhut: pop on vectors is O(log n), but such a nice fast O(log n) that only a theorist should quibble between that and O(1).

5:47 NeedMoreDesu: log32, afaik

5:47 andyfingerhut: pop on vectors doesn't use the same implementation that subvec does.

5:48 NeedMoreDesu: Is it faster?

5:48 hyPiRion: than what?

5:48 NeedMoreDesu: than subvec.

5:49 andyfingerhut: The O(log n) pop on vectors is asymptotically slower than O(1) subvec for large enough vectors. However, subvectors are not quite first-class citizens in the Clojure implementation today -- there are funky limitations on what you can do with subvectors

5:49 NeedMoreDesu: Oh.

5:50 So it's faster to use subvectors in this case?

5:50 andyfingerhut: Several JIRA tickets open for the limitations on subvecs, if you are curious.

5:51 There could be constant factors hidden in the O(1) vs. O(log n) that still make pop faster than subvec. For that you'd have to do some benchmarking to find out.

5:54 NeedMoreDesu: Results looks pretty much same.

5:55 andyfingerhut: That doesn't surprise me. I suspect they both usually allocate about the same amount of memory, which probably dominates the run time. Not much computation needed for those operations.

5:56 TEttinger: how about ##(sort-by #(rand-int -1000 1000) [:a :bb :ccc :dddd])

5:56 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox80477$eval85003$fn

5:56 TEttinger: how about ##(sort-by (fn [] (rand-int -1000 1000)) [:a :bb :ccc :dddd])

5:56 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox80477$eval85014$fn

5:56 hyPiRion: heh.

5:56 ,(sort-by (fn [_] (rand-int -1000 1000)) [:a :bb :ccc :dddd]) ; it is

5:56 NeedMoreDesu: Sometimes pop is faster, sometimes subvec. Well, I guess it's ok to use pop.

5:56 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core$rand-int>

5:57 andyfingerhut: I'd recommend going for pop, to avoid the corner cases you might otherwise hit with subvectors.

5:57 gvickers: Howcome ,,(= (keys {'foo "baz" 'bar "baz"}) ['bar 'baz])

5:57 is false

5:57 NeedMoreDesu: TEttinger but it's not lazy.

5:57 andyfingerhut: Not so much bug corner cases, but feature-not-yet-implemented-in-Clojure corner cases.

5:58 gvickers: meant for the vector to be ['bar 'foo]

6:00 NeedMoreDesu: gvickers: it's not really good idea to trust in order of keys in hash-map

6:01 andyfingerhut: gvickers: That and in your example the keys are 'foo and 'bar, not 'bar and 'baz, but yeah, what NeedMoreDesu said, unless you use a sorted-map, or sort the result of keys.

6:03 NeedMoreDesu: (keys (sorted-map 'foo "baz" 'bar "baz")) => (bar foo)

6:03 Still not ordered in that way it is written, but at least its the same each time it's launched.

6:04 gvickers: NeedMoreDesu: thanks, I think im going to try every? contains? {.... instead. forgot hashmaps are not sorted :p

6:11 TEttinger: ibdknox, it isn't in the announcement, but were themes removed from 0.5 of light table?

6:14 agumonkey: hello

6:14 i'm having issues with ordering in sets

6:14 (map (fn [e] e) #{:a :b :c :d})

6:15 => (:a :c :b :d)

6:15 TEttinger: sets are unordered.

6:15 you want a sorted-set

6:15 agumonkey: so map f set will always be potentially 'random' ?

6:15 TEttinger: ,(map (fn [e] e) (sorted-set :a :b :c :d))

6:16 clojurebot: (:a :b :c :d)

6:16 agumonkey: TEttinger: aight thanks

6:16 TEttinger: also, sorted-set-by

6:16 that one is handy for different sort orders

6:16 yours is alphabetical now

6:16 andyfingerhut: Or use regular sets, but before doing things like map on them, sort the elements with the function sort.

6:16 TEttinger: ,(map (fn [e] e) (sorted-set :a :aa :c :d))

6:16 clojurebot: (:a :aa :c :d)

6:17 TEttinger: andyfingerhut, that too

6:18 agumonkey: is there a syntax literal that I can use with `into` ?

6:18 or is (apply sorted-set existing-unordered-set) idiomatic enough (if at all) ?

6:19 TEttinger: ,(into sorted-set (range 2 5))

6:19 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.core$sorted_set cannot be cast to clojure.lang.IPersistentCollection>

6:19 andyfingerhut: There is no literal syntax in Clojure for sorted sets or maps.

6:19 TEttinger: ,(into (sorted-set) (range 2 5))

6:19 clojurebot: #{2 3 4}

6:19 hyPiRion: ^

6:19 TEttinger: that's as close as it gets

6:20 agumonkey: close enough

6:20 hyPiRion: also, in case you need

6:20 TEttinger: but regular sets sorted as needed also work

6:20 hyPiRion: ,(into (sorted-set-by >) #{2 3 4 5})

6:20 clojurebot: #{5 4 3 2}

6:20 agumonkey: thanks

6:30 ciphergoth: would you use clojure.async in a live commercial application?

6:31 ro_st: probably :-) be nice for it to go out of SNAPSHOT first

6:31 hyPiRion: no, as there is still no official version out.

6:31 ciphergoth: *nods*

6:34 hyPiRion: Apart from that, I'd be all over it I assume

6:35 ciphergoth: it is very impressive!

6:35 making it play nicely with aleph could be annoying

7:04 muhoo: why would you use both in a single app?

7:33 hmm, how long does memoize keep stuff around?

7:34 mpenet: forever

7:34 core.memoize has caching strategies

7:34 hyPiRion: until you discard the function

7:43 muhoo: ah i see, i can set it

7:44 getting tired. now i'm trying to figure out how to nested destructure stuff, i.e.

7:45 i have a ring req i want to take one in and get params out, like (defn foo [{:keys [{:keys [bar baz] :as params} headers] :as req}] foo)

7:46 so basically pull out the params and headers, but also pull out the individual params as their names

9:12 [Neurotic]: seancorfield: you awake?

9:30 jamii: I remember reading something about capturing repl interactions and reusing them as regressions tests but I can't for the life of me find it again. Does anyone know what I'm talking about?

9:33 Aha - https://github.com/cgrand/replay

9:45 muhoo: [Neurotic]: i doubt it. it's 6:30am here

9:45 [Neurotic]: it was always possible ;)

10:02 edw: ,(parition 2 '(1 2 3 4 5))

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

10:02 edw: ,(partition 2 '(1 2 3 4 5))

10:02 clojurebot: ((1 2) (3 4))

10:02 edw: Does that result concern anyone? It doesn't seem to match the docs.

10:04 OK, it does match the docs.

10:04 Or the examples…

10:05 jkkramer: ,(partition-all 2 '(1 2 3 4 5))

10:05 clojurebot: ((1 2) (3 4) (5))

10:05 vijaykiran: edw: what you are looking for is partition-all

10:05 ah - ask jkkramer said

10:06 edw: Ah, thank you. I was doing (parition n n nil coll), which is a bit of a PITA.

10:24 jtoy: &(doseq [x [1 2] i (take 2 (range))] (println i))

10:24 lazybot: ⇒ 0 1 0 1 nil

10:24 jtoy: why does thta print 0 1 0 1 and not just 0 1 ?

10:25 ToxicFrog: ...how does that resolve x and i?

10:25 &[x i]

10:25 lazybot: java.lang.RuntimeException: Unable to resolve symbol: x in this context

10:26 ToxicFrog: Oh, doseq takes a binding-form.

10:26 I thought it was another dorun variant.

10:27 jtoy: because it iterates over the product of both lists.

10:27 &(doseq [x [1 2] y [3 4]] (println [x y]))

10:27 lazybot: ⇒ [1 3] [1 4] [2 3] [2 4] nil

10:27 jtoy: i just want to have an i for each item in x

10:27 how would i do that with doseq?

10:28 agumonkey: maybe zip

10:28 ToxicFrog: So, first it iterates over the first value of x (1) and all values of i, then over the second value of x and all values of i - so each value of i shows up twice.

10:28 jtoy: what do you mean by "an i for each item in x"?

10:28 jtoy: so if i have x [ 34 78 99] i want to have an i that prints out 0 1 2

10:28 ToxicFrog: Er

10:29 jtoy: just the step I am at in the collection

10:29 agumonkey: jtoy: always 0 1 ... ? or any value ?

10:29 ToxicFrog: so (take (count x) (range)) then?

10:29 jtoy: yes, which is what I have earlier, but i dont want the product

10:29 cmajor7: jtoy: (map-indexed (fn [i xi] ...) [34 78 99])

10:29 ToxicFrog: &(let [x [5 8 12 4]] (take (count x) (range)))

10:29 lazybot: ⇒ (0 1 2 3)

10:29 agumonkey: cmajor7: +1

10:30 ToxicFrog: jtoy: "don't want the product"?

10:32 jtoy: ToxicFrog: you said earlier it itterates over the product of both?

10:32 tbaldridge: dnolen: ping

10:32 jtoy: i want to iterate through random collection with doseq but also know the position i am at

10:33 cmajor7: jtoy: why doseq? why not map-indexed?

10:33 jtoy: that does exactly that

10:33 jtoy: cmajor7: I am writing out a file and i need to put the line number

10:33 (doseq [line lines] (write lines and line number))

10:33 atyz: This might be silly - is there an easy way to return a realized map of a datomic entity with sub-entities (I have isComponent true). I'm in the midst of writing a function to realise them all and it feels like there should be an easier way

10:34 jtoy: cmajor7: is there a better way?

10:34 cmajor7: jtoy: (map-indexed (fn [n line] (write (str "n:" line))) lines)

10:34 ToxicFrog: jtoy: doseq does, yes. The answer is not to use doseq.

10:34 scgilardi: atyz: does "touch" get close?

10:34 cmajor7: (map-indexed (fn [n line] (write (str n ":" line))) lines)

10:35 jtoy: cmajor7: ok, I see, thanks

10:35 atyz: scgilardi: touch only realises the primary entity - not it's children

10:38 scgilardi: I think the intent is for it to recursively realize isComponent children. (from: https://groups.google.com/forum/#!topic/datomic/wsyvv8BCQw0 ) not sure why it wouldn't be in your case.

10:41 cmajor7: atyz: are your "refs" are "isComponent" or something else?

10:41 atyz: scgilardi: the problem is that it realises them as a DatomicEntityMap so if I want to do any manipulation to any of the subcomponents it won't allow me to

10:42 cmajor7: isComponent true on all in question here

10:42 cmajor7: usually [entity has "refs"], those "refs" should be "isComponent" to realize on (touch entity)

10:42 atyz: cmajor7: basically I don't want to have to use my datomic entity names in my application code

10:43 cmajor7: atyz: why names?

10:43 atyz: you only need id(s) to -> touch ..

10:44 i.e.

10:44 (defn entity [id]

10:44 (d/entity (db-now) id))

10:44 (defn touch-id [id]

10:44 (d/touch (entity id)))

10:45 this of course has a "db-now" hardcoded.. if you need to touch with different db values, pass those as well..

10:45 atyz: Oh sorry - miscommunication - the touching part works fine if you're trying to just print the data or access it. however I need to turn {:source/name "something" :sub {:sub/meh "somethingelse}} into {:name "something" :sub {:meh "somethingelse"}}

10:46 lycrgs678: I am new to clojure. What's the most common framework used for webapps? Noir?

10:46 atyz: ** :source/sub

10:46 cmajor7: lycrgs678: compojure

10:46 lycrgs678: thank you cmajor7

10:46 cmajor7: atyz: you mean convert to "no datomic" namespace map?

10:47 atyz: cmajor7: yes

10:48 cmajor7: atyz: yea.. looking at my code from some time ago, I have a function that does that :)

10:48 atyz: cmajor7: i would love it if you would let me look at it? :)

10:48 cmajor7: atyz: but it is a bit logic specific

10:49 atyz: trying to see if it can be cleaned up to show you. it is for a customer.. so not quite open source..

10:50 atyz: cmajor7: ahh - it would be appreciated if you could

10:50 are you currently using your fully qualified datomic names in your code?

10:51 cmajor7: atyz: you mean the attribute names as they are in the schema?

10:51 atyz: cmajor7: yes, sorry

10:52 cmajor7: atyz: yes, I do, but I do the conversion, since I pack the data in protobufs before sending it elsewhere

10:52 jballanc: anyone have advice on using npm/bower libraries with Clojurescript?

10:53 cmajor7: atyz: looking at the function, I wish I would write it now as I know a Clojure and Datomic better, otherwise I don't like my own code from 7 months ago :) it'd be easier if you give me a result of the query you want converted to a "no namespaced" map

10:56 dnolen: tbaldridge: pong

10:56 tbaldridge: dnolen: in CLJS if I have a predicate (active? foo) is negating with not going to slow things down a ton? (not (active? foo))

10:57 or can I type hint that with ^boolean to speed things up?

10:57 dnolen: tbaldridge: you don't need to negate, you can just type hint ^boolean

10:58 tbaldridge: the only time you might negate is you're checking for nil

10:58 tbaldridge: (if x ...) where x might be nil will emit a truth call. so (if-not (nil? x) ...) is better

10:58 tbaldridge: and (not (nil? x)) should be hinted?

10:59 well here's the actual code: (and (not (nil? buf)) (pos? (count buf)))

10:59 dnolen: tbaldridge: oh you never need to hind cljs.core predicates they already are

10:59 tbaldridge: protocols don't support type hints in Clojure is the problem with protocol methods that return boolean values

10:59 tbaldridge: yes there's not way around that - but no need for type hints there.

11:00 tbaldridge: ok, so I should be good then. I'm re-writing core.async CLJS channels today, so far I've probably cut 25% of the code. So this is looking good.

11:01 dnolen: tbaldridge: awesome! you can always look at the simple output to know if you're doing your boolean stuff correctly

11:01 tbaldridge: if it's right you won't get if((function() { ... }()) { ... }

11:01 tbaldridge: dnolen: kk

11:01 dnolen: tbaldridge: or if(cljs.core.truth_(x)) { ... }

11:08 wakeup: hi all

11:09 glosoli: hey

11:09 wakeup: I apparently have a LazySeq, and another seq, and I want the

11:09 elements in seq that do not appear in LazySeq?

11:10 clojure complains lazyseq doesn't support contains?

11:10 how do I convert my lazyseq to a seq I can call contains on?

11:11 arrdem: wakeup: do you have bounds on the lazyseq's length?

11:11 wakeup: arrdem: its the result of map and concat so I'd say yes, its not infinite

11:12 arrdem: wakeup: I mean you can just (apply list <expression>)

11:13 wakeup: but I contend that you should be able to perform a constant space difference operation by sequentially resolving the items of the lazy seq and testing them for membership in the hard seq.

11:13 wakeup: Ah

11:13 I uset set and difference and it works

11:17 tgoossens: how do i get the output of pprint written into a file?

11:17 arrdem: tgoossens: you can bind *out* to a file object for one..

11:18 tgoossens: jmm

11:18 *hmm

11:19 arrdem: so (binding [*out* (File. "~/my/path.dump")] (pprint <expr>))

11:19 ,*out*

11:19 clojurebot: #<StringWriter >

11:19 arrdem: yep. that's the var.

11:19 wolfes: Is there a way to get every namespace in a lein project to (require '[clojure.repl/pprint :as pp])

11:20 i figured out how to do it on init for the first namespace

11:20 but it doesnt seem to carry over for other ns

11:20 arrdem: wolfes: no and there shouldn't be one.

11:20 wolfes: you _can_ tell lein to automatically (require) some namespace when kicking off a repl

11:21 wolfes: repl-options init :)

11:21 tgoossens: iit doesn't write anything to the file though

11:21 (binding [*out* (File. "~/my/path.dump")] (pprint <expr>))

11:21 oops

11:22 (binding [*out* (java.io.FileWriter. (java.io.File. "graph.txt"))] (pprint "hello"))

11:22 arrdem: tgoossens: (-> *out (.flush) (.close))?

11:23 tgoossens: my god

11:26 jkkramer: (with-open [f (clojure.java.io/writer "graph.txt")] (binding [*out* f] (pprint "hello")))

11:26 …i think. that's untested

11:26 tgoossens: it works though...

11:26 arrdem: jkkramer: so what you're really saying is that like me you're spitting sexprs from the hip with not enough coffee

11:27 ,0xC0FFEE

11:27 clojurebot: 12648430

11:27 llasram: ,0xDECAFBAD

11:27 clojurebot: 3737844653

11:27 jkkramer: yeah, too bad irc doesn't have paredit

11:27 arrdem: I kinda want to write an erc script that supports diff messages...

11:28 so I can retroactively ammend what I've previously said :P

11:35 hyPiRion: ,36rClojurebot

11:35 clojurebot: 1279886746883501

11:36 arrdem: hyPiRion: why 36? I'd think that 26 or 52 would be in order.

11:37 hyPiRion: ,26rClojurebot

11:37 clojurebot: #<NumberFormatException java.lang.NumberFormatException: For input string: "urebot">

11:37 hyPiRion: ,52rClojurebot

11:37 clojurebot: #<NumberFormatException java.lang.NumberFormatException: Radix out of range>

11:37 hyPiRion: that's why

11:37 arrdem: I see the error, I don't follow the why.

11:38 cmajor7: atyz: (defn map-walk [m] (if (map? m) (reduce (fn[a [k v]] (assoc a (-> k name keyword) (map-walk v))) {} m) m))

11:38 make sure there are no duplicates in names of different namespaces on the same level, since it is going to ignore all but last

11:38 {:some/one 21 :every/one 42} => {:one 42}

11:38 atyz: cmajor7 thank you!

11:39 hyPiRion: well, base 36 is the highest supported with the r-format. 26 isn't enough because we start off with 0123456789, then the letters

11:39 TimMc: arrdem: 36 is the max radix for Java parseint.

11:39 You get some prefix of 0-9a-z.

11:39 hyPiRion: it's like, hm

11:40 TimMc: (Somehow I missed that hyPiRion had just explained it.)

11:40 hyPiRion: ,(apply str (concat (range 10) (take 26 (map char (iterate inc (int \a))))))

11:40 clojurebot: "0123456789abcdefghijklmnopqrstuvwxyz"

11:40 TimMc: Oh, and 52 (or 62) isn't an option because the format treats upper and lower case identically.

11:41 arrdem: TimMc: ah OK I didn't know there was an upper bound on the reader radix or that it was case insensitive :P

11:42 TimMc: &[36ra 36rA]

11:42 lazybot: ⇒ [10 10]

12:24 tbaldrid_: dnolen: so, on my box, with the new dispatcher and channel code, I can put 1 mil messages into a (chan 1) in 3600 ms. With a (sliding-buffer 1), that drops to 328ms

12:25 bbloom: tbaldridge: but how many messages are being dropped that way?

12:25 dnolen: tbaldridge: what changes did you make to the dispatcher?

12:25 tbaldridge: note I think my old tick idea was not good one because it ruins reasoning about buffer sizes

12:25 tbaldridge: dnolen: just the tick based ones you discussed. I added a unbounded ring buffer for the task queue, and then we run a max of 1024 tasks on each dispatch

12:26 bbloom: tbaldridge: oh nevermind, ignore my comment. misread you

12:26 TimMc: Do the size limits on the buffers guarantee an exact size, or a minimum size?

12:26 dnolen: tbaldridge: yes so I said earlier the tick idea is not good, you can lose control of buffer semantics

12:26 tbaldridge: bbloom: that's why the sliding buffer is slower, it just testing one side of the buffer

12:26 bbloom: yup gotcha now

12:26 tbaldridge: dnolen: eh, let me paste my code and see what you think

12:26 dnolen: tbaldridge: so now a buffer of size 5000 will never do what it's intended to do

12:26 coventry: What's the closest clojure has these days to CL conditions and restarts? It looks like error-kit is no longer used?

12:27 tbaldridge: dnolen: this is the new dispatcher code, it's not the same as the code you had https://gist.github.com/halgari/6321034

12:29 and that has a bug....well it's still WIP

12:30 dnolen: tbaldridge: so try this, remove the dispatcher code and try with with (chan 1024) and (chan 5000)

12:30 tbaldridge: I'm just not convinced about putting more logic in the dispatcher anymore

12:32 tbaldridge: but think of the logic, every time we have a put/take match inside a channel we have to run the dispatcher. so (chan) will always dispatch. So that code will be super slow without a better dispatcher.

12:32 dnolen: tbaldridge: this is not a real problem

12:33 tbaldridge: if somebody doesn't want to be dispatching all the time use a larger buffer size

12:33 tbaldridge: also I did some numbers about common use cases of (chan) like in the interactive case, mouse input

12:34 tbaldridge: it would take a pipeline 300 channels deeps in modern browsers before you would have a problem w/ (chan) and mouse input

12:34 if you mouse channel pipeline is 300 channels deep something needs refactoring.

12:35 tbaldridge: so what's the penalty of using a more complex dispatcher? time to do some tests.

12:35 dnolen: tbaldridge: the penalty is (chan N) where > N 1024

12:35 tbaldridge: that's a show stopper in my opinion

12:36 tbaldridge: (chan N) where > N 1024 ?

12:36 dnolen: tbaldridge: you will want a fat chan if you're creating events via data, 1024 is too small

12:36 supersym: coventry: I don't know about those, the only thing that springs to mind is https://github.com/MichaelDrogalis/dire

12:37 it has some example for self-correcting code

12:37 dnolen: tbaldridge: if you have custom dispatch code you're breaking how buffered channels works, whatever N is pick is now the clamp, instead of the user defined buffer size

12:38 tbaldridge: No, with my code the semantics stay the same, we just simply run as many tasks as possible before dispatching again. So we move the task queue from the browser into user code.

12:38 dnolen: tbaldridge: hrm, looking again

12:38 tbaldridge: New dispatcher/run functions are always put at the input of the FIFO queue.

12:39 dnolen: tbaldridge: ok how does this not break (chan) ? does that mean I need 1024 mouse events before another go block gets to run ?

12:39 a go block which might be consuming those events?

12:41 tbaldridge: note the browser will emit at most ~160 mouse events a second

12:43 tbaldridge: dnolen: nope, it doesn't break. the mouse event put!s into the chan and ends up in the puts queue, pending takes are dispatched, if there are no pending takes, then the mouse events pile up in the take queue.

12:44 *pile up in the put queue

12:44 coventry: supersym: Thanks, looking now.

12:44 dnolen: tbaldridge: dispatched? but won't it just end up in the dispatch queue instead of running immediately?

12:44 bbloom: for some reason my irc client has changed tbaldridge's handle from red to green, which now matches dnolen's, making it impossible to follow this discussion :-)

12:45 dnolen: tbaldridge: ok sorry I reading more closely now

12:46 tbaldridge: they don't run immediately with the old code either. the callback you get back from a impl/put! is the same callback you handed to impl/put! not the take's callback

12:46 so dispatch is always run against "the other guy"

12:46 dnolen: tbaldridge: I see now, you're accounting for more stuff that might appear between dispatches

12:46 tbaldridge: right

12:47 dnolen: tbaldridge: hey pretty cool :)

12:47 tbaldridge: if the ring buffer is 32 how could you ever reach 1024?

12:47 tbaldridge: I got one nasty bug to fix, but then I'll throw this all up in a branch and see where what you all think. I've also added .unbounded-unshift that resizes a ring-buffer if it runs out of space.

12:48 dnolen: tbaldridge: ok I get it now

12:48 tbaldridge: so each time it runs out of space, it'll double in size

12:48 dnolen: tbaldridge: unbounded-shift was the missing part for me

12:48 tbaldridge: looks cool, will try it when you get it up

12:52 coventry: supersym: dire looks awesome. I'm more interested in the restart side of the condition/restart system though. Something which will return the full stack at the point an exception occurs, rather than the stack in the catch/finally clause.

12:53 dnolen: tbaldridge: so do the takes/puts in ManyToManyChannel use ring buffers now too?

12:53 tbaldridge: dnolen: yes

12:53 dnolen: tbaldridge: sweet

12:54 tbaldridge: "ring buffer all the things!"

13:03 konr`: Is there a protocol for objects that implement toString?

13:04 dnolen: konr`: for CLJS?

13:04 konr`: dnolen: regular CLJ

13:04 dnolen: konr`: that would be Object

13:04 konr`: no protocol

13:05 konr`: dnolen: hmmm, didn't know of that!

13:05 dnolen: konr`: also for equals and hashCode

13:06 konr`: this means this can only be done in deftype, you can extend-type this stuff

13:06 s/can/cannot

13:06 supersym: coventry: ok, don't know any that does, soz

13:06 dnolen: konr`: doesn't work w/ defrecord since those things are provided for you

13:06 " this means this can only be done in deftype, you cannot extend-type this stuff"

13:06 coventry: Supersym: no worries

13:11 tbaldridge: dnolen: here's the code: https://github.com/clojure/core.async/tree/tims-optimizations

13:13 dnolen: tbaldridge: I leave some comments (minor boolean related stuff)

13:13 tbaldridge: kk

13:17 bbloom: tbaldridge: total nitpick, but there's really no need for "constants" to be IN-ALL-CAPS

13:17 i mean, *everything* is supposed to be immutable, right? :-)

13:17 tbaldridge: bbloom: but, but, that's the way it's done in C :-P

13:18 bbloom: tbaldridge: right, but in cleff i had to do COMMUNICATION-IDX to match what you did & i felt dirty :-P

13:18 dnolen: tbaldridge: ok little perf comments added

13:18 tbaldridge: bbloom: I'm sorry that I make you feel dirty. lol

13:18 bbloom: tbaldridge: you're forgiven, but only b/c the code is otherwise quite clean

13:19 dnolen: tbaldridge: looks pretty nice, after those changes I'll give it a run around

13:20 tbaldridge: dnolen: kk I'll get it updated

13:22 mdrogalis: coventry: I'm around if you need help with it.

13:26 wei_: how can I make (pr-str (org.bson.types.ObjectId. "5217512f3b7e53472217ea65")) return an EDN-readable format? i.e. #"ObjectId" "5217512f3b7e53472217ea65"

13:27 mdrogalis: wei_: What datatype do you want it to coerce to in EDN?

13:27 wei_: a str

13:27 stuartsierra: wei_: define a new method for print-method.

13:27 wei_: I'm trying to serialize mongo objects for use in clojurescript

13:28 tbaldridge: dnolen: done

13:31 lynaghk: dnolen: ping

13:31 dnolen: lynaghk: pong

13:31 lynaghk: dnolen: what are your thoughts on Polymer/WebComponents?

13:31 dnolen: lynaghk: not particularly positive

13:31 wei_: @stuartsierra could you elaborate a bit? I'm not understanding the print-method example

13:32 lynaghk: dnolen: yeah, I thought it was something like that (via a few of your tweets)

13:32 dnolen: is there anything in particular that you think is a bad idea?

13:32 stuartsierra: wei_: (defmethod clojure.core/print-method org.bson.types.ObjectId [oid writer] …)

13:33 dnolen: lynaghk: my experience with every UI system just tells me the assumptions present in Polymer are deeply flawed

13:33 wei_: i see, thanks. does that activate globally?

13:33 lynaghk: dnolen: there are some usual Clojurist things I'm not a fan of (e.g., implementation inhertance of components), but the general idea of trying to package up reusable components as new tags seems like a sound one to me---at least, it's a continuation of what browsers are already.

13:34 dnolen: those assumptions being?

13:34 dnolen: lynaghk: what's the value over jQuery UI or other widget libraries?

13:34 lynaghk: dnolen: declarative markup; that something lower level is handling initialization for you

13:35 rather than a shitshow main() method that is tightly coupled to IDs/classes.

13:35 patchwork: dnolen, lynaghk: From what I have heard of this, the advantage is the nested definition of components

13:35 dnolen: lynaghk: so you really don't believe Polymer is not going to result in a shitshow?

13:36 wei_: lynaghk: is this related to your quest for finding the perfect data binding solution for webapps?

13:36 lynaghk: I'm not sure how I feel about the "bang-on-the-view-model" approach of WebComponents/Angular.js, but I'm not sure what a more functional approach would look like

13:36 dnolen: lynaghk: this has all been done before, we know what the results look like

13:37 lynaghk: dnolen: the UI situation on the web right now is a shitshow, and polymer/angular seem like an improvement to me over the defacto main() method approach

13:37 dnolen: lynaghk: I don't see how Polymer will be an improvement beyond anything surface level

13:37 lynaghk: it solves two small things, but people will still make shitty components

13:37 bbloom: lynaghk: check out react.js

13:38 lynaghk: dnolen: you could use some of the good ideas of polymer in conjunction with core.async coordination

13:38 dnolen: lynaghk: implementation inheritance will be monstrosity

13:38 lynaghk: dnolen: totally

13:38 Anderkent: core.async question: does alts! busy loop until a channel is available? It seems so from eye-balling the code (ioc-alts! never returns nil, always either result or :recur). The docs say it will park though...

13:38 dnolen: lynaghk: if that's the way the current is flowing - not much you can do about it but I just don't really care that much.

13:38 lynaghk: bbloom: react.js doesn't seem to have a good story about separating markup from behavior

13:39 dnolen: lynaghk: also I find the markup parts very suspect

13:39 coventry: mdrogalis: Thanks.

13:39 dnolen: lynaghk: does the spec allow you replace w/ whatever you want?

13:39 lynaghk: dnolen: the notion of being able to create custom tags with their own styling and behavior?

13:40 dnolen: lynaghk: I mean how flexible is it, is it easy to break components if I add my own attributes, if I embed some subview etc.

13:40 bbloom: lynaghk: in what way do you want to separate markup from behavior? it strikes me as a strange idea that you even can strictly separate structure from behavior. doesn't behavior require some structure to operate on?

13:40 dnolen: lynaghk: or is this something they expect people mess up as usual?

13:41 lynaghk: dnolen: it's certainly more flexible/composable than something like jQuery UI---all of those things expect to get an element that they can totally own and clobber without any thought to composability

13:41 jtoy: how does one process a pair of items from 2 collections at the same time?

13:42 so if i had [1 2 3 ] [4 5 6] i could get 1,4 and 2,5 and 3,6 ?

13:42 lynaghk: bbloom: you definitely need some structure, but you should be able to do that in the HTML and not have to do it in the JS.

13:42 technomancy: ,(map vector [1 2 3] [4 5 6])

13:42 clojurebot: ([1 4] [2 5] [3 6])

13:42 bhauman: Anderkent: blocks inside of a go block.

13:42 dnolen: lynaghk: so then my concern is the value proposition is very small - with some resoundingly bad OO ideas baked in

13:43 bhauman: Anderkent: as far as I know it's reactive

13:43 lynaghk: bbloom: that all of the react.js examples I've seen have lots of HTML-in-strings-in-JS gives me the idea that it'll be very hard to build, e.g., a <tabs showing="idx"> <tab>...</tab> <tab>...</tab> </tabs> kind of component

13:43 dnolen: I agree with you about the OO ideas 100%

13:44 dnolen: re: value of building custom tags, it's by far the most composable approach I've seen thus far in the web UI world.

13:44 jtoy: thx

13:44 lynaghk: especially w.r.t. collaborating with designers

13:44 bbloom: lynaghk: there are no HTML-strings-in-JS. they have an *optional* javascript preprocessor that converts XML literals into data construction calls

13:44 dnolen: lynaghk: I just think it's all very short sighted. Looking forward who cares about the DOM, we need/want to abstract UI components over SVG, Canvas, WebGL

13:45 Anderkent: bhauman: so from doing it on the repl it seems it doesn't busy loop, but I can't see how that happens from the code. ioc-alts! calls do-alts, which eitehr says 'i read you a value' or returns nil if no channel has anything... ioc-alts! either advances the state machine in the first case, or returns :recur in the latter... Recur just makes the thread loop into ioc-alts! again as far as I can see.

13:45 dnolen: lynaghk: instead we're gonna get desktop UI thinking all over again, do not want

13:45 bbloom: dnolen: agree w/ that

13:45 lynaghk: dnolen: the DOM *is* abstract UI components!

13:45 dnolen: lynaghk: so how will your Polymer component work in WebGL?

13:45 it won't

13:46 bbloom: lynaghk: well, only if you allow custom dom elements to be created

13:46 dnolen: you'll replicate all the crap for a different surface

13:46 patchwork: dnolen: Abstracting over SVG, Canvas or Webgl you still need an approach to designing them!

13:46 lynaghk: patchwork: yes!

13:46 dnolen: you mean building out a full UI that renders in WebGL?

13:46 jtoy: is there a cleaner way to write this: (map first (filter #(= (last %) 1) (map vector candidates results)))

13:46 patchwork: The philosophy behind how to design a UI is independent of what it is implemented in

13:46 bhauman: Anderkent: you are far deeper into it, than I am. i only know from experience that it doesn't loop. But do you have any luck expanding the go macro

13:46 dnolen: patchwork: Polymer doesn't do this

13:47 lynaghk: UI components are processes not what they look like

13:47 patchwork: dnolen: Right, but how would you do that?

13:47 dnolen: patchwork: read my core.async posts

13:47 cespare: jtoy: well for starters instead of (first (filter you can use find-first

13:47 patchwork: The question is: What is the best way to design a UI?

13:47 dnolen: I'll check them out. core.async for UI?

13:47 dnolen: patchwork: yep

13:47 jtoy: cespare: that is different

13:47 dnolen: patchwork: http://swannodette.github.io/

13:47 sjl: cespare: it's (map first (filter not (first (filter

13:47 jtoy: i am mapping out the first item

13:47 Anderkent: bhauman: that's what I did, and I can't see how it returns control - even though I know it does. Perhaps I should put prints into the expanded form :P

13:48 lynaghk: dnolen: yes, agreed. So with polymer you can define something like <my-button with="arguments"> and style it independently.

13:48 cespare: jtoy: sorry misread

13:48 dnolen: lynaghk: but people are going to write logic that targets DOM

13:48 FAIL

13:48 bhauman: Anderkent: did you see the post explaining the state machines?

13:48 bbloom: dnolen: you can't say that's FAIL, there are different goals

13:48 lynaghk: dnolen: if you're saying that polymer isn't great because you can't take it and render it in WebGL, that's not something I'm very concerned about.

13:48 Anderkent: bhauman: yes. That's where my investigation started

13:48 I saw the ioc-alts! code and said 'wait a moment this busy loops

13:49 dnolen: lynaghk: that's not what I'm saying

13:49 lynaghk: dnolen: (also, if you do things correctly I don't see why you wouldn't be able to take the HTML + CSS and write a WebGL renderer)

13:49 bbloom: lynaghk: seriously though, go look at react.js. it's much more functional than it is OOP, in fact, it's only as OOP as javascript forces on it

13:49 jtoy: cespare: it looks bad to me because i do a transformation, filter, then another transformation

13:49 dnolen: lynaghk: people are going to deliver what could be reusable logic, but it won't be reusable

13:49 lynaghk: bbloom: noted, I'll take a deeper look at it

13:49 dnolen: lynaghk: you can only use it with Polymer

13:49 bbloom: lynaghk: polymer is yet another smalltalk-legacy MVC OOP mess

13:49 lynaghk: react.js looks kinda OOP & demos poorly b/c it seems like it's similar to what you've seen before

13:49 bhauman: Anderkent: well you are inspiring me to finally take a look at it.

13:50 Anderkent: it's pretty good

13:50 just don't start reading large blocks that he pastes in here and there

13:50 lynaghk: dnolen, bbloom: Again, I'm not 100% sold on polymer---it's just the best concrete thing I'm aware of right now. If you guys can point to other systems (or even whitepapers with pseudocode) I would love to see 'em

13:50 bbloom: lynaghk: but in reality, it works with *data* & external state. it hydrates instances on demand, memoizes functional rendering output, then incrementally mutates the dom, treating it as an external database

13:50 bhauman: Anderkent: I have been a happy incurious, consumber

13:50 Anderkent: I did that, spent 10 minutes parsing some sophisticated code, and then saw that he goes through it expression by expression below that

13:50 :D

13:51 bbloom: lynaghk: the majority of your components are stateless & their instances are not retained in memory except when necessary during rendering

13:51 lynaghk: stateful components are OOP only in the sense that they can respond to events in a traditional manner & have some state. but that state isn't stored in the object, it's stored in a global database & referenced by ID. you can't communicate between components except via parameterization

13:52 lynaghk: bbloom: don't you think many UI components need state? E.g., selected items in a list?

13:52 bbloom: lynaghk: yes, i do think that. which is why i like react's approach

13:53 lynaghk: bbloom: aren't polymer components attributes the parameterization you're describing?

13:53 sjl: cespare: I

13:53 bbloom: lynaghk: components are built up of 1) types (which are == the classes of the objects / custom element names) 2) "parameters" which are like arguments to the render function 3) children, which is the result of rendering 4) an optional state json object, which can be used to update params or children during the next render pass

13:53 sjl: 'd probably do something like (for [[c r] (map vector candidates results) :when (= r 1)] c)

13:54 bbloom: lynaghk: it feels similar to writing a server-side rendering with a templating language, only you can associate state & event handlers with components

13:54 sjl: and use (zip ...) from flatland/useful instead of (map vector ...)

13:54 Anderkent: bhauman: ah, I'm an idiot. in ioc-alts! I misread a `when-let` for an `if-let`

13:54 that's disappointing

13:54 bbloom: lynaghk: instead of inheritence, you just create lots of small, generally stateless components, which are similar to helper functions

13:54 lynaghk: bbloom: what triggers re-rendering? Is there a dirty-checking loop like angular, an ordered dependency graph like flapjax, or straight up callbacks on individual properties?

13:55 Anderkent: .. I'm gonna grab a beer.

13:55 tbaldridge: dnolen: there's a odd race condition I'm working through may not want to test this quite yet.

13:55 bhauman: Anderkent: no don't do that it won't help

13:55 dnolen: tbaldridge: ok

13:55 bhauman: Anderkent: :)

13:55 bbloom: lynaghk: it's similar to angular, but where angular diffs the view model, react diffs the views

13:56 Anderkent: bhauman: going home anyway :P

13:56 thanks for the help

13:56 lynaghk: bbloom: I thought the only state was in a JSON object

13:56 bbloom: lynaghk: it's a transactional model, like clojure. you have a database of components+state, when events fire, things react to them & commit new state. the components can not mutate each other's state nor can they even see the effects of their state changes. after each component gets a chance to react to events, which happen in a synchronous pass, then all the differing state triggers cascading re-renders

13:56 bhauman: Anderkent: enjoy, don't think I helped but it was good chatting.

13:56 lynaghk: bbloom: I do like that react.js and polymer both have TodoMVC entries = )

13:56 cespare: sjl: jtoy how about (keep-indexed #(if (= (results %) 1) true) candidates)

13:57 sjl: jtoy sorry i mean (keep-indexed #(if (= (results %) 1) %2) candidates)

13:57 bbloom: lynaghk: i think it's extended JSON, like you can have dates in there, just like in angular, you can store anything you can diff

13:57 dissipate: what is the 'best practices' rule of thumb for destructuring expressions? it seems like those can get out of hand

13:57 xiaq: clojurebot: how do i play with you?

13:57 clojurebot: Huh?

13:57 xiaq: clojurebot: $help

13:57 clojurebot: Excuse me?

13:57 xiaq: clojurebot: @help

13:57 clojurebot: Gabh mo leithscéal?

13:57 bbloom: lynaghk: dnolen argues correctly that react & polymer are both DOM-centric, but i think that react's model is a deeply functional approach under the hood

13:57 lynaghk: bbloom: interesting. I'm going to dig through it and Polymer's TodoMVCs. Maybe a blog post will come out of this.

13:58 or, god help me, some ClojureScript sketches = )

13:58 bbloom: lynaghk: dnolen: i've been on-and-off-again working on a underlying-tech-agnostic UI toolkit that has a lot in common w/ react's underlying model

13:58 lynaghk: bbloom: yeah, the bits of angular/polymer I'm excited about are the DOM integration, not the OO/mutation stuff.

13:59 bbloom: lynaghk: angular is nice, but you have to write a lot of crazy directive stuff for larger apps & reusable components. react & polymer make modularity the default, but polymer goes full OOP & react goes full memoizing pure render functions w/ a transactional update pass

14:01 lynaghk: bbloom: interesting summary. Thanks for bringing React to my attention. I'll dig 'round and try to figure out the best ideas to steal for use with cljs

14:02 bbloom: lynaghk: note that react doesn't bother trying to integrate w/ the dom. there are no actual custom tags reified at runtime b/c there is no value in that. there is no browser-level shadow dom or anything like that

14:02 dnolen: lynaghk: I also think the initialization stuff is not good

14:03 sjl: cespare: if results is a vector or somthing that supports effecient acces by index, that will work

14:03 dnolen: lynaghk: I'm leaning towards a model where widget sitting around in memory never happens, only processes over them that appear or disappear as required which is as it should be in my opinion.

14:03 sjl: cespare: that also assumes you don't have a candidate, result pair of nil 1

14:04 in which case it wouldn't return the nil properly

14:04 dnolen: lynaghk: basically I'm done w/ the last 8 years of stuff I've done on the web, Polymer is just more of the same to me in everyway.

14:04 bbloom: dnolen: that's exactly how react works

14:04 dissipate: dnolen, what do you mean you are 'done' with it?

14:04 lynaghk: bbloom: wahhhh, I'm confused now. There is so much value in a shadow DOM and custom tags

14:05 bbloom: lynaghk: there is value in custom tags, there is no value in reifying them for the browser to inspect

14:05 dnolen: dissipate: no longer interested in putting any more brain time into that style of programming.

14:05 bbloom: dnolen: react does not instantiate or retain widgets in memory

14:05 lynaghk: dnolen: yeah, I know you've been in the space for a while, which is why I'm interested in your opinion on these matters

14:05 bbloom: dnolen: if you widgets have state, then that state is stored in a global widget-id => state map

14:05 lynaghk: dnolen: sometimes I need to get pulled by the nose for a while before I can see the light, though = )

14:06 bbloom: dnolen: if an event is fired, the object is only instantiated to maintain a javascript-style developer experience. it's about as far from OOP as you can actually get. each object is more like a go-loop which responds to a message & keeps it's state as a loop argument

14:06 dissipate: dnolen, the web SUCKS. that's my opinion

14:07 dnolen: bbloom: yes, I still need to look at React (after grokking ANF ;), I've been thinking about a core.async AppState thing

14:07 lynaghk: dnolen, bbloom: I gotta run right now though. Thanks for all of the good ideas.

14:07 dissipate: how many more language X to javascript compilers do we need?

14:07 dnolen: dissipate: heh, I think the web is awesome, CLJS is a good model to reign in the monster

14:08 dissipate: dnolen, the web is broken as is the industry of 'web programming'

14:09 dnolen: dissipate: not any more than anything I've used - mainstream desktop / server programming looks equally gnarly to me.

14:09 dissipate: I think browser stuff aside, the reason people don't like web programming is that people are doing distributed system programming with crappy tools.

14:09 bbloom: everything sucks and no one cares!

14:09 dissipate: dnolen, all these highly caffeinated 'brogrammers' who think MVC is an architecture. have you ever seen Uncle Bob's stuff? http://www.youtube.com/watch?v=asLUTiJJqdE

14:09 bbloom: :-)

14:10 wink: no software is better than no software.

14:11 best quote from puppetconf :P

14:11 dissipate: dnolen, on the desktop you can pick your language, your architecture and whatever else. in the browser, you are trapped with HTML, CSS, javascript. that's bad

14:11 patchwork: dissipate: What is an architecture in your opinion?

14:11 bbloom: dissipate: you're preaching to the choir regarding choice of superior tools in the browser

14:11 patchwork: Also, that is what cljs is trying to solve

14:12 technomancy: http://www.buildingkeystones.com/wp-content/uploads/2012/03/no-software.jpg

14:12 whatever that means

14:12 dissipate: patchwork, the underpinnings of your software design. the 'stuff' that is not easily changed.

14:12 bbloom: technomancy: lol that's salesforces logo

14:12 technomancy: bbloom: still the deeper meaning is a mystery to me

14:13 bbloom: technomancy: clearly you haven't met the mascots: http://static3.businessinsider.com/image/4e65b08569bedd144500006f-480/salesforce-no-software.jpg

14:13 that's "chatty" the salesforce chatter mascot in the background there. he's a big red smiley face

14:13 * technomancy breathes deeply and contemplates the nature of nil

14:13 bbloom: :-)

14:13 patchwork: dissipate: Since the real world constantly demands change of software, could architecture be a liability then?

14:13 dissipate: patchwork, have you seen any of uncle bob's stuff?

14:14 patchwork, no, not at all. a good architecture let's you swap out technologies like web frameworks, databases etc.

14:14 patchwork: So then, the architecture is the backbone that allows other things to change

14:14 dissipate: patchwork, correct

14:14 patchwork, see this on clean architecture: http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

14:15 patchwork: Until your architecture becomes the thing preventing some kind of change : )

14:15 dissipate: I have not heard of uncle bob, I'll check it out. Thanks

14:16 dissipate: patchwork, he has a lot of material on clean code and clean architecture. he is also a proponent of Clojure.

14:16 wink: I haven't read the whole thing, but what I saw of Clean Coder was not so awesome

14:17 dissipate: wink, not sure about that book, but 'Clean Code' seems to be good

14:17 patchwork: Got it, so he is preaching separation of concerns

14:17 Any static thing can be made dynamic by adding a new level of indirection : )

14:17 The Law of Code

14:18 wink: dissipate: maybe I'm mixing it up, but it was this whole "you have to hone your skills even after going home from your 40+h job" - and I say that as someone who lists programming as a huge hobby

14:18 dissipate: plus a little know-it-all tone. but as I said, I haven't read both books cover to cover

14:18 bhauman: technomancy: bbloom: they keep using that word, but clearly they do not know ...

14:19 patchwork: So the architecture always becomes the base of the tree, it is by definition the thing that cannot change. Or rather, what still has not been granted a level of indirection that allows it to change

14:19 dissipate: patchwork, no, it can change, it's just more work

14:20 wink, yeah, i didn't really agree with that part

14:20 wink, professionals in other industries aren't expected to study after work

14:21 wink, but the problem is what do you do if your shop is using bad languages and technologies? in that case, it is in your interest to study outside of work and try to find a better shop

14:21 for instance, if i worked a java shop, i would work like hell to GTFO of that place

14:23 patchwork, the 'clean' layered architecture approach has the rule of thumb that you put the stuff that changes more often on the outside layers and the stuff that changes the least often in the inside layers

14:23 wink: dissipate: yeah of course. but that's intent to grow immensely beyond your current gig. not saying that's a bad thing, but a special case

14:24 dissipate: patchwork, do you agree that 99% of software out there is a big ball of mud? especially web stuff...

14:25 patchwork: dissipate: I haven't seen 99%! I have seen like 0.001 %

14:25 And yeah, most of it grew from humble beginnings far beyond its original scope

14:25 dissipate: patchwork, extrapolate from a statistical sample. :P

14:25 jonasen: Here’s a (demo)project of mine I’ve been working on for a while: http://cljsfiddle.net

14:26 It’s very (very!) alpha still so don’t expect too much :)

14:26 patchwork: dissipate: knowing how it is going to change beforehand is hard. I have also seen projects set up an architecture they never ended up needing, then growing in another direction and becoming a ball of mud anyway

14:26 seangrov`: jonasen: This is a great idea!

14:27 patchwork: To truly design software well you have to see what you will need in the future

14:27 * muhoo busts out the crystal ball

14:27 patchwork: Since this is impossible in practice, most software is gangly and obtuse

14:27 jonasen: Note that it'll be quite slow the first time you run a program, after that it will hopefully be a fast edit/run cycle thanks to http caching. Also, I'm only running an in-memory db for now so don't expect your work to be saved for long.

14:27 muhoo: i seee..... lines of code.... requirements changing constantly out from under you....

14:27 benkay: jonasen++

14:27 patchwork: muhoo: You really can see the future!

14:28 jonasen: a more advanced example: http://cljsfiddle.net/fiddle/jonase.bezier

14:28 dissipate: patchwork, and why doesn't this happen in other industries like mechanical engineering?

14:28 jonasen: seangrov`: benkay: thanks

14:28 dissipate: or electrical engineering for that matter

14:28 muhoo: it does happen in mechanical and electrical engineering

14:28 benkay: jonasen now implement nrepl.el keybindings

14:28 jk jk

14:28 dissipate: if one's designs were a big ball of mud, they would get thrown out, in those industries, no?

14:28 muhoo: it's slow-motion mud

14:28 patchwork: dissipate: Because no one comes along and changes the design of the bridge after its built

14:28 seangrov`: benkay: Yeah, the editor could probably use a touch of work :)

14:29 Very smart though

14:29 Well done!

14:29 muhoo: change is expensive and slow in hardware and mechanical.

14:29 benkay: dissipate: naw, man. you just hire more grunts to put the stuff together better.

14:29 dissipate: or you hire more grunts to test the stuff more rigorously

14:29 patchwork: The bridge is there now, people accept it can't change

14:29 benkay: dissipate: i left for many many reasons

14:29 dissipate: patchwork, things change in electrical and mechanical engineering.

14:30 benkay, from which industry?

14:30 patchwork: dissipate: Sure, but not after the project is built.

14:30 The designs change

14:30 muhoo: yes, after it's built. rev 2. rev 3, green wire and dead bugs haging off the board.

14:30 jonasen: benkay: heh, that'll have to wait

14:30 benkay: multiphysics engineering

14:30 dissipate: multiphysics engineering

14:31 patchwork: muhoo: Well sure, they change it as much as it can. But bridges are far less adaptable than software

14:31 dissipate: patchwork, you aren't disturbed at all by the fact that the average CS grad has no notion of software craftsmanship, or very little? and especially no notion of architecture. they got their degree by banging out code over long nights that none of their TAs can properly review because they went through the same program.

14:31 muhoo: it's just a slower, more expensive process

14:31 speed and cost make people more careful :-)

14:31 benkay: big-ish and small-ish systems for http://cascademicrotech.com among others, dissipate

14:31 patchwork: If you could modify a bridge as easily as you modify some code, we would see some horrific things

14:31 dissipate: benkay, and you left the industry because?

14:31 patchwork: You would see software level horror in bridge form

14:32 benkay: i left the industry for a multitude of reasons, dissipate.

14:32 speed of innovation

14:32 capital requirements for everything

14:32 boodle: I have a ring app I'm trying to deploy that uses jdbc mysql and sqlserver drivers.. I'm clueless on java and running into this: http://stackoverflow.com/questions/14977228/creating-an-uberjar-for-a-project-that-uses-mysql-and-sqlserver

14:32 benkay: mean reversion on teams

14:32 dissipate: benkay, so you do clojure software development now?

14:33 benkay: no beer in offices because you can't get insurance if your line operators have access to alcohol on-shift, and providing alcohol to the engineers makes the eng/prod split even worse

14:33 loliveira: .mt

14:33 benkay: i do cloud operations. clojure is involved.

14:34 dissipate: benkay, i see. seems like out of the frying pan into the fire. but i guess that's just my perspective.

14:35 benkay: writing code and managing boxen in service of increasing scale of problems i and my fellas can tackle sanely.

14:35 dissipate: at least you get to use clojure. so few clojure shops out there.

14:35 benkay: "mean reversion of teams"

14:35 i'm a snob.

14:35 seangrov`: dissipate: We're (probably) hiring two people who don't know clojure, they're happy to learn it

14:35 Plenty of places hiring developers

14:35 benkay: i don't have to design machines in such a way that operators can't rip their fingers off.

14:35 that's a net win.

14:35 seangrov`: Err, hiring developers to code in clojure

14:36 patchwork: dnolen: I am enjoying the CSP articles. Thanks for sharing

14:36 dissipate: seangrov`, you aren't worried how long it is going to take them? i'm coming from imperative languages and this is completely different stuff for me. :P

14:36 dnolen: patchwork: np

14:37 patchwork: dnolen: Have you built any large UI's with this approach?

14:37 dissipate: benkay, how long did it take you to make the transition?

14:37 patchwork: curious how it scales

14:37 seangrov`: dissipate: They have good skills and experience. I expect it to be a few weeks before they're up to speed and productive

14:38 benkay: dissipate: 9 months.

14:38 dissipate: seangrov`, a few weeks?? wow. someone told me it takes about a year to get comfortable with Haskell. Clojure isn't as bad, so cut that in half to maybe 6 months? a few weeks sounds cray

14:38 benkay: 6 before i was self-sufficient as a consultant

14:39 9 total before i was useful in someone else's organizatino

14:39 dnolen: patchwork: nope since I'm still learning it, but the autocompleter is a convincing non-trivial example in IMO

14:39 dissipate: benkay, wow, that's pretty quick. that's cool

14:39 benkay: but that's 9 months of 70+ hr weeks working and studying the computation stack.

14:39 dnolen: patchwork: much cleaner than other similar things I've build in the past and more flexible

14:40 benkay: granted i wasn't starting from scratch, i had a fair amount of experience in simulation and control system design and implementation.

14:40 dissipate: benkay, OpenStack?

14:40 benkay: dissipate: what about it?

14:40 seangrov`: dissipate: The ideas are already their in other languages, they're just expressed more succinctly in clojure. Takes time to understand, and I expect they'll be putting in time like benkay, but it's a matter of self-improvement

14:40 dissipate: benkay, is that what you are using or are you on AWS or a third party cloud provider?

14:40 benkay: ah.

14:41 client dependent.

14:41 the client that i've been working with the most for the past 5 months is actually a bare-metal shop

14:41 >.<

14:41 patchwork: dnolen: Haven't gotten to the autocompleter yet, I'll check it out.

14:41 benkay: i wasn't involved in those discussions.

14:41 patchwork: dnolen: Seems like you would still have to have somewhere to store and access all the channels in a non-gnarly way

14:42 dnolen: patchwork: no

14:42 dissipate: seangrov`, personally, i haven't found anything quite like macros in other languages.

14:42 seangrov`: dissipate: Meh, reader macros are even crazier :)

14:42 dnolen: patchwork: you don't store channels anywhere

14:42 patchwork: you wire things together but calling functions

14:42 benkay: but generally speaking, openstack is overkill for most clients. a simple cloud instance spinup script and provisioning tool serves most totally sufficiently.

14:42 justin_smith: dnolen: pub-sub :: malloc :: core.async : gc ?

14:42 benkay: that said, i'

14:42 dnolen: s/but/by

14:43 benkay: i'm always looking for larger scales of problem.

14:43 justin_smith: oops, extra : above

14:43 dissipate: benkay, Puppet/Chef?

14:43 patchwork: dnolen: Ah, you just hook them up? But what if you want to change the wiring?

14:43 interesting… I'll have to mess with it

14:43 benkay: chef for big client, salt for smaller clients, been playing around with ansible.

14:43 dnolen: justin_smith: pub-sub is one thing you can do w/ core.async, but you want to avoid pub-sub since that's a resource problem

14:43 dissipate: benkay, go work for google. that's pretty large scale. :P

14:43 benkay: f that

14:43 dnolen: patchwork: just give the channel to someone else if you need to

14:43 benkay: organizational pathology all the way down, dissipate.

14:44 plus no actual interaction with business.

14:44 dissipate: benkay, but i heard they pay well

14:44 benkay: look, we solve problems.

14:44 money ain't everything.

14:44 dnolen: justin_smith: sometimes you do need it of course, I'm still thinking about it, hoping to right up my thoughts on that at some point.

14:44 s/right/write

14:44 benkay: personal growth, joy in the experience of life and reputational development are all vastly more important to me and mine.

14:45 i'd rather work 30 hours per week for 80k than 40 for 120.

14:46 (that said, solving other humans business problems is so fun that i find myself working more than the important humans in my life want me to)

14:47 dissipate: benkay, and these business people have no idea you are using clojure?

14:48 benkay: i strive to find clients who trust me to use the appropriate tools for a given problem.

14:49 open comms are the foundation of trust.

14:49 dissipate: if they bring other developers on board later, there's going to be some WTFs :D

14:49 benkay: ah, your assumptions are showing.

14:49 dissipate: how so?

14:49 benkay: well, being 'a developer' tends to cap ones a) influence on projects and b) billable rate

14:50 dissipate: that i agree with

14:50 benkay: when i'm 'a developer' on a project, it's typically as a favor to someone and i do the best thing for their project.

14:50 which, take coinforest.com

14:50 john and i are friends

14:51 i gently suggested he move to AWS

14:51 he said 'lol i r no wat'

14:51 dissipate: you are doing bitcoin projects?? interesting...

14:51 benkay: so i wrapped it up in CM over a couple of nights and stood it up elsewhere. but it's just a wordpress site.

14:51 and it works for him.

14:52 so now it's in CM and backs itself up nightly.

14:52 without clojure. 'cause bash is totally sufficient.

14:52 futile: Is it bad practice to build up a regular expression via raw strings, like (str "(" (join "|" options) ")") ?

14:52 benkay: eh. if only there were real capital seeking to deploy itself in the bitcoin space.

14:53 dissipate: benkay, why did you pick wordpress over drupal?

14:53 benkay: again with the assumptions

14:53 it's his site

14:53 he stood it up first

14:53 i helped him insure it against falling over.

14:54 dissipate: i don't know about 'real' capital, but i personally made a boatload off my bitcoin investment

14:54 benkay: want to fund the development of an options exchange?

14:54 it'd only take about 120k by our estimation.

14:55 we'd be doing it in clojure and you could work on it too :)

14:55 came up with a sweet hack to get around the infinite downside problem.

14:55 dissipate: maybe... depends on how it is executed.

14:56 benkay: how would you want it executed?

14:57 dissipate: benkay, one of two ways, either all lawyered up and compliant with the feds, or set up in a way that makes it difficult/costly to shut down

14:57 benkay: those are the options, yes ;)

14:58 tbaldridge: dnolen: did we ever fix that timeout bug? I think I'm hitting it in my testing

14:58 dnolen: tbaldridge: sorry we didn't!

14:58 tbaldridge: I think those tests are broken, I forget to mention this

14:58 devn: what do people use for debugging in the repl these days?

14:58 dnolen: tbaldridge: let's just comment them out for now and I'll address later

14:58 arcatan: executed with java -jar exchange.jar

14:59 tbaldridge: dnolen: yeah, and in my tests I'm creating a (timeout 500) and it's never closing

14:59 dnolen: tbaldridge: the timeout tests are just badly designed, they shouldn't check for count because that's tied to behavior of dispatcher

15:00 tbaldridge: should check that the timeouts-map is purged of particular timeout

15:00 instead

15:02 tbaldridge: if it's actually never closing that's a different problem

15:02 tbaldridge: never encountered that before

15:02 hyPiRion: my, wrapped booleans are still behaving weirdly

15:02 ,(and (Boolean. false) true)

15:02 clojurebot: true

15:03 hiredman: hyPiRion: they always will, clojure doesn't change the wackiness that is Boolean

15:04 hyPiRion: hm =/

15:05 hiredman: clojure canonizes literals, but if you construct random Booleans you are on your own

15:07 hyPiRion: so the trick is just to know that the primitives false and nil are falsey, and that false? and true? return true if the input is the primitive false/true then

15:12 lynaghk: bbloom: Reading up on react-

15:12 bbloom: this stuff reminds me a lot of what I was doing with Singult/C2

15:13 though they seem to be doing a lot more optimization on your behalf (rather than complete DOM-subtree walking)

15:13 bbloom: lynaghk: they basically diff at the sibling level

15:13 lynaghk: which can be problematic for some cross-hierarchy stuff, but in general is pretty rare & easy to work around

15:14 lynaghk: but your render functions don't return full sub trees. they return descriptions of sub trees

15:14 [:button {:id "my-button"} "With some text on it"]

15:14 that's what you return & the evaluator will later look up the button rendering code & recurse

15:14 lynaghk: bbloom: right.

15:14 bbloom: it's a good design

15:15 lynaghk: conceptually it's similar to function composition in hiccup, no?

15:15 bbloom: yes

15:15 ie functional :-)

15:16 if the render finds that you give it a description of an object that already exists (ie has the same hierarchy path, element type, and optionally a string-key for matching up moving elements in a list view or something like that) then it will preserve the state & transfer over any new parameterization

15:16 lynaghk: bbloom: yeah, I liked writing UIs in that style with C2 and singult---the only issue was perf.

15:16 bbloom: otherwise, it will throw away the state of that widget & detatch handlers & all that

15:16 lynaghk: sure, perf sucks if you do the naive implementation

15:16 and i mean naive as in the technical sense, not as in you're stupid :-)

15:16 lynaghk: bbloom: of walking the subtree on each call to render

15:16 bbloom: what react does is aggressive memoization

15:16 lynaghk: (In singult it's called "merge")

15:17 bbloom: you can stop walking a subtree if you ever discover the parameters are not different

15:17 and if you only ever walk data & never touch the dom, it's much faster

15:17 lynaghk: bbloom: https://github.com/lynaghk/singult/issues/3

15:17 bbloom: react fully virtualizes the dom. it never looks in the real dom for anything unless it HAS TO for a browser quirk or whatever

15:17 lynaghk: ok so then yeah, you get this :-)

15:17 you should like this then! :-P

15:17 lynaghk: bbloom: = )

15:18 bbloom: I love having ideas and then finding out smarter people implemented them better.

15:18 bbloom: haha

15:19 yeah, your thing sounds just like react

15:19 where you screwed up was exposing the render function :-)

15:19 ie the one returning a live dom node

15:20 lynaghk: bbloom: I dunno about this JSX preprocessor stuff though; conceptually it seems like we're all on the same page---the real question now is the tradeoffs of html-ish syntax vs a richer format like hiccup or this react data stuff where you can have explicit references to shit besides strings

15:20 bbloom: you mean react sounds just like my thing from 12 months ago =P

15:20 bbloom: lol whatever

15:21 i'm not a big fan of the JSX idea in general b/c i hate xml notation & such an extension procludes use of other syntax extensions… you know… like coffeescript :-)

15:21 lynaghk: bbloom: The one place where this doesn't work out super great is when you want to compose with other libs that don't know about this style

15:21 bbloom: but in clojure w/ hiccup-style notation, it's basically the same idea

15:21 lynaghk: bbloom: e.g., for a client project I had to add this "ignore" special type to singult so that in a subtree I could throw a jQuery drag and drop thing

15:21 bbloom: lynaghk: react's escape hatch for that is here: http://facebook.github.io/react/docs/working-with-the-browser.html

15:22 lynaghk: yeah, damn. this react thing is very similar to Singult.

15:22 "in memory representation of the DOM" <=> hiccup.

15:22 bbloom: lynaghk: cool now explain it to dnolen :-)

15:22 lynaghk: though in their case you can have special tags

15:23 bbloom: yeah, the special tags is critical. it's your abstraction mechanism

15:23 coventry: I find the Ritz debugger a bit awkward to use. It's slow to start up, and the need for break-on-exception to use breakpoints means you break on lots of irrelevant exceptions. Would there be any value to an in-clojure debugger which works like edebug? That is, a special reader which instruments forms with debugging calls as it evals them?

15:23 bbloom: custom tags == functions, not objects

15:23 lynaghk: wheras in hiccup if you do something like [:ol (my-special-list-item-template data)] then you lose the semantic info

15:23 bbloom: STATEFUL custom tags == functions w/ loops in them that break out of the loop when the parent function stops including that ID in the dom

15:23 lynaghk: compared to [:ol [:my-list-element {:data data}]]

15:24 bbloom: lynaghk: yeah, that's something i'm trying to solve. unfortunately i think there are only two solutions: 1) explicitly defer execution by using vectors & keywords (my current solution)

15:24 lynaghk: and 2) totally custom language/evaluator

15:24 react is basically doing #1 with a sprinkling of #2 for using xml notation instead of vectors & keywords

15:25 futile: Does Clojure or Java have an analog to Core Data for local programs?

15:25 dnolen: bbloom: lynaghk: I dunno about this tree walking stuff

15:26 bbloom: lynaghk: why not compile templates ahead time + core.match

15:26 bbloom: dnolen: what does core.match have to do with anything?

15:26 futile: Maybe core.logic or Datomic makes sense for this.

15:26 dnolen: bbloom: why do you need tree walking?

15:27 lynaghk: dnolen: in Singult the tree walking was naive and done on fully-rendered DOM elements. There are situations where this is useless (e.g., if you want to change the type of an element at a given position---the walker has no idea what it's supposed to do).

15:27 dnolen: bbloom: throw that out the window think about precompiled templates + matching

15:27 bbloom: convert the data into paths, push through a template that uses pattern matching

15:27 bbloom: dnolen: you only need tree walking when your backend renderer is a tree. in my prototype, i use this model & there are two possible backends: one that returns a dom-like tree & one that returns a list of java2d/canvas-style draw commands

15:28 dnolen: the dom backend walks a tree, but the tree is an implementation detail for updating the dom via a diff

15:28 dnolen: the java2d backend just does full re-rendering & that's fast enough for small apps. in larger apps, it will need to memoize layers in to textures

15:29 i don't see how precompiled templates help, since you're building dynamic UIs. the template will need just as much branching & looping as your render functions that return javascript data structures instead of html snippets

15:31 mimieux: duck1123: Does exist a ciste tutorial?

15:31 duck1123: mimieux Not really. I've been meaning to write one for the longest time, but never have

15:32 lynaghk: bbloom: in this scheme, how do you imagine event handlers working?

15:32 bbloom: that your custom components handle the low-level events, and they have some way of emitting them back upstream as application-semantic events?

15:33 bbloom: lynaghk: i'm planning on using a multi-pass model

15:34 lynaghk: even though there are two backends for *rendering* (dom + canvas) there are other backends for other use cases too

15:34 lynaghk: for example, event processing or hit testing

15:34 lynaghk: you can think of the code you write as being a traversal over a data structure & then you parameterize your traversal with different evaluators

15:34 have you ever done any 3d/game/graphics programming?

15:35 lynaghk: bbloom: not a ton outside the web

15:35 bbloom: ever heard of a shaddow map?

15:35 lynaghk: bbloom: actually, lets step back from events real quick---I'm trying to explain to my designer what this approach would look like compared to frankenstein string attributes in HTML for templating.

15:36 since if he wants to control the markup/CSS, he'll need to use something closer to hiccup than to slim.

15:37 (hiccup having clojure's richer data structures to play with, compared to stringifying everything in HTML for a runtime evaluator based on the HTML)

15:37 bbloom: well, ignoring event handling, it would look a lot like react: you just write a pure render function that looks at some args, does normal code branch/loop code & then returns some dom-like node thinggies

15:38 mimieux: duck1123: ok, now reading jiksnu.

15:38 lynaghk: bbloom: my question is what the dom-like thing looks like--does it have higher-level semantic info in special tags/attributes?

15:38 bbloom: it's just data, make it look however you like

15:38 duck1123: mimieux, if you have any questions, let me know. I love getting feedback

15:38 lynaghk: bbloom: like, you have a [:unify {:data data :mapping-fn ...}] tag instead of a fully rendered [:container element1 element2 ...]

15:39 mimieux: duck1123: sure!

15:39 lynaghk: i.e., you pass the unevaluated fn as a tag to the renderer so that it can more intelligently handle the dom

15:39 bbloom: lynaghk: you could create a thunk, but you're probably better off returning some data structure w/ a name & some arguments

15:40 lynaghk: bbloom: right, that's my question

15:40 bbloom: [:widgets/tab-controls {:tabs […]}]

15:40 or something like that

15:40 if the renderer sees divs & spans & shit, it draws them or updates the dom. otherwise, it expands the widget

15:41 lynaghk: right

15:41 bbloom: how are you controlling scope?

15:41 bbloom: ok so on to the event handling idea :-)

15:41 scope of what?

15:41 everything is lexical

15:41 except the tag names

15:42 lynaghk: you don't want everything to have access to the toplevel scope, otherwise if anything changes up there you have to re-render everything

15:42 bbloom: yeah, you have to thread data down the views as arguments

15:42 lynaghk: you want the minimum scope per subtree---an explicit list of what data that subtree depends on, so that you can memoize effectively

15:42 bbloom: okay, right.

15:43 bbloom: yeah, look at how react does that: it divides data in to two halfs: 1) props 2) state

15:43 lynaghk: bbloom: so is it that each tag is basically a fn call

15:43 bbloom: yeah, just deferred until the renderer decides if it needs to call

15:43 there is a 3rd pseudo set of data, which are the children, so you can write <Tabs><Tab>asdfasdf</Tab></Tabs>

15:43 lynaghk: the children are opaque to the parent?

15:43 bbloom: but that's just sugar for a "children" key in prop

15:43 s

15:44 you have to explicitly render your children

15:44 lynaghk: bbloom: can we schedule a time to pair-program a whitepaper example of what todoMVC looks like with this approach?

15:45 bbloom: lynaghk: here's my non-functioning example that is surely bugged:

15:45 https://gist.github.com/brandonbloom/0acd45c60860e4dd562f

15:46 lynaghk: that's an approximate goal for my code. i have something about 5x as verbose as that working & i'm adding the features i need to get it to work properly. i'm focusing on the java2d backend for now tho, since i know that this approach works in react & i want to prove it's more general

15:46 whoops copy paste fail

15:46 refresh

15:48 lynaghk: bbloom: are you using keywords as a shortcut for clasess?

15:48 (section :main ...)

15:48 bbloom: you've seen my singult todomvc, yeah? https://github.com/lynaghk/todoFRP/blob/master/todo/c2/src/cljs/todo/list.cljs

15:49 well, c2+singult.

15:49 (same thing; c2 uses singult under the hood)

15:49 bbloom: lynaghk: maybe a long time ago? :-)

15:49 lynaghk: bbloom: are these actually fn applications per tag? It seems like you should have a separate evaluator, not Clojure's

15:50 bbloom: lynaghk: yes, i need a separate evaluator

15:50 s/defn/defview/

15:50 lynaghk: okay.

15:50 bbloom: the definition of a view is basically `[~fn-name ~@args]

15:50 heh

15:50 lynaghk: I think namespaced keywords as tag names would work fine

15:50 yeah.

15:50 bbloom: yup

15:50 now, two interesting things:

15:51 1) i mixed event handling directly in there

15:51 which can be a bit ugly, but i haven't designed yet a more general aspect-oriented system for injecting concerns like that

15:51 lynaghk: aspect-oriented?

15:52 bbloom: yeah, so like if i want to have some bit of behavior that runs before the behavior of every button, i should be able to (defaspect :before ::widgets/button ...)

15:52 or something like that

15:52 which would let me separate arbitrary logic, rather than just separating event handling from rendering

15:52 i think for simple cases & non-abstract components, strict separation of concerns is a waste of time

15:52 sometimes, you really do have a ONE OFF component. hell, MOST of the time

15:53 in that case, it's fine to couple things & just do whatever works. you can always refactor & abstract/parameterize later

15:54 lynaghk: bbloom: I wonder if you could implement that using CSS-style selectors on the vDOM

15:54 vDOM = virtual DOM (or whatever you want to call the pile of vectors)

15:55 bbloom: lynaghk: yeah, that's the idea, but CSS has a lot of DOM-warts & it's both too flexible & not flexible enough for my needs. so i punted on that & just did the concrete, non-separated thing for now

15:55 1 step at a time :-)

15:55 now you wanna hear how events work? :-)

15:55 lynaghk: yes.

15:55 = )

15:55 bbloom: http://www.cs.unc.edu/~zhangh/technotes/shadow/onebigfig.jpg

15:55 ok so that's an example of how shadow mapping works in a 3d game

15:56 notice that the final image is produced by composing a texture from the camera's view & a texture from the light's view

15:56 there are two "renderers": the color view & the depth view

15:57 and there are two "observers" the camera & the light

15:57 conceptually, you evaluate the scene from both observer's views & with both renderers

15:57 in reality, you don't need the light's color view, only it's depth (notice no arrow from it) that's just there for illustration

15:57 you have some data set which represents all the things in your scene

15:58 and you have a "query" on that database

15:58 "give me all the things in the view frustum"

15:58 and you pass the results of that query to the renderer along with the observer as a parameter

15:59 similarly, i might query that database & say "give me all the things that intersect this line" or "give me all the flowers" or whatever

15:59 you can conceive of many queries

15:59 and many ways to process those queries

15:59 so one way to think of UI rendering is to think of it like a query on your view data structure "give me all my view objects"

16:00 you can encode that strictly as data or you can write an explicit traversal

16:00 and if you swap in a different "renderer" which is, more generally, a different "evaluator" then you can perform different tasks

16:00 so each traversal pass, i parameterize with a different evaluator: one for rendering & another one for event processing!

16:01 so when rendering, (clicked? :whatever) => false

16:01 but when event processing, it might return true

16:02 make sense?

16:03 ideas shamelessly stollen from here: http://mollyrocket.com/forums/viewforum.php?f=10

16:03 lynaghk: hmm

16:05 bbloom: hopefully i explained that clearly, it's kinda a heady idea

16:06 but notice how nice the resulting code looks :-) it's super terse & to the point

16:06 it will be *slow as hell* to start, but it's actually really straightforward to optimize b/c you can memoize/cache at pretty much any level

16:08 like for games, imagine nothing in the view of the spot light ever moves. you don't need to re-render the texture!

16:08 :-)

16:13 lynaghk: So in general the scenegraph for view rendering can be completely different than the event scenegraph

16:13 ?

16:20 dnolen: bbloom: yeah not yet convinced about traversal stuff, nor diff'ing stuff, nor how templates are traditionally handled - I've got some ideas I'm poking around with

16:20 bbloom: dnolen: looking forward to seeing your approach :-)

16:21 dnolen: tbaldridge: were you able to sort out the bug?

16:21 tbaldridge: yeah, it was a bug in close!

16:21 dnolen: tbaldridge: cool will give it a spin then

16:22 tbaldridge: dnolen: something breaks for me with advanced compilation, it's like MessageChannel is super slow in adv more. Perhaps if you hit that bug you can help me figure it out.

16:23 dnolen: tbaldridge: seems strange will poke around

16:25 zeitue: is there anything like codecademy for clojure?

16:28 callen: zeitue: that's a really good idea.

16:28 zeitue: 4clojure is pretty close.

16:28 zeitue: callen: that's what I was looking for cause I'm teaching a few the language

16:29 dnolen: tbaldridge: what are you running that looks slow?

16:29 tbaldridge: dnolen: https://gist.github.com/halgari/6323472

16:29 zeitue: thanks for the recommendation I've seen that though now sure on it callen:

16:30 dnolen: tbaldridge: is that what you added to the tests, I see you're timing something now?

16:30 tbaldridge: dnolen: In chrome that takes 3000ms to run in simple, with adv it takes ~1000ms to run, the first time, if I reload the page it takes 70000ms, and continues to be that slow until close the tab and load it up in a different tab

16:32 dnolen: yeah, I need to remove that from the tests, but yes, it's timing total time to put/take 1mil items from a (chan)

16:32 dnolen: tbaldridge: ok will try running tests in advanced

16:35 tbaldridge: I can't reproduce your problem, neither in Chrome nor Chrome Canary

16:35 tbaldridge: I can't believe that runs so quickly!

16:35 tbaldridge: dnolen: okay, I'm fine with that perhaps we're good then

16:39 dnolen: tbaldridge: Huzzah!

16:39 tbaldridge: dnolen: it's faster for you?

16:39 dnolen: tbaldridge: Node.js Go daisy chain benchmarks takes 732ms!

16:40 tbaldridge: dnolen: down from?

16:40 dnolen: tbaldridge: setImmediate alone by itself takes ~350ms

16:40 tbaldridge: 100000 calls to setImmediate, so we're adding just a little bit of overhead to that.

16:41 tbaldridge: dnolen: yeah, a ring benchmark is like the worst case for the new dispatcher. Assuming only one message is being passed around the ring.

16:43 callen: tbaldridge: is this supposed to be like the thread ring benchmark on the shootout?

16:43 dnolen: tbaldridge: it's about ~250ms improvement over old perf

16:43 tbaldridge: dnolen: eh, not too bad then.

16:46 callen: yeah, a ring benchmark is like a recursive fibonacci benchmark, all you're doing is benchmarking overhead that wouldn't be a problem in real life code.

16:47 dnolen: tbaldridge: there are still some boolean things but if you merge master I can patch that stuff up

16:47 tbaldridge: dnolen: kk, if you're not seeing any bugs then I'll merge.

16:48 dnolen: tbaldridge: lemme test my autocompleter real quick

16:49 tbaldridge: works like a charm, go for it

16:50 tbaldridge: done

16:50 and hey! 200 commits to core.async!

16:51 callen: tbaldridge: I know that. I was just asking if it was comparable to thread ring or not.

16:51 tbaldridge: callen: I'd imagine so, I haven't seen the code dnolen was running

16:52 callen: tbaldridge: do you guys squash commits for clean bisect in core.async?

16:52 (asking because of the 200 commits #, which sounds low to me)

16:52 dnolen: callen: it's basically a thread ring yes

16:52 callen: 100000 channels linked together, benchmarking put something in at one end reading it at the other.

16:52 tbaldridge: callen: no I haven't seen that done with this project

16:52 callen: dnolen: very cool. I've been using the ability to write things like core.async as a library, as a way to demonstrate the value of Clojure at work :)

16:53 tbaldridge: sounds like very few commits for a project of that scope. *takes a look*

16:53 * hugod wonders where clojure.repl/source gets injected into each namespace - in nrepl, nrepl.el or elsewhere

16:54 tbaldridge: callen: actually, I developed the go macro over a week in a different repo, so that does skew things a bit.

16:55 callen: tbaldridge: it's not totally clear to me who's responsible for what parts of core.async.

16:57 avishai: anybody here using appengine-magic?

16:57 tbaldridge: callen: Rich did the channels, and I wrote the IOC stuff, the rest of it was collaboration between Relevance people, Rich and dnolen.

17:00 callen: tbaldridge: thanks. Is there a good primer on getting into the headspace behind how it works somewhere?

17:01 srruby: I'm a Rubyist/former Java programmer looking for Clojure work. Any tips ? I'm glad that Lisp is getting more popular!

17:01 callen: srruby: contracting with clients that trust you to do what makes sense.

17:01 srruby: if you're in the bay area, there are companies that use Clojure.

17:02 srruby: callen: Thanks, and yes I'm in the bay area. I'm starting to send out resumes locally.

17:02 callen: srruby: you really should be working on stuff of your own accord though.

17:03 It's not really fair or reasonable to expect an employer to pay you to learn Clojure on the job.

17:03 gtrak: srruby: Joy of Clojure is worth the time/effort investment.

17:03 tbaldridge: callen: not that I'm aware of, the best thing I can point out to you now is to read both channels.cljs and async.cljs. Today I rewrote this CLJS code so it's a bit easier to understand. The thing is, you can cancel callbacks, so every callback has to have commit executed against, and that makes things a bit harder to understand.

17:04 srruby: callen: I am and getting pretty good at it. I'm porting one of my open source projects from Javascript to Clojure.

17:04 tbaldridge: callen: once you grasp that, think "now how would I do this with multiple threads", and then read channels.clj.

17:04 callen: rich spent a ton of time figuring out all the lock stuff on the JVM, and that's something I hope I never have to do.

17:04 callen: tbaldridge: I understand systems like core.async conceptually, it's the state machine rewriting that is more puzzling to me.

17:04 tbaldridge: ah

17:04 callen: oh, the lock stuff would be interesting too I suppose.

17:05 srruby: if you need something to hack on in Clojure, I've always got a long list of things on my open source to-do list.

17:05 tbaldridge: callen: have you seen this? http://hueypetersen.com/posts/2013/08/02/the-state-machines-of-core-async/

17:05 callen: I have now, thanks.

17:06 tbaldridge: callen: that goes through the output of the macro. For the actual guts I always suggest that people read this: http://en.wikipedia.org/wiki/Static_single_assignment_form and then just view the go macro as a micro compiler.

17:06 callen: I hope that helps a bit

17:07 srruby: callen: Could I see the list?

17:07 callen: tbaldridge: I knew SSA was involved. this should help tie everything together, thank you very much :)

17:10 srruby: https://www.refheap.com/17988

17:10 `cbp: wakie wakie, eggs-n-bakie.

17:11 duck1123: That's quite a list for someone learning clojure

17:12 callen: `cbp: this is the current to-do list: https://www.refheap.com/17988 are you still working on sync! for Pomegranate?

17:12 duck1123: he asked for my to-do list, not for a learner's primer.

17:12 duck1123: half the stuff on there is pretty doable for a new person anyway.

17:12 srruby: callen: Looks pretty daunting. I better finish my project first :)

17:13 callen: the only really tricky one might be proxy+

17:13 that might be horrific if not impossible. I don't really know. Depends on how usable the Annotation(Visitor/Writer).java stuff is.

17:20 `cbp: callen: hihi

17:20 callen: technically no because i've been extremely busy but I was hoping to do more this weekend

17:20 callen: `cbp: sounds awesome. Thanks :)

17:23 dnolen: tbaldridge: wow, thread ring in Chrome takes 200ms, same as Clojure

17:23 tbaldridge: nice!

17:23 callen: dnolen: n of what?

17:23 100k or 1mm?

17:24 dnolen: http://gist.github.com/swannodette/6323988

17:24 callen: 100k

17:24 tbaldridge: that is pretty amazing

17:25 tbaldridge: dnolen: I was hoping we could get to this point. There was a ton of crap in the channels that was multithread specific.

17:27 dnolen: tbaldridge: a lot of fun stuff I want to try now :)

17:31 bbloom: cool stuff guys!

17:35 shaungilchrist: well that was odd, not sure why but ioc_helpers.run_state_machine_wrapped stopped being added to compiled cljs. lein cljsbuild clean fixed it but it would be nice to know why

17:36 callen: shaungilchrist: I assume by default that anything involving cljsbuild (however very nice it is) involves vague gesturing and magic incantations :P

17:37 dnolen: shaungilchrist: probably stale stuff in your target directory, often happens if you pull in a new version of some lib

17:40 tbaldridge: I always do cljsbuild clean after an upgrade

17:40 callen: tbaldridge: that pattern/habit probably merits documenting.

17:40 tbaldridge: docs? what is this, ruby?

17:40 shaungilchrist: hahaha

17:41 callen: I'm documenting the cargo cult right now. Somebody else can confirm/repro.

17:41 shaungilchrist: the upside of it was walking through the core.async source and compiled output which was (seriously) a thing of beauty

17:42 callen: https://github.com/emezeske/lein-cljsbuild/pull/223

17:42 tbaldridge: I'm in Klishin's camp. Documentation uber alles.

17:43 tbaldridge: well yes I was being sarcastic

17:43 callen: I'm perpetually serious.

17:45 dnolen: tbaldridge: wow flame graph profiles, memory profiles for core.async are GORGEOUS now in chrome

17:45 bbloom: dnolen: screen cap? :-)

17:45 maybe even a before/after? :-P

17:46 dnolen: bbloom: haha, I'll put something together but my push 1 millions items in a range into a channel + read them out use to involve a incredible long tail before GC kicked

17:46 now it's like goddamn CLIFF

17:46 BOOM memory reclaimed

18:03 tbaldridge: you're queuing dispatcher is sweet :), I believe it's the reason we're seeing such good GC behavior

18:03 tbaldridge: I wonder why that is. I wouldn't have though it would have a impact on memory.

18:04 dnolen: BTW, we probably want to update the ring buffer at some point to set old slots to nil after they are popped, that should help the GC in some cases as well.

18:04 dnolen: unless you know of a reason why we shouldn't

18:05 dnolen: tbaldridge: no that sounds like a good idea to me

18:08 tbaldridge: I'm pretty it's because we don't pound the browser with dispatches now esp in the case of (chan), they aren't cheap

18:09 tbaldridge: ah yeah, I could see that

18:09 dnolen: tbaldridge: it used to take 16 seconds to do 1000000 events with (chan) in Chrome

18:09 tbaldridge: now 1.5seconds

18:09 tbaldridge: :-D

18:09 callen: good lord. what'd you change to create such an improvement?

18:09 shaungilchrist: wow that is awesome

18:10 tbaldridge: callen: rewrote channel from scratch, switched from arrays to a ring buffers, implemented a custom event queue. and a ton of CLJS magic

18:10 callen: very cool. :)

18:11 tbaldridge: I take it you've read about LMAX Disruptor?

18:11 futile: dnolen: whoa.

18:11 dnolen: tbaldridge: definitely blown away that (chan) is this efficient now

18:11 tbaldridge: callen: yeah, sadly it doesn't work at all for the JVM stuff, but we're using something like that in CLJS now. Of course there's only one thread in CLJS so it's basically a ring buffer at that point.

18:12 callen: That makes sense.

18:12 bbloom: i'm available any time you need me to just say the name of a data structure & then sit back & let you guys do all the work :-)

18:13 really, good stuff guys. thanks for being awesome w/ that stuff

18:37 clj_newb_2345: anyone know of a good resource for "Clojure Pedestal" for people whose IQs aren't 4 digits?

18:39 nDuff: clj_newb_2345: have you walked through the tutorial?

18:39 clj_newb_2345: it's several hours, but it's hours well-spent.

18:39 callen: clj_newb_2345: are you working on a complicated web application?

18:39 clj_newb_2345: or are you just trying to learn to do web dev in Clojure?

18:42 arkh: clj_newb_2345: in addition to the pedestal app-tutorial, samples and pedestal.io documentation (not in that order) I'd recommend https://github.com/taylorSando/pedestal-todo/blob/master/beginners.md

18:43 callen: clj_newb_2345: if you're just learning how to do web dev in general with Clojure, Pedestal isn't a very good fit. It's better for more experienced Clojure users making web apps that are complicated in a particular way.

18:44 ucb: callen: I'm sure you've seen https://github.com/drcode/webfui before. What do you think of it?

18:44 also hi!

18:46 callen: ucb: yeah I've seen webfui before. no opinions. Seems like a plausible way to do things.

18:46 ucb: hi! how are you?

18:46 I've mostly been learning more Datomic lately.

18:46 ucb: callen: good stuff, thanks. I'm well, how you?

18:47 callen: Very good, looking forward to testing Clojure/Datomic at work for a project.

18:47 ucb: nice

18:47 callen: Didn't take long at all to find an excuse. :)

18:47 ucb: datomic on the browser mayhaps?

18:47 callen: it does map nicely to the problem.

18:47 ucb: nah, this is backend stuff.

18:47 ucb: hammers and nails

18:47 callen: need to aggregate data from a bunch of different sources and have a traversable history of the universe.

18:47 ideally with efficient aggregations and relationships.

18:47 which datomic fits neatly.

18:48 ucb: nice

18:49 and having said that, zzz

18:53 agumonkey: hey clojurists

18:53 I just wrote a weird take-like function

18:54 taking overlapping frames of a list

18:54 (frame (range 6) 3)

18:54 ((0 1 2) (1 2 3) (2 3 4) (3 4 5))

18:54 is there a common name for this function ? I'm sure it exists already

18:55 hyPiRion: agumonkey: partition

18:55 agumonkey: partition do overlaps ?

18:55 hyPiRion: ,(partition (range 6) 3 1)

18:55 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

18:55 hyPiRion: br, wrong way

18:55 ChongLi: ,(partition 3 1 (range 6))

18:55 clojurebot: ((0 1 2) (1 2 3) (2 3 4) (3 4 5))

18:55 hyPiRion: ^

18:55 agumonkey: I'll be damned

18:55 thanks a ton of lots

18:55 tbaldridge: agumonkey: careful....

18:55 agumonkey: with the partitioning or the daming ?

18:55 tbaldridge: , (partition 3 1 (range 7))

18:55 clojurebot: ((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6))

18:56 tbaldridge: partition drops partial segments

18:56 , (partition-all 3 1 (range 7))

18:56 clojurebot: ((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) ...)

18:56 tbaldridge: bleh, I'm failing here

18:56 , (partition 2 (range 3))

18:56 clojurebot: ((0 1))

18:56 agumonkey: alright, that's what my unnecessary `frame` was doing anyway

18:56 tbaldridge: , (partition-all 2 (range 3))

18:56 clojurebot: ((0 1) (2))

18:57 tbaldridge: just be aware of the difference, I've lost some time on that oddity

18:57 hyPiRion: what tbaldridge means is that the last two partitions are removed (the (5 6) and (6)) when using partition

18:57 agumonkey: And I actually remember reading these partition* functions in dash.el emacs lib ... I can't even reuse prior lisp knowledge

18:57 hyPiRion: they are kept with partition-all

18:57 tbaldridge: hyPiRion: yeah, what he said

18:57 rasmusto: or with #(partition % 1 someseq)

18:58 that I happen to use a lot

18:59 magnars: agumonkey: partition and partition-all work the same in dash as in clojure - just that there is no optional step argument. There's a separate partition-in-steps and partition-all-in-steps instead.

19:04 agumonkey: magnars: hey, well then I don't know where I got this idea

19:05 magnars: is there a lot of clojure in dash ? or is it more mainstream/vintage lisp ideas ?

19:05 magnars: it borrows heavily from clojure

19:05 agumonkey: ok

19:15 clj_newb_2345: nDuff, callen: arkh: I've already played with ClojureScript / ring / moustache / enlive

19:15 this is basically "Pedestal, nothign else will do"

19:15 I like their model of updates

19:15 and how it updates the DOM

19:16 callen: clj_newb_2345: there is a Pedestal channel on FreeNode, might be a better resource than this one.

19:19 seangrov`: After tinkering for awhile, I'm ready to ask for help

19:20 I'm making a toy battleship implementation in cljs, and I would like to have multiple implementation of the board - a single array, and array of arrays, maybe something else

19:20 Is this a use case for defprotocol and deftype?

19:20 callen: seangrov`: single array being partitioned according to row/col?

19:20 seangrov`: callen: Yeah, by calculating the offset

19:21 callen: seangrov`: the protocol is the API for interacting with the boards, the deftypes are the boards themselves, no?

19:21 seangrov`: Whereas the second implementation would be [[row-1][row2]...]

19:21 Yeah

19:21 Trying to make sure my understanding isn't too far off here

19:25 `cbp: seangrov`: maybe a multimethod and your dispatch fn can tell what kind of board it is based on the structure?

19:27 * seangrov` googles multimethods vs protocols

19:27 llasram: Note to self: do not write macro-writing macros

19:28 I've apparently had a library with `(~~fname ...) for years where I really needed `(~'~fname ...)

19:28 `cbp: seangrov`: I would probably model it as a set of occupied coordinates + possibly a set of checked coordinates though.

19:29 seangrov`: `cbp: Yeah, I have one implementation that works just fine, but I would like to separate it form the e.g. rendering code that's going to be consuming it and the game logic that'll be interacting with it

19:38 eric_normand: anyone using liberator 0.9.0?

19:38 I have a question about responses.

19:54 clj_newb_2345: callen: ha, nice, thanks!

19:55 seangrov`: It seems like protocols lend themselves towards mutable state

19:55 I'm probably using them incorrectly though

19:56 bbloom: seangrov`: why do you feel that they lead you that way?

19:58 seangrov`: bbloom: I'll post the code in a bit and ask for some review, it's pretty small

20:04 callen: llasram: nice.

20:11 clj_newb_2345: is there any wrappers of the _git api_ as a clojure library?

20:11 actually, wait

20:11 if I want a database with git like "DAG" structure

20:11 if I want adatbase with "DAG" like forking / remembering of history, is Datomic what I want?

20:13 bbloom: clj_newb_2345: not really. Datomic is more like git with only a master branch, plus a fast query engine

20:13 a multi-master version of datomic w/ a different set of trade offs would be awesome for a different set of use cases, though

20:14 clj_newb_2345: bbloom: so "datomic", roughly, is "CVS + fast query engine"

20:14 or rather, it's a "line" with a fast query engine, not a DAG

20:14 bbloom: clj_newb_2345: well no b/c CVS stores diffs

20:15 clj_newb_2345: datomic works like git, but the only shared branch is master. you can have local, uncommitted branches

20:15 clj_newb_2345: doesn't datomic store diffs? how else does it story the history?

20:15 bbloom: git doesn't store diffs

20:15 how else does it store history? :-)

20:15 hiredman: (which is amazing, btw)

20:16 clj_newb_2345: how does git store history?

20:16 bbloom: clj_newb_2345: http://vimeo.com/14629850

20:16 clj_newb_2345: oh, git blobs

20:16 that's what the hashes are for, no?

20:16 bbloom: the hashes are version numbers b/c you can have multiple committed masters in a distributed manner

20:17 datomic just uses an incrementing number for the basis time (ie version number)

20:18 clj_newb_2345: first world problem: the video is too big to play nicely n my nexus 7

20:20 hiredman: I wonder if datomic does a cas like thing

20:21 bbloom: hiredman: my understanding is that it's strictly serialized

20:21 hiredman: the server may be multithreaded, but transactions go in to a queue & a single consumer processes them linearly

20:21 no need for cas then

20:21 hiredman: bbloom: ah, I mean content addressable storage, wrong cas

20:22 bbloom: oh haha

20:22 hm, yeah, i imagine it must right?

20:22 it stores large chunks of indexes in block storage

20:22 hiredman: I dunno

20:22 bbloom: what else would it call the blocks?

20:23 hiredman: actually I guess it must

20:23 bbloom: i mean it *could* name regions of the indexes & store those names

20:23 but seems like a waste

20:23 hiredman: dunno, makes sense, I was going to say "oh, I assume a cas would have to be based on hashing" and then thought "oh, right"

20:24 bbloom: hiredman: i bet you can find out quite easily if you set up a store & peek in it

20:24 maybe somebody here has a store set up that they can run a sub-datomic level query & see what keys they got in there:-)

20:24 hiredman: meh, seems like a lot of work

20:25 clj_newb_2345: besides datomic and fleetdb; are there any other databses implemented _in_ clojure?

20:25 i'm more curious in how implementations work rather than raw performance

20:36 callen: clj_newb_2345: https://github.com/ninjudd/jiraph sorta.

20:36 same pluggable backend type design as Datomic.

20:58 bbloom: dnolen: hey perf man. question for you

20:58 dnolen: bbloom: what's up?

20:58 bbloom: dnolen: any reason vector nodes don't have cached hash values? seems odd that (hash (conj v :x)) is always going to be linear

20:59 dnolen: bbloom: huh, no particular reason no - I'm surprised we don't cache the value.

20:59 muhoo: ~cas

20:59 clojurebot: Excuse me?

20:59 dnolen: bbloom: I'm also up for the incremental hash calculation that people have brought up

20:59 muhoo: what is cas?

20:59 callen: muhoo: compare and swap

20:59 muhoo: thx

20:59 bbloom: callen: except not above

20:59 muhoo: ~cas is compare and swap

20:59 clojurebot: 'Sea, mhuise.

21:00 bbloom: muhoo: it also means "content addressable storage"

21:00 which is what hiredman was talking about

21:00 muhoo: ~cas s compare and swap or content addressable storage

21:00 clojurebot: Huh?

21:00 muhoo: ~cas is compare and swap or content addressable storage

21:00 clojurebot: In Ordnung

21:00 muhoo: ~cas

21:00 clojurebot: cas is compare and swap or content addressable storage

21:00 callen: nice.

21:00 muhoo: (inc clojurebot)

21:00 lazybot: ⇒ 30

21:00 callen: (inc muhoo)

21:00 lazybot: ⇒ 1

21:00 bbloom: dnolen: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentVector.java#L140-L145

21:00 callen: asking questions is goooooood

21:00 bbloom: :-( sad

21:00 muhoo: ~frp

21:00 clojurebot: It's greek to me.

21:01 callen: muhoo: functional reactive programming

21:01 muhoo: ~frp is functional reactive programming, or fiberglass reinforced plastic

21:01 clojurebot: Alles klar

21:01 dnolen: bbloom: oh, you're asking about CLJ, yeah this would be nice enhancement no? :)

21:01 bbloom: dnolen: it's also true of cljs

21:01 callen: ~frp

21:01 clojurebot: frp is functional reactive programming, or fiberglass reinforced plastic

21:01 bbloom: dnolen: i checked both

21:01 muhoo: ~java logging

21:01 clojurebot: java logging is clown shoes

21:01 muhoo: :-)

21:01 callen: Perfekt.

21:01 dnolen: bbloom: ok you're asking about incremental hashing

21:01 muhoo: ok back to work for me

21:02 callen: I love it when people break servers dev environments depend on.

21:02 dnolen: bbloom: yes this is a good idea, up for a patch to CLJS

21:03 bbloom: dnolen: ok :-)

21:03 dnolen: bbloom: Mark Engelberg brought this up with respect to CLJ, probably just need to submit a patch and bug one of the core devs

21:08 bbloom: dnolen: ok thx. i dunno if i'll bother to patch it, but good to know i'm not crazy for wanting that

21:09 dnolen: bbloom: if you feel so inclined feel to free to open a ticket for it. Michal might take it.

21:09 bbloom: dnolen: on clj or cljs or both or what?

21:10 coventry: I just watched Stuart Halloway's Clojure Tips talk from earlier in the year, where he said that debugging facilities in clojure are lacking, but traditional debugging tools are probably not what's needed. Has he written anything about what's needed instead?

21:10 bbloom: dnolen: oh haha http://dev.clojure.org/jira/browse/CLJ-15

21:10 dnolen: apparently rich himself reported this in 2008

21:10 dnolen: bbloom: ok, yeah Christophe's point is interesting

21:11 bbloom: dnolen: i know that we do a mix of hash code caching strategies. sometimes caching on use w/ mutation, sometimes cashing on construction. is there any reason not to universally cache on construction?

21:11 dnolen: bbloom: how can you can cache lazy values? (maybe there's a fancy way?)

21:12 bbloom: dnolen: ignore christophe's comment for a moment, i'll return to that

21:12 dnolen: i mean for vectors, PAM, PHM, etc

21:13 dnolen: bbloom: for literals makes sense, not sure about anything else, would need to benchmark

21:13 bbloom: nice to avoid that cost until needed

21:13 bbloom: if you do it for conj you're probably good anyway

21:13 bbloom: dnolen: right, but pay a test against -1 later. not sure how that balances out in practice

21:14 dnolen: bbloom: so literals + conj covers most cases I think.

21:14 bbloom: not sure about assoc ..., nor pop, or stuff like that though?

21:14 bbloom: anyways fancy hashing tricks is outside my knowledge

21:14 bbloom: dnolen: nah, i think the mutation thing makes the most sense

21:15 anytime you do anything, you create new nodes w/ -1

21:15 dnolen: and then you just decorate all the interior nodes of the tree w/ that caching/hashing strategy

21:15 so if you conj, you get a -1 hash again, but you only need to walk the top level of the tree, and the modified branch

21:16 dnolen: bbloom: ok right, so this why not done, a lot of work for every data structure?

21:16 we have a lot

21:16 bbloom: dnolen: yeah, it's just a big change

21:16 seems like it could be a big win for some use cases tho

21:17 in particular, i've had to twist my code a little bit to avoid "changing" things

21:17 partly because of GC concerns, but more b/c equality gets slow again

21:17 hell, i'd really love to wrap every persistent structure in a mutable cell, then garbage collect and compact things :-)

21:20 dnolen: i ran in to an issue once where i had a largely redundant data structure (like the cljs namespaces atom) and printing/reading it used absurd amounts of memory

21:21 dnolen: would be super awesome if you could recover lost structural sharing

21:22 clj_newb_2345: if everything is value

21:22 can't you recover structural sharing by calculating the sha256 sum of every node

21:22 then having a hash table of those hashes ?

21:22 bbloom: clj_newb_2345: you can do something like that, but the particular approach would be a bit different in order to perform well

21:23 clj_newb_2345: bbloom: indeed, on every object construction, looking up "does this hash exist" is probably a bit too much

21:24 bbloom: dnolen: oh, i realized why incremental hashing is a bit tricky: you need a hash algorithm that will compose correctly. if you have PAM and PHM interior nodes w/ non composing hash functions, then you wouldn't be able to do proper cross-implementation comparisons

21:24 clj_newb_2345: there are systems that do that: http://www.meta-environment.org/Meta-Environment/ATerms

21:24 clj_newb_2345: but not ideal, i think

21:25 clj_newb_2345: though given CLojure's meta data support, this is tempting

21:25 this also does make sense to go into the gc layer

21:25 the gc has to touch all the objects anyway; so while there, why not look for structural sharing

21:25 dnolen: bbloom: it just sounded tricky to me period, but OK

21:26 bbloom: dnolen: you need an associative hash function

21:26 clj_newb_2345: there is the downside that this requires all "hashed" objects to be immutable; since changing object -> changing hash -> might have to change a chain of hashes

21:26 bbloom: after that, i think it's relatively straightforward

21:26 clj_newb_2345: i consider that an advantage :-)

21:27 clj_newb_2345: I like immutable too

21:27 but occasionally, I like mutability

21:27 i.e. why I use clojure rather than, say Haskell

21:32 callen: 90% of the time I've seen somebody say they needed mutability or mutable global state for something, they haven't.

21:32 but the 10% is still there.

21:33 bbloom: see also http://en.wikipedia.org/wiki/Hash_consing

21:54 ddellacosta: good morning

22:01 callen: ddellacosta: morning.

22:01 ddellacosta: callen: morning, how goes it?

22:01 er, evening? I guess

22:02 I SEND YOU GREETINGS FROM THE FUTURE

22:02 seangrov`: ugt

22:02 ~ugt

22:02 clojurebot: ugt is Universal Greeting Time: http://www.total-knowledge.com/~ilya/mips/ugt.html

22:04 mmarczyk: dnolen: bbloom: re: incremental hashing, cgrand's comment on CLJ-15 about needing to force lazy seqs placed in vectors or maps applies; if that's unacceptable in general, something like Mark Engelberg's wrapper (in instaparse) can be used where it is; anyway, I've wanted incremental hashing of all PDSs for a while now and I'm totally up for implementing it in whichever fashion (and before that, spending time to figure out a

22:04 "cancellable" hash combiner)

22:04 ddellacosta: seangrov`: that's awesome, didn't know about that. I guess I was right in the first place.

22:05 bbloom: mmarczyk: aah now i understand his comment

22:05 hmmm

22:05 yeah, that is a pickle

22:05 mmarczyk: finishing sentence above, that's right after I finish my current secret PDS impl project, which I'm hoping will be of use to certain implementers of pretty printing libraries :-)

22:06 it is, unfortunately

22:06 bbloom: mmarczyk: :-D

22:06 mmarczyk: :-)

22:06 it is, unfortunately

22:06 for example it means no infinite seqs in vectors

22:07 bbloom: mmarczyk: yeaaah… i've always been kinda conflicted about how vectors & seqs work w/ respect to equality

22:07 mmarczyk: of course if anybody ends up hashing a vector with lazy stuff inside they'll force it anyway, but apparently often enough that doesn't happen

22:07 bbloom: mmarczyk: it's convenient as hell that seqs = vectors

22:07 but also kinda strange & wrong feeling

22:08 mmarczyk: notably split-at / split-with couldn't possibly work the way they do now

22:08 bbloom: yeah, it's kinda this weird compromise

22:09 lazy seqs are not always "values"

22:09 in fact, they are explicitly non-values, since they contain thunks

22:09 mmarczyk: yes, Clojure's notion of equality is a bit funny

22:09 well, I don't know if the fact there's a thunk inside makes it a non-value

22:10 but the potential infinity sort of sounds like a it's on the co- side of the relevant foo / cofoo divide :-P

22:10 ddellacosta: Is there any benefit to (or even any method for) using austin over piggieback if you are connecting to an already-started-app from an already started repl, the two being in different threads (that is, in contrast to the default example in the austin docs for connecting to an app)?

22:10 bbloom: mmarczyk: heh yeah

22:10 ddellacosta: cemerick is the man to ask

22:11 ddellacosta: bbloom: true, thanks

22:11 figured I'd throw it out there though, in case anyone else had an idea

22:12 cemerick: ddellacosta: didn't you just describe the "browser-connected REPL" use case, described in the README (vs. the "project REPL")?

22:13 (all this nomenclature needs serious work) :-P

22:13 mmarczyk: bbloom: thanks for the anf link btw, love the function names :-) I'll read it properly this weekend, along with the Flanagan et al paper hopefully

22:13 bbloom: mmarczyk: my pleasure! i haven't read the flanagan stuff at all :-/

22:14 ddellacosta: cemerick: um, yes, exactly--the big difference between your example and my use-case being that I have a script which starts up my app

22:15 mmarczyk: bbloom: re: lazy seqs, we'd have to give up value-based equality completely, not just equality with vectors, to avoid forcing to hash, which I guess is a complete no-go given the pervasive hidden (as in not explicitly asked for) laziness in the seq library

22:15 cemerick: ddellacosta: well, cljs' stock browser-REPL has a number of limitations that I used to hit regularly. Can't run multiple REPLs out of the same backend, need to shuffle port numbers around frequently, :cljs/quit shuts down the HTTP server until the next REPL session is created, etc.

22:15 ddellacosta: cemerick: and as far as what I've been able to figure out, it seems like I need to be running in the same thread to get the nrepl configuration working right, in terms of how values are set and where they are accessible. So I wondered if there was any value in it, since the default piggieback config is working pretty damn well (did you make that more robust? Haven't dug into the code yet).

22:16 cemerick: ddellacosta: not sure what you mean re: in the same thread?

22:16 bbloom: mmarczyk: yeah, i think it's past the point of no return. there isn't any way to solve this problem (that i can think of) that wouldn't involve dramatic sweeping changes to how laziness & evaluation works

22:16 dnolen: wow after core.async, the Promise/Rx dichotomy is JS is truly painful

22:16 s/is/in

22:16 bbloom: dnolen: i believe you, but i'm curious what motivated you to say that

22:17 mmarczyk: dnolen: you mean core.async is a sort of a de-numbing agent? :-P

22:17 ddellacosta: cemerick: so, it's entirely likely I'm confused about something. But the example you have for the browser-connected repl assumes you are starting your app from the repl, so you have access to the loaded namespaces/values in that repl

22:17 dnolen: bbloom: I was just toying around with some benchmarks between core.async and when.js one of the fastest Promises/A+ libraries

22:17 bbloom: and realizing so many of the things I've done are nearly impossible to express in terms of Promises.

22:18 and how wasteful Promises are, it's a one off

22:18 bbloom: dnolen: yeah, i found that you needed a pretty large promise library for common patterns. things that are pretty easy with multiplexing

22:19 dnolen: when i had no choice but to do js/coffee, i preferred async.js (which is callback combinator functions)

22:19 cemerick: ddellacosta: that's just the simple base case, where the REPL server port and session number are in-process, and so can be super-easily templated into your app

22:19 bbloom: it was basically the same as promises, but without the refied objects & with saner error handling semantics

22:19 cemerick: Nothing there is thread-related, tho.

22:19 seangrov`: ,(take 5 (iterate 10))

22:19 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$iterate>

22:20 seangrov`: ,(take 5 (iterate inc 10))

22:20 clojurebot: (10 11 12 13 14)

22:22 ddellacosta: cemerick: hmm, okay, I must be getting confused. To try to explain more completely, following the example for the browser-connected repl, when I call browser-connected-repl-js from cemerick.austin.repls in my routing, I get nil. I thought this was because I wasn't setting cemerick.austin.repls/browser-repl-env from within the same thread--my loaded ring app was not started via repl.

22:22 cemerick: ddellacosta: Just FWIW, if what you're doing now is working, carry on :-) Austin is by no means intended to be a the end-all-be-all of cljs REPLs.

22:23 ddellacosta: cemerick: oh, no--I just wanted to see if I wasn't mistaken about the use case! piggieback is definitely working, but I want to explore all the options so I can figure out what is possible, and also try to help if I can provide another way to smoothly get more use-cases working for the CLJS eco-system.

22:24 ToBeReplaced: cemerick: is there progress on strint/<< making it into core?

22:24 ddellacosta: cemerick: I figure, the more I am doing some yak-shaving to get my specific way of working going, if I can even just contribute some feedback and docs it will be useful to everyone.

22:24 cemerick: ddellacosta: if b-c-r-js is returning nil, then you haven't set the cemerick.austin.repls/browser-repl-env atom yet/properly

22:25 definitely nothing thread-related there

22:26 ToBeReplaced: Nope, not going to happen. I've been meaning to start distributing it in its own library, since right now it's basically marooned in incubator

22:28 ToBeReplaced: cemerick: is there discussion somewhere? anything going to happen in its place?

22:28 ddellacosta: cemerick: right, but it seems like, based in the example, it is assumed that you load repl-env in your running app from the same thread that you connect your repl, and therefore they have access to the same values. Because browser-repl-env is an thread-specific atom, if you don't start your app from the same thread you've set cemerick.austin.repls/browser-repl-env in, you can't access it when generating a script

22:28 in the app. Does that make sense, or am I totally off?

22:30 cemerick: argh, wait, I'm realizing the flaw in what I'm saying, hold on

22:30 cemerick: ToBeReplaced: The last discussion of string interpolation being in core was here in irc years ago. I would be very surprised if something like it ever landed in core.

22:30 ddellacosta: yeah, you're thinking of vars and binding

22:30 ddellacosta: cemerick: yes, not atoms. D'oh. Sorry for the confusion!

22:30 ToBeReplaced: cemerick: thanks

22:33 cemerick: ddellacosta: gots to run. Ping later if you're still having issues :-)

22:33 ddellacosta: cemerick: thanks for being my sounding-board so as to let me talk myself into figuring out my mistake…haha. Thanks, cheers! I think I'm good for now. ;-)

22:49 seangrov`: Should ISeqable be extended to [object NodeList]?

22:58 dnolen: seangrov`: don't do it. just pass array likes into prim-seq

23:02 seangrov`: dnolen: Ah, that works nicely, thanks

23:08 dnolen: seangrov`: yeah it's just too easy to miss something, prim-seq covers the bases

23:08 cgag: anyone seen "peerUri undefined" when trying to connect the clojuresript browser repl?

23:08 dnolen: cgag: you cannot use file:// protocol, are you going to localhost:9000/foo.html ?

23:09 cgag: i am

23:13 https://www.refheap.com/17991

23:13 basically all i have

23:13 the alert goes off

23:13 the first one at least

23:14 dnolen: quick post on latest core.async perf enhancements http://swannodette.github.io/2013/08/23/make-no-promises/

23:30 cgag: sounds like you're not specifying a version of ClojureScript in your project.clj

23:31 cgag: i just have lein-cljsbuild 0.3.2 and have been using that

23:37 it does seem to have generated a repl/clojure/browser folder

23:37 dnolen: cgag: specify a version, you can never trust what cljsbuild pulls in

23:37 cgag: i wonder if this is making some invalid assumptions about my directory structure

23:37 dnolen: cgag: 1859 is the latest

23:43 shaungilchrist: dnolen: awesome article noticed a typo in last sentence though - extra "the" after "providing"

23:44 dnolen: shaungilchrist: thx

23:44 shaungilchrist: your blog is a beacon of hope in a sea of callbacks

23:48 Apage43: i..

23:48 man.

23:50 cgag: dnolen: no dice :\

23:55 my project file: http://pastebin.com/TiVVmDSB

Logging service provided by n01se.net