#clojure log - Aug 30 2012

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

0:04 XPherior: Ah I'm an idiot. Trying to dispatch with (type) was dumb

0:04 mattmoss: ,(let [t java.util.Timer] (new t))

0:04 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: t, compiling:(NO_SOURCE_PATH:0)>

0:04 mattmoss: Is there a way to do that?

0:05 cshell: cshell?

0:05 clojurebot: I don't know anything about cshell.

0:06 jeremyheiler: ,(let [o Object] (.newInstance o))

0:06 clojurebot: #<Object java.lang.Object@b27d661>

0:07 mattmoss: ah

0:07 thanks jeremy

0:07 jeremyheiler: np

0:11 amalloy: mattmoss, jeremyheiler: that's really just going to lead to unpleasant surprises in a minute. newInstance only works for a zero-arg constructor

0:13 jeremyheiler: amalloy: yeah yeah...

0:13 mattmoss: amalloy: Yeah, noticed that... amongst other things. I was really hoping that there was some way to take the info from clojure.reflect and act upon it. Maybe there is, I haven't found info yet. Or maybe I just need to write it myself.

0:13 jeremyheiler: im curious what (new ..) actually does

0:16 i mean, there's only to options, right? either it generates the proper bytecode, or it reflectively grabs the constructor and instantiates it.

0:18 yep, it does the latter.

0:19 mattmoss: Where are you seeing that?

0:19 jeremyheiler: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L2365

0:19 djanatyn: clojure just helped me on my stats homework packet :)

0:19 jeremyheiler: nice!

0:20 djanatyn: I had to get a random sample of answers for a question

0:20 (defn rand-bool [] (case (int (rand int)) 0 true 1 false))

0:20 mattmoss: Gotcha. Now I know where more things are located in clojure source! :)

0:21 djanatyn: (repeatedly 60 rand-bool) ;; my results ;)

0:21 jeremyheiler: mattmoss: haha yeah, it's a bit difficult sometimes

0:21 djanatyn: I'm taking AP Stats this year, so I'm going to use clojure whenever I can

0:22 I used haskell pretty frequently in my calculus class last year to make things easier

0:22 hiredman: jeremyheiler: it does either, depending on if the proper types are known, and if the compiler is generateing bytecode or just evaling simple expressions at the repl

0:23 more complex expressions are always compiled

0:23 but if the type not determinable at compile time the emitted bytecode will use reflection

0:29 jeremyheiler: hiredman: looking at it more closely, i see what you're saying. good stuff.

0:34 casion: anyone know of an example of handling and processing soundfiles in clojure (that's not overtone)?

0:34 I've asked before and I either lost the links or no one had any at the time

0:34 brehaut: ~anyone

0:35 clojurebot: you are dead to me

0:35 clojurebot: Excuse me?

0:35 dansalmo: anyone know the regex for clojure.string/split to split a string at "<" but not at "<:"

0:35 casion: my google-fu has failed me in this regard

0:35 hiredman: ~anyone

0:35 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

0:35 cshell: lol

0:35 dansalmo: thx

0:36 what is the regex for clojure.string/split to split a string at "<" but not at "<:"

0:36 casion: I actually just want to know if anyone knows of an example haha

0:37 brehaut: negation is a bag of hurt in regexp, but something like #"<[^:]"

0:38 #"<([^:]|$)" perhaps

0:38 hiredman: ls

0:38 lazybot: bin boot dev etc lib lost+found selinux usr

0:38 brehaut: lol

0:38 mattmoss: cd etc

0:40 amalloy: brehaut, dansalmo: #"<(?!:)"

0:40 dansalmo: Thx brehaut, the 2nd one seems to work. The first one did catch < at the end of the string.

0:40 casion: ~regex

0:40 clojurebot: Sometimes people have a problem, and decide to solve it with regular expressions. Now they have two problems.

0:40 brehaut: amalloy: huh. good to know

0:41 amalloy: brehaut: yours consumes the character after the <, whereas mine doesn't

0:42 dansalmo: amalloy: that works even better, does not take out character after <:

0:42 brehaut: amalloy: yeah, i realised that, but without knowing about magic negation operators, its not really possible

0:43 amalloy: yeah

0:43 pyrtsa: It's called a (negative) look-ahead btw.

0:43 No magic. :)

0:43 amalloy: well, it's magic like negative look-ahead and capture groups that make regex impls hundreds of times slower than they could be

0:44 brehaut: and also makes them irregular in many cases

0:44 dansalmo: I see that now in the docs, never would have guessed I needed X, via zero-width negative lookahead

0:45 pyrtsa: I thought that were look-behinds that are problematic, but I agree.

0:46 aaelony: I seem to misunderstand swap! for an atom holding a map. (def x (atom {:a {} :b [] })) and (update-in @x [:a :a1] {} 123) give what I want, but (swap! x (update-in @x [:a :a1] {} 123)) yields nil ?!! perplexed… https://www.refheap.com/paste/4728

0:48 mattmoss: ,(let [x (atom {:a {} :b []})] (swap! x update-in [:a :a1] {} 123))

0:48 clojurebot: {:a {:a1 123}, :b []}

0:49 aaelony: thanks! so no paren before update-in...

0:49 mattmoss: swap! doesn't take the new value... but a function

0:49 aaelony: a-ha!! thanks again :)

0:49 mattmoss: and swap! will call that function with (deref x) as the first param and the other args to swap! as additional params

0:51 aaelony: cool

0:53 l1x: o hai

0:54 what is a good pattern to return a sequence (exact type doesnt matter) from a fn which has loop or recurn inside (eg. you are iterating over certain things and producing partial results)

0:57 emezeske_: l1x: The first example on this page is pretty typical: http://clojuredocs.org/clojure_core/clojure.core/loop

0:57 l1x: When you call recur, pass in the partial results, and keep appending to that

0:57 l1x: Once the termination condition is reached, just return that result

0:58 l1x: thanks, i try to implement it

1:09 i guess i cant use recur without loop this way

1:10 emezeske_: l1x: What are you trying to do?

1:10 l1x: rewrite this to return you a []

1:10 https://gist.github.com/3506753

1:13 emezeske_: l1x: So it's working how you want it, but is returning a seq instead of a vector?

1:13 l1x: it is printing now

1:14 i just would like to return a sequence instead, type does not matter

1:14 emezeske_: Oh I see

1:15 l1x: https://gist.github.com/a905f1fd2e2b6965accc

1:15 more like https://gist.github.com/3522630

1:16 but it just return an empty []

1:18 emezeske_: I think it's possible to do what you want with recur

1:19 I'm finishing something up right now, but in a minute I'll take a stab at helping

1:21 l1x: thanks a million

1:31 emezeske_: l1x: Okay, let's see.

1:33 l1x: Does this do the job? https://gist.github.com/3522797

1:34 l1x: I removed the ->> macro just for my own benefit (I found it easier to write without it).

1:34 l1x: haha i did the same :D

1:34 emezeske_: l1x: The main thing is that instead of using "when", it uses "if"

1:34 l1x: i dont get the ->> yet

1:35 emezeske_: So basically, my solution just keeps concating the row onto a result, which is initially set to []

1:35 l1x: ok so this was the missing point for me

1:35 emezeske_: Then, when (seq rows) is not truthy, it returns that whole concated result

1:35 l1x: that you have mutable data in clojure and you can just concat into it

1:35 emezeske_: It's not mutable :)

1:36 That's the great thing, concat is returning a totally new list of values

1:36 Notice that the new list returned by concat is passed into recur

1:36 So it is being passed into the function as the "result" argument

1:37 On each recursive call to spiral-print, result gets longer and longer

1:38 l1x: hmm

1:38 emezeske_: But it's not actually being mutated, it's a whole new list each time

1:38 Consider (let [x [1 2 3]] [(concat x [4]) (concat x [5])])

1:38 l1x: och i see

1:38 emezeske_: ,(let [x [1 2 3]] [(concat x [4]) (concat x [5])])

1:38 clojurebot: [(1 2 3 4) (1 2 3 5)]

1:39 emezeske_: ^ Notice that the second result is *not* (1 2 3 4 5)

1:39 ,(let [x [1 2 3]] [(concat x [4]) (concat x [5]) x])

1:39 clojurebot: [(1 2 3 4) (1 2 3 5) [1 2 3]]

1:43 l1x: thank you very much emezeske_

1:45 Urthwhyte: Evening

1:47 amalloy: emezeske_: you want into, not concat

1:47 emezeske_: amalloy: For what?

1:47 amalloy: https://gist.github.com/3522797

1:48 emezeske_: concat works fine

1:48 Does into have an advantage?

1:48 amalloy: concat will fail here if the matrix is too large

1:48 you're building up (concat (concat (concat ...)))

1:49 emezeske_: I guess I need to look at the source for concat and into to understand

1:50 Scriptor`: is the advantage here due to into using transients?

1:50 emezeske_: Wow, concat is way more complicated than into

1:51 amalloy: Are there situations where concat is better?

1:52 Scriptor`: emezeske_: concat is lazy, for one thing

1:53 emezeske_: I see. into is probably much much faster, being implemented in terms of reduce?

1:54 Scriptor`: emezeske_: there's also the fact that it uses transients, which means it does some mutating underneath

1:54 * emezeske_ doesn't know too much about transients.

1:55 emezeske_: Ahh, I see what amalloy is talking about with (concat (concat (concat))) -- it's a big deeply nested lazy-seq

1:56 Scriptor`: ,(let [foo []] (conj! foo 1) foo)

1:56 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.ITransientCollection>

1:56 Scriptor`: ,(let [foo (transient [])] (conj! foo 1) foo)

1:56 clojurebot: #<TransientVector clojure.lang.PersistentVector$TransientVector@6da6d943>

1:56 emezeske_: Whereas into will keep returning a longer flat list

1:56 Scriptor`: ,(let [foo (transient [])] (conj! foo 1) (persistent! foo))

1:56 clojurebot: [1]

1:56 Scriptor`: there we go

1:57 emezeske_: Oh, wild

1:57 Scriptor`: yep, it actually mutates the collection being conj'd onto, which normal conj doesn't

1:57 most of the time you'll never use this

1:57 emezeske_: I thought you had to just drop into dealing with arrays directly to do that

1:57 Very cool

1:58 Scriptor`: however, in very few cases you'll never need all the intermediary collections that might be built up by doing (reduce conj foo bar)

1:59 l1x: emezeske_: https://gist.github.com/3522630

1:59 emezeske_: Yeah, I could see that being a nice way to optimize a slow inner loop

1:59 l1x: i put there some dbg stuff

1:59 emezeske_: l1x: Nice.

1:59 Scriptor`: yep, clojure.org has a much better explanation than I can give http://clojure.org/Transients

1:59 emezeske_: Scriptor`, amalloy: thanks for the info.

1:59 l1x: the results are in the comment section

2:00 so, result is kinda growing with the iterations

2:00 but it seems to me like mutable variable...

2:01 emezeske_: ,(let [x [1 2 3]] [(into x [4]) (into x [5]) x])

2:01 clojurebot: [[1 2 3 4] [1 2 3 5] [1 2 3]]

2:01 emezeske_: Examine that ^

2:01 Notice that x is "intoed" a couple times, but its value stays the same

2:02 Scriptor`: yep, that's the idea, you won't ever notice the mutability, because it's wrapped up inside into

2:02 l1x: och i see

2:02 Scriptor`: so into doesn't mutate anything you pass it, it only mutates the collections it generates inside itself to get the final (immutable) result

2:02 l1x: so it does some magic inside into?

2:03 i guess it dereferences the original set and creates a new one

2:05 https://github.com/clojure/clojure/blob/d0c380d9809fd242bec688c7134e900f0bbedcac/src/clj/clojure/core.clj#L6070

2:05 ok guys, thanks everyone, great success

2:07 amalloy: Scriptor`: using conj! for side effects is a disaster - never do it; always use the result produced by conj!, even though it's generally the same collection you passed in

2:07 conj! and disj! are *allowed* to mutate the collection and return it, but they are not *required* to, and in fact don't

2:07 (or rather, don't always)

2:08 Scriptor`: amalloy: right, just demonstrating how it worked by mutating transient values

2:09 emezeske_: amalloy: Is deeply nesting lazy-seqs a bad idea in the general case?

2:10 amalloy: Now that I'm thinking about it, it doesn't seem like it's ever really what you want to do

2:10 amalloy: well, it causes a stackoverflowerror, so that sounds like a bad idea

2:10 emezeske_: For some value of "deeply" yes

2:11 I'm just trying to come up with a rule of thumb about when not to nest lazy-seqs

2:11 I guess the rule is "if you want a thing to be able to grow aritrarily long/big/deep"

2:11 amalloy: anytime you can't guarantee an upper bound on the depth seems reasonable

2:12 emezeske_: Yeah, that sounds good

2:12 I guess recur implies unbounded depth.

2:12 (Kind dumb to use recur and then still overflow the stack)

2:17 john2x: what would be the clojure equivalent of this: `String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", Calendar.getInstance())`? I'm trying (String/format "…" (Calendar/getInstance)) but it returns "java.util.GregorianCalendar cannot be cast to [Ljava.lang.Object"

2:29 hmm my bad.. it seems Processing has it's own String class..

3:09 lpetit: Hello there

3:10 On the Getting Started page for Counterclockwise, there is an old section related to how to install labrepl. But labrepl seems a little bit outdated, and so it is a shame that people are not exposed to more recent versions of clojure, libraries, etc.

3:11 My intent is to just drop this section, cutting the Getting Started page by a half (making it less frightening, btw).

3:11 Objections ?

3:13 Raynes: lpetit: I don't use CCW, but it sounds like a good plan. I'll note however that someone recently forked labrepl and added tryclojure integration to it.

3:13 Not sure if that's worth looking at or not.

3:13 But it's a consideration.

3:15 lpetit: Raynes: interesting. I think I'll still just drop it for now. I can always revive it by finding the text in the wiki history, right?

3:15 clgv: damn. too late to hear the "good plan"...

3:15 Raynes: Indeed.

3:15 clgv: lpetit, Raynes: good morning

3:16 lpetit: clgv: hello

3:17 clgv: I just added a (dissoc project-map :hooks) code when Counterclockwise interacts with leiningen so that the bug you mentioned the other week goes away.

3:17 clgv: lpetit: ah good. as a temporary fix until there is time to implement support for more leiningen features, right?

3:18 lpetit: with leiningen2-preview10 I could fix it via moving the :hooks to a profile, since technomancy fixed it the same day, I reported it <3

3:19 lpetit: clgv: the problem is that I wanted quick user feedback (for the class path) when the user changes project.clj. Thus Ive made ccw keep leiningen project maps live and in the same process as eclipse. For other Leiningen features, though, I intend to just launch separate jvms every time the users triggers a command

3:20 clgv: lpetit: thats probably a good idea

3:20 lpetit: clgv: would be interesting to see if that solves the problem and if I can then remove the hack. Please ping me when you've tested it ok (or not)

3:21 clgv: lpetit: can do

3:21 lpetit: kewl

3:22 clgv: lpetit: is thursday your regular CCW-Day? ;)

3:24 lpetit: clgv: yep

3:24 clgv: lpetit: I had not much backup data for that guess. only 2 data points ;)

