#clojure log - Apr 01 2012

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

0:00 TimMc: y3di: Symbols that the compiler special-cases.

0:00 They're built into the compiler as literals.

0:02 y3di: https://github.com/clojure/clojure/blob/1.3.x/src/jvm/clojure/lang/Compiler.java#L39

0:03 Not everything that the compiler special cases is a special form; many of those are just for optimization or bootstrapping.

0:24 y3di: wait, whats the difference between binding and let?

0:32 TimMc: dynamic and lexical scope

0:32 Frozenlock: http://stackoverflow.com/questions/1523240/let-vs-binding-in-clojure

0:34 Is there a function to compress files?

0:40 This might do : https://github.com/bonega/pacl

0:44 muhoo: ns_pablo: preroutes?

0:48 ns_pablo: muhoo: what do you mean?

0:48 muhoo: ns_pablo: http://www.webnoir.org/autodoc/1.0.0/noir.core-api.html#noir.core/pre-route

0:48 ns_pablo: afaik preroutes are used to aggregate behaviors for multiple routes, like checking for authentication

0:49 how would I use preroutes in this way?

0:50 I'm new with Noir, so forgive me if it's something obvious...

0:50 muhoo: i dunno, exactly, it's just a guess.

0:50 http://www.webnoir.org/tutorials/routes

0:50 i'm new too

0:50 * Frozenlock 's listening

0:50 muhoo: maybe you could use resp/redirect

0:51 to redirect based on the "module" url

0:52 like (pre-route "/foo" {} (resp/redirect "/soemwher/else")) ?

0:52 Frozenlock: I think it doesn't solve the basic issue, which if I'm right was to be able to simply specifiy a part of the url. "/test" instead of "/blog/test".

0:52 ns_pablo: well, that might work... I'll take a look at the source to see what exactly is preroute doing

0:52 Frozenlock but it might be a start towards a homegrown solution

0:55 what I'm really looking for is something like this http://www.padrinorb.com/guides/mounting-applications

1:04 This would be actually pretty easy to accomplish with Moustache: http://pastie.org/3707127

4:10 wei_: aoeu

4:11 oops sorry

6:35 espringe: I've written a parser, which produces an in-memory sexpresion that can be eval'd or what not. But I want to transform it into a a string, that is valid clojure code. Is there a built-in function for that?

6:36 e.g. when it turns the three letter string 'dog' into the five-lettter "dog" (adds quotes)

6:39 morphling: espringe: pr

6:39 espringe: morphling: perfect, thanks

6:40 bsteuber: or pr-str

6:43 laurus: Are people still working on Incanter?

6:46 bsteuber: laurus: given https://github.com/liebke/incanter/network - yes

6:49 laurus: bsteuber, interesting, thanks for that.

8:20 jayunit100: how does clojure "know" when its reached the end of a lazy-seq ?

8:20 (doc lazy-seq)

8:20 clojurebot: "([& body]); Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls. See also - realized?"

8:22 jayunit100: Im looking at the code for the partition function in https://github.com/richhickey/clojure-contrib/blob/master/src/main/clojure/clojure/contrib/string.clj..... and trying to figure out how it is that the (lazy-seq ... ) function ever returns.

8:26 gfredericks: jayunit100: without looking at it, the confusion probably comes from the fact that lazy-seq is a macro

8:26 macros don't follow the normal rules of evaluation

8:26 jayunit100: oh duh

8:26 thanks that helps okay.

8:27 so... lazy-seq is probably taking my function and implementing the ISeq interfaces for me.

8:28 gfredericks: whatever body you pass to lazy-seq has to return a seq

8:29 what lazy-seq does is prevent the body from being evaluated until necessary

8:30 regarding your earlier question about how clojure knows it has reached the end -- same as with a non-lazy seq. If the rest method returns nil (I believe) then that's the end

8:30 give or take a few details

8:30 the fact that it's lazy only changes when the sequence is computed, not how you interact with it

8:30 as a consumer of the seq

8:39 jayunit100: (macroexpand clojure.contrib.string/partition)

8:39 seems to return something not-useful

8:40 raek: jayunit100: macroexpand is a function so you have to give it the unevaluated code

8:40 (macroexpand '(clojure.contrib.string/partition ...))

8:41 ,(macroexpand '(when x a b c))

8:41 clojurebot: (if x (do a b c))

8:42 jayunit100: hmmmmm

8:43 raek: also, clojure.contrib.string is outdated

8:43 if possible, use clojure.string instead

8:43 jayunit100: user=> (require 'clojure.contrib.string)

8:43 nil

8:43 user=> (macroexpand '(clojure.contrib.string/partition pattern largeString))

8:43 (clojure.contrib.string/partition pattern largeString)

8:43 raek: are you sure partition is not just a regular function?

8:44 jayunit100: it is . but i thought macroexpand would look for macros inside of it :)

8:44 I guess it doesnt work that way :(

8:44 raek: the code in a function body is not inserted into the call site

8:44 jayunit100: but im surprised it didnt through an error.

8:44 throw i mean.

8:45 should macroexpand throw an error if a function is given as input

8:45 raek: macroexpand takes an arbitrary expression and expands any macros in it

8:45 in you case there were none, so the input was the same as the output

8:46 think of macroexpand as a pre-filtering step of the compiler

8:46 jayunit100: anyway, you can copy the body of the partition source code and pass it to macroexpand

8:47 ,(macroexpand '(lazy-seq (when x (cons y z))))

8:47 clojurebot: (new clojure.lang.LazySeq (fn* [] (when x (cons y z))))

8:48 raek: here you see a glimpse of how lazy seqs are implemented

8:57 gfredericks: jayunit100: one thing that may not be obvious is that because macros are effective at compile-time, a macro is only concerned with the _forms_ of the code that is given to the macro

8:58 (defmacro is-string? [x] (if (string? x) true false))

8:58 (is-string? "foo") will emit true

8:58 (let [s "foo"] (is-string? s)) will emit false

8:59 so when you wrote (macroexpand '(clojure.contrib.string/partition pattern

8:59 largeString))

9:00 eh nevermind I don't have anything else to say

9:02 RickInGA: TheBusby: you around?

9:39 Lajla: &(:fart {:fart "lol"})

9:39 lazybot: ⇒ "lol"

9:40 Lajla: &({:fart "lol"} :fart)

9:40 lazybot: ⇒ "lol"

9:40 Lajla: &(:fart {:diarrhoea "lol"})

9:40 lazybot: ⇒ nil

9:55 gtrak``: anyone ever write a physics engine? I'm getting some fun 'emergent' behavior :-), not sure where to go to learn about how to do this right: http://www.youtube.com/watch?v=415OTzYEXsk

9:57 gfredericks: gtrak``: what's going on in this video?

9:58 in particular with the all the balls falling to one side thing

9:58 gtrak``: ah, that's from user input, applying an acceleration

9:58 AimHere: He forgot to switch the second law of thermodynamics on ;)

9:58 gfredericks: okay; that was my guess

9:58 gtrak``: the emergent parts are the collisions that should happen and don't and the funny orbiting and sticking

9:58 tmciver: gtrak``: yes, I'm curious too. It looks like the balls stick together sometimes.

9:59 gtrak``: if you didn't intend for that behavior, it might be a bug with the collision detection.

9:59 gfredericks: maybe he programmed in gravity :)

9:59 gtrak``: van der waals forces

10:00 tmciver: gtrak``: Really? Is it supposed to be a molecular simulator?

10:00 gtrak``: j/k about that, yea, collision detection's borken, fun thing about this kind of thing is it's impossible to test :-)

10:01 gfredericks: that can't be true

10:01 is it deterministic?

10:01 gtrak``: well, *hard* to test

10:01 gfredericks: oh okay then :)

10:01 tmciver: Yes, it should be testable.

10:02 gtrak``: yea, it's all functional except for a single atom swap! on top

10:02 gfredericks: run the thing and expect that at each step the balls aren't closer than their radius

10:02 watch the failures come piling in

10:03 oh I just imagined doing it multithreaded where each ball is a ref

10:03 gtrak``: oh gosh, haha, that would be awful

10:03 gfredericks: and you have a spatial index telling you which balls are nearby that you need to coordinate with

10:03 gtrak``: but actually the drawing thread is separate, the simulation runs at 500fps

10:04 tmciver: nice

10:04 gtrak``: no optimization really, I'm impressed with the jvm

10:06 gfredericks, yea, the spatial index is one way to avoid checking every object against every object, right now it's n^2

10:08 y3di: ref and atoms are pretty similar

10:09 gtrak``: i imagine if you're doing all the calcs on one thread like me, an atom's much better

10:10 gfredericks: y3di: yeah using refs would allow you to do some updates in parallel

10:10 gtrak``: and there's an issue with throughput vs latency, it's always better to have predictable latency

10:11 in games i mean

10:12 i could use refs for scripted events, but not a tight simulation like this

10:12 gfredericks: I didn't mean it too seriously :)

10:12 although it'd be interesting to know what kind of scalability that would buy

10:13 gtrak``: hmm, i could probably pmap some things

10:13 if you're curious: https://github.com/gtrak/quilltest/blob/master/src/quilltest/balls.clj

10:15 y3di: how come some functions like swap! have a bang at the end?

10:15 what does the ! represent?

10:15 gtrak``: ! generally means mutable i think

10:15 gfredericks: sometimes mutation, sometimes hazardness...

10:15 sometimes it has to do with dosync specifically I think

10:15 in the case of swap!

10:16 tmciver: gtrak``: how is your collision checking n^2? I wrote a very simple 2D physics engine in Java some time ago but I believe my collision checking was something approximating n factorial: check one object against all others, if it wasn't colliding with anything, remove if from the list of objects to check. Then continue with the rest of them.

10:16 s/remove if/remove it

10:16 gfredericks: tmciver: that sounds n^2 to me

10:16 you're checking all pairs

10:17 tmciver: I'm terrible at this complexity stuff.

10:17 gfredericks: tmciver: it's addition vs multiplication

10:17 gtrak``: (filter (fn [[a b]] (p/colliding? (:rigid-body a) (:rigid-body b)))(for [x guys y guys [x y]))

10:17 gfredericks: tmciver: factorial is (apply * (range n)), whereas in this case it is (apply + (range n))

10:17 which is asymptotically equiv to n^2

10:18 gtrak``: i could fix that for to remove duplicate pairs if I keep a set

10:18 but it's still n^2

10:18 tmciver: gtrak``: you *may* be able to do better than that; aren't you chekcking objects against themselves and rechecking objects that can be known not to be colliding with anything?

10:19 gfredericks: I think that's what he means by removing duplicate pairs

10:19 gtrak``: yea, i can def do better, but like i said, it's totally fast enough right now for casual things :-), i want to make it right though

10:19 gfredericks: tmciver: if an algorithm has anything to do with factorials you don't have much hope for doing anything with more than 10 objects

10:21 tmciver: gfredericks: so the algo I described is something less than n^2. I don't know what kind of frame rate I was getting but my simulator seemed to move along with much more that 10 objects.

10:21 gtrak``: duplicate as in [:a :b] = [:b :a]

10:22 gfredericks: tmciver: less than n^2 steps in absolute terms, but in complexity terms it is still n^2

10:22 tmciver: gfredericks: makes sense.

10:22 gtrak``: also duplicate as in checking :a against :a

10:22 gtrak``: n^2 -5 is still n^2, so is n^2 -5x

10:23 gfredericks: n^2-5n you mean? :)

10:23 gtrak``: tmciver, yea, I caught that one, just didn't paste it in

10:23 gfredericks, yes :-)

10:24 gfredericks: and most relevant to this case is that 0.5*n^2 is still n^2

10:34 jayunit100: what is a " body of expressions"

10:34 y3di: why would you use futures over a function that started a new java thread?

10:35 jayunit100: in context to defining macros?

10:35 jayunit100: yeah

10:36 gfredericks: y3di: futures are syntactically simpler, and take care of providing a box for the result of the computation to go in

10:36 they might also be thread-pooled

10:37 and maybe even do the binding thing

10:38 jayunit100: im wondering... what it means to take a "body of expressions" as input. Is that synonymous to taking "n expressions"

10:38 gfredericks: yeah it means multiple experssions

10:38 y3di: jayunit100: i believe so

10:38 gfredericks: the canonical example is do

