#clojure log - Oct 16 2011

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

0:51 todun: I'm trying to figure out how this work. It seems simple but I'm not quite sure how inc does its work here. Any assistance is appreciated. http://pastebin.com/mFucfv5n

0:54 amalloy: todun: do you know what inc does?

0:54 todun: amalloy: inc a number right?

0:54 by one

0:54 so like java's ++

0:54 amalloy: not ++, which implies mutation

0:55 it just returns (+ 1 x)

0:55 todun: amalloy: oh.

0:56 amalloy: in that case and with recursion in the picture, maybe I see what's happening.

0:56 amalloy: so inc will keep returning (+ 1 x ) until size (rest v) is empty

0:57 then all those will be combined?

0:58 (+ 1 (+ 1 (+ 1 ...(0) ...)))

0:58 amalloy: indeed, but not (0)

0:58 just 0. stop calling things as functions :)

0:58 todun: amalloy: oh. ha.

0:59 (+ 1 (+ 1 ( + 1 ...(+ 1 0) ...) ) )

1:00 ibdknox: amalloy: macro question for you

1:01 amalloy: let's say I have a macro (defmacro aw [q] (+ ~q ~q))

1:01 amalloy: ibdknox: plus the missing `?

1:01 ibdknox: amalloy: er, yes

1:02 amalloy: will q be evaluated twice?

1:02 amalloy: yes

1:02 ibdknox: amalloy: so in such a case, you want to let the result?

1:03 amalloy: definitely

1:03 ibdknox: I'm not sure why I never internalized that until now

1:03 but it explains why my shit was broken :)

1:05 FrankL: What is a nice way to 'unpack' a map of set -> value relations? e.g. {#{:a :b :c} 1, #{:d} 2} would become {:a 1 :b 1 :c 1 :d 2}

1:05 amalloy: FrankL: actually, i have that code lying around somewhere

1:06 FrankL: amalloy, cool!

1:06 amalloy: https://github.com/flatland/useful/blob/develop/src/useful/map.clj#L172

1:07 FrankL: wow, that's exactly what i was looking for

1:07 ibdknox: haha amalloy: I love this: (map (to-fix (! set?) hash-set) entry)

1:07 FrankL: thanks!

1:07 ibdknox: really just the (! set?)

1:12 amalloy: ibdknox: what's the point of having a utility library if you don't use it to make your code short

1:12 ibdknox: 's true

1:12 I just think it reads amusingly :)

1:13 amalloy: it does. mapping over a collection known to be two elements long is also good for a laugh

1:14 FrankL: it's not exactly what you want, since it produces {:a #{1}} instead

1:14 ibdknox: all the cool kids are doing it these days :p

1:17 FrankL: yup

1:18 and i have no idea what's going on in those functions!

1:18 but figuring that out should teach me some things

1:36 devn: hey all

1:37 todun: I rewrote my nested reversal function from before to use recur. But now it just always returns an empty list. Am I misusing recur? Thanks. http://pastebin.com/hdRUYY9G

1:38 ibdknox: todun: you never put anything into acc

1:39 todun: ibdknox: uhm.

1:39 ibdknox: let me try something.

1:39 ibdknox: right now you're just reversing an empty list for every element in lst

1:40 todun: ibdknox: It seems then I'm using recur rightly but doing recursion wrongly.

1:43 ibdknox: is this a correct use of let? (recur (let [(rest temp-lst) acc]) (reverse acc) ))) or does the scope of using let have to be in the square-brackets?

1:43 ibdknox: todun: you have the let backwards

1:44 todun: how so?

1:44 ibdknox: ,(let [x (inc 1)] x)

1:44 clojurebot: 2

1:45 todun: uhm. I misread then. thanks.

1:45 MGT: ,1

1:45 clojurebot: 1

1:49 kanja: http://pastebin.com/XtS20p38

1:49 Raynes: ibdknox: Where is mah noir tryclojure?

1:49 todun: ibdknox: in your example you have x being the result type. I'm doing the following and it seems that acc isn't being updated. Do I have to put the result type after the let assignment(or I guess it's a local function)? (recur (let [acc (rest temp-lst)]) (reverse acc))))

1:49 kanja: I'm getting can't resolve guess in this context - but I have no idea which guess it's talking about. Any ideas?

1:50 ibdknox: Raynes: I got distracted by more important things :p

1:50 Raynes: I feel unimportant now.

1:50 ibdknox: aw

1:50 but I'm doing it for the greater good!

1:51 Raynes: kanja: For one, you need to wrap each arity in parentheses. (defn sq-iter ([x] ..) ([guess x] ..))

1:51 ibdknox: todun: the scope of the let is only valid for what's inside of it, your use of acc is outside of your let

1:51 Raynes: Second, don't put closing parens on they're on line.

1:51 their*

1:51 own*

1:51 * Raynes has a very, very bad headache.

1:51 todun: ibdknox: ok. thanks. let me try again..

1:52 kanja: Raynes: Yeah - Sorry, still learning the syntax.

1:52 Raynes: I guess that doesn't excuse not being able to type. Maybe my fingers are throbbing with my head.

1:52 todun: Raynes: sorry.

1:52 ibdknox: Raynes: get off the computer... that only makes it worse

1:52 todun: Raynes: idomatic clojure?

1:52 Raynes: kanja: I wasn't scolding you, just giving you a heads up. :)

1:52 todun: *idiomatic.

1:52 Raynes: todun: I was replying to kanja actually. Haven't been following your particular conversation.

1:52 ibdknox: flux helps.

1:52 todun: Raynes: ok.

1:53 kanja: :)

1:53 Thanks for the help

1:53 duck1123: feel free to put parens on their own line while you're coding it, just remember to clean up all that wasted space when you're done

1:53 kanja: I'm used to emacs lisp so I'm all kind of wierded out :)

1:53 duck1123: this is where paredit is great

1:54 Raynes: duck1123: Why encourage it at all? :p

1:54 kanja: I'm actually using paredit for the first time with this

1:54 I'm having a little trouble getting used to it

1:54 what's the right way to do the closing parens? all on the same line?

1:54 Raynes: Right.

1:54 ibdknox: Raynes: did you use the paredit clone for vim?

1:54 Raynes: One or two people in the universe disagree.

1:54 ibdknox: Yes. It was nice.

1:55 ibdknox: hm, maybe I should do that

1:55 lol

1:55 duck1123: I tend to be free with hitting enter while I'm coding so I have plenty of space to put new stuff, but I always clean up once I know I'm done for now

1:55 Raynes: ibdknox: Slurp, join, barf. Your life will be so improved.

1:55 ibdknox: haha

1:55 such nice names for the commands

1:55 kanja: haha

1:56 the default binding for them on emacs sucks

1:56 Raynes: duck1123: If there is even one parenthesis on a line alone, I freak out. My eyes start flashing red and sirens sound. It is the only thing I can think about until I fix it.

1:56 kanja: c-m-left for slurp

1:56 Raynes: Huh?

1:56 It's C-left/C-right for me.

1:56 No Ms about it.

1:58 kanja: huh, yeah

1:58 I guess I had it wrong

1:59 Raynes: Vim uses Leader< and Leader>

1:59 kanja: still not crazy about that though - I hate dropping down to the arrows

1:59 Raynes: I can't navigate with letter keys. My fingers don't work like that.

1:59 kanja: huh

2:00 duck1123: I use the arrows more, but there's always times when the letters save my life

2:00 Raynes: Well, I mean character-by-character navigation. Not clever commands. Those are a different beast entirely.

2:03 kanja: clever commands?

2:03 duck1123: C-t is a clever command

2:03 I never use it right

2:03 Apage43: for me i didn't really get used to using letters for navigation until I got really into using all the keys in vi

2:03 and also xmonad

2:04 and now it's just a can't be arsed to move my fingers all the way over to the cursor keys thing

2:04 kanja: yeah that's kind of how I feel

2:04 although I haven't made the jump into a twm yet

2:04 Apage43: kanja: i don't bother unless i've got a dual monitor setup

2:05 but in that case it really is nice. It's a "can't be arsed to move my mouse across two whole monitors and arrange crap manually on that much space" thing.

2:05 duck1123: I'm a fan of stumpwm

2:05 kanja: Apage43: Yeah, I'm using a laptop right now without much screen space, but my friends have been yelling about i3 for a while now

2:05 duck1123: I bind the stumpwm key to capslock

2:06 kanja: oof no good with emacs

2:06 I need that for control

2:07 duck1123: I played with using menu for it, but I've since then assigned that to gnome-do

2:07 Apage43: I still haven't been able to get used to using capslock for something else

2:07 i never really feel like touching that key

2:07 amalloy: duck1123: i also always forget to use C-t, so i rebound it to transpose-sexps, and now i use it all the time

2:07 duck1123: ooh, transpose-sexps... need to learn that one

2:08 amalloy: you should really rebind caps lock, whatever editor you use. for me, it helped a lot to relieve emacs-pinky

2:09 kanja: yeah I could never use emacs w/o capslock

2:09 amalloy: i gather it's just as useful for vim

2:09 duck1123: My left wrist has been messed up for like a week now. Damn emacs pinky

2:10 kanja: haha I just got bit by clj's ratios - the default case used 1 rather than 1.0 so I got a huge ratio and assumed my logic was bad

2:10 what's the use of the ratios?

2:10 more precision?

2:11 duck1123: ,(+ 1/3 1/3 1/3)

2:11 clojurebot: 1N

2:12 kanja: what does the N mean?

2:12 amalloy: &(class 1N)

2:12 lazybot: java.lang.NumberFormatException: Invalid number: 1N

2:12 amalloy: ,(class 1N)

2:12 clojurebot: clojure.lang.BigInt

2:12 kanja: ah

2:12 ty

2:12 amalloy: i'm surprised that results in 1N rather than 1, duck1123

2:13 todun: (recur (let [acc (rest temp-lst) acc (reverse acc)]) acc))) puts the acc in the [] scope. I yield it outside its scope so that recur can have access to its value. It still gives me an empty paren output. I'm obviously still doing something wrong.

2:13 ibdknox: is there some better way to execute a collection of functions over something than doing (reduce #(%2 %) ...)? My brain has stopped working.

2:13 duck1123: amalloy: yeah, same here

2:13 ibdknox: huh

2:13 amalloy: ibdknox: ((apply comp fs) x)?

2:13 i guess that goes in the wrong order

2:13 ibdknox: order doesn't matter

2:14 duck1123: It's going to be hell. I've been trying to get Gloss working correctly with 1.3, but right now, just about every single test fails due to comparing ratios with floats

2:14 ibdknox: duck1123: woah, really?

2:14 ,(= 1/2 0.5)

2:14 clojurebot: false

2:14 ibdknox: ...

2:14 kanja: yikes

2:14 duck1123: As far as I can tell, it still works, but all the tests fail

2:15 kanja: so uh, what's the point of the ratios?

2:15 ibdknox: wtf

2:15 kanja: sounds like they're causing issues

2:15 duck1123: There was a thread on the ml about it. word of god was that was intentional and by design

2:15 amalloy: ,(= 1 (+ (/ 1.0 3) (/ 1 3) (/ 1 3)))

2:15 clojurebot: false

2:15 kanja: is clj not ducktyped then?

2:16 amalloy: that is why ratios exist

2:16 duck1123: ,(== 0.5 1/2)

2:16 clojurebot: true

2:16 ibdknox: ,(doc ==)

2:16 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

2:16 kanja: ,(doc =)

2:16 clojurebot: "([x] [x y] [x y & more]); Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner. Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison."

2:16 ibdknox: is that new?

2:16 kanja: ah interesting

2:16 amalloy: ibdknox: no

2:17 duck1123: == is ancient, iirc

2:17 amalloy: though i think the docstring is less true in 1.3 than it used to be

2:17 ibdknox: that doc string is wrong now, type does matter for numbers :p

2:17 amalloy: ibdknox: i don't remember what the difference is though, do you?

2:18 ibdknox: amalloy: nope

2:18 ,(= 1N 1)

2:18 clojurebot: true

2:18 ibdknox: ,(= 1/1 1)

2:18 clojurebot: true

2:19 duck1123: ,(== [0.5] [1/2])

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

2:19 ibdknox: I guess I should've looked at the numerics changes closer

2:20 ,(= 1 1.0)

2:20 clojurebot: false

2:20 ibdknox: are floats the only thing that don't play with everyone else now?

2:20 duck1123: that one makes sense

2:20 ibdknox: duck1123: how so?

2:21 duck1123: 1.0 is not really 1. 1.0 can approximate 1 but they're not really the same and that difference will bight you

2:22 Not that I often need that distinction in practice...

2:23 ibdknox: I haven't done enough real numerical stuff to know why that's the case, but that's counter intuitive to me :)

2:23 MGT: ,(== 1 1.0)

2:24 clojurebot: true

2:25 ibdknox: == seems like the simple solution though

2:25 assuming you don't care

2:25 duck1123: generally though, you're going to know when you're going to be getting floats

2:27 MGT: ,(replicate 5 'a')

2:27 clojurebot: (a' a' a' a' a')

2:27 MGT: ,(replicate 5 "a")

2:27 clojurebot: ("a" "a" "a" "a" "a")

2:28 ibdknox: ,''

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

2:28 ibdknox: ,'a'

2:28 clojurebot: a'

2:28 ibdknox: interesting

2:28 learn something new every day

2:29 amalloy: ibdknox: 1.3 adds terminating-quotes in symbols, yeah?

2:29 or perhaps intervening

2:29 ,'a'b

2:29 clojurebot: a'b

2:30 amalloy: mostly in order to get auto-promoting arithmetic operators like +'

2:30 ibdknox: I see

2:30 tomoj: didn't replicate get removed?

2:30 ibdknox: that would make sense

2:30 ,(doc replicate)

2:30 clojurebot: "([n x]); DEPRECATED: Use 'repeat' instead. Returns a lazy seq of n xs."

2:31 ibdknox: not yet

2:31 amalloy: three cheers for deprecation

2:31 MGT: ,(doc repeat)

2:31 clojurebot: "([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs."

2:31 devn: why?

2:31 clojurebot: devn: because you can't handle the truth!

2:31 devn: lol

2:31 ibdknox: (inc clojurebot)

2:31 lazybot: ⟹ 7

2:31 ibdknox: ~anyone

2:31 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:32 ibdknox: good

2:32 it doesn't say I will answer questions :p

2:32 devn: ^anti-community statement by clojurebot

2:32 "don't waste my mother fucking time"

2:32 * devn eyerolls

2:32 ibdknox: yeah

2:32 lol

2:32 he's got shit to do

2:33 MGT: how do i do clojure

2:33 * ibdknox grabs his pitchfork

2:33 devn: "I'm an important businessman and I am receiving telegraphs from important foreign dignitaries. Kindly phrase your question in a way that pleases me, else you may shut the fuck up."

2:33 --clojurebot

2:33 amalloy: devn: yes please, *don't* waste my time by forcing me to say "yes, i am interested in answering a question" before i can hear your damn question

2:33 tomoj: "here's a tip that will make it more likely for you to get an answer"

2:34 devn: MGT: With great aplomb.

2:34 MGT: That's how.

2:34 MGT: ,(doc aplomb)

2:34 clojurebot: Excuse me?

2:34 MGT: ???

2:34 lazybot: MGT: Oh, absolutely.

2:35 devn: aplomb |əˈpläm, əˈpləm|

2:35 noun

2:35 self-confidence or assurance, esp. when in a demanding situation: Diana passed the test with aplomb .

2:36 ibdknox: clojurebot: anyone is <reply>Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

2:36 clojurebot: c'est bon!

2:36 ibdknox: ~anyone

2:36 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:36 ibdknox: amalloy: what'd I do wrong?

2:36 devn: ibdknox: treat it like an infobot

2:36 (that's what you did wrong)

2:36 amalloy: ibdknox: you need to tell him to forget the old one

2:37 devn: ibdknox: The old way was: "clojurebot: no, anyone is..."

2:37 Not sure if it conforms to that or not

2:37 ibdknox: clojurebot: forget anyone is <reply>Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:37 clojurebot: 'Sea, mhuise.

2:37 ibdknox: clojurebot: anyone is <reply>Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

2:37 clojurebot: Ack. Ack.

2:37 amalloy: noooooo

2:37 ibdknox: ~anyone

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

2:37 devn: clojurebot: no, anyone is a funny thing.

2:37 clojurebot: Ik begrijp

2:38 devn: clojurebot: anyone

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

2:38 devn: immutability is a harsh mistress every now and again

2:38 amalloy: ibdknox: the syntax for deleting stuff is really awkward. usually you just end up adding more accidentally

2:38 ibdknox: lol

2:38 amalloy: clojurebot: forget anyone?

2:38 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:39 ibdknox: lol

2:39 amalloy: hm. anyway, my point is he's now learned a meaning for "forget anyone"

2:39 ibdknox: oh

2:39 whoops

2:39 what was the correct way then?

2:39 amalloy: clojurebot: forget anyone |is| <reply>Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:39 clojurebot: I forgot that anyone is <reply>Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:39 ibdknox: ah

2:39 amalloy: clojurebot: forget forget anyone |is| <reply>Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:39 clojurebot: I forgot that forget anyone is <reply>Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

2:40 amalloy: ~anyone

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

2:42 devn: wow, that's not confusing.

2:43 ibdknox: it's why I got it right on my first try ;)

2:51 MGT: http://pastebin.com/hBx6ZLSX

2:51 is the first function as efficient as the second?

2:51 oops

2:52 http://pastebin.com/5p9xDB7x corrected first function

2:53 duck1123: MGT: you only need to check up to n/2

2:53 MGT: well

2:53 I only need to check up to sqrt(n), strictly speaking

2:53 clojurebot: brain dump is http://clj.thelastcitadel.com/clojurebot

2:53 MGT: but the second one uses tail recursion

2:54 and I was wondering if that makes it faster

2:54 ibdknox: lol

2:54 clojurebot is so weird

2:56 duck1123: MGT: some also uses recusion

2:57 MGT: is it tail recursion?

2:57 duck1123: (when (seq coll) (or (pred (first coll)) (recur pred (next coll))))

2:57 ibdknox: sweet

2:58 korma is getting somewhere now :D

2:58 MGT: sorry, what's that?

2:58 ibdknox: getting the table prefixes right was a lot harder than I expected

2:58 MGT: definition of some?

2:58 duck1123: MGT: that's the source body of some

2:58 MGT: ok, thanks

2:58 I have to familiarize myself with seq

2:59 duck1123: ibdknox: I look forward to giving korma a shot. (once I get back out of the Ruby hell i'm in at work)

2:59 ibdknox: duck1123: as of tonight it might actually be worth it

3:00 duck1123: still a few important loose ends I need to tie up

3:00 but I think I did the hard part

3:00 duck1123: did you ever figure out that whole lazy map thing you were working on?

3:01 ibdknox: I punted on that for now

3:01 Right now it's set up that if you do a has-many

3:01 it maps executing that query over the result set

3:02 so in the case that a user has many addresses

3:02 (select user (with address)) would return back (map get-and-assoc-addresses users)

3:03 duck1123: so are the records returned actual Records (in the defrecord sense)

3:03 ibdknox: not at this point

3:03 why, what are you thinking?

3:03 duck1123: I rely on being able to determine the class of a record for a lot of Ciste

3:04 ibdknox: it would be trivial to add meta-data to it

3:04 saying where something came from

3:04 creating records dynamically sounds a lil scary

3:05 amalloy: (inc ibdknox)

3:05 lazybot: ⟹ 4

3:05 tomoj: ciste? is that the gismu or a coincidence?

3:05 duck1123: structure

3:05 tomoj: yeah :)

3:07 duck1123: And then I named my identi.ca clone Jiksnu after jikca casnu for "social type of interaction"

4:03 tolstoy: When I hit "control-c" after "lein run," none of my shutdown hooks are run (Mac OSX). Is that because leiningen forks the JVM? (kill -2 <pid> works just fine).

4:03 amalloy: ibdknox: you could allow the user to pass you a constructor function at some point, and then dealing with records would be their problem

4:06 ibdknox: amalloy: that sounds reasonable, I was basically going to add something like that in anyways.. basically a transform that gets applied anytime the entity is retrieved

4:06 I say basically a lot when I get tired

4:06 lol

4:06 I was currently testing how slow string concat is

4:07 trying to determine if a query should use a single stringbuilder the whole way through

4:07 seems the difference of marginal practical value

4:07 I was generating around 30,000 complex queries a second

4:08 if you actually have a DB that can respond to that...

4:08 you're awesome :p

4:09 amalloy: ibdknox: basically, when you get tired, you say a lot

4:10 ibdknox: amalloy: haha fine. I'll go to bed.

4:10 amalloy: noooo, how will i query my databases?

4:11 ibdknox: I hear writing SQL by hand is fun :D

4:12 tolstoy: Ah, "lein trampoline" solves my problem.

4:13 ibdknox: alright folks, I've had enough SQL'ing for one day

4:14 g'nite!

4:24 archaic_: i'm trying to unquote from a syntax quote without namespace resolution.. currently i'm using `(~(symbol "+")) to get the job done but i assume there is a better way?

