#clojure log - Dec 05 2013

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

0:00 sm0ke: it seems i have to convert it to (foo ClassName. (into-array Object ["aa" "bb"]))

0:00 murtaza52: I have multiple keys on my system now, which gpg key does it use ?

0:01 sm0ke: wtf! how do people write interop!!

0:01 arrdem: sm0ke: yeah the 2nd one is fine, what of it?

0:01 sm0ke: oh i meant .foo

0:01 arrdem: why do i have to call it like that?

0:02 arrdem: sm0ke: because your java function is vardic, which really means that Java internally builds an array for one "real" argument.

0:03 sm0ke: hmm this has come down to compiler internals i see

0:04 arrdem: sm0ke: ... yeah you're trying to do interop. that's gonna happen.

0:04 sorry there isn't much we can do to clean it up :/

0:05 sm0ke: hmm its weird that clojure allown (doseq) on primitive arrays oob

0:05 technomancy: murtaza52: yes, your password is wrong.

0:05 sm0ke: but refuses to support varargs synactic suagr

0:05 technomancy: which key is chosen is up to gpg; `lein help gpg` might explain that, but it's not causing this failure

0:06 arrdem: sm0ke: see compier internals. raw arrays are ISeq, that totally works. Java built your method to a silly signature, not our fault.

0:07 or rather you gave your method a silly signature and javac did as it was bid

0:09 sm0ke: raw arrays are ISeq

0:09 what else i Iseq

0:09 is Collection ISeq too?

0:09 What i Iseq anyway

0:10 amalloy: raw arrays are not ISeq. that would be impossible

0:10 sm0ke: What!

0:10 you ust said they were

0:10 amalloy: they're seqable, but the compiler can't add new interfaces to them

0:10 arrdem: amalloy: thanks for the correction.

0:10 sm0ke: oh similar names

0:10 arrdem: amalloy: I was just thinking that would be pretty similar

0:10 *silly

0:11 amalloy: well, it would be great, it's just impossible

0:11 murtaza52: technomancy: which password my gpg or clojars ?

0:11 sm0ke: i guess ISeq must be something which supports cons