10:38 y3di: gfredericks: what's thread pooling?

10:39 gfredericks: y3di: runs the futures in a thread pool instead of creating a new thread for each one indiscriminately

10:39 which I assume means creating a million futures is more feasible than a million threads

10:39 y3di: so that means, oh ok, so futures will essentially wait for threeads to free up

10:39 gtrak``: y3di, i think in general you should separate computations (values) from the details of their execution, future is more abstract than a thread but gets the job done

10:40 gfredericks: &(->> (for [x (range 1000000)] (future x)) (map deref) (apply +))

10:40 lazybot: java.lang.SecurityException: You tripped the alarm! future-call is bad!

10:41 gtrak``: if you look at haskell's 'everything's lazy', that's more obvious

10:41 they might take it too far, though

10:42 gfredericks: oh I guess that code snippet doesn't actually illustrate anything since it's lazy

10:42 would have to doall before the map

10:43 jayunit100: hmmm it looks like (lazy-seq) cant have nils in the middle .... since that is the "end" of a the list.

10:44 gfredericks: jayunit100: nil values should be fine

10:44 jayunit100: then how will the lazy-seq "know" when the list is done ?

10:44 it would be infinitely long ?

10:44 gfredericks: it's when the entire rest of the sequence is null

10:44 not just one of the entries

10:45 jayunit100: oh ok. so if "rest" is null

10:45 where rest is a list.

10:45 gfredericks: right

10:45 &(count (lazy-seq (cons 1 nil)))

10:45 lazybot: ⇒ 1

10:46 gfredericks: &(count (lazy-seq nil))

10:46 lazybot: ⇒ 0

10:46 jayunit100: is there a way to grep the history of my repl

10:46 like in bash?

10:46 ,(history)

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

10:53 jayunit100: that is, maybe someone knows where the repl stores history so i can hack it.

11:02 hmmm.. is there a way to reload the current lein namespace ?

11:02 i.e. reload the source without explicitly mentioning a file name.

11:03 mega`: youst lein not lein.core?

11:03 just*

11:03 jayunit100: you mean....

11:04 i ran "lein repl" from the root of a project.. and made some changes to multiple files.

11:04 mega`: i dont realy know the use case are you writing a plugin ?? why do you whant to reaload the source

11:04 jayunit100: can I reload the project in lein

11:04 no , much simpler than that.

