#clojure log - Nov 12 2010

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

0:05 replaca: KirinDave: it seems that the consensus is that deftype and defrecord completely subsume defstruct

0:08 KirinDave: I thought so

0:08 Just wanted to make sure.

0:08 I'm doing a brief history of clojure OO for The Book.

0:12 TheBusby: Er, is their a simple/standard way to convert a string into a Clojure numeric?

0:15 scgilardi: TheBusby: one simple way is (read-string "300")

0:15 TheBusby: scgilardi: that's perfect thank you!

0:16 scgilardi: you're welcome

0:18 technomancy: even before defrecord there was hardly a reason to use defstruct

0:20 KirinDave: technomancy: I'm only mentioning it in a sidebar.

0:20 technomancy: sounds good; mostly of historical interest

0:24 LauJensen: Good morning all

0:24 amalloy: morning LauJensen

1:31 ppppaul: ~#90

1:31 clojurebot: 90. Computation has made the tree flower.

1:31 ppppaul: ~#89

1:31 clojurebot: 89. One does not learn computing by using a hand calculator, but one can forget arithmetic.

1:32 ppppaul: ??

3:00 bartj: , (doc fmap)

3:00 clojurebot: It's greek to me.

3:00 bartj: &(doc fmap)

3:00 sexpbot: java.lang.Exception: Unable to resolve var: fmap in this context

3:00 amalloy: $source fmap

3:00 sexpbot: Source not found.

3:00 amalloy: hrm

3:01 ~source fmap

3:01 wtf guys

3:01 bartj: gah, fmap doesn't preserve the structure!

3:01 you guys are lying the documentation

3:01 amalloy: bartj: what do you mean?