4:24 amalloy: &`(... ~'+)

4:24 lazybot: ⇒ (... +)

4:25 amalloy: though you should usually think twice about why you want to do this

4:26 archaic_: yeah thats the one.. thx.. the reason I want this.. I want to print data so I can view it easy.. but reuse it later in code.. otherwise I would get 3-4 lines of output with clojure.core/+ etc.. and I can't view results easy

4:30 zilti: I need a little help with 4clojure problem 21. What I have by now is #(fn [x] (if (= (count x) (+ (- (count %1) %2) 1)) (recur (rest x)) (first x))) %1) But that doesn't work??

4:30 lazybot: zilti: What are you, crazy? Of course not!

4:31 zilti: lazybot: How could you answer before I released my return key? That's even too fast for a bot!

4:32 Raynes: amalloy: He has a point. lazybot is awfully fast for such a complexbot.

4:33 I mean, he fires those hooks machine gun style.

4:34 zilti: That's why, one day, lazybot will take over the world - despite his lazyiness

4:34 amalloy: zilti: well, #(fn ...) has got to be a mistake

4:34 you don't want to create a function that returns a function, you just want a plain old function

4:35 zilti: amalloy: I actually wanted to create a function that calls an anonymous function defined within it to use recursion and an additional val.

4:35 But I guess that's bad style?

4:36 amalloy: zilti: that's fine style, sometimes

4:36 here you have some additional problems, like your parens don't match up

4:36 raek: zilti: a common technique is to let a function called "step" (or something similar) that does the recursion, and then simply call it with the initial parameters in the let body

4:37 amalloy: well. simpler to use loop/recur if you're going to be recur'ing anyway

4:37 raek: zilti: but with 'loop' and 'recur', you can often do without the let

4:38 zilti: I'll try it with let. I'll have to define "step" inside let, right?

4:43 raek: yes

4:43 zilti: argh.

4:44 raek: the idea is that you want to recur with one set of "loop parameters", but the outer function takes another set of parameters

4:44 zilti: So it is #(let[step (fn [x y z] (...))] (step %1 %1 %2))? But that gives me errors

4:44 raek: let's take ye olde factorial function as an example

4:46 (fn factorial [n] (let [step (fn [acc i] (if (zero? i) acc (recur (* acc i) (dec i))))] (step 1 n))

4:47 you can rewrite this with loop and recur

4:48 (fn factorial [n] (loop [acc 1, i n] (if (zero? i) acc (recur (* acc i) (dec i)))))

4:51 this is also a possible way:

4:51 (fn factorial [n] ((fn [acc i] (if (zero? i) acc (recur (* acc i) (dec i)))) 1 n))

4:51 I think that was what you tried to do originally

4:51 notice the "(("

4:52 zilti: Why those?

4:52 MasseR: Then you evaluate the newly-created function

4:53 raek: the inner one is for the (fn ...), which creates a new function

4:53 zilti: I'm totally confused as of now. My solution for problem 21 still doesn't work.

4:53 raek: the outer one calls that function with the arguments 1 and n (in my case)

4:53 zilti: "Can only recur from tail"

4:55 raek: it is also possible to do recursion without TCO by replacing 'recur' with the name of the function

4:55 anonyous functions can be named too :)

4:55 (fn f [..] ..f is available here..)

4:56 a variant of the factorial example that cannot be TCO'ed:

4:56 (fn factorial [n] (if (zero? n) 1 (* n (factorial (dec n)))))

4:58 the "(factorial (dec n))" call is not in tail position since the function does not return the result of that expression directly - the (* ..) call waits for its value

5:00 zilti: So recur-ing inside an if doesn't work as well?

5:00 amalloy: zilti: it does, because recur can still return immediately - the if "part" has already been evaluated

5:01 zilti: amalloy: But it doesn't work here.

5:01 amalloy: zilti: no, something else doesn't work :P

5:01 zilti: It says "can only recur from tail position"

5:01 amalloy: ~bug report

5:01 clojurebot: A bug report has three parts: What you did; what you expected to happen; what happened instead. If any of those three are missing, it is awfully hard to help you.

5:02 pyninja: Hi, is there a way to run my Ring app in one thread and create another thread which checks every minute for scheduled notifications and sends them? Is this even a good idea? I've kind of avoided threads so far in my life...

5:03 cark: java.util.Timer, its callback is on a separate thread

5:03 amalloy: pyninja: certainly it's possible. i don't see any immediate reason why it would be a terrible idea

5:04 pyninja: cark, amalloy: ok, cool

5:04 cark: carefull about the Timer callback tho, you'd better spawn another thread from there

5:04 depending on your use case

5:04 amalloy: $javadoc java.util.Timer

5:04 lazybot: http://download.oracle.com/javase/6/docs/api/java/util/Timer.html

5:04 pyninja: how do you mean?

5:05 cark: i don't remember right now, but i seem to recall you should not raise exceptions from this callback

5:05 pyninja: hm ok thanks

5:06 cark: Timer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread

5:06 raek: pyninja: also take a look at http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledExecutorService.html

5:06 cark: that's why i was spawning threads

5:06 raek: it's more mature

5:06 cark: so it's not about exceptions after all =)

5:07 raek: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newScheduledThreadPool(int)

5:07 pyninja: hm interesting

5:08 cark: reak: oh this one looks interesting

5:08 so it picks a free thread from the pool and runs it ?

5:09 yes that's exactly what pyninja needs

5:10 pyninja: yeah actually this way i wouldn't have to save scheduled notifications somewhere and send them all at once, i think i could just use scheduler.schedule

5:11 zilti: Why doesn't this recur work? http://pastie.org/2704759

5:11 raek: cron4j is interesting too

5:11 amalloy: pyninja: i actually wrote a teenty-tiny wrapper around this java functionality a while ago, at https://github.com/amalloy/cronicle/blob/develop/src/cronicle/core.clj

5:12 pyninja: amalloy: oh, cool. thanks a lot!

5:13 amalloy: zilti: it's much easier to see the problem if you get the indentation to match with the parens: https://gist.github.com/76362d613a17d59369bb

5:14 the call to (step lst) is actually inside the body of step, not in the outer function

5:16 as an aside, putting braces on the previous line C-style is going to horribly mislead people, especially you. best to keep each open-paren right next to the thing it opens

5:18 zilti: Oh great. "You tripped the alarm! nth is bad!" I don't even use nth now. Well at least I don't get other errors.

5:21 amalloy: &(macroexpand '(fn [[x]] x)) ;; zilti - this is usually why that nth-message comes up, but i agree it's a terrible message and wish there were some simple way to explain the issue

5:21 lazybot: ⇒ (fn* ([p__15973] (clojure.core/let [[x] p__15973] x)))

5:21 amalloy: &(macroexpand '(let [[x] (range)] x))

5:21 lazybot: ⇒ (let* [vec__15981 (range) x (clojure.core/nth vec__15981 0 nil)] x)

5:29 zilti: Bah. I get a class cast exception on the 4clojure REPL for code that works flawlessly in my REPL.

5:30 #((let[step (fn [frag] (if (= (count frag) (+ (- (count %1) %2) 1)) (first frag) (recur (rest frag))))] (step %1)))

5:31 raek: zilti: you have one pair of parens too much arount let

5:31 *around

5:33 also, I think it's easier to spot mistakes like this if you use the (fn ..) syntax instead of the #(..) syntax

5:40 robermann: hi

5:54 Borkdude: I'm developing a web noir app on my local machine, but I need to pass a callback url that needs to be in dev-mode "localhost:8080/smth" and on heroku obviously something else. how do I get the "localhost:8080" part programmatically ?

6:26 todun: I have been trying to fix this recursion for some time. I think I'm just missing something small, but cannot find it. Any help is appreciated: http://pastebin.com/cQsfNjW8

6:48 hugod: todun: what does your let form return?

6:49 todun: hugod: uhm. I don't follow.

6:49 do you mean what does it match?

6:49 or yield.

6:51 or if you mean return in the java sense, I didn't know let could return a value and did not write it thusly.

6:56 hugod: todun: the value the let form evaluates to

6:56 todun: hugod: oh ok. I'm not sure.

6:56 hugod: I was using let so that I could have a computation part and a recursive part.

6:57 the computation will give the recursive part its result.

6:57 os so was the plan.

6:57 the computation will reduce the problem.

6:58 hugod: ,(let [x 1])

6:58 clojurebot: nil

6:58 todun: hugod: I see.

6:59 maybe that's my problem, yes?

7:00 hugod: I'm not sure what the code is supposed to do, but I imagine that is part of the problem

7:01 zilti: Why doesn't that work:

7:01 ,(cons (1) ())

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

7:02 todun: hugod: sorry. it does nested reversals of a list.

7:03 hugod: so. I'd posted earlier and forgot that I should re-write the description.

7:03 hugod: so I have reverse. and then, for each list within a list of lists, I want to reverse those so that the list is reversed at all levels.

7:04 stuarthalloway: ,(1)

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

7:04 hugod: todun: you might also want to println the value of acc and temp-lst inside the loop, to get an idea of what is happening

7:04 todun: hugod: I'm doing a bunch of recursive problems and almost all of them are not working. I believe it is my misuse of recur & loop.

7:04 hugod: ok.

7:05 zilti: ,(cons '(1) ()) ; But how can I do that if I just have an argument instead of (1) ?

7:05 clojurebot: ((1))

7:05 daniel__: anyone ever got: unable to attach to a dyno when running a console session on heroku?

7:06 nvm, i had to add logging

7:09 stuarthalloway: ,(let [a '(1)] (cons a ()))

7:09 clojurebot: ((1))

7:13 zilti: stuarthalloway: http://imgur.com/KZB38

7:13 stuarthalloway: Fifth line is the problem, the (cons pack lst) part

7:14 stuarthalloway: zilti: it is pretty odd to use cons not conj btw

7:16 zilti: partition-by in core is a generalization of the fn you are writing, you should study it

7:17 ,(partition-by identity [1 1 2 1 1 1 3 3])

7:17 clojurebot: ((1 1) (2) (1 1 1) (3 3))

7:19 hugod: todun: the values passed to recur become the new values associated with the loop variables, so the value returned by let (which was nil) is being assigned to temp-lst on the next time through the loop

7:20 todun: hugod: uhm ok. I didn't realize this behavior was possible in let.

7:24 hugod: todun: see the example in http://clojure.org/special_forms#Special%20Forms--(recur%20exprs*)

7:24 todun: hugod: that makes sense.

7:25 hugod: so instead of a nil result type, the result is the binding of y

7:26 hugod: I'm just surprised it's affecting me, because I'm not using the result for anything. should I just set it to something?

7:26 I thought recur didn't use the result from its first argument.

7:28 hugod: in your example, the first value passed to recur becomes the value of temp-lst on the next iteration (and the second argument becomes the the value of acc)

7:29 todun: uhm. ok. that was not the effect I thought of when writing this, but that does help my agenda in this problem.

7:37 is it possible to do multiple args to a function in clojure and/or currying? http://pastebin.com/u0HsrHUk

7:40 zilti: todun: There are partials and varargs

7:42 todun: zilti: uhm. ok. will those let me do (defn yes [y] [n] ...) by default?

7:48 Is there an inbuilt function to remove a specific item from a list so that the output sequence does not have the item so removed? thanks.

7:53 zilti: todun: afaik not, but you can partially apply functions using the "partial" macro

7:54 todun: zilti: ok. I'm reading that up now.

7:55 zilti: todun: There's no need for currying in a dynamic typed language. Currying is for using a multi-argument-function as an argument to a function that wants a single-argument-function as argument.

7:55 todun: zilti: also, I couldn't find anything on varargs wrt clojure. will it be like (defn yes [*var] ...)?

7:56 zilti: todun: The varargs symbol is &, not *

7:56 todun: zilti: the reason I asked to curry was so I could have multiple args which may or maynot bind.

7:56 zilti: so (defn yes [&var] ...) ?

7:59 zilti: todun: almost. (defn yes [& var] ... )

8:01 todun: zilti: thanks.

8:01 zilti: also do you know of any inbuilt function to remove a specific item from a list?

8:03 zilti: todun: sequences/filter

8:04 todun: zilti: ok. I'll check it out. thanks.

8:04 zilti: actually, it's in core, not sequences

8:04 http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/filter

8:05 todun: zilti: I've been having a hard time finding so many high order functions. Is there some repo list I can go to find stuff like this?

8:06 zilti: todun: Well, there's http://clojure.github.com/clojure/ and http://clojuredocs.org/ but you're right, it's kinda hard if you don't know what you're looking for.

8:07 todun: zilti: thanks. checking those out.

8:14 zilti: I'm trying to build a grelim zapper. to that end, I'm trying to construct a string containing all valid stuff I'm interested in and another containing all ASCII characters so I can filter out the good from the bad using both lists. Is there an easier way to do this?

8:14 zilti: for instance in python I can call something like ascii and I'll have all the ascii characters.

8:15 or something like that.

8:15 thanks.

8:17 zilti: todun: I don't know. I'm quite new to Clojure as well. Sorry.

8:17 todun: zilti: thanks all the same. :-)

8:18 zilti: todun: No problem :)

8:23 todun: zilti: going back to your suggestion about my nested rreversal's use of let, I try that but then I break its validity like so: http://pastebin.com/JugyPFux

8:23 zilti: perhaps you can see something I'm doing wrong...

8:23 thanks.

8:42 hugod: todun: what are you trying to do by using a let?

8:44 todun: hugod: I'm trying to preserve the value of acc, then transfer it to the second argument of recur. Also to make sure that acc doesn't hold on to its older value(an empty list) for every iteration of the loop.

8:46 hugod: todun: you can't affect the value of acc on the next iteration, except through the second argument to recur

8:47 let can only change the values bound to symbols within its body

8:49 todun:so what I think you want is something like (recur (next tmp-lst) (reverse (conj acc (first tmp-list))))

8:50 todun_: hugod: ok. I'm trying that now...

8:53 hugod: todun: what would you expect (let [x 1] (let [x 2]) (println x)) to print?

8:53 todun: hugod: the value of the last block evaluated.

8:54 hugod: so 2

8:54 I mean. the value of the last block that binds x's value.

8:54 I'm wrong.

8:55 the repl says 1 \n nil \n :-P

8:56 kjeldahl`: One parens too many after the second let expression []...