11:04 llasram: jayunit100: (require 'your.namespace :reload) ?

11:04 mega`: oo the project

11:04 jayunit100: Im just editing more than one file in a clojure project

11:05 ---- im used to clicking "clean" in eclipse. assuming there is an analog in lein ?

11:05 sorry about the confusion :)

11:07 (other than ctrl-c)

11:08 hmm this is interesting - looks like "time" doesnt evaluate an anonymous function that is passed in. I wonder why ?

11:09 ,(time #(reduce + (range 1000)))

11:09 clojurebot: "Elapsed time: 0.429 msecs"

11:09 #<sandbox$eval27$ret__3993__auto____28 sandbox$eval27$ret__3993__auto____28@118b78d>

11:09 mega`: , (time (reduce + (range 10000)))

11:09 clojurebot: "Elapsed time: 69.498 msecs"

11:09 49995000

11:09 mega`: its a macro

11:11 gtrak``: ,(time (#(reduce + (range 1000)))

11:11 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

11:11 mega`: missing a paren

11:11 gtrak``: ,(time (#(reduce + (range 1000))))

11:11 clojurebot: "Elapsed time: 1.219 msecs"

11:11 499500

11:11 gtrak``: jayunit100, or for more clarity

11:12 ,#(reduce + (range 1000)))

11:12 clojurebot: #<sandbox$eval139$fn__140 sandbox$eval139$fn__140@f2e01b>

11:13 mega`: , (macroexpand '(time (#(reduce + (range 1000)))))

11:13 clojurebot: (let* [start__3992__auto__ (. java.lang.System (clojure.core/nanoTime)) ret__3993__auto__ ((fn* [] (reduce + (range 1000))))] (clojure.core/prn (clojure.core/str "Elapsed time: " (clojure.core// (clojure.core/double (clojure.core/- (. java.lang.System (clojure.core/nanoTime)) start__3992__auto__)) 1000000.0) " msecs")) ret__3993__auto__)

11:14 jayunit100: okay....

11:14 mega`: clear as paj

11:15 jayunit100: Im trying to understand whats the difference when I wrap the anonymous functoin in a closure.

11:15 ,#(reduce + [1 2])

11:15 clojurebot: #<sandbox$eval193$fn__194 sandbox$eval193$fn__194@5abaee>

11:15 gtrak``: huh?

11:15 jayunit100: ,(#(reduce + [1 2]))

11:15 clojurebot: 3

11:15 jayunit100: ha

11:15 okay

11:15 wrapping it in clojure results in evaluation.

11:15 gtrak``: there it is, eureka!!!

11:15 jayunit100: :]

11:16 gtrak``: actually, the anonymous function is a closure, wrapping it in parens executes a function, just like anything else

11:16 ,(1)

11:16 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

11:17 jayunit100: ok

11:24 (bump question about grepping through lein history).

11:32 i do see a .lein folder, but that seems not to have any history data in it.

11:53 yoklov: is there a better way to get the current value of 'this' in clojurescript than (js* "this")

11:54 mega`: theres a this-as macro

11:54 yoklov: is there?

11:55 still not really what I'm looking for.

11:55 gtrak``: huh, why wouldn't that be the same thing?

11:55 yoklov: oh wait

11:55 mega`: js/this maybe works

11:56 yoklov: i misunderstood what this-as did

11:56 gtrak``: http://www.chris-granger.com/2012/02/20/overtone-and-clojurescript/

11:56 there's an example

11:58 mega`: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/core.clj#L205

11:58 yoklov: yup

11:58 i was already on that page actually haha

11:58 looking for something like that.

11:59 gtrak``: gawd, extend-type is pretty intense

12:00 mega`: yea maybe extract some functions there

12:02 yoklov: they'd have to be in the api if you did that though, right?

12:02 because it's a macro and you couldn't defn- them

12:02 mega`: you can call functions from macros

12:02 yoklov: not private ones though, right?

12:02 in a separate namespace

12:03 i actually am unsure how clojure deals with that, its an issue I always thought racket dealt with inelegantly

12:03 mega`: you can call them while generating the code

12:03 yoklov: right

12:03 mega`: you cant refere to them in the produced code but you cant do that in cljs anny way

12:04 yoklov: hm, i guess less of that is actual macro output than i thought at first glance

12:04 mega`: Oo o ok

12:04 yea its mostly code and branches

12:07 jayunit100: hungarian notation for clojure !

12:07 http://web.mst.edu/~cpp/common/hungarian.html

12:07 mega`: love it

12:07 start doing that

12:08 TimMc: noooo, that's Systems Hungarian

12:08 https://en.wikipedia.org/wiki/Hungarian_notation#Systems_vs._Applications_Hungarian

12:09 jayunit100: ah good point

12:10 mega`: i had a robotics corse in scool where whe had to use a simelar notation

12:10 jayunit100: what about maps/arrays/lists

12:10 mega`: write o-* like in "object" :D

12:11 jayunit100: ,(nth "ABC")

12:11 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$nth>

12:11 jayunit100: oops meant to put that in the repl

12:12 yoklov: comma included? :p

12:12 jayunit100: yup

12:12 dont ask

12:12 yoklov: i mean, it is whitespace :)

12:12 jayunit100: ha

12:13 its funny b/c no joke then i did it in the repl to w/ the comma .

12:27 ,(seq (.toCharArray "ASDF"))

12:27 clojurebot: (\A \S \D \F)

12:27 jayunit100: this seems awefully non-elegant

12:27 mega`: Oo

12:27 , (seq "ASDF")

12:27 clojurebot: (\A \S \D \F)

12:27 mega`: pew pew

12:28 gtrak``: what else would it be?

12:28 maybe it just looks ugly :-)

12:28 jayunit100: well.. figured ther'd be a function for it

12:29 mega`: , (apply str (seq "ASDF"))

12:29 clojurebot: "ASDF"

12:29 jayunit100: with all this "clojurscript", "clojure in python" stuff... Im thinking it might be best to avoid java artifacts when possible

12:29 ,(seq "ASDF")

12:29 clojurebot: (\A \S \D \F)

12:29 jayunit100: ha

12:38 mega`: reddit has a time machine now :D :D :D :D

12:56 jonasen: lynaghk`: ping

13:02 hhutch: ibdknox: are you around?

13:06 jayunit100: um need some newbie help on a find-first-repeated-character .

13:06 http://pastebin.com/iCTmxAX4

13:07 if anyone has 3 milliseconds to look. Error is : ClassCastException java.lang.Character cannot be cast to clojure.lang.IFn problems.core/eval816 (NO_SOURCE_FILE:196)

13:07 mk: jayunit100: you seem to be putting a character into a list and accidentally executing it

13:08 mega`: you are using underline in your names

13:08 jayunit100: no underlines ?

13:08 mega`: thats clearly the prob

13:08 ofc

13:08 jayunit100: wow

13:08 mk: jayunit100: the convention is to use - instead of _

13:09 jayunit100: (defn first-duplicate-char [str-in]

13:09 (loop [list-Rem (seq str-in) set-Seen (set [])]

13:09 (print (type list-Rem) " " list-Rem (next list-Rem) "\n")

13:09 (if (= 0 (count str-in))

13:09 nil

13:09 (if (some #(= (first list-Rem) %) set-Seen)

13:09 mega`: also to create a set use #{}

13:09 jayunit100: (first list-Rem)

13:09 (recur

13:09 (seq (next list-Rem))

13:09 (conj set-Seen (first list-Rem)))))))

13:09 dnolen: jayunit100: please don't paste in channel

13:09 jayunit100: oh god that was ugly sorry wont do it again.

13:09 mega`: , (class #{})

13:10 clojurebot: clojure.lang.PersistentHashSet

13:10 dnolen: ,(let [x_cool 1] (+ 1 x_cool))

13:10 clojurebot: 2

13:10 jayunit100: I think underlines are okay.

13:10 dnolen: jayunit100: they are

13:11 mk: just don't use them in your code if you want it to be easy to read

13:11 dnolen: jayunit100: as mk says, _ are not idiomatic in names

13:12 jayunit100: updated.... But still fails .... :(. Whats the best way to debug this ? http://pastebin.com/RCXHy7bb

13:12 mk: (first list_Rem) looks like it has 3 elements at a glance, while (first list-rem) has just 2

13:13 TimMc: mk: Huh, that hasn't been a problem for me.

13:13 ...but maye that's because I've been doing some Python programming

13:14 lynaghk: jonasen: pong

13:14 jonasen: lynaghk: I released 0.0.3

13:14 mk: TimMc: it's subtle. It's just a bit of extra noise that you don't need (like the capitals on Rem)

13:14 lynaghk: jonasen: yeah, I just saw that. Thanks!

13:15 jayunit100: yeah. the rem should be lower case.

13:15 lynaghk: I'll do one last run through with cljx and open source that later today

13:15 jayunit100: but of course... my concern is this weird cast thingy. it seems perfect to me. the recursion prints out the correct smaller list on every iteration.

13:16 update --- okay, its definetly failing when it completes. For some reason... the return value is being evaluated or something... rather than just printed out at the REPL.

13:17 lynaghk: jonasen: also, re: mailing list. I don't think it would hurt. There seem to be a lot of people watching Kibit, so it'd be interesting to see what everyone is doing with it. Github chats are skewed to people with, er, issues.

13:17 mega`: jayunit100: http://pastebin.com/3P9Qd8P7

13:17 jayunit100: just to show you some stuff

13:17 dnolen: jonasen: lynaghk: I know I've said this before, but kibit is awesome!

13:18 jayunit100: mega thanks

13:18 jonasen: dnolen: thanks!

13:18 jayunit100: mega`: thanks i mean. :-]

13:18 dnolen: jonasen: lynaghk: I gave kibit 0.2 a run on Clojure itself and it ran suprisingly quickly.

13:18 lynaghk: dnolen: yes, it is crazy awesome!

13:18 mk: what does non-repetitive mean?

13:19 which problem is this from?

13:19 dnolen: so kibit can easily handle 14000 lines of Clojure which is going to bigger than most Clojure / ClojureScript projects

13:19 mega`: jayunit100: the ` is dear to me

13:19 lynaghk: dnolen: your speed test might make this a moot point, but will the fork/join stuff work automagically once it's merged into core.logic?

13:20 jayunit100: ha

13:20 jonasen: dnolen: I've done some optimizations on a private branch so I know how to make it run quicker if necessary :)

13:20 dnolen: lynaghk: probably, but I haven't looked into it quickly.

13:20 jonasen: yeah as the rules get larger you probably want to do some indexing.

13:20 I mean I haven't look into it deeply.

13:21 jonasen: is it pretty easy to add your own rules right now?

13:21 jonasen: dnolen: no. This release is mostly for Kevin ;) More to come!

13:22 dnolen: jonasen: yeah I imagine different shops would want to add rules for work practices.

13:22 lynaghk: dnolen: later today I'll be releasing a kibit-based lein plugin for rewriting sources. There is an option for custom rules in that

13:22 dnolen: depending on what you want to do with your custom rules.

13:23 dnolen: jonasen: one thing to think about is very complex rules really are possible - did the file ever get closed kind of thing. non thread safe Java types etc. You could probably even detect race conditions in ClojureScript.

13:24 lynaghk: very cool!

13:25 * lynaghk has to go take care of hipster friend's PDX urban chickens.

13:27 jayunit100: ok migrated to stack overflow : I think the issue is that the return val is being evaluated. not sure why though. probably a good lesson in here, somewhere. http://stackoverflow.com/questions/9966483/clojure-return-value-being-evaluated ..

13:34 TimMc: jayunit100: (set []) is #{}, (seq (next ...)) is (next ...), #'some on a set should really be #'contains

13:34 jayunit100: TimMc ?

13:35 TimMc: &(contains? (set "hello") \o)

13:35 lazybot: ⇒ true

13:35 jayunit100: oh i see, again not idiomatic.

13:35 TimMc: And I think you want rest, not next.

13:35 jayunit100: yeah, I was doing that just to validate the types and make them super explicit.

13:35 why rest not next?

13:36 ,(= (rest [1 2]) (next [1 2]))

13:36 clojurebot: true

13:36 xeqi: ,(= (rest []) (next []))

13:36 clojurebot: false

13:36 jayunit100: touche.

13:37 hhutch: dnolen: have you used ibdknox's monet?

13:38 dnolen: hhutch: i have not

13:38 jayunit100: TimMc: same problem still exists, even after changing to "rest" .

13:38 mfex: jayunit100, the exceptions are probably thrown by functions using first-duplicate-char, rather than in the function itself

13:39 hhutch: dnolen: you've done a bit of canvas+clojurescript though, right?

13:39 dnolen: hhutch: actually not much

13:39 hhutch: do you have a general question?

13:39 hhutch: dnolen: ok. i'm just concerned about the cpu usage

13:40 dnolen: hhutch: I would just program canvas directly w/ CLJS

13:41 hhutch: monet I think monet may lean on some of the higher level CLJS features which is not so good of your doing lots of custom drawing and perf really matters.

13:41 hhutch: ibdknox would know better than I tho I haven't looked at monet closely.

13:41 hhutch: dnolen: well, the issue with monet that i can see, which is just using canvas directly, is that it has a draw-loop which is redrawing the canvas constantly

13:41 jayunit100: mfex hmm. im calling it from the repl.

13:42 mfex:


13:42 hhutch: i have a cellular automata that is eating up 100% cpu when run in chrome

13:42 jayunit100: my problem was that I was wrapping the call in another closure somewhere.

13:42 dnolen: hhutch: just write your own thing :)

13:43 hhutch: dnolen: yeah i'm going to, i just wanted to see if anybody else had looked at the issue

13:43 mfex: jayunit100, the function can still use some work tho :)

13:43 jayunit100: Man.. It would be cool if clojure could embed some kind of safeguards for this. I always run into this problem.

13:43 Yeah, I was trying to hack it together as fast as possible without using the cheatsheet

13:43 hhutch: dnolen: thanks

13:43 dnolen: hhutch: fwiw, even pure JS I tend to avoid libraries for custom canvas drawing.

13:44 jayunit100: Im finding that i generally spend to much time w/ lein and docs when im learning new clojure stuff.. rather than focuing on writing stateless/dynamic lisp. the latter i think is more important as a first step .

13:44 Frozenlock: Is there a way to send a file to a Noir server by simply double clicking on an hyperlink shortcut? I want the user to be able to go the website and at the same time send pre-made data (small file). I'm thinking of using B64 encoded file in the url, but it feels like an ugly hack.

13:45 TimMc: jayunit100: I did a full answer on stackoverflow

13:46 jayunit100: Cool thanks. Im cleaning it up now.

13:49 weavejester: Has anyone ran into problems with lein2 and trampoline?

13:49 dnolen: weavejester: yep

13:49 weavejester: well I should qualify that - lein2 and lein-cljsbuild w/ trampoline doesn't seem to work.

13:49 weavejester: dnolen: Are you getting an "Unreadable form" error?

13:50 dnolen: weavejester: hmm, no I wasn't getting a specific error - just wasn't working.

13:50 weavejester: Hm… I don't see any issues open like this. I guess I'll report it.

13:51 TimMc: jayunit100: Made some more edits. I think I'm done.

13:56 jayunit100: Your problem was that (= 0 (count str-in)) never changes, so you eventually try to call first on nil.

13:56 Don't know if you saw that -- I edited it in just now.

13:57 AimHere: Idiomatically, isn't (= 0 (count str-in)) better written as (zero? (count str-in)) or even better (empty? str-in) ?

13:57 jayunit100: TimMc: actually that wasnt causing the bug. it was the way i called it at the repl

13:58 TimMc: &(first nil) ; oh, you might be right...

13:58 lazybot: ⇒ nil

13:58 jayunit100: AimHere: yeah. much more idiomatic to do it that way.

13:58 andyfingerhut: Would a github-related question be out of line here, if it is for a Clojure project on github?

13:58 jayunit100: TimMc: I suggest edit your answer to clarify that the function, inspite of its ugliness, works as is.

13:59 andyfingerhut: i think its okay to ask slightly off topic questions sparingly.

13:59 TimMc: Ah, it does!

13:59 dnolen: andyfingerhut: all Clojure related things allowed ;)

13:59 jayunit100: TimMc: what does & do ?

14:00 AimHere: Tells the bot to evaluate it

14:00 If you want a second opinion, use a comma instead

14:00 ,(first nil)

14:00 andyfingerhut: I forked someone else's project, committed some changes, made a pull request, they pulled them in, but they also had their own changes that aren't in my version. If I want to get up to the latest, should I delete my fork and create a new one based on their latest version, or is there a different way?

14:00 clojurebot: nil

14:00 jayunit100: sorry guys btw ....... im a hadoop developer so i never get to do any clojure and im constantly reusing variables and state... so i have a hard time getting back into clojureland.

14:02 TimMc: andyfingerhut: If you pull from upstream (their repo) into yours, you can get the changes.

14:02 mega`: andyfingerhut: your pull only needs to contain the changes you made.... are they in collition with there changes

14:02 ?

14:03 andyfingerhut: TimMc: You mean in my local repo on my laptop, I do a "git pull" with some kind of additional args to indicate the pull should come from their github repo instead of my github repo?

14:04 TimMc: yep, don't remember the incantation off the top of my head

14:04 andyfingerhut: TimMc: Thanks, I'll look at some docs focused in that area. Probably need to figure out the correct remote branch name.

14:04 TimMc: git remote add upstream git://... ; git fetch upstream ; git merge upstream/master

14:05 mega`: http://gitref.org/remotes/

14:05 TimMc: those last two can probably be combined into git pull upstream master

14:05 andyfingerhut: Thanks. Those are definitely going in my own personal git cheatsheet for future reference, since I won't be doing it very often.

14:06 TimMc: I had to go into my `history` list to find that.

14:07 mega`: no github related april fools?? seen

14:08 TimMc: There's this, whatever it is: http://cloud.github.com/

14:09 mega`: pritty :P

14:10 jayunit100: how come the REPL can't evaluate a destructured list

14:10 TimMc: ...but I don't know how old it is.

14:10 jayunit100: ,[[head & tail] [1 2 3 4]]

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

14:11 mega`: jayunit100: needs to be a let statment

14:11 TimMc: jayunit100: 1) Destructuring is a thing certain macros do, such as let

14:11 2) evaluation is done on code, not data

14:12 jayunit100: i guess 1) explains why this fails :

14:12 ,([[head & tail] [1 2 3 4]])

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

14:12 Bronsa: .(let [[head & tail] [1 2 3 4]] [head tail])

14:12 mega`: , (let [[h & t] (range 1 5)] (inc h))

14:12 clojurebot: 2

14:13 xeqi: ,((fn [h & t] [h t]) [1 2 3 4])

14:13 clojurebot: [[1 2 3 4] nil]

14:13 xeqi: heh

14:13 taapa: How does one decide on Hiccup or Enlive for web app? Each has its pros & cons.

14:13 andyfingerhut: Yep, other macros are loop for doseq defn fn defmacro if-let when-let. There might be others, but those are most common places I've seen destructuring used.

14:14 mega`: https://www.google.com/intl/en/chrome/multitask.html

14:24 TimMc: taapa: Hiccup doesn't html-encode strings by default, which is kind of terrible.

14:24 taapa: On the other hand, enlive is tricky to learn.

14:26 taapa: TimMc: thanks these are new to me. I like Enlive way of separating concern, cleaner. But just to know why people prefer Hiccup such as being the default in Noir.

14:26 gfredericks: TimMc: would there be an easy way to change hiccup so that it did?

14:26 I guess you could box up strings that you wanted kept raw

14:27 yoklov: taapa: personal preference matters too.

14:28 ah, nm didn't see your 2nd message

14:28 xeqi: taapa: I think the desire to be simple wins there

14:28 so that it is faster to get going

14:31 hhutch: taapa: personally, I think enlive vs hiccup breaks down this way...

14:31 taapa: My guess is Hiccup is an DSL, thus appealing if you want Clojure to be domain language of all your problems. But I wonder how do you code in Hiccup if you have a web designer that is not progammer.

14:31 hhutch: dev teams that consist entirely of clojure devs, or clojure devs are entirely responsible for the HTML markup, want to use hiccup

14:32 if you are working with web designers who can produce html/css though, enlive is a dream

14:32 taapa: hhutch: thanks

14:33 hhutch: taapa: also enfocus now exists (the clojurescript version of enlive) ... which changes the landscape as well

14:33 from what i've seen though, most ppl that use enlive also use hiccup

14:34 taapa: enfaces? will take a look.

14:34 enfocus I mean

14:34 not a bad idea to combine both I guess

14:35 hhutch: http://ckirkendall.github.com/enfocus-site/

14:35 gf3: ibdknox: yt?

14:36 taapa: hhutch: thanks for the link.

14:36 hhutch: sure

14:40 yoklov: there's also crate which is clojurescript hiccup :p

14:41 taapa: hiccup vs enlive => enfocus vs crate :(

14:42 hhutch: taapa: do you know jquery ?

14:42 taapa: hhutch: no, mainly back end

14:43 hhutch: or, are you familiar with manipulating dom elements with css selectors?

14:44 that's all that enlive is. Also, if you ever have a need to do things like scrape html documents, enlive is very useful

14:46 taapa: hhutch: guess i have to play with them a bit first. thanks for advice.

15:21 kjellski: Why is clooj showing only my input as output?

15:24 Frozenlo`: Is there a way to create a temporary file? One that is never written to disk?

15:25 kjellski: nvm… crashed after first start… now it works as expected...

15:25 mega`: Frozenlo: you on a unix system?

15:26 Frozenlo`: No..

15:26 mk: Frozenlo`: you can write to a bytebuffer of some sort

15:27 mega`: Frozenlo: so windows?

15:27 Frozenlock: Yes, win7

15:27 mk: Frozenlock: otherwise, java allows you to create a temporary file in the system's default temp path (but this writes to disk)

15:28 Frozenlock: mk: bytebuffer seems good, assuming I can apply the same functions as for ordinary files.

15:28 mega`: Frozenlock: why a file are you going to pass it to some other program?

15:28 Frozenlock: nm

15:28 Frozenlock: I want to use https://github.com/bonega/pacl to zip some data, but it requires a file as input

15:29 mk: Frozenlock: you won't be able to treat it as a file, but you can use bufferedoutputstream etc. on it

15:30 Frozenlock: "Just extracts all files from something that can be coerced into an inputstream"

15:31 Frozenlock: you might want to check if the output does something similar

15:31 Frozenlock: I'll read about streams, brb :)

15:33 mk: Frozenlock: they wrap each other

15:45 Frozenlock: Ok I'm lost. How does one send data to a stream?

15:45 mk: Frozenlock: what kind of data?

15:45 Frozenlock: A map in this case

15:46 mk: Frozenlock: depends. A stream is a stream - it's linear. How are you going to stuff a map into a stream?

15:46 Frozenlock: Or rather ultimately a string (once in a file)

15:46 mk: Frozenlock: any preference? if not, what are you plotting to do?

15:46 Frozenlock: Well like I said I want to zip it.

15:47 rlb: Frozenlock: if you just mean write it so you can read it back later, you can use (binding [*out* stream] (prn foo)).

15:47 mk: ok, so you have some arbitrary string, and you want to turn it into an "inputstream" that the library you linked to can read

15:47 Frozenlock: Exactly.

15:48 Unless of course I'm doing extra steps for nothing and there's an easier way to achieve this goal...

15:48 mk: Frozenlock: http://stackoverflow.com/questions/782178/how-do-i-convert-a-string-to-an-inputstream-in-java#782183

15:50 pedroteixeira: hello folks! in clojurescript, any tips when getting "namespace already declared"?

15:51 mk: pedroteixeira: I know nothing of this, but perhaps try to change your namespace declarations to new ones

15:51 pedroteixeira: mk: ok, thanks

15:52 mk: pedroteixeira: there are a few different functions which might do something to the namespace, so check if you're defining it with one, and then with another

15:52 rlb: Frozenlock: with-in-str?

15:53 ,(doc with-in-str)

15:53 clojurebot: "([s & body]); Evaluates body in a context in which *in* is bound to a fresh StringReader initialized with the string s."

15:53 mk: pedroteixeira: I'm not sure how cljs implements namespaces, but another issue might be that your namespace conflicts with something js already uses, like document.Math

15:53 rlb: ,(with-in-str "drinkme" (read-line))

15:53 clojurebot: "drinkme"

15:54 eiro: hello

15:54 mk: eiro: hey, welcome

15:54 eiro: thanks

15:54 rlb: or

15:54 ,(with-in-str "{:a 5}" (read))

15:55 clojurebot: {:a 5}

15:55 Frozenlock: mk: Unable to resolve classname: ByteArrayInputStream :(

15:55 mk: Frozenlock: it's in the package java.io - import the package, or qualify the name :)

15:57 rlb: Frozenlock: if you're just trying to *write* the map, then is prn not good enough?

15:57 Frozenlock: Oh yes, it worked. Now the moment of truth ^^

15:57 rlb: I really don't know... I will check what it does

15:57 mk: rlb: it needs to become an inputstream so that it can be passed to a library

15:58 rlb: mk: to a zip library?

15:58 Frozenlock: rlb: yes

15:58 mk: rlb: yep - I think it was linked above

15:59 Frozenlock: https://github.com/bonega/pacl

16:00 rlb: mk: right, I just misunderstood.

16:01 Frozenlock: Grrr... No method in multimethod 'compress' for dispatch value: class java.io.ByteArrayInputStream

16:01 mk: I think it might be possible to bind "string" to *in* and then pass *in* into the library?

16:01 Frozenlock: From the source: defmethod compress clojure.lang.IPersistentCollection

16:02 mk: Frozenlock: weird. Pass ["this is a dumb way to do it"] to the function

16:03 Frozenlock: That's for me or the library? :p

16:03 mega: is it ON?

16:03 mk: Frozenlock: for the library, and because we don't know how to use the library yet :)

16:03 rlb: if you don't mind everything being in RAM, you can prn to a string, then create a reader (*in*) from the string via with-in-str, but I don't know if that creates a reader that the zip lib will accept.

16:03 mk: in the end that might be a bad idea but it's worth testing

16:04 I guess it's trying to serialize a collection?

16:04 rlb: Of course if you want to stream to the zlib lib, that'll take a bit more work.

16:05 Frozenlock: -> [Thrown class java.lang.NullPointerException]

16:06 Meh, I might be better off trying to find something else to compress. Surely I'm not the first wanting to compress data?

16:06 mk: Frozenlock: hmm. Maybe there's a better way - do you just want to zip a string into a file? Do you need to get it out later?

16:07 pedroteixeira: mk: just to let others know, upgrading to clojurescript tag r1006 fixed it

16:07 Frozenlock: Yes, but on another machine- so for now I really just need to compress it and dump it somewhere.

16:08 mk: pedroteixeira: thanks - glad you solved it

16:09 will it be easier to leave it uncompressed than it will be to solve the compression issue?

16:11 Frozenlock: Sure, it would be easier.. but I don't want "easier", I want "fully working" :p

16:11 And as a last resort I can print to file and then compress. However I don't like the idea of this extra file on the disk.

16:12 mk: Frozenlock: http://docs.oracle.com/javase/6/docs/api/java/util/zip/ZipOutputStream.html

16:13 Frozenlock: you could also search for 'using zipoutputstream' or somesuch

16:18 Frozenlock: http://tripoverit.blogspot.ca/2008/04/java-create-zip-file-in-memory.html This looks promising

16:19 And this too :D http://clojure-log.n01se.net/date/2011-05-23.html

16:19 Thank god for IRC logs.

16:21 rlb: Frozenlock: something like this:

16:21 ?

16:21 (with-file [zip (java.util.zip.ZipOutputStream.

16:21 (clojure.java.io/output-stream "foo.zip"))]

16:21 (binding [*out* zip]

16:21 (prn some-map)))

16:21 s/with-file/with-open/

16:21 mk: maybe some day someone searching will see the links you posted now. zip zipping compressing how to compress file string

16:23 Frozenlock: rlb: trying now!

16:24 rlb: Oh, and I didn't test that at all (obviously) -- I just guessed...

16:25 Frozenlock: => ZIP file must have at least one entry. The solution is near :)

16:25 Give me some time, I want to try to figure this one out.

16:28 rlb: Frozenlock: certainly

16:34 autodidakto: Anyone have any thoughts about the Expectations unit testing framework? (http://blog.jayfields.com/2011/11/clojure-expectations-introduction.html)

16:39 Frozenlock: (with-open [zip (java.util.zip.ZipOutputStream.

16:39 (clojure.java.io/output-stream "foo.zip"))]

16:39 (-> zip (.putNextEntry (java.util.zip.ZipEntry. "foo.txt")))

16:39 (binding [*out* zip]

16:39 (prn tt)))

16:39 => java.util.zip.ZipOutputStream cannot be cast to java.io.Writer

16:39 What did I miss?

16:40 rlb: Frozenlock: oh, wait -- this is a *zipfile* class (i.e. zip/unzip) -- I was thinking about gzip...

16:40 ?

16:40 s/this is/is this/

16:40 mk: Frozenlock: you have to construct a Writer, with zipoutputstream as a parameter

16:40 rlb: i.e. zip is file based, gzip is stream based.

16:40 mk: Frozenlock: PrintWriter, for example

16:41 rlb: Oh, that -- right -- will (writer ...) handle it?

16:41 i.e. (java.io/writer (...))

16:41 Frozenlock: rlb: yes, it's a zip, not a gzip compression

16:41 rlb: as a wrapper

16:42 But that will only work if the zipoutputstream is actually a normal output stream -- and I don't actaully know that (haven't looked).

16:42 mk: rlb: what do you mean by normal?

16:43 rlb: mk: just meant something that clojure.java.io/writer can handle.

16:43 ,(doc clojure.java.io/writer)

16:43 clojurebot: "([x & opts]); Attempts to coerce its argument into an open java.io.Writer. Default implementations always return a java.io.BufferedWriter. Default implementations are provided for Writer, BufferedWriter, OutputStream, File, URI, URL, Socket, and String. If the argument is a String, it tries to resolve it first as a URI, then as a local file name. URIs with a 'file' protocol are converted to local...

16:44 mk: Frozenlock: create a PrintWriter(zipstream), and use its .append() or print or println methods to write your string

16:45 rlb: Frozenlock: do you really need a zip file (as opposed to a gzip file)?

16:45 If not: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/zip/GZIPOutputStream.html

16:46 Which I would assume behaves more like a normal stream.

16:46 Frozenlock: rlb: yes. However I will keep this for future references, thanks ^^

16:46 mk: rlb: writer might work, since it seems to wrap outputstreams

16:46 Raynes: Frozenlock: https://github.com/Raynes/fs/blob/master/src/fs/compression.clj#L10

16:46 mk: rlb: streams are just sequences of bytes (or characters, etc)

16:48 rlb: mk: I know -- I just meant that I hadn't checked to see if zipoutputstream was a normal stream (i.e. was actually subclassed from outputstream). It is.

16:48 mk: rlb: they can be fed into the disk, or into the network, or into a byte array. From that perspective, gzip and zip are identical

16:49 rlb: And the reason I had started to wonder was because zip is an archive format, rather than just a compresion format.

16:49 mk: rlb: it's usually very safe to assume that it is - I've never seen a class ending in OutputStream that didn't extend/implement the right things

16:49 rlb: But they've obviously implemented the class as a normal outputstream.

16:49 mk: right, but since I wasn't sure, I wondered.

16:50 mk: rlb: sure, but you can implement outputstreams for archives that aren't compressed - streams are very flexible :)

16:50 for example, you can create various CryptoOutputStreams with parameters, and they'll encrypt according to your public key or what have you

16:51 rlb: I know -- I just wasn't *certain* about that class until I actually looked at that particular class's docs.

16:51 mk: you can also attach HashOutputStreams (or Input) and feed data through them, and they'll tell you the MD5 or SHA1 of the bytes

16:52 rlb: yep :) don't mind me, I'm just being overinformative

16:52 Frozenlock: Raynes: thanks, but I want to zip on-the-fly, without a prior file on the disk.

16:52 Raynes: Frozenlock: Oh, I thought you wanted to extract a zip file.

16:53 Frozenlock: If you write something for that, please contribute it to fs.

16:53 rlb: mk: didn't know about the hash*streams.

16:53 mk: Raynes: String -> new zip file on disk

16:54 Frozenlock: Raynes: it's more like mk and rlb are writting it and I watch helplessly :P

17:00 Almost! The zip-file is there, an the foo.txt inside it. However the .txt is empty

17:00 (with-open [zip (java.util.zip.ZipOutputStream.

17:00 (clojure.java.io/output-stream "foo.zip"))]

17:00 (-> zip (.putNextEntry (java.util.zip.ZipEntry. "foo.txt")))

17:00 (.append (java.io.PrintWriter. zip true) "This is a string"))

17:00 ...

17:00 I'll find a paste site

17:03 https://gist.github.com/2278682

17:10 mk: Frozenlock: hmm, try using println instead of .append?

17:11 rads: has anyone tried using node.js with the latest version of lein-cljsbuid?

17:11 Frozenlock: I tried .write, .append, .print...

17:12 Of course... it works with println!

17:12 rads: I'm getting an error with clojurescript r1006 with any node.js compilation I try

17:12 Frozenlock: :D

17:12 But why?

17:13 mk: Frozenlock: I don't actually know, unfortunately - random guess

17:13 mega`: rads: compiler error?

17:13 rlb: Frozenlock: you're probably not closing the stream -- i.e. println has a newline which is forcing the flush.

17:13 rads: mega`: yeah. I think it might have been fixed here: https://github.com/clojure/clojurescript/commit/7472ab9013ad5d2b3468daabe20ba3479546f287

17:14 the error I'm getting comes from dependency-order-visit

17:14 rlb: Frozenlock: you could probably also just flush the stream manually, but closing everything properly should handle it.

17:14 mk: with-open doesn't auto-close?

17:14 rads: java.lang.String cannot be cast to clojure.lang.Associative

17:14 mk: closing a stream will flush it, and close (and flush) any sub-streams

17:15 rads: mega`: it happens even with a blank file with just an (ns) declaration

17:18 mega`: rads: 1.2.3?

17:18 rads: 0.1.5 ?

17:18 rads: yeah

17:18 node.js compilation breaks from 0.1.2 on

17:19 there was another clojurescript error in the version before r1006 too

17:20 so I've been using 0.1.1 for now

17:20 when I use that version my code compiles and runs just fine

17:21 mega`: rads: ill test it out brb

17:25 rads: just in case this didn't send since I got disconnected: mega`: awesome! thanks. I would test it out with r1006 myself, but I don't know much about adding my own development versions of dependencies with leiningen

17:25 yoklov: anyone want to checkout a neat clojurescript page i made? http://thomcc.github.com/hex/

17:26 mk: yoklov: pretty

17:27 yoklov: haha, thanks

17:27 dnolen: yoklov: nice!

17:28 yoklov: so you've done a CLJ and a CLJS app now :)

17:28 yoklov: haha, yup

17:28 i've done other clj stuff but nothing that interesting (and even more stuff that never got completed)

17:29 dnolen: yoklov: well I liked dunjeon!

17:29 yoklov: dnolen: dunjeon was a lot of fun to make

17:29 mk: it runs somewhat slowly if you do randomize

17:29 yoklov: yeah

17:29 mk: the more cells on the board, the slower it runs :/

17:30 i use `frequencies` and sets, which… take their toll.

17:31 mk: do you precompute the next round? because if you do a timeout, and then compute, perhaps you should compute, and then timeout

17:31 yoklov: the upshot of the way i do it now is it would be trivial to change to support an infinite grid if there were a faster hashmap implementation

17:31 hm, i hadn't thought of reordering that

17:31 dnolen: yoklov: it's nice and I imagine it will only get faster w/ time.

17:32 mk: yoklov: what do the alive and dead mean?

17:33 yoklov: mk: they're the rules, if a cell has one of the yellow numbers in `alive` neighbors and is active, it will be alive in the next round, if it has one of the numbers in `dead` and is dead, it will come to life the next round

17:33 if that makes any sense

17:34 dnolen: yup, that was my thinking too;

17:35 alexbaranosky: when does Clojure wrap thrown exceptions in Runtime exceptions?

17:37 yoklov: mk: no dice, still crawls after doing randomize if i reorder those

17:37 mk: so alive applies to alive cells, and is a sort of "must be these to keep alive", and dead applies to dead, and means "this many to come alive"

17:37 yoklov: yup.

17:37 actually i think it's faster in general if i do reorder them.

17:37 mk: yoklov: you shorten the timeout based on how long the computation took, yeah?

17:38 yoklov: no. i just do a timeout every 200ms

17:38 mk: yoklov: gotcha - initially I thought that alive meant what it took to come alive, and dead meant what it took to kill ;)

17:39 yoklov: yeah, i couldn't really think of any way to describe that in only a couple words

17:39 mk: yoklov: check system time before and after the calculation. So, start timer, display, calculate next round, stop timer, subtract now from start, subtract that from 200, timeout

17:39 yoklov: right no i'm familiar

17:40 you think it's really worth it though? it will still chug when it gets to the point that a computation takes more than 200ms

17:41 mk: yoklov: sure, why not? how long do the rounds take?

17:42 yoklov: after random? i just timed one which took nearly a second :/

17:42 amalloy: alexbaranosky: only on 1.3 - that change is reverted in 1.4

17:43 yoklov: (according to chrome dev console timelines)

17:43 mk: this hex pattern is rather pretty, and all of the combinations of alive/dead seem to produce very nice results - I'm trying nil/dead:1 now, and just starting with a dot

17:44 alexbaranosky: amalloy, thanks

17:45 yoklov: mk: that one looks very cool.

17:47 mk: the way i do it now hteres no chance of it skipping frames, if i did it the other way i think it would skip frames but keep a more consistent tick rate

17:47 mk: yoklov: you could also pretend that each cell is 3 units... and then have 8 states in each cell to check (or each cell 7, with 2^7 states)

17:48 yoklov: well

17:48 the way i could get the biggest benefit is by just using a 2d array for the cells

17:48 mk: ...that might actually be easier than it seems, since perhaps clojure could just calculate all those state values for you

17:49 yoklov: nah, I think you're right to avoid the 2d array, they're boring :)

17:49 yoklov: they are

17:50 but if i do it your way each cell would have 3 atoms in it?

17:50 or hm

17:56 mk: do we have the ability to stuff clojurescript into a <script> tag, and have it run?

18:02 gfredericks: mk: how would that work? send the cljs up to a compiler-service after it gets loaded in the browser?

18:03 yoklov: mk: no, the clojurescript compiler is written in clojure, and not clojurescript

18:04 mk: but... clojurescript is clojure...

18:04 gfredericks: people should stop saying that

18:04 mk: so the compiler is written in clojurescript?

18:04 yoklov: no, it's written in clojure.

18:04 if it were in clojurescript it could bootstrap itself.

18:04 and you could use clojurescript in a script tag.

18:05 gtrak``: mk, you can't have macros without eval, clojurescript doesn't have either

18:05 mk: yoklov: yes, exactly - like with coffeescript :)

18:05 how much work would need to be done for a js compiler?

18:09 yoklov: writing it in cljs is not really a goal for performance reasons (you'd need eval, i think, which can't happen if you do closure compiling)

18:10 and writing in js? meh. no clue, sounds _extremely_ hard

18:11 gfredericks: it can't be impossible to do it in cljs

18:11 compiling is just a function and cljs is turing complete...am I missing something?

18:11 is it just much messier?

18:12 yoklov: well, just because something is turing complete doesn't mean it can do that.

18:12 htere are plenty of undecidable problems

18:12 but

18:12 gtrak``: it's not impossible? clojurescript was meant to be a step forward for clojure-in-clojure, you'd need a full clojure-in-clojure to do it

18:13 yoklov: i have no idea. i think the issue is that it would suck more to do.

18:13 mk: yoklov: the set of undecidable problems for any two given turing complete things are identical

18:13 yes, it would suck more

18:13 yoklov: also it would require rewriting the compiler into cljs

18:13 mk: is the compiler written in java?

18:14 yoklov: clojure!

18:14 jvm clojure

18:14 mk: oh, well then that should convert right over to cljs...

18:15 Frozenlock: mk: I'm trying to put what I've learn earlier into a function taking optional argument (many files to zip), but I think I might have messed up with the recur. Would you mind to take a quick look? https://gist.github.com/2279100

18:15 The function works if I remove the (when.... (drop 2 remain)) part and use it for a single file to zip.

18:16 amalloy: i think you want [name cont remain], not [name cont & remain]

18:17 yoklov: mk: the languages aren't the same :/. they're very close, but certainly not identical. Also, if the cljs compiler were written in cljs, compilation would be slower than it already is

18:18 Frozenlock: Wouldn't it be nil either way? (If I don't give other filename that is..)

18:19 mk: yoklov: yeah, I don't know too much about cljs. Compilation of a few lines shouldn't be too bad though

18:20 yoklov: well you'd lose macros, is a proble

18:20 Frozenlock: amalloy: you were right... thanks :)