3:25 lpetit: clgv: I also wrote about it publicly here & there

3:26 clgv: lpetit: ah ok. didnt read that yet ^^

3:27 lpetit: clgv: working on CCW each thursday (except during holidays ;) ) all year 2012, thanks to Relevance sponsoring me.

3:27 clgv: lpetit: I read about the sponsoring, though. that's really great. I think users of CCW noticed that regular day^^

3:28 lpetit: clgv: I hope so :)

3:28 clgv: did you find time to test the beta ?

3:28 ejackson: bonjourLaurent

3:29 clgv: lpetit: not yet. I was always too tired in the evenings :/

3:29 lpetit: the project of another laurent keept me busy ^^

3:29 lpetit: ejackson: Hallo Freunde

3:30 clgv: ?

3:30 clgv: lpetit: I am using JPPF (jppf.org) for task computation distribution for my clojure algorithms

3:31 lpetit: the main (or even sole) maintainer is also a laurent it seems^^

3:31 lpetit: ha :)

3:41 n00b6502: q1 does clojure have LLVM backend q2 how much do clojure and commonlisp diverge

3:43 clgv: n00b6502: afaik currently, there is no LLVM backend - although some were discussing that idea on the mailing list

3:44 n00b6502: q3 clojure/android .. anyone done it ?

3:46 clgv: n00b6502: there is a google summer of code project dedicated to clojure on android

3:56 lpetit: btw. does the leiningen classpath container work together with project references?

3:56 lpetit: clgv: not yet

3:56 you mean, if it finds the dependency in the workspace, then it should use it instead?

3:57 clgv: lpetit: yes. similar to leiningen's "checkouts" feature but on eclipse level

3:57 lpetit: without leiningen classpath container the project references worked ^^

3:57 lpetit: clgv: this is a feature I want to add. Chas has been asking for it for a long time. Just need more thursdays :)

3:58 clgv: lpetit: ok I rename wednesday to "almost thursday" for you ;) :P

3:58 lpetit: clgv: I was not sure about the semantics, also.

3:58 clgv: ok, let's talk offline about the billing "detail" :)

3:58 clgv: lpetit: hm yeah I know that problem^^

4:00 lpetit: clgv: semantics = how should we "match" a project in the workspace with a dependency ? Should we bring in the version number in the match? Or just match groupId/artifactId ?

4:02 clgv: lpetit: well, we got the project referenced (as usual in eclipse), so we have the project.clj. I would "match" on groupId/artifactId only. since you explicitly decided to set the project as reference

4:04 lpetit: clgv: Oh, I was thinking about something more "magic", more like was m2e does for maven : the class path container for leiningen dependencies can declare projects (not just jars), so I intended to do this referencing automatically (maybe a global flag preventing this feature, also)

4:04 clgv: lpetit: but it's hard to tell if that has annoying consequences in every day development in other scenario then the one I have currently

4:05 lpetit: clgv: what about my last suggestn?

4:05 clgv: lpetit: oh, I haven't thought that far. could that magic not be build upon the classic scenario I just described?

4:06 lpetit: you mean, just have leiningen class path container drop dependencies for projects that are explicitly added by the user in the projects tab ?

4:06 clgv: lpetit: if there is a switch for the "magic part" then you can turn it off at debugging times when you do not trust it

4:07 lpetit: yeah that would work.

4:07 lpetit: clgv: I guess both approaches aren't exclusive, really. Not sure if we need both, though

4:07 clgv: lpetit: another idea is that you do the "magic way" but have a dialog to override decisions of it

4:09 lpetit: That's possible, there's a way to "customize" class path containers in a per-project way. But the results of the customization will live in the .classpath file (that's what the "class path container" framework does), so it'll be probably shared among developers if checked in the scm

4:09 Apage43: so, assuming I'm going to be blogging with some snippets of Clojure littered about, what doesn't suck terribly for highlighting it?

4:10 clgv: Apage43: you could integrate github pastes if you have an account there

4:10 Apage43: that might be what I wind up doing

4:11 I wish I could avoid HTML surgery to get the final post though :/

4:12 clgv: lpetit: humm, having this decision in scm is probably not that optimal.

4:12 lpetit: clgv: that's why I mentioned it

4:13 clgv: lpetit: is it possible to have the overriding settings int the ".settings" folder?

4:14 lpetit: clgv: by not using the default mechanism, probably

4:14 clgv: lpetit: hm you would violate the regular semantic to classpath containers then, right?

4:15 lpetit: maybe not. But he, we're not there yet, so maybe we should postpone digging deeper for another time

4:17 clgv: lpetit: right. I just have to decide for myself whether my main project should move to leiningen support without project references

4:18 lpetit: clgv: it's a shame that the ability to disable a dependency from the dependencies automatically listed by a class path container is not just an out of the box feature of Eclipse :-(

4:19 clgv: lpetit: maybe thats no requirement for java/eclipse projects..

4:19 lpetit: yep

4:20 clgv: oh, I can see that leiningen2 has changed quite a lot with the recent releases. I guess I will stop for a while doing bug corrections for ccw support until it has stabilized more (your patch will be included in next beta, tho)

4:21 clgv: lpetit: what lein2 preview did CCW 0.9.0 base on?

4:22 lpetit: clgv: preview 6 I guess

5:06 naeg: is there someting like a while with bindings? want to create a game loop which repeatedly asks for user input and changes a board according to that input

5:09 oh yeah, loop :)

6:01 how can I force the output of a single print?

6:14 ejackson: naeg, do ?

6:16 naeg: ejackson: didn't work, but (flush) did

6:17 also, one more small thing before my connect four is finished - what's the best way to read in a single integer from the user?

6:17 currently doing it like this: (dec (read-string (str (first (read-line)))))

6:18 (dec because if user choses column 1 it's vector 0)

6:18 lazybot: ⇒ -1

6:20 ejackson: naeg: didn't know that one, thanks.

6:24 raek: naeg: you can use read

6:25 clgv: (dec because if user choses column 1 it's vector 0)

6:25 lazybot: ⇒ -2

6:26 clgv: lol haha. karma ^^

6:26 naeg: raek: I guess I can skip over just using the first number - user input is error prone anyway

6:29 clgv: what's that about anyway?

6:29 nbeloglazov: clgv, don't be mean

6:29 (inc because if user choses column 1 it's vector 0)

6:29 lazybot: ⇒ -1

6:31 clgv: lol

6:31 $karma because if user choses column 1 it's vector 0

6:31 lazybot: because has karma 0.

6:31 clgv: $karma "because if user choses column 1 it's vector 0"

6:31 lazybot: "because has karma 0.

6:31 clgv: (karma because if user choses column 1 it's vector 0)

6:31 nbeloglazov: :)

6:31 clgv: hmm seems not very consistent

6:36 Raynes: naeg: Are you reading raw user input?

6:36 naeg: Make sure you do (binding [*read-eval* false] (code that does the reading here)) if so, otherwise users will be able to execute arbitrary code in your application.

6:38 naeg: Raynes: I actually just wanted to write a little game loop for experimenting my checking algorithm for connect four

6:39 what do you think about my connect four checking algorithm? https://gist.github.com/3520562

6:39 (farely new to clojure)

6:42 hyPiRion: naeg: First thing I notice is that you have empty-board as a function. It could just be a def, couldn't it?

6:43 naeg: hyPiRion: I actually planed to make it more flexible about the board dimensions, but didn't do so yet

6:43 hyPiRion: ah, figures.

6:48 (not= (get-in ... a) ... ) could be replaced as (apply not= (map #(get-in board %) [a b c d]))

6:48 at line 59

6:48 naeg: hyPiRion: very nice, thanks

6:48 hyPiRion: and from there on, you see that you could just remove the destructuring

6:49 naeg: hyPiRion: wouldn't that result in nested #()?

6:50 hyPiRion: ah, I meant that (fn [[a b c d]] ... ) could be replaced by (fn [coll] ...) instead

6:50 naeg: oh, yeah

6:52 looks a lot better with apply now

6:56 hyPiRion: Oh and yeah

6:56 ,(= (apply concat (for [y (range 6)] (for [j (range 4)] (for [i (range 4)] [y (+ i j)])))) (for [y (range 6), j (range 4)] (for [i (range 4)] [y (+ i j)]))))

6:56 clojurebot: true

6:57 hyPiRion: usually, patterns of 3 or more of the same function/macro can be compacted in some way

6:58 it's not always obvious how to do it though, so if it's evident what you're trying to achieve, it doesn't really matter that much

7:02 clgv: naeg: yeah should read more about `for`. you can write really compact "complex iterations" with it

7:03 e.g. ##(for [x (range 5) y (range 5) :when (< x y)] [x y])

7:03 lazybot: ⇒ ([0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4] [2 3] [2 4] [3 4])

7:03 clgv: as a small example ^^

7:04 naeg: clgv: I know about :when and :while if you mean that, but it doesn't come in handy here, does it?

7:04 clgv: naeg: no. but you can and should reduce the nested `for` forms to one^^

7:04 naeg: clgv: for the diags? I'll see what I can do

7:05 btw, is that "idiomatic" with the (def player) and just chose the symbol by number? Couldn't think about a better way

7:05 mindbender1: naeg: where does get-y come from

7:06 naeg: mindbender1: it's defined above? or do you mean why I actually need it?

7:06 mindbender1: I meant definition

7:07 clgv: naeg: you probably dont need the indirection from player to symbol. you could directly represent the player with the symbol. how about using keywords and nil for the board? :X :O nil

7:07 naeg: mindbender1: line 10-14?

7:07 clgv: (str :X nil :O)

7:07 &(str :X nil :O)

7:07 lazybot: ⇒ ":X:O"

7:08 naeg: clgv: I wanted to put it into one place (like a constant) so when I decide to change the representation, I only have to do it at that def

7:08 clgv: naeg: ok, if it is really worth it for you. keep it ^^

7:08 mindbender1: naeg: I can't see a def for get-y

7:08 naeg: otherwhise you have to do it for insert, empty-board, get-y, ...

7:09 mindbender1: my repl has an error on it

7:09 naeg: mindbender1: maybe reload the page? I can see it at line 10

7:09 clgv: naeg: it's inner state of your game. you could also only change it in the output function if you just want to change the output the user sees ;)

7:09 mindbender1: naeg: ok seen it now

7:11 naeg: clgv: seems more "functional"? just putting nil :1 :2 or :X :O and print as "X" and "O"

7:12 clgv: naeg: well, I dont think you would change that inner representation of this game in other (oop) languages often, as well

7:13 naeg: an interesting goal for your game would be, that your implementation is such that you can easily let 2 AIs play against each other as well as human and AI mixed.

7:14 naeg: clgv: https://github.com/naeg/clj-connect-four

7:14 had that in mind too ;)

7:14 clgv: ok^^

7:15 naeg: how about a reinforcement learning AI? ;)

7:17 naeg: clgv: maybe one day, but I have enough learning to do with my ideas already^^

7:17 clgv: for the insert, just take player-number (either 1 or 2) and do (keyword player-number)?

7:18 (keyword (str player-numer))

7:20 nah, well I guess I'll leave the board representation as it is. It's not about that anyway, it's about the checking algorithm (want to compare it to a bit-board solution and maybe core.logic)

7:24 thanks to all of you

7:25 nkkarthik: does clojurescriptone tutorial work with lein 2?k

8:08 mindbender1: nkkarthik: It has not been updated for lein 2

8:09 nkkarthik: mindbender1: yeah I guess so... thank you

8:09 from emacs can we jack-in into cljsbuild repl-launch?

8:13 xeqi: nkkarthik: with nrepl.el and https://github.com/cemerick/piggieback you can get a cljs-repl

8:13 nkkarthik: xeqi: oh I will look into that... thank you

8:36 cshell: Has anyone been able to connect to a remote repl from La Clojure?

8:37 cemerick: I didn't realize La Clojure had remote REPL capability at all…

8:38 cshell: Yeah, that appears to be the case

8:38 I wonder how hard it would be to add

8:38 Is there a java/clojure api for connecting/interacting with a remote repl?

8:38 cemerick: Depends on what REPL backend is being used.

8:39 cshell: What's the most common REPL back end?

8:39 cemerick: Last I looked, La Clojure just piped through to a terminal REPL; lifting that into something network-capable isn't pretty.

8:39 cshell: yes, that is the current state

8:40 but it would be valuable, right?

8:40 cemerick: cshell: http://github.com/clojure/tools.nrepl is what Leiningen, ccw, nrepl.el, etc use.

8:40 Yes, if you can somehow get La Clojure to use nREPL, that'd be great.

8:41 cshell: Okay cool, thanks for the link - maybe I'll try to get it working sometime soon - the hardest part will be navigating the plugin api for intellij - it's the worst thing about it

8:42 clgv: is there some clojure notation for "pure thread-local storage" without the capabilities of binding?

8:43 cemerick: cshell: note that nREPL includes a Java API, which might be helpful if La Clojure is implemented in Java: https://github.com/clojure/tools.nrepl/blob/master/src/main/java/clojure/tools/nrepl/Connection.java

8:44 cshell: awesome, yeah that is exactly what I was looking for

8:56 jowag: Hi, which is more idiomatic, (apply conj {} kv-seq), or a (reduce conj {} kv-seq) ?

8:57 cshell: jowag: good, question

8:57 jowag: chouser: Hi, which is more idiomatic, (apply conj {} kv-seq), or a (reduce conj {} kv-seq) ?

8:58 chouser: reduce

8:58 cshell: does the first one work?

8:58 jowag: in Clojurescript, reduce is faster, dunno about vanilla clojure

8:59 ,(reduce conj {} [[1 2][3 4][5 6]])

8:59 clojurebot: {5 6, 3 4, 1 2}

8:59 jowag: ,(apply conj {} [[1 2][3 4][5 6]])

8:59 clojurebot: {5 6, 3 4, 1 2}

8:59 cshell: nice

9:00 chouser: http://clojure-log.n01se.net/date/2009-01-12.html#13:48

9:01 cshell: wow didn't know about that log

9:01 xeqi: ,(into {} [[1 2][3 4][5 6]])

9:01 clojurebot: {1 2, 3 4, 5 6}

9:01 chouser: cshell: smile, you're being logged right now.

9:02 Note the date on that -- over 3.5 years ago.

9:02 jowag: chouser: thanks, that settles it

9:02 cshell: chouser: haha, good thing I've limited my worst comments to private chats with clojurebot

9:06 jowag: xeqi: thanks, seems like into is the best choice for this particular task

9:39 nkkarthik: ClojureScript cljsbuild repl-listen... getting JS errorNo *print-fn* fn set for evaluation environment... what could be done?

9:52 I got it... I cannot use (print "foo") I suppose

9:55 dnolen: nkkarthik: that doesn't really make sense at least IME. print should work just fine.

9:57 nkkarthik: dnolen: hmm... I have no clue why it is happening...

9:57 I had only two lines (ns try.core) (print "hello")

9:57 dnolen: nkkarthik: did you try println?

9:57 nkkarthik: did cljsbuild once... loaded the index.html with the generated js file and it shows that error

9:58 oh... didn't... just removed that line and it worked

9:58 dnolen: nkkarthik: oh if you're trying to use browser repl then you need to include it in your ns.

9:58 nkkarthik: actually I didn't needed any print (though I thought it would print to console)

9:58 dnolen: nkkarthik: *print-fn* needs to be set since we really can't make any assumptions about where you are runnign js

9:59 nkkarthik: in the browser it's console.log but that's not necessarily true in Rhino, or JSC, or SpiderMonkey JSShell etc.

9:59 nkkarthik: ah... what could be a decent default for firefox?

9:59 dnolen: nkkarthik: if you want that to work just (set! *print-fn* (fn [x] (.log console x)))

9:59 nkkarthik: do that in your file.

10:00 after that line print/println will work.

10:01 nkkarthik: dnolen: cool... I will try that... thank you for the help

10:12 can nrepl.el jack-in to use clojurescript repl? tried piggieback but getting some errors

10:13 cemerick: nkkarthik: Did you tweak your project.clj to add the piggieback middleware?

10:14 nkkarthik: cemerick: yeah... it said nrepl middleware not found

10:15 cemerick: Interesting.

10:15 nkkarthik: these are the things I added

10:15 cemerick: nkkarthik: which version of Clojure and Leiningen?

10:15 nkkarthik: :injections [(require 'cemerick.piggieback)]

10:15 :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}

10:15 clojure 1.4.0

10:15 Leiningen 2.0.0-preview7 on Java 1.6.0_18 OpenJDK 64-Bit Server VM

10:16 cemerick: nkkarthik: ah, ok: that Leiningen configuration requires a minimum of preview9, I think.

10:16 nkkarthik: sorry... that's just output redirected to here...

10:17 cemerick: It says Leiningen master in the README, but I think that was just prior to preview9.

10:17 nkkarthik: cemerick: oh ok... I will upgrade now and let you know

10:18 dnolen: for those following CLJS feedback on this would be appreciated - http://dev.clojure.org/jira/browse/CLJS-340

10:23 please check out the patch & comment on the ticket. would like to move forward on this one.

10:26 evalifoo: hello

10:26 is there any work done to get closure bindings for clojure ?

10:26 nkkarthik: cemerick: hey... nrepl started with latest leiningen

10:26 cemerick: next I tried to start browser repl with

10:26 cemerick: nkkarthik: Fabulous. :-)

10:30 nkkarthik: cemerick: you are awesome... thank you very much for giving us piggieback

10:30 cemerick: nkkarthik: Just a bit of glue :-) Glad it worked for you.

10:31 nkkarthik: cemerick: you can rhyme too :)