8:56 Move it to after the print...

8:57 ,(let [x 1] (let [x 2]) (println x))

8:57 clojurebot: 1

8:57 kjeldahl`: ,(let [x 1] (let [x 2] (println x)))

8:57 clojurebot: 2

9:01 todun: kjeldahl`: it ran ok as is in the repl for me though.

9:03 kjeldahl`: todun: If the expression you posted shows 2 in your repl, your repl is mistaken.

9:04 todun: it shows 1 :-D

9:05 kjeldahl`: Which is correct. Maybe I just did not understand your question. I though you expected it to show 2, but now I'm not sure.

9:07 todun: hugod: I get an exception when I tested it: http://pastebin.com/GLZf48dC

9:07 kjeldahl`: yes I expected it to show 2. but when I did it in the repl, it showed 1.

9:07 kjeldahl`: and so it was my reasoning about it that was wrong.

9:08 hugod: todun: don't worry about loop until you understand the lexical scope of let

9:08 todun: kjeldahl`: I was asking you why you made the comment about the parens.

9:08 hugod: ok.

9:09 hugod: loop is not something you need to learn initially

9:10 todun: hugod: but how can I accomplish my recursion without it?

9:11 hugod: todun: don't worry about anything until you understand why you got a 1 instead of a 2

9:11 todun: hugod: ok.

9:13 hugod: is this because the value of println x binds to the x coming from the outer let?

9:14 hugod: the println isn't within the body of the second let, so it sees the value bound by the first let

9:16 todun: hugod: oh ok. so it binds only with the (let ) scope.

9:16 hugod: I thought let was more restrictive in that it bound within the [] scope, no?

9:19 hugod: between, do you know how to use variable arguments in clojure? I'm having a hard time tracking down an explanatory example. thanks.

9:22 hugod: todun: variable arguments, or multiple arguments?

9:23 todun: hugod: actually both.

9:23 hugod: but I think I was making a mistake in my multi-arg...(defn yes [y] [n]...)

9:23 hugod: todun: (defun f [a b] (println a b))

9:24 todun: hugod: wow! that makes more sense! thanks.

9:24 hugod: now I find examples. I was searching for the wrong thing.

9:24 hugod: for varargs (defun [a & b] (println a b))

9:25 todun: hugod: I was searching for variable arguments instead of multiple arguments.

9:31 hugod: also, do you know if there is an inbuilt function to make a shell of nested loops? So instead of making the loop flat using flatten, I want to "ghost" the list of its elements.

9:33 gfredericks: todun: I would like to help but I have no idea what you're talking about

9:34 todun: gfredericks: an example should solve that problem. :)

9:34 given (1 (a (eqsd vsa)) 5 6 (7) ( )), the result is ((( )) ( ) ( )).

9:35 gfredericks: sorry about the confusion :-P

9:35 gfredericks: ah; so you're want to take a nested list and remove all the elements but keep the structure

9:36 todun: gfredericks: yes. that sounds like the proper way of saying it too. thanks.

9:36 gfredericks: well the (sequential?) function could help you pick between the things that are lists and the things that aren't

9:36 so ##(filter sequential? '(1 (a (eqsd vsa)) 5 6 (7) ( )))

9:36 lazybot: ⇒ ((a (eqsd vsa)) (7) ())

9:37 gfredericks: and then you can recursively map each one

9:37 so...

9:37 Bronsa: m

9:37 todun: gfredericks: thanks. that helps.

9:37 gfredericks: I've actually been stuck almost all weekend on recursion.

9:38 gfredericks: all my recursive implementations seem to not be working.

9:38 gfredericks: todun: did you want to see my implementation or try it yourself? :)

9:38 todun: gfredericks: try it out myself.

9:38 gfredericks: okay

9:38 todun: gfredericks: but I would like help on recursion.

9:38 gfredericks: I'm out for breakfast; have fun

9:38 will be back before too long, if you have specific questions

9:39 todun: gfredericks: thanks. will compose then as you munch.

10:00 gfredericks: todun: how's it going?

10:01 todun: still trying different things and reading more on the topic.

10:01 gfredericks: it occured to me that a lot of the recursive things you're trying could be handled by clojure.walk; which might again ruin your quest to "learn recursion"

10:02 todun: gfredericks: let me read up on that..one sec.

10:02 gfredericks: I also want to use more higher order functions to jump out of the imperative mindset..

10:04 gfredericks: it seems walk is like a generator of sorts, no?

10:05 gfredericks: walk lets you do things recursively to nested stuff

10:05 without having to do the recursion yourself

10:05 I just wrote your "list-ghosting" function with postwalk

10:06 todun: gfredericks: didn't find anything on the postwalk function.

10:07 gfredericks: http://clojure.github.com/clojure/clojure.walk-api.html#clojure.walk/postwalk

10:09 todun: gfredericks: uhm ok. I must have been using google wrongly. let me play with postwalk. thanks.

10:20 gfredericks: do I have to do some import? I keep getting source not available at the repl http://pastebin.com/5wJLKiAz

10:20 thanks.

10:25 gfredericks: (use 'clojure.walk)

10:26 todun: gfredericks: ok. let me try that. thanks.

10:26 gfredericks: yep

10:27 ghiu: hi, anyone with a bit of experience in compojure?

10:27 gfredericks: aye

10:28 shales: In clojurescript, how do I produce javascript like window["main"]? (aget window "main") isn't working

10:28 gfredericks: does (.main window) not work?

10:28 ghiu: gfredericks: this route definition doesn't work (GET "/add/?d=:d" [d] (add-gallery d)) <- can't i directly bind query string params?

10:29 gfredericks: ghiu: I don't think you need that explicit query string in the route

10:29 it'll collect all the query params for you, and you can bind them too, though I'm not sure the exact syntax. Might be (GET "/add/" {d :d} ...) or something like that

10:30 ghiu: (checking )

10:31 shales: gfredericks: no, window/main produces window.main, but I want to use javascripts array notation to avoid the advanced compiler renaming "main"

10:32 gfredericks: shales: okay. I don't know clojurescript well enough to keep helping then, sorry

10:32 todun: gfredericks: it seems I have to cast the result of the inner seq to that taken by postwalk.

10:32 gfredericks: todun: eh?

10:32 todun: gfredericks: I get an exception.

10:32 http://pastebin.com/r1jra2n2

10:33 and I was wondering if the fix was to cast the inner input into the the expected type of the outer one.

10:33 gfredericks: todun: that's an exception you get if you're accidentally calling a seq like it's a function: ##((range 12))

10:33 lazybot: java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

10:33 todun: since clojure is dynamically typed, I was not sure that was neccessary.(for I think of dynamic typing to be like automatic gear)

10:34 gfredericks: todun: yeah I don't think casting means anything in clojure

10:34 todun: gfredericks: oh. you can't do that in clojure?

10:34 gfredericks: I thought it was functional

10:34 gfredericks: todun: you can't call a seq like a function, no

10:34 what would you expect it to do?

10:35 todun: I thought it was a value

10:35 gfredericks: a seq is a value, but it is not a function

10:35 vectors are functions, and you could maybe want seqs to act like that, but they don't

10:35 &([7 8 3] 1)

10:35 lazybot: ⇒ 8

10:35 todun: gfredericks: sorry. I meant I thought functions were values..equational reasoning.

10:36 gfredericks: ok.

10:36 gfredericks: todun: they are in the sense you're probably thinking of, but that doesn't mean that everything is a function. in particular a seq is not a function, so you can't call it.

10:36 bpsm: todun: functions are values; but not all values are functions.

10:36 gfredericks: todun: just like you can't call a number: ##(7 :foo "bar")

10:36 lazybot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

10:36 todun: gfredericks: bpsm I see. thanks.

10:36 gfredericks: or a string ##("AHAHAHHA")

10:36 lazybot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn

10:36 ghiu: gfredericks: nope, it doesn't work

10:37 todun: gfredericks: so putting a & makes it a value?

10:37 gfredericks: ghiu: how so?

10:37 todun: no, & is for varags

10:37 todun: gfredericks: ok.

10:37 gfredericks: todun: it's hard for me to know what you're thinking about without seeing the code

10:37 todun: gfredericks: sorry. I thought I posted it..

10:37 let me repost.

10:38 gfredericks: not lately; last paste was just the error message

10:38 todun: gfredericks: ok. one second..

10:39 gfredericks: http://pastebin.com/1dvPXe3V

10:39 gfredericks: is the fastest way to get the last element of a vector just (v (dec (count v)))?

10:40 todun: my first result was a bit like that, so I made the same mistake you did

10:40 todun: gfredericks: I feel encouraged already.

10:40 gfredericks: todun: postwalk is going to call the function you give it on every element in the structure, including the leaves (e.g., the numbers) which are not seqs, so the function has to be able to handle both types

10:41 my function started with #(if (sequential? %) ...)

10:41 todun: ,(%)

10:41 ghiu: gfredericks: even this doesn't work and gives me page not found .. (GET "/add/" {params :params} (params :d));;(add-gallery d))

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

10:41 gfredericks: todun: Oh I just noticed you aren't even passing a function

10:41 todun: the first argument to postwalk has to be a function

10:41 ghiu: gfredericks: calling /add?d=http://asasdasd

10:42 todun: gfredericks: uhm..

10:42 gfredericks: ghiu: I think compojure is sensitive to trailing slash

10:42 ghiu: (GET "/add" …. doesn't work either!

10:43 gfredericks: ghiu: it should at least get there, whether or not the query binding works. Can you get it to work with no query-string or binding at all?

10:43 todun: in higher-order-functions like postwalk you often have to pass it a function

10:44 todun: gfredericks: (defn f [some-list] (filter sequential? some-list)

10:44 gfredericks: so I will pass f to it, no?

10:44 gfredericks: todun: you can do it at the top level using defn like you just suggested

10:44 you can also give the function inline with (fn [some-list] (filter sequential? some-list))

10:45 or more compactly, #(filter sequential? %)

10:46 todun: gfredericks: ok. so #(filter sequential? %) will be the arg to postwalk?

10:46 ghiu: gfredericks: this works (GET "/add" {params :params} "asd");;(add-gallery d)) when calling

10:46 gfredericks: ghiu: and then it complains it doesn't know what d is?

10:46 todun: yes

10:47 todun: you'll get an error on that, but it'll be a different error and you'll be a step closer :)

10:47 todun: gfredericks: ok. trying that. allot of new syntax and concepts here. so will quickly read up some.

10:48 gfredericks: I actually tried my way first. and I get another illegalArg exception

10:48 this time for integers.

10:49 gfredericks: todun: that's what I was thinking of when I said it was the same mistake I had made

10:49 ghiu: (GET "/add" {params :params} "asd") -> (GET "/add" {params :params} (params :d) -> error

10:49 gfredericks: the issue is that the function #(filter sequential? %) is going to be passed both the lists in the structure AND the leaf elements like the numbers

10:49 so it has to handle both

10:49 todun: I'm guessing because I have to make multiple functions and guard the inputs to postwalk?

10:49 gfredericks: right now that function just assumes its argument is a sequence because it passes it to filter

10:49 todun: true

10:50 gfredericks: ghiu: what's the error?

10:50 todun: so the next step would be to expand that function so it handles both cases, e.g. using if

10:50 in the case that the argument is not a function, you can just return the argument, as there's no transformation to do

10:50 s/function/seq/

10:50 lazybot: <gfredericks> in the case that the argument is not a seq, you can just return the argument, as there's no transformation to do

10:52 todun: gfredericks: ok. let me try something...

10:52 ghiu: gfredericks: seems like params keys are strings, not keyword, but anyway, i get no error, it simply return "Page not found" that is my not-found rute

10:53 gfredericks: ghiu: you go from a 200 to a 404 just by changing the body of the route?

10:54 todun: gfredericks: between I was trying to correct this code I found online. The error is in float. It takes too many arguments. But I'm not sure how to make sure it takes one argument and still preserve the logic of if. http://pastebin.com/VXgWKFP8

10:55 ghiu: gfredericks: yes

10:56 gfredericks: todun: that makes me think he defined a function called float= somewhere and had a typo when trying to refer to it

10:56 ghiu: then that is weird and I am confused.

10:56 todun: gfredericks: yes. that makes sense. woah, clojure truly is homoiconic if it can let you define such a token. thanks.

10:57 gfredericks: that just means it has permissive syntax for its symbols

10:57 (type 'float=)

10:57 ,(type 'float=)

10:57 clojurebot: clojure.lang.Symbol

10:57 gfredericks: ,(type '=)

10:57 clojurebot: clojure.lang.Symbol

10:58 todun: gfredericks: in clojure is permissive "syntaxing" the same as homoiconicity?

10:59 gfredericks: todun: no, homoiconicity is the fact that all of the clojure code is a clojure data structure; (+ 3 4) is a list of three elements: a symbol and two numbers

10:59 and it is also valid clojure code

11:00 try ((juxt eval reverse) '(+ 3 4)) in your repl

11:00 todun: gfredericks: ok...

11:00 gfredericks: I can't do it with the bots because they don't like eval

11:00 todun: gfredericks: ok. I did.

11:00 strange

11:01 never used eval before.

11:01 gfredericks: the point is you can treat the list like code (with eval) or like a list (with reverse)

11:01 that's what homoiconicity is talking about

11:02 todun: gfredericks: code is data, data is code..depending on context.

11:03 gfredericks: ,(map type '(defn foobar [& xs] (apply + xs)))

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

11:03 gfredericks: wut

11:03 oh geez

11:03 you could try that in the repl too

11:03 maybe try guessing what the output will be first

11:03 todun: gfredericks: strange.

11:04 gfredericks: but seemingly in line with what we'e talking about.

11:04 gfredericks: if you look at (defn foobar [& xs] (apply + xs)) as a data structure it should make sense

11:04 you should notice of course when I'm using the single-quote character to "quote" things

11:05 it's what keeps the code as a data structure instead of being evaluated

11:05 todun: gfredericks: making it a list.

11:05 gfredericks: ,(map type [(+ 3 4) '(+ 3 4)])

11:05 clojurebot: (java.lang.Long clojure.lang.PersistentList)

11:05 gfredericks: ,(list (+ 3 4) '(+ 3 4))

11:05 clojurebot: (7 (+ 3 4))

11:06 todun: gfredericks: ok. it preserves the data

11:06 and executes the code.

11:06 so what did you mean by permissive syntax?

11:07 gfredericks: todun: just that float= is a valid symbol, which I assume is what you were commenting on

11:08 my son just woke up so my attention will be sparse from here on out

11:09 todun: gfredericks: ok yes that's what I was talking about. thanks for all your help. I will come back to this latter in the day. perhaps we can talk more about recursion then. thanks again.

11:55 ghiu: can anyone check my problem with compojure out? it's described here: http://stackoverflow.com/questions/7785214/compojure-how-to-map-query-parametershttp://stackoverflow.com/questions/7785214/compojure-how-to-map-query-parameters

11:56 ehm http://stackoverflow.com/questions/7785214/compojure-how-to-map-query-parameters

12:00 kjeldahl`: Isn't params bound by default, see http://en.wikibooks.org/wiki/Compojure/Core_Libraries