18:21 mk: yoklov: that might be alright, as a start

18:21 yoklov: eh, i'd rather have macros than cljs-in-cljs

18:22 though maybe you could work around that, idk.

18:22 really i'd rather the compiler worked faster. even in its current state it's frustruating.

18:22 Frozenlock: Now I just need to find how to do the inverse... unzip on-the-fly without a file on disk.

18:22 mk: Frozenlock: I'd guess zipinputstream

18:23 Frozenlock: Indeed

18:26 rads: mega`: I tested my code with clojurescript r1006, and it seems to compile fine, so there must be something with lein-cljsbuild that breaks node.js compilation

18:30 mega`: rads: what did your test include?

18:39 muhoo: i'm complietely baffled by this ppassage in hex: https://refheap.com/paste/1634

18:39 Zoka: cemerick: CCW [0.7.0] beta looks great, no more printlns for me :)

18:39 cemerick: Zoka: :-)

18:40 Is that what you're planning on using from here on out?

18:40 muhoo: it seems like it's calling a vector with something as an arg

18:41 ah, vectors ara callbale, got it. nm

18:41 callable even

18:41 Zoka: cemerick: Yes, I could not use it before due to the nREPL conflict between ringMon and CCW

18:42 cemerick: ah, right

18:42 that shouldn't change much at all from here on out