10:31 uvtc: No more rhyming. I mean it.

10:31 nkkarthik: or maybe rap

10:32 cemerick: I don't really have that great a flow, probably because I rarely get a chance to blow.

10:33 uvtc: You should be happy for some rhyming; just imagine how irritating it'd be if we were all miming.

10:33 nkkarthik: ha ha ha... cool bro

10:33 cemerick: I'll be here all night folks, tip your waitresses. :-P

10:33 casion: that sounded sincere :P

10:33 uvtc: Probably it's no harm. ... It adds a certain charm.

10:35 casion: (Princess Bride reference :) )

10:36 casion: ah, never saw it

10:36 * nkkarthik is still trying to find some words he can make a rhyme out of

10:37 casion: cmon nkkarthik you can use any words, take your pick

10:37 uvtc: nkkarthik, are there compiler errors ahead?

10:38 hyPiRion: ,(require '[clojure.string :refer [join]])

10:38 clojurebot: nil

10:39 algernon: oh, compiler errors! / in my heart, they'll send tremors / for when I see one, I need to squish / and accidentally step on a fish.

10:39 hyPiRion: #poetry is over there, guys.

10:39 nkkarthik: uvtc: :)

10:39 gfredericks: "me fancy pants make me fancy prance"

10:40 technomancy: clojurebot: java.util.concurrent?

10:40 clojurebot: java.util.concurrent is "When I find myself in times of trouble / Prof. Doug Lea comes to me / Coding lines of wisdom / j.u.c."

10:40 llasram: niiice

10:40 gfredericks: if you want to include slashes in your poem do you have to escape them?

10:40 what is the standard escape mechanism in poetry?

10:41 llasram: gfredericks: You escape them with newlines

10:41 gfredericks: lol

10:41 nkkarthik: ha ha ha

10:41 hyPiRion: gfredericks: \n works fine

10:42 llasram: Anyone have any insight into why `clojure.java.io/Coercions` doesn't include an `as-uri`?

10:44 My understanding is that java.net.URL has (used to have?) some serious issues, and java.net.URI is generally the way to go. But maybe I'm mistaken?

10:45 clgv: llasram: doesnt URL has a toURI method?

10:50 llasram: clgv: It does at that, so I suppose one can easily implement `as-uri` in terms of `as-url`

10:50 clgv: llasram: I'd think so

10:50 llasram: I just don't quite understand the reasoning, given that classes have differences which are orthogonal to the URI/URL distinction

10:51 And the URL class really does seem to be completely broken: the .equals method (a) *resolves the hosts* of the URLs, and (b) considers them equal if they resolve to the same IP

10:51 And .hashCode also does host resolution

10:51 I'd really just rather never create one of these beasts :-)

10:52 uvtc: pjstadig: Informative talk (Laziness, the Good, Bad, & Ugly). Thanks. :) Too bad infoq doesn't show the code demo below where the slides would normally go. Aside: I'm glad I could hear the questions asked at the end. Sometimes those don't get recorded well.

10:52 pjstadig: yeah :(

10:53 clgv: llasram: sometimes they are created for you, cf. clojure.java.io/resource

10:53 pjstadig: i wanted to do something different with live coding, but it doesn't translate so well into video without videoing the projection screen

10:53 thanks the feedback :)

10:53 casion: oh, a new clojure talk

10:54 I needed something to listen to, yay

10:54 llasram: clgv: Fair enough. Although those are file: URLs, which are probably fine. I'm probably just over-thinking this

10:54 uvtc: pjstadig: Yeah, seems like there should be a solution there. A way to do live coding and have it translated into slides ...

10:56 Maybe an Emacs command to htmlize the current screen and send it directly as the "next slide".

10:57 casion: you could setup something with org-babel pretty easily I think

10:58 I don't know how people handle slides though, is there a way to update a presentation without reloading it?

10:59 pjstadig: uvtc: the code from the pres is available

10:59 https://github.com/pjstadig/laziness

10:59 scriptor: how do people typically embed code in slides anyway?

11:00 uvtc: I think it's great how infoq displays slides in sync with the talk.

11:00 pjstadig: thanks.

11:01 nDuff: ....so -- I have a delay that throws an exception in an external atom is nil. That works fine -- but when trying to eval it again, its locals have been cleared.

11:02 ...hrm, looks like CLJ-232

11:02 ...except that's marked fixed.

11:11 lpetit: Should something like (:foo (Object.)) have thrown an exception in my face, I would have not wasted a lot of debugging time :-/

11:13 nDuff: I'm seeing behavior that strikes me as a potential bug in Clojure 1.4 -- can anyone comment? https://gist.github.com/9a1fa25f9a7429b6def7

11:14 clgv: lpetit: yeah. you can do that with symbols as well

11:15 lpetit: clgv: well, I don't like it :)

11:15 clgv: lpetit: I had that several times myself :/

11:16 hyPiRion: nDuff: That's expected behaviour, I believe.

11:16 A delay just delays the computation, and saves the result from it later on.

11:17 When the delay throws an exception, nothing (nil) is returned.

11:17 nDuff: hyPiRion: Let me come up with a better test case -- that's not what it's actually doing.

11:18 hyPiRion: ...the real case I'm trying to simplify from clearly demonstrates that the code inside the delay is executing again, but with locals cleared.

11:20 ystael: I have a question about type annotation metadata and how to get at it once it's created

11:21 I'm trying to add support for exposing operations to clojure/java.jmx, and I thought it might be nice to support type annotations on signatures to expose parameter types through JMX (for non-Clojure JMX clients)

11:21 But I clearly don't understand where the annotation metadata "goes" once it's defined

11:22 hyPiRion: nDuff: ah.

11:22 nDuff: hyPiRion: Just updated with a new reproducer.

11:22 clgv: ystael: the "type hint" is stored in the metadata attribute :tag

11:23 ystael: If I do: (defn foo [^Long a] (* 2 a)) what object is the metadata attached to?

11:23 clgv: ystael: its attached to symbol a

11:23 ystael: i.e., (meta WHAT) should contain {:tag Long} ?

11:23 clgv: ,(meta ^Long a)

11:23 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0)>