12:01 In the 3rd example in the SO article, skip the {...} stuff and it should just work?

12:02 See "servlet bindings" in the wikibooks link.

12:04 ghiu: kjeldahl`: i've just checked out and get parameters are not bound by default, there's a middleware for that

12:05 kjeldahl`: but i still don't get why "add?:u" doesn't works as expected

12:09 zakwilson: Is it normal that a jar built under the Sun JDK isn't entirely reliable unde the Open JDK?

12:12 kjeldahl`: ghiu: I've struggled with the same a long time ago, and I do believe that the params map was (or is) bound by default, but I do not have a handy example. The compojure source also indicates this, by wrapping wrap-keyword-params by default.

12:14 ghiu: how did you work it out?

12:15 kjeldahl`: Aha!

12:15 See https://github.com/weavejester/compojure - Breaking changes!

12:25 ghiu: kjeldahl`: oh! thank you, but… it doesn't seem to work either :( query parapets are still missing from params

12:31 kjeldahl`: is wrap-params supposed to put query params into params?

12:36 kjeldahl`: ghiu: See the SO page, put working example there.

13:39 daniel__: ibdknox: good evening. i was thinking it would be a nice little project to write a web framework in clojure, could you give me any advice on where to start?

13:41 ibdknox: daniel__: a web framework? That seems like an odd project to do :p

13:41 daniel__: it depends on how low level you want to go

13:46 daniel__: ibdknox: not too low level

13:46 i dont want to write a server for example

13:47 ibdknox: daniel__: well ring will start you at the level oh http-request/http-response

13:47 of*

13:48 daniel__: yes, thats about right

13:51 pyninja: why would I get a "No matching method found: schedule for class java.util.concurrent.ScheduledThreadPoolExecutor" error? it's obviously there: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html

13:51 ibdknox: daniel__: out of curiosity, is there something that drives you to do this? or is just an interest in learning how such a thing is done?

13:52 pyninja: gist your code

13:52 pyninja: ibdknox: https://gist.github.com/b1b8561713cc5adf1611

13:53 daniel__: ibdknox: yes, just an interest

13:55 terom: daniel__: there's also a framework called conjure, which could be worth looking into

13:56 dnolen: pyninja: that works just fine for me. what version of Clojure?

13:57 pyninja: dnolen: 1.2 i think

13:57 dbushenko: hello guys!

13:57 pyninja: dnolen: 1.2.1 actually

13:57 dnolen: pyninja: then you probably need to cast 5 to long with (long 5)

13:58 pyninja: dnolen: oh, awesome, thanks

13:58 ibdknox: pyninja: yep, (long)

13:59 pyninja: how would i cast the first argument? because now it says "java.lang.IllegalArgumentException: More than one matching method found: schedule"

13:59 ibdknox: pyninja: (.schedule *timer* (fn [] (println "woo")) (long 4) (TimeUnit/MILLISECONDS))

14:00 pyninja: ibdknox: that still gives the same error for me

14:00 dnolen: ,(bases (class #()))

14:00 clojurebot: (clojure.lang.AFunction)

14:01 dnolen: ,(supers (class #()))

14:01 clojurebot: #{clojure.lang.IMeta clojure.lang.AFunction clojure.lang.IFn clojure.lang.IObj java.util.concurrent.Callable ...}

14:01 ibdknox: pyninja: does your timer creation look something like this? (def *timer* (. Executors newScheduledThreadPool 1))

14:02 dnolen: ,((supers (class #())) java.lang.Runnable)

14:02 clojurebot: java.lang.Runnable

14:02 dnolen: ,((supers (class #())) java.util.concurrent.Callable)

14:02 clojurebot: java.util.concurrent.Callable

14:03 pyninja: ibdknox: hm it worked with that timer.

14:04 ibdknox: i was using https://gist.github.com/2fc8d3345af793d78ebf

14:05 ibdknox: pyninja: that memoize doesn't make sense to me

14:05 pyninja: ibdknox: me neither. copied it from https://github.com/amalloy/cronicle haha

14:05 ibdknox: hah! amalloy is to blame!

14:07 pyninja: he's planning ahead for something that you're probably less likely to run into. Are you only ever going to have one pool?

14:07 pyninja: yeah, i think (. Executors newScheduledThreadPool 1) should work for me

14:07 thanks for the help

14:07 ibdknox: pyninja: yeah do that. Although you probably want more than 1 thread :)

14:08 pyninja: and dnolen also

14:08 yeah

14:09 hiredman: (Executors/newScheduledThreadPool 1)

14:10 khalid: suggest good project source to read

14:11 ibdknox: khalid: depends on what you want to learn

14:12 pyninja: hiredman: nice

14:22 khalid: functional programming (not concurrency specific topics - refs, etc. initially)

14:35 I am a newbie and need some help to be upto speed in clojure

14:35 have a text mining project and am suggesting clojure

14:36 competition is obviously scala

14:36 I am liking Clojure - looks pretty fast - just basic things I have played with

14:37 kjeldahl: ibdknox: Care to clarify how to call render to render a link such as "/adm/user/:username"? I've read the docs and done some test, but I'm still struggling.

14:37 theignorati: how would I create a map with multiple ranges (range 0 7) (range 16 23) etc as keys, all having nil as value?

14:37 kjeldahl: ibdknox: noir related, if that wasn't obvious already.

14:37 ibdknox: kjeldahl: (render "/adm/user/:username" {:username "hey"})

14:38 khalid: I am experienced in other lang and want to grok on some real good code

14:38 kjeldahl: ibdknox: Ah, thanks. I missed the fact that I needed the : part in the first param.

14:41 OpenJuicer: Hi, is there a way to install the latest clojure with leiningen?

14:41 raek: theignorati: something like (let [keys (concat (range 0 7) (range 16 23))] (into {} (for [key keys] [key 0]))) perhaps?

14:41 ibdknox: OpenJuicer: just add org.clojure/clojure "1.3.0" as a dep in your project

14:42 hm

14:42 zipmap ftw here

14:42 (zipmap (concat (range 0 7) (range 16 23)) (repeat nil))

14:42 ,(zipmap (concat (range 0 7) (range 16 23)) (repeat nil))

14:42 theignorati: thanks I have (zipmap (concat (range 0 7) (range 5 17)) (cycle [nil])) now

14:42 clojurebot: {0 nil, 1 nil, 2 nil, 3 nil, 4 nil, ...}

14:42 theignorati: heh

15:05 pcavs: what's a good library for parsing html in clojure? I just want to scrape google for the top hit for a query.

15:05 raek: pcavs: enlive

15:06 https://github.com/swannodette/enlive-tutorial

15:08 Lajla: Chousuke, my beloved, what is the Finnish word for 'trip' or 'voyage', I take it I can't just say mennäys right?

15:17 pcavs: raek: many thanks, following it now

15:22 daniel__: whats clojure.lang.IFn?

15:27 duck1123: daniel__: that's the interface that clojure functions implement

15:27 gfredericks: ,(map #(instance? clojure.lang.IFn) [#(+ 3 4) {} [] () 15 "hehe" :okay])

15:27 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox$eval27$fn>

15:27 gfredericks: wut.

15:28 oh

15:28 ,(map #(instance? clojure.lang.IFn %) [#(+ 3 4) {} [] () 15 "hehe" :okay])

15:28 clojurebot: (true true true false false ...)

15:28 gfredericks: grr

15:28 well you can imagine the rest

15:29 daniel__: thanks duck1123, found my problem

15:30 amcnamara: hash-maps and vecs are considered functions of their items, you can pass a key or index (respectively) to them -- in case you were wondering why they're showing as fns

15:32 and same deal with keywords for the same reason

15:32 daniel__: whats wrong with this? ,(take 5 (repeatedly (+ 1 1)))

15:33 duck1123: keywords are fns that look themselves up in the map (that one got cut off)

15:33 daniel__: ,(take 5 (repeatedly (+ 1 1)))

15:33 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

15:33 hiredman: daniel__: read the docs for repeatedly

15:33 daniel__: (doc repeatedly)

15:33 clojurebot: "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it"

15:33 daniel__: ah

15:34 raek: ,(take 5 (repeat (+ 1 1)))

15:34 clojurebot: (2 2 2 2 2)

15:34 amcnamara: &(instance? clojure.lang.IFn (+ 1 1))

15:34 lazybot: ⇒ false

15:34 daniel__: ,(repeatedly 5 (+ 1 1))

15:34 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

15:34 daniel__: ,(repeat 5 (+ 1 1))

15:34 clojurebot: (2 2 2 2 2)

15:34 daniel__: ok

15:34 Raynes: &(repeatedly 5 #(+ 1 1))

15:34 lazybot: ⇒ (2 2 2 2 2)

15:34 amcnamara: or alternatively ##(take 5 (repeatedly #(+ 1 1)))

15:34 lazybot: ⇒ (2 2 2 2 2)

15:35 Raynes: amcnamara: Go away.

15:35 ;)

15:35 amcnamara: hah

15:35 lazybot evaluated mine first!

15:35 (I just know)

15:35 Raynes: Lies and slander. The bot knows his master

15:37 daniel__: i did need repeatedly....repeat evaluates it once and then repeats, rather than repeating the evaluation each time

16:09 ,(int "2")

16:09 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character>

16:09 daniel__: ?

16:09 gfredericks: ,(new Integer "2")

16:10 clojurebot: 2

16:10 gfredericks: ,(doc int)

16:10 clojurebot: "([x]); Coerce to int"

16:10 daniel__: ;) thanks

16:11 raek: ,(Integer/parseInt "2")

16:11 clojurebot: 2

16:11 raek: ,(identical? (Integer/parseInt "2") 2)

16:11 clojurebot: true

16:11 gfredericks: ,(map #(try (int %) (catch Exception e :nope)) [7.0 7 7N 7M "7" :7 "seven"]))

16:11 clojurebot: gfredericks: No entiendo

16:11 raek: ,(identical? (Integer. "2") 2)

16:11 clojurebot: false

16:11 gfredericks: wtf

16:11 daniel__: ,(identical? (.Integer "2") 2)

16:11 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: Integer for class java.lang.String>

16:11 seancorfield: i'm updating clojure.java.jdbc to use regular maps instead of structmaps in the resultset-seq - it passes the tests (and i'm running a build against the world singles' test suite now) - but can anyone think how it might break existing code?

16:11 daniel__: ,(identical? (new Integer "2") 2)

16:11 clojurebot: false

16:11 gfredericks: raek: what's going on there?

16:12 raek: Integer/parseInt can reuse Integer instances

16:12 seancorfield: i'm not really sure what "structmap" is all about so i don't really understand how / why it's different to a regular map...

16:12 raek: the Integer constructor cannot do that since it has to construct a new object

16:12 they are equal, though

16:12 ,(= (Integer/parseInt "2") 2)

16:12 clojurebot: true

16:13 raek: ,(= (Integer. "2") 2)

16:13 clojurebot: true

16:13 gfredericks: raek: why would parseInt give an identical one? Are the Integers cached somewhere?

16:13 raek: gfredericks: yes. I think -128 to 127 are interned

16:14 gfredericks: ,(identical? (Integer/parseInt "23456") 23456)

16:14 clojurebot: false

16:14 gfredericks: well wuddayaknow.

16:14 seancorfield: ah, just spotted a subtlety with structmaps - if no value is supplied for a given key, it gets a nil value... hmm... don't think that will affect java.jdbc tho'...

16:17 amalloy: seancorfield: structmaps are an earlier iteration of records

16:19 i think they can have default values other than nil, perhaps? that would make a difference

16:19 gfredericks: are structmaps deprecated?

16:19 seancorfield: amalloy: ah, makes sense... java.jdbc only uses them to create key/value pairs based on columns in a resultset

16:20 did they guarantee iteration order?

16:20 amalloy: not easy to find documentation for them, apparently

16:21 seancorfield: i.e., if you did (def abc (create-struct :a :b :c)) and then (struct abc 1 2 3) and then map over the result, is there a guarantee that you'll get [:a 1], [:b 2], [:c 3] in order?

16:21 gfredericks: and what if other keys get added?

16:22 seancorfield: i replaced that pair of calls with (zipmap keys (row-values)) and got a different order... just not sure if that's going to be significant

16:23 amalloy: seancorfield: looking at the source it seems you do get them in that order, but i don't know if it's guaranteed because there are like no docs anywhere

16:23 either way, even if it's not guaranteed clients might conceivably be (incorrectly) depending on it

16:23 seancorfield: heh, well, i'll make the change and see if anyone complains :)

16:24 initially i had (into {} (map (fn [k v] [k v]) keys (row-values))) which seemed to generate them in the same order but i was under the impression map has no defined order...?

16:25 amalloy: seancorfield: that function is just vector

16:25 duck1123: don't struct maps work like regular maps where you'll get the keys back in order up to a certain point because it's more efficient (but you shouldn't count on it)

16:25 seancorfield: amalloy: yes, i realized that after i wrote it, but then realized i could replace the whole thing with zipmap :)

16:26 gfredericks: duck1123: I think the issue is that if he changes the implementation the order might change

16:26 maybe

16:26 maybe not

16:26 seancorfield: yup

16:26 using zipmap definitely gives a different order

16:27 duck1123: but if you have a structmap with a lot of keys, is that order stil preserved?

16:27 gfredericks: amalloy just looked at the code and said yes

16:27 amalloy: duck1123: if all the keys are in the basis map, yes

16:27 seancorfield: but the only situation where i can imagine folks relying on the order is if they do select some,keys,in,order from table and expect to map over them and get :some, :keys, :in, :order again

16:27 gfredericks: duck1123: the declared keys of a structmap are stored differently than any other keys you might add

16:28 duck1123: I always hated that you couldn't dissoc a basis key

16:28 gfredericks: duck1123: just on principle? Or did you want to do that at some point?

16:29 duck1123: I had a use case where I wanted to remove one of the keys and I had to jump through hoops to work around it

16:30 gfredericks: okay let's say I have an infinite binary tree and I want to create a lazy seq of all the nodes in order of depth. Can I do this without having to take up an arbitrary amount of memory (e.g., keeping an entire level in memory at a time)?

16:31 tomoj: in order of depth = breadth-first?

16:31 gfredericks: oh that's trivial, there was another restriction too -- I didn't want to compute the path from the root to the next node every single time

16:32 tomoj: I believe so, yes

16:32 tomoj: trivial?

16:32 seems impossible to me

16:32 suppose you're on the far right, now you jump down to the next level on the far left

16:32 amalloy: gfredericks: the constraints are not well-stated. certainly you can do it, by keeping everything on disk instead of in memory

16:32 tomoj: didn't you have to have the whole level in memory?

16:33 gfredericks: amalloy: add that constraint too :P and no keeping stuff in the cloud either

16:33 tomoj: hmmm

16:33 tomoj: I think at worst it would require going back up to the root and back down

16:34 amalloy: gfredericks: which is already infinite memory, in an infinite tree

16:34 gfredericks: maybe that's the best that can be done as well

16:34 amalloy: it's a lazy tree

16:34 amalloy: so?

16:34 gfredericks: amalloy: oh you mean the path

16:34 tomoj: pretty strange if it GC's branches you climb back up

16:34 gfredericks: the path is fine. I don't want any bottleneck worse than the path.

16:35 amalloy: if you realize the first (say) million left branches, those are all realized, and will stay that way because you're never GCing the root

16:35 gfredericks: "the whole row" would certainly be worse than the path

16:35 amalloy: man I'm bad at this describing a problem thing. It's not an actual tree, just a conceptual one.

16:36 so by lazy tree I just meant that it doesn't exist in memory, just the function to compute the children of a node

16:36 tomoj: are you using a conceptual computer? :P

16:36 gfredericks: nevermind, I'll go off in my corner and figure it out :P

16:36 tomoj: do you have a function to compute the parent given a child?

16:37 gfredericks: sure

16:37 I guess that's not obvious, but I do

16:37 tomoj: I didn't expect that answer. carry on. :)

16:38 gfredericks: I think I can just deal with having to go back to the root every once in a while...

16:39 it's at least better than my current implementation which goes back to the root every time

17:24 seancorfield: as a compromise i'm going to use (into {} (map vector keys (row-values))) which should preserve order for up to 16 columns because it uses a PersistentArrayMap (right?)

17:24 (sometimes reading the Clojure source code is not as enlightening as others)

17:25 raek: seancorfield: why not (zipmap keys (row-values)) ?

17:26 seancorfield: doesn't preserve the order at all

17:26 i'm worried that some ppl may be relying on getting the columns in the same order as their SQL select...

17:27 raek: sorry, didn't read the ArrayMap part

17:27 seancorfield: np, i'm sure it's an edge case anyway

17:27 gfredericks: hmmm....looks like into uses (reduce conj ...) while zipmap uses repeated assoc

17:27 seancorfield: i ran a full suite of tests with zipmap and it all passed so i know world singles' code is not relying on ordering :)

17:28 raek: ,(class (zipmap (range 3) (range 3)))

17:28 clojurebot: clojure.lang.PersistentArrayMap

17:28 duck1123: seancorfield: either make it an ordered map, or tell people there is no guarentee of order

17:28 raek: ,(zipmap (range 5) (range 5))

17:28 clojurebot: {4 4, 3 3, 2 2, 1 1, 0 0}

17:29 raek: ,(into {} (map vector (range 5) (range 5)))

17:29 clojurebot: {0 0, 1 1, 2 2, 3 3, 4 4}

17:29 seancorfield: duck1123: well, there was no specific documented guarantee of order - except insofar as resultset-seq used structmaps

17:29 raek: tough decision to make...

17:29 it's not fun to breake people's code

17:30 but they shouldn't relied on the order of the map entries anyway

17:30 seancorfield: i don't think structmap provided a documented guarantee of key order either?

17:30 raek: :/

17:30 duck1123: I would change it to explicitly say "don't count on it, bub"

17:30 seancorfield: raek: i agree

17:31 raek: the only guarantee I've heard about is that keys and vals should visit the entries in the same order

17:31 seancorfield: i think this is a reasonable compromise tho' so that's going in and i'll be declaring 0.1.0 soon...

17:31 raek: not time for 1.0.0?

17:32 since people have been using it for ages already

17:32 gfredericks: 1.0.0 would certainly take away the fear of breaking stuff

17:32 duck1123: this is c.j.jdbc, right?

17:32 isn't it already past 0.1.0?

17:33 raek: ideally, libs should be at least 1.0.0 when others rely on them

17:35 seancorfield: 1.0.0 of contrib requires clojure/core approval and there's a lot to improve in c.j.jdbc before it gets there

17:36 c.j.jdbc is at 0.0.7 now but i'll bump to 0.1.0 now structmaps are out

17:36 raek: ah, I see... didn't think of the processes involved... :-)

17:36 seancorfield: the other open tickets are all post 0.1.0 in my mind

17:37 i'm planning to provide an API overhaul for 0.2.0 based on feedback on clojure-dev and from some users

17:37 or rather add a new consistent simple API (and maintain the current API)

17:39 at world singles, we wrote a crud wrapper around c.j.jdbc to make it easier to work with and it fits well with some of the feedback i've been getting so i'm going to fold some of it down into c.j.jdbc

17:40 there was also specific feedback from clojure/core about binding vs passing in arguments which i've been considering for a while anyway

17:40 gfredericks: seancorfield: do they prefer one or the other?

17:40 ibdknox: seancorfield: is c.j.jdbc going to change a lot?

17:41 seancorfield: and feedback on merging the internal ns into the main ns as private vars (that would allow quite a bit of simplification as well)

17:41 clojure/core prefer the base API to let you pass everything as arguments - and then you can build the binding-based API on top of that

17:41 amalloy: really? separate namespaces seem much nicer than private vars

17:41 ibdknox: seancorfield: I've made a lot of headway on Korma, which has a decent amount of reliance on c.j.jdbc

17:41 I'm with amalloy on that one

17:42 seancorfield: ibdknox: no breaking changes, just additions

17:42 ibdknox: it also gives room to grow

17:42 gfredericks: I'm curious what simplifications a single ns gets you

17:43 seancorfield: currently some c.j.j.internal stuff is exposed as public vars in c.j.j by (def public-fn internal-fn) - because c.j.j.internal calls internal-fn

17:44 if it's all in one ns, the def can go away and the "internal" functions can call the public stuff directly

17:44 gfredericks: hmm

17:44 that's essentially a bidirectional dependency, isn't it?

17:44 seancorfield: when i started with clojure at world singles, we tended to do the same split: public api in a ns, delegating to a "private" api in another "internal" ns

17:45 but we've moved away from that over time and cleaned up our namespaces quite a bit

17:46 part of it was driven by our need to expose an API that could be called by non-Clojure code... but that consideration is less important now we have more code in Clojure (and now that we call clojure.core stuff directly in our non-Clojure code so we can create maps etc directly)

17:51 danielp1234: yo

17:51 gfredericks: danielp1234: yo

18:14 It is counterintuitive that distinct? takes varargs.

18:14 ibdknox: ,(doc distinct?)

18:14 clojurebot: "([x] [x y] [x y & more]); Returns true if no two of the arguments are ="

18:15 gfredericks: particularly since distinct takes a collection

18:22 amalloy: gfredericks: i wish min/max took collections too, but c'est la vie

18:23 gfredericks: varargs. they make everything better and worse.

18:26 technomancy: seancorfield: that's funny; we went the other way at sonian

18:26 partly for testability purposes

18:27 gfredericks: aren't internal namespaces easier to test than private functions?

18:27 seancorfield: (let [some-name @#'ns/some-name ...] ...) ;; exposes private function for testing :)

18:27 gfredericks: at least in the traditional clojure.test setup that lein gives you?

18:27 seancorfield: the question is: why are you testing private functions? :)

18:28 the unit testing world seems split on that question

18:28 gfredericks: does `lein test` run the functions attached to the :test metadata?

18:28 I don't know if anybody uses test metadata... I just read about it again the other day so it's in my head

18:29 technomancy: gfredericks: it runs based on all namespaces with corresponding files in the test/ dir

18:30 seancorfield: for the record I much prefer working with the connection as an explicit argument vs the with-* style since the latter can trivially be implemented in terms of the former

18:31 seancorfield: technomancy: yup, i agree and c.j.j is the way it is because that's how c.c.sql was when i inherited it

18:31 technomancy: oh, right

18:31 carry on then =)

18:32 seancorfield: the 0.2.0 API will expose functions with explicit arguments (and rewrite the with-* stuff to depend on those)

18:32 technomancy: also, what do you think about accepting a database connection URL rather than a map of :user, :host, :password, etc?

18:32 gfredericks: or both?

18:32 seancorfield: open a JIRA issue :)

18:32 technomancy: gfredericks: naturally =)

18:33 seancorfield: will do. I can put together a patch.

18:33 just wanted to run it by you first.

18:33 gfredericks: multimethod!

18:33 seancorfield: i don't have strong opinions on stuff like that - if folks would find it useful and it doesn't complicate the API for anyone else, i'm comfortable with it

18:34 amalloy: gfredericks: {:user "nobody" :host "localhost" :url "mysql:nobody@localhost..."} - an excellent way to do "both"

18:40 technomancy: yeah, just translate strings into {:url "..."} and extract username etc from the url if it's not already in the map

18:41 Raynes: When people tell me to open a JIRA issue, I tend to just decide that I don't need whatever it is that I wanted as bad as I previously thought.

18:41 amalloy: heh. i was *actually* suggesting you require both, just to annoy users, but technomancy's idea is better

18:41 gfredericks: amalloy: oh so "excellent" was ironic?

18:42 ah ha you were playing on the word "both". Man I could not figure out why you were recommending that.

18:43 amalloy: (if-let [x (foo)] (if (bar x) (then x) else) else) - is there any nice way i can remove the duplication of else, here?

18:44 gfredericks: I almost had something with juxt...

18:44 tomoj: (let [x (foo)] (if (and x (bar x)) (then x) else)) is that nice?

18:44 amalloy: i guess i could write (let [x (foo)] (if (and x (bar x)) (then x) else))

18:44 ibdknox: I wish if-let would allow multiple bindings

18:44 tomoj: and/or correct?

18:45 ibdknox: I almost always do (if-let [x 1] (let [y ...

18:45 amalloy: tomoj: yeah, that's correct except in the case where x is already bound and the let is intended to replace it

18:45 gfredericks: (let [x (foo), y (and x (bar x))] (if y (then x) else))

18:46 ibdknox: technomancy: why do you prefer the url?

18:46 tomoj: ibdknox: you'd want it to only check the truthiness of the first binding?

18:46 ibdknox: tomoj: yep

18:46 amalloy: ibdknox: i think the reason it doesn't exist is it's not clear what it does

18:46 ibdknox: it would be fairly trivial to implement a macro that does it

18:46 amalloy: I agree with that

18:47 amalloy: it would be equally "obvious/useful" to check the truthiness of all the bindings

18:47 ibdknox: I'm not sure it's the "right" thing to do... but it's what I want :p

18:47 I actually expected it would check all of them if you had more than one

18:48 tomoj: seems likely you'd have to check the values manually in the else anyway

18:48 guess not sometimes..

18:49 amalloy: tomoj: anyway, i think that's the right solution to the question i actually asked, except i was glossing over the fact that my if-let is actually an if-user macro that goes and looks the user up in the db

18:50 (if-user [u] (if (test u) (then u) else) else). i guess i could go write let-user

19:01 devth: any suggestions on a good way to format a map as a querystring? seems reduce is not the way to go.

19:01 gfredericks: string/join

19:02 devth: i don't see how that would work with key/vals

19:02 oh, i suppose you could use map to create the keypair representation

19:02 amalloy: right

19:02 gfredericks: (string/join "&" (for [[k v] m] (format "%s=%s" k v)))

19:03 amalloy: though this function has been written a number of times before

19:03 gfredericks: ^ and that of course ignores encoding complexity

19:03 devth: right. thanks.

19:04 gfredericks: also it assumes keys and vals are strings... :/

19:07 tomoj: &(format "%s" {:foo :bar})

19:07 lazybot: ⇒ "{:foo :bar}"

19:07 gfredericks: really?

19:08 Well I'll be.

19:08 amalloy: gfredericks: %s calls .toString

19:08 gfredericks: there goes java. always being relaxed about types.

19:08 amalloy: the scoundrels

20:25 technomancy: Raynes: if it were just for me I would probably skip it, but since this is for work I'll put up with jira

20:29 heh; that's funny, most people wishing for multi-if-let want and semantics, and everyone else wants or. this is the first I've heard of "just use the first value"

20:30 amalloy: technomancy: are you sure? i don't think "or" makes sense as a model

20:31 "bind at least one of these variables, i don't care which"?

20:35 technomancy: I don't think it makes sense either =)

20:35 but I think I've heard it

20:55 duck1123: and makes sense, with one else for if any of them fail

22:43 khaliG: hm. it takes 12s before my clojure/swing app pops up.. :(

Logging service provided by n01se.net