18:43 the easy stacking of HTTP on top has made me far more comfortable with the architecture, etc.

18:43 yoklov: muhoo: yeah

18:43 cemerick: 0.2.0 is still beta, so there's lots of little details to nail down, but it seems quite solid

18:43 yoklov: that code… its a little bit hacky at poitns

18:44 Zoka: I did not have any problems so far

18:44 yoklov: (i'm happy people are looking at it though :)

18:45 Zoka: I am really glad that CCW is in good shape since Emacs is not my cup of tea :)

18:45 muhoo: it's very cool. and it's only like 150 lines of cljs loks like

18:45 cemerick: Insofar as everyone using lein2 is using nREPL, it's gotten quite a beating from a testing perspective.

18:47 Zoka: Meanwhile, they should try lein2 webrepl, that works fine. :)

18:48 muhoo: webrepl? isnt' that himera?

18:48 Zoka: No, Himera is for ClojureScript

18:49 This is similar, but for Clojure proper

18:49 mk: in ccw, I had trouble with it not using 1.3, and I didn't like that it opened a new repl view each time, rather than having one view with numerous repls hooked into debug and console...

18:50 yoklov: muhoo: haha, yup, I usually try to be concise in my code.

18:50 emacs 4 life!

18:51 Zoka: mk: Now lets you use whatever is in your project.clj, but you have to do m2e import of pom.xml generated by 'lein pom'

18:51 mk: lein2 native support is comming shortly

18:52 cemerick: mk: numerous REPLs in one view? Is there another tool that works like that?

18:52 mk: Zoka: sounds excellent

18:52 cemerick: the console and debug views do this (not sure about other tools...)

18:53 cemerick: oh, in Eclipse you mean

18:53 Zoka: cemirck: one man's feature is another man's bug

18:53 cemerick: Yeah, I quite dislike how the Console view in Eclipse works.

18:54 mk: cemerick: yes. It would mean that I always had to move the view to the right place whenever a new one started

18:54 muhoo: yoklov: it's very cool. though i had to do stuff like this in order to attempt to get my feeble brain around it: https://refheap.com/paste/1635

18:54 mk: cemerick: what's the problem with it? that you can't pull them apart?

18:54 cemerick: mk: they always start in the same region as where you put the last one

18:55 I've always found the sub-view design very confusing

18:55 mk: cemerick: when I closed mine, it seemed to pick an arbitrary new position, perhaps beside console

18:55 Zoka: cemerick: you can open more than one REPL tab in CCW to the same process?

18:55 mk: cemerick: why is that?

18:56 cemerick: Zoka: sure, just connect to the same port

18:56 I suppose a button in the REPLView to do that would be good

18:58 Zoka: cemerick: that is feature I like, since you can run some slow thing in one tab, while dion normal stuff in another.

18:58 s /dion/doing/

18:59 cemerick: do you remember how to switch editor in structural mode in CCW?

19:00 mk: are haskell typeclasses essentially clojure protocols?

19:03 yoklov: haskells typeclasses can also dispatch on returntype

19:03 mk: yoklov: dispatch? returntype?

19:03 amalloy: mk: "use implementation X if the caller expects an Integer, and implementation Y if they expect a String"

19:04 yoklov: err, so they're polymorphic on the function's returntype, whereas protocols are only polymorphic on the function itself

19:04 mk: ah, I see. Yes, that's right - thanks

19:05 amalloy: $heval read "5" :: Int

19:05 lazybot: ⇒ 5

19:05 yoklov: so you can use `read` where something expects an integer, and it's the same as Integer/parseInt

19:05 yeah.

19:05 had no clue lazybot was that talented.

19:06 amalloy: there's another haskell bot in here somewhere

19:06 > 5

19:06 except i can't remember how to trigger him

19:06 gfredericks: amalloy: have you tried a monad?

19:07 amalloy: maybe

19:08 gfredericks: ~rimshot

19:08 clojurebot: Badum, *tish*

19:09 mk: I decided to learn about monads a couple of days ago, and ended up having to learn a bunch of haskell...

