#clojure log - Oct 28 2012

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

0:03 muhoo: use ALL the cores!

0:03 tomoj: I wonder what's a good way to deal with learning that two datomic entities actually represent the same entity. then later learning that that was an error

0:35 Sgeo: @mail `fogus If I buy your book from B&N, how do I get the ePub version?

0:35 What's the correct command?

0:45 xeqi: $mail Sgeo maybe this one?

0:45 lazybot: Message saved.

0:46 Sgeo: Thanks

0:46 $mail `fogus I bought your book on B&N. Is it possible, from that, to get the ePub version? (Preferably before the physical book arrives, because it might be a while due to hurricane)

0:46 lazybot: Message saved.

1:04 S11001001: Sgeo: if you mean joy, you need the code in the leaflet in the physical book

1:05 Sgeo: also, there's a major sale on manning.com for next few days; buy direct from them and it adds to your account right when you buy

1:07 Sgeo: S11001001, too late

1:07 S11001001: Sgeo: today and tomorrow dead trees (including ebook), tuesday ebooks, wednesday everything

1:07 Sgeo: lazybot, mail

1:07 S11001001: Sgeo: can't cancel an order on bn?

1:07 Sgeo: S11001001, I can, but why bother?

1:07 S11001001, also, easier for me to pay for stuff on B&N than elsewhere (long story)

1:08 S11001001: Sgeo: to be able to get the ebook right away

2:47 Sgeo: Does forcing a lazy sequence mutate stuff?

2:47 Suppose I have (def nums (range))

2:47 I do something like (doseq [i nums] (println i))

2:48 Hmm, bad example

2:48 (def nums (range some-really-large-number-such-that-holding-onto-the-entire-seq-at-once-will-run-out-of-memory-but-the-number-itself-isnt-that-big))

2:48 (doseq [i nums] (println i))

2:48 When everything is done printing, will I have run out of memory?

2:49 Or will nums be not forced?

2:52 tomoj: if nums isn't forced, what would print?

2:53 you will run out of memory

2:55 #'nums holds a reference to the head of the seq, so none of the seq can be garbage-collected

2:56 http://programming-puzzler.blogspot.com/2009/01/laziness-in-clojure-traps-workarounds.html

2:56 that is interesting in comparison to rx

2:56 reminiscent of hot vs cold observables

3:13 Sgeo: rx?

3:15 scottj: Sgeo: probably reactive extensions on .net

3:18 tomoj: and/or js

4:49 sheldonels: is there a way to recurse without naming a function? like, to just recall the function you're in at the moment

4:50 rodnaph: sheldonels: recur?

4:54 Sgeo: sheldonels, ##(doc loop)

4:54 Oh, you probably want recur

4:54 Ignore me

4:54 But the two go togethre

4:54 together

4:54 But you can recur without loop

4:54 Ok, I'm shutting up.

4:55 sheldonels: heh, no worries

4:55 been reading about recur since rodnaph mentioned it, the docs are above my functional grade I think

4:56 both the explanation on special forms and the examples are confusing, but I think I'll get it eventually

4:57 rodnaph: sheldonels: u don't have to think about special forms any differently than functions, it's just an implementation detail.

4:58 Sgeo: rodnaph, that... seems like that could cause some harm, saying that

4:59 sheldonels: ok, not sure I'll grasp this without some help, the docs say (recur exprs*)

4:59 Evaluates the exprs in order, then, in parallel, rebinds the bindings of the recursion point to the values of the exprs.

4:59 Sgeo: sheldonels, first: Do you know what tail-call recursion means?

4:59 sheldonels: is this like saying recur can mutate the things passed into the function above it?

4:59 not really

5:00 rodnaph: Sgeo: well, maybe "don't worry about it for now" is better advice.

5:00 sheldonels: I know clojure doesn't do it fully as a result of the jvm, and that other lisps do

5:00 Sgeo: rodnaph, that seems like it would be better for special forms v. macros

5:00 sheldonels: heh, I'm ok with that, if it's something for later, for now I should just name my functions for recursion purposes

5:00 rodnaph: yes, i almost said macros, but that would have probably just led to more questions, when it wasn't what was trying to be understood. but anyway...

5:01 Sgeo: Let's pretend for the moment that Clojure has it

5:01 And I want to define a factorial function

5:01 sheldonels: ok

5:01 Sgeo: (defn factorial [n] (* n (factorial (dec n))))

5:01 sheldonels: yep

5:01 Sgeo: (dec is a function that returns its argument - 1

5:02 When I call (factorial 5), it needs to do (* 5 (factorial 4))

5:02 sheldonels: like -- in imperative langs, yep

5:02 Sgeo: And that factorial 4 needs to do 4 * factorial 3

5:02 And so forth

5:02 sheldonels: gotcha

5:02 Sgeo: None of these can return until the one at the bottom returns

5:02 Oh, pretend that (factorial 0) returns 1, forgot to do that lol

5:02 sheldonels: yep, so it's kinda like a stack of function calls

5:02 Sgeo: Yes.

5:03 sheldonels: and the stack has to get bigger with each recursion

5:03 Sgeo: Yes.

5:03 sheldonels: until some limit

5:03 Sgeo: So, with a large enough n, my function will crash.

5:03 sheldonels: or your computer explodes :)

5:03 Sgeo: And will use a lot of memory even if it doesn't crash.