0:13 Wouldnt it had make sense if we had [

0:13 sorry

0:13 [String & Object] as valid def in gen-class

0:14 murtaza52: technomancy: I am signing in clojars using the same user/pass and it is working. I am also able to successfully enter my passphrase for both my ssh and gpg. So which one could be wrong ?

0:16 I created a new gpg key, updated it on clojars, and specified it in my profiles.clj. Its using it, but still failing.

0:16 sm0ke: or may be we can have simply 'varargs' aliased to "[Ljava.lang.Object;"

0:16 we do have 'void'

0:16 murtaza52: How can I debug which password is causing the problem ?

0:18 technomancy: when I enter a wrong password for clojars I get this error - ReasonPhrase: Unauthorized.

0:19 The one I am getting right now is ReasonPhrase: Forbidden.

0:19 sm0ke: anyhow, i see its unecessary, if i am trying to support java methods with varargs i can write a java class with varargs in my clojure project and have varargs convert to Collections

0:20 logic_prog: I'm using clojurescript repl. Web server is localhost:3000, clojurescript brepl server is localhost:3002. Is there anyway to tell chrome "dude, allow localhost:3002's iframe to access localhost:3000's page" ?

0:20 sm0ke: fking synactic sugar for imperative langs are nothing but nuisance

0:21 logic_prog: sm0ke: except for APL, where the syntax is the language

0:21 sm0ke: logic_prog: access-control-allow-origin: * ?

0:21 logic_prog: sm0ke: interesting, reading http://stackoverflow.com/questions/5008944/how-to-add-an-access-control-allow-origin-header now

0:22 SegFaultAX: Don't use *

0:22 Be explicit about what hosts you care to respond to.

0:22 sm0ke: yep you can use comma seperate domains

0:36 logic_prog: :headers {"Content-Type" "text/html; charset=utf-8" "Access-Control-Allow-Origin" "http://localhost:3002/"}

0:36 is that basically what I want in my compojure/ring response?

0:37 sm0ke: logic_prog: well you can try

0:38 logic_prog: did you say you were trying open 3002 as iframe in 3000?

0:38 logic_prog: sm0ke: trying

0:38 sm0ke: hmm actually, you dont need cross origing for iframe :P

0:38 if i am not wrong

0:38 what error were you getting

0:39 can you hit ctrl-shift-j to inspect?

0:41 logic_prog: i'm using chrome, not firefox

0:41 at the moment, I can't even (js/alert ...) anymore, so I must have broken something

0:41 sm0ke: ctrl-shift-j works in chrome too

0:42 logic_prog: alright

0:42 I have the developer console

0:43 elements / resources / network / sources / timeline / profiles / audits/ console

0:43 where do I check for the http headers?

0:44 sm0ke: on network

0:44 click the request for which you want to see headers

0:44 wth.. can you first tell what the error is under console?

0:45 logic_prog: Access-Control-Allow-Origin:http://localhost:3002 <-- I see this in one of the two

0:45 sure

0:45 let me restart few things, many things just broke

0:46 danenania: is there an idiomatic way to take a sequence of symbols like (symbol1 symbol2 symbol3) and turn it into a hash-map like {:symbol1 symbol1 :symbol2 symbol2 :symbol3 symbol3}

0:46 without writing out the keys?

0:46 logic_prog: (into {} (map #(vector (keyword %) %) ... )) ?

0:47 rasmusto: are they quoted symbols?

0:47 arrdem: ,(into {} ((juxt (comp name keyword) identity) ['x 'y 'z]))

0:47 clojurebot: #<NullPointerException java.lang.NullPointerException>

0:48 danenania: ok, will have to define my own i think

0:48 rasmusto: arrdem: missing a map?

0:48 arrdem: we should have a clojurebot shootout night... who can quickdraw the most map/filter/juxt/into solutions :P

0:49 rasmusto: lil bit

0:49 I'd loose but it'd be fun

0:49 sm0ke: ,(into {} (map #(vector (keyword %) %) '(a b c)))

0:49 clojurebot: {:a a, :b b, :c c}

0:49 sm0ke: logic_prog: well done

0:49 rasmusto: ,(into {} (map (juxt keyword identity) ['x 'y 'z]))

0:49 clojurebot: {:x x, :y y, :z z}

0:49 danenania: nope, not quoted

0:49 just find myself assembling hash-maps like that alot for keyword argument passing

0:49 logic_prog: sm0ke: if only cljs was as easy, lol

0:50 rasmusto: danenania: I build up maps like that manaually for the most part

0:50 arrdem: danenania: there's (let [{:keys [foo bar baz]} ...] ... )

0:50 rasmusto: and I save space by destructuring them afterwards using {:keys [a b c]}

0:50 sm0ke: guys i dont seem to be able to call https://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging.clj#L70 like (log "namespace" :info "something")

0:51 what does the logger-ns accepts?

0:51 danenania: rasumusto: yeah that's what i've been doing as well... just getting greedy and trying to save a few more keystrokes :)

0:51 sm0ke: i mean what is logger-ns , it surely is not a string

0:52 rasmusto: danenania: actually, I think I tried to write a macro or something to do it and it got really confusing. You should avoid quoted symbols IMO

0:54 danenania: yeah probably not worth it

0:58 logic_prog: sm0ke: cljs.user> js/parent "Error evaluating:" js/parent :as "" #<SecurityError: Blocked a frame with origin "http://localhost:3002" from accessing a cross-origin frame.> Error: Blocked a frame with origin "http://localhost:3002" from accessing a cross-origin frame.

0:58 https://gist.github.com/anonymous/7800751

1:01 sm0ke: logic_prog: can you try plain * for header

1:01 specific domain can be reworked later

1:04 danenania: here's what i ended up with:

1:04 (defn identity-map [syms] (into {} (map #(vector (keyword %) (eval %)) syms)))

1:04 logic_prog: sm0ke let me try

1:06 rasmusto: danenania: looks good, the only thing now is you have to manage a collection of quoted symbols :)

1:07 danenania: rasmusto: well assuming they're in context, i can just do (identity-map '(a b c))

1:07 not too bad

1:08 rasmusto: danenania: but that quote!

1:08 danenania: haha, can't have everything i suppose

1:09 arrdem: rasmusto: he could use a macro...

1:09 * arrdem ducks

1:09 rasmusto: yeah, I guess the macro would let you drop the quote

1:11 glosoli: Running into some weird problems with Enlive https://www.refheap.com/0788fd13a47504aa9f7593bed it does not seem to be able to select :script element by my custom :data-defer attribute, though if I rename that attr to class and check for some class name it works

1:11 Any ideas ?

1:16 sm0ke: wtf, https://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging/impl.clj#L161 logger-ns has to be a string

1:16 ugh, clojure stack trace fail again

1:16 i get this for an error => (log/log "ns" :info "ddddddd")

1:16 IllegalArgumentException ns clojure.tools.logging/eval130/fn--131 (misc.clj:6)

1:19 logic_prog: sm0ke: hmm, still same error, even with Access-Control-Allow-Origin: *

1:23 sm0ke: logic_prog: can you try some other browsers too?

1:43 kristof: Are common lisp channels mutable data structures?

1:44 And are the reading and writing operations on them destructive?

1:49 andyf: kristof: Do you mean the Common Lisp library called ChanL? I wasn't aware that the Common Lisp standard had something called channels.

1:51 bitemyapp: andyf: https://github.com/sykopomp/chanl

1:51 oh, yes, sorry

1:51 well now eother people can look at it.

1:51 kristof: andyf: I'm sorry, I actually meant Clojure channels in core.async

1:52 andyf: I'm secretly planning to port some of that juicy stuff over to CL but if I declare anything now it should be considered vaporware.

1:53 andyf: kristof: I am no authority on the matter, but I have a hard time imagining a sense in which a core.async channel could be considered an immutable data structure.

1:54 kristof: Seems sort of counter to Clojure philosophy to have something that can be bashed upon so easily

1:54 noprompt: went to update npm with npm update -g npm. it failed and now i don't have npm anymore.

1:54 the javascript life story right there.

1:54 kristof: andyf: But I was reading some of swannodette's (sp?) blog posts and it was pure magic.

1:54 andyf: kristof: Clojure is not Haskell

1:54 kristof: Oh, I'm certainly aware

1:55 But Clojure still tries to make bashing atomic and guaranteed, with STM

1:55 andyf: Mutability is embraced, when needed, or just plain old useful

1:55 kristof: at least when it's a shared resource

1:55 and atoms and actors are not meant to be shared resources so they do not count

1:55 andyf: How are atoms not meant to be shared resources?

1:56 kristof: Not meant to be modified by a lot of different things, I suppose

1:56 noprompt: kristof: the clojure focus is power, simplicity, and focus; how do channels/atoms and their usage conflict with that philosophy?

1:57 *the clojure philosophy

1:58 kristof: noprompt: Atoms *don't*, channels seem to. Atoms are not meant to be coordinated with...

1:58 well, I suppose data in channels don't, either, do they?

1:58 noprompt: kristof: nope. :)

1:58 kristof: noprompt: See, I was looking at channels like an unsafe kind of ref

1:59 noprompt: kristof: how are they unsafe?

1:59 kristof: unsafe in the sense that stuff can pop things off of the queue and put them on whenever, however

1:59 noprompt: that's the whole point.

2:00 kristof: Of course! I understood that, but it felt kind of weird because I was thinking of stm too much

2:00 But there's no coordination in channel usage, unlike in stm usage; in fact, THAT'S the whole point

2:00 "just do whatever, whenever"

2:00 noprompt: and it's not if i'm my code is suddenly going to start putting dog food on my channels.

2:00 kristof: right

2:01 I'm still slightly bedazzled by core.async, especially after having used javascript and thinking in terms of block block block

2:01 noprompt: on the client side i have no beef with core.async. i'll take dog food on channel over callbacks any day of the week.

2:01 * rasmusto is getting hungry

2:02 noprompt: kristof: yes core.async is *very* nice client side.

2:04 kristof: noprompt: And what about futures? They've enamored some people.

2:04 But not swannodette.

2:04 noprompt: kristof: futures are cool server side. i made heavy use of them with a huge database migration i had to do earlier this year.

2:05 kristof: nowadays i'd probably use core.async.

2:07 so far 2 out of the 3 node based cli apps have had some sort of wacky design flaw.

2:08 kristof: noprompt: What's the disadvantage of using a future over a go block?

2:09 noprompt: kristof: i don't know.

2:09 kristof: Hm. Alright.

2:09 noprompt: Eventually I'm going to need to find out how the different coroutines are multiplexed onto one thread. That might be... fun? :/

2:10 noprompt: kristof: you don't have to add a dependency on core.asyn in your project.clj i guess? i'm sure there's a better answer.

2:10 kristof: sounds like it might be. i'm pretty much hands off in that area.

2:10 kristof: i'm one of the "stayed for the data structures" guys.

2:11 kristof: Can't remember who said that

2:11 Maybe it was in a hickey talk?

2:11 noprompt: well that and having to put up with a minimum amount of bullshit from a programming language.

2:11 i've used clojure for a year solid now and still the only thing that bugs me is stack traces.

2:11 everything else is pretty nice.

2:18 getting sick is stupid.

2:19 who came up with that idea?

2:19 arohner: bitemyapp: sorry, I missed what you said

2:19 the irc client popped something up, but I disconnected & reconnected, or something

2:25 bitemyapp: arohner: oh I've wanted to do the same thing you wanted, I called it "draining" channels. Anyway, just wanted to know if the "repeatedly" solution guns recommended worked for you.

2:26 * arohner figures out where his IRC logs are going

2:26 bitemyapp: arohner: you wanted to get multiple items from a channel.

2:26 arohner: right. what did you suggest w/ repeatedly?

2:26 bitemyapp: a discrete number perhaps.

2:27 15:48 < gfredericks> would also be easy given a (defn ch->seq [ch] (->> (repeatedly #(async/<!! ch)) (take-while (complement nil?)))

2:27 blocking take looks like.

2:27 arohner: cool, I'll try that

2:27 ty

2:29 bitemyapp: arohner: guns provided an initial naive solution, gfredericks refined it.

2:31 jph-: newbie question - how do i select-keys on a list of maps?

2:32 i see filter, and select-keys, but how would i use them together?

2:32 rasmusto: jph-: make a function that uses select-keys

2:32 jph-: what args would it take?

2:33 the function

2:33 rasmusto: (map #(select-keys % [:a :b :c]) my-list-of-maps)

2:33 jph-: just one, the map that you're pulling keys out of

2:33 jph-: lemme try that on for size

2:33 rasmusto: jph-: check the argument order, I can't remember if the map or the keyseq comes first

2:34 jph-: that works

2:34 how would i filter based on key val?

2:34 ie (= val something)

2:34 bitemyapp: arohner: you really need a persistent IRC session that you can rejoin

2:35 arohner: meh. http://clojure-log.n01se.net/ is usually good enough

2:35 for some reason the logs cut off today though

2:35 bitemyapp: fair.

2:35 rasmusto: you can just use (filter #(= (:a %) val) coll)

2:35 Raynes: logs.lazybot.org

2:35 arohner: I really don't have the time to mess with irc sessions these days

2:36 rasmusto: jph-: you don't necessarily need the select-keys in this case, or you could do if after if you really want to cut the other ones out

2:36 jph-: rasmusto: you're my hero

2:36 cheers

2:36 im just learning all the ways to use these functions together

2:36 arohner: Raynes: cool!

2:36 jph-: rasmusto: thank you for help

2:36 Raynes: This log viewer is built-in to lazybot courtesy of aphyr (Kyle Kingsbury of Jepsen fame).

2:37 rasmusto: jph-: destructuring would be cool too: (filter (fn [{:keys [a b]}] (= [a b] [vala valb])) coll)

2:37 noprompt: (inc bbloom)

2:37 lazybot: ⇒ 19

2:37 jph-: rasmusto: i'll write that down and see what it does

2:37 is that to filter out

2:37 ?

2:37 or just another approach to filtering based on val?

2:38 rasmusto: destructuring can be applied anywhere you take a collection as a function argument or let binding, it works in this case becasue you are filtering a collection of maps

2:41 jph-: is there a repl trick to automatically (use) something on repl start?

2:41 in my lein config maybe?

2:42 nm i think ive found it

2:44 dbusnenko: yes

2:45 did you read "Worflow reloaded" by Sierra?

2:45 he describes that

2:46 noprompt: jph-: you can create are user.clj file in something like a ./dev folder and add that to your [:profiles :dev :source-paths]

2:46 jph-: i just want to avoid having to (use) on repl startup

2:46 for some common libs i load

2:46 i can put deps in ~/.lein/profiles.clj

3:05 logic_prog_: is there a linux tool that can merge the outputs of two stdouts? for example, I'd like a single window to contain the output of "lein cljsbuild auto" and "lein run main" -- both of them dump output messages, and I want both stdouts/stderrs to be in the same window (rather than take up two separte windows)

3:09 amalloy: logic_prog: cat

3:09 or tail, i suppose, if you want them interleaved

3:09 logic_prog_: doesn't cat only handle files?

3:09 amalloy: everything is a file

3:10 $ tail -f <(lein foo) <(lein bar)

3:10 $ tail -f <(lein foo 2>&1) <(lein bar 2>&1) ## since you want stderr as well

3:10 logic_prog_: no fucking way

3:10 this is balck magic

3:11 amalloy: logic_prog_: worked?

3:12 logic_prog_: not in zsh

3:12 trying bash

3:12 Raynes: But the prompts!

3:15 amalloy: tail -fq, if you want to suppress the fairly-useless headers

3:16 logic_prog_: this is weird

3:16 tail -f (ls 2>&1) works

3:16 sm0ke: wtf i ahve :aot on a ns and also :gen-class in the definition still no class is getting generated on lein compile

3:16 logic_prog_: but tail -f (lein cljsbuild once 2>&1) just hangs

3:16 amalloy: you forgot the <

3:17 logic_prog_: amalloy: you are right

3:19 sm0ke: wtf in lein :pre-tasks has to be [["compile"] "javac"] instead of ["compile" "javac"]

3:45 hiteki: hi there

3:48 ucb: hey hiteki

4:50 bitemyapp: http://alexott.net/en/fp/books/

4:53 ucb: bitemyapp: !

4:53 bitemyapp: ucb: about to sleep, anything before I go?

4:54 ucb: http://russiancircles.bandcamp.com/album/memorial

4:54 ucb: bitemyapp: nothing, just hi and good night :)

4:54 * ucb listens

4:54 bitemyapp: ucb: hi, good night. Let me know how you like the new Russian Circles album

4:54 ucb: will do

4:54 bitemyapp: ucb: check out those FP books, it's a fantastic list.

4:54 one of the best I've found.

4:54 ucb: yeah, reading

4:56 jarodzz: ,(+ 1 1)

4:56 clojurebot: 2

5:19 xificurC: I just installed cider on emacs via el-get and when I try to run it I get `cannot open load file: nrepl/cider', any ideas whats wrong?

5:20 I see the folder ~/.emacs.d/el-get/nrepl/ and I have cider.el as well as cider.elc

5:22 logic_prog_: with optimizations: none, how do I get goog.base installed?

5:22 in cljs, when building with optimiations: advanced or optimizations: whitespace, the necessary goog closure files are compiled in

5:23 with optimiations: none, I appear to need to somehow provide the goog.closure libraries

5:23 where do I get those libraries?

5:41 bozhidar: brainproxy: btw, I'm prelude's author. Glad to hear you like it :-)

5:45 I got a bit late to participate in the smartparens/paredit discussion, though. Maybe next time...

6:02 Fender: A new day, a new question. Today:

6:02 , (hash #"asd")

6:02 clojurebot: 30128182

6:02 Fender: (hash #"asd")

6:02 , (hash #"asd")

6:02 clojurebot: 12613946

6:02 amalloy: regexes don't have meaningful hashes or equality comparisons

6:02 Fender: :(

6:02 amalloy: yeah, bummer, i know

6:03 blame java

6:03 Fender: hehe

6:03 so to use regex in hashmaps, I'd ahve to instantiate exactly one regex and always refer to it indirectly

6:04 amalloy: or use its string representation as the key instead

6:04 hyPiRion: blame java on regex equality? Wat.

6:04 Fender: hmmm, is there a way to obtain the string from a regex?

6:05 or do I have to re-pattern every string?

6:05 amalloy: &(str #"foo")

6:05 lazybot: ⇒ "foo"

6:05 amalloy: &(str #"foo\*")

6:05 lazybot: ⇒ "foo\\*"

6:05 hyPiRion: ,(.toString #"foo\*")

6:05 clojurebot: "foo\\*"

6:05 amalloy: .toString? heretic!

6:06 hyPiRion: (heretic! hyPiRion true) ; ?

6:06 Fender: str!!! stupid me

6:09 actually, I gotta admit, I also tried .toString first -.-

6:09 well, thanks for the help

6:26 sm0ke: why doesnt this work? ##((symbol "inc") 0)

6:26 lazybot: ⇒ nil

6:26 hyPiRion: because that's a symbol, not a function

6:27 ,((-> "inc" symbol resolve) 0)

6:27 clojurebot: 1

6:27 sm0ke: ,inc

6:27 clojurebot: #<core$inc clojure.core$inc@822930>

6:28 sm0ke: hmm shouldnt a symbol resolve by itself?

6:28 ,(resolve 'inc)

6:28 clojurebot: #'clojure.core/inc

6:29 sm0ke: not i guess

6:30 hyPiRion: if it did, it would be hard to make macros and programs writing programs

6:30 ,`(~inc 0)

6:30 clojurebot: (#<core$inc clojure.core$inc@822930> 0)

6:30 hyPiRion: ^ not possible to read back in

6:30 sm0ke: ,(eval `(~inc 0))

6:30 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

6:31 sm0ke: i see the point

6:31 hyPiRion: sm0ke: as in, write to file and read back

6:31 ,(read-string (str `(~inc 0)))

6:31 clojurebot: #<RuntimeException java.lang.RuntimeException: Unreadable form>

6:32 sm0ke: ,`(inc 0)

6:32 clojurebot: (clojure.core/inc 0)

6:32 sm0ke: would you really need a ~ there?

6:33 hyPiRion: no, but that would've happened if the symbol resolved to a function

6:33 by default

6:34 sm0ke: also what is *ns*?

6:34 if i have a namespace ns1 which call a functon in ns2 which does (prn *ns*) what namespace would that be?

6:36 ucb: "And after a while we began to take their complaints seriously. We began to feel as if we really were responsible And disciples saith (below free (if (< n d) n (remainder (- n d) d))) We can thus make a factorial subroutine that returns to the entry point" -- http://kingjamesprogramming.tumblr.com/

6:36 sm0ke: thats a stupid question i suppose

6:36 ucb: sorry, couldn't resist.

6:36 hyPiRion: ,(:meta #'*ns*)

6:36 clojurebot: nil

6:36 hyPiRion: whops

6:36 ,(meta #'*ns*)

6:36 clojurebot: {:ns #<Namespace clojure.core>, :name *ns*, :added "1.0", :doc "A clojure.lang.Namespace object representing the current namespace.", :tag clojure.lang.Namespace}

6:36 hyPiRion: ,(:dynamic (meta #'*ns*))

6:36 clojurebot: nil

6:40 Apage43: sm0ke: oh, your symbol thing earler

6:40 symbols act like fns, but not the way you're thinking

6:40 they act like keywords ##((symbol "foo") {'foo :bar})

6:40 lazybot: ⇒ :bar

6:42 sm0ke: ,('foo {'foo :bar})

6:42 clojurebot: :bar

6:42 hyPiRion: yeah, implements ifn

6:42 sm0ke: yep i see your point

6:43 Apage43: whereas vars call their referenced thing

6:43 ,(#'inc 1)

6:43 clojurebot: 2

6:43 Apage43: when used as a fn

6:43 sm0ke: what is #'inc what is that?

6:44 Apage43: #'inc is shorthand for (resolve 'inc)

6:44 sm0ke: aha

6:44 Apage43: which returns a var

6:44 ,(type #'inc)

6:44 clojurebot: clojure.lang.Var

6:44 sm0ke: so coming to original form ##(#(symbol "inc") 0) ; should work

6:44 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox5671$eval40180$fn

6:44 Apage43: # is pretty weird

6:45 #' is (resolve 'foo)

6:45 but #(foo) is (fn [] (foo))

6:45 sm0ke: oh yes

6:45 Apage43: and #"" is shorthand for regexes =P

6:45 ,(type #"foo")

6:45 clojurebot: java.util.regex.Pattern

6:46 sm0ke: that is correct too

6:46 #

6:46 lol

6:46 Apage43: it's magic that lives in the reader, not something that exists in the thing that has been read

6:47 ,(read-string "#'inc")

6:47 clojurebot: (var inc)

6:47 Apage43: ,(read-string "#(foo)")

6:47 clojurebot: (fn* [] (foo))

6:47 Apage43: ,(read-string "#\"wat\"")

6:47 clojurebot: #"wat"

6:49 sm0ke: shouldnt the reader figure out #'(symbol "inc")

6:49 i mean #(symbol "inc")

6:50 Apage43: ,(read-string "#'(symbol \"inc\")")

6:50 clojurebot: (var (symbol "inc"))

6:50 sm0ke: hmm i see thats a valid function too

6:50 Apage43: #' is actually shorthand for var, as you can see

6:50 and var is macro-y

6:50 sm0ke: i havent see anyone using var in a code

6:50 clojurebot: Pardon?

6:50 Apage43: it's not a function

6:51 sm0ke: most people don't, because #' is shorthand for it =P

6:51 because it's not a fn you can't pass stuff to it at run time, it's evaluated at compile time

6:52 sm0ke: ok so this should work ##((var 'inc) 0)

6:52 lazybot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol

6:52 Apage43: ,((var inc) 0)

6:52 sm0ke: wth

6:52 clojurebot: 1

6:52 sm0ke: ,(var inc)

6:52 clojurebot: #'clojure.core/inc

6:53 hyPiRion: var is a macro

6:53 Apage43: rightr

6:53 hyPiRion: $source var

6:53 lazybot: Source not found.

6:53 hyPiRion: yeah, it's not even a macro I guess, it's a special form

6:53 Apage43: yeah

6:53 Why I said "macro-y"

6:54 sm0ke: not its not http://clojure.org/special_forms

6:54 * hyPiRion reads up a bit

6:54 hyPiRion: aha

6:54 sm0ke: cant find var

6:54 oh yes there is

6:54 Apage43: so forms like (var foo) are specially recognized by the compiler

6:55 sm0ke: i honestly havent see a #' in a code too

6:55 https://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging.clj this is full of macros

6:55 no #'

6:55 Apage43: sm0ke: using #' often happens when someone is doing livecoding type stuff

6:55 because if you do something like

6:56 hyPiRion: or in tests through alter-var-root and friends

6:56 Apage43: (def my-composed-thing (comp foo bar baz)) to compose the functions foo, bar, baz

6:56 if you then in a live coding session redefine foo bar or baz, my-composed-thing doesn't react

6:57 you can (comp #'foo #'bar #'baz)

6:57 and now that thing has indirection in it

6:57 and when those are called they look up what the var *currently* points to

6:57 sm0ke: Apage43: doesnt reloading foo bar baz would work?

6:58 Apage43: sm0ke: not if you don't reaload my-composed-thing as well

6:58 since it captured the *value* of the var at the time that code was evaluated

6:58 sm0ke: hmm i dont think thats necessary

6:58 ah ok you are right

6:58 comp is a macro

6:58 hyPiRion: generally not needed, you can usually reload the whole namespace

6:59 but for livecoding, that's usually iffy

6:59 sm0ke: $source comp

6:59 Apage43: where it comes in handy, for me, is when I'm messing with a web app

6:59 lazybot: comp is http://is.gd/jgSVls

6:59 sm0ke: hmm comp seems to be a function

6:59 Apage43: and I've run something like (start-http-server (-> my-handler wrap-some-middleware wrap-more-middleware))

7:00 so the http server has the *value* of my handler fn

7:00 if I replace that with #'my-handler I can redef it and not have to stop and start the http server

7:03 example: https://www.refheap.com/21522

7:04 sm0ke: what does juxt do?

7:05 ,(doc juxt)

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

7:05 Apage43: ,((juxt inc dec odd? even? pos? neg?) 12)

7:05 clojurebot: [13 11 false true true ...]

7:05 sm0ke: awesome sauce

7:05 jballanc: ,((juxt :foo :bar :baz) {:foo 1 :bar 2 :baz 3})

7:05 clojurebot: [1 2 3]

7:05 sm0ke: ,((juxt inc dec odd? even? pos? neg?) 12 13 14)

7:05 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core$inc>

7:06 sm0ke: ,((juxt inc dec odd? even? pos? neg?) [12 13 14])

7:06 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number>

7:06 sm0ke: wth

7:06 philandstuff: ,(map (juxt inc dec odd? even? pos? neg?) [12 13 14])

7:06 clojurebot: ([13 11 false true true ...] [14 12 true false true ...] [15 13 false true true ...])

7:06 Apage43: ((juxt f g h) a b c) == [(f a b c) (g a b c) (h a b c)]

7:07 ,((juxt count first last) [1 2 3])

7:07 clojurebot: [3 1 3]

7:07 Apage43: ,((juxt + - /) 1 2)

7:07 clojurebot: [3 -1 1/2]

7:07 sm0ke: i dont understand shit

7:07 Apage43: ((juxt + - /) 1 2) == [(+ 1 2) (- 1 2) (/ 1 2)]

7:08 sm0ke: ok i get it

7:23 Profpatsch: I’m going crazy here: https://github.com/Profpatsch/cljs-canvas-test

7:23 Can someone tell me why my namepaces are not accessible when I do lein repl?

7:23 It _should_ work in theory, since my source-paths are set to the right folders.

7:25 sm0ke: had a similar problem today, i had pre-tasks defined incorrectly

7:26 Profpatsch: Look at the project.clj, I can’t make it more minimal.

7:26 Maybe a typing error somewhere? oO

7:26 sm0ke: https://github.com/Profpatsch/cljs-canvas-test/blob/master/src/clj/canvas/core.clj#L15

7:26 what is that?

7:26 Profpatsch: It’s src/clj/canvas/core.clj

7:27 That’s the server.

7:27 sm0ke: you have wrong parenthesis

7:27 u instead of (

7:27 Profpatsch: Uuuuugh.


7:27 sm0ke: lein is evil

7:27 Profpatsch: That’s plain stupid.

7:28 It should Warning the hell out of me.

7:28 sm0ke: hmm i am surprised

7:28 amalloy: i mean, isn't that what lein repl and then (require 'canvas.core) *does* tell you?

7:28 unable to resolve symbol udefroutes, i would imagine

7:29 Profpatsch: No, nothing.

7:30 https://www.refheap.com/21523

7:30 afk for a bit.

7:30 amalloy: Profpatsch: yeah, you didn't attempt to compile it at all

7:30 that's why i said require, not in-ns

7:30 you could type random chinese garbage into any file and get that behavior - in-ns is for moving into already-compiled namespaces, not for compiling them

7:36 sm0ke: well i think to avoid this one can have :dev profile with :aot :all

7:36 hmm not sure though

7:44 buddywilliams: Good morning, anyone awake?

7:49 So, I was hoping someone could point me in the right direction. I am trying to build a simple Chess program in Clojure as a means to learn Clojure. Currently, I have constructed a Vector but I find myself continuing to stare at it because I have a few questions that I can't make sense of. If I have one Vector which will track the state of the chess pieces and board, does that then mean I have build mapping functionality into

7:49 most functions as I pass this data structure to? Do I have to replace the whole Vector each time I want to make a chance? How does destructuring help me?

7:50 (def chess-board (atom

7:50 [2, 3, 4, 5, 6, 4, 3, 2,

7:51 1, 1, 1, 1, 1, 1, 1, 1,

7:51 0, 0, 0, 0, 0, 0, 0, 0,

7:51 0, 0, 0, 0, 0, 0, 0, 0,

7:51 0, 0, 0, 0, 0, 0, 0, 0,

7:51 0, 0, 0, 0, 0, 0, 0, 0,

7:51 1, 1, 1, 1, 1, 1, 1, 1,

7:51 2, 3, 4, 5, 6, 4, 3, 2]))

7:53 sm0ke: i think for the second question the answer would be yes

7:53 but it doesnt imply inefficiency, as there is sharing between new and stable data structures

7:54 stale*

7:54 Profpatsch: amalloy_: I think I get the namespace stuff now. Still, lein repl should blow up in your face.

7:55 buddywilliams: so under the hood the language is seeing the fact that we are replacing and doing some kind-of compare update?

7:55 in order words, it only going to add/remove the parts which changed.

7:55 sm0ke: buddywilliams: yes absolutely

7:56 not in the sense of C/C++ arrays updates

7:56 buddywilliams: right

7:57 sm0ke: most data structures are internally trees.. so its a structural sharing between trees

7:58 buddywilliams: So, in my chess example, if I want to move a piece up, then I have to create a whole new vector.

7:58 I am sure there is some convenient way to operate on these structures but it's a little confusing.

7:58 to me at least

7:59 I think I am more concerned with how to solve the problem then I am the solution to this given problem.

7:59 sm0ke: buddywilliams: well creating is not as clumsy as it sound

7:59 buddywilliams: for eg ##(assoc [0 1 2 3] 0 -1)

7:59 lazybot: ⇒ [-1 1 2 3]

8:00 sm0ke: this just created a new vector with 0th index replaced

8:00 Profpatsch: It only does the immutable stuff internally.

8:00 buddywilliams: That makes sense.

8:00 Profpatsch: But because it didn’t mutate the old object you can still use it without worrying someone changes stuff under your ass.

8:00 buddywilliams: Someone else has already done the hard work of looping, find the right index, making a new array, etc.

8:01 Profpatsch: This is a great help for me: http://clojure.org/cheatsheet

8:01 sm0ke: yep that would be rich hickey

8:01 buddywilliams: Basically, it's all about learning the functions which give you quick access to some nested structure.

8:02 Profpatsch: Under Vector it lists all the stuff you can use to “modify” the data structure.

8:02 buddywilliams: I saw the chest sheet yesterday for the first time, I'll comb it today.

8:02 Profpatsch: Do not try to understand every function in one go.

8:02 That’s way to many to learn at once.

8:02 sm0ke: buddywilliams: you just have to think about what you want to do

8:02 Profpatsch: And then look in the right section of the cheat sheet.

8:03 sm0ke: heh

8:03 buddywilliams: I am playing something of the dummy, because well I feel like one, I have watched hours upon hours of talks, read tons of articles, trying to get my mind to a place where I can think functionality.

8:04 sm0ke: hmm yep functional programming coming form an imperative or oo background looks awful

8:04 buddywilliams: In the assoc example, would I then use swap! one I call that function?

8:04 So far, I love the ideas and I'm convinced it has a lot to offer me, but getting started in a bear because everything is so easy to understand until I try to do something non-trivial.

8:05 is a bear*

8:05 Profpatsch: I guess it’s the working on the datastructures, working /with/ the datastructures part that’s hardest to grasp.

8:05 sm0ke: buddywilliams: yes for atoms you use swap!

8:06 Profpatsch: And all the meta-stuff, like multimethods.

8:06 buddywilliams: Right. I have basic questions like, should my whole app just use one nested map?

8:06 Questions that keep me confused about where to begin.

8:06 sm0ke: maps with keywords as keys are good for data abstraction

8:07 buddywilliams: Imagining the data structure is easy, but thinking about how to build an application, I am lost.

8:07 Profpatsch: But when writing e.g. I noticed that my code consists basically only out of list comprehensions, so I figured: Why not use a functional language from the get-go?

8:07 buddywilliams: Okay smoke.

8:08 I am sold profpatsch.

8:08 Profpatsch: Yeah, and realizing that maps are The Best Think That Can Happen To You.

8:08 *Thing

8:08 buddywilliams: tired of beating my head against the whole and not making progress

8:08 Are you saying, it's worth the pain?

8:08 :)

8:08 Profpatsch: I guess so.

8:09 buddywilliams: I am so much a big picture thinker than it's hard to go on parts.

8:09 Profpatsch: The other part of is that we are all just experimenting. There ar e not many best practices for functional programming yet.

8:09 buddywilliams: So for my chess application, do you guys think it's okay to use one data structure?

8:09 Profpatsch: of course.

8:10 buddywilliams: That makes me happy, at least I am not totally of base.

8:10 Profpatsch: Since you only have 64 fields, it should work splendidly.

8:10 But I’m not sure if a vector is your best bet here.

8:10 buddywilliams: I will never forget the joy I had from reading Paul Graham's article and spent the whole weekend trying to understand a one page list that at the end I could say, yeah I got it.

8:11 Profpatsch: Hah, same here.

8:11 sm0ke: hmm i agree i would rather go with a map

8:11 buddywilliams: Really, a map?

8:11 I built one of those too, but only as a way to reference the positions.

8:11 sm0ke: yes why not, its easy to look up a position

8:11 buddywilliams: (def chess-board-map {:a8 0, :b8 1, :c8 2, :d8 3, :e8 4, :f8 5, :g8 6, :h8 7,

8:11 :a7 8, :b7 9, :c7 10, :d7 11, :e7 12, :f7 13, :g7 14, :h7 15,

8:11 :a6 16, :b6 17, :c6 18, :d6 19, :e6 20, :f6 21, :g6 22, :h6 23,

8:11 :a5 24, :b5 25, :c5 26, :d5 27, :e5 28, :f5 29, :g5 30, :h5 31,

8:11 :a4 32, :b4 33, :c4 34, :d4 35, :e4 36, :f4 37, :g4 38, :h4 39,

8:11 :a3 40, :b3 41, :c3 42, :d3 43, :e3 44, :f3 45, :g3 46, :h3 47,

8:11 :a2 48, :b2 49, :c2 50, :d2 51, :e2 52, :f2 53, :g2 54, :h2 55,

8:11 :a1 56, :b1 57, :c1 58, :d1 59, :e1 60, :f1 61, :g1 62, :h1 63})

8:12 That's true.

8:12 but I thought the logic of move here would mean I would have to figure out a way to get the movements to think in terms of chess board rather than indexs.

8:14 Well, I'll go and do the hard work of more reading and experimenting.

8:15 sm0ke: buddywilliams: you can map each poition to a tuple too like :a1 -> [0 0]

8:15 buddywilliams: okay.

8:16 I am tuple a vector?

8:16 Is a*

8:16 one for each player, is that why I would use a tuple?

8:18 sm0ke: buddywilliams: yes a vector of length 2, i meant it to be like [x,y] coordinated on board

8:19 buddywilliams: how would you store the location of the peice?

8:19 echo-area: Neat, in clojure-mode where indentation doesn't work, M-x fill-paragraph (M-q) auto indents correctly

8:19 buddywilliams: [x,y,peice]?

8:20 okay I see, with x,y I can give the meaning to :a1 for example

8:21 sm0ke: buddywilliams: thats can to be a map of {:piece [x,y]}

8:21 buddywilliams: Interesting.

8:21 VFe: yeah, like {:a1 [x, y, piece]}, or like smoke said depending on how you want to organize the data

8:21 buddywilliams: makes sense though

8:22 I guess that's part of the confusion, does it really matter? Hard to tell in the beginning.

8:22 modulus: So guys, if i have a defrecord on a namespace and i use it from anotehr file, i don't seem to get the constructors for the records but i get the functions. is this how it's meant to be?

8:23 sm0ke: well i depends a lot on what exactly makes its easy for you to write algorithm on it

8:23 buddywilliams: yeah, I can see that.

8:23 write some, refactor, write some more, etc.

8:24 sm0ke: a 8*8 size is really small data, for keeping track of current positions etc

8:24 modulus: like (ns bla) (defrecord Foo) then from another file (ns other [:use [bla :as that])) and i can't do (that/Foo.)

8:24 VFe: Yeah, it's more about how you want to model the data so that it's easy for *you* to use it(or whoever)

8:29 buddywilliams: modulus, I don't know the answer to your question.

8:31 sm0ke: well its not really trivial once it comes to algorithms though

8:31 well then it would come to knowledge of gametheory i guess

8:32 buddywilliams: chess is partial game right?

8:33 modulus: hmm ok

8:34 buddywilliams: ?

8:34 partial, what do you mean?

8:34 sm0ke: anyhow people seem to have written chess in clojure may be you wanna have a look https://github.com/clojure-dus/chess

8:35 buddywilliams: have you written chess in some other language before?

8:35 buddywilliams: cool, I haven't seen this one. I looked at a couple of others but the authors didn't finish then.

8:35 no, I have not.

8:36 The only game I have written was tetris

8:36 sm0ke: ok, i was asking about how to decide on the next move

8:36 buddywilliams: AI?

8:37 sm0ke: yep

8:37 partial impartial games?

8:37 partizan if you prefer

8:37 grundy theorem

8:37 hehe game theory scares me

8:38 buddywilliams: reading about it on wikipedia now...

8:38 yeah, I agree

8:39 I will be happy to see a piece move on screen :)

8:40 sm0ke: ok later

9:17 marutks: has anyone tried to invoke overloaded methods on a hessian proxy? I couldn't get it working, type hints didnt help.

9:42 konr: Is there some sort of linked-hash-map in clojure, in which I can keep inserting new key-val pairs and it'll be ordered by insertion order?

9:43 nightfly: just do a list of lists or something

9:46 mdrogalis: konr: TreeMap from Java?

9:47 arrdem: konr: https://github.com/flatland/ordered

9:48 Profpatsch: Can someone explain this: https://www.refheap.com/21525 ?

9:49 mdrogalis: Profpatsch: ns's can partially load.

9:50 BAMbanda: What IDE do you guys recommend for linux?

9:50 is there anything like SLIME for clojure

9:50 arrdem: $google nrepl emacs

9:50 lazybot: [clojure-emacs/cider · GitHub] https://github.com/clojure-emacs/cider

9:50 hyPiRion: ~nrepl

9:50 clojurebot: nrepl is a network REPL implementation: http://github.com/clojure/tools.nrepl

9:50 arrdem: hyPiRion: jinx

9:50 mdrogalis: arrdem: I did not know lazybot did that :P

9:51 BAMbanda: thanks

9:51 arrdem: mdrogalis: my bot-foo is very hit or miss but that one is handy

9:52 BAMbanda: emacs + (nrepl.el | cider) is the reccomended setup around here.

9:52 BAMbanda: arrdem, alright, i was looking for something with emacs, this is good thanks

10:01 Profpatsch: mdrogalis: Does the second require try to reload the namespace? Or will it do nothing?

10:01 mdrogalis: Profpatsch: I'm not sure to be honest.

10:02 You could drop a print in there and find out.

10:19 sm0ke: guys

10:19 is there an easy peasy way to defined getters and setters for gen-class/

10:19 ?*

10:24 i can define methods getP setP but thats too much work

10:24 there must be an easy way

10:25 danlamanna^: what are peoples takes on web frameworks for clojure? in terms of python i would be looking for something closer to django than flask

10:25 BobSchack: sm0ke: :exposes {protected-field-name {:get name :set name}, ...}

10:25 Since the implementations of the methods of the generated class

10:25 occur in Clojure functions, they have no access to the inherited

10:25 protected fields of the superclass. This parameter can be used to

10:25 generate public getter/setter methods exposing the protected field(s)

10:25 for use in the implementation.

10:25 from http://clojuredocs.org/clojure_core/clojure.core/gen-class

10:26 TimMc: I think I would have preferred just the link. :-P

10:26 or fewer linebreaks

10:26 `cbp: danlamanna^: libraries over frameworks is kinda the motto around here

10:26 BobSchack: yeah sorry about that :(

10:27 `cbp: danlamanna^: you won't find much in the way of django or rails around here unfortunately

10:27 or fortunately

10:27 vijaykiran: danlamanna^: there isn't anything closer to Django - may be try http://let-caribou.in

10:27 brainproxy: bozhidar: prelude is awesome and thanks for merging my patch the other day for def-...

10:30 sm0ke: oh let me try

10:30 i really dont understanf

10:31 whats the protected-field-name?

10:33 `cbp: the field for which youre generating setters and getters

10:34 sm0ke: `cbp: then why is :get :set needed?

10:34 wei__: what's the minimum Clojure version to use core.reducers? I'm using 1.5.1 and get 'clojure.core.reducers' not found when trying to require

10:35 sm0ke: i get field not defined in class, or ancestor

10:37 stuartsierra: wei__: Reducers is part of 1.5.1. Check your `require` syntax, maybe?

10:37 sm0ke: as far as i know you can only define one field using gen class

10:37 wei__: (require '[clojure.core.reducers :as r])

10:37 llasram: wei__: You may get an exception if using Java 6 and not including a ForkJoin lib

10:37 wei__: (using the repl.) could it be because I'm running java 6?

10:38 should probably upgrade to java 7 then. but the exception is "Exception namespace 'clojure.core.reducers' not found clojure.core/load-lib (core.clj:5380)", not a forkjoin lib error

10:39 llasram: Are you sure you're using 1.5.1?

10:39 ,*clojure-version*

10:39 clojurebot: {:interim true, :major 1, :minor 6, :incremental 0, :qualifier "master"}

10:43 wei__: {:major 1, :minor 5, :incremental 1, :qualifier nil}

10:46 sm0ke: i was basically writing a log4j appender

10:46 wanted to have some custom properties

10:47 i guess id have to write get/set as :methods mutating atom in :state

10:49 gfredericks: so exceptions thrown in a go block

10:50 llasram: wei__: Beats me then. You do need to add jsr166y for it to work w/ java 6 though. Try adding that to your deps and trying again

10:50 gfredericks: they will totally crash the process and there's no generic mechanism for catching them?

10:51 jonasen: Bronsa: ping

10:51 Bronsa: jonasen: pong

10:52 jonasen: Should :static-field have a :validated? true?

10:53 gfredericks: it's also weird that map< returns a "channel" that can throw exceptions on take

10:53 jonasen: (analyze 'String/CASE_INSENSITIVE_ORDER (empty-env)) does not have a :validated? key

10:53 Bronsa: jonasen: no, if it's a static-field there's no need for :validated?

10:53 jonasen: Bronsa: ok

10:54 thanks

10:54 Bronsa: jonasen: same goes for :instance-field

10:55 gfredericks: I guess you can't generally assume that <!! is a safe operation

10:55 Bronsa: jonasen: basically reflection happens on :static-call/:instance-call with no :validated? and on :host-interop, all the other cases are validated

10:56 jonasen: Constructors also must be validated, right?

10:57 Bronsa: yeah

10:59 jonasen: probably adding :runtime-reflection? would be a good idea to make it easier to understand, I'll probably add that

11:06 bozhidar: brainproxy: you're welcome

11:11 brainproxy: is there something like *warn-on-reflection* for clojurescript

11:11 ah see it here: https://github.com/clojure/clojurescript/blob/master/devnotes/corelib.org

11:11 but what's the correct usage?

11:12 eLobato: question, is there any clojure library that uses 'libgit2' to offer an interface to git? Or clj-jgit is the only thing that has been developed?

11:40 seangrove: brainproxy: What would it do in cljs?

12:00 brainproxy: seangrove: wasn't sure, something I've never come fully to terms with in any case

12:00 but I saw it listed, wondered

12:01 I'm starting to see garbage in my compiled js files if I edit a macro file during an auto build

12:01 it doesn't always happen

12:01 clojurebot: Huh?

12:01 brainproxy: but when it does, I have to do a cljsbuild clean and reckick the auto build

12:02 hiredman: brainproxy: I've had that recently when I had a cljsbuild auto that didn't die when I closed the terminal it was in, so I ended up with two running

12:03 brainproxy: hiredman: thanks! I had 3 running...

12:04 hiredman: paying it forward (dnolen suggested it to me after I had opened an issue for cljsbuild about it)

12:05 jcidaho: is anyone using clamq or an alternative? Clamq seems a bit dead

12:10 egosum: Is there a reason Clojure's compiler isn't two pass, with the first pass just declaring all the vars, so that forward declaration aren't necessary?

12:11 seangrove: egosum: Interesting question. Not sure though.

12:11 technomancy: egosum: that would make it fail to catch typos

12:11 seangrove: I believe the cljs compiler has passes now, but they're not used for forward declarations

12:11 egosum: technomancy: I'm not sure I follow?

12:12 dnolen: egosum: it means making the compiler more complicated for little perceived value

12:12 egosum: Couldn't it just declare top level defs, essentially?

12:12 dnolen: egosum: Clojure is fundamentally an expression level compiler

12:12 technomancy: egosum: (defn x [] (thingy 1)) (defn thing [n] ...) ; <- obviously a mistake, but with auto-forward-declare it succeeds

12:12 dnolen: egosum: sure but it's never going to happen

12:13 egosum: technomancy: that would still fail; `thingy` would never have been declared

12:13 technomancy: egosum: oh I see; you're proposing something else. never mind.

12:13 egosum: technomancy: Ah, sorry for being unclear

12:14 technomancy: egosum: no, it's just that most people who complain about foward declarations want to solve it a different way =)

12:14 anyway, I appreciate the fact that the compiler is just (doseq [f forms] (eval f))

12:14 much easier to understand

12:16 egosum: dnolen technomancy: It is more simple, it seems, from a structural perspective to be able to write code in logical order e.g. line 1-n (defn most-abstract-form-written-using-fns-i-haven't-defined-but-have-imagined) lines n—EOF defs filling in the blanks. Otherwise, you need to re-order your code.

12:16 dnolen: egosum: declare solves this problem

12:16 egosum: dnolen: declare is boilerplate

12:16 dnolen: w/o complicating the compiler

12:17 technomancy: egosum: it's certainly easier to not have to think about how you order your code before writing it

12:17 dnolen: egosum: in your opinion, anyways your points are going to fall on deaf ears

12:17 technomancy: however, I question whether "thinking less about order" is a good goal to have

12:17 egosum: dnolen technomancy: but I can appreciate the compiler simplicity

12:17 brainproxy: (inc hiredman)

12:17 lazybot: ⇒ 29

12:18 technomancy: forcing you to think about order forces you to think about the relationship between different parts of your code

12:18 egosum: dnolen: I hope I haven't come across as hostile; I'm fine with using declare, I just am wondering about the reasons behind the design decision. I'm always interested in what smarter people than I think about

12:19 technomancy: I buy that, yeah

12:19 dnolen: egosum: it makes the compiler really simple to implement that's the main reason, and in practice it's not really a big deal

12:19 egosum: in the 7500 lines of the CLJS standard library we have ~30 declare expressions

12:19 brainproxy: dnolen: is there a straightforward way to go from (cljs/analyze-symbol ...) to getting a form to pass back through the reader during compile time?

12:19 dnolen: not exactly a pain point

12:20 technomancy: egosum: it also helps when reading; you know that as you progress from top-to-bottom, you don't have to think about any functions you haven't seen yet.

12:20 egosum: dnolen: makes sense

12:20 dnolen: brainproxy: the ast preserve the original form under :form

12:21 brainproxy: dnolen: ok!

12:21 I can gen an ast using a func in cljs.compiler right?

12:22 dnolen: brainproxy: cljs.analyzer/analyze

12:22 brainproxy: oh duh, I see what you mean

12:22 I was making it too complicated :/

12:22 egosum: dnolen finally got around to using core.async since seeing you speak at 2sigma—had a great time using it, thank you for that into (though I ended up not using it with cljs)

12:22 brainproxy: but good times reading through the source in any case :)

12:23 egosum: technomancy: right, that is nice. It also acts as a sort of todo-list when writing code, which is how i tend to think about it

12:23 rather than relying on the compiler to tell me which var i've forgotten to define

12:23 dnolen: egosum: nice!

12:23 technomancy: clojurebot: use a map is https://twitter.com/krisajenkins/status/408625918362791936/photo/1

12:23 clojurebot: c'est bon!

12:25 egosum: are people using defn- these days, or ^{:private true}?

12:25 brainproxy: clojurebot: shared mutable state is http://image.slidesharecdn.com/concurrencygotchas-100408105435-phpapp01/95/slide-7-728.jpg?cb=1270742095

12:25 clojurebot: c'est bon!

12:25 technomancy: egosum: defn- absolutely

12:26 anything that gets more people to be explicit about what part of their lib is an implementation detail is a wonderful thing

12:26 egosum: technomancy: k…that's what i thought. I'd recently come across a few examples with the meta tag instead, was wondering if the style had changed

12:26 technomancy: some people like the consistency with def since there's no def- but IMO that's silly

12:28 bbloom: technomancy: i do find it mildly annoying that there is no def-, defmacro-, etc. and then whenever you create any kind of def-ing macro you need to take care to copy the metadata across

12:29 technomancy: i do use defn-, but i think i prefer the ^:private syntax across the board b/c otherwise some part of my brain has to resist the urge to define my own defwhatever-

12:29 coventry: You have to be careful to copy the metadata across anyway, no?

12:30 bbloom: yeah

12:30 i have a love/hate relationship w/ metadata

12:30 i love that it's there when i need it

12:30 i hate that it's there when i forget to think about or look at it :-P

12:30 mikerod: Isn't :private anything really just a bad thing? Functions should be generic and reusable. :)

12:30 technomancy: bbloom: yeah, the arguments against adding def- are baffling to me

12:31 mikerod: you should strive to communicate to your consumers what parts of the library are subject to change in minor bumps and where you're committing to compatibility

12:31 mikerod: if someone is okay with breakage, they can go ahead and use private vars. it's just two more characters to do so

12:31 but then when it breaks it's their fault

12:32 bbloom: the rules about what preserves metadata and what doesn't seem really arbitrary

12:32 bbloom: technomancy: the argument is pretty simple to me: then what about defmacro- ? and what about defprotocol- or whatever? we already have a consistent syntax for arbitrary annotations that is much more future proof. i'd rather deprecate defn- :-)

12:32 mikerod: technomancy: True, so you use private to relay this information to consumers of a lib. I can see that argument. Sometimes I wonder if it should just be a "private" namespace of functions.

12:32 bbloom: technomancy: yeah, it's b/c each data structure needs to deal w/ metadata on their own

12:33 coventry: How about a def-private-def* macro macro? :-)

12:33 bbloom: coventry: i have on several occasions wanted a defdefmacro macro

12:33 technomancy: mikerod: if you have enough, sure

12:33 enough vars, I mean

12:34 bbloom: coventry: i'd say like 30% of my macros are trivial wrappers around some (def f (comp whatever (fn ...)))

12:35 technomancy: that's an interesting point. mikerod suggests making another namespace, which is a nice idea but suffers from the fact that the small amount of friction stops ppl from doing things like that

12:35 pg wrote some thing about the "weight" of function names

12:35 how smaller function names encourage more use subconciously

12:35 he took it to an absurd extreme w/ arc, but he's right in many respects

12:35 technomancy: bbloom: which is why I heard defn-

12:35 *heart

12:36 bbloom: if you want people to do stuff, you need to make it 1) the default or 2) absurdly easy to accomplish

12:36 mikerod: hmm, yeah I can see the weight of a namespace making it not happen in practice I suppose

12:36 I just don't know that I'm a fan of seeing how carried away people get with defn-

12:36 bbloom: mikerod: it's entertaining to me how many dumb ideas have shown up in programming b/c people don't like to type a little bit

12:37 technomancy: bbloom: REGISTER_GLOBAL_VARS or whatever

12:37 bbloom: mikerod: it affected me for a long time. and it's poisonous in some communities

12:37 technomancy: i'm thinking more of Ruby's const_missing

12:37 technomancy: oh heavens

12:37 mikerod: I like to question why something is private, and ask does it need to be or could it easily be generalized. I get that some things are just subject-to-change implementation details though obviously.

12:38 bbloom: when you try to evaluate `User`, you get const_missing('User') which basically winds up calling require("models/#{'User'.camelize}")

12:38 weeeeeeee

12:38 horrifying.

12:38 mikerod: bbloom: the fear of typing is real indeed.

12:39 bbloom: i much prefer the clojure way of just sticking lots of stuff in a namespace, but then you wind up with what mikerod mentioned about people getting crazy with defn-

12:39 and you have the problem of private things being really *internal* things

12:40 and you wind up having to refactor in to namespaces later anyway and delete all the ^:private metadata

12:40 technomancy: mikerod: what I really hate is having to make a change on a function that I should have declared as private and wondering "is this safe to change? I bet nobody's *actually* using this. I'll just go ahead and see what happens I guess?"

12:40 reducing your surface area decreases your responsibility

12:41 if someone wants to use it, they can deref the var and ask you to commit to maintaining it in future versions

12:41 mikerod: yeah, that's a valid downside it indeed

12:41 tommo__: can someone explain when i would use reduce/apply as opposed to the other?

12:42 coventry: tommo__: Have a look at the clojuredocs examples. If it's not clear from that, feel free to ask again.

12:42 tommo__: already did, thats why i resorted to here coventry :p

12:43 technomancy: tommo__: they're totally different. apply results in a single call; reduce results in one call per coll item.

12:43 teslanick: apply is something you do to a function, reduce is something you do to a seq.

12:43 That's simplifying, but that's how I tend to think about them.

12:43 tommo__: so apply is basically (+ 1 2 3), and reduce would be (+ (+ 1 2) 3)?

12:43 coventry: Oh, I see why you're confused.

12:44 ,(reduce #(do (pr [%1 %2]) (+ %1 %2)) [1 2 3 4 5])

12:44 clojurebot: [1 2][3 3][6 4][10 5]15

12:44 coventry: ,(apply #(do (pr [%1 %2]) (+ %1 %2)) [1 2 3 4 5])

12:44 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (5) passed to: sandbox$eval63$fn>

12:44 coventry: ,(apply #(do (pr [%1 %2 %3 %4 %5]) (+ %1 %2)) [1 2 3 4 5])

12:44 clojurebot: [1 2 3 4 5]3

12:45 tommo__: ahh i see

12:45 thanks alot

12:46 coventry: The initial clojuredocs examples are confusing here, because they work roughly the same in those cases. (reduce + [1 2 3 4 5]) vs (apply + [1 2 3 4 5])



12:46 tommo__: thats what confused me

12:47 raek_: tommo__: 'apply' is useful when you want to pass a sequence of arguments from your function to another one. 'reduce' is useful when you want to combine all values in a sequence using a function that takes two arguments

12:47 tommo__: similar to what teslanick said

12:48 ty

12:49 teslanick: I map the two functions to their javascript counterparts, because I'm far more familiar with JS. That introduces a degree of conceptual blindness about when to use them. So maybe it's not a helpful way to think about the two in all cases.

12:55 jonasen: Bronsa: https://www.refheap.com/21533

12:56 Bronsa: ^ similar issue as yesterday?

12:57 Bronsa: jonasen: no, the method name needs to be munged, looks like I forgot to do it

12:58 TimMc: bitemyapp: I know you <3 tracing -- any tips on dealing with gigantic argument and return values?

12:58 I'd love some kind of interactive trace analyzer where I can expand and collapse nodes.

12:59 justin_smith: TimMc: yeah, imho there should be a tracer that ouputs emacs org files

12:59 so you can expand for detail as you wish

12:59 I've thought of hacking that up myself

13:01 ohcibi: is there a function like map that gives me the last return value? so like a mix of reduce and map 8-)

13:02 coventry: ,((comp last map) identity (range 5))

13:02 clojurebot: 4

13:02 S11001001: which is the same as just taking the last thing and calling the function on it

13:03 ndp: ,((comp identity last) (range 5))

13:03 clojurebot: 4

13:03 `cbp: when is joy of clojure coming out? :P

13:03 coventry: S11001001: Only if the function is pure. :-)

13:03 S11001001: coventry: I'm just going to assume that :)

13:03 Bronsa: jonasen: pushed a fix

13:04 `cbp: ohcibi: for side effects?

13:04 jonasen: Bronsa: Awesome!

13:04 `cbp: or just (f (last coll))

13:04 ohcibi: `cbp: no side effects

13:04 `cbp: then just (f (last coll))

13:07 justin_smith: if coll is a vector (f (peek vec)) is much faster (linear rather than O(n) time), btw

13:07 just in general, probably does not apply here

13:08 * make that ~O(1) instead of O(n)

13:09 coventry: You mean constant rather than linear.

13:09 justin_smith: right

13:09 jonasen: Bronsa: That took care of one NoSuchMethodException. I've got another (on another piece of code): java.lang.NoSuchMethodException: clojure.lang.RT.get(java.lang.Object, clojure.lang.Keyword)

13:09 I'll try to find a minimum failing test

13:10 (might also be a bug in my code)

13:12 ohcibi: `cbp: I meant in (map f coll) that for each call of f I can pass something to the next call of f... what I want to do is iterate over a vector of vectors and select one element based on the index of the element that was taken from the last vector... where the first vector hast only one element..

13:12 Bronsa: jonasen: don't bother with finding a minimal case, just give me the piece of code that fails, I have a feeling I know what's going on

13:12 danneu: I keep clicking the "Mute" button on Github thinking I'm unmuting it. This icon fools my brain: https://dl.dropboxusercontent.com/spa/quq37nq1583x0lf/p-zlrg7x.png

13:15 jonasen: https://github.com/jonase/eastwood/blob/master/src/eastwood/analyze_ns.clj

13:15 ^ when I analyze that namespace

13:16 I have a pass that reflects on :instance-call, :static-call, :static-field, :instance-field and :new

13:16 I think it fails on a :static-call

13:16 Bronsa: is that enough?

13:17 Bronsa: gah. this should trigger that (loop [a 1] (if true (get {} :foo) (recur ""))

13:17 coventry: ohcibi: You can do that with reduce. The return value of the fn you pass to reduce can be whatever you want.

13:18 Bronsa: indeed

13:18 coventry: ohcibi: Unless you also want the sequence of results to be returned like with map, I guess.

13:18 ohcibi: coventry: I want it to return a sequential

13:19 Bronsa: jonasen: thanks, I'll try to fix this, might take me a while though

13:19 ohcibi: coventry: i will reduce afterwards, but I need the single values first 8-)

13:19 jonasen: Bronsa: the code you pasted does trigger the same exception

13:19 Bronsa: no hurry.

13:20 Bronsa: jonasen: yeah, the cause is similar to why (for [a nil]) was failing yesterday

13:20 coventry: ohcibi: reductions.

13:20 Bronsa: and it's terribily hard to debug validate-loop-locals

13:21 jonasen: Bronsa: the java reflection api is not smart enough to know that a java.lang.Keyword is a java.lang.Object?

13:21 ohcibi: coventry: perfect... thanks

13:21 Bronsa: jonasen: no, I'm tagging the method args with the wrong type :)

13:28 jonasen: ok that was easier than I thought, should be fixed now

14:20 rurumate: is there a canonical way to write hadoop jobs in clojure? I've been using clojure-hadoop so far, am I missing anything?

14:21 technomancy: rurumate: llasram has some stuff for that

14:21 rurumate: I see

14:25 llasram: rurumate: Oh yeah, my new stuff: https://github.com/damballa/parkour/ and the incumbent: https://github.com/nathanmarz/cascalog

14:30 mdrogalis: rurumate: It really depends on what you're trying to do on Hadoop.

14:30 I've used about 5 different Java/Clojure frameworks. There's big trade-offs with each.

14:34 llasram: mdrogalis: Nah. I'm pretty sure Parkour is the right tool for all jobs :-D

14:34 seangrove: Hah

14:34 mdrogalis: llasram: Hah.

14:35 technomancy: cascalog seems like a lot more than just "write hadoop jobs in clojure"

14:35 I mean it looks neat, but it's a very different paradigm

14:35 mdrogalis: It's pretty great since it brings a logic programming abstraction, but a few things from Cascading, the library underneath seep through.

14:35 So it's not quite as intuitive as Datomic's datalog.

14:37 llasram: My current rule of thumb is that if I need more than 1 non-replicated join in sequence of jobs, I still reach for Cascalog

14:37 It's pretty killer at that

14:37 mdrogalis: Joins are pretty darn slow with Map-Reduce though. :/

14:37 seangrove: llasram: No storm?

14:38 llasram: mdrogalis: Oh yeah. Which is why I've managed to switch 90%ish of Damballa's jobs Parkour

14:38 seangrove: In what sense?

14:38 seangrove: llasram: Guess I'm not totally clear on the hadoop/storm divide, other than hadoop seems more batch oriented vs storm's continuous processing

14:39 It seemed from a vague, far-off distance that storm would be nicer to work with overall

14:39 mdrogalis: That's pretty much it, seangrove.

14:39 llasram: seangrove: That's my understanding as well. Storm looks pretty slick, but I just haven't personally had an occasion yet to use it

14:39 mdrogalis: Some jobs truly need to be batch oriented, so Storm just don't fit.

14:39 seangrove: mdrogalis: Maybe hadoop's raw crunching ability/throughput is better though?

14:39 technomancy: storm doesn't have any analog to HDFS afaict, which is kind of the whole point of using hadoop

14:40 llasram: (inc technomancy)

14:40 lazybot: ⇒ 87

14:40 llasram: Pretty much

14:40 seangrove: technomancy: The idea there being to keep the data close to the computation?

14:40 technomancy: seangrove: exactly

14:40 mdrogalis: Meh, it's a dated concern.

14:40 Network speeds have caught up.

14:40 Netflix uses Map-Reduce and keeps their data on S3.

14:41 llasram: We used to do that. Maybe it's gotten better in the... 2 years? since we invested in our own cluster, but my experience is on the order of a 100x speed-up

14:42 seangrove: llasram: That's pretty considerable.

14:42 noncom: what is the most idiomatic way to access and/or update a value in an arbitrary comples clojure datastucture? for example, I want to read or write or update an integer in a [] which is in a {} which is in a {} which is in a [] which is in a #{} which is in a [] which is in a {}, well you get the idea...

14:42 mdrogalis: llasram: Yeah, I mean, you need something like SSDs and infiniband to get equal performance, but you can get close otherwise now.

14:42 seangrove: noncom: assoc/update-in ?

14:43 hiredman: llasram: cluster for storage or for compute

14:43 llasram: because I bet the slow down there would be ec2 compute, not s3 storage

14:43 llasram: It probably also depends on your data and your access patterns. If you have relatively small amounts of data that you preform heavy computation on, S3 is probably perfectly reasonable

14:43 seangrove: ,(update-in [1 1 {:a [0 0 {:c 20}] :b 9} 3 3] [2 :a 2 :c] inc)

14:43 clojurebot: [1 1 {:a [0 0 {:c 21}], :b 9} 3 3]

14:44 mdrogalis: I mean, it's kind of the same reasoning for Datomic running queries right on the peer.

14:44 seangrove: ,(assoc-in [1 1 {:a [0 0 {:c 20}] :b 9} 3 3] [2 :a 2 :c] 88)

14:44 clojurebot: [1 1 {:a [0 0 {:c 88}], :b 9} 3 3]

14:44 llasram: hiredman: You think so? Hmm. I was totally going in the other direction

14:44 mdrogalis: S3 is pretty slow to read off of.

14:44 seangrove: noncomm ^

14:44 llasram: You can always throw more money at EC2 for more compute on your nodes, but you can't make Amazon bounce our data to and from S3 any faster

14:45 s,our,your,

14:45 slpsys: amen

14:45 technomancy: it's not uncommon for me to see archives that download from S3 in less time than they take to untar

14:45 noncom: seangrove: cool! i just teted it in the repl, it works for {} and [], although, doesn't punch through #{} :/

14:46 brainproxy: dnolen: I just tried what you suggested earlier; :form only gives me the symbol

14:46 dnolen: brainproxy: what were you expecting?

14:46 llasram: This looks like it call for some empirical evaluation! Volunteers?

14:46 seangrove: noncom: Interesting, not sure how to approach that, since sets don't have guaranteed ordering

14:47 brainproxy: well, what I really want is to be able to get to the s-expr that the symbol points to on the cljs side

14:47 mdrogalis: llasram: Maaaybe another time :P

14:47 llasram: mdrogalis: Awesome. Let me know what you find!

14:48 mdrogalis: *Uploads a 500 GB file under company's AWS account*

14:48 *Innocent whistle*

14:48 noncom: seangrove: hmmmm very true... i think i can't formulate what behavior i expect from sets here..

14:48 brainproxy: dnolen: I also tried using resolve-var from cljs.analyzer, and it finds the var, but there's no source/form associated with that, but there are :line :and column numbers

14:48 that's what I was alluding to originally when I asked about an easy way to extract...

14:49 dnolen: brainproxy: I don't know what you asking - the s-expr the symbol points to?

14:49 noncom: seangrove: although definitely there must be something as they (sets) are not terminals of the datastructure. only bnon-collection types are terminals

14:49 brainproxy: sorry, wasn't accurate with terminology

14:49 on cljs side I have (def xyz [...])

14:50 noncom: or maybe we have to treat a set as a terminal

14:50 and break the path in pieces if there are sets

14:50 brainproxy: and on clj side I have (defmacro resme [sym] (cljs.analyzer/... ...))

14:51 what I want is to be able to invoke resme with xyz from the cljs side, but resolve the [...] source on the clj side

14:51 noncom: the next piece is only valid if a value is present in the set

14:51 does it sound like nonsense?

14:51 seangrove: noncom: Yeah, I believe that will work...

14:51 noncom: ok, i'll try

14:51 seangrove: noncom: But then you need to have the data structure you're looking up in the set anyway

14:52 But depending on your use case, it could work

14:54 noncom: seangrove: see, i am displaying the datastruct as a tree. and the user can visually type in a new value for any leaf. thus, if the leafs are separated by at least one #{} from the root of the tree, there is this problem. probably just have to treat sets as roots, update them separately and then update the whole set as a single atomic data type for the previous collection..

15:03 seangrove: noncom: In that case, you can probably just use assoc-in, since you can generate the path to the leaf you want to update

15:16 dnolen: brainproxy: yeah I have no idea what you are trying to do

15:17 brainproxy: if you're trying to determine the form that xyz was assigned to via the analyzer this is not possible nor will it be

15:18 brainproxy: at least out of the box, you could add a pass to do this yourself though but it's going to be expensive since you'll be saving the AST of all tops levels - you could only do this for special cases via metadata or something

15:19 justin_smith: is there a way to have my protocol default to noop / identity methods if they are not defined? I tried implementing it on object or record so that the superclass resolution would take care of it but I get an error about the class being closed

15:20 hiredman: justin_smith: that doesn't sound right

15:21 justin_smith: could be pebkac, I will double check and try this again

15:21 hiredman: the jvm doesn't even have the concept of a class being closed, since they are all "closed" to begin with

15:22 so getting an error about classes being closed makes no sense

15:22 justin_smith: let me get that exact message again

15:26 hiredman: the problem is that if I define some subset of the protocol (to my new record type for example) and leave any of the methods unspecified, it is not inheriting from java.lang.Object, but instead just not finding a method

15:26 the previous was my misunderstanding/misremembering the problem

15:27 llasram: justin_smith: That's the way protocols work: all-or-nothing far a given implementation

15:27 justin_smith: llasram: OK, so I have no option for "specialize these two methods, and leave the other 9 at the default"

15:27 llasram: justin_smith: You can, just have to do it differently

15:27 justin_smith: do tell

15:28 llasram: You can use `extend` to pass in a map of implementations. The map is a plan map of protocol-function keyword to Clojure function. You can define a base implementation map, then `assoc` in specific implementations

15:28 hiredman: it is an a la cart thing, separating inheretence hierarchy from implmentation sharing

15:28 llasram: justin_smith: Check out clojure.java.io for a pretty good example

15:28 hiredman: if you want to share implementation you can create a custom macro for templating

15:29 justin_smith: cool, thanks guys

15:29 I guess I just expected it to act like implicit subclass inheritance

15:32 seangrove: technomancy: Is this still the way to add local jars?

15:32 https://www.pgrs.net/2011/10/30/using-local-jars-with-leiningen/

15:35 bobajett: is "cond" different in clojure from elisp in that only one expression is allowed in clojure for a conditional?

15:37 hyPiRion: no, multiple expressions are allowed

15:37 coventry: bobajett: The syntax is different in that in elisp each pair is wrapped in an extra set of parens. Otherwise, it's the same.

15:38 hyPiRion: ,(let [n 10] (cond (zero? n) :zero, (neg? n) :neg, (pos? n) :pos))

15:38 clojurebot: :pos

15:41 bobajett: ,(let [n 1] (cond (< n 0) :neg, :else (print "hello") (print "goodbye")))

15:41 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: cond requires an even number of forms>

15:41 bobajett: hyPiRion: *I think* in elisp you can have multiple expressions follow a test?

15:42 justin_smith: bobajett: oh yeah, likely, because of the extra set of parens you could have an implicit do there

15:42 coventry: bobajett: Oh, yes, that's true.

15:42 hyPiRion: bobajett: yeah, that's true. You can do that in Clojure with the `do` macro

15:42 justin_smith: with clojure you can do that with do

15:43 hyPiRion: special form, rather

15:43 bobajett: ah awesome! you guys just cleared up my confusion! I need "do" to acheive the sme thing! thanks!

15:45 OscarZ: if i have a function x returning a vector with 3 values like [1 2 3] and i want to use that vector as parameters for some other function y so that it would called just like (y 1 2 3) .. can i do that ?

15:45 i know i can pass a vector and destructure it

15:45 dnolen: React is pretty incredible, lazy tree construction, faster diffing w/ immutable values - https://gist.github.com/swannodette/7813518

15:45 hyPiRion: OscarZ: use apply: `(apply y [1 2 3])`

15:45 dnolen: this boilerplate-y but it can made more awesome

15:46 hyPiRion: ,(apply + [1 2 3 4 5]) ; == (+ 1 2 3 4 5)

15:46 clojurebot: 15

15:46 OscarZ: hyPiRion: nice, i didnt realize that :) thanks

15:48 hyPiRion: np

15:49 dnolen: eric_normand: not sure how you are using React, but I have a basic approach that I think could be taken further ^

15:49 noprompt: dnolen: regarding the discussion in the gist, i'm a bit confused. am i to understand the direct use of renderComponent is less performant than the use of createClass + renderComponent?

15:50 eric_normand: dnolen: more than the gist you posted a few days ago?

15:50 coventry: dnolen: A few comments in these gists would hugely broaden their reach.

15:50 dnolen: For instance, I have no idea what (pure) does, and I've watched Pete Hunt's talk.

15:50 eric_normand: dnolen: I'm just using renderComponent with DOM

15:51 dnolen: trying to finish the app before I start refactoring

15:51 dnolen: though I would love hiccup style (at runtime, not a macro)

15:51 noprompt: eric_normand: if you're willing to accept the performance tradeoffs that should be fairly easy to do.

15:52 dnolen: one second

15:53 noprompt: eric_normand: it's fairly easy to build the hiccup style parser/compiler with extend-protocol.

15:53 dnolen: noprompt: coventry: eric_normand: gist updated with supporting code

15:53 noprompt: thanks.

15:53 eric_normand: dnolen: thanks

15:54 coventry: thanks x 3

15:55 eric_normand: noprompt: where is performance tradeoff?

15:56 dnolen: eric_normand: noprompt: in my gist I use createClass to just make a wrapper component

15:57 noprompt: eric_normand: i'm not sure if there is one, that's why i'm asking. i was confused by some of the comments.

15:57 eric_normand: dnolen: does that help in some way?

15:57 dnolen: that is, why keep the state in the component?

15:57 dnolen: eric_normand: I don't think you can write faster Rect code than what I've done

15:57 in fact it should blow away what people are doing in JS w/ React

15:57 noprompt: does (enable-console-print!) do what it says on the tin?

15:57 dnolen: out of the water

15:57 noprompt: it does

15:58 pure create a node for diffing

15:58 since we're in CLJS we're using immutable values

15:58 eric_normand: dnolen: because of the state dirtiness check?

15:58 dnolen: but that means we can use *identity* checks

15:58 none of this horrible JS object traversal crap

15:59 eric_normand: dnolen: that makes sense, but is it faster than not having state?

15:59 dnolen: and traversing the virtual dom?

15:59 dnolen: eric_normand: what state?

16:00 eric_normand: dnolen: the value in (defmacro pure [value children]

16:00 dnolen: eric_normand: that's not really state

16:00 it's just an immutable value used for diffing

16:01 eric_normand: dnolen: if I understand correctly, you are saying "re-render all children if this value is different from last time"

16:01 dnolen: eric_normand: yes, this everything that React does for JS, but faster and in a functional non-oopy style

16:02 eric_normand: dnolen: "but if it is the same, don't re-render"?

16:02 dnolen: eric_normand: yep

16:02 so you can have a massive graph of UI

16:02 update one tiny piece of it

16:02 and this will BLAZE

16:03 eric_normand: dnolen: yeah, makes sense

16:03 dnolen: you just have to select your value carefully

16:03 dnolen: eric_normand: no, it's just the value that represent the value of the component

16:04 eric_normand: dnolen: right. but it means that if your children were depending on a global atom or something, you need to put the derefed atom into the value

16:06 dnolen: eric_normand: right, or you could just propagate that value into their "state", which is probably what you should do 95% of the time.

16:06 eric_normand: dnolen: and if that atom had a map with a bunch of irrelevant stuff, now I need to get rid of the irrelevant stuff

16:07 dnolen: that kind of invalidates the way I just designed this program

16:08 dnolen: global state in an atom

16:08 dnolen: and render the current value of the atom functionally

16:08 dnolen: this is still just a sketch, but I think it could be cleaned up a taken much further - this is going to rock :)

16:09 seangrove: Oh, god damn Java inner classes

16:09 eric_normand: dnolen: but having the comparison value as you do in the gist is awesome

16:09 dnolen: so I'm going to play with it and see where it goes

16:09 dnolen: eric_normand: cool

16:10 eric_normand: dnolen: I'm not sure if this happens generally, but in my case, the dom tree corresponds pretty closely to the state tree

16:10 dnolen: which would benefit a lot from this

16:10 dnolen: I am very excited about React right now

16:11 dnolen: the first "framework" that actually does some of the dom work for you :)

16:11 dnolen: eric_normand: yes this should always be true. We can represent UI as ... maps & vectors!

16:11 and update it efficiently

16:11 more efficiently than you ever could with popular JS patterns

16:14 egosum: Is there a preferred way to run tests (faster than lein test)?

16:15 llasram: egosum: From the REPL

16:16 eric_normand: egosum: for fast testing, I use clojure-test-mode in emacs

16:16 bitemyapp: TimMc: that's pretty rough, I usually make a trace-filterer and customize the tracing behavior to change the way the args get printed (elision, summarization, etc)

16:16 egosum: eric_normand llasram: that seems introduces all sorts of incidental bugs—reordering/renaming vars and the old vars persist in the running JVM. Or am I doing something wrong?

16:17 SegFaultAX: egosum: Reload the namespace(s) before running.

16:17 eric_normand: dnolen: clojurescript is paying its own way :)

16:17 TimMc: bitemyapp: In this case it's ring middleware, so I should probably use some ring-specific tracer, but... ugh.

16:17 eric_normand: dnolen: does react use google closure compatible requires/provides?

16:17 dnolen: can it be closure optimized?

16:17 dnolen: eric_normand: :) something like React is honestly the last piece of the puzzle for the CLJS story

16:18 egosum: SegFaultAX: does clojure-test-mode handle that for you?

16:18 eric_normand: dnolen: Last? that's optimistic

16:18 dnolen: eric_normand: React is ~27K gzipped, this is acceptable for what it provides a "view" story

16:18 eric_normand: heh, well last for me - we know have the pieces to compete with JS MVC approaches

16:19 s/know/now

16:19 eric_normand: dnolen: but core.async to get local event loops and React for a functional dom:

16:19 SegFaultAX: egosum: Dunno, not an emacs user.

16:19 egosum: Somehow I doubt it though.

16:19 eric_normand: dnolen: I have to say it: it also competes with pedestal

16:19 dnolen: (and wins in my book)

16:19 SegFaultAX: eric_normand: What does?

16:20 technomancy: egosum: it does

16:20 egosum: technomancy: thanks—just started reading the source

16:20 dnolen: eric_normand: yes but pedestal can't win against React for this specific use case since it wants to do more - React focuses on specific thing.

16:20 s/on/one

16:20 llasram: technomancy: Oh, it does? I must have an old version. I don't rename tests frequently, but never noticed it wiping and reloading the NS before

16:20 eric_normand: dnolen: true, pedestal has a lot of developer tools, etc

16:20 bitemyapp: TimMc: yeah probably. are your requests really fat or something?

16:20 egosum: technomancy: i'm guessing you're using clojure-test-mode, then?

16:21 bitemyapp: TimMc: or the responses, I guess, would be?

16:21 egosum: (aside from you know, just writing it)

16:21 technomancy: egosum: not really

16:21 egosum: in addition to*

16:21 bitemyapp: TimMc: you can just summarize the "body" of the response if it's spamming you.

16:21 egosum: technomancy: what are you using these days?

16:21 eric_normand: dnolen: but it kind of punts on the UI, which I think is still the hardest part of web frontend

16:21 bitemyapp: I wouldn't recommend summarizing the request unless something strange is going on.

16:21 dnolen: eric_normand: but I also don't see really see them as incompatible. I think Pedestal could scale bake and integrate with how React works

16:21 eric_normand: the other cool bit is that the server can render the right HTML for a particular UI state

16:22 eric_normand: and the client will know exactly what's going on

16:22 "scale bake" "scale back"

16:22 technomancy: llasram: it just reloads, not wipe+reload

16:22 eric_normand: dnolen: agreed re: scaling back

16:23 dnolen: the new branch of pedestal with core.async is way more understandable

16:23 dnolen: something similar with a virtual dom for the view would be great

16:23 technomancy: egosum: I'm working on replacing clojure-test-mode with something that's not hard-coded to emacs

16:23 egosum: but also I'm not really writing any tests

16:23 llasram: technomancy: That's what I thought. I believe the specific issue under discussion is the way deleted/renamed test vars hang around

16:23 eric_normand: dnolen: about rendering on the server, do you mean running React in node.js?

16:24 dnolen: eric_normand: no you don't need the whole React infrastructure server side

16:24 bitemyapp: egosum: (require '[clojure.tools.namespace.repl :refer [refresh]]) (refresh) (require '[clojure.pprint :refer [pprint]]) (require '[clojure.data :refer [diff]]) (require '[clojure.repl :refer :all])

16:24 dnolen: eric_normand: just something that generates DOM w/ checksum attributes that's it

16:24 egosum: technomancy: Fair enough. I'm writing them as additional documentation, mostly. clojure-test-mode will work for me (thanks)

16:24 bitemyapp: that's my standard "test loop" macro in Emacs.

16:24 eric_normand: dnolen: I see. the client builds the virtual dom from the real dom?

16:25 dnolen: that's pretty cool.

16:25 dnolen: eric_normand: it doesn't need to build anything :) unless the user clicks something

16:25 eric_normand: and boom, React knows what to change!

16:25 eric_normand: dnolen: that's a compelling story.

16:25 dnolen: fuck yeah it is

16:25 hyPiRion: bitemyapp: heard of Stuart Sierra's development loop? That one's kind of nifty for stuff

16:26 coventry: egosum, technomancy, llasram: I'v been meaning to experiment with putting something like (remove-ns 'ns-symbol) before the ns form to prevent the confusion from stale vars. Anyone tried something like that?

16:26 bitemyapp: hyPiRion: that's sort-of what I do.

16:26 hyPiRion: except I don't go full architecture astronaut like him.

16:26 eric_normand: dnolen: and if you're sharing hiccup between the two, no big maintenance cost

16:26 technomancy: coventry: in slime you could do C-c C-l to wipe a namespace before loading it

16:26 hyPiRion: bitemyapp: hehe

16:26 dnolen: eric_normand: yep

16:26 technomancy: coventry: I don't think it's been ported yet

16:26 llasram: coventry: I think that would cause doom as vars in other NSs find the NS they used to refer to is gone

16:26 bitemyapp: hyPiRion: I do avoid def'ing bare vars with side effects in namespaces though.

16:27 because it's fucking stupid.

16:27 and it's bad for growing your code.

16:27 hyPiRion: or vars with mutable/global state in it

16:27 oh, the pain

16:27 eric_normand: clojure: better than Java and use the java ecosystem

16:27 technomancy: bitemyapp: ugh we got a bunch of slamdhound bug reports from people who just loooove doing that

16:27 eric_normand: clojurescript: better than Javascript, and use the js ecosystem!

16:27 bitemyapp: bare vars pointing to values can't "grow" as well as functions that return data things are dependent on.

16:28 eric_normand: let those other guys code up a good library, we wrap it, and it's better!

16:28 does clojure clean up everything it touches? :)

16:28 hyPiRion: does Clojure clean up anything at all? :p

16:29 bitemyapp: technomancy: http://i.imgur.com/GwSrBuw.jpg

16:29 eric_normand: no

16:29 eric_normand: bitemyapp: example?

16:30 bitemyapp: eric_normand: no types

16:30 coventry: technomancy: Thanks, will take a look.

16:31 eric_normand: bitemyapp: can you give me an example of something that clojure has wrapped that is not better than the original? Not saying it doesn't exist.

16:32 bitemyapp: eric_normand: oh, wrapped? then no.

16:32 eric_normand: bitemyapp: that's what I meant :)

16:32 bitemyapp: eric_normand: I mean, I could cherry-pick libraries, but at the language level, no.

16:32 eric_normand: there are many terrible libraries though.

16:32 terrible, terrible libraries.

16:32 eric_normand: bitemyapp: yeah, agreed

16:32 bitemyapp: like Korma and it's relationship with c.j.j

16:33 eric_normand: bitemyapp: I don't like korma either. Did too much

16:33 bitemyapp: eric_normand: I'm a maintainer on Korma, I think the basic design and idea is solid, but it needs to be reworked.

16:33 hyPiRion: Well actually, when thinking about it, Clojure has wrapped regexes nicely

16:33 bitemyapp: hyPiRion: what?

16:34 hyPiRion: like, Java regexes

16:34 bitemyapp: hyPiRion: what?

16:34 what was wrapped?

16:34 tommo: regex's are not specific to java

16:35 bitemyapp: tommo: I'm sure everybody here knows that. He's probably talking about the API.

16:35 technomancy: "Everything's a function in Clojure; it's great!" / "Oh cool. Even regexes?" / "No, not regexes."

16:35 eric_normand: bitemyapp: the classes Pattern, Match, etc

16:35 technomancy: =(

16:35 eric_normand: technomancy: I cried when I heard that, too

16:35 bitemyapp: wouldn't that have effectively turned strings into functions?

16:35 eric_normand: just string literals with # in front

16:36 but I don't know how it should work

16:36 technomancy: bitemyapp: strings are final

16:36 hyPiRion: bitemyapp: more like actually writing them, like #"\\" vs "\\\\" (as an example)

16:36 eric_normand: should it be like re-match, re-find, re-seq?

16:36 technomancy: (regexes are final too, but no one in the history of clojure has ever used regexes for interop, so it doesn't matter)

16:36 osa1: hello everone. I'm currently playing with LightTable, is there a way to use it's browser and editor for ClojureScript currently?

16:37 eric_normand: btw, I'm not saying clojure makes things perfect

16:37 bitemyapp: hyPiRion: oh, yeah, that's an improvement.

16:37 eric_normand: have you used a language with a nice type system?

16:37 technomancy: that is the official story anyway. ("and that's final.")

16:37 bitemyapp: haha; I asked him that like just last week

16:38 eric_normand: bitemyapp: never. Only used Java, C, and Haskell.

16:38 coventry: Bwahaha

16:39 bitemyapp: coventry: arg/resp elision.

16:39 coventry: bitemyapp: Sorry, I don't follow.

16:40 eric_normand: Haskell's type system has some benefits.

16:41 And maybe it's not the type system's fault, maybe it's just the language itself.

16:41 (it's hard to say when the type system is so integral to the language)

16:43 I can say this: I miss types at times.

16:45 I think row types may have solved a lot of what I don't like about Haskell, but I'm not sure, since I never used row types

16:46 coventry: Where can I read about row types?

16:46 google(haskell row types) returns a thicket.

16:46 brehaut: i think puffnfresh might have an introduction to them on his blog

16:47 http://brianmckenna.org/blog/row_polymorphism_isnt_subtyping perhaps?

16:47 coventry: Thanks, brehaut

16:47 brehaut: nope its not really an intro. ignore me

16:48 maybe it'll help anyway

16:48 coventry: Yeah, I can understand that.

16:49 eric_normand: coventry: this *may* be useful: http://cufp.org/sites/all/files/slides/2013/kmett.pdf

16:53 coventry: the answers to this question look decent: http://www.reddit.com/r/haskell/comments/1qol5n/ermine_presentation/

16:54 coventry: the main reason I was thinking row types was because of how we use maps in clojure: just look at the keys you care about, ignore the rest

16:54 S11001001: eric_normand: now that core.typed has heterogenous map types perhaps you'd like to try it? :)

16:54 eric_normand: coventry: this reduces coupling between modules

16:55 S11001001: core.typed is on my list of things to try

16:55 coventry: eric_normand: Thanks, those slides are pretty challenging, but I'll take a look.

16:56 eric_normand: coventry: it's basically saying "this function accepts any type that has field 'a' of type 'Int', regardless of other fields and their types"

16:56 coventry: which is a great form of polymorphism that supports a lot of reuse

16:56 coventry: Oh, cool. That is a great idea.

16:57 bitemyapp: coventry: he's using the wrong terminology, you want "row polymorphism"

16:58 coventry: lenses + row polymorphism is how the cool kids write Haskell.

16:59 row polymorphism is built on nested pairs (tuples)

16:59 you can write your code as if you were writing in a dynamically typed concatenative language if you wanted (in Haskell)

16:59 not sure why you would, but you could.

16:59 eric_normand: but that's how it goes with types: you always want more :)

16:59 bitemyapp: eric_normand: row polymorphism is less, not more.

17:00 people that want more are hacking Agda and Idris, not fucking with tuples.

17:00 coventry: It's a broader domain for your function, so in that sense it's more. :-)

17:00 bitemyapp: we're talking about types.

17:00 and how to leverage them. it's not more.

17:02 eric_normand: bitemyapp: but then you want more expressive types

17:02 bitemyapp: I need scotch for this conversation to continue and I have none.

17:02 eric_normand: it's a multi-faceted, multi-dimensional subject.

17:03 and not one you're doing a very good job of talking about in a meaningful capacity, so lets drop it before dnolen has a hairy canary.

17:03 eric_normand: bitemyapp: agreed. I would love to be schooled, but not now.

17:03 bitemyapp: I don't want to school anybody, I want people to stop strawmanning type systems.

17:04 eric_normand: bitemyapp: ok, let's stop talking about it.

17:04 bitemyapp: let's supposed to be a contraction of "let us"?

17:04 is let's*

17:05 serious question.

17:05 eric_normand: yes

17:05 coventry: $google let's let-us

17:05 lazybot: [let's - Wiktionary] http://en.wiktionary.org/wiki/let's

17:05 bitemyapp: good to make certain.

17:06 eric_normand: bitemyapp: good change of subject :)

17:06 bitemyapp: eric_normand: there's no intent here, I was more interested in verifying that than entertaining a strawman.

17:07 noncom: as far as i understand, every anonymous (fn) creates a new class, so it can ruin permgen, right?

17:07 eric_normand: bitemyapp: bad change! you went back!

17:07 noncom: if anused too much i mean

17:07 s/anused/abused :)

17:07 bitemyapp: noncom: write a test, find out.

17:07 eric_normand: noncom: I might be wrong, but I believe that was fixed

17:08 noncom: but a test would do the trick!

17:08 coventry: noncom: This was discussed on IRC recently. I believe the conclusion was that it's not a problem.

17:08 hyPiRion: hm

17:08 bitemyapp: I'll never understand programmer hesitation to employ empiricism.

17:10 noncom: ,(let [a (repeatedly 999999999 (fn [] (fn [x] (+ 1 x))))] a)

17:10 clojurebot: (#<sandbox$eval29$fn__30$fn__31 sandbox$eval29$fn__30$fn__31@1a9759d> #<sandbox$eval29$fn__30$fn__31 sandbox$eval29$fn__30$fn__31@68a394> #<sandbox$eval29$fn__30$fn__31 sandbox$eval29$fn__30$fn__31@1cb6ca2> #<sandbox$eval29$fn__30$fn__31 sandbox$eval29$fn__30$fn__31@491938> #<sandbox$eval29$fn__30$fn__31 sandbox$eval29$fn__30$fn__31@116bd1d> ...)

17:10 hyPiRion: nah, won't evaluate all

17:10 ,(last (repeatedly 1e7 #(fn [a b] (a (b a)))))

17:10 clojurebot: #<sandbox$eval61$fn__62$fn__63 sandbox$eval61$fn__62$fn__63@139bfb>

17:10 noncom: hmmmm

17:12 coventry: Good to know. I didn't realize clojure's print functions are smart enough to only evaluate the displayed parts of a lazy function.

17:12 s/function/structure/

17:12 TimMc: bitemyapp: But I only have 500 lives left! Every compiler error consumes one.

17:14 eric_normand: (loop [] (fn []) (recur)) runs at 140% CPU and 200MB memory

17:14 TimMc: noncom: Every place you write fn in the code corresponds to a class; every time that part of the code is executed, a new *instance* of that class is created.

17:15 coventry: So I guess you could hose the permgen by (eval)ing a lot of fn.

17:15 TimMc: To ruin permgen, you'd need something like (loop [] (eval '(fn [])) (recur))

17:15 noncom: no guys, don't worry, i'm just stupid

17:16 oh, that's what.. i'd never guess

17:16 bbloom_: the more js/rb i write, the more i <3 clojure. ::group hug::

17:16 noncom: so evaling an (fn) actually creates a class

17:16 TimMc: Compiling it, yes.

17:17 noncom: still ain't really used to that part of lisp

17:17 bitemyapp: bbloom_: you made a serious mistake following me on Twitter.

17:17 bbloom_: bitemyapp: ok fine. you're unfollowed

17:17 bitemyapp: bbloom_: good, you're not invited to the salad.

17:18 coventry: How does a set of eval'd fn's not get a corresponding set of classes?

17:18 bitemyapp: bbloom_: you couldn't handle it anyway.

17:18 TimMc: noncom: You can see in your example above that your inner fn's class is sandbox$eval29$fn__30$fn__31 and you keep having new instances of it.

17:18 seangrove: I have an announcement: I will be attending the meteor.js devshop/meetup tonight instead of the clojure meetup.

17:19 bitemyapp: seangrove: I'm disowning you.

17:19 * seangrove hangs his head

17:20 noncom: so that fn does not really get evaled?

17:20 dnolen: seangrove: shameful

17:20 bitemyapp: seangrove: there are many things that are suitable excuses for not coming to the Clojure meetup, but tonight is the lightning talk one!

17:20 noncom: oh well..

17:20 seangrove: S'alright, I'm going to feel the crowd out a bit.

17:20 bbloom_: seangrove: you're going to discredit meteor, right? :-P

17:20 `cbp: (dec seangrove)

17:20 lazybot: ⇒ -3

17:20 bitemyapp: (dec seangrove)

17:20 lazybot: ⇒ -4

17:20 seangrove: Jesus christ, I must have the lowest karma in here now

17:20 technomancy: wow, harsh

17:20 bbloom_: aw c'mon

17:20 bitemyapp: seangrove: leave your badge and lambdas on the desk.

17:20 bbloom_: (inc seangrove)

17:20 lazybot: ⇒ -3

17:20 llasram: (inc seangrove)

17:20 lazybot: ⇒ -2

17:20 bbloom_: i think he deserves 0 karma at worst

17:20 bitemyapp: $karma bitemyapp

17:20 lazybot: bitemyapp has karma 15.

17:20 bitemyapp: how am I higher karma than seangrove?

17:20 dnolen: seangrove: I recently read the scaling Meteor.js post that was on HN, I'm really surprised people use it

17:20 bbloom_: (dec bitemyapp)

17:20 lazybot: ⇒ 14

17:20 bitemyapp: karma isn't karmic :(

17:21 seangrove: bitemyapp: Sacha Greif is staying with me and presenting at the meetup, so that's the reason I'm going

17:21 dnolen: (inc seangrove)

17:21 lazybot: ⇒ -1

17:21 bbloom_: seangrove: you're at -1

17:21 technomancy: I would inc him, but I am a bit wary of the ecological implicaitons of http://finalfantasy.wikia.com/wiki/Meteor_(Final_Fantasy_VII)

17:21 bitemyapp: (inc seangrove)

17:21 lazybot: ⇒ 0

17:21 bitemyapp: seangrove: forgiven.

17:21 seangrove: I tried to convince myself that there's some overlap with meteor.js and cljs, but just can't really find any.

17:21 bbloom_: seangrove: that's a sentinel value for "unbounded"

17:21 bitemyapp: SG is a good reason.

17:21 technomancy: bitemyapp: maybe because he used to go by seangrov` all the time

17:21 bitemyapp: $karma seangrov`

17:21 lazybot: seangrov` has karma 0.

17:21 technomancy: (identity seangrov`)

17:21 lazybot: seangrov` has karma 0.

17:21 technomancy: hm

17:21 bitemyapp: nope.

17:21 he came by the negative karma honestly :)

17:22 seangrove: Haha

17:22 More or less

17:22 hyPiRion: (inc seangrove)

17:22 lazybot: ⇒ 1

17:22 seangrove: I am curious to talk to some of the meteor guys about react though

17:22 They're all pretty impressive distributed systems people

17:22 bitemyapp: what?

17:22 clojurebot: what is cells

17:22 bbloom_: seangrove: meteor is much more about the model layer

17:22 react doesn't provide any model layer stuff

17:22 bitemyapp: seangrove: I don't think you mean distributed systems.

17:22 seangrove: Curious to hear what they're doing around simplifying ui programming

17:23 bitemyapp: They're mostly very impressive MIT people who were working on distributed systems before

17:23 bbloom_: also react is all about taking out the stupid 2-way data binding from your views... why would you want to add 2-way databinding to your models too?

17:23 seangrove: Well, I don't know "mostly" anymore... about a year ago anyway

17:23 bbloom_: "you know, my database is pretty nice to work with. i'd really like to make it more like my annoying UI code"

17:23 booo.

17:23 bitemyapp: there's something perverse here.

17:24 seangrove: bbloom_: Yeah, so I'm not sure I see a huge win with meteor beyond a cool use of ddp

17:24 But smart people are interesting to talk to, and often have surprising insight

17:24 bbloom_: http://www.meteor.com/blog/2012/03/21/introducing-ddp says:

17:24 "DDP is a standard way to solve the biggest problem facing client-side JavaScript developers: querying a server-side database, sending the results down to the client, and then pushing changes to the client whenever anything changes in the database."

17:24 that is *far* from the biggest problem in any javascript client app i've ever used

17:25 bitemyapp: Meteor is as far from how Clojure people usually like to design things as I can possibly imagine.

17:25 it also solves a solved non-problem in the worst way possible using semantics that don't even really make sense at scale.

17:25 (declarative, idempotent expression of intent > stateful bit smashing) for talking to the backend.

17:26 bbloom_: when dnolen and i talked to petehunt the other day he mentioned https://github.com/petehunt/react-graph

17:26 david & i suggested he study datomic :-P

17:26 alandipert: bbloom_: DDP looks sane, and afaict the rest of meteor is par-for-blub while being very nicely documented

17:26 bbloom_: but his readme shows he's on the right track :-)

17:26 seangrove: bbloom_: Yeah, but I'm working on some UI stuff, so curious at least to see how they're approaching it over the next year or so

17:27 I'm really blown away at how bad writing ui's in js/cljs is right now, amazingly bad

17:27 bitemyapp: bbloom_: that react-graph repo is something I've wanted for awhile.

17:27 historical client-state.

17:27 toss in pluggable asynchronous synching to a backend and you're in business.

17:28 bbloom_: bitemyapp: i dunno if pete has been in here yet, but the next time he's on irc, i'll make sure he starts idling in here

17:28 dnolen: seangrove: you should look more closely at React, bbloom was dead on

17:28 bitemyapp: bbloom_: plzdo.

17:28 dnolen: seangrove: I was afraid it was good tech but couldn't be used in a functional way from CLJS - happy to know I'm wrong

17:28 bbloom_: (inc reactjs)

17:28 lazybot: ⇒ 1

17:29 alandipert: (+ reactjs 0.2)

17:29 dnolen: bbloom_: so I have a basic approach to reactjs that should be faster than what React can offer JS devs based on petehunt's suggestions

17:29 alandipert: oh

17:29 bbloom_: dnolen: nice. gist?

17:29 dnolen: bbloom_: https://gist.github.com/swannodette/7813518

17:29 bbloom_: alandipert: i can't comment on the impl of DDP w/o digging in to more details

17:29 seangrove: dnolen: I'm working on combining react in a pluggable way with hiccup-syntax that can compile out to various implementations, bootstrap/foundation/closure ui, etc.

17:30 dnolen: bbloom_: as suspected we can use =, and we can instantiate the tree only when we need it

17:30 bbloom_: dnolen: fast equality checks are like the best thing to ever happen to anything ever

17:30 dnolen: bbloom_: we can rerender from the root and it will be fast, and we don't need to adopt any goofy OO stuff

17:30 bbloom_: dnolen: told you :-P

17:31 dnolen: bbloom_: ;)

17:31 alandipert: bbloom_: i've only read https://github.com/meteor/meteor/blob/master/packages/livedata/DDP.md

17:31 bitemyapp: I really wish Clojure had docstrings.

17:31 bbloom_: dnolen: i think this is like the 3rd time you ignored me for 6 months until you realized i was right. you should start "give it 5 minutes" to more random shit i say :-)

17:32 dnolen: bbloom_: haha noted

17:32 ivan: bitemyapp: do you mean triple-quoted strings?

17:32 bbloom_: alandipert: i'll try to look in a bit

17:33 noprompt: react is nuts.

17:33 and by nuts, i mean awesome.

17:33 alandipert: bbloom_: oh, not recommending, so no worries :-)

17:34 bitemyapp: ivan: yes.

17:34 I am tired of escaping "

17:34 eric_normand: source maps in cljs are rocking my world!

17:34 OscarZ: whats react about? some new web framework? :)

17:34 bbloom_: alandipert: tab closed. :-P

17:35 ivan: OscarZ: https://www.youtube.com/watch?v=x7cQ3mrcKaY

17:35 bbloom_: dnolen: looking at your gist. yeah the single "value" key is the trick i was suggesting

17:35 so their internal shallow copy doesn't cause us issues

17:36 bitemyapp: OscarZ: frontend stuff.

17:37 OscarZ: ok.. are there some new revolutionary ideas ?

17:37 noprompt: OscarZ: i supposed that would be your call.

17:37 bitemyapp: OscarZ: revolutionary? no, but people are starting to move beyond callbacks (the goto of async).

17:38 There are no revolutions in computer science because blub programmers exist.

17:38 noprompt: :(

17:38 bitemyapp: only incremental dragging of intransigent lazy-bones into the future.

17:38 noprompt: ;_;

17:38 dnolen: bbloom_: yeah, React is pretty rocking. I'm curious to see if we can beat Backbone on the TodoMVC benchmark w/ this

17:38 bbloom_: if we can you can expect a blogpost :)

17:38 bitemyapp: noprompt: be happy.

17:39 noprompt: :)

17:39 XD

17:39 bitemyapp: noprompt: http://i.imgur.com/GwSrBuw.jpg

17:40 noprompt: ugh, i picked up a cold over the holidays and getting information in to my brain is like trying to give a dog medicine that isn't wrapped in bologna.

17:40 OscarZ: yeah i havent done much front end but enough to know what the callback mess... i saw some tutorial on pedestal, it uses some kind of queue to make things sequential

17:40 bitemyapp: noprompt: My insomnia flared up and I started eating less. I'm living on coffee, tea, and hatred these days.

17:41 asteve: noprompt: so I have to trick you into thinking it's food and then throw it at your face so you catch it?

17:41 bitemyapp: OscarZ: it's closer to a core.async DAG of channels, but yeah, close enough.

17:41 bbloom_: OscarZ: apparently the pedestal stuff has changed quite a bit recently. i have no idea what it's like now

17:41 bitemyapp: noprompt: also stop reminding me how I don't have a dog :(

17:41 bbloom_: there are some core.async agitators in the ranks.

17:42 noprompt: dnolen: this is a great hack.

17:42 OscarZ: i wanted to do things like.. "wait these 3 callbacks to do their thing and then do this"

17:42 theres deferred in jQuery for that.. but thats all i used..

17:42 bitemyapp: OscarZ: core.async is good for that.

17:42 OscarZ: i guess these frameworks are for sorting this kind of thing?

17:43 dnolen: noprompt: heh, I wouldn't call it a hack :) I came to that solution after picking petehunt and balpert's brain in #reactjs

17:43 OscarZ: cool.. i should look into core.async

17:43 can core.async be used on client side as well ?

17:43 dnolen: noprompt: but you maybe you just meant it's cool code, then I agree w/ that

17:43 bitemyapp: OscarZ: only because of CLJS, but yes.

17:44 OscarZ: being used in CLJS was a design goal for core.async.

17:44 seangrove: bbloom_: It looks like pedestal and react independently converged on quite a few ideas

17:44 bitemyapp: ~reactjs

17:44 clojurebot: reactjs is a poorly implemented comonad

17:44 bbloom_: no, no it isn't

17:44 clojurebot: forget reactjs

17:44 clojurebot: Titim gan éirí ort.

17:44 bitemyapp: clojurebot: forget bbloom

17:44 TimMc: Hmm, eval'ing '(fn []) in a tight loop is generating 1000 classes per second, but they're getting cleaned up.

17:44 clojurebot: Huh?

17:44 noprompt: dnolen: i'm of the mind that everything is pretty much a hack client side. haha! but yes, it's definitely cool.

17:44 bitemyapp: ~bbloom is afraid of comonads

17:44 clojurebot: In Ordnung

17:45 OscarZ: bitemyapp: cool.. thought its more for server side processing queues etc..

17:45 prolly can be used for that too of cos

17:45 noprompt: :(

17:45 bitemyapp: OscarZ: it's good for anything async. Really.

17:45 OscarZ: I use it to clean up callback bullshit all the time.

17:45 server and client-side.

17:45 OscarZ: cool

17:45 bitemyapp: cultureshipname: GCU: Only Free Men Can Negotiate

17:47 TimMc: http://i.imgur.com/7WliQqW.png

17:48 noprompt: dnolen: this plus core.async. i wanna fall out my chair. but i have hard wood floors.

17:50 dnolen: so i guess my next question would be, how much stuff do you put in a component? i mean how big should these things be?

17:51 bbloom_: noprompt: as small as possible but no smaller

17:51 also worth asking in #reactjs

17:51 noprompt: bbloom_: good point.

17:52 bbloom_: i was more or less thinking of nesting components.

17:53 i think it's time to go get some pho.

17:55 dnolen: noprompt: I suspect they can be very large for us

17:55 noprompt: at some point I'd like to do some benchmarks

18:01 bitemyapp: TimMc: looks like the GC is keeping up with the stuff that fell out of scope. Seems fine to me.

18:03 TimMc: bitemyapp: Yeah, but it shows that I was wrong about it messing up permgen.

18:04 That also means I can't knock over clojurebot with this:

18:04 ,(let [evil ((symbol "eval") (ns-publics 'clojure.core))] (dotimes [_ 500000000000] (evil '(fn []))))

18:04 bitemyapp: TimMc: it's churning the PermGen.

18:05 clojurebot: Execution Timed Out

18:05 bitemyapp: TimMc: you weren't wrong about that, you were just wrong about how smart it is about scoping.

18:05 TimMc: there's still possibly a way to smash the PermGen with this.

18:05 TimMc: Oh, heh.

18:05 bitemyapp: spawn threads + long sleep.

18:05 shouldn't be able to harvest then. I would think.

18:06 new anonymous fn in each executable thread before it sleeps.

18:06 OscarZ: after long time lurking i've been starting to actually code Clojure lately.. doing project euler exercises.. learning basic stuff about map, filter, sequences etc..

18:06 bitemyapp: I don't think Euler is a good way to learn Clojure.

18:06 4Clojure is better for learning the API.

18:07 bbloom_: (inc 4clojure)

18:07 lazybot: ⇒ 2

18:07 OscarZ: yeah was going to ask what you guys think would be a good next step.. what APIs or concepts to learn

18:07 seangrove: I'd agree that 4Clojure is probably a reasonably good approach to start with

18:09 bitemyapp: OscarZ: 4Clojure and clojure book are my usual recommendations.

18:09 ~clojurebook

18:09 clojurebot: Excuse me?

18:09 bitemyapp: ~clojurebook is http://clojurebook.com

18:09 clojurebot: Ik begrijp

18:10 bitemyapp: OscarZ: ^^

18:10 OscarZ: was impressed how easy it is to "compose" stuff from smaller building blocks

18:11 bitemyapp: ok.. ill check it out.. i have a clojure book on kindle that ive been reading when ive had time.. Programming Clojure i think

18:11 tommo: im working through that too, its really good

18:15 OscarZ: yeah its a nice book.. ive had it for some time, have read a chapter or two once in a while.. should have started actually coding earlier :)

18:16 sritchie: magnars: would it make sense to add gzip support?

18:17 for static resources?

18:18 bitemyapp: sritchie: to what?

18:18 sritchie: to optimus

18:18 though, from looking at the discussion,

18:18 bitemyapp: sritchie: you shouldn't be serving static assets from something like that.

18:18 sritchie: what do you mean

18:18 something like optimus?

18:19 OscarZ: 4clojure looks nice.. i think ive tried it a bit long time ago

18:19 bitemyapp: sritchie: if you care enough about performance to worry about gzipping, you should be statically compiling assets and deploying to an nginx server or a CDN.

18:19 sritchie: it looks like you get more wins from adding gzip as a middleware and compressing any response, dynamic html included

18:19 bitemyapp: I'm using a CDN for static assets

18:19 cloudfront, which refreshes from optimus

18:19 bitemyapp: if you're fronting with cloudfront then why are you worried about gzipping in optimus?

18:20 sritchie: I didn't realize cloudfront gzipped

18:20 bbloom_: bitemyapp: cloudfront doesn't do it's own gzipping

18:20 bitemyapp: bbloom_: wow.

18:20 sritchie: well, there we go

18:20 bitemyapp: so my conclusion at that point would be to not use a CDN that doesn't gzip, of all things.

18:20 bbloom_: bitemyapp: cloudfront serves whatever you give it

18:20 what level of gzip should it use?

18:20 what resource types should it gzip for?

18:20 bitemyapp: shouldn't the headers decide this?

18:21 bbloom_: gzip slows performance for some file types

18:21 cloudfront has two modes

18:21 basically read-through caching or write-through caching

18:21 in the write-through mode, you can literally just give it a .http file

18:21 w/ a raw response & it will inject a header or two & that's that

18:22 but that requires you add stuff to your deployment process

18:22 the read-through approach is way easier, but it serves whatever you serve

18:22 sritchie: bbloom_: so sounds like gzipping ANY text response, + html, is the right way to go

18:22 via middleware

18:23 (for hosts that accept gzip)

18:23 which means that cloudfront will get the benefits

18:23 bbloom_: yes

18:28 sritchie: bbloom_: do you know if cloudfront keeps separately cached items for gzip vs not?

18:28 bbloom_: sritchie: yeah, per-encoding header, i believe

18:28 sritchie: bbloom_: meaning, if it gets a file once with gzip, then a client asks that doesn't support gzip, does it refresh

18:28 okay

18:28 nice

18:29 bbloom_: but with huge expires headers, the first time you fail to return a gzip version when cloudfront asks for gzip,

18:29 you're hosed until you change the file

18:29 which is fine

18:29 bbloom_: this is all relatively well documented on the amazon site

18:30 akurilin: Hey folks. I'm trying to find the most maintenance-free way of dumping error logs from both our various frontends and backend. I could just make a new ring app with a db on the existing PG instance, but I'd rather not. I'm thinking of something like Parse or Dynamo as this hassle-free log dump. Any thoughts?

18:30 OscarZ: bitemyapp: why you think project euler is a bad way to learn clojure?

18:33 bitemyapp: project euler has more to do with math than programming.

18:33 and not even the interesting math.

18:34 technomancy: and everyone knows you need a type system to do math

18:34 OscarZ: interesting.. would it be better to use something like Haskell for that?

18:34 bitemyapp: no.

18:35 euler is boring no matter what language you use.

18:35 Haskell isn't necessarily any more well suited for mathy things than anything else.

18:35 technomancy: OscarZ: I'm just messing with bytemyapp

18:35 hiredman: it's true, otherwise you'll try and add two different kinds of numbers together

18:35 technomancy: bite

18:35 bitemyapp: ouch dude.

18:35 OscarZ: :)

18:36 bitemyapp: hiredman: it's better than the 31-bit Ints in OCaml.

18:37 jwieringa: Interesting, I was just using euler to learn more about Clojure and spent more on Wikipedia reading about Mathematical functions :)

18:38 brainproxy: dnolen: yes, you understood what I was trying to do

18:38 OscarZ: jwieringa: its wrong. now you have to get drunk and erase it all :)

18:38 bitemyapp: jwieringa: that's kinda the point.

18:38 brainproxy: found a difference mechanism that works better in the first place, so it's fine

18:39 dnolen: I had thought maybe there would be an easy way to tease the info out of the analyzer, gave it a naive go

18:39 s/difference/different

18:40 jwieringa: bitemyapp: Yeah, the timing of the conversation was good :)

18:41 dnolen: brainproxy: we don't store AST information, only the usual metadata on top levels + function info for optimization

18:42 brainproxy: dnolen: right, well I'm learning, today was the first I spent some serious time in the analyzer/compiler/etc codebase poking around, fun stuff

18:45 eric_normand: how did it get to be quarter to six?

18:45 I've got to stop logging into irc :(

18:45 bitemyapp: eric_normand: it didn't - because it's actually 1545

18:45 technomancy: time travel

18:45 eric_normand: bitemyapp: off by two error!

18:47 bitemyapp: eric_normand: you middle-country people don't exist.

18:47 devn: eric_normand: some of my best and worst moments have been captured on IRC

18:47 bitemyapp: devn: you're nothing but a lazy sequence of moments, with the universe itself (take ...)'ing from you.

18:48 bbloom_: is there any good paper/explaination/details about the transient implementations? reading their code is only a little enlightening

18:49 bitemyapp: bbloom_: that's one slightly annoying thing about stuff I find in Clojure, there's often less published work backing the implementation.

18:50 bbloom_: *shrug* for the most part the impl is absurdly simple

18:50 bitemyapp: I'm not speaking only about impl.

18:50 bbloom_: the data structures are pretty much the only interesting part of the implementation

18:50 bitemyapp: not talking only about Clojure's implementation...

18:50 bbloom_: oh ok then

18:51 hyPiRion: re transient impl: I'll possibly write something about them in January

18:51 bitemyapp: hyPiRion: preemptive thank you

18:51 bbloom_: hyPiRion: cool

18:51 hyPiRion: does that mean you can give me a 5 sentence explaination now? in particularly PHM. PV makes much more sense to me

18:51 eric_normand: devn: I have never really been much to chat online. I'm liking it and glad I'm a little hooked. Otherwise, I would never do it.

18:52 bitemyapp: eric_normand: I grew up on IRC and cll, thus why I'm a terrible person.

18:53 eric_normand: bitemyapp: that explains it! I was on cll, once. ONCE!

18:53 but I kid

18:53 there are some really great posts on cll

18:54 hyPiRion: bbloom_: Wish I could, but I want to be really sure I understand them properly

18:54 bbloom_: heh

18:54 ok then

18:54 bitemyapp: I'm pretty sure I spent the first 60% of my programming life believing evil correlated with intelligence because of cll and IRC.

18:54 arrdem: bitemyapp: that explains so much...

18:54 cll not even once.... irc all day erry day

18:54 bitemyapp: well, time to stop relinquishing my secrets and go back to plotting the demise of my enemies.

18:55 hyPiRion: I usually end up understanding something halfway through my own explanation, and have to rewrite because I haven't taken that stuff into account

18:55 bbloom_: hyPiRion: always good for your understanding tho

18:56 i have dozens of blogposts that i started to write but stopped b/c i learned something

18:56 :-P

18:56 hyPiRion: bbloom_: yeah, it's wonderful, but I don't want to explain something I'm not sure I completely understand myself :p

18:56 bitemyapp: Speaking of cll, I want conditions and restarts.

18:56 hyPiRion: re those 5 sentences

18:57 arrdem: bitemyapp: we don't have a jvm bytecode goto. not gonna happen.

18:58 bitemyapp: arrdem: could fake it.

18:58 not the goto, the state preservation.

18:59 arrdem: the state preservation sure... restarting in place no way... restarting from the top sure.

19:00 but then you just have a try with a loop around it :P

19:00 bitemyapp: arrdem: that's not state-preserving.

19:00 arrdem: I could think of multiple ways to do it in a language not Clojure that shall go unnamed.

19:03 arrdem: https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings I see a goto.

19:03 * arrdem starts having really bad ideas

19:03 bitemyapp: arrdem: I think you meant that Java doesn't have goto, the JVM certainly does.

19:03 probably needed it for implementing exceptions sanely.

19:04 too bad they did exceptions the wrong way.

19:05 arrdem: so given that we have a goto... why don't we have TCO? is it that we do class generation rather than bytecode emission?

19:05 amalloy: the jvm's bytecode goto is restricted to staying within the same method

19:05 bitemyapp: arrdem: we use methods.

19:06 amalloy: and also rich wanted clojure function calls to be java method calls, otherwise interop looks pretty bad

19:06 bitemyapp: arrdem: look at Frege to see the other evolutionary branch.

19:07 arrdem: amalloy: okay yeah that's what I thought.

19:08 still... you have jumps to word aligned addresses... with that you could splat out several entire

19:08 "methods" into a single function and then just provide a wrapper to make it look sane

19:09 bitemyapp: arrdem: have you looked at Frege? It's a really cool language for thinking about how to target the JVM.

19:09 arrdem: bitemyapp: I only just learned about it :P

19:11 bitemyapp: arrdem: excellent opportunity to learn!

19:12 arrdem: bitemyapp: first I need to beat deft into submission and start a clojure.RT and JVM pre CinC reading list then add that...

19:17 bitemyapp: arrdem: props for making SimpleVM a register machine btw.

19:18 arrdem: bitemyapp: why are you looking at that shitheap

19:18 thanks tho :P

19:20 really it's more of a heap machine than a register machine... it provides an infinite register set which really means that all its ops are memory->memory

19:22 noprompt: omg. <3 pho.

19:23 bitemyapp: noprompt: $10 bowl of broth.

19:23 noprompt: bitemyapp: nah they hook it up out here.

19:24 bitemyapp: $10 bowl of broth and poorly prepared, nearly flavorless noodles/meat.

19:24 noprompt: bitemyapp: :| that sir is not the case.

19:24 rasmusto: hahahahaaha, I remember this conversation

19:24 bitemyapp: noprompt: pho is a waste of money.

19:24 rasmusto: ramen supremacy

19:24 arrdem: bbq is king

19:24 noprompt: bitemyapp: startups are a waste of money, pho is not.

19:25 bitemyapp: noprompt: except for the one I work at, sure.

19:25 noprompt: bitemyapp: i can't speak for pho in the bay but here in fresno i'm pleased to say the pho scene is good.

19:26 bitemyapp: http://www.cpptips.com/term_except

19:26 noprompt: I've had pho in most corners of the country. It was all a waste of time and money.

19:27 noprompt: bitemyapp: you need to take of those lollerskates buddy.

19:27 *off

19:27 bitemyapp: noprompt: come to SF, I'll show you real food.

19:28 noprompt: bitemyapp: pretty sure i just ate "real" food.

19:28 bitemyapp: http://www.reddit.com/r/haskell/comments/1s6wb6/a_modified_approach_to_comonadic_cellular/

19:28 noprompt: you ate peasant broth at first world prices.

19:28 noprompt: bitemyapp: i'm pretty sure there was blood in it which is what i want.

19:29 arrdem: clojurebot: offtopic |is| #clojure-offtopic is #emacs

19:29 clojurebot: Ok.

19:29 bitemyapp: noprompt: goulash and borscht are superior alternatives.

19:29 noprompt: bitemyapp: i'm sure they are.

19:29 and i will eat them too.

19:29 bitemyapp: noprompt: also, kapusniak.

19:30 now I want kapusniak. dammit.

19:30 rasmusto: had some of this the other day: http://en.wikipedia.org/wiki/Dinuguan

19:30 noprompt: rasmusto: now that's what i'm talking about.

19:31 rasmusto: anytime there's blood and organs in a bowl of stew i'll be the first at the table.

19:31 rasmusto: noprompt: <3 (and ears/tail/snout/liver...)

19:31 akurilin: now you made me hungry

19:31 noprompt: rasmusto: my ex was philipino but her mom never made that dish. :( i feel cheated.

19:32 rasmusto: she did make ox tail soups a lot though. that was pretty good.

19:32 rasmusto: sounds rich

19:33 noprompt: bitemyapp: you take me to get blood soup.

19:34 bitemyapp: noprompt: no

19:34 noprompt: bitemyapp: fine. organ meat then.

19:40 arrdem: amalloy / bitemyapp: any hints for starting reading the Clojure core, or do I just need to spend a week with coffee?

19:41 bitemyapp: arrdem: avoid coffee, drink tea if you want caffeine.

19:41 rasmusto: drink blood tea

19:41 arrdem: rasmusto: BLOOD FOR THE BLOOD GOD

19:44 brehaut: http://amultiverse.com/tag/corn-god/

19:45 scottj: arrdem: clojure or java parts?

19:45 bitemyapp: is the core.clj bootstrap that interesting?

19:46 realistically the more interesting bits are going to be in Java.

19:49 arrdem: scottj: I've read some of the clojure bootstrap and I've written lisp bootstraps before. It's the java bits that I'm curious about.

20:35 dpetrovics: anyone know if there is an analog of jquery's wrap-all in Enlive?

20:35 Im looking to wrap a div around all elements in the set of matches from an Enlive selector

20:38 never mind-- looks like wrap actually does that-- I assumed it would wrap each match

20:41 amalloy: dpetrovics: fwiw, it's a useful rule of thumb that not many clojure functions "do x to each y". it's more flexible to just "do x to y", and then use map if you want it on multiple things

20:42 coventry: Going back to the earlier question about permgen and fn creation, the only ill effects of (last (repeatedly 1e8 #(eval '(fn [] "foo")))) seems to be that it runs forever (three hours on my system.)

20:43 dpetrovics: amalloy: here's what I mean-- looks like the at form actually does apply the transformation to each match

20:43 (at [{:tag :p :content ["foo"]} {:tag :p :content ["bar"]}] [:p] (wrap :div {:class "outer"}))

20:44 that will actually wrap each

20:44 p element

21:01 bbloom_: dnolen: finally got brenton to look at react too :-)

21:07 bitemyapp: noprompt: you should've come to the Clojure meetup and given a talk.

21:08 noprompt: bitemyapp: man, that would have been awesome. i really want my life to get back to normal.

21:09 bitemyapp: i'm going to be talking about clojure two days a week for six weeks starting january.

21:32 ddellacosta: I want to do a union of two vectors of hash-maps, but based only on the value of a specific key/value pair (id). What is the most efficient way to do this?

21:34 sorry, I meant intersection, not union

21:34 amalloy: ddellacosta: that's too vague a request for me to really understand, but "most efficient" has got to be the wrong question

21:35 learn how to do it at all, and then if it really really matters you can worry about what's efficient

21:38 hyPiRion: (into {} (for [[k v :as entry] m1 :when (= entry (find m2 k))] entry)) is probably okay-ish

21:40 ddellacosta: amalloy: ouch

21:40 let me restate the question

21:40 sritchie: shot in the dark - anyone played with infinite scroll in cljs?

21:40 amalloy: hyPiRion: vector of maps

21:40 ddellacosta: Say I have [{:a 1 :b 2}{:a 2 :b 3}] and [{:a 1 :b 2}{:a 3 :b 6}] --I want to get [{:a 1 :b 2}] in the end

21:41 hyPiRion: oh, eh.

21:42 ddellacosta: oh, but I should qualify that further-- even if the value for :b is different in the second vector, I want to get (one of the vectors values for) the map with :a that has value 1

21:43 amalloy: i mean, that sounds like just doing (group-by :a ms) on each vector, and then working with them as maps

21:47 bitemyapp: ddellacosta: group-by + merge

21:48 ddellacosta: map reduce (group-by :id ....)

21:48 map reduce merge (group-by :id ...)

21:48 ddellacosta: amalloy, bitemyapp: thanks, will try these. Messing about with clojure.set now

21:49 sritchie: technomancy, I can't track it down - what was your rec about how to inject :aot :all AFTER the prep tasks?

22:10 ddellacosta: feel like I could do this better: https://www.refheap.com/21549

22:11 bitemyapp: "Clojure is basically lazy by default" yeah. uh huh.

22:11 ddellacosta: bitemyapp, amalloy: I tried with group-by, but wasn't sure how it helped me get the answer I wanted...probably wasn't thinking about it correctly though.

22:11 bitemyapp: ddellacosta: merge each group

22:11 ddellacosta: bitemyapp: that gave me a union though, and I wanted an intersection

22:12 bitemyapp: ddellacosta: oh sorry, set/intersect + select-keys

22:20 deadghost: what's #'

22:20 google doesn't like stuff like that

22:20 bitemyapp: deadghost: var

22:20 deadghost: k

22:20 bitemyapp: deadghost: where did you see it?

22:20 coventry: deadghost: http://clojure.org/reader

22:21 arrdem: ,((require 'clojure.pprint)(#'clojure.pprint/pprint {:foo :bar :baz {:many-key :so-nested} :wow true}))

22:21 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: clojure.pprint/pprint in this context, compiling:(NO_SOURCE_PATH:0:0)>

22:21 deadghost: after a ran a function for scraping

22:21 it's a little confusing because I spent the last money in CL

22:21 *month

22:42 * devn suddenly has the urge to make all of the things invokable

22:43 arrdem: devn: as long as you promote regexes to IFn while you're at it, I'l all for it.

22:45 deadghost: I'm curious... can you offer any compelling reason to really master CL/Guile? I tried to use CL a few times and the lack of packages or propper module structure really rubbed me the wrong way.

22:46 deadghost: arrdem, why do you think I'm on clojure

22:46 technomancy: guile is pretty great for interop inside a larger system

22:46 deadghost: I couldn't string enough packages together to write a simple scraper

22:55 arrdem: deadghost: oh ok. I was hoping that you had sucessfully used CL for something serious. And yeah. The library infrastructure, clojars and leiningen are totally killer features for Clojure over the other Lisps I've played with.

22:56 deadghost: clojure definitely left a better first impression

22:56 nope, tried and failed

22:58 Qarry: deadghost, everyone hates me. =(

22:58 Even Chousuke

23:00 deadghost: although leinin is mad at me

23:00 Qarry: deadghost, Vladimir Lenin?

23:00 deadghost: but I figure that's because marmalade is borked and I got it off melpa

23:01 mikerod: how can I get lein test to show output from println or similar functions

23:01 i.e. show me stdout stream stuff

23:01 `lein test`

23:02 Qarry: Chousuke, sä etkään oli täällä katsoksesi suomeani parentua

23:03 deadghost: arrdem, how was your CL experience?

23:04 what did you try writing?

23:04 arrdem: deadghost: I looked at CL before clj, used CL for one class assignment and then despite my prof's warnings about not having any clj sample code I threw out his CL codebase and went it solo for the term. worked out great, thanks in no small part to #clojure

23:05 deadghost: the project was a toy pascal compiler

23:12 echo-area: True or false: If I'm adding an extra argument to many functions and the purpose of this argument is all the same, I can make it a dynamic var

23:12 Will it look like weird?

23:13 arrdem: dynamic vars seem to be considered an anti-pattern... but I'd be OK with it

23:14 echo-area: I have concerns on if it's idiomatic rather than pattern, and I'm okay with it too, but I still want suggestions

23:14 Is there any drawback on this?

23:15 I personally haven't seen any

23:15 (Although I have to use binding-fn, but that's a price to pay)

23:15 arrdem: the main question (or issue) is that dynamic vars play badly with threads and lazyness

23:17 echo-area: I'll get a non-lazy result at the end of the "scope" I set the dynamic var up.

23:19 But I think it would be easier to address the problem if I intentionally leave the root value of the var to be unbound

23:19 s/the problem/problems

23:19 coventry: echo-area: Sounds OK for a quick hack prototype, but it will complicate your life over the long haul if you keep it that way.

23:23 echo-area: coventry: The most clean way, as I can see, is to pass the arg on every function call.

23:23 coventry: Yeah, that's a sane approach.

23:24 echo-area: Hmm, maybe dynamic scope is only for temporarily altering behavior of some part of the program

23:24 Only for this scenario can it be clean

23:25 technomancy: echo-area: if you invoke dynamic binding, you must also take responsibility to ensure nothing lazy escapes its scope

23:25 sometimes that's easy and sometimes that's impossible

23:27 echo-area: I have to figure out a sane way

23:27 Thanks for the suggestions

23:35 Is it weird that I create some functions in let's lexcial binding?

23:37 arrdem: as long as you aren't emitting defs from there you're fine

23:37 in theory at least

23:38 echo-area: No I'm not. But I may have to use letfn. To me this sounds like a compromise between dynamic scope and adding args to many more functions

23:39 It does make testing a bit hard, so hmm

23:40 I'd better fall back to use an extra arg for those functions

23:48 brainproxy: echo-area: what's the extra arg for?

23:48 echo-area: brainproxy: More like for the usage of state, context, or configuration

23:49 brainproxy: echo-area: have you explored the State monad pattern, it's pretty nice for that

23:49 echo-area: brainproxy: No, I hear about this for the first time. I'm search for it. Thank you!

23:50 brainproxy: echo-area: here's a clojure based tutorial to give the idea

23:50 http://www.clojure.net/2012/02/10/State/

23:50 there are now several libraries that implement State and other monad apis

23:50 protocol-monads, algo.monads

23:51 fluokitten

23:53 technomancy: without the compiler's help it's arguable as to whether that results in simpler code

23:54 brainproxy: technomancy: depends on how much power you pack into the macros/sugar around monads

23:54 with a good implementation of `do` i find it helps me, but i could be weird or misguided

23:57 in any case, it's really just a patter; programmers can "taste and see", and use it appropriately if they find it useful

23:57 *pattern

23:58 technomancy: yeah, give it a try

23:59 I have seen some very messy monadic code in clojure but I don't want to rule out the possibility that it can be done well

23:59 brainproxy: I'm doing a sizable project with them currently; my biggest complaint is that the code density gets extremely high

23:59 basically just lots and lots of symbols

Logging service provided by n01se.net