19:10 I think I'm at the point where I'm close to understanding what a monad is

19:11 yoklov: it's been a while since i did anything with them, so i might be defining this too narrowly, but iirc its just a type which helps you thread a value through some computation

19:13 mk: yoklov: that's part of it, I think, but there's also the IO part, and other things

19:13 yoklov: IO is still computation.

19:13 though you could be right i don't recall. I remember reading about the list monad in haskell was what made them click for me.

19:13 mk: yoklov: what value do you thread through it?

19:14 yoklov: oh

19:14 the value representing the state of the world

19:14 brb

19:14 mk: yoklov: I've had several things click, but I don't think I get monads yet

19:16 ah, right. Yeah, and haskell is affecting or acting on the state. I've read a post that was suggesting that this was the wrong way to think of it, that IO basically left a bunch of unfinished computations that were waiting for main (or something like that)

19:26 yoklov: maybe, but thats might be just because haskell has laziness to worry about

19:27 in terms of thinking of monads in general i don't think that's a bad way to think about the specific case of IO

19:27 i could be wrong though.

19:28 mk: the world-state idea is still a bit confusing for me, since IO gains type String, for example

19:30 yoklov: yeah, you're probably better off asking #haskell.

19:30 err, not with a period.

19:31 jimduey_: If you're interested in monads in clojure, may I humbly suggest http://clojure.net.

19:31 yoklov: or maybe someone else here can help

19:32 gfredericks: jimduey_: that's quite a domain name there

19:32 jimduey_: Yeah, I picked it up in the very early days of Clojure.

19:34 mk: yoklov: I tend to ask there when I get stuck. I did the whole "hey guys, what's a monad" thing a couple days ago, and it went from "it's just an interface" and "when you figure out what they are, you'll think 'is that all??' " to "you need to either learn haskell, or category theory in order to understand monads" over the course of a number of minutes

19:35 jimduey_: That middle comment could very well be from me. :)

19:36 brehaut: IMO the best way to learn what a monad is is to spend time reading the code, performing reductions by hand, and writing implementations of your own

19:36 mk: jimduey_: thanks for the link - I'll read through the monads-in-clojure page

19:37 jimduey_: mk: feel free to shoot me any questions you might have.

19:37 mk: brehaut: yeah, but that's also the slowest way, and requires you to be proficient in a monady language haskell

19:37 brehaut: mk: it does not

19:38 i learn monads by writing implementations in javascript and python

19:38 s/learn/learnt/

19:38 mk: jimduey_: thanks

19:39 brehaut: any examples that were particularly enlightening? (I know js but not python)

19:39 brehaut: mk: id start of trying to write an identity monad, and then a maybe

19:40 mk: brehaut: I think I've done both, though I'm unsure if they meet the various criteria and functions associated with monads

19:44 yoklov: mk: if they say you need to understand cat. theory or haskell they're wrong

19:46 brehaut: mk https://refheap.com/paste/1640

19:46 rough around the edges, but IdentityM and MaybeM in JS

19:46 mk: yoklov: I figured, but I don't know if the thing that will make people grok monads exists

19:47 brehaut: the thing to make you grok monads is to put in the work to grok monads

19:48 mk: brehaut: definitely - but definitions of "work" vary, from "learn haskell or category theory" to "just think of it as an interface in java"

19:49 brehaut: learning category theory is about as far away from learning monads for function programming as you can get :P

19:50 and re haskell: any language with closures is a suitable enviroment for learning about monadic constructions

19:50 haskells syntax just happens to make it much less painful to write large pieces of monadic code

19:52 mk: brehaut: introduce corresponds to "return", I take it

19:52 brehaut: yes

19:52 mk: I'm still hazy on the equivalence of bind with fmap and join

19:53 brehaut: for two reasons: a) return is a reserved word b) i think introduce is slightly clearer name for it when you are learning: it introduces a value into the monadic context

19:53 justin1: what's the easiest way to sort a map a custom order of its keys? ie I have a map {:a 1 :b 2 :c 3} and I want to get a sorted map ordered {:b :c :a}?

19:53 brehaut: (ie, theres less semantic overloading with what most programmers think return does)

19:55 jimduey_: justin1: Depends on what you want. If you want a sequence of the key value pairs from a map once, use a variant of 'sort'.

19:55 If you want an actual map that will always return the values in a sorted order, use a sorted map.

19:55 You can specify the comparator to sort with in both instances.

19:56 mk: justin1: what jimduey_ said, and have a look at sorted-map-by. You might also find http://clojure.org/cheatsheet useful

19:56 jimduey_: brehaut: Nothing turns the light on for monads like actually working with them at the REPL.

19:56 brehaut: jimduey_: absolutely

19:57 justin1: thanks guys, I'm just wondering if there's a quick way to build make a comparator to return a specific, arbitrary order based on the keys

19:57 mk: jimduey_: "A monadic function is a function that accepts a value and returns a monadic value" - can the value be itself a monadic value, and does a monadic function count as a monadic value?

19:57 brehaut: jimduey_: although for state-m i found a simple example and then did all the reductions by hand on paper

19:57 jimduey_: And implementing a couple is a great exercise if you have the patience.

19:58 mk: jimduey_: by the value, I mean the value that is accepted

19:59 jimduey_: mk: The value passed in can be any value, even a monadic value. But in that case, it's treated like any other value. Nothing special happens just because it's a monadic value.

19:59 And a monadic function does not count as a monadic value.

20:00 Though in some monads, monadic values are functions. They are different than monadic functions in those monads. Which is where some of the confusion comes in.

20:00 I try to untangle that in some later posts.

20:00 mk: jimduey_: I take it that this is because it is unwrapped before being given to the Monad-wrapped function (my thoughts are burrito-explanation flavoured here)

20:02 jimduey_: If I get your question correctly, the answer is no. Any value passed to a monadic function is just used as is, there is no unwrapping. But the function returns a monadic value.

20:05 mk: supposing that 1,[1] -> [2] (this is just addition within a monad), what sort of function will allow [1][1]->[2]?

20:05 brehaut: well bind only takes a unary function, so you need to partial your addition

20:05 and then wrap it up in a return

20:06 so that it returns a monadic value

20:06 jimduey_: Yeah, a monadic function by definition only accepts a single parameter.

20:06 brehaut: that operation of taking a non monadic function and making it return a monadic value is called lifting

20:09 mk, i mucked up my bind definitions above

20:09 mk: how far above?

20:10 brehaut: mk in the refheap paste

20:10 mk, bind: function (f) { return (this.v !== null) ? f(this.v) : new MaybeM(null); }

20:11 mk: and usage would be new MaybeM(1).bind(function (v) { return new MaybeM(v + 1); }).v

20:11 mk: you removed the monad wrapper around the returned value?

20:11 brehaut: thats correct

20:11 mk: are you sure that's right?

20:12 brehaut: yes

20:12 mk: but then bind doesn't return a monadic value

20:12 brehaut: exactly

20:12 well

20:12 sort of

20:12 it does because the function passed to it does

20:14 mk: yes I see

20:14 brehaut: the type of the function bind takes is a -> m a

20:16 mk: one of the confusing things about monads is how bind can be seen either as taking a monadic value and a monadic function, returning a monadic value; or as taking a monadic value, and returning a function with a closure that takes functions and spits out the prior-mentioned result value

20:17 jimduey_: yeah, I can see how that's confusing when you first see monads. I typically only focus on the 1st perspective.

20:24 gfredericks: ,(prn (keyword "foo (System/exit)"))

20:24 clojurebot: :foo (System/exit)

21:00 Frozenlock: Is there a way to put a default file name in (choose-file) in the seesaw library?

21:08 jasox: Need help people, can not configure slime to work with emacs24. Please can someone tell me what is easiest way to configure slime with emacs. If someone have links for useful dot files. ANYTHON !! Thanks

21:09 bpr: does ring.middleware.wrap-file follow symlinks?

21:09 mega`: jasox: w8 for link

21:10 Raynes: w8? wait?

21:10 mega`: Raynes: yea dont play games much? :D

21:10 Raynes: Please don't do that unless you're typing on a keyboard in klingon and you don't know how to spell 'wait' on it.

21:11 mega`: jasox: http://marmalade-repo.org/packages/starter-kit

21:11 autodidakto: Raynes: omglol

21:11 Raynes: rofl

21:11 autodidakto: Raynes: you're complaing about w8? srsly?

21:11 Raynes: yarly

21:11 weavejester: bpr: The easiest way is to check it out, I think. It should do… because it just uses the normal Java I/O libraries.

21:11 mega`: Raynes: where in a chat this is absolutly the playes for w8, brb, etc ....

21:12 jasox: Yeah I instelled it. But can not configure it. What should I add in .emacs

21:12 Official tutorial is not working for me :/

21:12 Raynes: Yikes.

21:12 weavejester: mega`: I'm trying to decide if you're doing an april-fools :)

21:12 Raynes: Yeah, I'm thinking he is. At least, I'll sleep better tonight if I think that.

21:13 mega`: jasox: create a .emacs.d directory

21:13 jasox: and make init.el file

21:13 jasox: o w8 i think 24 alreddy has package.el

21:13 bpr: weavejester: It looks like it doesn't.

21:13 jasox: and ?

21:14 autodidakto: weavejester, Raynes: stop being a h8ter

21:14 Raynes: kk

21:14 autodidakto: as mega said, he's absolutely the playa

21:14 jasox: mega`, it has

21:14 mega`: jasox: so M-x and package-list-packages

21:15 jasox: and C-s to search for clojure-mode

21:15 jasox: press x to select the package for instalation

21:15 jasox: k

21:15 mega`: jasox: i mean i to select it and x to install

21:16 jasox: get the test mode and clojurescript while your att it

21:16 jasox: "get the test mode and clojurescript while your att it" - don't get it

21:17 mega`: jasox: u can select multiple packages for install

21:17 jasox: k

21:20 mega`: jasox: when your done whit that you need to get the swank-clojure plugin for leiningen

21:28 jasox: mega`, ok what should I do then.

21:29 mega`: jasox: you have lein installed?

21:29 jasox: yes

21:29 mega`: jasox: and swank-clojure?

21:30 yoklov: how can i get a more, uh, useful string version (or print one out) of a structure in cljs? right now the best i've got in most cases is [object Object]

21:30 jasox: mega`, yes

21:30 mega`: jasox: then navigate to your project

21:30 jasox: and use M-x clojure-jack-in

21:31 jasox: WOW, finally. Thank you mega`

21:32 timvisher: hey kids

21:32 can anyone point me to the rationale behind clojure's lack of support for currying?

21:32 amalloy: timvisher: varargs

21:32 mega`: timvisher: there the partial function