11:23 clgv: ,(meta ^Long 'a)

11:23 clojurebot: nil

11:23 clgv: not that easy

11:24 ,(meta (read-string "^Long a"))

11:24 clojurebot: {:tag Long}

11:24 clgv: ,(pr (meta (read-string "^Long a")))

11:24 clojurebot: {:tag Long}

11:24 ystael: ,(do (defn foo [^Long a] (meta 'a)) (foo 3))

11:24 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

11:25 clgv: ystael: no, that is not possible. you can only access that metadata in a macro on compile time

11:25 ystael: ah ha! that's the problem

11:26 ^ is processed by the reader and what is floating around in the *source chewed by my macro* is a symbol that has metadata on it

11:26 but it does not survive until the actual code runs

11:26 correct?

11:27 clgv: ystael: ok, I checked. it is still present in (-> #'foo meta :arglists)

11:28 ystael: try the following to see it (binding [*print-dup* true] (-> #'foo meta :arglists pr))

11:28 ystael: clgv: yeah, (-> #'foo meta :arglists first first meta) ;; => {:tag Long}

11:28 hyPiRion: clgv: Seems like it loses its environment

11:29 sorry, I meant nDuff

11:29 nDuff: Shoot.

11:30 Looks like it only happens with slingshot's throw+

11:30 works fine with (throw (Exception. "foo"))

11:30 ystael: clgv: but this doesn't work with letfn?

11:30 ,(binding [*print-dup* true] (letfn [(foo [^Long a] (* a 2))] (-> 'foo meta :arglists pr)))

11:30 clojurebot: nil

11:30 clgv: ystael: humm maybe not

11:31 ystael: makes sense because 'foo there is just a symbol, the fn is not bound to it until run tiem

11:31 clgv: (binding [*print-dup* true] (letfn [(foo [^Long a] (* a 2))] (-> foo meta pr)))

11:31 ,(binding [*print-dup* true] (letfn [(foo [^Long a] (* a 2))] (-> foo meta pr)))

11:31 clojurebot: nil

11:32 ystael: but if i chew that letfn-body up in a macro, the metadata should be visible in the arg symbol there

11:32 which is what i want to do

11:32 * nDuff ponders whether he has the time track down the root cause sufficiently to file a CLJ ticket, or if filing against Slingshot will do.

11:33 hyPiRion: nDuff: hm.

11:34 clgv: ystael: yeah in a macro you have the metadata on the symbols

11:37 ystael: clgv: cool, thanks much for your help

11:37 hyPiRion: ,(let [b (fn [s a] (let [d (delay (if (nil? @a) (throw (Exception.)) s)) c (atom nil) f (b "foo" c)] (try @f (catch Exception _ (swap! c not) @f)))

11:37 clojurebot: hyPiRion: Cool story bro.

11:37 clgv: ystael: pr with *print-dup* set to true often helps ^^

11:39 hyPiRion: clojurebot: So you don't like try catch, eh.

11:39 clojurebot: Cool story bro.

11:40 clgv: hyPiRion: try lazybot^^

11:40 hyPiRion: &(try 0 (finally 1))

11:40 lazybot: ⇒ 0

11:40 hyPiRion: &(let [b (fn [s a] (let [d (delay (if (nil? @a) (throw (Exception.)) s)) c (atom nil) f (b "foo" c)] (try @f (finally (swap! c not) @f)))

11:40 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

11:41 clgv: so it's not clojurebot's fault. he is just too lazy to give you the reason for not evaluating ;)

11:41 hyPiRion: clgv: it is

11:41 ,(try 0 (finally 1))

11:41 clojurebot: hyPiRion: Cool story bro.

11:42 hyPiRion: Well, and I had some semantics messed up

11:43 clgv: ah lol. well maybe it's philosophical: don't try - just do!

11:43 hyPiRion: &(let [b (fn [s a] (let [d (delay (if (nil? @a) (throw (Exception.)) s))] (fn [] @d))) c (atom nil) f (b "foo" c)] (try (f) (finally (swap! c not) (f))))

11:43 lazybot: java.lang.NullPointerException

11:43 hyPiRion: Yeah, there we go. It loses its environment.

11:44 it's a hellhole though, better clean the thing up a bit.

11:48 Interesting.

11:49 &(let [a (atom false), b "foo", d (delay (if @a (/ 0 1) b))] (try d (finally (swap! a not) d)))]

11:49 lazybot: ⇒ #<Delay@57d10: :pending>

11:49 hyPiRion: &(let [a (atom false), b "foo", d (delay (if @a (/ 0 1) b))] (try @d (finally (swap! a not) d)))]

11:49 lazybot: ⇒ "foo"

11:51 uvtc: How can I get every item in a coll *except* for the nth one? (I'd actually like a way to get both at the same time: the n'th, and everything but the n'th). Currently I'm using shuffle then first & rest.

11:52 (Er, I mean, I'm using `shuffle` because the n'th I want is a random n'th.)

11:52 lotia: java interop question. any pointers to syntax help on how I'd import multiple java classes within a namespace definition

11:52 uvtc: (In this particular case, anyway.)

11:56 clgv: uvtc: well use a set - randomly draw one element and remove it from the set

11:59 uvtc: ,(let [s #{:a :b :c :d}] [(first s) (rest s)])

11:59 clojurebot: [:a (:c :b :d)]

12:00 uvtc: clgv: Nice. Thanks. :)

12:00 jeremyheiler_: hyPiRion: The delay was forced in the try, so that makes sense.

12:01 &(let [a (atom false), b "foo", d (delay (if @a (/ 0 1) b))] (try d (finally (swap! a not) @d)))

12:01 lazybot: ⇒ #<Delay@135f562: 0>

12:01 clgv: uvtc: just to be exact, that's not what I meant

12:02 uvtc: clgv: can you give me an example?

12:03 clgv: ,(let [s #{:a :b :c :d} i (rand-int (count s)) e (nth s i)] [e (disj s e)])

12:03 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: PersistentHashSet>

12:03 clgv: ,(let [s #{:a :b :c :d} i (rand-int (count s)) e (nth (seq s) i)] [e (disj s e)])

12:03 clojurebot: [:b #{:a :c :d}]

12:03 clgv: ,(let [s #{:a :b :c :d} i (rand-int (count s)) e (nth (seq s) i)] [e (disj s e)])

12:03 clojurebot: [:a #{:c :b :d}]

12:04 arkh: would anyone know why raynes conch has a 'read-line' function missing in the clojars jar but it's present on his github repo?

12:04 clgv: uvtc: it works. but might perform good or bad depending on its context

12:04 uvtc: clgv: thanks!

12:06 jeremyheiler_: arkh: How are you determining that it's missing?

12:07 arkh: jeremyheiler_: I did a wget on the clojars jar (the same URL lein used) and compared conch.core to his github repo. read-line doesn't exist in the jar

12:08 jeremyheiler_: and caused me errors and consternation ;)

12:08 nDuff: hyPiRion: Are you running with this one yourself, or should I submit your reproducer as part of a CLJ ticket?

12:09 arkh: jeremyheiler_: I'm using 0.2.1

12:10 jeremyheiler_: arkh: It seems the read-line function didn't appear until 0.2.4

12:11 At least, that is the version number in project.clj when read-line was committed.

12:12 arkh: jeremyheiler_: oh - I blindly followed the readme.md instructions on his master branch. Thank you for finding that!

12:12 jeremyheiler_: Yeah, so actually that means read-line didn't appear until 0.3.0

12:12 lpetit: Can this be simplified ?

12:12 #(let [comparator (serverrepl/textmate-comparator prefix)]

12:12 (comparator (:completion %1) (:completion %2)))

12:14 clgv: lpetit: if you need to sort something there would by sort-by - but it seems there is no compare-by

12:14 lpetit: Assume I have a comparator c1. And I want it to apply only on the :completion key of its inputs.

12:15 clgv: I need some kind of higher level functions which would take the target function (the comparator), then argument transformation functions.

12:16 So that it could be called like: (adapt-arguments c1 :completion :completion) -> then calls to it would be equivalent to calls to (comparator (:completion %1) (:completion %2))

12:17 clgv: lpetit: you probably have to write that one yourself.

12:17 lpetit: clgv: so I will just use the code shown above for now on :)

12:33 clgv: there were are, https://gist.github.com/3532443

12:33 clgv: lpetit: that pattern looks strangely familiar

12:34 lpetit: clgv: I first wrote the generic function (the last line), then added special cases for 1 & 2 arguments functions so that it goes generally fast (e.g. for my comparator which takes 2 arguments)

12:35 clgv: lpetit: ah right map&co do the same^^

12:35 lpetit: So I had first a clear version made of 4 lines, and now I have a one line version plus an obscure helper function of 20 lines :)

12:37 technomancy: is there a good thrush-friendly idiom for "call update-in on this map with this key path, but only if the key is already present?

12:37 "

12:38 clgv: lpetit: arg the symbol-issue ('symbol anything) bit me just now :(

12:39 lpetit: clgv: corrected in the beta I will release soon

12:39 clgv: lpetit: no I meant, I had a similar error to what you mentioned with keywords before ;)

12:40 lpetit: ah :)

12:42 clgv: well. next try. I hope there won't emerge an error.log this time ^^

12:46 hah. works! :)

12:47 hyPiRion: jeremyheiler_: Yeah, I screwed up a lot in that test. It's better when you can def and so forth in an actual repl.

12:47 jeremyheiler_: ah ok

12:48 I opened the logs and saw the rest of your conversation with nduff, and realized what was going on

12:50 gzmask: humm... newbie question folks, ['a 'b :name 12.5] in this vector, what are the 'a and 'b? are they lists?

12:50 hyPiRion: nDuff: I'll have a better look at it now, as the code I used here didn't really make sense at all.

12:51 clgv: gzmask: symbols

12:51 mattmoss: ,(class 'a)

12:51 clojurebot: clojure.lang.Symbol

12:51 clgv: &(map type ['a 'b :name 12.5] )

12:51 lazybot: ⇒ (clojure.lang.Symbol clojure.lang.Symbol clojure.lang.Keyword java.lang.Double)

12:51 thorbjornDX: ,(class '(a))

12:51 clojurebot: clojure.lang.PersistentList

12:51 mattmoss: Ya, realize that 'a is shorthand for (quote a)

12:54 gzmask: mattmoss: (quote a) is no eval ?

12:54 mattmoss: gzmask: Yeah, I guess you could say that it prevents eval.

12:55 shaungilchrist: wow lazy-seq stuff is rad

12:55 mattmoss: So... (1 2 3) the compiler will attempt to eval as calling function "1" with args 2 and 3.

12:55 Where as '(1 2 3) is a sequence/list of 3 items.

12:55 ,(1 2 3)

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

12:55 mattmoss: ,'(1 2 3)

12:55 clojurebot: (1 2 3)

12:55 gzmask: mattmoss: oh i see, that's how lisp preserves a list

12:56 mattmoss: And (quote (1 2 3)) = '(1 2 3)

12:56 hyPiRion: And by using this, we can generate code on the fly:

12:56 ,(cons '+ (1 2))

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

12:57 hyPiRion: ,(cons '+ (list 1 2))

12:57 clojurebot: (+ 1 2)

12:57 mattmoss: hmm...

12:57 ,((cons '+ (list 1 2)))

12:57 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IFn>

12:57 jsnikeris: What's a good way to coerce parameters using ring? E.g. "1" -> 1, "2012-08-30" -> java.util.Date. Is it better to do this in a handler or using middleware?

12:57 gzmask: ,((cons '+ '(1 2)))

12:57 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IFn>

12:58 mattmoss: gzmask: Ignore what I typed... was experimenting, and added extra ( )

12:58 hyPiRion: So how would you then evaluate the result of your cons?

12:58 hyPiRion: mattmoss: usually, you'd use eval to evaluate a list

12:59 gzmask: ,(cons '+ '(1 2))

12:59 clojurebot: (+ 1 2)

12:59 mattmoss: Is eval "evil" in clojure as compared to other langs?

12:59 ,(eval (cons '+ '(1 2)))

12:59 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

12:59 `fogus: Moar evil!

12:59 mattmoss: lol

12:59 gzmask: like js?

12:59 mattmoss: Apparently it's evil here.

12:59 nDuff: mattmoss: Not as much as some, but it's still better avoided.

12:59 hyPiRion: ~evil

12:59 clojurebot: evil is DENIED

12:59 S11001001: mattmoss: eval is evil in clojure, as with all reasonable lisps

12:59 jsnikeris: handler

13:00 jsnikeris: S11001001: That's what I'm thinking. So basically every parameter handles coercing the parameters it expects, right?

13:00 hyPiRion: mattmoss: It's "evil" in the sense that we have discovered that it will lead to bugs, and that you will become frustrated at your code if you're using it

13:00 S11001001: jsnikeris: yes

13:00 jsnikeris: S11001001: thanks!

13:01 mattmoss: It's just... I'm hooking up a Java lib that involves calling lots of camel-case g/setters, originating from clojure maps with typical dashified keywords.

13:01 `fogus: A slightly less-evil eval --> https://github.com/fogus/evalive

13:01 gzmask: ,(eval (cons '+ '(1 2)))

13:01 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

13:01 mattmoss: So I tried various ways to use macros with (defn dash-to-camel [] ...) etc, but could not figure out how to generate the calls into java without going to reflection.

13:02 And granted, reflection might be the proper way to do it rather than messin' with macros.

13:02 hyPiRion: gzmask: clojurebot and lazybot doesn't allow eval, because it may run dangerous code.

13:02 S11001001: mattmoss: I've written this before, without reflection: (bean-set! jobj {:a b, :c d}) => do setA(b), setC(d) on jobj

13:02 gzmask: hyPiRion: yea, i figured. it's da evil here...

13:03 mattmoss: S11001001: Is that in contrib? Hadn't seen that...

13:04 uvtc: `fogus: Egads, scary icon graphic for evalive. :)

13:04 mattmoss: Although I did find this: http://pastebin.com/DbBdFxmG

13:05 `fogus: uvtc: Helps to highlight the level of evil we're dealing with

13:05 uvtc: hahaha

13:05 S11001001: mattmoss: that's not my version; I don't have it around right now, but you have to exploit all the compile-time knowledge you can get your hands on to implement it

13:06 mattmoss: in particular, it's possible to implement a version that can sometimes avoid reflection even if the map you provide isn't literal, but much harder to do so

13:07 mattmoss: the simple implementation strategy relies on the presence of a map literal to compile out the reflection

13:07 rbxbx: `fogus nice reference :)

13:07 mattmoss: Well, now that I am recalling the work I did at 2am last night... reflection might not be so bad. I'm using that anyway to determine what getters and setters exist.

13:08 Although clojure.reflect doesn't seem to have an included way to call a method from clojure.reflect.Method info.

13:13 Frozenlo`: Did I imagine this, or there's a way for a function to have different behavior depending on the type of argument?

13:13 S11001001: Frozenlo`: sure

13:13 ,(doc case)

13:14 clojurebot: "([e & clauses]); Takes an expression, and a set of clauses. Each clause can take the form of either: test-constant result-expr (test-constant1 ... test-constantN) result-expr The test-constants are not evaluated. They must be compile-time literals, and need not be quoted. If the expression is equal to a test-constant, the corresponding result-expr is returned. A single default expression can foll...

13:14 mattmoss: Perhaps Frozenlo` is thinking of multimethods?

13:14 S11001001: mattmoss: perhaps you should try writing this function: (setters cls) => (fn [arg] (case arg :a #(.setA % %), :bob #(.setBob % %), ...); then, write a :inline (see core.clj) for it that exploits a direct `cls' reference

13:14 SegFaultAX|work2: What's the best way to split a number into its digits?

13:14 Eg (digits 1234) => (1 2 3 4)

13:14 Frozenlo`: isn't case the same thing as cond?

13:15 S11001001: no

13:15 Frozenlock: (if (string? it) do-something do-something-else) :)

13:15 mattmoss: S11001001: Thanks... good idea. I'll take a look at it.

13:15 S11001001: SegFaultAX|work2: str, then map subtracting 32, with coercions as needed

13:16 Frozenlock: S11001001: Thanks!

13:16 SegFaultAX|work2: ,(map #(Integer/parseInt %) (str 1234))

13:16 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.String>

13:16 SegFaultAX|work2: ,(map #(Integer/parseInt (str %)) (str 1234))

13:16 clojurebot: (1 2 3 4)

13:17 SegFaultAX|work2: That's the best way?

13:17 S11001001: ,(map #(- (int %) 32) (str 1234))

13:17 clojurebot: (17 18 19 20)

13:17 S11001001: well, not 32, 48 I guess

13:17 mattmoss: ,(clojure.string/split (str 1234) #"[0-9]")

13:17 clojurebot: []

13:17 mattmoss: oops, doh

13:18 ignore me

13:18 S11001001: ,(map #(- (int %) 48) (str 1234567890))

13:18 clojurebot: (1 2 3 4 5 ...)

13:18 S11001001: SegFaultAX|work2: no need for the str-again-and-parse roundtrip

13:18 mattmoss: ,(map #(- (int %) \0) (str 1234567890))

13:18 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number>

13:18 mattmoss: I lose!

13:18 S11001001: mattmoss: you forgot the coercion

13:19 mattmoss: Ya.

13:19 Too much time spent in C++-/Ruby-/whatever-land.

13:19 * mattmoss is leaving all other languages for PHP.

13:20 Frozenlock: What is the prefered way between multi and protocols?

13:21 technomancy: multimethods

13:21 S11001001: multimethods

13:21 technomancy: unless it's a performance bottleneck

13:22 Frozenlock: Thanks, I'll try it immediately.

13:22 technomancy: "The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet."

13:24 dnolen: Frozenlock: if you predict you and your consumers are not going to call your fn from an inner loop, multimethods are nice. you wouldn't want first to be a multimethod. But the chances that you're something as critical as first is probably pretty low.

13:24 you're writing I mean.

13:28 shaungilchrist: so I am coming from the land of backbone apps, I would like to transition entirely to using clojurescript and cljs-isms is the pinot/ibdknox libs my best bet?

13:29 dnolen: shaungilchrist: there isn't really a backbone equivalent for CLJS yet.

13:31 shaungilchrist: well not completely true, CLJSOne tries to be something of a complete solution ... though the branch that's more to up to date with CLJS hasn't been merged to master.

13:32 shaungilchrist: interesting, I will check it out again - had issues w/ my lein version last time I tried it

13:34 dnolen: emezeske: heh still no feedback tho I think you're patch looks pretty good to me.

13:34 emezeske: dnolen: Cool. Did the IWriter protocol come out like you were expecting?

13:35 dnolen: emezeske: I think it's pretty nice!

13:35 emezeske: dnolen: The fact that it writes straight to stdout is pretty cool

13:35 gzmask_: why vimclojure always cause me vim to quit with ABRT?

13:35 emezeske: dnolen: It was pretty silly to print to a buffer and then print that before

13:36 lpetit: New Counterclockwise Beta released.

13:36 dnolen: emezeske: and it can easily be redirected to anything that implements IWriter

13:36 emezeske: dnolen: Yep!

13:40 dnolen: emezeske: perhaps my only reservation now is the name of the protocol IPrintWriter ... perhaps simply IWritable is better?

13:42 Frozenlock: Ok so I want to try (defmulti foo class) in cljs, but when I try (class "sad") in my repl I get an error. Is class defined in cljs?

13:43 dnolen: Frozenlock: it is not

13:43 Frozenlock: but you do have type

13:43 emezeske: dnolen: Hmm, yeah, I wasn't super happy with IPrintWriter

13:44 dnolen: Really, it should just be IPrintable :)

13:44 lpetit: clgv: ^^

13:44 dnolen: emezeske: I'm actually warming up to writable since it's more generic and better communicates that it works with IWriter

13:44 IWritable I mean

13:44 borkdude: lpetit nice, any new cool features?

13:45 lpetit: borkdude: since last beta ? or last stable ?

13:45 emezeske: dnolen: I kind of feel like the "print" part is important, as that implies (to me) pr-style formatting

13:45 borkdude: lpetit ehm, since like six weeks ago :)

13:46 Frozenlock: dnolen: So (defmethod foo (type "") [s] :a-string) would be idiomatic cljs?

13:46 emezeske: dnolen: E.g. technically you can't juse pass an IWritable instance to IWriter's -write, which is what I think those names would imply

13:46 just*

13:46 dnolen: Frozenlock: no (defmethod foo String [s] :astring)

13:46 lpetit: borkdude: well, I fixed something like 10 bugs, enhanced a little bit the code completion, integrated some pull requests. But nothing brand new. Worth the upgrade, I think.

13:47 hyPiRion: Okay, can people try this code? https://www.refheap.com/paste/4740

13:47 Apparently, the delay loses its closure/environment and NPE all the way.

13:47 lpetit: borkdude: http://code.google.com/p/counterclockwise/issues/list?can=2&q=status%3Afixed

13:48 dnolen: emezeske: hmm, because you need the surrounding setup ... IPrintWithWriter?

13:48 hyPiRion: Interestingly only parts of it though.

13:49 dnolen: Frozenlock: actually (defmethod foo js/String [s] :astring)

13:49 Frozenlock: dnolen: My REPL goes crazy

13:49 Ah

13:49 nsxt: has fleetdb been superseded by another project?

13:49 jml: I'm trying to find an example of using :expose with gen-class (for protected attributes), but am not having much luck. anyone know of any?

13:50 Frozenlock: dnolen: And for map that would be cljs.core/ObjMap ?

13:50 emezeske: dnolen: IPrintWithWriter is better than IPrintWriter I think.

13:50 dnolen: Frozenlock: yes, though you probably don't need cljs.core/ObjMap since cljs.core is implicitly used

13:50 Frozenlock: Oh right!

13:51 dnolen: emezeske: cool mind updating the patch with that?

13:51 Frozenlock: Yay it works :D

13:51 emezeske: dnolen: No problem, I can do that this evening

13:51 dnolen: emezeske: thx!

13:51 Frozenlock: Thanks!

13:52 dnolen: Frozenlock: np

13:55 SegFaultAX|work2: Can there be multiple :when contraints in a for form?

13:55 hyPiRion: SegFaultAX|work2: Try it out

13:55 ,(for [x (range 10) :when (odd? x) :when (even? (+ x 1))] x)

13:55 clojurebot: (1 3 5 7 9)

13:55 SegFaultAX|work2: ,(for [x (range 3) y (range 3) :when (even? x) (odd? y)] [x y])

13:55 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: for requires an even number of forms in binding vector in sandbox:>

13:56 SegFaultAX|work2: Ohh, I have to supply :when multiple times.

13:56 scriptor: is there a function like reduce but which takes a seq of functions, and iterates through that seq as it goes through coll?

13:57 so something like (reduce '(+ *) [1 2 3])

13:57 which would result in 9

13:58 gzmask: functors...

13:58 hyPiRion: scriptor: Can you give another example?

13:58 SegFaultAX|work2: ,(reduce (comp + *) [1 2 3])

13:58 clojurebot: 6

13:59 scriptor: SegFaultAX|work2: nope, it has to go through the functions one by one

13:59 shaungilchrist: would it cycle through the functions if the seq had more items?

13:59 SegFaultAX|work2: scriptor: I'm not even sure what you're asking for.

13:59 nDuff: ...so you want a stateful reducer?

13:59 scriptor: shaungilchrist: possibly, I was thinking of just passing in something like (cycle [+ *])

13:59 nDuff: yes, basically

13:59 SegFaultAX|work2: I think you want applicative functors.

13:59 shaungilchrist: (* (+ 1 2) 3) is what he is asking for

14:00 hyPiRion: oh.

14:00 scriptor: I figured it would be a allow for an interesting way to do player moves in a game

14:00 gzmask: yea, haskell has this as adaptive functors. I am new to clojure so i don't know what this is

14:01 scriptor: (stateful-reduce (cycle [player1 player2] (board) [move1 move2 move3 …])

14:02 where player1 and player2 are functions that take a move and a game board, and return the next game board

14:05 SegFaultAX|work2, gzmask: any links for reading up on them?

14:05 found the haskewllwiki for applicative functors

14:05 gzmask: sorry, it should be applicative functors

14:06 SegFaultAX|work2: scriptor: I don't know if such a thing exists in Clojure. But the applicative style makes this sort of thing quite simple.

14:06 zerokarmaleft: technomancy: ping

14:06 hyPiRion: ,(let [(f1 [x y] (if (empty? y) x #(f2 (+ x (first y)) (rest y))))) (f2 [x y] (if (empty? y) x #(f1 (* x (first y)))))] (trampoline x 1 [2 3]))

14:06 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

14:07 hyPiRion: oh darnit.

14:07 mattmoss: lolz

14:07 Need paredit for irc?

14:07 Or irc in your emacs?

14:07 hyPiRion: Why doesn't M-x package-list-packages work in irssi?

14:08 scriptor: shouldn't be hard to enable paredit in erc

14:08 SegFaultAX|work2: mattmoss: That's actually possible.

14:08 ghadishayban: anyone used christophe grand's regex library?

14:10 mattmoss: SegFaultAX: What *isn't* possible in emacs?

14:10 hyPiRion: THERE

14:10 ,(letfn [(f1 [x y] (if (empty? y) x #(f2 (+ x (first y)) (rest y)))) (f2 [x y] (if (empty? y) x #(f1 (* x (first y)) (rest y))))] (trampoline f1 1 [2 3]))

14:10 clojurebot: 9

14:10 mattmoss: I mean, when I woke up this morning, emacs was in the kitchen grinding beans and making coffee. Seriously.

14:11 pjb3: How are people doing environment specific configuration in Clojure apps?

14:11 I'm doing something right now with env var

14:11 and the loading different DB configuration based on that

14:11 technomancy: zerokarmaleft: hello

14:12 pjb3: one thing I'd like to do is when I run "lein test" have it default to the test environment

14:12 ghadishayban: pjb3: you can slurp from classpath/resources

14:12 zerokarmaleft: technomancy: when running `lein repl` standalone, repl-port gets left behind after the server shuts down...should that get cleaned up afterwards?

14:12 ghadishayban: (-> path slurp read-string)

14:13 pjb3: ghadishayban: yeah, but I'm trying to figure out how to read the appropriate files so I can connection to a different DB for test and dev

14:13 and CI, prod, etc.

14:14 SegFaultAX|work2: zerokarmaleft: That is annoying, isn't it?

14:14 technomancy: zerokarmaleft: I guess so

14:14 target should always be on gitignore, so no one should ever notice, but it might as well get deleted

14:14 amalloy: scriptor: that's not hard to write as an ordinary reduce

14:15 &(reduce (fn [acc [f x]] (f acc x)) 0 (map vector (cycle [* +]) [1 2 3]))

14:15 lazybot: ⇒ 6

14:16 hyPiRion: &(reduce (fn [acc [f x]] (f acc x)) 1 (map vector (cycle [* +]) [1 2 3])) ;?

14:16 lazybot: ⇒ 9

14:17 zerokarmaleft: if `lein repl` is launched outside of a git repo (e.g. ~/), then it seems reasonable to delete it

14:17 amalloy: &(reduce (fn [acc [f x]] (f acc x)) 1 (map vector (cycle [+ *]) [2 3])) is probably most like what he actually said, since we have to fake the reduce1 behavior

14:17 lazybot: ⇒ 9

14:17 technomancy: zerokarmaleft: oh, absolutely

14:18 best to do it in either case; wasn't thinking about outside a project

14:19 zerokarmaleft: technomancy: should i file an issue?

14:19 technomancy: sure

14:20 hyPiRion: I can agree with this

14:20 zerokarmaleft: ok

14:20 hyPiRion: I just did `find -name repl-port | wc -l` and ended up with 15.

14:20 technomancy: patch would be great; shouldn't be difficult at all

14:21 scriptor: amalloy: was there a design reason why reduce doesn't multiple collections in the same way map does?

14:21 *doesn't do

14:21 zerokarmaleft: technomancy: i'll take a crack at it

14:21 hyPiRion: scriptor: the optional argument would be hard to find then.

14:21 ,(doc reduce)

14:21 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val i...

14:22 scriptor: ah, good point

14:32 pjb3: Is there a way to have lein run a function when the repl is loaded?

14:33 borkdude: listening to the podcast with cemerick and Raynes now

14:33 cemerick: borkdude: :-)

14:34 That's http://mostlylazy.com/2012/08/30/episode-7-anthony-grimes-tools-and-projects-minimum-viable-snippets/ for anyone interested.

14:34 shaungilchrist: amalloy: your solution to scriptors quandry is awesome. so clean! I had a solution twice as long :-(

14:36 technomancy: cemerick: for the record, you have "download the mp3" and "or download the mp3 directly" links that both go to the same place

14:36 shaungilchrist: I think I have correctly used it to make: (defn reduce-cycle [fns a-seq] (reduce (fn [acc [f x]] (f acc x)) (first a-seq) (map vector (cycle fns) a-seq))) so (reduce-cycle [* +] [1 2 3]) works as expected.

14:36 cemerick: technomancy: where? I only see one download link

14:38 technomancy: cemerick: http://p.hagelb.org/mostly-lazy.png

14:38 cemerick: ah

14:38 technomancy: Maybe you don't have flash installed? The first download link might be a fallback for the player that usually goes there.

14:38 technomancy: yeah, I don't have flash

14:41 SegFaultAX|work2: Is there a function to make "2" \2?

14:41 hyPiRion: get

14:41 ,(get "2" 0)

14:41 clojurebot: \2

14:42 metellus: ,(char "2")

14:42 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>

14:42 cemerick: SegFaultAX|work2: just first will do

14:42 SegFaultAX|work2: Lame. The switching between chars and strings annoys me.

14:42 (Sometimes)

14:42 rbxbx: ,(first "2")

14:42 clojurebot: \2

14:42 Urthwhyte: srs are just char vectors aren't they?

14:43 rbxbx: that feels somewhat hacky though. Not that the other solutions don't.

14:44 hyPiRion: Well, you can to .charAt

14:44 cemerick: Urthwhyte: Clojure Strings are JVM/Java Strings.

14:44 erider: is there a way to use the repl to lookup methods in java.lang.Integer

14:44 hyPiRion: ,(.charAt "2" 0)

14:44 clojurebot: \2

14:44 Urthwhyte: ahh, of course

14:44 Just started playing with Clojure a bit yesterday

14:45 gfredericks: erider: you can use the java reflections API but that can be a bit cumbersome at a repl

14:45 cemerick: erider: good code completion is a wonderful thing :-)

14:46 amalloy: erider: (clojure.java.reflect/reflect Integer), i think

14:47 but really, just use javadoc if you're at the repl - reflect is more machine-friendly

14:47 erider: ok I will try the javadoc then thanks

14:48 but I wanted to be able to use the repl like with (doc)

14:48 duck1123: ,(get "2" 0)

14:48 clojurebot: \2

14:48 cemerick: ,(->> (clojure.reflect/reflect Integer) :members (filter :return-type) (map :name) sort)

14:48 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.reflect>

14:48 cemerick: meh

14:48 ,(require 'clojure.reflect)

14:48 clojurebot: nil

14:48 cemerick: ,(->> (clojure.reflect/reflect Integer) :members (filter :return-type) (map :name) sort)

14:48 clojurebot: (bitCount byteValue compare compareTo compareTo ...)

14:49 cemerick: erider: You could put that in a function somewhere if you really wanted to do that regularly.

14:50 erider: cool thanks

15:05 uvtc: What's a good practice for loading some input data from a my-proj/resources/input-data.clj file within my src/my-proj/core.clj? I'm currently using `(load-file "resources/input-data.clj")`and referring to the symbols in input-data.clj directly, as if they were defined right there in my core.clj...

15:06 ... but I'm not sure I like referring to symbols that just appear out of the aether like that. :)

15:06 gfredericks: uvtc: make the file contain actual top-level data structures rather than deffing

15:07 and then use read-string or some variant thereof

15:07 perhaps also with clojure.java.io/resource to find the file

15:07 uvtc: gfredericks: which file? The input-data.clj file? It already contains top-level data structures: `(def foo 3)`...

15:07 gfredericks: uvtc: change it to {:foo 3}?

15:08 then you can merely read it instead of evalling it

15:09 uvtc: gfredericks: So, something like `(def stuff (read-string (slurp "resources/input-data.clj")))`?

15:10 gfredericks: yeah that should work

15:10 uvtc: gfredericks: thanks.

15:10 gfredericks: or if you like being silly, (->> "resources/input-data.clj" slurp read-string (def stuff))

15:10 do the 1.4 data readers imply that read-eval will be off by default eventually?

15:12 thorbjornDX: I have an easy question: how do I reload clj source files when in a repl? I've tried require and use, and (source myfunc) shows new code, but seems to run as if nothing changed. I'm getting confused :(

15:13 S11001001: thorbjornDX: (require blah :reload)

15:13 gfredericks: that's weird that source would have updated o_O

15:13 S11001001: thorbjornDX: doesn't percolate new exports to existing :users though

15:14 thorbjornDX: S11001001: okay, thanks

15:14 clojurebot: I'm no man, and she's no lady!

15:14 S11001001: gfredericks: I think it's based on file/line loc reading, not direct meta

15:14 gfredericks: ah ha

15:14 I'm sure that's the case now that you mention it

15:33 muhoo: there has got to be a better way to do this: https://www.refheap.com/paste/4744

15:34 amalloy: ((useful.fn/knit keyword identity) (.split #" = " l))?

15:37 muhoo: amalloy: thanks!

15:37 pandeiro: that useful lib is pretty cool

15:37 i started studying it last night

15:39 * nDuff is disappointed that max requires a number as opposed to working on any sequence of Comparable items

15:40 muhoo: ah, juxt would work there too

15:41 cemerick: nDuff: (first (sort …))?

15:41 amalloy: &(doc max-key)

15:41 lazybot: ⇒ "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest."

15:42 amalloy: i suppose you're right that Comparable would be more general, and i'm sure haskell does it that way. i imagine max uses numbers so that it can use jvm primitives

15:45 cemerick: (max "b" "c" "a") => "a" feels too much like PHP bad juju to me.

15:46 lynaghk: cemerick: re: your tweet; have you seen https://github.com/edgecase/dieter

15:46 cemerick: lynaghk: oh, I had not!

15:46 lynaghk: cemerick: I keep wanting some unified thing that will handle HAML+SASS in JVM world, but like you I keep restraining myself

15:47 cemerick: I've never used it, but it looks like it'd be a good starting point if I ever want to bite the bullet and say goodbye to "bundle exec".

15:47 cemerick: lynaghk: so assume I'm an idiot (hah!), and explain why dieter isn't that?

15:47 uvtc: ,(max "a" \b "c")

15:47 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number>

15:47 jowag: muhoo: (update-in (clojure.string/split l #" = ") [0] keyword)

15:47 uvtc: ,(int \b)

15:47 clojurebot: 98

15:47 amalloy: cemerick: meh. that's just guilt by association; max can perfectly reasonably be typed to accept Comparable. in haskell it's max :: (Ord a) => a -> a -> a

15:47 muhoo: jowag: rock star

15:48 lynaghk: cemerick: oh, it might be. I'm a precompile everything-in-advance kind of guy, and dieter looks like middleware

15:49 cemerick: before clojure I used quite the elaborate haml+sass+Jammit custom Rakefile getup. Now I just use guard and don't worry so much about asset optimization because almost all of Keming's projects are for our client's internal use

15:50 amalloy: in java it'd have to be something dreadful like: public static <T extends Comparable<? super T>> T max(Collection<T> coll)

15:50 mattmoss: oh boy that looks fun

15:50 muhoo: because i am insane, i'm doing embedded development on a beaglebone with clojure. all looks well except nrepl keeps timing out

15:51 cemerick: lynaghk: I may need to investigate it further. I definitely want something that's live, and something that'll play nice with cljs, too.

15:51 Might need to lower expectations :-P

15:51 muhoo: Sounds very cool. Does it time out after some period of time, or straight away?

15:51 muhoo: after a few minutes

15:52 cemerick: hrm, that's interesting

15:52 muhoo: if i'm doing stuff. remember, it could take a minute for a form to compile

15:52 java 97% CPU

15:52 cemerick: muhoo: which client?

15:52 muhoo: nrepl.el

15:53 i'm ssh tunnelling. i'll have to try it without ssh, and also sniff the wire and see what's going on.

15:53 but thanks for nrepl! i

15:53 lynaghk: cemerick: what's with the live-recompile requirement? I mean, things like SASS are handwritten by humans, so they should only have to be compiled once after changes, no?

15:54 cemerick: lynaghk: Yeah, but do I want to switch to the console after twiddling a file?

15:54 I suppose if I can kick off a recompile through the REPL, then that'd be acceptable.

15:56 muhoo: I don't have any thoughts off the top of my head re: the timeouts. Let me know if you run into anything I can help with.

15:56 lynaghk: cemerick: yeah. definitely have some autoreload. I just mean it should be in a lein plugin (like lein cljsbuild) rather than in the architecture of the compiler itself (e.g., compiler only works as ring middleware).

15:57 cemerick: ah, sure

15:57 I still haven't started using cljsbuild, so we'll see how that mixes in.

15:58 weavejester: IMO things like SASS and Clojurescript would be best dealt with by caching middleware rather than external processes.

15:58 cemerick: Both have their place, I think.

15:59 e.g. if you're hoping to wrap up a war, then compiling SASS at runtime is a no-go.

15:59 weavejester: Hm? Why?

16:00 cemerick: Well, assuming you don't want to make sure you have a ruby stack around, etc.

16:00 weavejester: Oh, right.

16:00 cemerick: SASS will probably work with JRuby, but…

16:00 weavejester: I'd forgotten SASS was Ruby.

16:00 cemerick: someone's got to actually wire that up.

16:01 weavejester: LESS and Clojurescript are both Javascript though, and can be compiled with Clojure

16:01 lynaghk: cemerick, weavejester: I'm biased as a clientside-app guy, but if everything is static (i.e., you can compile in advance) then you can use awesome things like S3 and, um, rsync.

16:01 emezeske: weavejester: I run my cljs web app on google app engine, which does not have access to local files, so it's not possible to run the ClojureScript compiler there

16:01 weavejester: I know other cloud providers have similar restrictions

16:01 cemerick: There's also something to be said for having a known-good binary; an oddball environment problem could botch your compilation, etc.

16:02 emezeske: weavejester: Plus, I don't want to run a compiler as part of my production server (for dev I think middleware is great)

16:02 pandeiro: weavejester: are the instructions for better indentation for compojure macros on the wiki current?

16:02 weavejester: lynaghk: You could do that anyway, I think.

16:03 pandeiro: it's not working for me when i include that code in my my-clojure.el which gets called in init.el

16:03 cemerick: I think both LESS and Sass are unfortunate; I'm mostly being led around by the nose by Foundation.

16:03 weavejester: pandeiro: They're what I use in my init.el

16:03 lynaghk: cemerick: SASS is a lifesaver compared to writing plain CSS. Also you can use things like Compass, which are great as soon as you need to start using vendor prefixes.

16:03 pandeiro: weavejester: let me move them to init.el and test... do you use clojure-mode btw?

16:03 weavejester: pandeiro: Yep

16:04 akhudek: In my experience compiling everything before hand is a must.

16:04 Deploying as a war or jar is just too useful to give up.

16:04 arohner: cemerick: lynaghk: we use dieter. it's immature, but it kinda works for now

16:04 cemerick: heh "kinda works"

16:04 Raynes: cemerick: We're like legendary and stuff.

16:04 pandeiro: weavejester: define-clojure-indent is undefined for some reason... any idea what i do?

16:04 weavejester: You can still deploy as a war or a jar if you compile dynamically. Just have the files as resources and cache the compiled results.

16:05 Raynes: We should co-host that thing.

16:05 weavejester: pandeiro: How did you install clojure-mode? Through marmalade/packages?

16:05 Raynes: Or not. Mostly not.

16:05 cemerick: lynaghk: The concept is great, but mucking around with js and ruby-based preprocessors really harshes my buzz. :-P

16:05 arohner: oh, and rhino is incredibly slow, for the JS compilation. we're working on packaging v8 as a jar.

16:05 cemerick: (Leaving aside syntactic quibbles, etc)

16:05 pandeiro: weavejester: yep

16:06 cemerick: Raynes: I thought it came out great :-)

16:06 akhudek: weavejester: but what do you gain by compiling dynaically?

16:06 xeqi: cemerick: do you keep d/l or listening stats for mostlylazy?

16:06 weavejester: pandeiro: Did you (require 'clojure-mode) before (define-clojure-indent …)?

16:06 akhudek: I understand that watch mode is nice for dev, but I can't see a point for production

16:06 pandeiro: weavejester: ah i think maybe it only loads clojure-mode conditionally

16:06 cemerick: xeqi: There's ~500 subscribers last I looked.

16:07 weavejester: akhudek: Why have two different systems for dev and production?

16:07 lynaghk: cemerick: you might find the Gemfile and Guardfile and such in this repo useful: https://github.com/lynaghk/vcf

16:07 weavejester: pandeiro: I'll edit the wiki page to include the (require 'clojure-mode)

16:07 lynaghk: it's pretty standard setup for our projects; SASS+HAML for CSS and HTML, plus guard for auto reload and such.

16:08 pandeiro: weavejester: cool, i never explicitly require clojure mode. i will do that in my-clojure.el and then add the indent code below it. thanks a lot

16:09 XPherior: Howdy folks. I wrote a library for generating test data based on abstract specifications. Hope someone finds it useful :) https://github.com/MichaelDrogalis/zombie

16:09 weavejester: pandeiro: My fault really; I forgot I needed to mention that.

16:09 My view on precompiling is that if dynamic compiling is good enough for Clojure, it's good enough for everything else ;)

16:10 It's also nice to have dev mode as close to production as possible.

16:10 borkdude: does autocomplete already work in lighttable?

16:11 ohpauleez: weavejester: playing devil's advocate - in one case you're optimizing for developer happiness, in another case your' optimizing for user happiness

16:11 re: one for dev one for prod

16:11 cemerick: weavejester: If Sass, etc. were implemented in a straightforward JVM library, I'd probably agree.

16:11 akhudek: weavejester: dynamic compiling isn't always good enough for clojure. We have a command line clojure app that we completely AOT compile.

16:12 Ironically, the app itself is a compiler.

16:12 Also, the problem was startup time.

16:12 Not a big deal for web stuff though.

16:12 weavejester: ohpauleez: User happiness is just speed, right? Which for compiled code means just a good cache. You don't even need to worry about expiring it.

16:13 emezeske: weavejester: Hitting a URL in a clojure webapp that requires clojure compilation adds milliseconds to the request time

16:13 weavejester: Hitting a URL that requires clojurescript compilation could add 30 seconds easily (for advanced mode)

16:13 weavejester: cemerick: Yeah, I might not do it with Sass, but I might for Clojurescript and LESS

16:13 emezeske: weavejester: So you have to worry about sending warmup requests to those servers before they serve users, etc

16:14 weavejester: emezeske: Yes, but you can cache, and precompile on the initialization function.

16:14 emezeske: weavejester: Right, I'm just pointing out that you are essentially just precompiling your code in prod anyway

16:15 weavejester: Thereby negating any benefits of having it as a middleware (other than "it's the same as in dev")

16:15 weavejester: emezeske: Oh, absolutely. It's the same effect, but it means you don't need separate tools.

16:15 emezeske: And reload middleware and so forth will work with it.

16:16 pandeiro: how can i quickly eval a app.repl namespace with utility functions when i begin my SLIME repl?

16:16 (i don't really want them to be namespaced, i just want them available in user>)

16:16 ...along with basic things like (use 'clojure.repl)

16:16 emezeske: weavejester: Sure. I don't think it's a terrible idea, I just want to point out why someone might choose not to do it.

16:17 weavejester: emezeske: It's not going to be for everyone, I agree. And it's not going to work with all libraries.

16:17 arohner: pandeiro: (in-ns 'user) (use 'foo.bar)

16:18 amalloy: use the lein2 :user profile, right?

16:18 ohpauleez: weavejester: Assuming user happiness is just speed is unrealistic. If your only quality attribute is latency sensitivity, you have it easy. I often find there are tangible requirements for reliability, dependability, availability, maintainability. Removing moving pieces, pushing for static solutions (ie: macro-level immutability) is often an easy way to achieve these things

16:19 and allows you to push all things static to a CDN

16:19 buying back the latency guarantees

16:19 pandeiro: amalloy: haven't used the profiles yet, i will look into that; arohner: thanks, still doesn't load everything, ie (use 'clojure.repl) that is inside 'foo.bar

16:20 ohpauleez: but, I'm just playing the advocate here, I've rolled both systems before

16:32 pandeiro: could anyone point me to an example of using lein2 profiles for auto-loading code into a slime repl session? is that a use-case?

16:38 nbeloglazov: pandeiro: this is my profile: https://www.refheap.com/paste/4750 I use injections for autoloading

16:49 pandeiro: nbeloglazov: awesome, thank you.. where could i have learned about this :injections key??

16:49 lazybot: pandeiro: Definitely not.

16:50 technomancy: is anyone using java 7 because they need specific features, or is it more just because it's the latest version?

16:50 nbeloglazov: pandeiro: from here https://github.com/technomancy/leiningen/blob/master/sample.project.clj

16:59 S11001001: technomancy: symlinking!

17:01 technomancy: S11001001: for a production app?

17:05 S11001001: technomancy: might have been handy for leiningen before local-repo-classpath

17:07 amalloy: technomancy: forkjoin, right?

17:08 technomancy: amalloy: that's been backported though IIRC

17:08 amalloy: sure, there's a jsr for it

17:08 or whatever the verbiage is; a jar that works in jre 6

17:08 also there must be people using it because they want try-with-resources

17:10 xeqi: invoke-dynamic?

17:11 S11001001: now that I can switch on strings, I don't need jvm alternatives anymore, back to Java

17:12 hiredman: technomancy: the back port just means a roughly comparable java level api, I expect forkjoin on java7 to outperform the backport

17:12 nbeloglazov: S11001001: did you often need to switch strings before?

17:13 S11001001: nbeloglazov: </sarcasm> :]

17:13 nbeloglazov: oh, stupid me :\

17:14 S11001001: You know how software reviewers sometimes say the UI "feels snappier"? And you don't believe it, and you don't believe they know what they're talking about?

17:14 I've heard that about Java 7.

17:21 akhudek: technomancy: I've just recently updated to Java 7 simply because it's the latest version.

17:23 ohpauleez: technomancy: garbage collection improvements and fork/join

17:30 SegFaultAX|work2: What's the best way to do a "get-keys" function like: (get-keys {:a "foo" :b "bar"} [:b :a]) => ["bar" "foo"]

17:30 But actually, the keys are strings, so juxt won't fit.

17:32 jkkramer: ,(map {:a "foo" :b "bar"} [:b :a])

17:33 clojurebot: ("bar" "foo")

17:33 metellus: ,(map {"a" "foo" "b" "bar"} ["b" "a"])

17:33 clojurebot: ("bar" "foo")

17:34 SegFaultAX|work2: I forgot maps were functions of their keys.

17:34 Thanks.

17:56 hyPiRion: man.

18:01 cored: hello

18:01 is there an standard way for project organization for a web app in Clojure?

18:03 technomancy: cored: not really

18:06 cored: well, I'm battling with a lot of problems with the Rails way of structuring things in the Ruby world

18:06 most web apps even when they are not using Rails are structure that way

18:06 which in most cases I don't think is right, was wondering if Clojure was the same

18:07 brehaut: cored: people structure web apps like any other program in clojure; as it demands

18:07 hyPiRion: So, can anyone explain to me what's going on here?

18:07 &(let [d (let [y (delay 0)] (delay (if (zero? @y) (/ 0 0) (/ 1 1))))] (try @d (finally @d)))

18:07 lazybot: java.lang.NullPointerException

18:07 hyPiRion: &(let [d (let [y (delay 0)] (delay (if (zero? @y) (/ 0 0) (/ 1 @y))))] (try @d (finally @d)))

18:07 lazybot: java.lang.ArithmeticException: Divide by zero

18:07 technomancy: cored: it's much less of an issue in clojure since jump-to-definition is so easy to implement

18:07 brehaut: cored: but a common small site might have a model/data ns, a routes ns and an html generation ns

18:07 technomancy: if you want to know where something is, just point to it and jump; you can follow a codebase that's much more spread out with ease

18:08 cored: brehaut: I see

18:08 technomancy: did not get the part of jump-to-definition :-)

18:09 technomancy: cored: I mean most tools support navigating the codebase with ease rather than falling back to grep

18:10 with ruby often answering "where is this defined" is tricky; with clojure it's trivial.

18:12 devinus: how would you guys do this: https://gist.github.com/3542598

18:14 cored: technomancy: get you now

18:14 metellus: devinus: I don't understand what the function is supposed to do

18:14 nDuff: devinus: ...so, it's not completely obvious from knowing your inputs and your desired outputs what the relationship between those is. Is this something like a topological sort?

18:14 cored: technomancy: oh, I thought that Clojure was also dynamic and I think that the problem with finding definitions in Ruby is because it's dynamic ature

18:15 amalloy: hyPiRion: i don't understand the NPE at all

18:15 devinus: nDuff: i read the wikipedia entry on a topological sort and i don't think it's exactly like that

18:15 nDuff: devinus: Generally speaking, an English-language problem description is more useful than a code on.

18:15 devinus: but it sounds a lot like that

18:15 nDuff: s/on/one/

18:16 technomancy: cored: no, it's hard in Ruby because Ruby is dynamic *and* object-oriented *and* supports monkeypatching.

18:16 devinus: nDuff: basically i have injections i need to sort and i'm prototyping it in clojure

18:16 every injection is a tuple (name, before, after)

18:16 technomancy: just using dynamic types doesn't pose any difficulties by itself

18:16 brehaut: technomancy: and doesnt require you to declare that you are introducing a name?

18:16 technomancy: that too

18:17 nDuff: devinus: ...that sounds very much like what a topological sort is good for.

18:17 cored: technomancy: but wait a sec, I think I read somewhere that you can do that in Lisp, the monkeypatching that's it and Clojure is a Lisp dialect

18:17 devinus: nDuff: i need ['a 'b' nil] to come before ['b nil nil]

18:17 nDuff: devinus: ...also like something you could use core.logic for.

18:17 brainproxy: simplest way to decode/encode a string w.r.t. base64?

18:17 devinus: i'd rather not use core.logic right now :( i can only prototype it in clojure

18:17 metellus: ,(filter identity (sort-by first [['b 'c nil] ['a 'b nil] ['d nil 'c] ['c nil nil] ['e nil 'd]]))

18:17 clojurebot: ([a b nil] [b c nil] [c nil nil] [d nil c] [e nil d])

18:17 devinus: i then have to implement it in JS

18:17 metellus: err, that filter identity is left over from something else

18:18 technomancy: cored: it's technically possible to do monkeypatching-ish things in Clojure, but it's not done in practice because people recognize the fact that it's horribly problematic

18:18 metellus: ,(sort-by first [['b 'c nil] ['a 'b nil] ['d nil 'c] ['c nil nil] ['e nil 'd]])

18:18 clojurebot: ([a b nil] [b c nil] [c nil nil] [d nil c] [e nil d])

18:18 devinus: metellus: pretend they dont sort lexigraphically

18:18 because in reality they dont

18:18 cored: technomancy: got it

18:18 devinus: a-d was prob bad symbols

18:18 to use

18:19 lexicographically*

18:19 metellus: how do they sort?

18:19 devinus: by my description

18:19 each tuple is (name, before, after)

18:20 and a tuple can't have both a before and after

18:20 that's a rule i've already built in

18:22 amalloy: devinus: so transform to name/after pairs first; having to deal with name and either before or after makes the problem harder

18:25 or perhaps mash it up into a map like '{a #{b c}, d #{e}}. then build a Comparator that looks through that map

18:25 and use that comparator in a call to sort

18:27 devinus: but can it be done in one pass?

18:34 hyPiRion: amalloy: I found an earlier issue about delays aggressively clearing locals, so I'm fairly certain that's the issue.

18:36 &(let [d (let [y (delay 0)] (delay (prn y) (if (zero? @y) (/ 0 0) (/ 1 1))))] (try @d (finally @d)))

18:36 lazybot: java.lang.NullPointerException

18:47 TimMc: Well. That was irritating.

18:48 Apparently Tor relays are exit nodes by default. Got klined by freenode for the day. >_<

18:50 amalloy: TimMc: you must have had an unusually productive day

18:51 also: my non-exit tor node worked great for a month, and now doesn't seem to want to turn back on

19:13 TimMc: amalloy: It's true, I did!

19:15 azkesz: Can I have the following without using (force nn) but just nn? (def nn (delay (let [ff (future (do (Thread/sleep 2000) (println "done")) 100)] (do (println "main done") @ff) )))

19:17 andersf: anyone familiar with net.cgrand.regex? how would i go about matching a union of character sets?

19:23 azkesz: can I have a variable that evaluates only when first used? without having to dereference it or use force on it?

19:23 andersf: found it; net.cgrand.regex.charset/+ if anyone should care..

19:34 azkesz: ok i can only do it with macro but then I have to call it as a function ie. (nn), is there something like lazy variable like lazy-seq?

19:36 ohpauleez: azkesz: You could just use promises

19:36 typically in clojure, the type of interaction you're looking for comes from deref'ing

19:36 azkesz: is it possible to see the last element of a lazy sequence, as it is (assuming it's a call to a function) i imagine an infinite lazy sequence which had like 10 elements evaluated and the 11th is the one i want to see like an expand macro sort of thing?

19:37 ohpauleez, ok i'll check

19:37 dnolen: azkesz: you will still need to deref even w/ promises.

19:37 amalloy: see clojure.tools.symbol-macrolet though

19:38 azkesz: dnolen, it's ok I guess, I just wanted to know if it's possible to do just nn instead of @nn and have the same effect(delayed evaluation)

19:38 amalloy: (let [x-delayed (delay (println 1))] (symbol-macrolet [x `@x-delayed] (foo x)))

19:38 or something roughly like that; i don't recall the syntax

19:39 azkesz: amalloy, where should I look for clojure.tools.symbol-macrolet ?

19:39 amalloy: er, clojure.tools.macro/symbol-macrolet

19:40 xeqi: can you change lein-cljsbuild to use target/out/ instead of out/ for compiling?

19:40 azkesz: found it, https://github.com/clojure/tools.macro/

19:41 ,(macroexpand-1 (take 1 (range)))

19:41 emezeske: xeqi: You can change that with the clojurescript compiler's :output-dir option

19:41 clojurebot: (0)

19:41 emezeske: xeqi: It's not specific to lein-cljsbuild, but you can change it with that too: https://github.com/emezeske/lein-cljsbuild/blob/master/sample.project.clj#L101

19:42 xeqi: emezeske: hmm, I have an out/ and a .lein-cljsbuild-compiler-0/, let me remove them and see which one comes back

19:44 emezeske: I must of done something weird before, now I only have the .lein-cljsbuild-compiler-0/ which is good enough

19:44 thanks

19:45 emezeske: xeqi: Good deal!

19:54 azkesz: how can I make 'let' not deref my future here? (def nn (let [ff (future (do (Thread/sleep 2000) (println "done")) 100)] (println "main done") ff))

19:54 ,(def nn (let [ff (future (do (Thread/sleep 2000) (println "done")) 100)] (println "main done") ff))

19:54 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

19:54 azkesz: ,(let [ff (future (do (Thread/sleep 2000) (println "done")) 100)] (println "main done") ff)

19:54 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

19:57 azkesz: oops, nvm I'm missing something else,

19:57 rlb: denied from the sandbox -- sniff...

19:57 amalloy: rlb: you can play in the sandbox if you want. but stay away from the sanbox

19:58 azkesz: I see that even this will cause the future to be executed: (def nn (future (do (Thread/sleep 2000) (println "done")) 100))

19:58 I thought it will only do so when dereferenced, @nn

19:58 tomoj: would it be possible to set up a binding for one of your own vars in a repl session?

19:58 nrepl middleware maybe?

19:59 (doc future)

19:59 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block, unless the variant of deref with timeout is used. See also - realized?."

19:59 azkesz: ok then it's the do

19:59 tomoj: maybe you want delay?

20:00 azkesz: well i misunderstood future, for starters:)

20:01 I thought it was doing the eval on the first deref

20:01 tomoj, you're right but then I have to use force

20:01 tomoj: @ works too

20:02 devth: anyone know of a lib to execute a fn at specific times (e.g. noon every M-F)?

20:02 azkesz: tomoj, awesome

20:02 amalloy: cron

20:02 SegFaultAX|work2: Am I wrong for hating that in the stdlib, the parameters to a function go on a new line?

20:02 casion: devth: why not use your os's facilities for this task?

20:02 tomoj: azkesz: delay doesn't start a new thread though, unlike future

20:03 SegFaultAX|work2: (defn foo [a b] looks so much nicer than (defn foo\n[a b] IMHO

20:03 devth: sure, but is there an existing interface to cron from clj?

20:03 azkesz: tomoj, yes I figured... but at least I know that i misunderstood future:)

20:04 devth: found some old clj-sys and cron4j so far

20:05 it's from within a chatbot, so it's already running 24h/day

20:10 azkesz: thanks guys: tomoj, amalloy, dnolen, ohpauleez

20:10 ohpauleez: no problem! I hope you found something that worked for you

20:12 * Sgeo needs to ponder how to make a useful letrec

20:12 SegFaultAX|work2: I'm really addicted to 4clojure right now.

20:12 Sgeo: The reverse state monad relies on laziness

20:14 SegFaultAX|work2: Sgeo: Is declare lexically scoped?

20:14 Sgeo: ,(doc declare)

20:15 clojurebot: "([& names]); defs the supplied var names with no bindings, useful for making forward declarations."

20:15 SegFaultAX|work2: Sgeo: It doesn't say. But if it is could you use it to forward declare your let bindings?

20:16 I'm struggling with how you'd implement letrec.

20:16 ,(let [foo #(add1 %) add1 #(+ % 1)] (foo 1))

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

20:17 SegFaultAX|work2: ,(let [foo #(add1 %) add1 #(+ % 1)] (add1 1))

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

20:17 amalloy: &(doc letfn)

20:17 lazybot: ⇒ "Macro ([fnspecs & body]); fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body."

20:18 Sgeo: But they have to be function specs :/

20:18 SegFaultAX|work2: Is letfn not deprecated?

20:18 Sgeo: Maybe I want recursively defined lazy sequences or delays or something

20:19 SegFaultAX|work2: Sgeo: Just use mutually recursive functions.

20:23 ,(letfn [(foo [n] (lazy-seq (cons n (bar (inc n))))) (bar [n] (lazy-seq (cons n (foo (inc n)))))] (take 10 (foo 1)))

20:23 clojurebot: (1 2 3 4 5 ...)

20:34 erider: ,([1 2 3 4 5] 3)

20:34 clojurebot: 4

21:00 gfredericks: does cljs support (:require foo :refer [...])?

21:06 dnolen: gfredericks: I don't think it supports that, but it does support the :refer ns directive

21:07 tomoj: I thought :require/:refer was supported

21:07 but it's (:require [foo :refer [...]])

21:14 gfredericks: I'm having issues with namespaces being written to the output JS file out of order

21:14 how would I debug such a thing?

21:17 dnolen: gfredericks: this sounds like a problem others have encountered

21:17 gfredericks: oh nevermind. I remembered that when I've seen this before it helps to restart lein-cljsbuild

21:17 and that worked

21:17 dnolen: gfredericks: let me know if that doesn't work

21:18 gfredericks: dnolen: sorry for the quasi-false alarm

21:30 tomoj: cemerick: is it possible to get extra bindings into the session with an nrepl middleware?

21:33 besides creating a changed copy of the session middleware..

21:34 oh, I think I see how

21:39 cemerick: tomoj: You mean default set!-able vars?

21:40 tomoj: no, project-specific set!-able vars

21:41 cemerick: Nothing comes to mind immediately. Same "problem" exists with all REPLs: only vars with a dynamic binding can be set!'d.

21:42 tomoj: can you describe your use case?

21:43 oh, with a middleware!

21:43 Yeah, that's easy :-)

21:44 tomoj: writing a library involving learning experiments. most functions (currently, at least) take a first arg which has experiment hyperparameters and state

21:44 cemerick: tomoj: sorry, I didn't read your first message closely enough, I guess.

21:44 tomoj: if I don't change that I'd probably let them optionally get the experiment from a dynamic binding

21:45 but in-experiment would be more convenient at the repl than with-experiment

21:46 cemerick: tomoj: I didn't really grok that. :-)

21:48 akhudek: tomoj: could you use a -> like method to implement with-experiment?

21:48 cemerick: Anyway, a middleware that :depends on the "clone" op (so it'll be "below" the session middleware) that makes sure that any message going by has bindings in its :session for the vars you care about will work.

21:48 But, my sense is that REPL middleware is the wrong level at which to tackle this.

21:50 cjfrisz: Good night...does vimclojure-easy install vim-minibufexpl?

21:50 And why is it such a horrid plugin?

21:50 Completely interrupts a reasonable workflow

21:51 * cjfrisz will stop ranting

21:52 tomoj: cemerick: the use cases are those where you have a dynamic var in your project that you want bound to one value for relatively long periods of time in the repl

21:53 so like we have in-ns at the repl and don't have to wrap every line in (with-ns ...)

21:54 whether I should have a dynamic var for this actual use case in my project, I don't know

21:56 cemerick: tomoj: right, that's where I was about to go. alter-var-root or just an atom is easier, and probably just as effective.

21:57 No other REPL (AFAIK) currently allows for additional set!-able vars; that you *could* make it happen with nREPL maybe isn't a good enough reason to do so, though.

21:58 it certainly seems like something that could cause some degree of trouble; e.g. REPL interactions that you'd expect to work would not within a REPL environment that didn't have the middleware, etc.

21:59 tomoj: yeah, I didn't think about other people seeing the function that set!'s and not realizing some extra middleware is required

22:04 * cjfrisz almost started ranting

22:04 * cjfrisz will just sit in the corner and contentedly go back to using emacs

22:05 tomoj: I don't think I even need an atom or alter-var-root

22:08 amalloy: (inc emacs)

22:08 lazybot: ⇒ 1

22:08 cjfrisz: ~emacs

22:08 clojurebot: emacs is an out-moded belief system

22:09 cjfrisz: I think clojurebot must be broke

22:10 casion: it'd be awesome if there was some sort of modal alternative to emacs

22:10 with it's own scripting language as well

22:11 gfredericks: my vimmy coworker has become totally sold on evil-mode over the last week

22:11 hoover_damm: nice!

22:11 cjfrisz: I was trying to work on my vim chops by doing some of my Clojure stuff in it

22:11 I found the whole experience very...unpleasant

22:12 casion: when I first tried clojure, I tried in vim… despite being an emacs user

22:12 cjfrisz: Some goofy minibuffer explorer plugin got installed somehow (hell if I installed anything vim-related) and made saving and closing buffers really awful

22:12 casion: needless to say, I gave up and didnt think about clojure for a year after

22:12 cjfrisz: casion: That makes me sad

22:13 gfredericks: casion: that sounds a bit like "I installed windows so I could try out grep"

22:13 cjfrisz: casion: stock vim is *reaaly* *bad* at Lisp

22:13 Khaoz: Hi. I'm learning clojure through some online beginners tutorials, but i want to buy a book to complement my studies. I'm between Programming Clojure and Cojure Programming.

22:13 casion: Khaoz: do you know any other languages

22:14 uvtc: 10 minutes of Vim and I'm accidentally putting ":wq" all over the place for the rest of the day.

22:14 casion: cjfrisz: yep. I use vim sometimes without issue… for C, and that's about it

22:14 cjfrisz: I cut my teeth on emacs, but I can certainly appreciate how compact the controls are

22:14 And how lightweight it is

22:14 Khaoz: casion: i have some skills with java (i need java on my soa day job :) ) and also some knowledge on python and perl

22:14 casion: I've been using emacs for a good while, and never touched lisp until clojure

22:15 cjfrisz: But I spend 95%+ of my time writing lisp variants

22:15 casion: Khaoz: get clojure programming then IMO

22:16 it has some examples in python, and assumes more java knowledge than programming clojure I think, which gets you going a bit faster

22:16 that's assuming you have the prerequisite knowledge to work with it

22:16 Khaoz: I think that i have

22:17 i'm a programmer since 99

22:17 casion: Khaoz: and the author(s) here right now

22:17 so you could always just ask directly

22:20 Khaoz: casion: thank you very much

22:20 casion: sure, they're both awesome books

22:20 Khaoz: my kindle have a new book on in :)

22:20 casion: yeah, I have both on my dx (and paper)

22:20 it's pretty fantastic

22:20 Khaoz: my main problem are with expressions like ^{:a 1 :b 2} [1 2 3]

22:21 casion: if you have a smaller kindle, programming clojure doesnt display very well

22:21 errr

22:21 clojure programming doesnt.

22:21 Khaoz: i want to compare this kind of thing with other languages

22:21 casion: programming clojure looks good on the small kindle

22:21 Khaoz: but well, i will finish the beginning guides. Probably i will get a better picture about everything

22:24 and about my kindle, it's a 6", so it's small.

22:24 tmciver: Khaoz: it's not the size that matters, it's how you use it. ;)

22:25 Khaoz: casion: but thank you again. Probably i will get both.

22:25 casion: great idea :)

22:25 Khaoz: tmciver: hahahahahhahahaha

22:25 casion: fwiw though, reading clojure programming on the 6" kindle is nearly impossible

22:25 there's times where you'll end up with 3-4 consecutive pages with code cut across a page

22:26 I had to reformat it with calibre

22:26 uvtc: There's a neat bit of styling for Scheme code blocks in html that I've seen on the Chicken wiki: http://wiki.call-cc.org/man/4/faq#how-can-i-add-compiled-user-passes . Hover the mouse over the parens in the code example.

22:28 Auto-electric paren matching? Need to look into how that's done. Would be neat to have that for Clojure snippets.

22:29 brehaut: uvtc: i had a look at trying to get something like that working with the JS SyntaxHighlighter package

22:29 but it was going to require too much mucking about in the plumbing

22:29 uvtc: Ah.

22:29 Would be very cool, IMO.

22:30 brehaut: ive seen a slightly nicer version which just highlights the characters that are in the expression under the cursor, rahter than coloring the brackets

22:30 uvtc: Oooh. :)

22:30 Can you remember/find the link?

22:31 casion: that'd be nice to have emacs

22:31 brehaut: it was over a year ago sorry

22:31 clojurebot: shut up |is| <reply>My new year's resolution is to remember that not every message with "is" in it is addressed to me.

22:31 Khaoz: It's a little bit late here in Brazil, so i'm going to sleep. Thank you guys. Hope to be able to code in clojure and contribute with something soon :)

22:31 brehaut: i think with a bit of dedication you could do just the brackets in the JS lib, it'd be a bit wonky though

22:31 casion: good luck Khaoz

22:31 cjfrisz: Anybody else wish that nREPL in emacs would do stack traces the same way as Swank?

22:31 I find it just unpleasant enough that I've kept on using Swank

22:32 casion: cjfrisz: yes! god damnit yes

22:32 I switched to nrepl.el and that is alraedy annoying me

22:33 cjfrisz: I really want to like nrepl

22:33 And I'm pretty sure that's the one thing holding me back

22:33 casion: I became quite used to it in swank-clojure, I automatically jump my hands to 1234567890 when do anything

22:33 when I do*

22:34 cjfrisz: If I remember correctly, the other aspects of it are very pleasant

22:34 casion: I'm going to try ritz tomorrow

22:34 cjfrisz: casion: I'm not familiar

22:34 amalloy: casion: emacs already has that

22:34 casion: cjfrisz: https://github.com/pallet/ritz

22:34 amalloy: has what?

22:35 amalloy: the paren highlighting, i mean

22:35 casion: amalloy: I meant the highlight coed in current statement

22:35 I know about rainbow delimiters and such

22:35 amalloy: obviously

22:35 M-x show-paren-mode

22:35 casion: that exists? hum

22:36 amalloy: and M-x customize-face show-paren-match face

22:36 plus, some kind of var to toggle whether it lights just parens or the whole xpr

22:36 personally either would drive me crazy

22:37 casion: hum

22:37 that is neat… and far more distracting thatn I expected

22:37 than you

22:37 thank*

22:37 maybe useful for browsing code, but I don't think I could live with that when writing

23:02 cjfrisz: Is it weird that 'def' returns the value of its init argument, or is does it just seems weird because it's different from Scheme?

23:05 cemerick: cjfrisz: def returns the var it is defining

23:05 Though you shouldn't be caring about return values of vars in general anyway.

23:05 s/of vars/from def

23:05 cjfrisz: cemerick: Good point

23:06 cemerick: I only care in that I'm writing a source-to-source compiler and trying to preserve semantics

23:08 cemerick: I'm just kind of used to things like 'def' returning void

23:10 dnolen: finally one of the absolutely most annoying bugs in CLJS resolved - http://dev.clojure.org/jira/browse/CLJS-180

23:10 cjfrisz: A wild dnolen appears!

23:17 tomoj: hooray

23:17 thanks

23:36 cemerick: It seems that web apps are still often built with static resources baked into each project, instead of bundled up into dependencies. Any rationale for this, since serving classpath resources is so damn easy with ring?

23:37 brehaut: cemerick: so that you can push them out to a more lightweight webserver?

23:37 (such as an nginx gateway)

23:37 * brehaut guesses wildly

23:38 cemerick: Sure, but you can pull assets from the classpath like nothing.

23:38 Why not take advantage of versioned dependencies?

23:38 brehaut: perhaps i did not understand the question

23:39 cemerick: Common practice is to download e.g. jquery vX.Y.Z, drop it into /resources/public, and serve away.

23:40 Rather than put that rev of jquery (or whatever) into a jar deployed with the right version number to e.g. an s3 maven/lein repo.

23:40 So N projects have N copies of jquery, etc. All the same downsides of putting jars into git apply AFAICT.

23:41 brehaut: right

23:41 wmealing_: so, oracle released the java patch

23:41 http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html

23:41 cemerick: For example, I started using foundation; so, I get my build of it, drop it into /resources/asset-deps/ of a new project, stamp it with v3.0.9-1 (the -1 so I can version my custom builds of the framework), and deploy to my s3p repo.

23:42 wmealing_: known about it for 4 months.. now only releases

23:42 cemerick: Then I just add a route to my app: (route/resources "/" {:root "asset-deps"})

23:42 Frozenlo`: After zyzanie https://github.com/Frozenlock/zizanie, here comes siren! https://github.com/Frozenlock/siren !!

23:42 cemerick: And any other static assets I have on my classpath under that asset-deps prefix get served automagically, and bumping the rev is easy as a project.clj edit.

23:43 Frozenlo`: I'm starting to like cljs :D

23:43 dnolen: Frozenlock: glad to hear it

23:43 Frozenlock: dnolen: I could not have done without your help, of course :P

23:44 *it

23:44 * cemerick just trying to figure out if there's a rationale to the practice, or if it's just hard-won habit

23:44 xeqi: 1) it's easier to drop in the file then jar it; 2) seting up a server to serve static files without hitting the whole web stack is easier than something like varnish

23:45 brehaut: cemerick: well, i know that nginx serving static files is bloody fast, vs forwarding the request to my jvm http server to then run through ring, resources handling, and back out

23:46 cemerick: i do horrible dropping built JS blobs into git because its easy, even though its horrible

23:47 cemerick: but surely you could easily make a lein build process that produes static resources based on project.clj deps and puts them outside of the jvm server

23:47 cemerick: brehaut: quite, yes

23:48 xeqi: "it's easier to drop the jar file in git than to put it in a repo" :-)

23:48 xeqi: never said they were good reasons

23:48 cemerick: heh

23:48 fair enough

23:49 Even if/when I have a site that needs a CDN, etc., I sure don't want to have a separate deployment process for assets. Let the proxy/CDN come to you for the files.

23:50 devn: 'lo

23:51 brehaut: cemerick: that does make sense

23:52 cemerick: whats stopped me is the 101 shitty tools for building various resources that arent hosted in the JVM

23:54 cemerick: fair point

23:54 back to the WTF Sass et al. thread :-P

23:54 brehaut: i guess it depends how sharp your yak razor is ;)

23:54 ha yes

23:55 cemerick: ah, ok

23:56 brehaut: sass and less are both just better kinds of horrible unfortunately

23:56 cemerick: brehaut: so if you're using Sass and such, you're probably trying to gather *everything* up into the "top level" of your app in terms of assets, so that js and css minifiers can create a minimum of prepared files.

23:56 brehaut: right

23:57 cemerick: i.e. the more modular asset dependencies are, the harder it is to get everything into place for the command-line-based toolchains

23:59 hah, right, so e.g. Foundation vendors jquery and modernizr into its repo, so if you were rolling it into your Sass compilation, you wouldn't have separate deps for those libraries anyway

23:59 brehaut: ha

23:59 (inc modernizr)

23:59 lazybot: ⇒ 1

Logging service provided by n01se.net