3:01 bartj: (fmap #(* 10 (first %)) {:a [1] :b [2] :c [3]})

3:01 I was expecting this: {:a [10] :b [20] :c [30]}

3:02 amalloy: bartj: how on earth could fmap know to do that?

3:02 it knows it got [1] as an argument, and you gave it 10 as a result

3:02 bartj: the documentation says it preserves the structure

3:02 hmm

3:02 amalloy: yeah, it preserves the map

3:02 bartj: you mean the keys of the map?

3:03 amalloy: the keys, and makes sure they still match with the same transformed values

3:03 but what you do to the values is your business

3:03 anyway (fmap (comp vector #(* 10 %) first) {:a [1] :b [2] :c [3]})

3:05 bartj: amalloy, hmm

3:05 amalloy: if fmap faithfully reproduced the structure, which conceivably it could, how would i turn {:a [1]} into {:a 1}?

3:06 bartj: ok, it leaves the transformation of the values to the user

3:06 thanks!

3:06 amalloy: right

3:06 enjoy!

3:06 bartj: one more thing: is there a function which does (complement nil?)

3:06 I want to check that a value is not nil

3:06 and I don't want to do a (complement nil?)

3:07 amalloy: do you care if it's false?

3:07 that is: do you want it to return true or false when given false as the input

3:07 bartj: the values are generally strings only

3:08 amalloy: then the function you're looking for is identity :P

3:08 &(keep identity ["str" 1 nil :a])

3:08 sexpbot: ⟹ ("str" 1 :a)

3:09 bartj: ,(doc keep)

3:09 clojurebot: "([f coll]); Returns a lazy sequence of the non-nil results of (f item). Note, this means false return values will be included. f must be free of side-effects."

3:10 amalloy: bartj: (keep f s) is basically (filter identity (map f s))

3:10 or i guess, (remove nil?), since apparently it includes false

3:10 bartj: or (remove nil? collection) is easier :)

3:11 amalloy: sure. but i'm demonstrating identity for you

3:11 bartj: to remove the nil IMO

3:11 oh ok!

3:11 amalloy: if you just want to drop nils from a seq, i'd use filter identity, personally

3:11 but there's nothing wrong with remove nil?

3:19 ppppaul: can someone give me suggestions for extracting strings from strings in clojure?

3:20 do i have to do java interlop?

3:20 amalloy: ppppaul: um, it depends on what you mean by "extracting strings from strings". what's an example of what you want to do?

3:21 ppppaul: "abcd" -> "ab"

3:21 (apply str (take 2 "abcd"))

3:21 bartj: , (apply str (take 2 "abcd"))

3:21 amalloy: clojure.string probably has that, though the interop is really easy too

3:21 clojurebot: "ab"

3:22 ppppaul: in this case, using apply isn't helping to make my code understandable

3:22 amalloy: &(clojure.string/take 2 "abcd")

3:22 sexpbot: java.lang.Exception: No such var: clojure.string/take

3:22 ppppaul: clojure.string has some nice stuff for splitting and replacing... but i want subsections

3:22 amalloy: (use 'clojure.string)

3:23 &(require 'clojure.string)

3:23 sexpbot: ⟹ nil

3:23 amalloy: &(clojure.string/take 2 "abcd")

3:23 sexpbot: java.lang.Exception: No such var: clojure.string/take

3:23 amalloy: bah

3:23 ppppaul: take is not in string

3:23 it's in core

3:23 amalloy: oh. i'm looking at clojure.contrib.string

3:23 &(require 'clojure.contrib.string)

3:23 sexpbot: ⟹ nil

3:23 ppppaul: oh

3:23 maybe i should look there too

3:23 amalloy: &(clojure.contrib.string/take 2 "abcd")

3:23 sexpbot: ⟹ "ab"

3:23 ppppaul: nice

3:23 :D

3:24 bartj: ppppaul, http://richhickey.github.com/clojure-contrib/string-api.html has a whole lot of string functions

3:25 ppppaul: bartj, replace 'richhickey' with 'clojure' for he updated site

3:25 i'm looking at it now... has tons of sexy string stuff :D

3:25 bartj: hmm, ok!

3:27 tWip: what's the deal with clojurebot sending weird private messages?

3:27 by weird, I mean unsolicited, like "Huh?"

3:28 amalloy: tWip: i've never seen him do that. private messages?

3:28 tWip: or are they channel notices or something similar

3:29 amalloy: tWip: are they going to you personally, or to the channel in general?

3:29 Raynes: I've never seen him PM somebody with an odd message. I imagine that would be a bug.

3:29 tWip: perhaps it's a bug in irccloud, as I don't remember getting them with irssi

3:31 ppppaul: clojurebot sending me oppressive messages is a bug?

3:31 Raynes: ppppaul: Sending them in PM would probably be a bug. Not the messages themselves. He's always sent random messages when people say certain things.

3:32 ppppaul: i think the 8ball is broken

3:32 amalloy: Raynes: apparently it's not just certain things. hiredman specifically has him respond to 0.5% of messages

3:32 Raynes: How could it possibly be broken? :p

3:32 ppppaul: ~8ball is the 8ball broken?

3:32 clojurebot: Pardon?

3:32 amalloy: $8ball is this working?

3:32 sexpbot: amalloy: Yes.

3:32 ppppaul: $8ball is the 8ball broken?

3:32 sexpbot: ppppaul: Yes.

3:32 ppppaul: there

3:32 proof

3:33 Raynes: Yep, that solves it.

3:33 ppppaul: anyway, i would like to propose a fortune cookie feature

3:34 Raynes: $fortune

3:34 sexpbot: I have no fortune cookies. Please feed me some!

3:34 Raynes: $addfortune You will yawn in 5 seconds.

3:34 ppppaul: $fortune

3:34 sexpbot: Fortune cookie eaten.

3:34 You will yawn in 5 seconds.

3:34 ppppaul: $addfortune one day sexpbot will have a large fortune database

3:34 sexpbot: Fortune cookie eaten.

3:35 ppppaul: $addfortune sometimes the 8ball is wrong.

3:35 sexpbot: Fortune cookie eaten.

3:36 rpierich: anyone wish to chat?

3:38 ppppaul: is this a chatting room?

3:38 rpierich: i'm not sure

3:38 ppppaul: & (#(% %) #(% %))

3:38 sexpbot: java.lang.StackOverflowError

3:39 ppppaul: $8ball is this a chatting room?

3:39 sexpbot: ppppaul: Very doubtful.

3:39 ppppaul: well then...

3:39 wanna chat about monads?

3:39 rpierich: what is a monad?

3:40 ppppaul: it is a way to represent a change in state using functions

3:40 i think

3:40 i could be wrong

3:40 Raynes: You are.

3:42 ppppaul: enlighten me

3:43 amalloy: they're like burritos

3:43 $google monad burritos

3:43 sexpbot: First out of 200 results is: Code To Joy: Monads are Burritos

3:43 http://codetojoy.blogspot.com/2009/03/monads-are-burritos.html

3:43 ppppaul: wow

3:43 should i eat them?

3:43 Raynes: Only if they're poisoned.

3:45 ppppaul: poisoned with smaller burritos?

3:46 (ns rosettacode.align-columns

3:46 (:require [clojure.contrib.string :as str])) i made a mistake, but my code is similar to the clojure documentation at http://clojure.org/libs

3:47 what do?

3:48 did i make a tpyo/

3:48 Raynes: What is the problem?

3:49 ppppaul: str.take doesn't work

3:49 Raynes: str/take

3:49 ppppaul: oh shit

3:49 Raynes: Also, clojure.contrib.string = clojure.string now.

3:49 ppppaul: really?

3:49 amalloy: Raynes: no

3:50 Raynes: amalloy: maybe

3:50 amalloy: clojure.string has a lot less stuff

3:50 Raynes: My statement isn't really incorrect though.

3:50 Some of it was moved over.

3:51 I /did/ use = and not identical?, so yeah. Sue me.

3:51 amalloy: Raynes: (not= #{1 2 3 4 5} #{1 2})

3:51 Raynes: We can't be friends anymore.

3:52 amalloy: &(boolean "amalloy and Raynes are friends")

3:52 sexpbot: ⟹ true

3:53 ppppaul: lol

3:54 i now have a padding function!

3:54 extra padding

3:55 Raynes: *cough*format*cough*

3:56 ppppaul: indeed

3:56 oh

3:56 oh

3:56 looking that up now

4:00 woah, format is big

4:00 Raynes: $source format

4:00 sexpbot: format is http://is.gd/gXJXY

4:03 ppppaul: format doesn't seem to do center justification

4:20 noidi: is there a built-in function like (fn [a b] (if-not (nil? a) (cons a b) b))

4:21 I seem to need something like that quite often when using recursion and destructuring

4:23 amalloy: noidi: do you need to cons it right away, or are you building something up lazily?

4:24 ppppaul: what would be a good way of going about adding meta data to a string?

4:24 esj: morning all

4:24 noidi: amalloy, right away. I'm doing macro-like stuff (only in a function).

4:24 I think I'll just write that little helper

4:25 ppppaul: $8ball morning?

4:25 sexpbot: ppppaul: Without a doubt.

4:26 amalloy: noidi: i'm not at all convinced that macro-y stuff is related to non-laziness

4:26 Chousuke: ppppaul: you can't add metadata to strings.

4:29 ppppaul: i know i can't

4:29 Raynes: Then why ask how you can?

4:29 ppppaul: which is why i'm asking about a good way to do so... should i use records or lists or lambdas?

4:30 noidi: my function takes a vector defining a list of things [:foo :bar :baz], and each of the definitions may be followed by one or two optional arguments [:foo, :bar [...], :baz [...] {...}]

4:30 amalloy: ppppaul: maps?

4:30 ppppaul: hashmaps

4:31 noidi: right now I do this when parsing the definition (let [[a b c & rest] definition] ...)

4:31 ppppaul: i think lambdas may be the best way, cus they could return the string

4:32 noidi: the thing is, I have to cons b and c back to rest, but only if they're non-nil (which either means that there was a nil in the input sequence or the sequence ended)

4:32 maybe I'm approaching this the wrong way...

4:32 ppppaul: filter nils

4:32 nils are icky

4:33 noidi: ppppaul, hmm... true! there's no point in supporting them in the "dsl", since they contain no information.

4:35 ppppaul: (filter nil? everything)

4:35 (remove nil? everything)

4:35 i think filter does the opposite

4:40 noidi: ppppaul, thanks, everything got way easier with that :)

4:42 now I got rid of the icky cons stuff and can just do (recur ...accumulation... (concat (remove nil [b c]) rest)) in the branch that handles the case with no optional arguments (where b & c are regular elements or nils if a was the last item in the seq)

4:42 ppppaul: :D

4:50 i want to return 0 when an exception happens in the below code... i get a cast error right now

4:50 (try

4:50 (count (nth % n))

4:50 (catch Exception e (eval 0)))

4:50 when (nth goes out of bounds, i want to return 0

4:51 amalloy: ppppaul: (eval 0) is bizarre. just return 0

4:51 ppppaul: that is the idea

4:52 amalloy: just put 0 there instead of (eval 0)

4:52 is what i am saying

4:52 ppppaul: it was

4:52 i didn't change it back, yet

4:52 noidi: ,(try (count (nth [] 10)) (catch Exception _ 0))

4:52 clojurebot: noidi: excusez-moi

4:52 noidi: works for me

4:53 ppppaul: ok, my bug must be somewhere else, then

4:53 thanks :)

4:53 amalloy: and is this your real code, or an example to demonstrate exceptions? i'd suggest writing your code to do checking ahead of time instead of waiting for exceptions

4:55 &(if-let [x (seq (drop 3 [1 2 3 4 5]))] (first x) 0)

4:55 sexpbot: ⟹ 4

4:55 amalloy: &(if-let [x (seq (drop 3 [1 2]))] (first x) 0)

4:55 sexpbot: ⟹ 0

4:55 amalloy: ppppaul: ^^

4:57 ppppaul: ^^ indeed

4:57 parens were wrong

4:58 would be nice to have a short-hand for the try-catch stuff

4:58 (on-exception (code) (exception code))

4:59 or maybe (try+

4:59 amalloy: ppppaul: you could write that macro easily enough, but a lot of your try/catch code will involve interop, which often has side effects

5:00 therefore you can't just assume the first form is the "working" case and the rest are "error" cases

5:00 ppppaul: i guess i don't have much experience with exception handling... didn't use it much when i did java

5:02 i would actually like the syntax to be something like (code) (:oops exception return)

5:02 clojurebot: http://homepages.inf.ed.ac.uk/kwxm/JVM/codeByNo.html

5:03 amalloy: ppppaul: you already have that syntax. it's try-catch

5:04 ppppaul: i guess i could do something like (? (body) (simple exception-body)

5:04 yeah, but (catch Exception e (body)).... i just want (body)

5:05 e = % or something

5:05 amalloy: (try+ (.init someObj) (bar someObj) 10)

5:06 how can try+ know where the try ends and the catch begins?

5:06 ppppaul: (try+ (body) (catch body))

5:06 like if

5:07 could just have a keyword :oops

5:07 amalloy: ppppaul: so write the macro yourself. it's not complicated

5:07 ppppaul: (? (body) :oops %)

5:07 amalloy: then use it for a while and see if it's useful

5:08 ppppaul: i'll write it up

5:08 *learning how to write macros*

5:10 bmh: Can I easily convert a vector of strings into a java string array? I've looked at functions like object-array, but nothing fits the bill.

5:10 amalloy: bmh: into-array

5:11 LauJensen: 2 more features and ClojureQL is 1.0 :D

5:11 bmh: amalloy: Thanks. That was easy.

5:11 amalloy: bmh: we aim to please :)

5:14 esj: LauJensen: cool bananas !

5:14 amalloy: (defmacro ? [& body] (let [[work [_ & broke]]

5:14 (split-with (complement #{:oops}) body)]

5:14 `(try ~@work (catch Throwable ~'_ ~@broke))))

5:14 ppppaul: ^^

5:15 ppppaul: :D

5:15 thanks

5:15 amalloy: welcome. i'm off to bed now

5:15 ppppaul: night

5:16 LauJensen: esj: yea - speaking of bananas, did you see you were listed on disclojure.org today?

5:16 esj: courtesy of you.... thanks :)

5:16 LauJensen: Toni Batchelli actually, he hand picks

5:16 esj: pretty sweet indeed

5:37 fliebel: morning

5:38 I remember people talking about some Bonjour git stuff for the conj, anyone know what that was? I found bananajour, but I'm not sure it's the thing.

5:40 esj: bananajour ! ahhahaha

5:50 hsuh: i was happily using leiningen and its project structure, but now i have a second application (something that will run on another computer, say) for the same project, which should share files with the other application. how should i organize this ?

6:20 LauJensen: Remind me, how is it I disable that warning "slime versions differ x y z (y n ) ?"

6:20 hsuh: +1

6:22 i think you can force it with (setq slime-protocol-version 'ignore)

6:23 yep, that worked

6:24 LauJensen: thanks

6:24 hsuh: of course that will come back to bite us when we update swank or slime :)

6:27 LauJensen: live for today hsuh :)

6:59 Raynes: cemerick: Good morning.

7:00 cemerick: Raynes: :-)

7:00 hsuh: how could/should i share "utility functions" across projects (using leiningen) ?

7:04 cemerick: hsuh: hopefully lein will support artifact deployment to non-clojars repos soon.

7:05 hsuh: hm.. but that is the case for small stuff that you're still adding to, i guess

7:05 *not the case

7:11 what i have actually are two different apps which share some source code (for db access for example) and i dont know how to organize that... i'm considering even making a single project with two different run scripts (but then lein jar wont work in the future)

7:12 cemerick: hsuh: The typical thing to do would be to put the common utilities, etc. in their own project, which produces its own versioned artifact that is then added to a repository that you control. Then your other projects can add a dependency upon that common artifact.

7:13 hsuh: hm, ok... but what if these common files are also being developed? pain?

7:14 Raynes: Sounds like you want something like cake's subproject dependencies.

7:14 cemerick: hsuh: every sane development environment has something like lein's checkout dependencies, or better.

7:15 Raynes: Look for it in the cake readme: http://github.com/ninjudd/cake

7:15 I'm sure Leiningen does something similar.

7:15 octe: /12/12

7:15 Raynes: Right, checkout dependencies is lein's version, I think.

7:15 cemerick: Raynes: neither of them will solve his problem unless his build tool will push the common artifact to his own repo

7:16 hsuh: Raynes, cemerick: cool, that exactly that.. i was just searching the mailing list for the wrong keyword

7:18 cemerick: hsuh: Notice my last msg @ Raynes. You need to get that common utility project deploying into your own repo in order for the main application projects to build.

7:19 hsuh: cemerick: yeah i typed that before seeing yours... although cake's says that "If you really do want changes to clojure source files to show up immediately, you can always add the subproject src directory to your project classpath in .cake/config like this:"

7:19 cemerick: AFAICT, that's intended for developement-time only.

7:20 i.e. it won't affect actual builds.

7:21 hsuh: cemerick: oh but i'm worried about development now

7:22 cemerick: "We'll be fine; I've got enough in the larder to last through February!"

7:22 I think I remember that from a Little House on the Prairie episode ;-)

7:26 raek: to me, leiningen's checkouts feature sounds like what hsuh is looking for

7:27 at least I have used it for doing development on two projects at the same time, without having to push jars to the local repo

7:27 hsuh: perhaps it should be a single project with two ways of building (two different mains)... that would be much simpler

7:27 cemerick: raek: how do you get the artifacts into that local repo?

7:28 raek: I haven't done anything repo-related

7:28 cemerick: raek: oh, misread "without" in your last msg

7:28 raek: leiningen simply adds the classpaths of the other projects into the current one

7:28 cemerick: right, but....

7:29 is this typical, setting up projects so that they can be used and built on a local machine, but require significant classpath relationship setup elsewhere?

7:31 raek: elsewere = production or another dev setup?

7:31 hsuh: i dont really have two projects - they will "always" be developed together, its just that it should produce two jars (for now)

7:31 cemerick: raek: all of the above

7:31 raek: I use checkouts when the version of the dep I want to use does not have a jar

7:32 cemerick: hsuh: sure, I have one cluster that is ~12 projects that are all developed together. Not splitting them up would have been a nightmare.

7:32 raek: my experience is limited.

7:34 I think "checkouts" are best suited for "local hacking"

7:34 cemerick: that's what they're intended for, yes

7:34 raek, hsuh: I've been dancing around pointing both of you at maven. It solves these problems in a general way.

7:35 hsuh: cemerick: otoh everyone heard the horror stories

7:35 raek: what is maven's approach to this problem?

7:36 hsuh: what are "checkout dependencies" called in maven land ?

7:36 cemerick: hsuh: yeah, lots of horror stories about lisp, too :-P

7:36 hsuh: true, i dont see any parens

7:38 cemerick: raek: checkout dependencies are orthogonal to the build and release process, so maven leaves that up to one's tooling; the major IDEs provide supersets of the "checkout dependency" feature. However, we'll be adding something similar to clojure-maven-plugin for those that prefer emacs/vi/textmate: http://groups.google.com/group/clojure-maven-plugin/browse_frm/thread/ec87a43c3bfac1b6

7:39 s/leaves/wisely leaves

7:39 sexpbot: <cemerick> raek: checkout dependencies are orthogonal to the build and release process, so maven wisely leaves that up to one's tooling; the major IDEs provide supersets of the "checkout dependency" feature. However, we'll be adding something similar to clojure-maven-plugin for those that prefer emacs/vi/textmate: http://groups.google.com/group/clojure-maven-plugin/browse_frm/thread/ec87a43c3bfac1b6

7:42 Raynes: cemerick: You'll never convert me to maven. NEVAR.

7:42 cemerick: Raynes: Funny, you use maven every time you touch/touched lein. #toolate :-P

7:43 Raynes: I don't use leiningen.

7:43 cemerick: well, you *did*

7:43 Raynes: And, I've never had to touch a .pom file, so meh.

7:43 cake uses maven (for the time being) as well, so you could have used that as an example.

7:43 cemerick: whichever

7:44 The blub paradox is alive and well w/ Clojure devs vis a vis build tooling. :-/

7:49 neotyk`: Guys is following snippet in good style?

7:49 ,(let [m {:k1 {:a [1]} :k2 {:a []} :k3 {:a nil}}] (select-keys m (for [[k v] m :when (not-empty (:a v))] k)))

7:49 clojurebot: {:k1 {:a [1]}}

7:57 Raynes: cemerick: I still <3 you.

7:57 cemerick: Raynes: Likewise :-)

7:57 Raynes: But you'll end up using maven someday.

7:57 Sorry. :-)

7:58 Raynes: When dead men walk and man can fly.

7:58 neotyk`: cemerick: or aether

7:58 Raynes: Nobody likes clojail. :< no new watchers.

7:58 Adamant: Raynes: when there's no room in hell and the dead walk the Earth, we'll be too busy fighting the undead to worry about Maven

7:58 Raynes: I guess a sandbox is kind of a... really domain specific thing.

7:59 Adamant: Touché.

7:59 cemerick: neotyk`: sure, but then if backends count, then Raynes has already used maven via lein and cake

7:59 Raynes: If backends count, then sure. Pretty much everybody has used maven then.

8:00 cemerick: Raynes: …or when your first job has 14 modules, and the prospect of using anything else makes people go pale.

8:01 neotyk`: in our project we maintain both pom.xml and project.clj as pom doesn't allow us such a nice integration with emacs like elein does

8:01 Raynes: If ever I need something that cake cannot provide or easily be made to provide, than I will succumb to mavens rule

8:01 neotyk`: but we have multiple modules

8:01 cemerick: neotyk`: `mvn clojure:swank`?

8:01 neotyk`: and java dev in projects

8:01 cemerick: not lein, but elein

8:02 cemerick: neotyk`: never heard of it?

8:02 neotyk`: elein is https://github.com/remvee/elein

8:02 clojurebot: elein is https://github.com/remvee/elein

8:02 clojurebot: In Ordnung

8:03 neotyk`: so I can do M-x elein-swank or elein-reswank or elein-deps from within emacs

8:04 all no need to start in shell swank server

8:04 Raynes: cemerick: Are you wearing a wife-beater in your twitter image?

8:05 cemerick: neotyk`: you keep separate project.clj's in sync just to use a 180-line elisp module? :-O :-)

8:05 Raynes: I'm pretty sure I've never worn a wife-beater in my life. :-)

8:05 neotyk`: well, I don't have to maintain poms ;-)

8:05 I maintain project.clj

8:05 sometimes just help a bit with poms

8:06 cemerick: neotyk`: Ah; my point being, writing an emvn.el or somesuch would seem to be a more efficient route :-)

8:06 hsuh: twitter just told "Similar to @cemerick chrishouser Follow"

8:06 cemerick: Raynes: nah, that's just a green polo shirt

8:06 neotyk`: cemerick: I'm still kind of afraid of writing my own emacs packages

8:15 fogus_: I need to add triangle-key support to clojure-mode.el! http://lispm.dyndns.org/news?ID=NEWS-2008-07-27-1

8:16 Raynes: fogus_: ohai

8:18 cemerick: Hyper-Super-Meta-Control :-P

8:18 fogus_: cemerick: Thanks for the pom tips. I will clean it up later today

8:20 cemerick: fogus_: None of it is *bad*, was just FYI.

8:22 fogus_: cemerick: It's good stuff. I need to learn these things

8:23 Raynes: Hello to you sir

8:29 cemerick: I guess it's safe to say that *no one* uses update-proxy.

8:32 fogus_: cemerick: I know a certain book that devotes a half page to it. :-O

8:32 cemerick: fogus_: indeed, I found that surprising!

8:32 it's a neat facility, but I wouldn't be surprised if it went away so as to maximize proxy perf

8:33 fogus_: cemerick: I think update-proxy is a great incremental development tool.

8:33 That's kinda the angle we took

8:35 It would be ashamed if it went away

8:36 stuartsierra: As far as proxies go, I wouldn't expect it to change

8:36 cemerick: fogus_: I'd much rather explicitly delegate to an external var, and then I can just load code to update my "proxied" function.

8:37 I suppose you might actually want a *single* instance to gain a different method impl, but I've not encountered that use case.

8:38 stuartsierra: having to pay the indirection cost just because you have to extend a concrete class is a bummer. Combined with the lack of use of update-proxy, and… *shrug*

8:38 stuartsierra: I think deftype/reify is the performant path

8:39 fogus_: cemerick: using proxy and gen-class pollutes my beautiful Clojure semantics, so I like the benefit of dynamism ... it dulls the pain a bit. ;-)

8:39 stuartsierra: dunno if that performance can be matched when extending a concrete class

8:47 neotyk`: (find-doc "every")

8:47 sorry not this window

8:52 jweiss_: how do i convert a map into a seq? (not the keypairs, just a list (k v k v etc)

8:53 Raynes: &(flatten (seq {:a :b :c :d}))

8:53 sexpbot: ⟹ (:a :b :c :d)

8:54 cemerick: &(mapcat identity {:a :b :c :d})

8:54 sexpbot: ⟹ (:a :b :c :d)

8:54 jweiss_: ah good ones

8:54 Raynes: Mine is two characters shorter, mhm.

8:54 ;)

8:54 jweiss_: i think Raynes' is a bit more obvious what it does too :)

8:55 Raynes: mapcat is really simple though, if you read the docstring.

8:55 cemerick: I've never liked flatten much

8:55 jweiss_: me either

8:55 Raynes: Almost certainly faster as well.

8:55 cemerick: &(flatten {:a :b})

8:55 sexpbot: ⟹ ()

8:55 Innar: sexpbot is some kind of script that recognizes clojure forms and evals them?

8:55 cemerick: ^^ feels wrong

8:55 Raynes: sexpbot does a lot more than evaluate clojure code.

8:55 $whatis sexpbot

8:55 sexpbot: sexpbot does not exist in my database.

8:55 jweiss_: hehe

8:55 Raynes: Something wiped my whatis db.

8:56 Something being me, accidentally.

8:56 http://github.com/Raynes/sexpbot

8:56 neotyk`: I think cemerick's solution has one less node

8:56 cemerick: jweiss_: use whatever reads better to you :-)

8:57 jarpiain: ,(flatten (seq {:a [1 2] :b '(3 4)}))

8:57 clojurebot: (:a 1 2 :b 3 4)

8:57 jweiss_: cemerick: even though the flatten one seems more readable, i don't like flatten. so i'll go with yours

8:57 Raynes: &(mapcat identity {:a [1 2] :b '(3 4)})

8:57 sexpbot: ⟹ (:a [1 2] :b (3 4))

8:58 Raynes: You'd better go with his.

8:58 His actually works.

8:58 ;)

8:58 fogus_: identity is too verbose! (mapcat #(-> %) {1 2 3 4}) :p

8:58 Kjellski: I want to write a function that prints every char in a two dimensional Character/TYPE array, but a newline at every end, what's the best way to do that?

8:58 jweiss_: Raynes: yours would have worked too, for my purposes - the vals are all strings

8:58 Raynes: &(flatten {:foo "foo" :bar "bar"})

8:58 sexpbot: ⟹ ()

8:58 Raynes: &(flatten (seq {:foo "foo" :bar "bar"}))

8:58 sexpbot: ⟹ (:foo "foo" :bar "bar")

8:59 cemerick: Raynes: see, that first one always bothers me

8:59 Raynes: cemerick: Indeed, I didn't notice that behavior until a moment ago.

8:59 jweiss_: that behavior is not at all obvious from the doc either.

8:59 cemerick: I'd much prefer that it simply leave unflattenable values in the seq, untouched

9:00 &(flatten "foo")

9:00 sexpbot: ⟹ ()

9:00 jweiss_: yeah, i thought flatten would basically just remove inner braces/parens

9:00 if there aren't any, then it's done

9:01 except replacing the outer braces with parens, in the case of a map

9:01 but maps aren't seqs... so i guess the doc isn't *wrong*, just leaves out what it does

9:02 cemerick: jweiss_: I don't think it leaves anything out necessarily -- just that providing it with non-Sequential values is essentially bad input

9:03 Tossing an exception would probably be preferred, if that's the case.

9:03 jweiss_: cemerick: yeah, i just don't see why it was limited to seqs

9:03 cemerick: jweiss_: it's not -- it's limited to sequential things

9:03 jweiss_: i don't see why it can't handle maps too

9:04 &(flatten [:a {:b :c} :z :y])

9:04 sexpbot: ⟹ (:a {:b :c} :z :y)

9:04 jweiss_: it just leaves maps alone when they're not toplevel

9:06 tonyl: ping?

9:06 clojurebot: PONG!

9:19 Kjellski: What could be the problem when "alength" was not found?

9:20 tonyl: alength? is it an object method?

9:20 oh got it :P

9:22 Kjellski: ,(doc alength)

9:22 clojurebot: "([array]); Returns the length of the Java array. Works on arrays of all types."

9:22 Kjellski: =( should I :use it in my namespace? I mean it's in clojure.core ... I don't get it ...

9:23 tonyl: gist of the code you are using it?

9:34 lrenn: cemerick: What are your thoughts on Ivy?

9:35 cemerick: lrenn: it's a good solution for dep management, if you're stuck in ant.

9:36 I think gradle uses it too, but I might be mistaken on that.

9:37 lrenn: cemerick: Oh, you don't think it's better than maven for dependency management? How is maven better re: dep management?

9:37 cemerick: and yes, the gradle folks were smart enough to realize that maven was not what they wanted.

9:38 cemerick: lrenn: Maybe it's not, but insofar as maven defines the standard that ivy adheres to, I'd be surprised if ivy offered much more.

9:38 Besides, if I were to use ivy, then I'd have to use *something* for doing actual builds, which leaves me in the cold AFAICT.

9:38 lrenn: cemerick: ivy only adhers to that standard when it's force to stoop down to maven's leven (ie, maven compatibility) :)

9:39 cemerick: what is wrong with lein/cake? Build tools that were built from the ground up with Clojure in mind, as opposed to maven which has been 99% built to do something other than build clojure projects.

9:39 cemerick: lrenn: nothing's wrong with lein or cake, if they meet one's requirements

9:39 lrenn: cemerick: how do lein/cake not meet your requirements?

9:40 cemerick: I don't like the reimplementation aspect of them, but *shrug*

9:40 lrenn: interop with existing tools and a large plugin ecosystem for starters

9:40 lrenn: not liking the reimplementation aspect of them (what does that mean exactly?) is different thatn not meeting your requirements.

9:44 cemerick: I mean that, at least from my perspective, build tools aren't very interesting, and are orthogonal to writing Clojure applications. Insofar as the latter will inevitably require interop with platform-esque tools/environments/etc, there's far less friction involved in using what is mostly standard on the host platform, than in tackling the hairy build problem from scratch.

9:45 i.e. if I were to ever do any serious work with ClojureCLR, I'd go find what the Microsoft camp uses for builds, and use that.

9:45 lpetit: Irenn, cemerick: my 2 cents. lein started simple, because it did not address a large spectrum of needs. My feeling is that as time passes, lein will have to cover more and more needs, as the kind of projects built with it grows. So in the end, lein will be as big as maven. I think that a better approach could be towards maven as clojure is towards java: a thin layer over existing stuff.

9:46 Kjellski: tonyl: https://gist.github.com/674172 =)

9:47 lrenn: lpetit: the large number of people who use gradle and or still use ant would disagree with that.

9:48 tonyl: Kjellski: let me take a look

9:48 lrenn: I think this thought that we have to use maven because that's what some java people use is silly. As far as I'm concerned Phil and Justin have already built a better build tool.

9:49 Kjellski: tonyl: thanks!

9:49 lrenn: The only real objection I've heard is that you lose the plugin support.

9:49 cemerick: lrenn: Just because someone with fewer/different requirements uses a different tool, doesn't mean that that different tool is somehow superior/better/etc.

9:50 lpetit: Irenn, cemerick: the real question I'm still asking myself is: are we throwing the baby with the bath water ? maven's syntax is something. maven's plugins ecosystem is another.

9:50 cemerick: lrenn: and tooling support. I use eclipse and hudson. Those are more important than my build tooling.

9:50 lrenn: cemerick: agreed. I still would like to stick up for lein/cake. I should not have said they are "better", but for building clojure code, I fail to see how they are inferior.

9:51 Kjellski: tonyl: Hmmm... somehow it's working now... sorry for taking your time and thanks for having a look =)

9:51 cemerick: lrenn: you don't need to stick up for them at all -- no one's tearing them down :-)

9:52 lrenn: cemerick: I see a growing chorus of people suggesting it is silly for us to use lein/cake when maven already exists. That sentiment was already expressed once during this conversation :)

9:53 cemerick: LOL @ growing chorus :-)

9:54 For the most part, those of us that use maven for clojure builds keep our head down, because of a constant barrage of "why would you torture yourselves with that thing" comments.

9:55 tonyl: Kjellski: it works for me. also there is no need to put a for loop inside a for loop

9:55 the for construct does it for you if you just write (for [row (range (alength scene)), col (range (alength scene))] ...)

9:56 the most inner loop would be on the right and work it's way up to the left

9:56 I am guessing your problem could be ns related?

10:07 lrenn: cemerick: you're right, "growing chorus" was not the correct phrase ;) Anyway, I don't think it's the blub paradox, I truly believe a build tool built and designed specifically for clojure is preferable to maven. I appreciate your time.

10:08 cemerick: lrenn: I'd disagree re: blub, esp. if "building clojure" is the only aspect of the charter. Build, release, and deployment is far more wide-ranging than that.

10:09 * cemerick walks away for a while

10:09 lrenn: cemerick: i include release/deployment as well.

10:23 bartj: can someone please give an example of a java "NaN" stored inside a clojure variable?

10:26 tonyl: (def NaN java.lang.Double/NaN)

10:26 (def NaN Double/NaN)

10:27 bartj: tonyl, thanks...

10:28 I am wondering why does this result in an error: (read-json (json-str [Double/NaN]))

10:28 tonyl: oh, that is nat a javascript NaN though

10:28 bartj: because (json-str [Double/NaN]) certainly does not throw an error

10:28 so why is read-json complaining?

10:28 is this a bug ?

10:29 tonyl: because it needs a javascript NaN since it reads json which is a based on javascript

10:29 bartj: I think the NaN comes from some Java code

10:29 how best to gracefully handle this case?

10:30 it would be nice if NaN is stored as a string

10:30 tonyl: you could with javascript Math.sqrt(-5).toString()

10:31 chouser: that's not valid json

10:31 surely

10:32 bartj: chouser, I completely agree

10:33 but, I am helpless since it comes from some Java code I have no control of

10:33 chouser: sounds like JSON defines no way of storing NaN

10:33 bartj: :(

10:34 tonyl: yeah I would say store it as a string "NaN"

10:34 chouser: you'll have to either use an "extended" JSON (who doesn't, after all) or encode it differently.

10:35 bartj: hmm, thanks guys

10:36 chouser: I suppose if json-str is shooting for conformance, it should complain when you give in NaN

10:37 tonyl: (require '[clojure.contrib.json :as json])

10:37 &(require '[clojure.contrib.json :as json])

10:37 sexpbot: ⟹ nil

10:37 tonyl: (json/json-str [Double/NaN])

10:37 &(json/json-str [Double/NaN])

10:37 sexpbot: ⟹ "[NaN]"

10:38 tonyl: &(json/read-json (json/json-str [Double/NaN]))

10:38 sexpbot: java.lang.Exception: JSON error (unexpected character): N

10:39 bartj: chouser, my point exactly!

10:39 because (json-str Double/NaN) works just fine

10:40 tonyl: &(json/read-json (json/json-str [Double/NaN]) false)

10:40 sexpbot: java.lang.Exception: JSON error (unexpected character): N

10:40 chouser: bartj: well, maybe it doesn't work since it generates something that is not technically valid JSON

10:41 tonyl: &(json/read-json (json/json-str ["NaN"]) false)

10:41 sexpbot: ⟹ ["NaN"]

10:43 chouser: some options for encoding NaN: 1) "NaN", 2) NaN, 3) { "double": 0, "isNaN": true }

10:43 bartj: &(json/read-json (json/json-str [Double/NaN]) false)

10:43 sexpbot: java.lang.Exception: JSON error (unexpected character): N

10:43 chouser: 2 is what json-str is doing, but it's not valid JSON

10:43 stuartsierra: json-str should throw an error on NaN

10:44 because it's not defined in the JSON spec

10:44 bartj: tonyl, why doesn't false work in my case ?

10:45 stuartsierra, is this a bug ?

10:45 stuartsierra: yes

10:45 tonyl: because NaN either way when it is compile in json it is not a valid name

10:46 in fact even in javascript you have to create a NaN variable

10:46 like Math.sqrt(-5)

10:46 in javascript there is only the NaN error and the isNaN() function

10:47 I am guessing when read-json tries to get the value in the array it fails

10:47 bartj: tonyl, I mean you don't need the false

10:47 tonyl: on the read-json call?

10:47 bartj: &(json/read-json (json/json-str ["NaN"]))

10:47 sexpbot: ⟹ ["NaN"]

10:48 bartj: tonyl, yes

10:48 samx: &(json/read-json (json/json-str Double/POSITIVE_INFINITY) false)

10:48 sexpbot: java.lang.Exception: JSON error (unexpected character): I

10:48 tonyl: no you don't

10:48 samx: (json/read-json (json/json-str Double/NEGATIVE_INFINITY) false)

10:48 &(json/read-json (json/json-str Double/NEGATIVE_INFINITY) false)

10:48 sexpbot: ⟹ -Infinity

10:48 tonyl: now that is weird

10:49 bartj: I am unable to understand what the false param does from the documentation

10:49 tonyl: http://clojuredocs.org/clojure_contrib/clojure.contrib.json/read-json

10:49 stuartsierra: keywordized map keys

11:01 bartj: thanks everyone

11:25 opqdonut: how can I cast a char into a byte in clojure?

11:25 ,(byte \c)

11:25 clojurebot: java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number

11:25 opqdonut: ,(byte (.charValue \c))

11:25 clojurebot: java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number

11:26 cemerick: ,(byte (int \c))

11:26 clojurebot: 99

11:26 opqdonut: ah.

11:26 thanks

11:41 chouser: I wonder if that's acceptable, in light of what rhickey has said about coersion functions being for interop

11:42 cemerick: chouser: I was assuming opqdonut was asking for an interop context…

11:43 alpheus: I need to learn about configuration for clojure programs. I've declared a few vars that must be bound before my program's external functions are called but don't know where to have the user store them. Loading a clojure file specified by the user seems convenient, but how do I handle namespaces etc.

11:43 opqdonut: interop yes

11:43 building some packets in a bytebuffer

12:29 xkb: hi

12:30 tonyl: hello

12:31 quoll: Does anyone know why leinengen might complain "That's not a task" on autodoc if I have a :dev-dependenies entry of [autodoc "0.7.1"] ???

12:31 (with corrected spelling of dev-dependencies, of course) :-)

12:32 amalloy: quoll: i don't use autodoc, but is it possible you need to specify an organization id to help it find the autodoc jar?

12:32 hiredman: quoll: did you run lein deps?

12:33 xkb: does clojure have something like haskell's $ for function application?

12:33 replaca: quoll: I don't think the autoodoc plugin is working in the latest lein

12:33 amalloy: xkb: i don't know what $ does in haskell, but yes :P

12:33 replaca: quoll: it suffers from version-itis, which I'm working to fix

12:33 amalloy: probably the answer is (apply f arg args)

12:34 quoll: hiredman, no. I'm new to leinengen, and I figured it would do the deps automatically. Running now

12:34 xkb: amalloy: its like shorthand: sum (map sqrt [...]) becomes sum $ map sqrt etc.

12:34 quoll: replaca: should I go with 0.7.0?

12:34 xkb: I have this really long line of function applciations in clojure, and want to make it a bit more readable

12:34 hiredman: ->

12:34 sexpbot: java.lang.Exception: EOF while reading

12:34 amalloy: xkb: we don't have that, but -> and ->> are similar

12:35 hiredman: ,(-> 1 inc inc inc inc)

12:35 clojurebot: 5

12:35 quoll: hiredman: deps worked. Thank you.

12:35 xkb: amalloy: Ok, will check them on the clojure site! Thanks

12:35 amalloy: xkb: for example: ##(->> (range) (filter even?) (drop 100) (take 5))

12:35 sexpbot: ⟹ (200 202 204 206 208)

12:36 xkb: amalloy: ahh exactly what I was looking for

12:36 replaca: replaca: you can try it, but I think the problems run deeper than that

12:36 xkb: nice

12:36 replaca: leinigen has moved forward, but autodoc hasn't

12:36 amalloy: xkb: great

12:37 replaca: (I meant quoll)

12:37 technomancy: replaca: what's the root problem?

12:37 replaca: quoll: so is autodoc working for you, then

12:37 technomancy: (we talked about this a long time ago)

12:37 quoll: replaca: yes indeed. Browsing the html now

12:37 much easier than (doc .....) :-)

12:37 replaca: technomancy: the fact that autodoc wants to be both a lib and an executable

12:38 quoll: that's great news

12:38 technomancy: ah, right.

12:38 replaca: technomancy: and therefore has its own clojure version deps

12:38 technomancy: I'm surprised to hear it works at all now, but my plan is to make a shim that goes between

12:39 technomancy: and does an exec in proj

12:39 technomancy: just haven't gotten to it yet

12:40 technomancy: replaca: you should know about the :eval-in-leiningen key you can use to avoid spinning up tests for the project in a separate process.

12:43 replaca: technomancy: right, but doesn't that use whatever version of clojure that lein is using?

12:44 technomancy: yeah, I don't think you can avoid making the executable its own project

12:44 replaca: "end of file while reading" would be a whole lot more useful if it told me which file! (and maybe the beginning of the top-level form as well)

12:45 technomancy: and that's not really a big deal. Still, I'm a little befuddled about how it works at all currently. That 0.7 version quoll is using in based on Clojure 1.1 and I swear it didn't used to work

12:47 quoll: replaca: I'm not doing anything fancy with it either. Just added the :dep-dependencies entry and ran it. No other settings at all

12:48 replaca: quoll: if it works at all, I would expect it to be easy :). still I'm surprised (and happy - I thought folks using lein were suffering)

12:51 quoll: yeah, I figured it was an all or nothing deal, but then again, I also figured that it didn't hurt to let you know that I hadn't done anything unexpected

12:53 replaca: quoll: thanks!

12:54 quoll: np

12:54 thanks for working on autodoc :-)

12:55 replaca: quoll: I try! :)

12:56 ninjudd: cemerick: just to be clear, maven is not the backend for cake. we use maven only for dependencies, and lrenn is working on making that pluggable so you can use ivy instead

12:56 though we plan to still support using maven too

12:57 cemerick: ninjudd: *a* backend, then? :-)

12:57 ninjudd: do you have two sentences on "Why ivy?"

12:58 ninjudd: 27 deps -> 2 deps. i'm sure lrenn can expand on that ;)

12:59 3 deps.. sorry

12:59 cemerick: ninjudd: oh, I was wondering more about capability

13:00 ninjudd: cemerick: from my research, it looks like ivy can do everything with regard to deps that maven can and more.

13:00 cemerick: yeah, I knew it was at least equivalent.

13:00 * tonyl lunch time

13:01 cemerick: anyway, I didn't intend to open up another build tool discussion :-)

13:01 ninjudd: cemerick: i'm working on a response to your mailing list message

13:02 i might be misunderstanding, but i don't see what we would get from using maven instead of a 4 line macro

13:03 sounds like it is going in the wrong directlion: simple -> complex

13:04 cemerick: i'd prefer to someday have cake implemented purely in clojure eventually (save for a *very* small client script if you want a persistent jvm)

13:04 with options to use maven/ivy for deps if you really need something only they offer

13:15 jcromartie: is there any sort of work for image-based Clojure development?

13:16 I've always found it to be a very productive way to program but it seems to be an idea absent from mainstream languages

13:16 Smalltalk, Forth, common lisp even

13:17 dnolen: jcromartie: seems like something JVM would have to support directly right?

13:17 jcromartie: what would a Clojure image "look like"? maybe some special def forms?

13:17 I think it could be bolted onto the JVM

13:17 forget about threads and other objects at first

13:18 I'm mostly concerned with the code I write in a repl... sometimes I want it to stick around

13:19 pdlogan: (having worked for gemstone, I can attest that an image-based anything on the jvm is... more problematic than you might first imagine)

13:20 dnolen: jcromartie: persistent jvms are fun that way, one thing I like about cake, I can try some stuff in ns user, quit, come back later and it's still there.

13:20 jcromartie: cake does that?

13:20 pdlogan: oh cool, you're a smalltalk vet?

13:21 pdlogan: yes

13:21 jcromartie: pdlogan: I'm recently enamored with Pharo and Seaside

13:21 dnolen: jcromartie: yes it, tho if you restart your machine it's gone of course.

13:22 jcromartie: ah, I see

13:31 jfields: what's the easiest way to get from {:a 565 :b 878 :c 565 :d 997} to {:b 878 :d 997} ? (removing all kv pairs where the value equals X)

13:33 dnolen: (->> (remove (fn [[k v]] (= v 565)) {:a 565 :b 878 :c 565 :d 997}) (into {}))

13:33 ,(->> (remove (fn [[k v]] (= v 565)) {:a 565 :b 878 :c 565 :d 997}) (into {}))

13:33 clojurebot: {:b 878, :d 997}

13:33 dnolen: is one way

13:34 jfields: dnolen, thanks

13:37 LOPP: what's the best way to merge/concatenate sets

13:37 jfields: LOPP look in clojure.set

13:37 there's union

13:40 chouser: or use into

13:40 dnolen: ,(reduce (fn [m [k v]] (if (not= v 565) (assoc m k v) m)) {} {:a 565 :b 878 :c 565 :d 997})

13:40 clojurebot: {:d 997, :b 878}

13:40 dnolen: jfields: that's more verbose but faster than my first suggestion

13:41 technomancy: into uses transients

13:41 chouser: maybe dissoc would be good

13:43 ,(let [m {:a 565 :b 878 :c 565 :d 997}] (reduce (fn [m [k v]] (if (not= v 565) m (dissoc m k))) m m))

13:43 clojurebot: {:b 878, :d 997}

13:43 dnolen: chouser: nice, but turns out it's about the same speed as my second attempt

13:44 chouser: dnolen: on a that small array-map?

13:45 dnolen: chouser: yeah, it seems so

13:46 chouser: I would guess it would matter more on a larger hash-map. And then probably depend on whether most of the input entries match or not.

13:48 fogus_: Slight mod to chouser's:

13:48 ,(let [X {:a 565 :b 878 :c 565 :d 997} R #{565}] (reduce (fn [m [k v]] (if (R v) (dissoc m k) m)) X X))

13:48 clojurebot: {:b 878, :d 997}

13:49 chouser: nice

13:49 the local is to avoid re-evalling the set?

13:50 fogus_: That is one advantage... the other being it's easier for me to add/remove values when testing

13:51 chouser: I've been recently re-remembering that quoting collections avoids re-evaluation

13:52 (if ('#{565} v) ...)

13:53 jarpiain: the compiler would cache that set since all the elements are compile-time constants

13:53 fogus_: chouser: Nice! Mind if I use that as a @learnclojure tweet?

13:54 chouser: jarpiain: the Clojure compiler, or hotspot?

13:54 jarpiain: at least cljc does and I copied that from Compiler.java :)

13:54 chouser: hmmm

13:54 jarpiain: only because it's in the function position?

13:55 I was pretty sure I looked at the bytecode for this not long ago.

13:56 LOPP: I don't understand this talk about collection re-evaluation

13:57 chouser: ,(map (fn [x] #{x}) (range 5))

13:57 clojurebot: (#{0} #{1} #{2} #{3} #{4})

13:57 chouser: LOPP: in that case, the #{x} clearly has to be re-evaluated for each value of x, to generate all those sets.

13:57 jarpiain: in https://github.com/clojure/clojure/blob/d7787a758031fcc21f16c613cb759c5a6bee7a8a/src/jvm/clojure/lang/Compiler.java#L2719 it checks if all the elements are LiteralExpr

13:58 LOPP: for my question on merging sets earlier I think I went with (apply (partial conj set1) set2)

13:58 that's clear yes

13:58 hiredman: chouser: well, the set doesn't need to be reevaluated

13:58 x needs to be re-evaluated before the set is created

13:59 dnolen: jarpiain: yeah I remember seeing that commit, constant datastructures optimization, especially useful in cases like [], #{}, {} etc

14:00 amalloy: LOPP: that's equivalent to (apply conj set1 set2)

14:02 chouser: jarpiain: clearly you are correct. I wonder what I'm thinking of.

14:03 fogus_: might want to skip tweeting that one. :-)

14:03 * fogus_ hits cancel

14:07 cemerick: ninjudd: simplicity shouldn't be an objective in and of itself IMO.

14:07 i.e. function before form

14:08 * cemerick is trying not to be grating; he's just remarkably burnt out on the build tooling topic

14:10 dnolen: cemerick: "function before form", that's the root cause of most bad software I'd say ;) "function *and* form"

14:10 cemerick: dnolen: I'd agree with you in almost every other domain.

14:10 dnolen: cemerick: we can agree to disagree about that.

14:11 danlarkin: I'm going to throw you all off your game and say "neither function NOR form!"

14:11 ha ha

14:12 cemerick: dnolen: It's forced upon us by the tools and community issues.

14:12 ninjudd: cemerick: so what function do we get by replacing a 4 line macro with pmaven?

14:12 fogus_: For once I wish someone would say, "Let's disagree to agree"

14:12 dnolen: fogus_: ha!

14:12 cemerick: (inc fogus_ )

14:12 sexpbot: ⟹ 1

14:12 cemerick: ninjudd: I thought I was clear about that in my msg to that ggroup.

14:12 fogus_: Hmmm, my karma seems to be stuck at 1. :(

14:12 cemerick: (inc fogus_ )

14:12 sexpbot: ⟹ 2

14:13 cemerick: shazam!

14:14 ninjudd: The endgame re: cake, lein, pmaven, etc. isn't great if things continue as they are now. Either Clojure is going to get really significant use in industry or not; in the former case, maven/pmaven will be in widespread use, but if people can't work together because of their build tool preferences/requirements, that does no one any good.

14:16 hiredman: cemerick: I must say say, speaking of industry, sonian ditched maven for lein and everyone is happier for it

14:16 cemerick: hiredman: plucky startups aren't what I really had in mind. But, good data point.

14:17 ninjudd: cemerick: maybe i'm being dense, but i think we actually lose function by using pmaven to parse project.clj instead of the clojure reader

14:18 cemerick: ninjudd: you can make pmaven parse project.clj however you want

14:18 i.e. you and technomancy and whoever else cares about the topic would be in control of the mapping between project.clj and the POM

14:19 ninjudd: by reimplementing the clojure reader?

14:19 cemerick: no

14:19 pmaven has all of clojure at its disposal

14:19 lrenn: cemerick: who says the industry will use maven/pmaven? That didn't happen with groovy, what makes you think it will happen with clojure?

14:19 amalloy: i don't see clojure.[contrib].string containing an equivalent to clojurel.core/split-at. is there a reason c.c.string has take/drop/partition but not split-at? eg, there's something else i should be using instead?

14:20 stuartsierra: c.c.string is dead

14:20 ninjudd: cemerick: does pmaven currently use the clojure reader to parse pom.clj? i was under the impression that it didn't

14:20 stuartsierra: replaced by clojure.string

14:20 amalloy: stuartsierra: since when? c.c.string has all kinds of nice stuff c.string doesn't

14:20 in 1.2, anyway

14:20 stuartsierra: too bad

14:21 amalloy: stuartsierra: why?

14:21 cemerick: lrenn: Every exposure I've had to groovy in "corporate" environments involved it being built using maven, not gradle. *shrug*

14:21 stuartsierra: not enough value, the important stuff is in clojure.string now

14:22 cemerick: ninjudd: I don't know what the implementation details are, but if jvanzyl was accurate in his email from a few weeks ago (you got that, yes?), then there are no limits on what you can use to implement the de/serializer for pmaven POM files.

14:23 ninjudd: cemerick: you still haven't told me what function we get for paying the price of a very large set of 20+ dependencies

14:24 cemerick: i would be happy to share my implementation of defproject as a separate project though, so pmaven can use it

14:24 stuartsierra: support for all Maven plugins

14:24 cemerick: ninjudd: Again, it's in my msg to that ggroup. (a) One implementation of the model, not 3+, (b) free interop with all tools that support maven 3/pmaven, (c) access to all maven plugins

14:25 (http://groups.google.com/group/projectclj---spec/browse_frm/thread/855ce112689fb33f for those following along)

14:25 ninjudd: using pmaven to parse project.clj doesn't give us support for all maven plugins. the price for that would be even higher

14:25 the price for that would be selling our soul to maven, which i'm not prepared to do

14:25 cemerick: oh, crud

14:26 stuartsierra: oh dear god

14:27 cemerick: ninjudd: Do you have a hyperbole-free objection?

14:27 ninjudd: what i mean by that is, i'm not willing to have the cake's core implementation be dependent on maven

14:27 cemerick: no one suggested that.

14:28 fogus_: cemerick: I am definitely stealing that phrase for my next all-hands meeting

14:28 cemerick: "you could add commands to your

14:28 respective frontends to drive various pmaven/maven-provided

14:28 functionality, such as generalized deployment, using existing maven

14:28 plugins, etc."

14:28 ninjudd: i would love to have a cake plugin that provides support for all maven plugins in cake

14:28 cemerick: ninjudd: If you want to reimplement commodity build processes, that's your perogative, but that doesn't mean you can't delegate off to pmaven to invoke maven plugins.

14:28 ninjudd: (LauJensen and i have discussed creating such a plugin)

14:29 * cemerick apologizes for the snarkiness :-(

14:29 ninjudd: cemerick: it sounds like i misunderstood your message then. i thought you were suggesting we depend on pmaven for the model

14:30 (which is why i asked here before responding)

14:30 cemerick: Yes, I'm suggesting that you use the POM. It's the only formal build model anywhere, and is the gateway to interop with essentially all JVM-land build/deploy/mgmt tooling.

14:31 stuartsierra: Using the model doesn't mean you have to use any particular implementation of that model.

14:31 slyrus: so... when you guys live on the bleeding edge with, say, 1.3.0-alpha3 and the corresponding contrib jars, do you just pick them up from maven/clojars or do you build your own jars?

14:31 cemerick: what stuartsierra said

14:31 ninjudd: i'm happy to produce a pom.xml, if that is what you mean

14:31 * cemerick swears off any knowledge of the impl details of anything

14:32 slyrus: cemerick: what are "commodity build processes"?

14:32 tonyl: i build my own

14:32 stuartsierra: Maven / Hudson / Nexus

14:32 danlarkin: formal build model is made up? First you're asserting that it is something, and then you're asserting that it is something desirable

14:32 slyrus: tonyl: and you install them in your local maven repo?

14:32 cemerick: slyrus: compiling code, assembling jar files and other artifacts, deploying them to repositories, etc.

14:32 slyrus: commodity?

14:32 tonyl: I don't use maven neither lein or anything else

14:33 slyrus: ah, good for you

14:33 ninjudd: cemerick: currently cake uses ant for most of that

14:33 tonyl: just a bash script the runs the repl or the clj script i pass it to it

14:34 i should start learning more about them though, my projects are starting to get bigger

14:35 cemerick: ninjudd: that's fine, but totally orthogonal to the discussion of the model

14:35 ninjudd: cemerick: so what do you mean when you say "use the POM"?

14:35 tonyl: i thought somebody posted that clojars has an alpha 1.3.0 though

14:38 pppaul: $8ball women?

14:38 sexpbot: pppaul: Reply hazy, try again.

14:38 ninjudd: $8ball what does "use the POM" mean?

14:38 sexpbot: ninjudd: Ask again later.

14:39 ninjudd: :)

14:39 lrenn: stuartsierra: but the clojure community has no say over that model right?

14:40 stuartsierra: We have spies inside Sonatype.

14:41 pppaul: what model?

14:41 slyrus: so clojure contrib is now split amongst 76 jars?

14:41 lrenn: So, it should have been "selling our souls to sonatype" as opposed to maven...and would thus not be hyperbole.

14:41 pppaul: has there been a photo shoot?

14:41 * slyrus is trying to wrap his head around the clojure changes from the last 2 months or so

14:41 stuartsierra: I don't have a soul anyway.

14:41 pppaul: 76 jars... wow

14:42 stuartsierra: And I prefer to call it "participating in the broader Java community."

14:42 This includes things like getting Clojure and major libraries into the central Maven repository network.

14:42 slyrus: am I the only one who thinks that the name "complete-[version].jar" is a bit ambiguous?

14:43 stuartsierra: no

14:43 Got a better name?

14:43 slyrus: complete what???

14:43 hiredman: clojure-contrib-complete-[version].jar

14:43 slyrus: contrib-complete would certainly be better

14:43 pppaul: obviously string completion

14:43 slyrus: or what hiredman says

14:43 stuartsierra: complete is really just for legacy compatibility

14:44 slyrus: ok, so I should be using the other 75 jars instead?

14:44 stuartsierra: New projects under the "contrib" umbrella will have their own repositories and releases.

14:44 cemerick: I'd be surprised if further contrib umbrella artifacts were set up…?

14:44 stuartsierra: the "legacy" contrib with 70-some modules will be phased out I hope

14:44 cemerick: slyrus: you probably only need a handful, suited to your project's actual dependencies.

14:45 slyrus: fair enough

14:45 stuartsierra: as a bonus, this makes your project's footprint smaller

14:46 the 70-module thing was my (failed) attempt to make it easier to contribute

14:46 ninjudd: stuartsierra: there is a subset of the larger java community that only uses ant and ivy without using the POM at all

14:46 stuartsierra: ninjudd: they're still using Maven's group/artifact/version and repository layout

14:46 hiredman: sure it's only for legacy compat, but complete.jar is the worst jar name ever

14:46 slyrus: so if I'm following along at home and building my own clojure-contrib I just do some #!/bin/bash hackery to install each jar into my local maven repo?

14:46 stuartsierra: hiredman: yeah

14:47 slyrus: no just run "mvn install" at the top level

14:47 hiredman: I've got bigger problems

14:47 ninjudd: stuartsierra: yes, i don't plan to move away from using group/artifact/version, but what does "use the POM" mean other than that?

14:47 does it mean, use the project lifecycle goal names that maven uses?

14:48 slyrus: Is there a -n (as in make -n) argument for mvn? as in "tell me what you're going to do, but don't actually do it"

14:48 ninjudd: does it mean: support maven plugins?

14:48 stuartsierra: it will mean differet things to different people

14:48 To *me*, it means it is possible to build, test, and deploy the project using only Maven.

14:48 even if you also support other tools

14:50 * slyrus notices that "mvn install" really means "run a bunch of tests and then we'll talk about things"

14:50 stuartsierra: slyrus: yes

14:50 tonyl: slyrus: there is a README file in the top level describing what you can do with mvn

14:50 ninjudd: stuartsierra: so build, test and deploy are the only goals you care about then?

14:50 lrenn: stuartsierra: no they're not.

14:51 stuartsierra: see springsource.

14:51 stuartsierra: what about it?

14:51 slyrus: tonyl: I prefer to do as little as possible with mvn :)

14:51 cemerick: ninjudd: AFAIC, it means defining a single canonical clojure serialization of the POM, ideally whose structure and semantics has a passing resemblance to maven's.

14:51 slyrus: I see it as an unnecessary evil

14:52 stuartsierra: cemerick: that would be nice

14:52 cemerick: ninjudd: "test" and "deploy" are phases, not goals :-)

14:52 ninjudd: ok, maven newbie question. can i change the default locations of src, test, target, etc?

14:52 stuartsierra: yes

14:52 cemerick: ninjudd: of course

14:52 ninjudd: cemerick: phases. that's the word i was searching for

14:52 lrenn: stuartsierra: https://ebr.springsource.com/repository/app/faq

14:52 cemerick: ninjudd: see https://github.com/sonatype/polyglot-maven/tree/master/pmaven-clojure for the current pmaven clojure impl.

14:53 stuartsierra: lrenn: ok, that's OSGi

14:53 The only other widely-used JAR repository format

14:53 tonyl: slyrus I understand, to get my contrib 1.3.0 i just mvn install and rename the resulting jar

14:53 ninjudd: cemerick: so what about features that are only implemented by cake or lein? where do those go in the universal POM?

14:54 stuartsierra: as plugins

14:54 slyrus: what's the difference between standalone and complete?

14:54 stuartsierra: standalone = one big jar

14:54 jfields: if you don't care about the result, for example, you wanted to log a bunch of things, which is better (doall (map log-stuff coll)) or (doseq [i coll] (log-stuff i))

14:54 stuartsierra: complete = lots of little jars

14:54 ninjudd: stuartsierra: what about features only implemented by maven? plugins too?

14:54 cemerick: ninjudd: what stuartsierra said, or: it's perfectly fine if stuff that's above and beyond what the formal POM is included IMO. But it should come with big warning flags about it likely not working with other tools.

14:55 dnolen: jfields: doseq reflects the side-effect-y nature of the code better

14:55 stuartsierra: what cemerick said

14:55 lrenn: stuartsierra: ?? OSGI is not a jar repository format.

14:55 jfields: dnolen, agreed. performance wise any pref?

14:55 stuartsierra: it's a way of packing up JARs for distribution tho

14:55 cemerick: lrenn: what's this about OSGi?

14:56 stuartsierra: SpringSource has a "bundle repository"

14:56 lrenn: stuartsierra: um, sort of. But that that has nothing to do with the format of their repository.

14:56 dnolen: jfields: doseq is strict, doall is realizing lazy computations. doseq is probably going to be faster for side-effect-y things.

14:56 cemerick: lrenn: presumably similar in concept to p2, I suppose?

14:56 jfields: thanks.

14:56 stuartsierra: and the springsource repo still follows the maven/ivy layout

14:57 jfields: why is there no (doseq f coll) -- (doseq [i coll] (f i)) feels so verbose.

14:57 slyrus: stuartsierra: so what's in complete.jar if not the contents of all of the little jars?

14:57 stuartsierra: nothing

14:57 it's just their as a dependency

14:57 there

14:58 lein/maven dependencies need "complete.jar" to be a real file to work

14:58 slyrus: oh, so we're lying to our build tools? cool.

14:58 stuartsierra: rub it in. I can take it

14:58 cemerick: slyrus: not lying -- just getting around there being no support for multiple POM inheritence :-P

14:59 dnolen: jfields: just a macro away :)

14:59 * slyrus is blissfully ignorant of things like dependencies and multiple POM inheritance

14:59 jfields: dnolen, indeed.

14:59 thanks.

15:00 dnolen: jfields: doseq supports list comprehension style things, something to consider.

15:01 lrenn: stuartsierra: no, it actually doesn't. It may look that way to you, but the way organizations are handled is different.

15:03 amalloy: jfields: (dorun (map f coll))

15:04 cemerick: lrenn: am I simply imagining the directions for how to use the spring bundle repo with maven, then?

15:05 lrenn: cemerick: the urls are different, the "ivy" version starts with /ivy.

15:06 cemerick: lrenn: so I guess they explicitly provide direct support for maven and ivy. Is that bad?

15:07 lrenn: cemerick: no, it's not bad at all. As someone who uses ivy and spring at work, I am very grateful they do so :)

15:07 cemerick: Cool.

15:08 Then everything is unicorns and rainbows. :-)

15:08 malkomalko: quick question.. I'm really loving clojure lately.. ya know, gettin' into the whole (lisp) thang... but alas, I feel like I'm turning into an ahole.. is that ok?

15:08 cemerick: malkomalko: you mean you feel "Smug Lisp Weenie" syndrome coming on? ;-)

15:09 lrenn: malkomalko: "Just because we Lisp programmers are better than everyone else is no excuse for us to be arrogant." --Erann Gat

15:11 hiredman: ~#19

15:11 clojurebot: 19. A language that doesn't affect the way you think about programming, is not worth knowing.

15:17 cemerick: malkomalko: Fight the urge. :-) Patience, empathy, and kindness are always called for, even if you've a sense of grandiosity.

15:18 malkomalko: I wear a size 7 1/2 hat, I'm just worried my head's going to get a little too big

15:18 but it's a lot of fun :)

15:19 bobo_: putting the log of this channel on a webpage is the best thing since sliced bread! so many times it solved my problems via google :-)

15:21 arkh: trying to understand how memoize works (and underlying clojure by association) and the first question I have is: how is mem retained between calls? It looks like it falls out of lexical (let) scope.

15:23 slyrus: so all of my "dependencies" specify a particular version. How do I find out what the "current" version for something like swank-clojure is?

15:23 stuartsierra: slyrus: at the moment, search clojuars

15:23 *clojars

15:24 lrenn: speaking of clojars, does anyone know if Alex (ato) is still maintaining it?

15:25 slyrus: stuartsierra: http://clojars.org/search?q=swank-clojure

15:26 clojars searching is pretty lame it seems

15:26 samx: arkh, mem is in the lexical scope of the function 'memoize' returns. the returned function retains it's lexical scope as a lexical closure, so every time you call the returned function, it's accessing the same local variable.. it's not retained between differnt calls to 'memoize', only to the function returned by memoize

15:26 abedra: slyrus: that won't actually pull up swank-clojure

15:26 stuartsierra: slyrus: yeah

15:26 abedra: slyrus: you have to search for swank

15:26 and then find it

15:27 stuartsierra: clojars definitely needs work, it's been kind of in limbo for a while

15:27 abedra: yes

15:27 stuartsierra: dliebke was experimenting with alternatives

15:27 abedra: the search has gotten a little better, but exact matches still don't work

15:27 slyrus: mind you, I don't actually want to use clojars, just to know what the latest version is

15:27 abedra: stuartsierra: yeah, cljr works quite well :)

15:27 slyrus: yeah, that's what i use it for as well

15:28 slyrus: and I see swank-clojure doesn't have a pom.xml, so mvn install doesn't DTRT

15:29 not that I'm complaining about swank-clojure not supporting maven of course...

15:30 ninjudd: slyrus: 'lein install' should work, or 'lein pom && mvn install'

15:30 s/lein/cake/

15:30 sexpbot: <ninjudd> slyrus: 'cake install' should work, or 'cake pom && mvn install'

15:30 ninjudd: (also)

15:30 slyrus: oh, thanks. that's certainly easier than export SWANKDIR=~/.emacs.d/site-lisp/swank-clojure

15:30 mvn install:install-file -DgroupId=swank-clojure -DartifactId=swank-clojure \

15:30 cemerick: stuartsierra: nexus on the backend with a slick search UI tapping whatever APIs it provides would seem to be an obvious option?

15:30 slyrus: -Dversion=1.3.0-SNAPSHOT -Dpackaging=jar -Dfile=${SWANKDIR}/swank-clojure-1.3.0-SNAPSHOT.jar

15:30 whoops

15:30 ninjudd: oh, the bait and switch!

15:30 stuartsierra: cemerick: yeah, I like Nexus

15:31 slyrus: I thought "lein install" sounded nice :)

15:31 cemerick: Well, nexus *works*. :-) I don't like that UI toolkit.

15:31 slyrus: now I see I need cake

15:31 ninjudd: slyrus: i figured you were more likely to have lein which is why i said that first

15:31 slyrus: indeed

15:31 stuartsierra: cemerick: yeah, esp. the fact that the login form doesn't autocomplete

15:31 ninjudd: but i wanted to make sure someone watching along at home knew that either would work ;)

15:33 arkh: samx: thanks; your explanation helps me understand both memoize and closures better

15:33 * slyrus didn't know about lein install

15:33 * slyrus figures he'll have to check out cake as well

15:33 dnolen: slyrus: cake/lein install is awesome

15:36 slyrus: yecch... clojure-1.3.0-alpha3 and clojure-1.2.0 on the classpath :(

15:42 shouldn't clojure.jar be a dev-dependency of swank-clojure so it doesn't get pulled into projects that use swank-clojure?

15:46 arkh: in memoize, how does the sequence 'args' work as a key to the map referred to by 'mem'? Isn't the sequence '(:one 2) a different sequence every time its used?

15:49 samx: arkh, 'memoize' function isn't really using 'args' for anything.. it's just returning a function that has a formal parameter 'args'.. so 'args' won't be bound to a value, until you invoke a call to the function that was returned by 'memoize'

15:49 hircus: slyrus: but how can you have a Clojure project without depending on clojure.jar ?

15:50 slyrus: hircus: dev-dependency

15:51 hircus: slyrus: sure. but what are you trying to achieve? a project.clj that has no dependencies and only a single dev-dependency?

15:51 amalloy: arkh: ##(= [:one 2] [:one 2])

15:51 sexpbot: ⟹ true

15:51 slyrus: I'm trying to have my own projects which have swank-clojure as a dev-dependency not pull in the version of clojure that was used to build the swank-clojure jar

15:51 hircus: ah

15:52 slyrus: why would i want 1.2.0 and 1.3.0 on the classpath? seems like a recipe for disaster

15:52 stuartsierra: slyrus: you can declare an exclusion

15:52 hircus: so your project is built against clojure 1.3.0 alpha but swank pulls in 1.2.0 for its own use

15:52 stuartsierra: not ideal, maybe, but it works

15:52 slyrus: hircus: yes

15:52 amalloy: arkh: maps use = and hashcode to index things, so equivalent sequences will be looked up correctly even if they're not identical objects: ##((juxt = identical?) [:one 2] [:one 2])

15:52 sexpbot: ⟹ [true false]

15:53 hircus: have you tried a newer version of Swank -- they have 1.3.0 snapshots, I think

15:53 slyrus: stuartsierra: or I can change my local swank-clojure/project.clj to pull in clojure as a dev-dependency and everything seems fine

15:53 hircus: this is from the latest swank-clojure git HEAD

15:53 hircus: hmm

15:53 stuartsierra: yeah, you'll have to take that up with swank-clojure's current maintainer

15:53 slyrus: technomancy?

15:53 clojurebot: technomancy is to blame for all failures

15:54 slyrus: you the man, clojurebot

15:54 arkh: amalloy: that actually sounds fascinating - I need to look at the relevant source

15:55 stuartsierra: clojurebot: stuartsierra ?

15:55 clojurebot: stuartsierra is awesome

15:55 slyrus: surely there's an army of swank-clojure using minions here?

15:55 stuartsierra: :)

15:55 it used to say "stuartsierra is volunteering"

15:55 abedra: stuartsierra: evidently you upgraded

15:56 clojurebot: abedra ?

15:56 clojurebot: Huh?

15:56 abedra: lol

15:56 exactly

15:57 stuartsierra: :)

15:57 slyrus: so there's no magic syntax for lein's dependencies like "my-proejct-THE-NEWEST-AND-KEWLEST-VERSION-EVARRR"?

15:58 which makes me think that clojure.jar should be a dev-dependency for all of my projects

16:00 technomancy: slyrus: swank has clojure as a dependency so you can have standalone swank sessions outside a project

16:00 stuartsierra: Yo, haters, check out "rebuild" branch at https://github.com/stuartsierra/clojure/tree/rebuild

16:00 fix the tests for me

16:01 technomancy: slyrus: but if leiningen is preferring swank's version of clojure over the one you're specifying in project.clj that is a bug.

16:01 I don't think that's what you mean though

16:02 stuartsierra: technomancy: it happens when swank is a dev-dependency

16:02 you get one clojure in lib/dev and another in lib

16:02 technomancy: oh, ok; is this bad because it's messy or because it's causing actual breakage?

16:03 stuartsierra: causes breakage

16:03 I work around it by using :exclusion[s org.clojure/clojure]

16:04 arkh: where's the clojure code that implements = ?

16:04 amalloy: arkh: not in clojure

16:04 it's in java. src/jvm/clojure/lang/RT, i think

16:05 slyrus: technomancy: what do you mean a "standalone" swank session? surely whatever environment is going to try to invoke functionality from swank-clojure.jar can be smart enough to find a clojure.jar somewhere?

16:05 technomancy: so... jars from lib/ definitely have precedence over lib/dev.

16:05 arkh: amalloy: thank you

16:05 stuartsierra: ok

16:05 amalloy: arkh: and i think the relevant method is called equiv

16:05 slyrus: technomancy: I'm not sure what you mean by precedence, but they're both on the classpath

16:05 amalloy: $source =

16:05 sexpbot: = is http://is.gd/gYMyK

16:05 technomancy: slyrus: the ~/.lein/bin/swank-clojure shell script starts a standalone swank session

16:05 slyrus: the classpath operates on a first-entry-wins basis

16:06 stuartsierra: I ran into some bugs when both 1.2 and 1.3 were present

16:06 amalloy: arkh: apparently it's clojure.lang.Util.equiv(x, y)

16:06 stuartsierra: but maybe that was caused by something else

16:06 slyrus: technomancy: bin/swank-clojure sets up its own classpath!

16:07 technomancy: if they are easily reproducible then I would love to hear more, especially as there's a release soon.

16:07 slyrus: if it were pulling it from ~swank-clojure/project.clj your argument might hold water

16:08 arkh: amalloy: you rock

16:08 lrenn: does maven not do evictions? (ie, if it finds clojure 1.2 and 1.3 it will use 1.3 but tell you it isn't going to use 1.2)

16:08 technomancy: slyrus: right; that's what "lein swank" is for

16:08 * amalloy leans on sexpbot to find things in the source :P

16:08 technomancy: the swank-clojure shell script is something totally different

16:08 stuartsierra: lrenn: it does, but lein has 2 separate dependency lists

16:08 amalloy: sexpbot: botsnack

16:08 sexpbot: amalloy: Thanks! Om nom nom!!

16:09 slyrus: technomancy: you said " slyrus: the ~/.lein/bin/swank-clojure shell script starts a standalone swank session" and "swank has clojure as a dependency so you can have standalone swank sessions outside a project"

16:10 technomancy: anyway, if you can reproduce a problem that arises from having dev-deps on the classpath please file a bug report; I need to head off

16:10 slyrus: are you saying that swank-clojure's project.clj needs clojure as a dependency to make lein happy?

16:10 dev-deps on the classpath aren't a problem!

16:10 two clojure jars on the classpath is the problem

16:11 swank's clojure.jar should be a dev-dependency, if you ask me

16:11 lrenn: stuartsierra: right. thanks.

16:12 slyrus: and it's fine (as far as I'm concerned) for lein to have clojure as a dependency, rather than a dev-dependency, which should make standalone swank sessions work fine

16:18 tonyl: &(source =)

16:18 sexpbot: java.lang.Exception: Unable to resolve symbol: source in this context

16:18 tonyl: ~#source =

16:18 clojurebot: It's greek to me.

16:18 tonyl: clojurebot: help

16:18 clojurebot: help is http://clojure.org

16:18 hiredman: ~source =

16:18 tonyl: $help

16:18 sexpbot: You're going to need to tell me what you want help with.

16:18 tonyl: $help source

16:18 sexpbot: tonyl: Link to the source code of a Clojure function or macro.

16:19 tonyl: $source =

16:19 sexpbot: = is http://is.gd/gYMyK

16:19 hiredman: oh hell

16:20 tonyl: $help help

16:20 sexpbot: tonyl: Get help with commands and stuff.

16:20 tonyl: $help list

16:20 sexpbot: tonyl: Lists the available help topics in the DB.

16:20 tonyl: $list

16:20 sexpbot: I know about these topics:

16:31 amalloy: tonyl: i don't think there's a list of all commands available directly from sexpbot, but there's one at https://github.com/Raynes/sexpbot/wiki/Commands

16:32 tonyl: amalloy: thanks

16:33 amalloy: sexpbot: remind me to add that

16:33 sexpbot: also remind me to add a $remind command :P

16:34 tonyl: amalloy: is it possible to sed sexpbot responses?

16:35 amalloy: tonyl: you mean, ask sexpbot to repeat the last thing he said, but sedded? not currently

16:35 tonyl: sexpbot technomancy ?

16:35 sexpbot: technomancy ?

16:36 amalloy: $whatis technomancy

16:36 sexpbot: technomancy does not exist in my database.

16:36 tonyl: or change the reply to why?

16:36 why?

16:36 clojurebot: http://clojure.org/rationale

16:36 tonyl: those kind of replies

16:37 amalloy: you'd have to write a new plugin for it. and also convince Raynes and me that it's a good idea :P

16:37 tonyl: alright :P

16:37 amalloy: clojurebot already jumps on a lot of messages; it's hard enough keeping the two of them from stepping on each other's toes

16:37 tonyl: yeah

16:37 i likt the $command syntax though

16:38 amalloy: $whatis sexpbot

16:38 sexpbot: sexpbot does not exist in my database.

16:38 amalloy: $whatis sexpbot the bestest sexpbot ever

16:38 sexpbot: sexpbot does not exist in my database.

16:38 tonyl: $whatis clojure

16:38 sexpbot: clojure does not exist in my database.

16:38 amalloy: oh right

16:38 $learn sexpbot the bestest sexpbot ever

16:38 sexpbot: My memory is more powerful than M-x butterfly. I wont forget it.

16:38 amalloy: $whatis sexpbot

16:38 sexpbot: sexpbot = the bestest sexpbot ever

16:38 tonyl: nice

16:39 * amalloy wonders what M-x butterfly does

16:40 * tonyl gotta get back to fix trixbox machine

16:54 belun: $learn belun not what, but who ? strong male

16:54 sexpbot: My memory is more powerful than M-x butterfly. I wont forget it.

16:54 belun: $whatis belun

16:54 sexpbot: belun = not what, but who ? strong male

16:57 lrenn: do sexbotp and clojurebot work just the same if you /msg them? :)

16:58 tonyl: $tryhaskell reverse "hello"

16:58 sexpbot: => "olleh"

16:59 amalloy: lrenn: yess

17:00 oh, i get it. you were subtly telling them to stop spamming :P

17:00 i missed the :) - a lot of people actually don't know and aren't willing to try it

17:01 tonyl: :P

17:02 :P you are right

17:10 bendlas: Hey, folks

17:10 tonyl: hello

17:11 bendlas: Is there a resource for conj talks somewhere?

17:12 lancepantz: bendlas: dont think so yet

17:13 bendlas: Specifically I'd be interested in rhickeys reasoning about making ^:static default

17:14 dnolen: bendlas: there quite a bit of chatter about that in the irc logs while you wait for the video

17:15 bendlas: I'll check that out, thx

17:15 hiredman: ^:static is not default

17:15 I really wish people would stop saying that

17:16 I specifcly asked rich to clarify that at the conj

17:16 non-dynamic is not the same thing as :static

17:16 dnolen: bendlas: hiredman is correct, the changes were really about binding, the benefits of static fell out of the changes.

17:17 bendlas: hiredman, in which way will those differ?

17:17 _isn't_ static all about binding time?

17:18 hiredman: no

17:18 bendlas: Where, of course static enables compile time inlining, ...

17:19 hiredman: :static causes "hard references" to the class of a function to be inserted at compile time

17:19 no

17:19 :static is not compile time inlining

17:19 bendlas: But enables it

17:19 hiredman: no

17:20 dnolen: bendlas: any perf benefits from ^:static were from hotspot optimizing your code at run time, ^:static also supported primitive arg/return

17:21 bendlas: Ok

17:22 dnolen: now since dynamic binding is no longer the default, and the semantics of unbounds has changed, you get the benefits of static w/o doing anything at all, you can redef (:static didn't allow this), and you get primitive arg/return. primitive fns can now interop w/ protocol fns as well.

17:24 bendlas: Was just gonna ask that, thx

17:25 dnolen: bendlas: the biggest difference in the new world is that unbound vars no longer throw errors during compilation.

17:25 bendlas: So you'll need :dynamic for (binding ...) ?

17:25 dnolen: bendlas: yes

17:26 tonyl: is this in 1.3.0 alpha2 ?

17:27 dnolen: tonyl: yes

17:27 bendlas: dnolen, sounds reasonable

17:28 Does that mean you can defn in arbitrary order like in a java class body?

17:29 jarpiain: the compiler must resolve the vars on the first pass so you still have to (declare ...)

17:32 * bendlas needs to find an instance where a (declare ...) d but unbound var would cause compile errors

17:32 tonyl: ping?

17:32 clojurebot: PONG!

17:33 tonyl: $ping

17:33 sexpbot: tonyl: Ping completed in 0 seconds.

17:33 bendlas: Ok guys, thanks for the info. Blog material on the issue still seems a bit sparse

17:35 amalloy: tonyl: any reason you need to ping both of them?

17:35 and not, say, /msg one or both of them?

17:36 jarpiain: (declare x) (def y x) throws unbound var error in 1.2

17:36 bendlas: ^^

17:37 tonyl: my bad, out of habit

17:38 dnolen: bendlas: it is alpha stuff, and most people are still trying to understand 1.2.0 :)

17:44 neotyk`: how do you jump to end of expression with paredit?

17:45 scottj: C-M-n

17:49 and C-M-e depending on definition of expression

18:05 amalloy: anyone happen to know the maximum length of an irc message?

18:07 mabes: (set! *warn-on-reflection* true) issues warnings on compilation.. is there a way to have the warnings issued whenever Reflector.getMethods is used?

18:07 I've type hinted all the code that seems like a bottleneck but Reflector.getMethods is still taking ~20% of the process

18:09 neotyk`: scottj: thanks!

18:24 powr-toc: what's the purpose of Channels? I mean what do they offer over lazy-seqs?

18:25 Is it just that they're queues?

18:28 amalloy: powr-toc: channels in what context? like java.nio.Channels?

18:33 powr-toc: amalloy: as in aleph/lamina... I'm guessing they might be nio channels underneath https://github.com/ztellman/lamina

18:33 but I think they're using a clojure.lang.BlockingQueue

18:34 amalloy: powr-toc: not that i know anything about lamina, but those are definitely not nio Channels

18:34 powr-toc: no they're not nio channels

18:34 they're purely for in process communication

18:36 amalloy: powr-toc: did you read the wiki entry as the readme suggests?

18:36 powr-toc: yes...

18:37 I mean I see how they're different from seqs... in that seqs are pulled and they're pushed

18:37 slyrus: is there a new (clojure-1.3-ish) replacement for c.c.except?

18:38 and it looks like all of the various clojure-contrib-1.3-ish changes mean that folks code/build-hackery that works on 1.3 isn't likely to work will under 1.2 anymore, right?

18:38 powr-toc: I'm just not sure what to use them for

18:39 amalloy: powr-toc: and they allow arbitrary amounts of forking - four channels which are all dumping into one master channel, which is again being sucked into two duplicate channels with different callbacks

18:40 powr-toc: amalloy: I saw that... I guess the thing I'm not clear on, is how multiple consumers can ever use these without interfering with each other

18:41 I guess I need to play with them...

18:41 amalloy: powr-toc: instead of having them all plugged into the same channel, you can fork the channel

18:41 then they each get a private copy

18:43 powr-toc: amalloy: but fork consumes and removes all the messages from the channel

18:43 or am I reading that bit wrong

18:43 amalloy: you are

18:44 see also near the top "If two callbacks are registered on an empty channel, they both receive the next message."

18:45 powr-toc: amalloy: ahhh ok... I missed that bit... now it makes a bit more sense

18:47 slyrus: anyone have a good example of a clojure-1.3-ready lein project.clj?

18:50 ah, this is the syntax I was looking for: [org.clojure.contrib/def "1.3.0-SNAPSHOT"]

18:54 :( is swank-clojure broken with the current slime?

18:59 amalloy: slyrus: i've heard technomancy say that slime breaks all by itself pretty often; there's some version or other he recommends you stick with, rather than living on the edge

19:00 rata_: hi all

19:01 slyrus: amalloy: and with that attitude it will never get fixed :)

19:01 amalloy: slyrus: feel free to join the emacs slime community :P

19:03 insomniaSalt: Versions differ: 2010-11-03 (slime) vs. 20100404 (swank). Continue? (y or n) y

19:03 Derander: I'm using nil (slime)

19:03 don't know how I ended up w/ that

19:03 slyrus: insomniaSalt: yeah, but it's been doing that for a long time. that's not the breakage I'm referring to.

19:03 * slyrus has too many moving parts ATM

19:04 lancepantz: slyrus: yes, swank clojure is broken with slime HEAD

19:04 insomniaSalt: i remember trying to fix that :-)

19:04 slyrus: :( ok, thanks lancepantz

19:08 hmm... I wish slime had two histories. one for my CL REPLs and one for my clojure REPLs.

19:09 M-p isn't very useful when it's giving me back CL forms in a repl connected to a swank-clojure instance

19:10 amalloy: slyrus: two emacs frames/screens?

19:10 slyrus: amalloy: sure, but when I start a new session it doesn't keep track of the two old ones

19:11 and I'm not supposed to use *earmuffs* for non-dynamic vars anymore?

19:15 perhaps it was premature to try to go to 1.3

19:16 technomancy: earmuffs have always been only for dynamic vars

19:22 slyrus: technomancy: there's a difference (in my mind anyway) between a constant var that is globally accessible and a globally accessible var whose value can be changed by bind

19:28 amalloy: pppaul: ping

19:28 pppaul: $8ball pong?

19:28 sexpbot: pppaul: Most likely.

19:28 slyrus: I guess I'm just used to CL's special variables

19:29 pppaul: no specials in clojure?

19:29 amalloy: pppaul: just wondering whether you're finding the try/catch macro useful or inadequate

19:29 slyrus: pppaul: you have to declare your vars as dynamic now if you want (bind [...] ...) to work

19:29 pppaul: oh, i didn't get it to work... i tried macro-expanding and it would just give me the evaluated forms...

19:30 i went to sleep after you gave it to me, and i haven't done anything with clojure since then ^_^

19:30 amalloy: pppaul: (macroexpand '(whatever)), not (macroexpand (whatever))

19:30 pppaul: ooooooooooooh

19:30 silly me

19:31 amalloy: ##(macroexpand '(when (pred x) x))

19:31 sexpbot: ⟹ (if (pred x) (do x))

19:31 pppaul: i think i broke clojure... can't find the defmacro symbol

19:34 cool

19:34 looks like it works ^_^

19:37 amalloy: let me know whether you find it convenient or annoying when you've played with it a bit

19:38 pppaul: (defn col-width [n table] (reduce max (map #(? (count (nth % n))

19:38 :oops 0)

19:38 table)))

19:38 seems good for simple try-catches ^_^

19:39 maybe i should be using the maybe monaaaaaaaaaaaaaaaaaaad

19:39 amalloy: that doesn't really seem applicable to finding a max

19:40 pppaul: i don't really know what to apply any monad to right now... the wikipedia entry isn't helping much since it's all in haskell

19:43 rata_: pppaul: http://intensivesystems.net/tutorials/monads_101.html

19:43 pppaul: reading that too

19:43 rata_: ok

19:43 pppaul: i thought it would be better for me to start with wikipedia, though

19:45 rata_: i thought the same, but that article resulted to be much more useful for me

19:47 pppaul: ^_^

19:47 (doc map)

19:47 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

19:48 pppaul: woot, seems to work the way i want it to

19:48 map is so sexy

19:51 slyrus: hrm... what am I supposed to make of this: NoSuchMethodError clojure.core$concat.invokeStatic(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; clojure.contrib.def/defalias (def.clj:66)

19:53 amalloy: slyrus: that's java's equivalent of a linkage error

19:53 the code was compiled against one version of clojure, and is running against another

19:54 slyrus: ah, but which code?

19:54 amalloy: clojure.contrib doesn't match clojure.core

19:54 slyrus: oh, I see... ok.

19:54 :(

19:54 amalloy: make sure your deps are right in project.clj

19:54 and lein deps. maybe that will help

19:56 slyrus: I think I built clojure-contrib improperly

20:01 amalloy: slyrus: why build it at all? just get the binary

20:01 slyrus: that just seems _wrong_

20:04 Derander: I have an atom @keep-running.

20:04 I am trying to swap its value out from true to false

20:04 (swap! @keep-running false) says "java.lang.Boolean cannot be cast to clojure.lang.Atom"

20:04 amalloy: Derander: two errors there

20:04 &(swap! (atom true) (constantly false))

20:04 sexpbot: ⟹ false

20:04 amalloy: &(swap! @(atom true) (constantly false))

20:04 sexpbot: java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.Atom

20:04 amalloy: &(swap! @(atom true) false)

20:04 sexpbot: java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.Atom

20:05 amalloy: anyway, the first is what you want

20:05 technomancy: three if you count using swap! instead of reset!

20:05 Derander: ah, thank you

20:05 amalloy: technomancy: yeah, i suppose so

20:05 Derander: technomancy: checking documentation

20:05 amalloy: thanks for your examples :P

20:06 okay, that is indeed what I want

20:06 technomancy: Derander: swap+constantly will work, but reset! is what you really mean.

20:06 Derander: yeah

20:06 I misunderstood how swap worked

20:06 it's all good now

20:23 pppaul: how do i do newlines with pr-str?

20:39 tonyl: prn-str

20:42 pppaul: doesn't seem to be working

20:43 &(prn-str ".....\n.....")

20:43 sexpbot: ⟹ "\".....\\n.....\"\n"

20:43 pppaul: &(pr-str ".....\n.....")

20:43 sexpbot: ⟹ "\".....\\n.....\""

20:43 pppaul: &(prn-str ".....\\n.....")

20:43 sexpbot: ⟹ "\".....\\\\n.....\"\n"

20:45 pppaul: &(print ".....\\n.....")

20:45 sexpbot: ⟹ .....\n.....nil

20:46 pppaul: &(print ".....\n.....")

20:46 sexpbot: ⟹ ..... .....nil

20:46 pppaul: print is more like what i want than prn-str.... but still not doing newlines

20:47 tonyl: prn-str appends a newline char at the end. do you want it somewhere else?

20:48 pppaul: i have newlines in my strings

20:48 i think sexpbot doesn't do newlines

20:49 tonyl: so u want to get rid of them or actually display them in the repl like a new line?

20:49 pppaul: yeah, (print is working

20:49 tonyl: ok

20:50 alexyk: evening

20:51 I have a gigantic lazy seq, like there's no tomorrow

20:51 I want to extract pieces from each element and dump into a text file, line per elem

20:51 pppaul: $8ball is there a tomorrow?

20:51 sexpbot: pppaul: Concentrate and ask again.

20:51 alexyk: is write-lines meaningful for it?

20:51 or it will force lines?

20:52 lazy seq is produced from mongodb as (fetch :collection)

20:52 tonyl: when u r using i/o i think there is no way than to force the seq

20:52 pppaul: (apply write-lines seq) ???

20:52 tonyl: that would probably cause an SOE

20:53 but who knows

20:53 alexyk: Son of Eve?

20:53 pppaul: lol

20:53 tonyl: lol stackoverflow error

20:53 you can partition the seq and then map through it

20:54 alexyk: yeah... what do we do when we can't us ewrite-lines, like some nasty file handle and a writer?

20:54 tbatchelli: I always play Bocelli when you join

20:55 tbatchelli: :D

20:56 alexyk: not a bad choice

20:56 alexyk: batchelli sounds like a batch version, as opposed to an interactive one

20:57 * alexyk can't help parsing words

20:57 tbatchelli: alexyk: I am glad you didn't parse it as bat-chelli... as in MS-DOS

20:58 alexyk: tbatchelli: any luck with Twitter data?

20:58 tbatchelli: alexyk, not yet, got distracted with other cool stuff :) re: #pallet

20:59 alexyk: tbatchelli: bat-chelli are like multiple MS-DOS chello synthesizers, or miniature chelloes for bats :)

20:59 livingston: i'm driving myself crazy trying to get mvn clojure:swank to run the JVM with more memory (e.g. the equivalent of setting -Xmx4G) ... the variables are documented on the clojure-maven-plugin site, but I can't figure out how to set them through maven. Do any of you do that?

21:00 alexyk: pallet looks cool indeed, I'd like to get a cluster to test it

21:01 tbatchelli: I meant celli of course

21:01 form cello

21:01 livingston: isn't a whole point of maven to drive one crazy?

21:02 livingston: up until this point it has saved me a lot of trouble

21:02 tbatchelli: alexyk: I like miniature chelloes for bats... make for a nice image in my brain :)

21:03 livingston; part of the license you're accepting by running maven is that you sell your soul to the devil... and the devil eventually comes back to claim it. It's still the best alternative out there though.

21:03 alexyk: tbatchelli: imagine a whole cave with all the bats playing celloes! now that's a great Xmas card

21:04 livingston: "up to this point" means it's the point of no return :)

21:04 livingston: i'm also assuming that (.maxMemory (Runtime/getRuntime)) will show me the value of the -Xmx argument

21:06 alexyk: livingston: seems to report correctly

21:08 livingston: alexyk: yeah I keep seeing 129957888 instead of the 4G I ask for

21:09 alexyk: livingston: I switched to lein and cake... but you can ask on clojure-maven list

21:13 livingston: alexyk: arghhh I just noticed pom was requesting clojure-maven plugin v1.3.2 the feature I wanted was added at 1.3.4 and 1.3.5 is current doh! (still have a problem, but it's a start)

21:13 alexyk: aha

21:18 chouser: there's not a single write-lines in TJoC?!

21:19 chouser: eh? write-lines?

21:20 alexyk: chouser: yeah, from duck streams. Not a single usage!

21:20 livingston: alexyk: yeah lein isn't really an option for me, we have too much java in house and it's the primary language, so I need something that plays more nice with java

21:20 alexyk: I wanted to find IO wisdom!

21:21 livingston: understood, I did the same in a joint Scala/Clojure project

21:21 * alexyk still wants to play with Polyglot Maven

21:22 alexyk: chouser: I was spoiled by write-lines and can't find a simple way to just open a damn writer and write line by line. What is the clojure way to do that?

21:22 lancepantz: livingston: does maven not honor $JAVA_OPTS ?

21:22 alexyk: besides calling a javaesque writer directly

21:22 tonyl: what about with-open

21:22 livingston: lancepantz: I really don't know

21:22 lancepantz: i would expect it to

21:23 alexyk: tonyl: and then chain nasty buffered writers on top of writers?

21:23 livingston: lancepantz: the thing is this is weird because it's a java called by the clojure-maven plug-in that starts the swank server

21:23 chouser: alexyk: I generally use Java methods directly

21:24 alexyk: chouser: :(

21:24 livingston: I don't necessarily want to globally set my java to 4G either

21:24 chouser: alexyk: maybe clojure.java.io/writer

21:24 ...and then java methods. *shrug*

21:24 livingston: this worked: mvn -Dclojure.vmargs=-Xmx4G clojure:swank but this does not: mvn -Dclojure.vmargs="-d64 -Xmx4G" clojure:swank so I'm not sure how to set 2 options yet

21:24 alexyk: yeah

21:27 * alexyk finds that #clojure makes a great pastime in a moving bus

21:28 alexyk: lancepantz: I read the above as, "does maven has no honor anymore?!"

21:29 lancepantz: yes!

21:30 or no! depending on how you parse the negative

21:31 alexyk: lancepantz: yeah. or no. :)

21:33 hugod: livingston: https://github.com/hugoduncan/pallet/blob/master/pom.xml sets clojureOptions for clojure-maven-plugin

21:34 livingston: hugod: thank you so much - I was using the wrong setting I guess, I was using clojure.vmargs

21:35 it's unclear to me what the different settings are for

21:38 hugod: that seemed to work although it was nice having the command line option

21:41 hugod: livingston: https://github.com/talios/clojure-maven-plugin seems to suggest that there isn't one in "Configuring your clojure session"

21:44 livingston: yeah, but what's the difference between "jvm args" and "additional jvm args" ?

21:50 hugod: livingston: vmargs doesn't seem to appear anywhere in the clojure-maven-plugin source

21:51 livingston: hugod: odd. it does respond when I gave it the single parameter to raise the heap size though... it's gotta be in there somewhere?

22:12 ustamills: hey all

22:12 Are there really 236 users in this room? Or did my chat client miscount?

22:13 KirinDave: Nope.

22:13 amalloy: ustamills: most of them are idling, usually, like most irc channels :P

22:13 ustamills: We had maybe 9 Wednesday.

22:14 amalloy: in #clojure?

22:14 ustamills: Yeah

22:14 amalloy: no way

22:14 ustamills: Unless there's another clojure chat room, yeah way.

22:14 amalloy: there are more than 9 people who never log out

22:14 hiredman: <--

22:14 KirinDave: Netsplit.

22:14 Perhaps?

22:14 amalloy: could be

22:15 ustamills: What's netsplit?

22:15 amalloy: large-scale connection problems

22:15 ustamills: i c

22:16 This is good, then. Wed night was my first night on. This is a pleasant surprise.

22:16 Derander: I never log out

22:17 amalloy: yeah. on occasion there can be no talking for an hour or two, but never are there so few people around

22:18 ustamills: Question then. I don't get recur vs basic recursion just yet. Why do we need the recur function (or special form, or whatever it is) rather than just use straight recursion?

22:18 amalloy: ustamills: you run out of stack space without recur

22:19 ustamills: I haven't in other Lisps. What happens in clojure?

22:19 amalloy: &(let [f (fn x [] (x))] (f))

22:19 sexpbot: java.lang.StackOverflowError

22:19 ustamills: It's a java thing?

22:19 amalloy: &(let [f (fn x [] (recur))] (f))

22:19 sexpbot: Execution Timed Out!

22:19 amalloy: no, any language will have it

22:19 you can easily overflow the stack; i did when i was learning CL

22:20 livingston: ustamills: the jvm does not support the standard things compilers do to implement tail recursion

22:20 ustamills: I guess, just practically, I didn't see it in z-lisp. Maybe it was possible.

22:20 livingston: Thanks, I was wondering about the java part (not a java expert at all)

22:20 dnolen: ustamills: recur and recursion from the tail position are equivalent. but recur also works with anonymous fns and loop.

22:21 livingston: real lisp compilers are smart and optimize tail recursion for you BUT they aren't required to like they are in say Scheme, in common-lisp it's just a bonus if you get it

22:22 johndeo: The jvm is likely to support tail call optimization at some point, right?

22:22 That's what rich hickey says in his talks.

22:22 amalloy: and you can write code that's hard, or impossible for any compiler to optimize right

22:22 dnolen: johndeo: less likely in the near future with Oracle driving.

22:22 livingston: ustamills: since there are some ways to support TCO (tail call optimization) without the JVMs help, Rich decided to implement them, but to be sure you don't think you are getting it when you aren't he decided to make you request it, and if it can't give it to you it will error

22:22 johndeo: That Oracle stuff is CRAZY

22:23 but typical

22:23 Derander: of course oracle would start fucking with java right as I start to use it/clojure :P

22:23 literally within 1 week

22:23 livingston: keeping people from shooting themselves in the foot is ok sometimes, not sure how happy I am with this particular design decision though

22:23 hiredman: ~oracle

22:23 clojurebot: The sky is falling!

22:24 ustamills: Maybe somebody could look at this. I'm trying to write my first recur function, an exponent function. Easy in recursion, but I don't get the recur version....

22:24 johndeo: I can't see any way they can pull the rug out on 50 bazillion companies using open source Java

22:24 hiredman: they aren't

22:24 they never said they would

22:24 they have infact said they won't

22:24 ustamills: (defn pwr [ x y ]

22:24 (loop [myx x

22:24 myy y]

22:24 (if (>= y 1)

22:24 (recur (* myx myx) (dec myy))

22:24 myx)))

22:24 hiredman: johndeo: please don't spread that fud here

22:24 ustamills: I know the (* myx myx) bit isn't what I mean. Not sure how to say what I mean though.

22:25 johndeo: Okay, I'll go get more informed.

22:25 livingston: johndeo: I don't know, it would be nice, if they implement it. the JVM is far ahead of Java so... you never know.

22:26 amalloy: ustamills: you're close

22:27 ustamills: I tried to execute (using Slime) and it just went away and never showed anything

22:27 amalloy: ustamills: because you're testing y, not myy

22:27 livingston: ustamills: i'm not sure that's computing x^y but something more like factorial? or weirder

22:27 ustamills: ,DOH

22:27 clojurebot: java.lang.Exception: Unable to resolve symbol: DOH in this context

22:28 amalloy: &'DOH!

22:28 sexpbot: ⟹ DOH!

22:28 amalloy: but you need to actually recur on three parameters. (1) the base, (2) the exponent left to work on, and (3) what the product so far is

22:29 ustamills: #3 is the part I'm missing.....

22:29 amalloy: well er

22:29 livingston: you can also recur to the main call too, remove the loop and recur directly to pwr itself

22:29 amalloy: (1) isn't necessary, since base is a constant

22:30 &(loop [base 2, pow 5, acc 1] (if (zero? pow) acc, (recur base (dec pow) (* acc base))))

22:30 sexpbot: ⟹ 32

22:31 livingston: tbatchelli: I just climbed into the depths of maven and reclaimed my soul, at least for today. we'll see when it gets me again (trying to simultaneously develop code in the repl from two projects will probably be another 10 round knock-out challenge)

22:31 amalloy: ustamills: is how i would write it. look over it, try to make sense of it, and ask whatever questions you have left

22:31 ustamills: Woot! Thanks!

22:31 (defn pwr [ x y ]

22:31 (loop [res x

22:31 myy y]

22:31 (if (> myy 1)

22:31 (recur (* res x) (dec myy))

22:31 res)))

22:32 amalloy: ustamills: please don't make huge pastes here

22:32 use a paste site like https://gist.github.com/

22:32 ustamills: Will do. Thanks.

22:33 amalloy: yep, that looks like a perfect exponent function

22:33 tbatchelli: livingston: are you sure you are the same person than a couple of hours ago? I think you need to be quarantined!

22:34 amalloy: ustamills: to convert a singly-recursive function to a tail-recursive function, usually you need to add one more variable, which "accumulates" the value you're planning to return

22:34 livingston: tbatchelli: i do have this cough, ..

22:35 ustamills: Because we aren't really doing recursion, we're doing, basically, goto's.

22:35 amalloy: right

22:36 (and not just basically gotos. actually gotos)

22:36 ustamills: If Java had tail call optimization, would Clojure still use recur?

22:37 amalloy: that's a philosophical question, i suspect

22:37 dnolen: ,((fn [base exp] (reduce * 1 (take exp (repeat base)))) 2 0)

22:37 clojurebot: 1

22:37 dnolen: ,((fn [base exp] (reduce * 1 (take exp (repeat base)))) 2 16)

22:37 clojurebot: 65536

22:38 dnolen: ustamills: strong support for lazy sequences are another useful tool to work around the lack of TCO.

22:38 livingston: ustamills: it would become redundant, unless there were still some cases where it couldn't be had and people still wanted you to beg for it. -- I would hope that it would go away at that point though, certainly it shouldn't not give it, just because you didn't ask.

22:38 ustamills: dnolen: Thanks for the post, I just realized my fn doesn't handle the 0 exponent

22:38 _fogus_: ustamills: I think yes

22:38 livingston: dnolen: lazy seqs are useful, but they are not directly related to TCO

22:39 dnolen: ustamills: the current real painpoint for lack of TCO is mutally recursive functions, trampolines work but are kinda slow

22:39 amalloy: dnolen: (= (repeat exp base) (take exp (repeat base)))

22:39 ustamills: Not grokking the lazy sequences just yet ......

22:39 dnolen: livingston: they are in the sense that rhickey forefronted them in the lang specifically because lack of TCO.

22:40 KirinDave: Huh

22:40 It's disappointing to see someone as smart as nk say shit like: http://twitter.com/nk/status/3234929919918080

22:40 amalloy: ustamills: they're incredibly powerful. if you ever find yourself actually writing recursion or loop/recur, often you should reevaluate and use the builtin lazy functions

22:41 dnolen: KirinDave: I saw that, I was thinking of snarky responses, but not worth it.

22:41 _fogus_: KirinDave: That is a lot of nothingness. I don't even understand his point.

22:41 Derander: I'm lost too :P

22:41 livingston: dnolen: I don't see what one has to do with the other? one is a way to use things like map even though you know you aren't going to go all the way through the list; the other is a way to write simpler code without blowing the stack -- they are orthoganal

22:41 amalloy: &(nth (iterate #(* 2 %) 1) 6)

22:41 sexpbot: ⟹ 64

22:42 Derander: "java runs on processors. clearly procedural programming is better."

22:42 hiredman: most of the state in the clojure compiler is bound vars (threadlocal)

22:42 amalloy: livingston: no

22:42 dnolen: livingston: not true, lazy sequences are a general way to represent any kind of computation without blowing the stack.

22:42 KirinDave: _fogus_: I think he' arguing that "if immutability is so great, why don't you marry it?

22:42 amalloy: livingston: lazy seqs let you write simpler code without blowing the stack too

22:43 hiredman: offhand I can't think of any state in the compiler that isn't in vars

22:43 _fogus_: KirinDave: If purity is so great, then why even turn on the machine?

22:44 hiredman: 103103

22:44 ~#103

22:44 clojurebot: 103. Purely applicative languages are poorly applicable.

22:44 livingston: yes, lazy seq happen to work like the recur implementation, but that doesn't mean they are isomorphic -- regardless it's not important to me at this time of night

22:45 dnolen: livingston: you can think what you like, but rhickey has said as much. I defer to him ;)

22:45 livingston: er, maybe in this case they can substitute for each other, but the use cases are or should be different

22:46 KirinDave: What's even weirding is that clojure is all about controlling mutability

22:46 Not immutability.

22:47 That's prolog, down the hall.

22:47 livingston: I tend to write a lot of recursive code as if I was in Scheme, it's not necessarily good style, but the Franz Allegro compiler was so good I got kind of spoiled. having to flag it all the time is a real bummer now.

22:47 ustamills: begs the question.... Why use recur over lazy seqs, or the reverse?

22:48 livingston: ustamills: recur is for when you intend to go the whole way, and just want to save the stack frames, lazy seq is for being speculative that you might not go all the way down the rabbit hole and would like to save the work if you can

22:49 .. in general - from a readability and intent point of view.

22:50 dnolen: ustamills: recur is 'strict' simpler semantics, lazy is just that lazy, there's all kinds of implication because of that. many a Clojurian has been burned by a lazy sequence.

22:51 livingston: only if you are counting on side effects ;) (which is frequently unavoidable once you brush too close against java)

22:51 amalloy: livingston: still wrong

22:51 livingston: actually it hits me a lot when I want to wrap time around something

22:52 amalloy: you can build lazy sequences that blow the stack if you try

22:53 dnolen: livingston: there's lots of scenarios where laziness will bite you even when you're writing purely functional code. i.e. debugging lazy code is generally a big PITA.

22:53 livingston: anyone can blow anything up if they do it wrong, but I don't get it, here you all just spend I don't even know how long trying to tell me lazy = recur ...

22:54 * dnolen looks forward to george jahad writing a lazy sequences debugger

22:56 ustamills: Getting recur very slowly ... (and maybe the bot too)

22:56 .((fn pwr [x y] (loop [r 1 i y] (if (>= i 1) (recur (* r x) (dec i)) r))) 2 3)

22:56 amalloy: ustamills: comma or &, not period

22:56 ustamills: :) tx

22:57 amalloy: (& is the bot Raynes and i work on, , is hiredman's bot)

22:57 ustamills: ,((fn pwr [x y] (loop [r 1 i y] (if (>= i 1) (recur (* r x) (dec i)) r))) 2 3)

22:57 clojurebot: 8

22:57 ustamills: ((fn pwr [x y] (loop [r 1 i y] (if (>= i 1) (recur (* r x) (dec i)) r))) 2 0)

22:57 ooops

22:57 , ((fn pwr [x y] (loop [r 1 i y] (if (>= i 1) (recur (* r x) (dec i)) r))) 2 0)

22:57 clojurebot: 1

22:58 ustamills: tx everybody. Now I go read seqs.

23:06 harishtella: does anyone know of a good example/tutorial on understanding clojure java interop ( stuff like proxy and binding)

23:08 amalloy: harishtella: binding isn't really to do with java interop

23:09 but labrepl has a good thing on proxy/swing interop

23:09 https://github.com/relevance/labrepl

23:10 harishtella: amolloy: got that, will look into it

23:10 thanks

23:14 I wish http://clojuredocs.org/ was more prominently linked on clojure.org

23:19 livingston: later. thanks for the conversation / help everyone.

Logging service provided by n01se.net