21:33 timvisher: mega`: completely aware of that. That's not really currying in the Haskell sense.

21:33 amalloy: that's the rationale? as in JVM varargs?

21:34 amalloy: no, as in clojure varargs

21:34 how do you curry the + function? it takes any number of args

21:34 timvisher: gotcha

21:34 yoklov: timvisher: think about things like zipWith3 in haskell.

21:34 you don't need ugliness like that in clojure.

21:34 timvisher: yoklov: i actually have no experience with Haskell ;)

21:34 yoklov: (as a result, you hava ugliness in partial application)

21:34 ah

21:34 timvisher: but I'll take your word for it

21:34 amalloy: yoklov: it's an ugliness tradeoff, yeah

21:34 autodidakto: Clojure vs Haskell, as well as currying, also comes out in difference over pattern matching

21:35 timvisher: it's quite obvious once you state it that way

21:35 amalloy: autodidakto: well, that's a feature that can be added on top of what clojure already has

21:36 xeqi: autodidakto: core.match is pretty good

21:36 mk: clojure functions that take varargs can be thought of as taking lists, instead

21:37 yoklov: mk: doesn't solve the problem though, because during partial application they aren't taking a list

21:37 autodidakto: xeqi: ah yes. I've been meaning to check that you

21:37 amalloy: how would you go about it?

21:38 amalloy: i'd probably just ask dnolen to do it

21:38 and then he'd be like "oh, i already did, mate, it's in core.match"

21:38 assuming that for april fools he fakes an australian accent

21:38 mk: yoklov: the cases of partial application on vararg fns that I can think of involve the non-vararg parts (as if you're initializing the function) - is partial application of varargs common?

21:39 yoklov: ,(map (partial + 5) [1 2 3])

21:39 autodidakto: amalloy: kangaroo.match maybe, hehe heh

21:39 clojurebot: (6 7 8)

21:39 autodidakto: ,(+ 5 [1 2 3])

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

21:40 autodidakto: oh duh, map

21:40 yoklov: thats usually when i use partial application

21:41 autodidakto: yoklov: as a short/simple-function-like-shortcut?

21:41 yoklov: yeah

21:41 autodidakto: ,(map #(+ %) [1 2 3])

21:41 clojurebot: (1 2 3)

21:41 autodidakto: deer

21:41 yoklov: or if i want to express somethign iin a snooty way

21:41 autodidakto: ,(map #(+ 5 %) [1 2 3])

21:41 clojurebot: (6 7 8)

21:41 yoklov: ,(map (partial map +) [[1 2] [3 4]] [[5 6] [7 8]])

21:41 clojurebot: ((6 8) (10 12))

21:42 autodidakto: *head explodes*

21:42 mk: yoklov: yeah somewhat, though you might as well think of add as (+ a b list-goes-here)

21:42 yoklov: lol, think of (partial map +) as `point-add`

21:42 autodidakto: that's snooty. did you type that with your pinky fingers in the air?

21:42 yoklov: yeah.

21:43 ,(map (partial + 1 2 3) [4 5])

21:43 clojurebot: (10 11)

21:44 yoklov: mk: varargs and currying just don't mix well

21:44 mk: ,(map (partial + 6) [4 5])

21:44 clojurebot: (10 11)

21:44 mk: I agree, but I'm not sure I'm a fan of either

21:44 yoklov: right, but you can only do that because you know that (+ a b c … rst) is the same as (+ (+ a b c) … rst)

21:45 thats certainly not true in every case.

21:46 mk: + is a pretty good case for varargs, but it's really just (sum [1 2 3...])

21:46 mega`: &(doc sum) ; dont think whe have sum

21:46 lazybot: java.lang.RuntimeException: Unable to resolve var: sum in this context

21:47 mega`: mk: so yea + is the sum

21:47 brehaut: sum is (apply + …)

21:47 yoklov: it's just apply +

21:47 Raynes: Or (reduce +)

21:47 yoklov: (partial apply +) :p

21:47 (or reduce)

21:47 Raynes: #(apply + %)

21:47 clojurebot: Cool story bro.

21:47 mk: the reason I don't like varargs is that they are placed in arbitrary places in some of our functions (like in the middle), and some functions take lists when they may as well take varargs

21:48 autodidakto: ,((partial apply +) '(1 2 3))

21:48 clojurebot: 6

21:48 mega`: mk: in the midle?? what

21:48 Raynes: In the middle of a gunfight.

21:48 mk: mega`: yeah, let me find it...

21:49 autodidakto: Raynes: Never bring a vararg knife to the middle of a curry gunfight

21:49 at least that's my understanding

21:49 amalloy: btw, since we're discussing apply vs reduce, my favorite explanatory tool is ##((juxt apply reduce) (partial list '+) (range 5))

21:49 lazybot: ⇒ [(+ 0 1 2 3 4) (+ (+ (+ (+ 0 1) 2) 3) 4)]

21:50 yoklov: mk: i really wouldn't want to part with vararg map.

21:50 autodidakto: ,(doc juxt)

21:50 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)]"

21:50 amalloy: yeah, god help us if we had zipWith5 in the language. blech

21:51 mk: the best way to explain apply on its own, I think, is as injecting the given function into the front of the given list. It's an injector.

21:51 brehaut: amalloy: (partial list '+) (range 5) is cute, but why not just (list* '+ (range 5)) ?

21:51 amalloy: uhhh

21:51 because that doesn't illustrate the point?

21:51 yoklov: mk: well but then it gets hairy, because some languages (ruby, for one) call reduce inject :p

21:51 smalltalk too i think.

21:52 amalloy: the point is that reduce and apply do different things; i'm not just calling ((partial list '+) (range 5))

21:52 Raynes: That's because it was named by a Japanese guy.

21:52 mega`: yoklov: .net cals it Aggregate

21:52 yoklov: right but he said it was injecting… yeah nevermind

21:52 brehaut: oh right

21:52 autodidakto: yoklov: inject is the more common synonym, but i like reduce is an alias to the method

21:52 *but i think reduce is

21:52 Raynes: That's because .NET was created by suits with no human bodies inside.

21:52 mk: yoklov: map throws the varargs as params, so initially that looked fine - but then - have you used map to map into vararg functions? because that sounds interesting

21:52 autodidakto: Raynes: Report to HR, immediately

21:53 yoklov: mk, you mean like my example above?

21:53 ,(map (partial map +) [[1 2] [3 4]] [[5 6] [7 8]])

21:53 clojurebot: ((6 8) (10 12))

21:53 amalloy: &(apply map vector [[1 2 3] [4 5 6]])

21:53 lazybot: ⇒ ([1 4] [2 5] [3 6])

21:53 yoklov: oh thats neat.

21:53 * yoklov makes note

21:53 amalloy: ~zip

21:53 clojurebot: zip is not necessary in clojure, because map can walk over multiple sequences, acting as a zipWith. For example, (map list '(1 2 3) '(a b c)) yields ((1 a) (2 b) (3 c))

21:54 autodidakto: *head explodes*

21:55 oh right right, when given multiple lists/vectors/maps.. map takes one from each at a time..

21:55 mk: right, yeah - those are in fact interesting

21:56 mega`: , (map + (range 0 4) (range 0 8))

21:56 clojurebot: (0 2 4 6)

21:57 autodidakto: and stops when the shortest list ends...

21:57 mk: autodidakto: it takes all of the first elements in all of the given collections, and then shoves them into the given function as params (and then the second elements, then third...)

21:57 ,(apply map vector [1 2] {:a 8 :b 9})

21:57 clojurebot: ([1 :a :b] [2 8 9])

21:57 autodidakto: mk: I see. thanks

21:58 but what's that apply do?

21:58 ,(map vector [1 2] {:a 8 :b 9})

21:58 clojurebot: ([1 [:a 8]] [2 [:b 9]])

21:58 autodidakto: hmm

21:58 xeqi: ,((partial map vector [1 2]) {:a 8 :b 9})

21:58 clojurebot: ([1 [:a 8]] [2 [:b 9]])

21:58 mega`: &(doc apply)

21:58 lazybot: ⇒ "([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args]); Applies fn f to the argument list formed by prepending intervening arguments to args."

21:59 mk: I like to imagine them as.. dropping down, so [1 2 3 4] becomes vertical, and them map runs the function down this vertical strip. When given varargs, they all just roll down vertically

22:00 autodidakto: ,(map str [1a 2a 3a] [1b 2b 3b])

22:00 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.NumberFormatException: Invalid number: 1a>

22:01 mk: oh, apply is the one that takes varargs in the middle

22:01 autodidakto: ,(map str ["1a" "2a" "3a"] ["1b" "2b" "3b"])

22:01 clojurebot: ("1a1b" "2a2b" "3a3b")

22:01 amalloy: no it doesn't

22:01 mega`: mk: only the last one has varargs

22:01 mk: could be wrong, I'll check

22:02 autodidakto: scroll up to the last lazybot

22:03 mk: it lies

22:03 ,(apply vector 1 2 3 4 5 6 7 8 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 '(99 999))

22:03 clojurebot: [1 2 3 4 5 ...]

22:03 amalloy: okay...

22:04 mk: you can put an arbitrary number of arguments into the middle, and they are all injected into "args"

22:04 amalloy: i mean, i guess i see what you mean by varargs in the middle, there

22:05 mk: what's described as "args" can actually only be one argument. If you try to apply into an apply, you'll end up applying... I'm going to cut that sentence off there

22:06 mega`: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L596

22:07 mk: apply is what you pull out when you want to use a list as varargs

22:07 mega`: &(doc spread)

22:07 lazybot: java.lang.RuntimeException: Unable to resolve var: spread in this context

22:07 TimMc: mega`: That's private, I think.

22:07 mega`: yea

22:08 TimMc: &(meta #'clojure.core/spread)

22:08 lazybot: ⇒ {:ns #<Namespace clojure.core>, :name spread, :arglists ([arglist]), :private true, :static true, :line 574, :file "clojure/core.clj"}

22:08 TimMc: ...and doesn't have :doc anyhow.

22:09 mk: it's two functions up in that link above

22:09 amalloy: spread is just list*, iirc

22:09 except that it's a primitive used to define functions like apply and list*

22:09 &(#'clojure.core/spread 1 2 [3 4])

22:09 lazybot: clojure.lang.ArityException: Wrong number of args (3) passed to: core$spread

22:10 mega`: takes a seq directly

22:10 amalloy: right, it's (partial apply list*)

