#clojure logs

2011-10-16

00:51todunI'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
00:54amalloytodun: do you know what inc does?
00:54todunamalloy: inc a number right?
00:54todunby one
00:54todunso like java's ++
00:54amalloynot ++, which implies mutation
00:55amalloyit just returns (+ 1 x)
00:55todunamalloy: oh.
00:56todunamalloy: in that case and with recursion in the picture, maybe I see what's happening.
00:56todunamalloy: so inc will keep returning (+ 1 x ) until size (rest v) is empty
00:57todunthen all those will be combined?
00:58todun(+ 1 (+ 1 (+ 1 ...(0) ...)))
00:58amalloyindeed, but not (0)
00:58amalloyjust 0. stop calling things as functions :)
00:58todunamalloy: oh. ha.
00:59todun(+ 1 (+ 1 ( + 1 ...(+ 1 0) ...) ) )
01:00ibdknoxamalloy: macro question for you
01:01ibdknoxamalloy: let's say I have a macro (defmacro aw [q] (+ ~q ~q))
01:01amalloyibdknox: plus the missing `?
01:01ibdknoxamalloy: er, yes
01:02ibdknoxamalloy: will q be evaluated twice?
01:02amalloyyes
01:02ibdknoxamalloy: so in such a case, you want to let the result?
01:03amalloydefinitely
01:03ibdknoxI'm not sure why I never internalized that until now
01:03ibdknoxbut it explains why my shit was broken :)
01:05FrankLWhat 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}
01:05amalloyFrankL: actually, i have that code lying around somewhere
01:06FrankLamalloy, cool!
01:06amalloyhttps://github.com/flatland/useful/blob/develop/src/useful/map.clj#L172
01:07FrankLwow, that's exactly what i was looking for
01:07ibdknoxhaha amalloy: I love this: (map (to-fix (! set?) hash-set) entry)
01:07FrankLthanks!
01:07ibdknoxreally just the (! set?)
01:12amalloyibdknox: what's the point of having a utility library if you don't use it to make your code short
01:12ibdknox's true
01:12ibdknoxI just think it reads amusingly :)
01:13amalloyit does. mapping over a collection known to be two elements long is also good for a laugh
01:14amalloyFrankL: it's not exactly what you want, since it produces {:a #{1}} instead
01:14ibdknoxall the cool kids are doing it these days :p
01:17FrankLyup
01:18FrankLand i have no idea what's going on in those functions!
01:18FrankLbut figuring that out should teach me some things
01:36devnhey all
01:37todunI 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
01:38ibdknoxtodun: you never put anything into acc
01:39todunibdknox: uhm.
01:39todunibdknox: let me try something.
01:39ibdknoxright now you're just reversing an empty list for every element in lst
01:40todunibdknox: It seems then I'm using recur rightly but doing recursion wrongly.
01:43todunibdknox: 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?
01:43ibdknoxtodun: you have the let backwards
01:44todunhow so?
01:44ibdknox,(let [x (inc 1)] x)
01:44clojurebot2
01:45todunuhm. I misread then. thanks.
01:45MGT,1
01:45clojurebot1
01:49kanjahttp://pastebin.com/XtS20p38
01:49Raynesibdknox: Where is mah noir tryclojure?
01:49todunibdknox: 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))))
01:49kanjaI'm getting can't resolve guess in this context - but I have no idea which guess it's talking about. Any ideas?
01:50ibdknoxRaynes: I got distracted by more important things :p
01:50RaynesI feel unimportant now.
01:50ibdknoxaw
01:50ibdknoxbut I'm doing it for the greater good!
01:51Rayneskanja: For one, you need to wrap each arity in parentheses. (defn sq-iter ([x] ..) ([guess x] ..))
01:51ibdknoxtodun: the scope of the let is only valid for what's inside of it, your use of acc is outside of your let
01:51RaynesSecond, don't put closing parens on they're on line.
01:51Raynestheir*
01:51Raynesown*
01:51todunibdknox: ok. thanks. let me try again..
01:52kanjaRaynes: Yeah - Sorry, still learning the syntax.
01:52RaynesI guess that doesn't excuse not being able to type. Maybe my fingers are throbbing with my head.
01:52todunRaynes: sorry.
01:52ibdknoxRaynes: get off the computer... that only makes it worse
01:52todunRaynes: idomatic clojure?
01:52Rayneskanja: I wasn't scolding you, just giving you a heads up. :)
01:52todun*idiomatic.
01:52Raynestodun: I was replying to kanja actually. Haven't been following your particular conversation.
01:52Raynesibdknox: flux helps.
01:52todunRaynes: ok.
01:53kanja:)
01:53kanjaThanks for the help
01:53duck1123feel 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
01:53kanjaI'm used to emacs lisp so I'm all kind of wierded out :)
01:53duck1123this is where paredit is great
01:54Raynesduck1123: Why encourage it at all? :p
01:54kanjaI'm actually using paredit for the first time with this
01:54kanjaI'm having a little trouble getting used to it
01:54kanjawhat's the right way to do the closing parens? all on the same line?
01:54RaynesRight.
01:54ibdknoxRaynes: did you use the paredit clone for vim?
01:54RaynesOne or two people in the universe disagree.
01:54Raynesibdknox: Yes. It was nice.
01:55ibdknoxhm, maybe I should do that
01:55ibdknoxlol
01:55duck1123I 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
01:55Raynesibdknox: Slurp, join, barf. Your life will be so improved.
01:55ibdknoxhaha
01:55ibdknoxsuch nice names for the commands
01:55kanjahaha
01:56kanjathe default binding for them on emacs sucks
01:56Raynesduck1123: 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.
01:56kanjac-m-left for slurp
01:56RaynesHuh?
01:56RaynesIt's C-left/C-right for me.
01:56RaynesNo Ms about it.
01:58kanjahuh, yeah
01:58kanjaI guess I had it wrong
01:59RaynesVim uses Leader< and Leader>
01:59kanjastill not crazy about that though - I hate dropping down to the arrows
01:59RaynesI can't navigate with letter keys. My fingers don't work like that.
01:59kanjahuh
02:00duck1123I use the arrows more, but there's always times when the letters save my life
02:00RaynesWell, I mean character-by-character navigation. Not clever commands. Those are a different beast entirely.
02:03kanjaclever commands?
02:03duck1123C-t is a clever command
02:03duck1123I never use it right
02:03Apage43for me i didn't really get used to using letters for navigation until I got really into using all the keys in vi
02:03Apage43and also xmonad
02:04Apage43and now it's just a can't be arsed to move my fingers all the way over to the cursor keys thing
02:04kanjayeah that's kind of how I feel
02:04kanjaalthough I haven't made the jump into a twm yet
02:04Apage43kanja: i don't bother unless i've got a dual monitor setup
02:05Apage43but 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.
02:05duck1123I'm a fan of stumpwm
02:05kanjaApage43: Yeah, I'm using a laptop right now without much screen space, but my friends have been yelling about i3 for a while now
02:05duck1123I bind the stumpwm key to capslock
02:06kanjaoof no good with emacs
02:06kanjaI need that for control
02:07duck1123I played with using menu for it, but I've since then assigned that to gnome-do
02:07Apage43I still haven't been able to get used to using capslock for something else
02:07Apage43i never really feel like touching that key
02:07amalloyduck1123: i also always forget to use C-t, so i rebound it to transpose-sexps, and now i use it all the time
02:07duck1123ooh, transpose-sexps... need to learn that one
02:08amalloyyou should really rebind caps lock, whatever editor you use. for me, it helped a lot to relieve emacs-pinky
02:09kanjayeah I could never use emacs w/o capslock
02:09amalloyi gather it's just as useful for vim
02:09duck1123My left wrist has been messed up for like a week now. Damn emacs pinky
02:10kanjahaha 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
02:10kanjawhat's the use of the ratios?
02:10kanjamore precision?
02:11duck1123,(+ 1/3 1/3 1/3)
02:11clojurebot1N
02:12kanjawhat does the N mean?
02:12amalloy&(class 1N)
02:12lazybotjava.lang.NumberFormatException: Invalid number: 1N
02:12amalloy,(class 1N)
02:12clojurebotclojure.lang.BigInt
02:12kanjaah
02:12kanjaty
02:12amalloyi'm surprised that results in 1N rather than 1, duck1123
02:13todun(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.
02:13ibdknoxis there some better way to execute a collection of functions over something than doing (reduce #(%2 %) ...)? My brain has stopped working.
02:13duck1123amalloy: yeah, same here
02:13ibdknoxhuh
02:13amalloyibdknox: ((apply comp fs) x)?
02:13amalloyi guess that goes in the wrong order
02:13ibdknoxorder doesn't matter
02:14duck1123It'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
02:14ibdknoxduck1123: woah, really?
02:14ibdknox,(= 1/2 0.5)
02:14clojurebotfalse
02:14ibdknox...
02:14kanjayikes
02:14duck1123As far as I can tell, it still works, but all the tests fail
02:15kanjaso uh, what's the point of the ratios?
02:15ibdknoxwtf
02:15kanjasounds like they're causing issues
02:15duck1123There was a thread on the ml about it. word of god was that was intentional and by design
02:15amalloy,(= 1 (+ (/ 1.0 3) (/ 1 3) (/ 1 3)))
02:15clojurebotfalse
02:15kanjais clj not ducktyped then?
02:16amalloythat is why ratios exist
02:16duck1123,(== 0.5 1/2)
02:16clojurebottrue
02:16ibdknox,(doc ==)
02:16clojurebot"([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"
02:16kanja,(doc =)
02:16clojurebot"([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."
02:16ibdknoxis that new?
02:16kanjaah interesting
02:16amalloyibdknox: no
02:17duck1123== is ancient, iirc
02:17amalloythough i think the docstring is less true in 1.3 than it used to be
02:17ibdknoxthat doc string is wrong now, type does matter for numbers :p
02:17amalloyibdknox: i don't remember what the difference is though, do you?
02:18ibdknoxamalloy: nope
02:18ibdknox,(= 1N 1)
02:18clojurebottrue
02:18ibdknox,(= 1/1 1)
02:18clojurebottrue
02:19duck1123,(== [0.5] [1/2])
02:19clojurebot#<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number>
02:19ibdknoxI guess I should've looked at the numerics changes closer
02:20ibdknox,(= 1 1.0)
02:20clojurebotfalse
02:20ibdknoxare floats the only thing that don't play with everyone else now?
02:20duck1123that one makes sense
02:20ibdknoxduck1123: how so?
02:21duck11231.0 is not really 1. 1.0 can approximate 1 but they're not really the same and that difference will bight you
02:22duck1123Not that I often need that distinction in practice...
02:23ibdknoxI haven't done enough real numerical stuff to know why that's the case, but that's counter intuitive to me :)
02:23MGT,(== 1 1.0)
02:24clojurebottrue
02:25ibdknox== seems like the simple solution though
02:25ibdknoxassuming you don't care
02:25duck1123generally though, you're going to know when you're going to be getting floats
02:27MGT,(replicate 5 'a')
02:27clojurebot(a' a' a' a' a')
02:27MGT,(replicate 5 "a")
02:27clojurebot("a" "a" "a" "a" "a")
02:28ibdknox,''
02:28clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>
02:28ibdknox,'a'
02:28clojurebota'
02:28ibdknoxinteresting
02:28ibdknoxlearn something new every day
02:29amalloyibdknox: 1.3 adds terminating-quotes in symbols, yeah?
02:29amalloyor perhaps intervening
02:29amalloy,'a'b
02:29clojurebota'b
02:30amalloymostly in order to get auto-promoting arithmetic operators like +'
02:30ibdknoxI see
02:30tomojdidn't replicate get removed?
02:30ibdknoxthat would make sense
02:30ibdknox,(doc replicate)
02:30clojurebot"([n x]); DEPRECATED: Use 'repeat' instead. Returns a lazy seq of n xs."
02:31ibdknoxnot yet
02:31amalloythree cheers for deprecation
02:31MGT,(doc repeat)
02:31clojurebot"([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs."
02:31devnwhy?
02:31clojurebotdevn: because you can't handle the truth!
02:31devnlol
02:31ibdknox(inc clojurebot)
02:31lazybot⟹ 7
02:31ibdknox~anyone
02:31clojurebotPlease 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.
02:32ibdknoxgood
02:32ibdknoxit doesn't say I will answer questions :p
02:32devn^anti-community statement by clojurebot
02:32devn"don't waste my mother fucking time"
02:32ibdknoxyeah
02:32ibdknoxlol
02:32ibdknoxhe's got shit to do
02:33MGThow do i do clojure
02:33devn"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."
02:33devn--clojurebot
02:33amalloydevn: 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
02:33tomoj"here's a tip that will make it more likely for you to get an answer"
02:34devnMGT: With great aplomb.
02:34devnMGT: That's how.
02:34MGT,(doc aplomb)
02:34clojurebotExcuse me?
02:34MGT???
02:34lazybotMGT: Oh, absolutely.
02:35devnaplomb |əˈpläm, əˈpləm|
02:35devnnoun
02:35devnself-confidence or assurance, esp. when in a demanding situation: Diana passed the test with aplomb .
02:36ibdknoxclojurebot: 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 ..."
02:36clojurebotc'est bon!
02:36ibdknox~anyone
02:36clojurebotPlease 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.
02:36ibdknoxamalloy: what'd I do wrong?
02:36devnibdknox: treat it like an infobot
02:36devn(that's what you did wrong)
02:36amalloyibdknox: you need to tell him to forget the old one
02:37devnibdknox: The old way was: "clojurebot: no, anyone is..."
02:37devnNot sure if it conforms to that or not
02:37ibdknoxclojurebot: 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.
02:37clojurebot'Sea, mhuise.
02:37ibdknoxclojurebot: 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 ..."
02:37clojurebotAck. Ack.
02:37amalloynoooooo
02:37ibdknox~anyone
02:37clojurebotJust 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 ..."
02:37devnclojurebot: no, anyone is a funny thing.
02:37clojurebotIk begrijp
02:38devnclojurebot: anyone
02:38clojurebotJust 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 ..."
02:38devnimmutability is a harsh mistress every now and again
02:38amalloyibdknox: the syntax for deleting stuff is really awkward. usually you just end up adding more accidentally
02:38ibdknoxlol
02:38amalloyclojurebot: forget anyone?
02:38clojurebotPlease 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.
02:39ibdknoxlol
02:39amalloyhm. anyway, my point is he's now learned a meaning for "forget anyone"
02:39ibdknoxoh
02:39ibdknoxwhoops
02:39ibdknoxwhat was the correct way then?
02:39amalloyclojurebot: 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.
02:39clojurebotI 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.
02:39ibdknoxah
02:39amalloyclojurebot: 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.
02:39clojurebotI 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.
02:40amalloy~anyone
02:40clojurebotJust 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 ..."
02:42devnwow, that's not confusing.
02:43ibdknoxit's why I got it right on my first try ;)
02:51MGThttp://pastebin.com/hBx6ZLSX
02:51MGTis the first function as efficient as the second?
02:51MGToops
02:52MGThttp://pastebin.com/5p9xDB7x corrected first function
02:53duck1123MGT: you only need to check up to n/2
02:53MGTwell
02:53MGTI only need to check up to sqrt(n), strictly speaking
02:53clojurebotbrain dump is http://clj.thelastcitadel.com/clojurebot
02:53MGTbut the second one uses tail recursion
02:54MGTand I was wondering if that makes it faster
02:54ibdknoxlol
02:54ibdknoxclojurebot is so weird
02:56duck1123MGT: some also uses recusion
02:57MGTis it tail recursion?
02:57duck1123(when (seq coll) (or (pred (first coll)) (recur pred (next coll))))
02:57ibdknoxsweet
02:58ibdknoxkorma is getting somewhere now :D
02:58MGTsorry, what's that?
02:58ibdknoxgetting the table prefixes right was a lot harder than I expected
02:58MGTdefinition of some?
02:58duck1123MGT: that's the source body of some
02:58MGTok, thanks
02:58MGTI have to familiarize myself with seq
02:59duck1123ibdknox: I look forward to giving korma a shot. (once I get back out of the Ruby hell i'm in at work)
02:59ibdknoxduck1123: as of tonight it might actually be worth it
03:00ibdknoxduck1123: still a few important loose ends I need to tie up
03:00ibdknoxbut I think I did the hard part
03:00duck1123did you ever figure out that whole lazy map thing you were working on?
03:01ibdknoxI punted on that for now
03:01ibdknoxRight now it's set up that if you do a has-many
03:01ibdknoxit maps executing that query over the result set
03:02ibdknoxso in the case that a user has many addresses
03:02ibdknox(select user (with address)) would return back (map get-and-assoc-addresses users)
03:03duck1123so are the records returned actual Records (in the defrecord sense)
03:03ibdknoxnot at this point
03:03ibdknoxwhy, what are you thinking?
03:03duck1123I rely on being able to determine the class of a record for a lot of Ciste
03:04ibdknoxit would be trivial to add meta-data to it
03:04ibdknoxsaying where something came from
03:04ibdknoxcreating records dynamically sounds a lil scary
03:05amalloy(inc ibdknox)
03:05lazybot⟹ 4
03:05tomojciste? is that the gismu or a coincidence?
03:05duck1123structure
03:05tomojyeah :)
03:07duck1123And then I named my identi.ca clone Jiksnu after jikca casnu for "social type of interaction"
04:03tolstoyWhen 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).
04:03amalloyibdknox: you could allow the user to pass you a constructor function at some point, and then dealing with records would be their problem
04:06ibdknoxamalloy: 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
04:06ibdknoxI say basically a lot when I get tired
04:06ibdknoxlol
04:06ibdknoxI was currently testing how slow string concat is
04:07ibdknoxtrying to determine if a query should use a single stringbuilder the whole way through
04:07ibdknoxseems the difference of marginal practical value
04:07ibdknoxI was generating around 30,000 complex queries a second
04:08ibdknoxif you actually have a DB that can respond to that...
04:08ibdknoxyou're awesome :p
04:09amalloyibdknox: basically, when you get tired, you say a lot
04:10ibdknoxamalloy: haha fine. I'll go to bed.
04:10amalloynoooo, how will i query my databases?
04:11ibdknoxI hear writing SQL by hand is fun :D
04:12tolstoyAh, "lein trampoline" solves my problem.
04:13ibdknoxalright folks, I've had enough SQL'ing for one day
04:14ibdknoxg'nite!
04:24archaic_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?
04:24amalloy&`(... ~'+)
04:24lazybot⇒ (... +)
04:25amalloythough you should usually think twice about why you want to do this
04:26archaic_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
04:30ziltiI 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??
04:30lazybotzilti: What are you, crazy? Of course not!
04:31ziltilazybot: How could you answer before I released my return key? That's even too fast for a bot!
04:32Raynesamalloy: He has a point. lazybot is awfully fast for such a complexbot.
04:33RaynesI mean, he fires those hooks machine gun style.
04:34ziltiThat's why, one day, lazybot will take over the world - despite his lazyiness
04:34amalloyzilti: well, #(fn ...) has got to be a mistake
04:34amalloyyou don't want to create a function that returns a function, you just want a plain old function
04:35ziltiamalloy: I actually wanted to create a function that calls an anonymous function defined within it to use recursion and an additional val.
04:35ziltiBut I guess that's bad style?
04:36amalloyzilti: that's fine style, sometimes
04:36amalloyhere you have some additional problems, like your parens don't match up
04:36raekzilti: 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
04:37amalloywell. simpler to use loop/recur if you're going to be recur'ing anyway
04:37raekzilti: but with 'loop' and 'recur', you can often do without the let
04:38ziltiI'll try it with let. I'll have to define "step" inside let, right?
04:43raekyes
04:43ziltiargh.
04:44raekthe idea is that you want to recur with one set of "loop parameters", but the outer function takes another set of parameters
04:44ziltiSo it is #(let[step (fn [x y z] (...))] (step %1 %1 %2))? But that gives me errors
04:44raeklet's take ye olde factorial function as an example
04:46raek(fn factorial [n] (let [step (fn [acc i] (if (zero? i) acc (recur (* acc i) (dec i))))] (step 1 n))
04:47raekyou can rewrite this with loop and recur
04:48raek(fn factorial [n] (loop [acc 1, i n] (if (zero? i) acc (recur (* acc i) (dec i)))))
04:51raekthis is also a possible way:
04:51raek(fn factorial [n] ((fn [acc i] (if (zero? i) acc (recur (* acc i) (dec i)))) 1 n))
04:51raekI think that was what you tried to do originally
04:51raeknotice the "(("
04:52ziltiWhy those?
04:52MasseRThen you evaluate the newly-created function
04:53raekthe inner one is for the (fn ...), which creates a new function
04:53ziltiI'm totally confused as of now. My solution for problem 21 still doesn't work.
04:53raekthe outer one calls that function with the arguments 1 and n (in my case)
04:53zilti"Can only recur from tail"
04:55raekit is also possible to do recursion without TCO by replacing 'recur' with the name of the function
04:55raekanonyous functions can be named too :)
04:55raek(fn f [..] ..f is available here..)
04:56raeka variant of the factorial example that cannot be TCO'ed:
04:56raek(fn factorial [n] (if (zero? n) 1 (* n (factorial (dec n)))))
04:58raekthe "(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
05:00ziltiSo recur-ing inside an if doesn't work as well?
05:00amalloyzilti: it does, because recur can still return immediately - the if "part" has already been evaluated
05:01ziltiamalloy: But it doesn't work here.
05:01amalloyzilti: no, something else doesn't work :P
05:01ziltiIt says "can only recur from tail position"
05:01amalloy~bug report
05:01clojurebotA 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.
05:02pyninjaHi, 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...
05:03carkjava.util.Timer, its callback is on a separate thread
05:03amalloypyninja: certainly it's possible. i don't see any immediate reason why it would be a terrible idea
05:04pyninjacark, amalloy: ok, cool
05:04carkcarefull about the Timer callback tho, you'd better spawn another thread from there
05:04carkdepending on your use case
05:04amalloy$javadoc java.util.Timer
05:04lazybothttp://download.oracle.com/javase/6/docs/api/java/util/Timer.html
05:04pyninjahow do you mean?
05:05carki don't remember right now, but i seem to recall you should not raise exceptions from this callback
05:05pyninjahm ok thanks
05:06carkTimer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread
05:06raekpyninja: also take a look at http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledExecutorService.html
05:06carkthat's why i was spawning threads
05:06raekit's more mature
05:06carkso it's not about exceptions after all =)
05:07raekhttp://download.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newScheduledThreadPool(int)
05:07pyninjahm interesting
05:08carkreak: oh this one looks interesting
05:08carkso it picks a free thread from the pool and runs it ?
05:09carkyes that's exactly what pyninja needs
05:10pyninjayeah 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
05:11ziltiWhy doesn't this recur work? http://pastie.org/2704759
05:11raekcron4j is interesting too
05:11amalloypyninja: 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
05:12pyninjaamalloy: oh, cool. thanks a lot!
05:13amalloyzilti: it's much easier to see the problem if you get the indentation to match with the parens: https://gist.github.com/76362d613a17d59369bb
05:14amalloythe call to (step lst) is actually inside the body of step, not in the outer function
05:16amalloyas 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
05:18ziltiOh great. "You tripped the alarm! nth is bad!" I don't even use nth now. Well at least I don't get other errors.
05:21amalloy&(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
05:21lazybot⇒ (fn* ([p__15973] (clojure.core/let [[x] p__15973] x)))
05:21amalloy&(macroexpand '(let [[x] (range)] x))
05:21lazybot⇒ (let* [vec__15981 (range) x (clojure.core/nth vec__15981 0 nil)] x)
05:29ziltiBah. I get a class cast exception on the 4clojure REPL for code that works flawlessly in my REPL.
05:30zilti#((let[step (fn [frag] (if (= (count frag) (+ (- (count %1) %2) 1)) (first frag) (recur (rest frag))))] (step %1)))
05:31raekzilti: you have one pair of parens too much arount let
05:31raek*around
05:33raekalso, I think it's easier to spot mistakes like this if you use the (fn ..) syntax instead of the #(..) syntax
05:40robermannhi
05:54BorkdudeI'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 ?
06:26todunI 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
06:48hugodtodun: what does your let form return?
06:49todunhugod: uhm. I don't follow.
06:49todundo you mean what does it match?
06:49todunor yield.
06:51todunor if you mean return in the java sense, I didn't know let could return a value and did not write it thusly.
06:56hugodtodun: the value the let form evaluates to
06:56todunhugod: oh ok. I'm not sure.
06:56todunhugod: I was using let so that I could have a computation part and a recursive part.
06:57todunthe computation will give the recursive part its result.
06:57todunos so was the plan.
06:57todunthe computation will reduce the problem.
06:58hugod,(let [x 1])
06:58clojurebotnil
06:58todunhugod: I see.
06:59todunmaybe that's my problem, yes?
07:00hugodI'm not sure what the code is supposed to do, but I imagine that is part of the problem
07:01ziltiWhy doesn't that work:
07:01zilti,(cons (1) ())
07:01clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>
07:02todunhugod: sorry. it does nested reversals of a list.
07:03todunhugod: so. I'd posted earlier and forgot that I should re-write the description.
07:03todunhugod: 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.
07:04stuarthalloway,(1)
07:04clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>
07:04hugodtodun: you might also want to println the value of acc and temp-lst inside the loop, to get an idea of what is happening
07:04todunhugod: 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.
07:04todunhugod: ok.
07:05zilti,(cons '(1) ()) ; But how can I do that if I just have an argument instead of (1) ?
07:05clojurebot((1))
07:05daniel__anyone ever got: unable to attach to a dyno when running a console session on heroku?
07:06daniel__nvm, i had to add logging
07:09stuarthalloway,(let [a '(1)] (cons a ()))
07:09clojurebot((1))
07:13ziltistuarthalloway: http://imgur.com/KZB38
07:13ziltistuarthalloway: Fifth line is the problem, the (cons pack lst) part
07:14stuarthallowayzilti: it is pretty odd to use cons not conj btw
07:16stuarthallowayzilti: partition-by in core is a generalization of the fn you are writing, you should study it
07:17stuarthalloway,(partition-by identity [1 1 2 1 1 1 3 3])
07:17clojurebot((1 1) (2) (1 1 1) (3 3))
07:19hugodtodun: 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
07:20todunhugod: uhm ok. I didn't realize this behavior was possible in let.
07:24hugodtodun: see the example in http://clojure.org/special_forms#Special%20Forms--(recur%20exprs*)
07:24todunhugod: that makes sense.
07:25todunhugod: so instead of a nil result type, the result is the binding of y
07:26todunhugod: I'm just surprised it's affecting me, because I'm not using the result for anything. should I just set it to something?
07:26todunI thought recur didn't use the result from its first argument.
07:28hugodin 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)
07:29todunuhm. ok. that was not the effect I thought of when writing this, but that does help my agenda in this problem.
07:37todunis it possible to do multiple args to a function in clojure and/or currying? http://pastebin.com/u0HsrHUk
07:40ziltitodun: There are partials and varargs
07:42todunzilti: uhm. ok. will those let me do (defn yes [y] [n] ...) by default?
07:48todunIs 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.
07:53ziltitodun: afaik not, but you can partially apply functions using the "partial" macro
07:54todunzilti: ok. I'm reading that up now.
07:55ziltitodun: 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.
07:55todunzilti: also, I couldn't find anything on varargs wrt clojure. will it be like (defn yes [*var] ...)?
07:56ziltitodun: The varargs symbol is &, not *
07:56todunzilti: the reason I asked to curry was so I could have multiple args which may or maynot bind.
07:56todunzilti: so (defn yes [&var] ...) ?
07:59ziltitodun: almost. (defn yes [& var] ... )
08:01todunzilti: thanks.
08:01todunzilti: also do you know of any inbuilt function to remove a specific item from a list?
08:03ziltitodun: sequences/filter
08:04todunzilti: ok. I'll check it out. thanks.
08:04ziltiactually, it's in core, not sequences
08:04ziltihttp://clojure.github.com/clojure/clojure.core-api.html#clojure.core/filter
08:05todunzilti: 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?
08:06ziltitodun: 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.
08:07todunzilti: thanks. checking those out.
08:14todunzilti: 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?
08:14todunzilti: for instance in python I can call something like ascii and I'll have all the ascii characters.
08:15todunor something like that.
08:15todunthanks.
08:17ziltitodun: I don't know. I'm quite new to Clojure as well. Sorry.
08:17todunzilti: thanks all the same. :-)
08:18ziltitodun: No problem :)
08:23todunzilti: 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
08:23todunzilti: perhaps you can see something I'm doing wrong...
08:23todunthanks.
08:42hugodtodun: what are you trying to do by using a let?
08:44todunhugod: 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.
08:46hugodtodun: you can't affect the value of acc on the next iteration, except through the second argument to recur
08:47hugodlet can only change the values bound to symbols within its body
08:49hugodtodun:so what I think you want is something like (recur (next tmp-lst) (reverse (conj acc (first tmp-list))))
08:50todun_hugod: ok. I'm trying that now...
08:53hugodtodun: what would you expect (let [x 1] (let [x 2]) (println x)) to print?
08:53todunhugod: the value of the last block evaluated.
08:54todunhugod: so 2
08:54todunI mean. the value of the last block that binds x's value.
08:54todunI'm wrong.
08:55todunthe repl says 1 \n nil \n :-P
08:56kjeldahl`One parens too many after the second let expression []...
08:56kjeldahl`Move it to after the print...
08:57kjeldahl`,(let [x 1] (let [x 2]) (println x))
08:57clojurebot1
08:57kjeldahl`,(let [x 1] (let [x 2] (println x)))
08:57clojurebot2
09:01todunkjeldahl`: it ran ok as is in the repl for me though.
09:03kjeldahl`todun: If the expression you posted shows 2 in your repl, your repl is mistaken.
09:04todunit shows 1 :-D
09:05kjeldahl`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.
09:07todunhugod: I get an exception when I tested it: http://pastebin.com/GLZf48dC
09:07todunkjeldahl`: yes I expected it to show 2. but when I did it in the repl, it showed 1.
09:07todunkjeldahl`: and so it was my reasoning about it that was wrong.
09:08hugodtodun: don't worry about loop until you understand the lexical scope of let
09:08todunkjeldahl`: I was asking you why you made the comment about the parens.
09:08todunhugod: ok.
09:09hugodloop is not something you need to learn initially
09:10todunhugod: but how can I accomplish my recursion without it?
09:11hugodtodun: don't worry about anything until you understand why you got a 1 instead of a 2
09:11todunhugod: ok.
09:13todunhugod: is this because the value of println x binds to the x coming from the outer let?
09:14hugodthe println isn't within the body of the second let, so it sees the value bound by the first let
09:16todunhugod: oh ok. so it binds only with the (let ) scope.
09:16todunhugod: I thought let was more restrictive in that it bound within the [] scope, no?
09:19todunhugod: between, do you know how to use variable arguments in clojure? I'm having a hard time tracking down an explanatory example. thanks.
09:22hugodtodun: variable arguments, or multiple arguments?
09:23todunhugod: actually both.
09:23todunhugod: but I think I was making a mistake in my multi-arg...(defn yes [y] [n]...)
09:23hugodtodun: (defun f [a b] (println a b))
09:24todunhugod: wow! that makes more sense! thanks.
09:24todunhugod: now I find examples. I was searching for the wrong thing.
09:24hugodfor varargs (defun [a & b] (println a b))
09:25todunhugod: I was searching for variable arguments instead of multiple arguments.
09:31todunhugod: 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.
09:33gfrederickstodun: I would like to help but I have no idea what you're talking about
09:34todungfredericks: an example should solve that problem. :)
09:34todungiven (1 (a (eqsd vsa)) 5 6 (7) ( )), the result is ((( )) ( ) ( )).
09:35todungfredericks: sorry about the confusion :-P
09:35gfredericksah; so you're want to take a nested list and remove all the elements but keep the structure
09:36todungfredericks: yes. that sounds like the proper way of saying it too. thanks.
09:36gfrederickswell the (sequential?) function could help you pick between the things that are lists and the things that aren't
09:36gfredericksso ##(filter sequential? '(1 (a (eqsd vsa)) 5 6 (7) ( )))
09:36lazybot⇒ ((a (eqsd vsa)) (7) ())
09:37gfredericksand then you can recursively map each one
09:37gfredericksso...
09:37Bronsam
09:37todungfredericks: thanks. that helps.
09:37todungfredericks: I've actually been stuck almost all weekend on recursion.
09:38todungfredericks: all my recursive implementations seem to not be working.
09:38gfrederickstodun: did you want to see my implementation or try it yourself? :)
09:38todungfredericks: try it out myself.
09:38gfredericksokay
09:38todungfredericks: but I would like help on recursion.
09:38gfredericksI'm out for breakfast; have fun
09:38gfrederickswill be back before too long, if you have specific questions
09:39todungfredericks: thanks. will compose then as you munch.
10:00gfrederickstodun: how's it going?
10:01todunstill trying different things and reading more on the topic.
10:01gfredericksit 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:02todungfredericks: let me read up on that..one sec.
10:02todungfredericks: I also want to use more higher order functions to jump out of the imperative mindset..
10:04todungfredericks: it seems walk is like a generator of sorts, no?
10:05gfrederickswalk lets you do things recursively to nested stuff
10:05gfrederickswithout having to do the recursion yourself
10:05gfredericksI just wrote your "list-ghosting" function with postwalk
10:06todungfredericks: didn't find anything on the postwalk function.
10:07gfrederickshttp://clojure.github.com/clojure/clojure.walk-api.html#clojure.walk/postwalk
10:09todungfredericks: uhm ok. I must have been using google wrongly. let me play with postwalk. thanks.
10:20todungfredericks: do I have to do some import? I keep getting source not available at the repl http://pastebin.com/5wJLKiAz
10:20todunthanks.
10:25gfredericks(use 'clojure.walk)
10:26todungfredericks: ok. let me try that. thanks.
10:26gfredericksyep
10:27ghiuhi, anyone with a bit of experience in compojure?
10:27gfredericksaye
10:28shalesIn clojurescript, how do I produce javascript like window["main"]? (aget window "main") isn't working
10:28gfredericksdoes (.main window) not work?
10:28ghiugfredericks: this route definition doesn't work (GET "/add/?d=:d" [d] (add-gallery d)) <- can't i directly bind query string params?
10:29gfredericksghiu: I don't think you need that explicit query string in the route
10:29gfredericksit'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:30ghiu(checking )
10:31shalesgfredericks: no, window/main produces window.main, but I want to use javascripts array notation to avoid the advanced compiler renaming "main"
10:32gfredericksshales: okay. I don't know clojurescript well enough to keep helping then, sorry
10:32todungfredericks: it seems I have to cast the result of the inner seq to that taken by postwalk.
10:32gfrederickstodun: eh?
10:32todungfredericks: I get an exception.
10:32todunhttp://pastebin.com/r1jra2n2
10:33todunand I was wondering if the fix was to cast the inner input into the the expected type of the outer one.
10:33gfrederickstodun: that's an exception you get if you're accidentally calling a seq like it's a function: ##((range 12))
10:33lazybotjava.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn
10:33todunsince clojure is dynamically typed, I was not sure that was neccessary.(for I think of dynamic typing to be like automatic gear)
10:34gfrederickstodun: yeah I don't think casting means anything in clojure
10:34todungfredericks: oh. you can't do that in clojure?
10:34todungfredericks: I thought it was functional
10:34gfrederickstodun: you can't call a seq like a function, no
10:34gfrederickswhat would you expect it to do?
10:35todunI thought it was a value
10:35gfredericksa seq is a value, but it is not a function
10:35gfredericksvectors are functions, and you could maybe want seqs to act like that, but they don't
10:35gfredericks&([7 8 3] 1)
10:35lazybot⇒ 8
10:35todungfredericks: sorry. I meant I thought functions were values..equational reasoning.
10:36todungfredericks: ok.
10:36gfrederickstodun: 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:36bpsmtodun: functions are values; but not all values are functions.
10:36gfrederickstodun: just like you can't call a number: ##(7 :foo "bar")
10:36lazybotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
10:36todungfredericks: bpsm I see. thanks.
10:36gfredericksor a string ##("AHAHAHHA")
10:36lazybotjava.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
10:36ghiugfredericks: nope, it doesn't work
10:37todungfredericks: so putting a & makes it a value?
10:37gfredericksghiu: how so?
10:37gfrederickstodun: no, & is for varags
10:37todungfredericks: ok.
10:37gfrederickstodun: it's hard for me to know what you're thinking about without seeing the code
10:37todungfredericks: sorry. I thought I posted it..
10:37todunlet me repost.
10:38gfredericksnot lately; last paste was just the error message
10:38todungfredericks: ok. one second..
10:39todungfredericks: http://pastebin.com/1dvPXe3V
10:39gfredericksis the fastest way to get the last element of a vector just (v (dec (count v)))?
10:40gfrederickstodun: my first result was a bit like that, so I made the same mistake you did
10:40todungfredericks: I feel encouraged already.
10:40gfrederickstodun: 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:41gfredericksmy function started with #(if (sequential? %) ...)
10:41todun,(%)
10:41ghiugfredericks: even this doesn't work and gives me page not found .. (GET "/add/" {params :params} (params :d));;(add-gallery d))
10:41clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: % in this context, compiling:(NO_SOURCE_PATH:0)>
10:41gfrederickstodun: Oh I just noticed you aren't even passing a function
10:41gfrederickstodun: the first argument to postwalk has to be a function
10:41ghiugfredericks: calling /add?d=http://asasdasd
10:42todungfredericks: uhm..
10:42gfredericksghiu: I think compojure is sensitive to trailing slash
10:42ghiu(GET "/add" …. doesn't work either!
10:43gfredericksghiu: 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:43gfrederickstodun: in higher-order-functions like postwalk you often have to pass it a function
10:44todungfredericks: (defn f [some-list] (filter sequential? some-list)
10:44todungfredericks: so I will pass f to it, no?
10:44gfrederickstodun: you can do it at the top level using defn like you just suggested
10:44gfredericksyou can also give the function inline with (fn [some-list] (filter sequential? some-list))
10:45gfredericksor more compactly, #(filter sequential? %)
10:46todungfredericks: ok. so #(filter sequential? %) will be the arg to postwalk?
10:46ghiugfredericks: this works (GET "/add" {params :params} "asd");;(add-gallery d)) when calling http://127.0.0.1:8080/add?d=http://google.com
10:46gfredericksghiu: and then it complains it doesn't know what d is?
10:46gfrederickstodun: yes
10:47gfrederickstodun: you'll get an error on that, but it'll be a different error and you'll be a step closer :)
10:47todungfredericks: ok. trying that. allot of new syntax and concepts here. so will quickly read up some.
10:48todungfredericks: I actually tried my way first. and I get another illegalArg exception
10:48todunthis time for integers.
10:49gfrederickstodun: that's what I was thinking of when I said it was the same mistake I had made
10:49ghiu (GET "/add" {params :params} "asd") -> (GET "/add" {params :params} (params :d) -> error
10:49gfredericksthe 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:49gfredericksso it has to handle both
10:49todunI'm guessing because I have to make multiple functions and guard the inputs to postwalk?
10:49gfredericksright now that function just assumes its argument is a sequence because it passes it to filter
10:49toduntrue
10:50gfredericksghiu: what's the error?
10:50gfrederickstodun: so the next step would be to expand that function so it handles both cases, e.g. using if
10:50gfredericksin the case that the argument is not a function, you can just return the argument, as there's no transformation to do
10:50gfrederickss/function/seq/
10:50lazybot<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:52todungfredericks: ok. let me try something...
10:52ghiugfredericks: 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:53gfredericksghiu: you go from a 200 to a 404 just by changing the body of the route?
10:54todungfredericks: 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:55ghiugfredericks: yes
10:56gfrederickstodun: that makes me think he defined a function called float= somewhere and had a typo when trying to refer to it
10:56gfredericksghiu: then that is weird and I am confused.
10:56todungfredericks: yes. that makes sense. woah, clojure truly is homoiconic if it can let you define such a token. thanks.
10:57gfredericksthat just means it has permissive syntax for its symbols
10:57gfredericks(type 'float=)
10:57gfredericks,(type 'float=)
10:57clojurebotclojure.lang.Symbol
10:57gfredericks,(type '=)
10:57clojurebotclojure.lang.Symbol
10:58todungfredericks: in clojure is permissive "syntaxing" the same as homoiconicity?
10:59gfrederickstodun: 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:59gfredericksand it is also valid clojure code
11:00gfrederickstry ((juxt eval reverse) '(+ 3 4)) in your repl
11:00todungfredericks: ok...
11:00gfredericksI can't do it with the bots because they don't like eval
11:00todungfredericks: ok. I did.
11:00todunstrange
11:01todunnever used eval before.
11:01gfredericksthe point is you can treat the list like code (with eval) or like a list (with reverse)
11:01gfredericksthat's what homoiconicity is talking about
11:02todungfredericks: code is data, data is code..depending on context.
11:03gfredericks,(map type '(defn foobar [& xs] (apply + xs)))
11:03clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
11:03gfrederickswut
11:03gfredericksoh geez
11:03gfredericksyou could try that in the repl too
11:03gfredericksmaybe try guessing what the output will be first
11:03todungfredericks: strange.
11:04todungfredericks: but seemingly in line with what we'e talking about.
11:04gfredericksif you look at (defn foobar [& xs] (apply + xs)) as a data structure it should make sense
11:04gfredericksyou should notice of course when I'm using the single-quote character to "quote" things
11:05gfredericksit's what keeps the code as a data structure instead of being evaluated
11:05todungfredericks: making it a list.
11:05gfredericks,(map type [(+ 3 4) '(+ 3 4)])
11:05clojurebot(java.lang.Long clojure.lang.PersistentList)
11:05gfredericks,(list (+ 3 4) '(+ 3 4))
11:05clojurebot(7 (+ 3 4))
11:06todungfredericks: ok. it preserves the data
11:06todunand executes the code.
11:06todunso what did you mean by permissive syntax?
11:07gfrederickstodun: just that float= is a valid symbol, which I assume is what you were commenting on
11:08gfredericksmy son just woke up so my attention will be sparse from here on out
11:09todungfredericks: 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:55ghiucan 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:56ghiuehm http://stackoverflow.com/questions/7785214/compojure-how-to-map-query-parameters
12:00kjeldahl`Isn't params bound by default, see http://en.wikibooks.org/wiki/Compojure/Core_Libraries
12:01kjeldahl`In the 3rd example in the SO article, skip the {...} stuff and it should just work?
12:02kjeldahl`See "servlet bindings" in the wikibooks link.
12:04ghiukjeldahl`: i've just checked out and get parameters are not bound by default, there's a middleware for that
12:05ghiukjeldahl`: but i still don't get why "add?:u" doesn't works as expected
12:09zakwilsonIs it normal that a jar built under the Sun JDK isn't entirely reliable unde the Open JDK?
12:12kjeldahl`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:14ghiuhow did you work it out?
12:15kjeldahl`Aha!
12:15kjeldahl`See https://github.com/weavejester/compojure - Breaking changes!
12:25ghiukjeldahl`: oh! thank you, but… it doesn't seem to work either :( query parapets are still missing from params
12:31ghiukjeldahl`: is wrap-params supposed to put query params into params?
12:36kjeldahl`ghiu: See the SO page, put working example there.
13:39daniel__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:41ibdknoxdaniel__: a web framework? That seems like an odd project to do :p
13:41ibdknoxdaniel__: it depends on how low level you want to go
13:46daniel__ibdknox: not too low level
13:46daniel__i dont want to write a server for example
13:47ibdknoxdaniel__: well ring will start you at the level oh http-request/http-response
13:47ibdknoxof*
13:48daniel__yes, thats about right
13:51pyninjawhy 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:51ibdknoxdaniel__: 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:52ibdknoxpyninja: gist your code
13:52pyninjaibdknox: https://gist.github.com/b1b8561713cc5adf1611
13:53daniel__ibdknox: yes, just an interest
13:55teromdaniel__: there's also a framework called conjure, which could be worth looking into
13:56dnolenpyninja: that works just fine for me. what version of Clojure?
13:57pyninjadnolen: 1.2 i think
13:57dbushenkohello guys!
13:57pyninjadnolen: 1.2.1 actually
13:57dnolenpyninja: then you probably need to cast 5 to long with (long 5)
13:58pyninjadnolen: oh, awesome, thanks
13:58ibdknoxpyninja: yep, (long)
13:59pyninjahow would i cast the first argument? because now it says "java.lang.IllegalArgumentException: More than one matching method found: schedule"
13:59ibdknoxpyninja: (.schedule *timer* (fn [] (println "woo")) (long 4) (TimeUnit/MILLISECONDS))
14:00pyninjaibdknox: that still gives the same error for me
14:00dnolen,(bases (class #()))
14:00clojurebot(clojure.lang.AFunction)
14:01dnolen,(supers (class #()))
14:01clojurebot#{clojure.lang.IMeta clojure.lang.AFunction clojure.lang.IFn clojure.lang.IObj java.util.concurrent.Callable ...}
14:01ibdknoxpyninja: does your timer creation look something like this? (def *timer* (. Executors newScheduledThreadPool 1))
14:02dnolen,((supers (class #())) java.lang.Runnable)
14:02clojurebotjava.lang.Runnable
14:02dnolen,((supers (class #())) java.util.concurrent.Callable)
14:02clojurebotjava.util.concurrent.Callable
14:03pyninjaibdknox: hm it worked with that timer.
14:04pyninjaibdknox: i was using https://gist.github.com/2fc8d3345af793d78ebf
14:05ibdknoxpyninja: that memoize doesn't make sense to me
14:05pyninjaibdknox: me neither. copied it from https://github.com/amalloy/cronicle haha
14:05ibdknoxhah! amalloy is to blame!
14:07ibdknoxpyninja: 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:07pyninjayeah, i think (. Executors newScheduledThreadPool 1) should work for me
14:07pyninjathanks for the help
14:07ibdknoxpyninja: yeah do that. Although you probably want more than 1 thread :)
14:08pyninjaand dnolen also
14:08pyninjayeah
14:09hiredman(Executors/newScheduledThreadPool 1)
14:10khalidsuggest good project source to read
14:11ibdknoxkhalid: depends on what you want to learn
14:12pyninjahiredman: nice
14:22khalidfunctional programming (not concurrency specific topics - refs, etc. initially)
14:35khalidI am a newbie and need some help to be upto speed in clojure
14:35khalidhave a text mining project and am suggesting clojure
14:36khalidcompetition is obviously scala
14:36khalidI am liking Clojure - looks pretty fast - just basic things I have played with
14:37kjeldahlibdknox: 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:37theignoratihow would I create a map with multiple ranges (range 0 7) (range 16 23) etc as keys, all having nil as value?
14:37kjeldahlibdknox: noir related, if that wasn't obvious already.
14:37ibdknoxkjeldahl: (render "/adm/user/:username" {:username "hey"})
14:38khalidI am experienced in other lang and want to grok on some real good code
14:38kjeldahlibdknox: Ah, thanks. I missed the fact that I needed the : part in the first param.
14:41OpenJuicerHi, is there a way to install the latest clojure with leiningen?
14:41raektheignorati: something like (let [keys (concat (range 0 7) (range 16 23))] (into {} (for [key keys] [key 0]))) perhaps?
14:41ibdknoxOpenJuicer: just add org.clojure/clojure "1.3.0" as a dep in your project
14:42ibdknoxhm
14:42ibdknoxzipmap ftw here
14:42ibdknox(zipmap (concat (range 0 7) (range 16 23)) (repeat nil))
14:42ibdknox,(zipmap (concat (range 0 7) (range 16 23)) (repeat nil))
14:42theignoratithanks I have (zipmap (concat (range 0 7) (range 5 17)) (cycle [nil])) now
14:42clojurebot{0 nil, 1 nil, 2 nil, 3 nil, 4 nil, ...}
14:42theignoratiheh
15:05pcavswhat's a good library for parsing html in clojure? I just want to scrape google for the top hit for a query.
15:05raekpcavs: enlive
15:06raekhttps://github.com/swannodette/enlive-tutorial
15:08LajlaChousuke, my beloved, what is the Finnish word for 'trip' or 'voyage', I take it I can't just say mennäys right?
15:17pcavsraek: many thanks, following it now
15:22daniel__whats clojure.lang.IFn?
15:27duck1123daniel__: that's the interface that clojure functions implement
15:27gfredericks,(map #(instance? clojure.lang.IFn) [#(+ 3 4) {} [] () 15 "hehe" :okay])
15:27clojurebot#<ExecutionException java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox$eval27$fn>
15:27gfrederickswut.
15:28gfredericksoh
15:28gfredericks,(map #(instance? clojure.lang.IFn %) [#(+ 3 4) {} [] () 15 "hehe" :okay])
15:28clojurebot(true true true false false ...)
15:28gfredericksgrr
15:28gfrederickswell you can imagine the rest
15:29daniel__thanks duck1123, found my problem
15:30amcnamarahash-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:32amcnamaraand same deal with keywords for the same reason
15:32daniel__whats wrong with this? ,(take 5 (repeatedly (+ 1 1)))
15:33duck1123keywords are fns that look themselves up in the map (that one got cut off)
15:33daniel__,(take 5 (repeatedly (+ 1 1)))
15:33clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>
15:33hiredmandaniel__: read the docs for repeatedly
15:33daniel__(doc repeatedly)
15:33clojurebot"([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:33daniel__ah
15:34raek,(take 5 (repeat (+ 1 1)))
15:34clojurebot(2 2 2 2 2)
15:34amcnamara&(instance? clojure.lang.IFn (+ 1 1))
15:34lazybot⇒ false
15:34daniel__,(repeatedly 5 (+ 1 1))
15:34clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>
15:34daniel__,(repeat 5 (+ 1 1))
15:34clojurebot(2 2 2 2 2)
15:34daniel__ok
15:34Raynes&(repeatedly 5 #(+ 1 1))
15:34lazybot⇒ (2 2 2 2 2)
15:34amcnamaraor alternatively ##(take 5 (repeatedly #(+ 1 1)))
15:34lazybot⇒ (2 2 2 2 2)
15:35Raynesamcnamara: Go away.
15:35Raynes;)
15:35amcnamarahah
15:35amcnamaralazybot evaluated mine first!
15:35amcnamara(I just know)
15:35RaynesLies and slander. The bot knows his master
15:37daniel__i did need repeatedly....repeat evaluates it once and then repeats, rather than repeating the evaluation each time
16:09daniel__,(int "2")
16:09clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character>
16:09daniel__?
16:09gfredericks,(new Integer "2")
16:10clojurebot2
16:10gfredericks,(doc int)
16:10clojurebot"([x]); Coerce to int"
16:10daniel__;) thanks
16:11raek,(Integer/parseInt "2")
16:11clojurebot2
16:11raek,(identical? (Integer/parseInt "2") 2)
16:11clojurebottrue
16:11gfredericks,(map #(try (int %) (catch Exception e :nope)) [7.0 7 7N 7M "7" :7 "seven"]))
16:11clojurebotgfredericks: No entiendo
16:11raek,(identical? (Integer. "2") 2)
16:11clojurebotfalse
16:11gfrederickswtf
16:11daniel__,(identical? (.Integer "2") 2)
16:11clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: Integer for class java.lang.String>
16:11seancorfieldi'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:11daniel__,(identical? (new Integer "2") 2)
16:11clojurebotfalse
16:11gfredericksraek: what's going on there?
16:12raekInteger/parseInt can reuse Integer instances
16:12seancorfieldi'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:12raekthe Integer constructor cannot do that since it has to construct a new object
16:12raekthey are equal, though
16:12raek,(= (Integer/parseInt "2") 2)
16:12clojurebottrue
16:13raek,(= (Integer. "2") 2)
16:13clojurebottrue
16:13gfredericksraek: why would parseInt give an identical one? Are the Integers cached somewhere?
16:13raekgfredericks: yes. I think -128 to 127 are interned
16:14gfredericks,(identical? (Integer/parseInt "23456") 23456)
16:14clojurebotfalse
16:14gfrederickswell wuddayaknow.
16:14seancorfieldah, 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:17amalloyseancorfield: structmaps are an earlier iteration of records
16:19amalloyi think they can have default values other than nil, perhaps? that would make a difference
16:19gfredericksare structmaps deprecated?
16:19seancorfieldamalloy: ah, makes sense... java.jdbc only uses them to create key/value pairs based on columns in a resultset
16:20seancorfielddid they guarantee iteration order?
16:20amalloynot easy to find documentation for them, apparently
16:21seancorfieldi.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:21gfredericksand what if other keys get added?
16:22seancorfieldi 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:23amalloyseancorfield: 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:23amalloyeither way, even if it's not guaranteed clients might conceivably be (incorrectly) depending on it
16:23seancorfieldheh, well, i'll make the change and see if anyone complains :)
16:24seancorfieldinitially 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:25amalloyseancorfield: that function is just vector
16:25duck1123don'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:25seancorfieldamalloy: yes, i realized that after i wrote it, but then realized i could replace the whole thing with zipmap :)
16:26gfredericksduck1123: I think the issue is that if he changes the implementation the order might change
16:26gfredericksmaybe
16:26gfredericksmaybe not
16:26seancorfieldyup
16:26seancorfieldusing zipmap definitely gives a different order
16:27duck1123but if you have a structmap with a lot of keys, is that order stil preserved?
16:27gfredericksamalloy just looked at the code and said yes
16:27amalloyduck1123: if all the keys are in the basis map, yes
16:27seancorfieldbut 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:27gfredericksduck1123: the declared keys of a structmap are stored differently than any other keys you might add
16:28duck1123I always hated that you couldn't dissoc a basis key
16:28gfredericksduck1123: just on principle? Or did you want to do that at some point?
16:29duck1123I 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:30gfredericksokay 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:31tomojin order of depth = breadth-first?
16:31gfredericksoh 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:32gfrederickstomoj: I believe so, yes
16:32tomojtrivial?
16:32tomojseems impossible to me
16:32tomojsuppose you're on the far right, now you jump down to the next level on the far left
16:32amalloygfredericks: the constraints are not well-stated. certainly you can do it, by keeping everything on disk instead of in memory
16:32tomojdidn't you have to have the whole level in memory?
16:33gfredericksamalloy: add that constraint too :P and no keeping stuff in the cloud either
16:33gfrederickstomoj: hmmm
16:33gfrederickstomoj: I think at worst it would require going back up to the root and back down
16:34amalloygfredericks: which is already infinite memory, in an infinite tree
16:34gfredericksmaybe that's the best that can be done as well
16:34gfredericksamalloy: it's a lazy tree
16:34amalloyso?
16:34gfredericksamalloy: oh you mean the path
16:34tomojpretty strange if it GC's branches you climb back up
16:34gfredericksthe path is fine. I don't want any bottleneck worse than the path.
16:35amalloyif 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:35gfredericks"the whole row" would certainly be worse than the path
16:35gfredericksamalloy: man I'm bad at this describing a problem thing. It's not an actual tree, just a conceptual one.
16:36gfredericksso by lazy tree I just meant that it doesn't exist in memory, just the function to compute the children of a node
16:36tomojare you using a conceptual computer? :P
16:36gfredericksnevermind, I'll go off in my corner and figure it out :P
16:36tomojdo you have a function to compute the parent given a child?
16:37gfrederickssure
16:37gfredericksI guess that's not obvious, but I do
16:37tomojI didn't expect that answer. carry on. :)
16:38gfredericksI think I can just deal with having to go back to the root every once in a while...
16:39gfredericksit's at least better than my current implementation which goes back to the root every time
17:24seancorfieldas 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:24seancorfield(sometimes reading the Clojure source code is not as enlightening as others)
17:25raekseancorfield: why not (zipmap keys (row-values)) ?
17:26seancorfielddoesn't preserve the order at all
17:26seancorfieldi'm worried that some ppl may be relying on getting the columns in the same order as their SQL select...
17:27raeksorry, didn't read the ArrayMap part
17:27seancorfieldnp, i'm sure it's an edge case anyway
17:27gfrederickshmmm....looks like into uses (reduce conj ...) while zipmap uses repeated assoc
17:27seancorfieldi ran a full suite of tests with zipmap and it all passed so i know world singles' code is not relying on ordering :)
17:28raek,(class (zipmap (range 3) (range 3)))
17:28clojurebotclojure.lang.PersistentArrayMap
17:28duck1123seancorfield: either make it an ordered map, or tell people there is no guarentee of order
17:28raek,(zipmap (range 5) (range 5))
17:28clojurebot{4 4, 3 3, 2 2, 1 1, 0 0}
17:29raek,(into {} (map vector (range 5) (range 5)))
17:29clojurebot{0 0, 1 1, 2 2, 3 3, 4 4}
17:29seancorfieldduck1123: well, there was no specific documented guarantee of order - except insofar as resultset-seq used structmaps
17:29raektough decision to make...
17:29raekit's not fun to breake people's code
17:30raekbut they shouldn't relied on the order of the map entries anyway
17:30seancorfieldi don't think structmap provided a documented guarantee of key order either?
17:30raek:/
17:30duck1123I would change it to explicitly say "don't count on it, bub"
17:30seancorfieldraek: i agree
17:31raekthe only guarantee I've heard about is that keys and vals should visit the entries in the same order
17:31seancorfieldi think this is a reasonable compromise tho' so that's going in and i'll be declaring 0.1.0 soon...
17:31raeknot time for 1.0.0?
17:32raeksince people have been using it for ages already
17:32gfredericks1.0.0 would certainly take away the fear of breaking stuff
17:32duck1123this is c.j.jdbc, right?
17:32duck1123isn't it already past 0.1.0?
17:33raekideally, libs should be at least 1.0.0 when others rely on them
17:35seancorfield1.0.0 of contrib requires clojure/core approval and there's a lot to improve in c.j.jdbc before it gets there
17:36seancorfieldc.j.jdbc is at 0.0.7 now but i'll bump to 0.1.0 now structmaps are out
17:36raekah, I see... didn't think of the processes involved... :-)
17:36seancorfieldthe other open tickets are all post 0.1.0 in my mind
17:37seancorfieldi'm planning to provide an API overhaul for 0.2.0 based on feedback on clojure-dev and from some users
17:37seancorfieldor rather add a new consistent simple API (and maintain the current API)
17:39seancorfieldat 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:40seancorfieldthere was also specific feedback from clojure/core about binding vs passing in arguments which i've been considering for a while anyway
17:40gfredericksseancorfield: do they prefer one or the other?
17:40ibdknoxseancorfield: is c.j.jdbc going to change a lot?
17:41seancorfieldand feedback on merging the internal ns into the main ns as private vars (that would allow quite a bit of simplification as well)
17:41seancorfieldclojure/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:41amalloyreally? separate namespaces seem much nicer than private vars
17:41ibdknoxseancorfield: I've made a lot of headway on Korma, which has a decent amount of reliance on c.j.jdbc
17:41ibdknoxI'm with amalloy on that one
17:42seancorfieldibdknox: no breaking changes, just additions
17:42ibdknoxit also gives room to grow
17:42gfredericksI'm curious what simplifications a single ns gets you
17:43seancorfieldcurrently 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:44seancorfieldif it's all in one ns, the def can go away and the "internal" functions can call the public stuff directly
17:44gfrederickshmm
17:44gfredericksthat's essentially a bidirectional dependency, isn't it?
17:44seancorfieldwhen 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:45seancorfieldbut we've moved away from that over time and cleaned up our namespaces quite a bit
17:46seancorfieldpart 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:51danielp1234yo
17:51gfredericksdanielp1234: yo
18:14gfredericksIt is counterintuitive that distinct? takes varargs.
18:14ibdknox,(doc distinct?)
18:14clojurebot"([x] [x y] [x y & more]); Returns true if no two of the arguments are ="
18:15gfredericksparticularly since distinct takes a collection
18:22amalloygfredericks: i wish min/max took collections too, but c'est la vie
18:23gfredericksvarargs. they make everything better and worse.
18:26technomancyseancorfield: that's funny; we went the other way at sonian
18:26technomancypartly for testability purposes
18:27gfredericksaren't internal namespaces easier to test than private functions?
18:27seancorfield(let [some-name @#'ns/some-name ...] ...) ;; exposes private function for testing :)
18:27gfredericksat least in the traditional clojure.test setup that lein gives you?
18:27seancorfieldthe question is: why are you testing private functions? :)
18:28seancorfieldthe unit testing world seems split on that question
18:28gfredericksdoes `lein test` run the functions attached to the :test metadata?
18:28gfredericksI don't know if anybody uses test metadata... I just read about it again the other day so it's in my head
18:29technomancygfredericks: it runs based on all namespaces with corresponding files in the test/ dir
18:30technomancyseancorfield: 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:31seancorfieldtechnomancy: 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:31technomancyoh, right
18:31technomancycarry on then =)
18:32seancorfieldthe 0.2.0 API will expose functions with explicit arguments (and rewrite the with-* stuff to depend on those)
18:32technomancyalso, what do you think about accepting a database connection URL rather than a map of :user, :host, :password, etc?
18:32gfredericksor both?
18:32seancorfieldopen a JIRA issue :)
18:32technomancygfredericks: naturally =)
18:33technomancyseancorfield: will do. I can put together a patch.
18:33technomancyjust wanted to run it by you first.
18:33gfredericksmultimethod!
18:33seancorfieldi 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:34amalloygfredericks: {:user "nobody" :host "localhost" :url "mysql:nobody@localhost..."} - an excellent way to do "both"
18:40technomancyyeah, just translate strings into {:url "..."} and extract username etc from the url if it's not already in the map
18:41RaynesWhen 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:41amalloyheh. i was *actually* suggesting you require both, just to annoy users, but technomancy's idea is better
18:41gfredericksamalloy: oh so "excellent" was ironic?
18:42gfredericksah ha you were playing on the word "both". Man I could not figure out why you were recommending that.
18:43amalloy(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:44gfredericksI almost had something with juxt...
18:44tomoj(let [x (foo)] (if (and x (bar x)) (then x) else)) is that nice?
18:44amalloyi guess i could write (let [x (foo)] (if (and x (bar x)) (then x) else))
18:44ibdknoxI wish if-let would allow multiple bindings
18:44tomojand/or correct?
18:45ibdknoxI almost always do (if-let [x 1] (let [y ...
18:45amalloytomoj: yeah, that's correct except in the case where x is already bound and the let is intended to replace it
18:45gfredericks(let [x (foo), y (and x (bar x))] (if y (then x) else))
18:46ibdknoxtechnomancy: why do you prefer the url?
18:46tomojibdknox: you'd want it to only check the truthiness of the first binding?
18:46ibdknoxtomoj: yep
18:46amalloyibdknox: i think the reason it doesn't exist is it's not clear what it does
18:46ibdknoxit would be fairly trivial to implement a macro that does it
18:46ibdknoxamalloy: I agree with that
18:47amalloyit would be equally "obvious/useful" to check the truthiness of all the bindings
18:47ibdknoxI'm not sure it's the "right" thing to do... but it's what I want :p
18:47ibdknoxI actually expected it would check all of them if you had more than one
18:48tomojseems likely you'd have to check the values manually in the else anyway
18:48tomojguess not sometimes..
18:49amalloytomoj: 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:50amalloy(if-user [u] (if (test u) (then u) else) else). i guess i could go write let-user
19:01devthany suggestions on a good way to format a map as a querystring? seems reduce is not the way to go.
19:01gfredericksstring/join
19:02devthi don't see how that would work with key/vals
19:02devthoh, i suppose you could use map to create the keypair representation
19:02amalloyright
19:02gfredericks(string/join "&" (for [[k v] m] (format "%s=%s" k v)))
19:03amalloythough this function has been written a number of times before
19:03gfredericks^ and that of course ignores encoding complexity
19:03devthright. thanks.
19:04gfredericksalso it assumes keys and vals are strings... :/
19:07tomoj&(format "%s" {:foo :bar})
19:07lazybot⇒ "{:foo :bar}"
19:07gfredericksreally?
19:08gfredericksWell I'll be.
19:08amalloygfredericks: %s calls .toString
19:08gfredericksthere goes java. always being relaxed about types.
19:08amalloythe scoundrels
20:25technomancyRaynes: if it were just for me I would probably skip it, but since this is for work I'll put up with jira
20:29technomancyheh; 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:30amalloytechnomancy: are you sure? i don't think "or" makes sense as a model
20:31amalloy"bind at least one of these variables, i don't care which"?
20:35technomancyI don't think it makes sense either =)
20:35technomancybut I think I've heard it
20:55duck1123and makes sense, with one else for if any of them fail
22:43khaliGhm. it takes 12s before my clojure/swing app pops up.. :(