5:03 sheldonels: yep, the usual worry with recursion style programming

5:03 Sgeo: Now, let's define factorial differently:

5:04 (Pretending that Clojure has tail-call optimization, which it doesn't)

5:04 (defn factorial [acc n] (if (== n 0) acc (factorial (* acc n) (dec n))))

5:05 Let's look at what happens with (factorial 1 2)

5:06 It will call (factorial (* 1 2) (dec 2)), which is (factorial 2 1)

5:06 And the function will return that

5:06 But since the function is going to return that, if Clojure was smart, it doesn't need to keep track of where it's coming from

5:06 The stack of function calls doesn't need to grow

5:07 Does this make sense?

5:07 sheldonels: kinda, just mulling over the brackets a bit still

5:08 in your example, you're calling 1 2

5:08 why is 1 there as well

5:08 Sgeo: It's the accumulator, the trick I'm using in order to avoid needing to grow the function stack

5:09 When n is 0, I just return the accumulator, which will be the answer.

5:09 sheldonels: right, a way to sum up each step

5:09 Sgeo: Well, multiply up each step, but yes

5:10 sheldonels: and that's the key to avoiding needing to keep track of each step in a stack right, cause it's a passed along value

5:10 think I got it

5:10 Sgeo: :)

5:10 sheldonels: actually, still not sure how that form wouldn't have a stacked effect

5:11 it still needs to call over and over right

5:11 and wait for the 0 condition it unwind

5:11 Sgeo: It is getting called over and over, but since the result of the call is the result of the function, it doesn't need to bother storing where it's calling from

5:12 There's no multiplication that it still needs to do as it unwinds, so it doesn't need to bother with growing the stack

5:12 sheldonels: right

5:12 gotcha

5:12 Sgeo: Tail-call optimization refers to whether the language is smart enough to detect this. Clojure is not.

5:13 However, Clojure provides a form called recur, that you would use in place of that inside factorial call

5:13 (defn factorial [acc n] (if (== n 0) acc (recur (* acc n) (dec n))))

5:14 sheldonels: makes a whole lot more sense now, thanks

5:14 Sgeo: You're welcome

5:15 sheldonels: so using recur is a good idea whenever you can if I'm reading the docs right, as it's the only non stacked recursion available?

5:15 Sgeo: But note that you can ONLY use recur in places where it will be the return value of the enclosing ... function or loop form.

5:15 sheldonels, there's another form of non stacked recursion, but it's more annoying to use

5:15 sheldonels: heh, fair enough

5:16 I'm ok with skipping the annoying parts :)

5:16 Sgeo: Well, if you're interested, look up trampoline

5:16 It does things you can't do with recur

5:20 And with recur you should probably look at loop

5:20 sheldonels: will do

5:20 it's quite a tough thing at first, all this recursion. my first time learning a functional language. so used to imperative style stuff.

5:21 Sgeo: I should note that often you can avoid using recur, since there are easier ways to loop. recur is mainly for when you need explicit recursion, there are functions that are implemented using it but are easier to use than using recur directly.

5:21 sheldonels: in your 2nd example using recur, the named fn wouldn't necessarily need a name right? recur can just work out to rerun the function/loop it's in?

5:22 sure, I've been working through 4clojure.com to try learn

5:22 Sgeo: Right

5:22 sheldonels: I think they purposefully are sidestepping those easier ways to help the learning process

5:22 like some of the questions disallow certain functions that would make the answers trivial

5:23 I'm about to try do a function to count the things in a sequence, going to see if I can do it with recur now

5:23 Sgeo: Awesome

5:23 After you do that, see if you can find a way to do it without recur.

5:29 sheldonels: heh, no luck working it out, maybe without recur will be easier

5:30 rodnaph: does anyone know with aleph, if i can use a single (wrap-ring-handler) for all my compujure routes, or if it needs to be done once for each route. doesn't seem to work, but wanna see if that i'm doing *should* work befroe investigating further...

5:32 Sgeo: sheldonels, hmm.

5:32 sheldonels: yep, got it

5:32 hiredman: rodnaph: a single wrap-ring-handler should work, but it tends to eat exceptions, so you should wrap your routes in something that deals with them somehow (prints them out or whatever)

5:32 sheldonels: named functions I guess are easier for my tiny brain!

5:32 why is recursion so hard, stupid thing

5:32 heh

5:33 with recur, I'm getting a "Can only recur from tail position"

5:33 Sgeo: sheldonels, you can't try to "do stuff" like multiply the result of a recur

5:34 sheldonels: is that cause of similar to your first factorial example, I can't use this construct unless the value it returns doesn't get reused in the function it's called from?

5:34 Sgeo: It can only go back up to the enclosing function or loop

5:34 sheldonels: right

5:34 Sgeo: sheldonels, yes

5:35 sheldonels: is the factorial example doable with recur without an accumulator? I don't think so, just checking

5:35 Sgeo: I don't believe so

5:46 sheldonels: no luck with the recur version, I need an accumulator, but can't default it to 0 it seems

5:46 if I make it optional, then I get a really weird error

5:46 and default makes it mismatch the argument count

5:46 I guess recur can only do runtime matching arguments

5:48 anyone know why I would be getting this error? https://gist.github.com/3968185

5:50 rodnaph: looks like the destructuring is causing problems as you recurse maybe?

5:51 sheldonels: I'm not even seeing a long anywhere there, is it something internal as part of recur maybe?