22:10 &(#'clojure.core/spread [1 2 [3 4]])

22:10 lazybot: ⇒ (1 2 3 4)

22:10 amalloy: &((partial apply list*) [1 2 [3 4]])

22:10 lazybot: ⇒ (1 2 3 4)

22:13 autodidakto: amalloy: can you give me another clue to understanding apply?

22:13 mk: apply is kinda like a cons that gets evaluated

22:13 scriptor: autodidakto: what other languages do you know?

22:14 mk: ,(cons '+ '(1 2 3))

22:14 clojurebot: (+ 1 2 3)

22:14 autodidakto: scriptor: ruby

22:14 mega`: , (eval (cons '+ '(1 2 3)))

22:14 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

22:14 scriptor: hmm, not sure about the equivalent of apply in ruby

22:14 mk: (eval (cons '+ '(1 2 3)))

22:14 mega`: :(

22:15 mk: hmm

22:15 > 6

22:15 scriptor: autodidakto: in a sense, apply is like ruby's send, except that it works on functions, not methods

22:15 mega`: :D

22:15 amalloy: scriptor: it's like ruby's splat operator

22:15 mk: (apply + '(1 2 3))

22:16 amalloy: (apply f a b c) => f(a, b, *c)

22:16 scriptor: yes, that too

22:16 autodidakto: hmm

22:17 scriptor: splat + higher order func

22:17 mk: autodidakto: at first think of apply as taking two arguments - a function, and a list

22:18 it puts the function at the front of the list, and then runs away (the new list is evaluated, as a list usually would be)

22:19 alternatively, if you have a function and it's missing a bunch of arguments, apply removes the brackets from that list, and puts them at the end of the function

22:20 apply fun '( 1 2 3) -> eval'd(fun 1 2 3)

22:20 autodidakto: ,(str '(1 2 3))

22:20 clojurebot: "(1 2 3)"

22:20 autodidakto: ,(apply str '(1 2 3))

22:20 clojurebot: "123"

22:20 mk: ,(str 1 2 3)

22:20 clojurebot: "123"

22:21 mk: in your first expression, you gave a list to str, but it expects varargs

22:22 apply is for turning any function that takes varargs into the same function, but taking a list

22:23 autodidakto: using the individual items of the list as it's arguments?

22:23 *its

22:23 mk: yep

22:24 varargs can be thought of as being a list anyway

22:24 autodidakto: "alternatively, if you have a function and it's missing a bunch of arguments, apply removes the brackets from that list, " is this what amalloy was talking about with the splat operator?

22:25 scriptor: autodidakto: more or less

22:25 amalloy: i don't want to be held responsible for any description of apply that makes it sound like it's manipulating source forms like brackets

22:26 mk: right - keep in mind that's not what it actually does. But when you're looking at something like...

22:26 scriptor: yes, don't really think about it in terms of shuffling parentheses around, it takes the function f and uses the elements of the list as its arguments

22:27 mk: ,(str '(1 2 3))

22:27 clojurebot: "(1 2 3)"

22:28 scriptor: autodidakto: what don't you still get?

22:29 mk: and you mess around with it and you find that (str 1 2 3) works just fine... well, the diff between the two is a pair of brackets. So you use apply

22:31 autodidakto: ,(map vector [1 2 3] [4 5 6])

22:31 clojurebot: ([1 4] [2 5] [3 6])

22:31 autodidakto: ,(apply map vector [[1 2 3] [4 5 6]])

22:31 clojurebot: ([1 4] [2 5] [3 6])

22:31 autodidakto: I'm trying to see how apply, like, went into the outter [vector]

22:32 mk: ,(map vector [1 2 3] [4 5 6])

22:32 clojurebot: ([1 4] [2 5] [3 6])

22:32 autodidakto: oh, by putting map inside it...?

22:32 mk: ,(apply map vector '( [1 2 3] [4 5 6]))

22:32 clojurebot: ([1 4] [2 5] [3 6])

22:32 mk: by putting both map and vector inside it

22:33 autodidakto: that would be the same as the "<mk> apply fun '( 1 2 3) -> eval'd(fun 1 2 3)" thing you said

22:33 scriptor: autodidakto: with your second expression, you're telling apply, "take the function map, and pass it 'vector' as the first argument, and [1 2 3] and [4 5 6] as the 2 and 3rd arguments"

22:34 autodidakto: scriptor: ah. that helps too

22:34 mk: the vararg thing is why I think it's easier to think of apply as shoving all the left-side arguments into the single right-side list

22:35 (apply list 1 '(22) 3 '(4))

22:35 ,(apply list 1 '(22) 3 '(4))

22:35 clojurebot: (1 (22) 3 4)

22:36 mk: ,(list 1 '(22) 3 , 4)

22:36 clojurebot: (1 (22) 3 4)

22:36 autodidakto: could you say that apply is a way to "prepare" the arguments for a given function?

22:36 yoklov: autodidakto, sort of

22:37 so i don't know if clojure does it this way

22:37 autodidakto: though by the name "apply", i guess it would be the other way around

22:37 yoklov: however typically

22:37 evaluators are made up of two runctions

22:37 `eval` and `apply`

22:37 scriptor: autodidakto: there's no 'preparing' done, it's about applying a given function to a list of arguments

22:37 yoklov: apply takes a function and a list of arguments, and applies the function to the arguments

22:37 scriptor: or a vector of args

22:37 yoklov: and eval uses apply to eval everything

22:38 so, when you type (apply foo '(bar baz)) it gets evaluated the same as (foo 'bar 'baz)

22:38 mk: autodidakto: you can think of it that way, because it's equivalent to how it's done, but not actually how it's done. Also, in (apply f :a :b '(1)), :a :b are arguments, too

22:39 yoklov: oh right, apply in clojure does that.

22:40 right, and apply just calls .applyTo on the function

22:40 with the args made into a list

22:41 mk: autodidakto: do you have a good handle on the two-parameter apply? where it's just a function and a list (or vector, or seq)?

22:42 autodidakto: mk: good enough I think

22:42 in that case i think "I have a list, but now I want to use the items in that list as my arguments"

22:43 mk: ,(apply list :a :b [3 4])

22:43 clojurebot: (:a :b 3 4)

22:44 mk: ,(apply (partial list :a :b) [3 4])

22:44 clojurebot: (:a :b 3 4)

22:44 mk: that's how the multi-param version of apply works (or another way to think of it)

22:45 autodidakto: in that first apply, how does it "know" to open up the vector?

22:45 (apply list :a :b [3 4] [5 6])

22:45 ,(apply list :a :b [3 4] [5 6])

22:45 clojurebot: (:a :b [3 4] 5 6)

22:46 mk: autodidakto: it's the last argument

22:47 autodidakto: i see

22:47 ,(apply (partial list :a :b) [3 4] [5 6])

22:47 clojurebot: (:a :b [3 4] 5 6)

22:47 mk: ,(apply (partial (partial list :a :b) [3 4]) [5 6])

22:47 clojurebot: (:a :b [3 4] 5 6)

22:48 mk: ,(apply (partial list :a :b [3 4]) [5 6])

22:48 clojurebot: (:a :b [3 4] 5 6)

22:48 mk: there's apply, then there's the stuff in the middle, and then there's the last item

22:49 the stuff in the middle is the function and its first few params

22:51 autodidakto: Is there an easy way to describe the situation in which apply is needed and a simple (fn arg1 arg2) wouldn't work?

22:51 mk: you have a list, and you need to use that list inside a function that takes varargs

22:52 autodidakto: with the list as it's varargs? or all it's args?

22:52 *its

22:53 mk: as its varargs

22:53 ,(+ '(1 2 3))

22:53 clojurebot: #<ClassCastException java.lang.ClassCastException>

22:53 mk: ,(apply + '(1 2 3))

22:53 clojurebot: 6

22:54 autodidakto: gotcha

22:54 mk: (obviously if you were typing this in, you would just remove the brackets in the first case, but '(1 2 3) is meant to stand in for a symbol)

22:55 autodidakto: i'll start looking around for examples of apply in use and think about what's going.

22:56 mk, scriptor, amalloy: thanks for the tutoring :)

22:57 mk: np. The only thing you need to know about apply is that if you have a list, and a vararg function, you can use apply

22:57 autodidakto: ah, yoklov too

22:57 mk: ...apply could have been averted if none of our functions used varargs :P

22:58 yoklov: haha, no clue if i helped at all :p

22:58 mk: you'd still need it in eval

22:58 mk: yoklov: yeah yeah :)

22:58 scriptor: no prob, eventually you'll find a place where apply will come in handy and it'll all click

22:59 autodidakto: mk: does that have something to do you with rant about varargs?

23:00 yoklov: I was intrigued about what you said about evaluators using eval/apply. I'm remembering the logo of the videos for the SICP book (which i havent finished *cough*)... the wizard with Eval/Apply in his crystal ball

23:00 yoklov: oh yeah

23:00 exactly that.

23:00 you should finish that. sicp is amazing :)

23:01 autodidakto: yoklov: the math-based examples make me squint at the screen

23:01 mk: autodidakto: yes. It also has to do with that part about varargs being in the middle, because that fun application of apply that you started with is... hard to start with

23:01 ,(apply map vector [[1 2 3] [4 5 6]])

23:01 clojurebot: ([1 4] [2 5] [3 6])

23:01 yoklov: hah, the math in that book is a killer.

23:02 regardless what i'm talking about was chapter 4

23:02 autodidakto: yoklov: cool. I'll look it up

23:02 mk: i see

23:03 mk: ...I just realized why ,(+ 1 2) works in my repl even though it has a weird symbol at the very front

23:06 scriptor: isn't , treated the same as whitespace?

23:06 mk: yes.

23:07 autodidakto: ,(doc ,str)

23:07 clojurebot: "([] [x] [x & ys]); With no args, returns the empty string. With one arg x, returns x.toString(). (str nil) returns the empty string. With more than one arg, returns the concatenation of the str values of the args."

23:07 mk: "cool, my repl accepts the same special initial symbols as clojurebot - that's pretty convenient for pasting"

23:08 scriptor: autodidakto: don't need the , before str

23:08 mk: , is whitespace

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

23:09 autodidakto: right right, just confirming your point

23:10 yoklov: SICP is really quotable -> It is no exaggeration to regard this as the most fundamental idea in programming: The evaluator, which determines the meaning of expressions in a programming language, is just another program. To appreciate this point is to change our images of ourselves as programmers. We come to see ourselves as designers of languages, rather than only users of languages designed by others.

23:11 yoklov: haha, sicp is really amazing. chapter 4 is my favorite :)

23:11 mk: ,(apply apply apply map vector [[[[1 2 3] [4 5 6]]]])

23:12 clojurebot: ([1 4] [2 5] [3 6])

23:13 autodidakto: mk: ouch, thanks :)

23:15 muhoo: autodidakto: then what about people who design languages for designers of languages?

23:16 autodidakto: muhoo: they sit in the lotus position, hovering 3 feet off the floor

23:17 muhoo: or in a hammock.

23:17 autodidakto: muhoo: taking the year off

23:18 muhoo: "In a hammock, nobody knows you're not sleeping." -- Rich Hickey

23:18 autodidakto: Which really sums up clojure development.... I think

23:20 There needs to be a comic of him lying in a hammock, taking the year off, and braiding his hair... hmm what other memes can i shove in there...

23:26 autodida: muhoo: Is there an online collection of rhickey quotes taken wonderfully out of context?

23:30 arohner: is there an an await that works for future?

23:32 mk: autodida: you might try searching the logs at http://clojure-log.n01se.net/

23:32 amalloy: arohner: isn't that just...deref?

23:33 Raynes: Or download all of the logs from raynes.me/logs/irc.freenode.net/clojure and grep them.

23:33 arohner: amalloy: I was thinking await did something it didn't, which is block on all agents (i.e. without listing them)

23:33 I'm writing some tests, and I'd like the test to block until all futures are finished, but I'd like to not explicitly list them

23:35 autodida: according to clojure, rhickey hasn't been seen since 08?

23:35 Raynes: $seen rhicky

23:35 lazybot: I have never seen rhicky.

23:35 Raynes: $seen rhickey

23:35 lazybot: rhickey was last seen joining on clojure 1 week and 6 days ago.

23:35 muhoo: wow, didn't know he used to be ini this channel.

23:35 Raynes: muhoo: He used to talk on this channel a lot.

23:35 muhoo: 2010, looks like

23:35 TimMc: He pops in with announcements every once in a while.

23:36 Raynes: Guys. 1 week, 6 days ago.

23:36 TimMc: Raynes: "joining"

23:36 Raynes: Yes, but he was here.

23:36 It's fair that he doesn't join very often though. With 400+ users every day, it can get a little hairy.

23:36 slyrus: but he went out

23:37 TimMc: I remember him coming in and asking naming advice for what ended up being called "realized?"

23:37 mk: there's actually a secret channel where all the oldhats talk about things

23:37 TimMc: I can see why he doesn't show up much.

23:37 muhoo: i'm sure there is a backchannel still.

23:37 technomancy: mk: it's called irc.thinkrelevance.com

23:37 muhoo: hehehe

23:40 well i'm sure linus doesn't hang around in #linux

23:41 nor guido in #python, etc etc

23:41 autodidakto: linus: my sounds card breaks the drivers, what's with that?

23:43 muhoo: he was, however, active on the lkml for a long time, may still be even, i dunno.

23:44 mk: many of the channels for more popular languages are pretty much tech support. Nobody stays around for long enough for there to be a productive community

23:45 autodidakto: mk: do the tech support conversations swamp the deeper ones? or?

23:46 muhoo: i've seen people in #debian and #emacs who've been there over a decade though.

23:46 brehaut: they are all weighed down by their beards. they literally could not leave, even if they wanted to

23:47 mk: it's encouraging to see new users (especially when they're using your clojure libs), but devs start to leave if there's too much noise

23:47 muhoo: brehaut: that is awesome. thank you for that.

23:49 autodidakto: beards stuck under those old school loud, big-key keyboards

23:49 10 years of tech support is enough to grey a beard, though

23:51 muhoo: autodidakto: http://www.flickr.com/photos/two_pi_r/264672521/

23:52 technomancy: nobody talks about Emacs in #emacs though, so that's different

23:52 it's mostly politics and bot abuse

23:53 autodidakto: muhoo: hehe yeah

23:53 brehaut: technomancy: emacs is now sufficiently intelligent that it can maintain political discourse and nobody notices?

23:53 im not sure if that says more for emacs, or political debate

23:54 technomancy: brehaut: M-x no-u

23:55 brehaut: i cant tell if thats a joke i havent got, or if an emacs package i havent got

23:56 technomancy: political "debate" these days consist mostly of "no, YOU're the one who is wrong!!!oneone"

23:56 so it's easy to automate, I guess?

23:56 brehaut: ah. lol

23:56 heh yeah

23:56 hidden markov model ?

23:56 or just random

23:56 technomancy: brehaut: oh man

23:56 brehaut: its not like either party is actually listening to each other

23:56 technomancy: just ask rudybot about pretty much anything

23:56 it's reminiscent of talk show radio

23:56 brehaut: lol

23:57 is that a #emacs bot?

23:57 technomancy: yeah, he picks a random unlikely word from your line and searches his logs for a line that matches

23:57 it's hilarious how often it almost makes sens

23:57 e

23:57 brehaut: haha

23:58 autodidakto: sounds like some kind of post-apocolyptic dystopia... uncaring robots have taken over.

23:59 brehaut: id rather the uncaring robots than any american political faction

23:59 autodidakto: talk show radio -> Rush Limbot

23:59 brehaut: the robots are at least logical

23:59 muhoo: politics for me is a particularly insidious form of bikeshedding

Logging service provided by n01se.net