5:51 rodnaph: or the (next l) actually. l is a long correct?

5:52 `(next [1 2 3])

5:52 sheldonels: a list

5:52 rodnaph: oops

5:52 sheldonels: the idea is to count the items in the list

5:52 using an accumulator so that I can recur

5:52 rodnaph: yah, but (next 1) doesn't make sense (and will give that error)

5:53 (next) needs to take a collection, not a single long

5:53 sheldonels: right, I thought (next '(1 2 3)) gives '(2 3)

5:53 rodnaph: yes it does

5:53 sheldonels: l is my list I think, unless I messed up the syntax somewhere

5:53 (next l) should be l minus 1 item

5:54 rodnaph: well, l is not a list in some call (that's what the error is saying)

5:54 sheldonels: right, I see

5:54 thanks :)

5:57 ah well, I give up, at least I got it working without recur

5:58 thanks for all the help rodnaph, Sgeo. cya around.

5:58 rodnaph: good luck!

6:10 andrewmcveigh: &(= (

6:10 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

6:10 andrewmcveigh: (fn c [l & [a]] (if l (recur (next l) (+ (if a a 0) 1)) 0))

6:10 '(1 2 3 3 1)) 5)

6:11 &((fn [l & a] (if l (recur (next l) (+ (if a a 0) 1)) a)) '(1 2 3 3 1))

6:11 lazybot: ⇒ 5

6:20 samrat: tab-completion isn't working with emacs-live + evil-mode. Any ideas on how to fix it?

7:02 rodnaph: trying to create a websocket server with aleph - can anyone help?

7:48 mklappstuhl: gfredericks, any advice regarding my question from yesterday?

7:50 I want to simulate a fictional stock portfolio and I'm wondering which data structures to use to create the portfolio...

7:50 I have some ideas here: https://github.com/mklappstuhl/computational-investing.clj/blob/master/src/mklappstuhl/stock_utils/simulate.clj

7:50 Any feedback would be greatly appreciated :

8:34 I want to simulate a fictional stock portfolio and I'm wondering which data structures to use to create the portfolio...

8:34 I have some ideas here: https://github.com/mklappstuhl/computational-investing.clj/blob/master/src/mklappstuhl/stock_utils/simulate.clj

8:34 Any feedback would be greatly appreciated :)

9:44 sheldonels: ((fn f [x] (if x (conj (rest x) (first x)) nil)) '(1 2 3 4)) trying to switch around rest and first to reverse the list, conj doesn't work with the first param being an item rather than a collection, anyone know of something I can use to get a new item added to a collection at the far end?

9:59 AimHere: sheldonels, you could just use the reverse function

10:02 Oh, he's gone

10:29 ambrosebs: If anyone was thinking of contributing to Typed Clojure, some small jobs https://github.com/frenchy64/typed-clojure/wiki/Small-Jobs

10:43 edmund__: ambrosebs: was reading your dissertation this am. Very nice work.

10:44 its a nice way for me to learn about this whole typing jiggery-poke

10:44 ambrosebs: edmund_: thanks!

10:44 ditto for me :)

10:45 Learnt a lot this year hehe

10:45 How are you finding it? Any confusing bits?

10:46 I didn't get a chance to run it by anyone but my supervisor...

10:46 I can still correct it before December.

10:47 edmund__: well, I'm not academically able in CS

10:47 but this is good as the new concepts you introduce are clear to me

10:48 i did have a question on listing 1.9

10:48 ambrosebs: The target audience is basically people familiar with popular programming languages.

10:48 edmund__: the (if a a 0)

10:49 ambrosebs: yep

10:49 just a regular if?

10:49 edmund__: should it be (if a a nil) perhaps

10:49 ambrosebs: look at the return type of num-vec2

10:49 tmciver: ambrosebs: where can one read this dissertation?

10:49 edmund__: the else branch returns a nil and you say that the type of the else branch collapses (U nil Number) to nil

10:50 whereas 0 is Number

10:50 I'm probably being dumb though :)

10:51 ambrosebs: ah it's a bit hard to read.

10:52 Similarly, following the else branch refines the type of -->"a"<-- to nil from (U nil Number)

10:52 edmund__: aaaaaaaah

10:52 yes

10:52 tmciver: ambrosebs: Ah, was looking for your disseration; found it.

10:52 edmund__: not the type of the function

10:52 quite right ;)

10:52 ambrosebs: tmciver: cool, corrections welcome!

10:53 edmund__: i'm confused about the ... type

10:53 ambrosebs: edmund__: I'll reword it.

10:53 edmund__: but that needs further work from me :)

10:53 ambrosebs: edmund__: where does it come up first?

10:53 Listing 1.8?

10:54 edmund__: pg 11

10:54 yeah 1.8

10:54 i just need to digest a bit what it meas

10:54 s/meas/means

10:54 ambrosebs: yea, it's tough to get your head around it at first.

10:54 edmund__: and how Type b ... b interacts with Type a

10:55 all new stuff to me

10:55 ambrosebs: I don't think there's anything notable about that interaction.

10:55 edmund__: what would be uber cool for the Conj is if you gave a handson session where we go through some examples of using TC

10:56 i imagine your talk will be more technically focussed

10:56 ambrosebs: the interesting bit is between b ... b and (U nil (Seqable b)) ... b

10:56 edmund__: yeah, let me think about that for a bit and get back to you with questions

10:56 but, this is really interesting work and something that I hope you continue with

10:56 you doing further studies ?

10:57 ambrosebs: I still haven't worked out exactly what I'm talking on. But my Conj proposal says I'm talking about practical features.

10:57 edmund__: aaah well, in that case :)

10:57 its always easier to reason from concrete to abstract

10:57 ambrosebs: I'm giving an Unsession talk on the theory.

10:58 which is the day after

10:58 edmund__: perfect: pretty exciting stuff.

10:59 ambrosebs: I know right! ;)

10:59 edmund__: i still have to get my talk into any sort of shape. EEEP

11:01 ambrosebs: I'm giving a 20m seminar on Thursday for my degree. Hopefully will kickstart the work (although writing a dissertation sure helps)

11:01 edmund__: good luck with that - you'll kill

11:01 ambrosebs: :)

11:04 user: test

11:06 edmund__: user: pass

11:06 user: :)

11:29 solussd: I've been playing around with Clojure-py the past couple of days. Any insight on why it appears to be about 20x slower than python?

11:31 goracio: hi ther here is the problem - i try (def thing (func)) func takes some time to do stuff and then i use thing and it appears unbound - how to handle this stuff ?

11:38 so any thoughts ?

11:38 solussd: goracio: could you upload the actual usecase to refheap?

11:40 goracio: solussd: well it's pretty simple - i want define thing and then use it but to defining thing takes some time so when i use it compiler says that it is ubound

11:41 solussd: goracio: it shouldn't be, so there must be something weird going on in your code. :)

11:41 goracio: solussd: so function took some time to execute and it appears that thing wasn't defined cause compiler doesn't wait

11:43 solussd: for example (def thing (func)) will compiler wait for results that func will return or may be will not ever

11:44 solussd: so, does this leave blah unbound? : (def blah (#(do (Thread/sleep 5) "hi")))

11:44 it will wait

11:45 goracio: hmm

11:45 tmciver: goracio: I had a problem like this when trying to def a var to a jetty server. But since the 'create server' function never really returns (the server is running), the server var was unbound. I think you simply can't use the var until the function returns. Perhaps you need a Future, or something.

11:47 goracio: tmciver: yes func is communicating with the db server and waits results from it but func is returning something for sure

12:58 erwagasore: I am using require instead of use in my namespace, something like this : (ns mynamespace (:require [ring.adapter.jetty :refer [run-jetty]]))

12:59 Is something like this possible: (ns mynamespace (:require [ring.util.response :refer :all :exclude [not-found]])

12:59 ?

13:09 or something like this: (ns mynamespace (:require [ring.util.response :refer :all [not-found :as nf]]))

14:22 TimMc: I think there might be a rename...

14:23 Maybe that's only with use.

14:32 devn: Anyone know where (raise) went in clojure.contrib.condition? Is there an analagous form in slingshot?

15:10 hyPiRion: TimMc: Yeah, there's rename

15:11 &(require '[clojure.pprint :refer [cl-format] :rename {cl-format fmt}])

15:11 lazybot: ⇒ nil

15:11 hyPiRion: &(fmt true "~{~A~^, ~}~%" [1 2 3])

15:11 lazybot: ⇒ 1, 2, 3 nil

15:25 hiredman: dnolen: does the clojurescript compiler (outside of google closure) do any constant propagation? I am seeing (def ^:export m 1) (defn f [] (g m)) turn 'm' in to the constant 1 in the generated js

15:25 which means I cannot fiddle the exported value m and get a different result

15:30 dnolen: hiredman: it does not, that would be gclosure

15:30 hiredman: I think you'll see that with even simple optimizations

15:32 tomoj: is there a problem doing `:where [$a _ :foo ?foo-a] [(foo ?foo-a) ?foo)] [$b _ :foo ?foo-b] [(foo ?foo-b) ?foo]` ?

15:34 hiredman: dnolen: that is kind of a drag

15:36 tomoj: shouldn't it be ^:dynamic ?

15:36 (and would that make a difference?)

15:40 gfredericks: tomoj: probably depends on if it makes a difference in the generated JS, rather than just compiler warnings

15:42 dnolen: hiredman: yeah it's annoying, perhaps it can be defeated w/ a JS object? (def ^:export props (jsobj "m" 1)) ?

15:47 hiredman: dnolen: I'll try that next time

15:50 gfredericks: if the jsobj idea didn't work that would say bad things about the correctness of atoms I would think

15:51 dnolen: hiredman: hmm there's probably a way for us to avoid ugly hacks like that if we expose more hooks to closure annotations http://developers.google.com/closure/compiler/docs/js-for-compiler

15:52 hiredman: ^:expose I think

15:55 hiredman: dnolen: maybe :export should just imply expose

15:57 dnolen: hiredman: that might be true, http://dev.clojure.org/jira/browse/CLJS-410

16:08 tomoj: seems joining on the output of a db fn like that is O(n^k)

17:20 mklappstuhl: I want to simulate a fictional stock portfolio and I'm wondering which data structures to use to create the portfolio...

17:20 I have some ideas here: https://github.com/mklappstuhl/computational-investing.clj/blob/master/src/mklappstuhl/stock_utils/simulate.clj

17:20 Any feedback would be greatly appreciated :)

17:21 basically I try to wrap "buy" functions in a list...

17:21 But I think there might be better tools in clojure to do it ..

17:26 technomancy: huh: https://twitter.com/atosborne/status/180246603586736128

17:30 etherealG: what's the difference between sequential and iseq?

17:30 amalloy: &(map (juxt sequential? seq?) '[[1 2 3] (1 2 3)])

17:30 lazybot: ⇒ ([true false] [true true])

17:31 amalloy: technomancy: isn't that just optimizing refer :all? i can see it speeding up the refer-clojure that happens in every namespace, but not much else. given that, why not just cache the mappings for clojure.core, and have it take roughly zero time for the case that's actually slow?

17:31 frio: &(sequential [1 2 3 4 4])

17:31 lazybot: java.lang.RuntimeException: Unable to resolve symbol: sequential in this context

17:31 frio: &(sequential? [1 2 3 4 4])

17:31 lazybot: ⇒ true

17:32 frio: hrm

17:33 bbloom: in short: sequential means it has a well defined order. It's a sequence if it's a head/tail cons-style data structure, and "seqable" implies that it can be coerced to a sequence via the seq function

17:33 vectors are sequential, but not sequences

17:33 lists are sequential and are actually sequences

17:33 technomancy: amalloy: yeah, probably makes more of a difference with :refer :all

17:34 amalloy: technomancy: no, i mean it looks to me like that code is only used at all for refer/all

17:34 etherealG: gotcha, so sequential? is the right thing to use for code that you want to be collection agnostic?

17:34 if you need to check the incoming data for being able to do things like filters etc.

17:35 amalloy: if you need to filter, just call filter and break if an exception happens

17:35 technomancy: you can filter over lots of nonsequentials

17:36 bbloom: etherealG: generally, you simply coerce to a sequence and test against nil

17:37 etherealG: er, sorry, misunderstood your question, yeah, you're right

17:37 Sgeo: ,(for [[k v] {:a 1 :b 2}] [v k])

17:37 clojurebot: ([1 :a] [2 :b])

17:38 bbloom: ,(seq {:a 1 :b 2})

17:38 clojurebot: ([:a 1] [:b 2])

17:38 bbloom: ,(sequential? {:a 1 :b 2})

17:38 clojurebot: false

17:38 bbloom: etherealG: see that ^^ maps aren't sequential, but they are seq-able

17:39 some canonical linearization of maps exists :-)

17:39 Sgeo: ,(seq {:a 1 :b 2})

17:39 clojurebot: ([:a 1] [:b 2])

17:39 Sgeo: hmm

17:40 ,(find [2 1 0] 0)

17:40 clojurebot: [0 2]

17:40 Sgeo: awesome

17:40 ,(class (find [2 1 0] 0))

17:40 clojurebot: clojure.lang.MapEntry

17:42 amalloy: &(-> (iterate #(find % 0) [0 0]) (nth 1000))

17:42 lazybot: ⇒ [0 0]

18:05 dnolen: bbloom: hrm, it seems like we still have some let cases to address? http://dev.clojure.org/jira/browse/CLJS-411

18:06 bbloom: dnolen: give me a moment & i'll take a look

18:08 neither of those throw an assertion error for me

18:09 dnolen: what's the problem exactly?

18:14 ForSpareParts: If I compile some Clojure AOT using gen-class, will I still be able to do REPL-state stuff with the compiled code? Say, accessing def'd stuff in the clojure code that Java is invoking?

18:16 And a related question: what's the best way to pull data out of a Clojure map (with flexible structure) in Java code? I'd rather not have a chain of type casts several lines long, but I'm also a little concerned that using the RT package would have performance implications

18:16 (I'm trying to make a simple game, and parsing/compiling on every line seems like a bad choice)

18:40 AtKaaZ: is there a git library for clojure?

18:40 if not, what would be the way to run a command and get back its output?

18:41 AdmiralBumbleBee: conch is good for that

18:41 no idea if there's a git library

18:42 AtKaaZ: thank you, I'll check that

18:43 tomoj: codeq just uses Runtime.exec :O

18:44 Apage43: https://github.com/clj-jgit/clj-jgit

18:45 AtKaaZ: hmm, I'm getting cannot resolve dependency conch/conch , maybe I'll try using Runtime.exec

18:45 tomoj: it's just conch

18:46 https://clojars.org/conch

18:46 amalloy: tomoj: conch is an alias for conch/conch; that's what lein does if you omit a groupid

18:46 AtKaaZ: yeah but that's what it says, probably resolves to that when namespace not specified

18:46 tomoj: orite

18:46 AtKaaZ: wait, do I need the clojars plugin?

18:47 or lein knows to look there

18:47 dnolen: bbloom: you're right, not a problem

18:47 bbloom: dnolen: good news! the unmanaged vars really do look nice huh? :-)

18:48 dnolen: bbloom: they do :)

18:48 amalloy: AtKaaZ: you could try jgit, though i don't know how easy it is to use

18:50 AtKaaZ: don't mind if I'll give it a try

19:00 amalloy: this seems useful: https://github.com/clj-jgit/clj-jgit

19:01 bbloom: dnolen: i might be doing something wrong, but i've got a relatively simple cljs-build setup going on and i'm getting a warning trying to use defprotocol

19:01 WARNING: Use of undeclared Var cps/-return at line 3 src/cps.cljs

19:01 where line 3 is the -return form here:

19:01 (defprotocol IContinuation

19:01 (-return [_ result])

19:01 (-raise [_ error]))

19:01 any ideas what might be causing that?

19:03 amalloy: bbloom: related to return being a javascript keyword?

19:03 bbloom: amalloy: i thought that might be it, but the - is converted to a _ also the next line gives a similar warning:

19:03 WARNING: Use of undeclared Var cps/-raise at line 3 src/cps.cljs

19:03 raise isn't a keyword

19:13 dnolen: bbloom: hmm I don't know.

19:14 bbloom: it's only supposed to issue that warning if it encounters a symbol that hasn't been declared or def'd

19:14 bbloom: dnolen: could it have something to do with a cli (non cljs) namespace of the same name?

19:15 dnolen: bbloom: oh hmm, it looks like you've aliased a namespace to cps and are using -return in a different namespace?

19:16 bbloom: if so it should have analyzed the other namespace first and picked up those protocol definitions

19:16 bbloom: dnolen: i have cps.clj and cps.cljs -- the former for compile time & macros, the later for runtime stuff

19:16 dnolen: bbloom: so is cps/-raise something emitted by the macro?

19:16 bbloom: dnolen: nope

19:17 dnolen: https://github.com/brandonbloom/cljs-cps/

19:18 dnolen: if you look at the bottom of cps.clj, you'll see all my compile time tests… i've started on test.cljs, which is going to be the runtime tests

19:18 dnolen: you'll also see how pretty an AST transform can be :-)

19:19 dnolen: bbloom: yes that looks pretty cool. dunno about the issue tho, minimal case would be helpful.

19:19 bbloom: I would look more closely myself but busy w/ some other things atm.

19:19 bbloom: ok, ill try to figure it out

19:19 i've got to run now

20:06 AtKaaZ: type hint for array of String?

20:07 I hope it's not this {:tag "[Ljava.lang.String;"}

20:13 Sgeo: ,(class (string-array))

20:13 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: string-array in this context, compiling:(NO_SOURCE_PATH:0)>

20:13 Sgeo: ,(class (object-array))

20:13 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core$object-array>

20:13 Sgeo: ,(class (object-array 0))

20:13 clojurebot: [Ljava.lang.Object;

20:13 Sgeo: ...what

20:13 I have no idea what's going on

20:29 dnolen: AtKaaZ: that is correct, ^"[Ljava.lang.String;"

20:29 AtKaaZ: yep thanks

20:31 wingy: the Java interop comes handy dealing with external services who only have Java SDK

20:32 how do i use maven projects in my project.clj?

20:40 amalloy: same way you use clojure projects, which are published via maven

20:41 akhudek: wingy: just add to the dependencies something like [group-id/artifact-id "version"]

20:41 if the group and artifact id are the same, like for many clojure projects, you can just use [artifact-id "version"]

20:46 wingy: akhudek: it says i have to add their repository at http://x.github.com/x/releases

20:46 dnolen: bbloom: ok, I bendlas found a legitimate issue http://dev.clojure.org/jira/browse/CLJS-411

20:47 akhudek: wingy: you can specify extra repositories in lein with :repositories (see https://github.com/technomancy/leiningen/blob/preview/sample.project.clj#L161)

20:49 wingy: akhudek: ok thx

20:58 bendlas: bbloom: hi I had wondered about your IRC handle

20:58 dnolen: yeah, sorry for the miscommunication

21:00 meredydd: Hey

21:01 Anyone around and interested in giving me feedback on a new function-call mocking library?

21:01 github.com/meredydd/expect-call

21:01 (Hmm, that's not clickable in XChat. http://github.com/meredydd/expect-call)

21:16 AtKaaZ: ,(assert false)

21:16 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.AssertionError: Assert failed: false>

21:17 AtKaaZ: does this work regardless of the -ea jvm option?

21:17 in other words, is it unlike the assert used in java?

21:18 I believe the answer is yes but still, I'd prefer this to be documented

21:23 amalloy: &(macroexpand-1 '(assert false))

21:23 lazybot: ⇒ (clojure.core/when-not false (throw (new java.lang.AssertionError (clojure.core/str "Assert failed: " (clojure.core/pr-str (quote false))))))

21:30 TimMc: The question is really whether Clojure assertions are enabled iff Java assertions are enabled at macro-expand time.

21:31 Sgeo: (source assert)

21:31 &(source assert)

21:31 lazybot: java.lang.RuntimeException: Unable to resolve symbol: source in this context

21:31 Sgeo: ,(source assert)

21:31 clojurebot: Source not found

21:31 TimMc: ,(apropos 'source)

21:31 clojurebot: (*source-path* source source-fn resource)

21:32 TimMc: ,(apropos 'assert) bah

21:32 clojurebot: (assert *assert*)

21:32 AtKaaZ: &*clojure-version*

21:32 lazybot: ⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}

21:32 gfredericks: TimMc: it's based on the *assert* var, ain't it?

21:32 AtKaaZ: &(use 'clojure.repl)

21:32 lazybot: ⇒ nil

21:33 AtKaaZ: &(source source)

21:33 lazybot: ⇒ Source not found nil

21:33 Sgeo: http://clojuredocs.org/clojure_core/clojure.core/assert

21:33 It only returns code when *assert* is truthy

21:34 gfredericks: (set! *assert* :falsy)

21:34 AtKaaZ: ,(binding [*assert* false] (assert false))

21:34 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.AssertionError: Assert failed: false>

21:34 gfredericks: AtKaaZ: it was truthy at compile-time

21:35 Sgeo: The binding occurs at runtime, but the macro is expanded at macroexpand time

21:35 AtKaaZ: makes sense

21:35 gfredericks: you can (binding [*assert* false] (eval '(assert false)))

21:35 Sgeo: ,(alter-var-root #'*assert* (constantly false)) (assert false)

21:35 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

21:36 AtKaaZ: ,(binding [*assert* false] (eval '(assert false)))

21:36 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

21:36 AtKaaZ: oh right, eval

21:36 gfredericks: what happens if you take a val and put it on computers?

21:37 AtKaaZ: the computer believes?

21:37 gfredericks: no, you get an e-val!

21:37 AtKaaZ: nice

21:48 callen: you know, I put up a pull request fixing that irritating SANBOX DENIED typo ages ago

21:50 AtKaaZ: in what way?

21:51 oh i see, typo :)

22:01 TimMc: callen: I've grown fond of it.

22:09 jimduey: Sgeo: Hi

22:12 Sgeo: Hi jimduey

22:13 jimduey: Saw your comment about m/do being a macro.

22:13 I was actually pleased that it was the only one I needed to be a macro. :)

22:13 And that's because it deals with binding values to symbols, which can only be done using a macro.

22:13 Sgeo: Actually, the thing with it is that its name is the same as the name of a special form

22:14 jimduey: Ah. That I understand.

22:14 Sgeo: Which means you can't actually use it in, you can only refer to it with a qualified name, either fully qualified or alias, like m/do

22:14 jimduey: Good point.

22:16 TimMc: OK, what's the point of this? https://github.com/clojure/clojure/blob/master/src/clj/clojure/main.clj#L85

22:16 jimduey: Not sure what else to call it, since 'do notation' is the term in Haskell.

22:16 Regardless, thanks for carrying the monad flag in Clojure land. :)

22:16 TimMc: (binding [foo foo] ...) seems like a no-op -- is there a point to creating a new dynamic scope level?

22:17 Sgeo: http://ideone.com/JQz5VF

22:17 jimduey, you're welcome

22:18 A way to get special forms to be namespaced like the rest of clojure.core would be nice

22:22 * gfredericks is surprised he's never thought of that

22:23 Sgeo: I really should work on fixing delimc

22:23 Although I think it might be harder than I originally thought

22:23 I forgot how I came to that conclusion though

22:26 tomoj: what's wrong with delimc?

22:27 Sgeo: tomoj, it doesn't work unless you use it, bringing all its symbols directly into the current namespace

22:27 Due to it being a port from CL -> Clojure, and the subtle difference between CL symbols and Clojure symbols+namespaces

22:28 There might be more issues due to that difference, I'm not sure

22:28 Erm, Clojure symbols+vars

22:28 tomoj: I see

22:31 jimduey: If you do :exclude some symbols from clojure.core, you can always get at them again by fully qualifying their names. clojure.core/do etc.

22:33 Sgeo: jimduey, the point is that :exclude on do flat out does not work.

22:33 An unqualified do always refers to the core do, under all circumstances.

22:34 jimduey: so it is. I'll just hang up my keyboard and go to bed now. :)

22:38 ivan: <Sgeo> An unqualified do always refers to the core do, under all circumstances. <- only in list head position, maybe obvious

22:38 Sgeo: Oh, erm, yes

22:38 * Sgeo feels like a derp

22:38 Sgeo: ,(let [do 5] (do do))

22:38 clojurebot: 5

22:38 gfredericks: is (do do) ever not funny??

22:38 lazybot: gfredericks: What are you, crazy? Of course not!

22:38 Sgeo: ,(let [+ 5] (+ +))

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

22:40 gfredericks: ,(let [+ partial] (+ + + + + + + +))

22:40 clojurebot: #<core$partial$fn__2495 clojure.core$partial$fn__2495@39ff48d8>

22:43 callen: TimMc: ugh.

22:48 muhoo: wait, how is that even possible

22:48 ,(5 5)

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

22:48 muhoo: right.

22:48 ,(let [do 5] (do do))

22:48 clojurebot: 5

22:48 muhoo: ????

22:51 Sgeo: muhoo, do is a special symbol

22:51 Unqualified, it always refers to the same thing in head form

22:52 So, the (do do) is the special form do with lexically scoped variable do

22:52 ,(special-symbol? 'do)

22:52 &(special-symbol? 'do)

22:52 lazybot: ⇒ true

22:54 Sgeo: ,(let [-> 5] (-> ->))

22:54 &(let [-> 5] (-> ->))

22:54 lazybot: ⇒ 5

22:55 Sgeo: o.O what

22:56 &(let [-> inc] (-> 5))

22:56 lazybot: ⇒ 5

22:56 Sgeo: &(special-symbol? '->)

22:56 lazybot: ⇒ false

22:57 metellus: ,(let [+ -] (+ 5 3))

22:57 Sgeo: &(let [+ -] (+ 5 3))

22:57 lazybot: ⇒ 2

22:57 metellus: &(let [inc 5] (inc inc))

22:57 lazybot: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn

22:58 xeqi: &(let [-> 5] ->)

22:58 lazybot: ⇒ 5

23:00 Sgeo: Going to try it at the REPL, maybe clojail's weird?

23:01 user=> (let [-> inc] (-> 5))

23:01 6

23:02 (do do) still does its thing, though

23:03 &*clojure-version*

23:03 lazybot: ⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}

23:03 Sgeo: Raynes, hello

23:03 gfredericks: lazybot: quit being weird

23:04 Sgeo: It's probably Clojail

23:05 Why is clojurebot broken?

23:05 ,5

23:05 xeqi: ,asdf

23:06 ,(5 5)

23:06 hmm, muhoo got it to work earlier :p

23:09 gfredericks: &(let [-> 8] ->)

23:09 lazybot: ⇒ 8

23:10 gfredericks: &(let [-> :foo] (-> {}))

23:10 lazybot: ⇒ {}

23:10 gfredericks: in clojail, all clojure macros are special forms :)

23:11 Sgeo: Yes. As far as I'm concerned, this is a bug.

23:13 AtKaaZ: what's the safest way to make sure a bunch of statements get executed?

23:16 Sgeo: hm?

23:16 clojurebot: benchmarking is https://github.com/hugoduncan/criterium

23:17 AtKaaZ: I guess dorun will do...

23:21 Sgeo: AtKaaZ, what do you mean by "a bunch of statements"?

23:22 AtKaaZ: forms

23:22 with side effects

23:23 Sgeo: You don't need to wrap them in anything unless you're doing them in a for otherwise involving laziness

23:23 AtKaaZ: they are in a true branch of an if

23:23 Sgeo: Ah

23:23 AtKaaZ: but I used dorun

23:23 Sgeo: You probably want do

23:24 if takes three things: A test, ONE form for the true branch, and optionally, ONE form for the false branch

23:24 AtKaaZ: just that I was wondering if somehow it would trigger the dorun [n coll] instead of dorun [coll]

23:24 Sgeo: do will let you combine multiple forms into 1 form

23:25 (if true (do (println "Hello") (println "There")) (println "This is in the else"))

23:25 dorun is specifically for realizing lazy collections

23:26 AtKaaZ: what would be the difference between do and dorun there? assuming the first println is something like (.delete fFile)

23:26 for some reason I was unsure that do will cause the side effects to happen, but it kind of makes sense, since the forms are evaluated before being passed to the do (so to speak)

23:28 Sgeo: dorun is not intended to group multiple forms together. It is intended to fully realize a lazy sequence and induce any side-effects in that sequence by doing so

23:28 Why do you think that the side effects might not happen

23:31 AtKaaZ: I just cannot imagine all possible variants and therefore I chose to be unsure :) but if do was a macro then I'd be unsure, I guess since it's a function the passed forms are all evaluated prior to executing the do

23:31 which returns last

23:31 tomoj: it's not a function

23:31 AtKaaZ: special form?

23:31 tomoj: it's a special form

23:31 AtKaaZ: ok

23:31 so in theory it can act like a macro then?

23:32 Sgeo: Yes.

23:32 But macros can evaluate the forms they're given if they choose

23:32 But the do special form always evaluates its forms, assuming that the do itself is evaluated

23:33 AtKaaZ: alright

23:34 ,(= (ifn? 'do) (special-symbol? 'do))

23:34 clojurebot: true

23:35 zackzackzack: What does the syntax ::foo mean?

23:36 Raynes: &::foo

23:36 lazybot: ⇒ :clojure.core/foo

23:36 AtKaaZ: ,:foo

23:36 clojurebot: :foo

23:37 AtKaaZ: ,::foo

23:37 clojurebot: :sandbox/foo

23:37 zackzackzack: So a namespaced keyword of sorts?

23:39 AtKaaZ: prefixing it with the current namespace

23:39 ,*ns*

23:39 clojurebot: #<Namespace sandbox>

23:39 zackzackzack: Ahhh

23:39 That makes sense

23:42 Sgeo: Oh hey clojurebot's back

23:42 ,(let [-> inc] (-> 5))

23:42 clojurebot: 6

23:43 Sgeo: I don't think I'm going to forget which one uses Clojail now

23:50 flying_rhino: hello guys

23:51 zackzackzack: flying_rhino, hi

23:53 Raynes: Sgeo: Yeah, I noticed that a while back. Haven't had time to investigate.

23:53 flying_rhino: how 'scriptable' (for lack of a better word) is clojure? For example, I wonder if I can load clojure code as a replacement for XML. I also wonder if I can have REPL inside application, so I can try things out without recompliling.

23:54 Raynes: flying_rhino: You can absolutely have an embedded repl.

23:54 You can even run an nrepl server in there and attach/detach from it as you please.

23:54 zackzackzack: ,(println "Say hello clojurebot")

23:54 clojurebot: Say hello clojurebot

23:54 Raynes: There is actually a thing, drawbridge I think, for talking to nrepl servers deployed in web apps.

23:55 zackzackzack: flying_rhino, this irc room has an embedded repl named clojurebot

23:55 Raynes: Also lazybot

23:55 &(+ 3 3)

23:55 lazybot: ⇒ 6

23:57 flying_rhino: can I keep that repl sandoxed so if it crashes it doesn't crash my whole app?

23:57 some sort of task manager thing where I can kill threads that get stuck?

23:58 zackzackzack: Raynes, clojail would work for that, right?

23:58 https://github.com/flatland/clojail

23:58 Raynes: I don't think that's the kind of sandboxing he wants.

23:58 zackzackzack: Yeah, you've written it be pretty strong

Logging service provided by n01se.net