#clojure log - Jun 03 2010

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

0:07 KirinDave: Anyone wanna tell me I'm wrong?

0:07 http://kirindave.tumblr.com/post/658770511/monkey-patching-gorilla-engineering-protocols-in

0:08 tomoj: your fonts are ultra sexy

0:12 KirinDave: tomoj: Thanks. Museo and Museo Slab.

0:12 Museo is free. Slab is not.

0:14 tomoj: My opinion: typekit is worth every penny ;)

0:25 mabes: KirinDave: great post. The only thing that you might want to add is an explanation on why defprotocols, etc, are not simply wrapper objects like you would see in Ruby and other OO languages

0:25 KirinDave: mabes: Care to be more specific?

0:26 mabes: KirinDave: sure, the the problem with wrapper objects is (as explained to me at the recent clojure training) is that they usually destroy the concept of identity

0:27 KirinDave: Sure.

0:27 I actually don't know how protocols work

0:28 I noticed that if you have two protocols on the same type with the same name, it complains.

0:28 Which leads me to believe it's actually injecting things into the class?

0:29 mabes: so a MyIntHolder in Ruby would not == an int of the same value unless the the programmer explicitly added a #== method, where as in clojure the concept of equality is much simpler and is constant

0:29 KirinDave: Right, but does it actually inject the method into the class?

0:30 mabes: into the what class?

0:30 er.. into what class

0:31 KirinDave: Say, I extend MyIntHolder with 2 protocols that both name a method with identical name and arity, it complains.

0:31 tomoj: yeah, the generated class gets actual methods

0:33 KirinDave: But for say java.lang.String?

0:33 tomoj: oh, I was thinking of deftype/defrecord

0:36 extend-protocol just modifies the protocol, not any classes

0:36 mabes: I know there was a misunderstanding on stackoverflow about that very issue.. people were saying that clojure somehow allowed for monkey patching of java.lang.String, but that is really not the case... I'm trying to find it to see if a more knowledgeable person explained the difference well

0:38 I think stuart holloway's video may touch on this subject as well: http://vimeo.com/11236603

0:41 hrm... I can't seem to find it..

0:43 tomoj: https://gist.github.com/3fbd7c6f776820639aa1

0:43 also, (.foo "") gives an error

0:45 mabes: tomoj: very nice. thats the best example I've seen showing how the extensions respect name spaces and how they are different from monkey patches :)

0:48 tomoj: it seems like deftype/defrecord examples usually use extend-protocol

0:48 I wonder why

0:50 KirinDave: tomoj: I tried to mention both. Probalby because most people have one protocol and many types. Because it's more typing.

0:50 Err, less typing to have one protocol and more types.

0:50 qebab: Assuming I know scheme, python, c and have some passing experience with common lisp and haskell, should I just get a language reference and jump right into coding something or am I better off following a tutorial?

0:51 KirinDave: If you know python you are TAINTED

0:51 seoushi: qebab, thats what I've done so far. I've watched and read a few things but for the most part just jumped into coding.


0:52 qebab: KirinDave: even worse, I even like it! :(

0:52 seoushi: okay, that sounds good

0:52 mabes: qebab: with a lisp background you could probably jump right in... this is a pretty good tutorial that you could skim through: http://java.ociweb.com/mark/clojure/article.html

0:52 qebab: thanks mabes

0:53 tomoj: KirinDave: ah, yeah

0:54 mabes: qebab: reading this, if you haven't already, might also save you some frustration as well: http://clojure.org/lisps

0:55 qebab: mabes: thanks again

1:41 lancepantz: isn't there a reader macro that sets the :tag key in a functions meta data?

1:41 or is that deprecated in 1.2?

1:42 tomoj: ,(meta #^String (fn [x] x))

1:42 clojurebot: {:tag java.lang.String}

1:42 tomoj: hmm

1:43 ,(meta ^String (fn [x] x))

1:43 clojurebot: {:tag java.lang.String}

1:43 tomoj: ,*clojure-version*

1:43 clojurebot: {:interim true, :major 1, :minor 2, :incremental 0, :qualifier "master"}

1:44 lancepantz: so it has to be a java class?

1:44 tomoj: ,(meta ^:foo {})

1:44 clojurebot: {:tag :foo}

1:45 lancepantz: nice

1:45 thanks tomoj

1:45 tomoj: this is kinda weird

1:45 ,(let [a 3] (meta ^a {}))

1:45 clojurebot: {:tag 3}

1:45 tomoj: (meta ^3 {})

1:45 ,(meta ^3 {})

1:45 clojurebot: Metadata must be Symbol,Keyword,String or Map

1:50 lancepantz: wish i could use a list or vector as metadata

1:50 *tag metadata

1:52 tomoj: how would that make sense

1:52 ^[Foo] for a function that returns a seq of Foos?

1:52 lancepantz: i'm using it to "tag" tests

1:53 tomoj: that sounds evil

1:53 lancepantz: so you can tag a test as unit, functional etc, i like the reader macro, but i'd like to be able to tag one test with multiple tags

1:53 why's that?

1:54 tomoj: :tag has special meaning

1:54 lancepantz: i was afraid that's what you were going to say, do you know what its used for?

1:55 tomoj: it's for the return type of a fn or type of a value in a var

1:55 ,(meta ^{:test-tags [:foo :bar :baz]} {})

1:55 clojurebot: {:test-tags [:foo :bar :baz]}

1:55 qebab: what's the best way of running a clojure shell in emacs? just setting *inferior-lisp*?

1:56 lancepantz: yeah, i guess i'll do it that way

1:56 tomoj: I don't think anything will blow up if you misuse :tag.. but it sounds like a bad idea to me

1:56 you can of course define a macro which makes it prettier :)

1:56 qebab: SLIME?

1:57 qebab: tomoj: ohh, neat

1:57 tomoj: didn't know clojure was supported, I'll look into that, thanks :)

1:57 lancepantz: test functions don't actually have a return value, so i don't think it would affect anything, for now.

1:57 tomoj: qebab: http://github.com/technomancy/swank-clojure/blob/master/README.md

1:57 qebab: thanks a million tomoj

1:59 tomoj: qebab: basically: install ELPA, install clojure-mode and slime-repl from ELPA, use leiningen or maven

2:00 lancepantz: tomoj: how could i use a macro to make it prettier?

2:00 i would have to redefine deftest, correct?

2:01 tomoj: wrap over it, yeah

2:01 yours could be called deftest or something else

2:02 lancepantz: cool, thanks for the pointers

2:47 tomoj: can anyone confirm that rec-map at http://blog.ethanjfast.com/2010/03/analyzing-word-frequencies-with-clojure-enlive-and-incanter/ is absolutely bonkers?

2:51 replaca: tomoj: bonkers in what way?

2:53 tomoj: well, very overcomplicated and misusing trampoline, for example?

2:55 replaca: tomoj: maybe. I doubt the tree would be so deep as to really need trampoline

2:55 tomoj: right

2:55 but isn't that use of trampoline equivalent to just recurring naively (e.g. (rec-map newc))?

2:56 replaca: tomoj: but I don't have a problem with using it and otherwise it doesn't look too complicated to me

2:56 tomoj: I mean, if the tree were deep enough, those trampolines wouldn't help

2:56 replaca: tomoj: hmm, maybe. I'd have to reread the docs

2:57 tomoj: also.. (defn match [thing lst] (reduce #(or %1 %2) (map #(= thing %1) lst)))

2:57 that, at least, is overcomplication, I hope

2:58 replaca: yeah, you could just do (#{:div ...} mytag)

2:59 and not string the tag

2:59 tomoj: I didn't even think about the stringification

3:00 replaca: tomoj: now that you mention it, just replace the whole (let...) with

3:01 tomoj: I think the whole function could be replaced by some simple enlive stuff, but I'm not sure because I still don't really understand what the heck it's doing

3:02 replaca: (rec-map (if (#{:div ...} (:tag %1)) (:content %1) ""))

3:03 for starters

3:03 tomoj: so.. at least a little bonkers, eh?

3:03 :)

3:04 replaca: oh, we all need some cod review

3:04 but using enlive just means letting Christophe handle your complexity for you

3:04 tomoj: yeah, the question for me was whether the code could be improved or whether I needed to be improved

3:05 replaca: but, yeah I would say the (str (%1 :tag)) is bad style

3:05 tomoj: I think code by people who are much smarter than me usually doesn't make any sense at first, so hard to tell whether it's the code or me that sucks

3:05 replaca: it's more idiomatic to live in keyword-space

3:08 but it's important to read lots of code

3:08 I recommend the enlive source, in particular

3:08 tomoj: thanks

3:09 replaca: it'll warp your brain, but you'll come out the end a better functional programmer

3:10 timcharper: any concurrency/lazy-seq wiz's in here?

3:10 replaca: hmm, maybe

3:10 shoot your q

3:10 timcharper: I'm trying to build a pipeline function

3:11 where a collection is passed through a various set of map transformations

3:11 I'd like each step of the pipeline to happen in parallel, similar to how | works in bash (each process runs at full speed, sensitive to the buffers of the surrounding processes)

3:11 this implementation, unfortunately, does not work:

3:11 http://pastie.org/990136

3:13 It eager loads, but what happens is map #1 will eager load 33 records, then once that's done, map #2 will proceed, do some work, wait for map #1

3:13 in the end, they effectively wait on one-another instead of processing each seq in parallel

3:14 (i've tried it with pmap too.... pmap of a pmap ends up not being much of a pmap at all :( )

3:14 well... pmap + chunking... because overhead of thread scheduling is great

3:14 replaca: timcharper: yeah, that looks completely serial to me

3:15 timcharper: but since I'm wrapping the lazy-seq in a future... wouldn't it cause it to eager load in a separate thread ?

3:15 or is it because the deref of the future is what causes the eager-load, so therefore it blocks?

3:15 replaca: yeah, the deref will load it

3:15 timcharper: oh... ok

3:16 so the future is effectively worthless (as the results show)

3:16 replaca: lazyness and futures have nothing to do with each other, really

3:19 timcharper: yeah, I understand that

3:19 http://clojure-log.n01se.net/date/2010-06-02.html

3:19 technomancy mentioned I can wrap my calculations in a future, and it will work

3:19 replaca: you might be able to get something to work if you did a future with a doall on the collection to force the evaluation in the other thread

3:19 timcharper: wanting to exploit streams here (not load the whole thing in memory)

3:19 replaca: but you're still going to be lock stepping on the deref

3:19 timcharper: or rather, streaming-properties of lazy sequences

3:19 perhaps I ask for too much ?

3:19 (I don't see any reason why this shouldn't be possible)

3:19 replaca: you might look at fill-queue, though that adds a little complexity

3:19 (c.c.seq/fill-queue)

3:20 timcharper: extra complexity is acceptable so long as it gets the job done and it's tucked away in an abstraction

3:21 replaca: your lazy seqs could be built around reading from a queue of values

3:21 I'd have to play around with that, but I bet you could get a nice abstraction there

3:21 timcharper: how would it look?

3:22 replaca: hmmm

3:27 at it's core would be something like (fill-queue (fn [fill] (map f-sub-0 (fill-queue (fn [fill] (map f-sub-1 (fill-queue (fn [fill] ...)))))

3:27 but you wouldn't really build it that way - you'd automatically create a vector of fill functions or something

3:28 timcharper: yeah :) which I have already in the pipeline function

3:28 I'll give it a shot

3:28 replaca: also, you probably want to specify a significant queue size with the :queue-size parameter

3:29 timcharper: in other news.... I caused a eager-load to occur in the future

3:29 replaca: it would be nice to abstract the fill-queue stuff away from the caller, of course

3:29 timcharper: it loaded the first 33 itmes

3:29 replaca: sound like 1 chunk

3:29 timcharper: still... even though it was occurring in a separate thread and the first item was calculated, it wouldn't give it to me until it was done eager loading

3:30 replaca: yeah, cause you're really sucking the whole thing over to the other thread

3:30 concurrency in clojure is tricky!

3:30 tomoj: replaca: StackOverflowError

3:30 :D

3:31 replaca: cool when you get it right, but head scratching when you don't

3:31 timcharper: the fill-queue will overcome it ?

3:31 replaca: used properly, my son, it is a weapon of great power :-)

3:31 timcharper: heheh, ok

3:32 replaca: in any case, time for me to get some sleep

3:32 let me know how it goes

3:32 timcharper: an excellent plan

3:32 good luck with it

3:32 replaca: thx :)

3:47 tomoj: oh, wow, the stack overflow wasn't from rec-map calling itself

3:48 it was inside .replaceAll

3:48 apparently you can get stack overflows from bad regexes

4:02 LauJensen: totally OT, but if there are any network experts that can help I'd really appreciate it: http://bbs.archlinux.org/viewtopic.php?pid=768835

4:03 tomoj: :( good luck

4:04 TheBusby: er, is it only with wireless you have the problem?

4:05 LauJensen: TheBusby: I would imagine so, but I actually haven't tested eth0

4:05 TheBusby: I'd do that first since it'll reduce the numbers of potential issues considerably

4:05 LauJensen: k, sec

4:24 Ok - I think I know what the problem is now, thanks TheBusby for getting me out of my chair :)

4:43 TheBusby: hehe, good to hear

4:45 LauJensen: Yes - Except for the fact that its probably unfixable

4:46 tomoj: what was the problem? just curious

4:46 oh, nevermind, saw your last post

4:47 LauJensen: Yea I just updated it with my last whine :)

4:47 TheBusby: well I thought you said it worked fine in Ubuntu 9.04 . That means there is definitely a work around though it may require some trade off rightT?

4:48 LauJensen: My wifes laptop is running Ubuntu 9.04, I've never tried 9.04 of this machine as I installed 10.04 directly when I got it, then when I discovered this issue, I upgraded to Arch 2010.05

4:48 But I guess booting from a 9.04 live-cd is a cheap way to find out

4:48 TheBusby: yep

4:49 er, what was the issue? driver I'm guessing?

4:49 LauJensen: I think it has to be the iwl-5000-ucode firmware

4:50 core/iwlwifi-5000-ucode

4:50 Intel wireless firmware for Intel's 5100BG, 5100ABG, 5100AGN, 5300AGN and 5350AGN wireless devices


4:51 TheBusby: isn't the firmware the same between Windows and Linux though? Wouldn't that still be a driver issue? (or is the firmware require a signed driver or something strange?)

4:52 LauJensen: I don't know. I imagine that Windows has a firmware/driver combo developed by Intel,and Linux has something 2 hobby devs slapped together in a basement

4:54 This might be the way to go: http://www.instructables.com/id/WIFI-Antenna-Hack!/

4:56 TheBusby: I'm assuming from this topic that when you used an ethernet cable the speeds were fine right?

4:56 what leads you to believe it's the wireless driver?

4:58 LauJensen: TheBusby: The tip was, eth0 was fullspeed, bringing it down and going to wlan was also full speed. Going back into my office was slow speed. I think its the driver because it works fine in Windows, eliminiting any hardware issues

4:58 TheBusby: so after you connected via ethernet, and experienced no problems

4:58 the wireless continued to work with no problems?

4:59 you've essentially removed the possibility of hardware issues with the Windows/Linux test

5:00 but a number of possibilities remain. Is it driver, kernel, tcp/ip, etc...

5:00 LauJensen: Yes the wireless had no problems when I was sitting right next to the router, going back to the office (about 20m away caused the issue)

5:01 TheBusby: so you only experience the problem in linux at a distance from the router correct?

5:01 LauJensen: Yes

5:02 TheBusby: and do the signal strength, and noise ratio appear the same in both windows and linux at that distance?

5:03 LauJensen: No, like I state in the post on the forum, the signal strength is 350% better when Im in Windows - Measuring from the office. I didn't test both OS' while next to the router, but I noticed that Linux had only 54% strength at 1.5 meters distance, which is much too little, I imagine Windows would have 100%.

5:09 TheBusby: can you increase the signal strength? $ sudo iwconfig wlan0 txpower 15

5:09 LauJensen: Hmm, my router can adjust its transmission power from 0 - 255, it was set to 10 which is the default

5:09 increasing to 100 makes the signal 20% instead 8%

5:09 TheBusby: you were having problems uploading though correct?

5:09 I'm wondering what you broadcast strength is set at...

5:10 LauJensen: No problem uploading

5:10 But to be honest I think this was the queue I needed to install cabled internet throughout the house

5:10 TheBusby: still it's nice to use wireless with a laptop

5:10 eevar2: or switch to windows/mac? :p

5:11 LauJensen: eevar2: I'd rather loose 350% wifi signal, than 750% productivity, but thanks

5:11 TheBusby: so you only have the bandwidth problem with downloading?

5:11 your archlinux post says the bandwidth problem is when "upholding"

5:12 also wondering if you're using the same channel, etc when using linux/win

5:12 eevar2: TheBusby: that's a router setting afaik?

5:13 channel, that is

5:14 TheBusby: don't remember the proper terms, but is it using the same frequency and everything?

5:16 LauJensen: ping?

5:16 clojurebot: PONG!

5:16 LauJensen: ,ping

5:16 clojurebot: java.lang.Exception: Unable to resolve symbol: ping in this context

5:16 LauJensen: I had some kind of drop, but order is restored, 200x amplified signal solved the problem

5:16 cables will be the permanent solution

5:17 TheBusby: Just for background, https://bugs.launchpad.net/ubuntu/+source/linux-backports-modules-2.6.27/+bug/282453

5:17 er, nmind

5:50 esj: LauJensen: More Power !

5:50 LauJensen: esj: hehe - I'm cable shopping now

5:50 But I guess with Linux its true, you really get what you pay for :)

6:02 slurp does about 30mb/s here, how are you guys doing?

6:03 Interesting:

6:03 bestinclass.admin> (time (do (last (read-lines "access.log")) nil))

6:03 "Elapsed time: 372.741705 msecs"

6:03 bestinclass.admin> (time (do (slurp "access.log") nil))

6:03 "Elapsed time: 2030.449639 msecs"


6:04 Probably the missing hints in slurps definition

6:51 rhickey: Any particular reason conj takes xs and conj! only takes x ?

6:51 rhickey: LauJensen: nope

7:06 Licenser_: swing makes me sad :(

7:08 hoeck: Licenser_: why?

7:08 Licenser_: because my swing tree does not update

7:08 it works great in my demo example but not in my code :/

7:08 eevar2: Licenser_: read the tutorial. learn the event model

7:09 Licenser_: eevar2: it works for the example, sadly not in my real app and I'm not sure why

7:09 hoeck: and stick your gui-code to the event-dispatch-thread

7:09 Licenser_: well it gets called and all that isn't the problem I think

7:10 it is very odd

7:10 eevar2: Licenser_: i'd make the same assumption as hoeck. guess i should have written event/threading/painting

7:11 Licenser_: everything that gets called from without swing will be in the swing thread right?

7:11 or do I have to wrap every form into it?

7:14 hoeck: Licenser_: http://java.sun.com/docs/books/tutorial/uiswing/concurrency/dispatch.html

7:16 Licenser_: if you call something from an action-listener, it is executed within the swing thread, from the repl you should use SwingUtilities/invokeLater

7:18 Licenser_: hoeck: I am only calling stuff from listeners

7:20 odd thing is, in the thread if I call it once it works if I call it twice it doesn't

7:20 erm the other way round

7:27 hoeck: mhh, maybe some listeners are fireing in the wrong order

7:29 Licenser_: do you have a small example which reproduces the error?

7:31 Licenser_: hoeck: that is the problem, I have a smnall example which does not even so I do mostly the same

7:39 but I try to make it so it breaks there too :P

7:45 hoeck: I got on the trace of it, problerm seems to be maps as keys

7:53 hoeck: problem is the exxam ple can't be small since it uses clj-swing :/

7:56 spariev: candera: thanks for the suggestion, I didn't know about <= taking more that 2 args

8:00 hoeck: Licenser_: mhh, if you do everything via listeners, maybe some of your actions must be invoked with SwingUtilities/invokeLater?

8:00 Licenser_: hoeck: I think the problem is something else it wokrs unless I use hashmaps as keys

8:00 hoeck: Licenser_: so that, before taking other actions, the "initial" event chain can be executed

8:00 Licenser_: I think it is an algoriuthm error not one of swing

8:00 candera: spariev: NP. That problem has been in my head since you mentioned it yesterday. :)

8:01 hoeck: Licenser_: ah, ok

8:01 spariev: heh )

8:01 candera: I was also trying to figure out if a zipper would make it easier to express.

8:01 Licenser_: which is hard since it's uglyish complex

8:01 and I have to wrap stuff in treepath and events and all other kind of ugly objects

8:02 oh this makes headache

8:09 spariev: candera: I found it quite hard for me to think about such kind of problems in functional style, where you basically have to mutate data structures

8:10 too accustomed to imperative style thinking

8:10 candera: That's my big challenge too.

8:10 The other areas of Clojure that are new to me haven't been nearly as hard to adjust to.

8:11 Which is why I was thinking of zippers, since it's a functional way to "remember" your location in a sequence, which might make an approach that looks ahead a bit more tractable.

8:11 But maybe I'm just trying to be pseudo-imperative.

8:25 Licenser_: I really don't get it :(

8:27 bartj: er, can't lazy seq be returned from a function?

8:27 cemerick: of course they can

8:27 bartj: for eg: using the code in the winning answer here - http://stackoverflow.com/questions/613929/how-do-i-connect-to-a-mysql-database-from-clojure

8:28 I am unable to return only the resultset of the sql query

8:28 ie. instead of (dorun (map #(println %) rs)) -> can't I just return rs?

8:30 cemerick: bartj: if the population of the rs (or any lazy seq) is dependent upon a thread-local binding (which may be the case given with-connection?), then you just need to return (doall rs) to ensure the seq is fully realized before escaping that scope.

8:30 hoeck: bartj: you can, but then you have to keep the connection open

8:30 Licenser_: \huzza I found it!

8:32 cgrand: bartj: try (doall rs) to force realization of the seq inside of the with-connection (dynamic) scope

8:32 hoeck: Licenser_: what was it?

8:32 bartj: another approach I tried was to store the resultset into a variable using let and return that, which still doesn't help

8:32 Licenser_: I casted something to a string at one point

8:33 bartj: cgrand: no luck

8:33 Licenser_: which made it work with string indexes (of cause) but not anything else

8:33 bartj: cgrand: did try that

8:35 cemercik: no (doall rs) strangely doesn't seem to work

8:35 cgrand: bartj: what did you get? an error? nil?

8:35 bartj: nil

8:37 candera: (into [] rs), to realize the seq, perhaps?

8:37 cemerick: bartj: if it's returning nil, you've got bigger issues than returning a lazy seq

8:38 candera: Ah, right. I was thinking doall didn't return the seq. Wrong again! :)

8:39 bartj: like I said: (dorun (map #(println %) lazy-seq)) does show some output

8:40 so wondering WTH I can't return the lazy-seq as well

8:43 cemerick: actually it doesn't return anything

8:44 cemerick: bartj: if you can print the results, you can return the results

8:48 bartj: cemerick: (defn get-result-set [] (sql/with-connection *db* (sql/with-query-results rs ["select-query"] rs)))

8:57 LauJensen: ,(import '(javax.mail Session))

8:57 clojurebot: java.lang.ClassNotFoundException: javax.mail.Session

8:59 zmila: -- download jar: http://www.java2s.com/Code/JarDownload/mail.jar.zip

8:59 LauJensen: yea I got it, just missed a dep in project.clj

9:00 Is there anything in contrib like (max 5 "hi there buddy") =>> "hi..y" ?

9:02 cemerick: bartj: I don't know what the semantics are of with-connection or with-query-results, but assuming rs is a lazy seq, then returning (doall rs) would seem sensible.

9:05 r0man: ,(defrecord Dataset [url])

9:05 clojurebot: DENIED

9:06 r0man: ,(new (type (Dataset. nil)) nil)

9:06 clojurebot: java.lang.IllegalArgumentException: Unable to resolve classname: (type (Dataset. nil))

9:09 r0man: how can i make a new record from instance of a record?

9:19 a_strange_guy: r0man why would you do that?

9:20 they are immutable, so there is no copiing necissary

9:23 r0man: a_strange_guy: i want to create a new modified instance

9:24 a_strange_guy: (assoc instance :key value)

9:24 r0man: a_strange_guy: and because (dissoc my-data-datatype :key-to-remove) yields a map and not a instance of my datatype

9:25 a_strange_guy: you cannot dissoc a 'field' in a record

9:25 well, you can

9:26 r0man: (defrecord Dataset [url])

9:26 (class (dissoc (Dataset. "some-url") :url))

9:26 a_strange_guy: but it will return a map

9:26 r0man: yes and i want a datatype

9:26 a_strange_guy: that is not possible

9:26 a defrecord MUST have the specified keys

9:27 r0man: a_strange_guy: so i thought building a new one with one of the keys set to nil

9:27 a_strange_guy: (Dataset. nil)

9:28 a_strange_guy: (assoc (Dataset. "Url") : url nil)

9:29 r0man: a_strange_guy: but i want to decide at runtime which record i instantiate

9:29 a_strange_guy: ok

9:30 a_strange_guy: if you want to remove the key completely

9:30 then you shouldnt sprecify it as a key

9:30 r0man: a_strange_guy: thx, it's solved. i was thinking around the corner :)

9:30 a_strange_guy: xD

9:50 _exterm: hey everybody, after switching from clojure 1.0.0 to 1.1.0 I get the following stacktrace when building: http://pastebin.com/kvHvqHwe

9:50 any ideas?

9:58 i don't use with-bindings anywhere in my own code...

10:00 chouser: maybe your swank version is out of date?

10:00 * chouser knows nothing about swank

10:00 _exterm: ah, now that's an idea :-)

10:01 do you think it's somehow defining its own version of with-bindings?

10:01 I'll look for it

10:01 thanks for the idea!

10:12 no, it's definitely not the swank version. Nonetheless I'll check the other libraries I use.

10:14 korre: hawing problem with printing on other threads?

10:18 _exterm: turns out it was (:use clojure.main) .

11:31 chouser: I have data handed to me that I would like to extend with a protocol. But the data is a vector, and I don't mean to extend *all* vectors.

11:32 candera: Why a protocol? To group a set of functions?

11:32 chouser: I could put metadata on the vector and use multimethods, or I could add a defrecord wrapper.

11:32 candera: yes, and because I need polymorphism. Other things will hand me similar data in a different format, and I want the same set of functions to work on both.

11:33 AWizzArd: chouser: I am in the same situation. I would have to wrap maps into a defrecord on which I then can define a protocoll. Kind of artificial though.

11:33 chouser: right. wrappers are bad.

11:33 candera: If you don't care about the perf involved with protocols, seems like a multimethod would be a good fit.

11:34 protocol = dispatch on type, which you don't want. mm = dispatch on whatever.

11:34 KirinDave: chouser: Hey, I'm about to toss an article towards the digg/reddit/hnews sphere

11:34 chouser: Did I get anything majorly wrong with http://kirindave.tumblr.com/post/658770511/monkey-patching-gorilla-engineering-protocols-in

11:34 ?

11:34 candera: And as you said, wrappers are bad, especially here, where I'd assume you don't want to lose all the other operations that are valid against the vector.

11:34 chouser: I wonder if multimethod calls could ever get call-site caching like protocols, and how close the performance would be then.

11:35 KirinDave: chouser: I was reading a paper on that, actually

11:35 chouser: KirinDave: I was just reading that.

11:35 your blog, I mean.

11:35 KirinDave: Ah

11:35 chouser: Egregiously wrong?

11:35 chouser: very smoothly written

11:36 KirinDave: Thanks. cemerick and I are putting together a book proposal so I figured it was time to dust off my writing and see if it was still readable.

11:36 LauJensen: chouser: Got a link to some descent explanation of call-site caching and all that goes with it?

11:36 chouser: LauJensen: no, I've got nuthin'

11:36 LauJensen: chouser: then you'll have to hack out something in here, go:

11:36 chouser: I've done the research, so I should write something up.

11:37 KirinDave: LauJensen: http://anyall.org/self%20-%20polymorphic%20inline%20caching%20-%20ecoop91.pdf

11:37 The self paper is popular for that.

11:37 LauJensen: If you're running a mac, get Papers.app. helps you organize+find these things.

11:37 eintr: what's the idiomatic way for a noop-function? I have a list of functions to be applied to a set, but some should be blank... something like apply-if-not-nil

11:37 cemerick: KirinDave: Probably shouldn't spread that around until, we, y'know, know what's going to happen. ;-)

11:37 candera: chouser: obviously didn't mean to imply that you don't know any of that. :)

11:37 chouser: KirinDave: "protocols laid out in advance" might give the impression the protocol has to exist before the classes in question. I don't think that's what you meant, is it?

11:38 KirinDave: chouser: No.

11:38 cemerick: I don't think it matters that much. I did recruit publicly in here, if you recall ;)

11:39 bsteuber: are there still active discount codes for Clojure in Action?

11:39 chouser: candera: I was hoping rhickey would show up and so, "oh right, I'll just check in a change so that protocols can dispatch on metadata"

11:39 eintr: (constantly nil)

11:39 candera: Heh. Wave his magic brain, as it were.

11:40 KirinDave: Speaking of protocols, chouser

11:40 I was wondering if you knew how the implementation worked underneath.

11:40 LauJensen: Are there any (java?) libs out there estimating IQ based on some text that people have written, like a comment? Is it even possible?

11:40 chouser: KirinDave: not deeply, but I have some clues.

11:40 KirinDave: Specifically, how come if you have an object with 2 protocols that both implement a similar signature same name method, they can't coexist.

11:41 I was surprised to learn that.

11:41 So I deftype and project two protocols that both implement (fn mymethod [x] ...)

11:41 I thought that it WASN'T opening the type to include methods, since you could also do it to things like String.

11:41 clojurebot: multimethods is what separates the boys from the men.

11:41 chouser: KirinDave: it's not opening the type, but the protocol functions are real functions and live in a namespace

11:42 KirinDave: chouser: Sure, but if I have a.Proto1 and b.Proto1 and I try to project them onto user.Type1 and they have identical signatures, it collides.

11:42 I'd have thought in that scenario it'd be okay.

11:42 chouser: where a and b are different namespaces? That should be fine.

11:43 KirinDave: I tried it the other day and it complained. Standby

11:45 chouser: https://gist.github.com/f680abfeb365a3f881e6

11:45 chouser: See?

11:46 chouser: ah, fascinating!

11:46 I wonder if that's documented anywhere...

11:47 KirinDave: Reload it

11:47 chouser: but the reason is that defining a method inline in a defrecord or deftype is not the same ...

11:47 right

11:47 KirinDave: It works fine with java.lang.String

11:47 chouser: is not the same as extending it after it exists.

11:47 KirinDave: Let me try

11:48 Huh , you're right.

11:48 chouser: defining it inline makes it an actual java method of the actual java class. This is good for interop, performance, etc. but you can't do it after the class is defined and the methods can collide.

11:48 may collide

11:48 KirinDave: But it's still wired into the protocol system

11:48 chouser: yes

11:48 KirinDave: That's a little confusing

11:50 I don't think that asymmetry is documented. It may be implied, but it's not really specified.

11:50 chouser: when you define a protocol, it creates an interface of the same name.

11:51 KirinDave: I get that part

11:51 chouser: any java class that implements that interface is then wired into the protocol system

11:51 (defprotocol testp (x [this])) (x (proxy [user.testp] [] (x [] :hello)))

11:51 KirinDave: It's just, I thought that (deftype internals ifacea ... ifaceb ...) was isomorphic to (extend-type)

11:52 But it seems like extend-type must be doing something quite different

11:52 cemerick: everything in the deftype/defrecord body is about defining a class

11:52 chouser: method defs inlined in deftype actually implement the interface methods, not really the protocol method.

11:52 cemerick: extend-type is bridging a protocol to a (fixed) class

11:52 KirinDave: That's really interestin.

11:53 I guess that's sort of implied by the visibility of internal members in deftype but not in extend-type

11:53 chouser: but since the protocol function knows how to work with all things that implement the interface, it works properly

11:53 KirinDave: So where do the mappings made by extend-type and extend-protocol live?

11:54 In something related to the protocol functions themselves?

11:54 chouser: KirinDave: defprotocol creates an interface and a var

11:54 user.testp and user/testp

11:55 the var has all the dynamic info

11:56 (-> testp :impls keys) should return all the dynamically extended classes

11:58 KirinDave: Ahhh, that's clever

11:59 I read something about the performance of protocols being much better though

11:59 chouser: better than what?

11:59 KirinDave: Generics

11:59 chouser: Java Generics?

11:59 KirinDave: clojure generic multi-methods.

11:59 chouser: oh. yes, better than multi-methods

12:00 KirinDave: The multiple dispatch stuff

12:00 But it seems like it has a similar map lookup to do.

12:00 chouser: when you call a multimethod it calls your dispatch function every time. Then looks up the result in a cache to get the implemention method, which is then called.

12:00 cache miss is of course worse

12:02 when you call a protocol, there is a one-item cache right at that call site. If the type of the object, it calls the implementation method directly.

12:03 because instance? is fast on JVM, and because processors do branch prediction and speculative execution, this type lookup stuff is very close to free.

12:32 bartj: er, is there a clojure function which converts strings to integers

12:33 I am asking this because Integer.parseInt(String) in Java returns int -> which I do not want to use since the strings are really long

12:33 defn: ,(map int "abcdef")

12:33 clojurebot: (97 98 99 100 101 102)

12:33 pedroteixeira: bartj: could use (read-string "1")

12:34 bartj: defn: I mean the string is already an integer

12:34 pedroteixeira: clojure decides the type of the object?

12:35 pedroteixeira: bartj: yep, just reads the object.

12:35 Chousuke: The BigInteger class probably has a suitable method

12:35 defn: ,(class (read-string "1"))

12:35 clojurebot: java.lang.Integer

12:36 Chousuke: if you use the reader you might get non-integer objects though :P

12:36 defn: Yeah, might be...shall we say...messy...

12:39 Lajla: Chousuke, onko clojure:ssa conintuation:ia?

12:40 pedroteixeira: Chousuke: using the reader, seemed the easiest to achieve this.. but one can use the (.parse (java.text.NumberFormat/getInstance) "1")

12:40 ,(.parse (java.text.NumberFormat/getInstance) "1")

12:40 clojurebot: 1

12:50 cemerick: bartj: (BigInteger. "somestring") is what you're looking for.

12:50 jeez, never thought of using NumberFormat for parsing simple integers :-/

12:53 bartj: continuing the experiment - well, this seems puzzling

12:53 (def numbers '(37107287533902102798797998220837590246510135740250 46376937677490009712648124896970078050417018260538))

12:53 ,(def numbers '(37107287533902102798797998220837590246510135740250 46376937677490009712648124896970078050417018260538))

12:53 clojurebot: DENIED

12:53 bartj: (+ (first numbers) (ffirst numbers))

12:54 throws up a Don't know how to create ISeq from java.math.BigInteger

12:54 but this seems to work:

12:54 , (+ 37107287533902102798797998220837590246510135740250 46376937677490009712648124896970078050417018260538)

12:54 clojurebot: java.lang.ExceptionInInitializerError

12:54 bartj: ,(+ 37107287533902102798797998220837590246510135740250 46376937677490009712648124896970078050417018260538)

12:54 clojurebot: java.lang.ExceptionInInitializerError

12:54 Chousuke: ffirst is short ofr (first (first ..))

12:54 bartj: er, atleast on my sistem

12:54 *system

12:55 Chousuke: you mean "second"

12:55 bartj: oh

12:55 defn: im not quite sure what you're trying to accomplish bartj

12:56 bartj: defn: I have large numbers in a file and am trying to sum them up

12:56 defn: is this project euler?

12:56 bartj: defn: yes

12:57 defn: is it the 1000 digit number?

12:58 cemerick: what's the problem, exactly?

12:58 ,(BigInteger. "37107287533902102798797998220837590246510135740250")

12:58 clojurebot: 37107287533902102798797998220837590246510135740250

13:01 bartj: 13

13:03 defn: I mean problem 13

13:12 cemerick: thanks!

13:13 KirinDave: Hmm

13:14 Is it tacky to submit my own article to hackernews?

13:15 _fogus_: KirinDave: Yes. But not if you ask someone else to do it.

13:16 KirinDave: haha

13:16 Does anyone want to submit my clojure article to them?

13:16 http://kirindave.tumblr.com/post/658770511/monkey-patching-gorilla-engineering-protocols-in

13:16 _fogus_: Which article?

13:16 KirinDave: linked

13:16 _fogus_: on it

13:17 technomancy: KirinDave: only if your HN username matches your domain name =)

13:17 _fogus_: submitted

13:17 Is it tacky for me to tell everyone to go and upvote it? ;-)

13:17 KirinDave: technomancy: Which it does.

13:17 _fogus_: Never

13:18 _fogus_: Everyone wins!

13:18 KirinDave: technomancy: Damn my well-managed web identity!

13:19 So funny how easy it is to get onto the frontpage of hackernews

13:19 _fogus_: Yes. Whihc reminds me, I should work on my latest blog post

13:19 "Erlang, Clojure, Paul Graham, Starups"

13:19 KirinDave: _fogus_: I imagine you're doing a lot of writing lately. Is it making it hard to keep the blog going?

13:20 _fogus_: KirinDave: Actually, we're done. :-) Mostly

13:20 KirinDave: Oh congrats

13:20 _fogus_: Thank you

13:20 KirinDave: The Meap doesn't seem to have everything yet then?

13:20 chouser: there's a pipeline...

13:21 KirinDave: Ah

13:21 _fogus_: No. They have a somewhat different release frequency than we'd like

13:21 chouser: we've got robots trying to cut the pipeline and cap it, but we're not sure it'll work

13:21 wait, that's not right

13:22 candera: Anyone have any ideas on how I can stop typing "(using ..." and "(foreach ..." in C# instead of "using (..." and "foreach (..."? :)

13:22 KirinDave: text macros

13:22 _fogus_: candera: I have similar issues with Python

13:23 candera: Well, supposedly C# 5 is all about metaprogramming...

13:23 KirinDave: burgh

13:23 C# is all about vestigal features

13:23 candera: Yeah, I sort of hope not to be around to learn about it.

13:23 KirinDave: That "no feature left behind" policy microsoft has hurts a language even more than an OS

13:23 candera: One thing Clojure has taught me, though, is that I like it better than Java.

13:24 KirinDave: Clojure over java or C# over java?

13:24 candera: Clojure >> C# > Java

13:24 clojurebot: amespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

13:24 KirinDave: candera: Really?

13:24 candera: Java may not have some features I want, but C#'s design is just a mess.

13:24 And the class libraries, the core ones, are WAY worse than Java's.

13:24 I mean, you want to see a mess?

13:25 The reflection is a complete cluster.

13:25 candera: So, I agree that C# is a big ball of "features". But I've been using them incrementally for ten years, and I'd miss a lot of them (Linq, Closures, properties) if I didn't have them.

13:25 KirinDave: Linq is a great example of a terrible idea.

13:25 candera: Not going to argue the library design, either. But again, I've gotten used to it.

13:26 KirinDave: A consistent collection API would have made way more sense than Linq, but linq predates lambdas

13:26 candera: Linq is not perfect. But it's damn handy a lot of times. I'm talking about the extension methods over IEnumerable<T>, not the language keywords.

13:26 KirinDave: So now we're stuck with linq.

13:26 Sure, but those are also polluted by linq.

13:26 For example, what everyone calls map, they call select

13:26 But it's also sorta different

13:26 candera: Yep. That's suboptimal.

13:26 Still take it over nothing. ;)

13:27 KirinDave: That's a charitable way to put it.

13:27 candera: Well, I'm hanging out on the Clojure channel while I'm supposed to be hacking C#, so you know where my heart is...

13:27 KirinDave: ;0

13:27 same

13:28 candera: Java just feels like C# 1.0 to me. Strictly from a "how annoyed would I be using it" standpoint.

13:29 But that turns out to be awesome from a "use it from Clojure" standpoint. Generics, properties, events, delegates, etc. - all that would be annoying to interop with. Not sure how D. Miller is going to pull all that off in a reasonable way.

13:33 bendlas: hey guys

13:33 found a glitch in c.c.zip-filter.xml

13:34 when parsing with zf/xml-> , zf/text eats newlines and the like

13:34 when they are properly quoted in the original xml

13:35 like &#xd;

13:36 using v1.1

13:38 am i doing something wrong?

13:42 _fogus_: "My conclusion is that Clojure without TDD is just as much a nightmare as Java or Ruby without TDD."

13:43 * _fogus_ reading http://blog.objectmentor.com/articles/2010/06/03/tdd-in-clojure

13:43 LauJensen: _fogus_: ?

13:43 I think you mean "TDD is a nightmare in any language"

13:44 _fogus_: not mine. blame uncle bob.

13:44 KirinDave: Huh

13:44 I am just not a TDD guy

13:44 Maybe I am just AMAZING

13:44 But I sort of test interactively with the repl.

13:45 _fogus_: What's the acronym for someone who tests after the code is written?

13:45 KirinDave: I test during the coding cycle

13:45 I just don't write formalized unit tests

13:45 I do that later

13:45 _fogus_: I guess I do something similar

13:45 KirinDave: I test interactively as I go, that's what repls are good at.

13:46 Usually I understand a function I have just written fairly intimiately because I've called it a few times.

13:46 candera: I have found TDD to be great working in C#.

13:47 Good enough that I would hesitate to give it up until enough experience in Clojure shows me that it's not necessary. Stu Halloway has said that he's largely moved away from test-first towards test-post-facto.

13:47 _fogus_: I like DDD

13:47 (Developer Driven Development)

13:48 bendlas: Hey, I don't want to bother you, but could at least somebody tell me off for not getting xml/zipfilters/...

13:48 see above

13:48 candera: And here I was trying to think of a good "triple D" joke.

13:50 LauJensen: bendlas: you should bug chouser about it, I think he broke it

13:51 KirinDave: Shoot! I forgot to mention that you could extend pre-existing types.

13:51 _fogus_: That can be part 2

13:51 KirinDave: Guess so.

13:51 I should show how you can do a real thing with it

13:52 bendlas: LauJensen: thanks

13:52 KirinDave: Maybe I should rewrite my exchat server using those things.

13:52 TimMc: I'm trying to use Clojure to make a medium-sized web app -- does anyone have recommendations on HTML templating libraries?

13:52 LauJensen: TimMc: Did you catch my last blogpost?

13:52 TimMc: LauJensen: Link?

13:52 LauJensen: http://bestinclass.dk/index.clj/2010/05/refresh-your-cache--best-in-class-has-been-baked.html

13:53 Im working on OpenSourcing the entire project as we speak

13:53 TimMc: thansk

13:55 Hmmm... this web app is very much database-driven.

13:56 LauJensen: TimMc: Not a problem, that just means that you make an update cycle which updates the db and not the html files - i use those as a db

13:56 The way you would use Enlive-templates is exactly the same

13:57 TimMc: Enlive... another good pointer.

13:57 LauJensen: Almost the only pointer, Enlive generated everything you see on bestinclass.dk incl. the atom-feed

13:58 TimMc: A little background -- I'm researching languages, libraries, and frameworks for use in replacing a doddering old internal web app that ships our company's software to customers.

13:59 It is mostly CRUD operations on MySQL, with some emailing.

14:00 We're a Java shop, but some of the higher-ups have background in LISP, so Clojure is possibly viable.

14:00 LauJensen: ok, there's a javalib for emailing which I have wrapped in Clojure, then you have contrib.sql and http://gitorious.org/clojureql for sql interfaces, and then enlive can help you build/scrape whatever html/xml you might want

14:00 TimMc: I'm very new to it, though.

14:01 Cool. I think Enlive was the missing piece. Once I understand exactly what that does, I'll check out your stuff. :-)

14:01 LauJensen: Javalib is javax.mail - available from maven central

14:01 TimMc: If you hang around or follow me on twitter/laujensen you'll get a ping once I upload the opensource code for the entire site, hopefully tonight or early tomorrow

14:02 TimMc: Will do.

14:05 LauJensen: TimMc: http://bestinclass.dk/index.clj/2009/12/dynamic-interactive-webdevelopment.html

14:05 That might also be interesting - It shows a little web and a little sql action, though I don't use Compojure anymore myself, bestinclass.dk is driven entirely by Moustache, but the transistion is easy

14:16 TimMc: (I really need to get comfortable with Emacs, but it has a long learning curve.)

14:16 (Watching your screencast.)

14:17 LauJensen: TimMc: There are altenatives to Emacs (I've also blogged about them), but if you want to be at the top of the class, then yes you need to check out Emacs :)

14:19 bartj: LauJensen: your solution in the above blogpost and Compojure (which I have looked yesterday) seem to "mix" html and Clojure

14:20 I thought web-designers would not want to touch any Clojure

14:20 LauJensen: bartj: Yea, you mean the screencast?

14:20 bartj: no this - http://bestinclass.dk/index.clj/2010/05/refresh-your-cache--best-in-class-has-been-baked.html

14:21 LauJensen: Oh, not the HTML and the code are seperated completely. I have html files which serve as templates, and then template.clj which generates the final pages by mixing some params/transformations with the html

14:26 bartj: LauJensen: from my very limited knowledge of compojure, it seems that the html and clojure is quite interleaved

14:27 LauJensen: bartj: Ok - But good luck trying to find any compojure in the blogpost you just linked :)

14:28 bartj: LauJensen: which I apparently will not because you used Enlive?

14:28 LauJensen: Yes

14:29 I mean, right, you wont

14:30 The backend is still spewing out some html, but still using templates, no html/code mixed

14:30 And thats the Moustache part

14:38 bartj: LauJensen: Can you please post your Repl commands in the screencast somewhere?

14:39 LauJensen: bartj: Its a pretty old blogpost and the code is supremely outdated, so if there's anything specific you need to do lets talk about it instead :)

14:39 (not that I dont want to help, but I doubt its relevant now)

14:44 bartj: I seem to be currently using clojure.contrib.sql and the screen-cast uses clojureeql

14:44 LauJensen: clojureql, yes

14:45 TimMc: Urgh, it's going to take a bit for me to get used to tilde instead of comma for unquote.

14:46 LauJensen: TimMc: The good news is, that the macro-handler is going away in version 1.0 of ClojureQl, it will have an entirely new frontend, so at present I wouldn't start any new projects with it: http://gitorious.org/clojureql/pages/FrontendReworked

14:48 And before you ask about a release date, Im waiting for kotarak to finish his work on aliases, and we're working on getting an overview of how much we need to retrofit the backend - and then we're 1.0 :)

14:49 bartj: is there some comparision of clojureeql and clojure.contrib.sql

14:50 I am not sure if clojure.contrib.sql allows one to open a "global" handle ie. only one sql connection

14:51 LauJensen: Not that I know of. ClojureQL lets you run the same code on MySql, Oracle, Sqlite and PostgreSql - Mongo and Fleet are almost implemented as well

14:51 ClojureQL is also all-lisp, and in Frontend2.0 all statements are Higher Order functions

14:51 bartj: and re-use it as necessary, where as looking at Lau's screencast shows that I can open a single global sql connection and use that for multiple sql statements - is this right Lau?

14:52 TimMc: LauJensen: The screencast is good, but the reuse of names for bindings and MySQL tables and columns is confusing.

14:52 LauJensen: bartj: We're putting in a connection pool, but I dont know how complex it will be. The 'run' function will take either a description of a connection, which it will open and close, or it will take the name of a global persistently open connection

14:52 TimMc: And like I said - thats going away in 1.0 :)

14:53 TimMc: No, I mean in your screencast -- calling your vector of vectors "roster" and then iterating through it to insert the data into `roster`.

14:53 Oh! But in the new frontend, it wouldn't be as confusing. Got it.

14:54 Looking at using keywords?

14:54 LauJensen: Yea, it would be (insert-into :name name :age age) etc

14:54 TimMc: sweet

15:00 bartj: LauJensen: your screen-cast doesn't create a globally persistent connection. Am I right?

15:00 LauJensen: No it does - I call (open-global :mysql (...)) right at the beginning, that opens a connection which is managed by ClojureQL

15:01 TimMc: LauJensen: WHen you saved your webdev.clj file and hit refresh in the browser, the changes were there. I assume that means the server is dynamically running the .clj files? Or is something intelligently updating variables?

15:03 LauJensen: TimMc: In that example, the page is generated on every load, so refreshing updates the clock

15:04 TimMc: Sorry, not that bit -- where you added (ANY "*" 404)

15:04 LauJensen: Ah - I most likely evaluated that expression (all routes) by hitting M-C-x and just forgot to mentioned it :±

15:04 TimMc: Or was that a little white lie, because the browser wasn't going to try getting the favicon again so soon?

15:04 LauJensen: No lies

15:04 TimMc: Heh, OK.

15:06 So, you rebound my-routes to the new value, and the next time the servlet consulted its routing table, it had the new routes?

15:06 bartj: yes - you mean (open-global :mysql connection-info) where connection-info is a map right?

15:07 I also find it surprising that the connection-info map does not contain the driver class-name (com.mysql.jdbc.Driver) as a key

15:07 LauJensen: TimMc: Correct

15:07 bartj: Correct

15:08 bartj: You dont necessarily want to load a driver everytime to define a connection

15:08 bartj: Lau Jensen: how else would it get the class name?

15:09 LauJensen: Not following

15:12 bartj: LauJensen: let me re-phrase - why doesn't the connection-map not have a key which has the name of the driver to load?

15:14 LauJensen: bartj: Because the task of defining a connection isn't directly linked with loading a driver

15:15 TimMc: LauJensen: Is that because there are multiple possible drivers per connection type?

15:15 (So saying "I want to talk to a MySQL instance" wouldn't be sufficient.)

15:16 LauJensen: TimMc: No its more to do with the fact that if I dont have a clear reason to do so I wont force it upon the user. But I suppose you could use different drivers for the same connection, for some odd type of troubleshooting, but I admit Ive never seen it

15:16 bartj: er, how? if the protocol which is in the connection map is "mysql" then, don't I *have-to* know that the driver class-name is "com.mysql.jdbc.Driver"

15:16 LauJensen: And it might be better to bundle the two in (defconnection) or similar, so Im definitely open to it

15:16 TimMc: Perhaps dependency injection for test suites.

15:16 (If you need to snoop the connection, for instance.)

15:16 LauJensen: bartj: Oh like that you mean - I cant guess which driver you're going to use

15:17 I use com.mysql, but you might use net.openjvm.mysql

15:18 TimMc: Yeah, that's what I was referring to.

15:18 bartj: OK, I get what you say....the driver class is not related to the connection because different drivers can be used. Right?

15:19 LauJensen: Yes

15:24 maxhodak: print-dup monkeypatches java classes/

15:24 ?

15:24 it seems to override the toString method

15:25 (. myclass toString) --> whatever serialization i've defined in (defmethod print-dup com.foo.myclassdef [o w] ...)

15:28 kotarak: maxhodak: you have some code with some output showing the problem in a paste?

15:30 tomoj: (print-dup (Foo.) *out*) -> "foo\"

15:30 (.toString (Foo.)) -> ".......Foo@1f95fc4"

15:31 maxhodak: kotarak: http://gist.github.com/424341

15:31 chouser: prn doesn't use print-dup by default

15:31 it uses print-method unless *print-dup* is true

15:31 maxhodak: hmm

15:32 tomoj: that shouldn't matter, should it?

15:32 the thing being prn'd is a string

15:34 maxhodak: (prn *print-dup*) --> false

15:34 pedroteixeira: any way to bind a private var in another namespace? was thinking something like (let [#'foo/bar 1]) )

15:35 maxhodak: (prn (. (ObjectId.) toString))) --> "(com.mongodb.ObjectId. \"4c08030520559bdc153828d5\")"

15:35 ???

15:35 makes no sense

15:35 bartj: LauJensen: what were the pain points that you were trying to solve with ClojureQL?

15:35 tomoj: maxhodak: yeah, no sense at all

15:36 maxhodak: it's not a prn using print-dup or print-method issue

15:36 it's a toString method issue

15:36 because prn is just getting a string anyway

15:37 LauJensen: bartj: Actually it started with me not wanting to write SQL, but rather stay completely in the lisp syntax. On larger projects its a pain to troubleshoot and quality maintain SQL. Then kotarak brought in the multimethod approach to the backend, which made it very easy to target multiple backends, so that was the groundwork

15:38 chouser: tomoj: is there a print-method of ObjectId or one of its ancestors?

15:38 tomoj: I don't know, but why would it matter?

15:39 maxhodak is telling us that after defining print-dup for ObjectId, the toString method of ObjectId changes

15:39 chouser: sorry, wrong person. also, I'm not thinking clearly.

15:39 tomoj: that can't be true, can it?

15:39 maxhodak: chouser: ObjectId is defined completely in java and doesn't inherit from anything

15:40 chouser: maxhodak: you see the same result without (prn ...), right?

15:41 if ObjectId is a java class, that 'use' isn't right.

15:42 maxhodak: chouser: oh

15:42 crap wait

15:42 bartj: LauJensen: ok thanks

15:42 maxhodak: when i'm (read)'ing the serialized forms back

15:42 it's returning '(com.mongodb.ObjectId. "4c0804fa87f39bdcb900f8a9")

15:42 rather than (com.mongodb.ObjectId. "4c0804fa87f39bdcb900f8a9")

15:42 i.e., it's a sequence where the first is a symbol

15:43 chouser: yes

15:43 maxhodak: rather than actually evaluating the form

15:43 chouser: the reader doesn't evaluate

15:43 normally

15:43 maxhodak: hmm

15:43 chouser: that step comes later.

15:43 bartj: LauJensen: which do you prefer Enlive or Compojure?

15:43 maxhodak: ok, i have to run

15:43 i'll experiment

15:43 chouser: use #=

15:44 maxhodak: yeah

15:44 chouser: that is, try printing #=(com.mongodb.ObjectId. ...) instead

15:44 maxhodak: thanks, works

15:44 LauJensen: bartj: They are for completely different purposes. Enlive is half selections (scraping) and half templating. Compojure is just a small layer over Ring providing some helper functionality for dynamic webdevelopment. Moustache would be comparable to Compojure

15:46 arohner: is there a function in contrib or java for generating a random string of N characters?

15:48 bartj: arohner: Perhaps try a SHA-1 (or any other hash) of the current time-stamp?

15:49 LauJensen: let me rephrase - If you building something like foursquare/twitter which would you use?

15:52 LauJensen: bartj: If it was my show I'd probably try with Moustache/Enlive, but if I was contracted and paid by the hour, I'd use Scala or C++

15:53 TimMc: Moustache is an alternative to Compojure, as a Ring wrapper?

15:54 tomoj: moustache really just seems like a routing library to me

15:54 LauJensen: TimMc: Yes

15:54 tomoj: Moustache is just routing, but Compojure is so stripped in its 0.4 version, that it adds very little more

15:55 fliebel: Is there something weby for clojure that wraps a huge Java framework, like spring for example?

15:55 tomoj: but compojure's routing stuff is out in clutch, right?

15:56 so what the hell is compojure? :)

15:56 LauJensen: tomoj: oh they put that in clutch? :) Then Compojure is ...hmm.. imports?

15:56 tomoj: haha

15:56 hmm, I don't see clutch anymore

15:57 oh, clutch is the couchdb thing. what was the routing library called?

15:57 LauJensen: routjure

15:57 tomoj: clout

15:58 http://github.com/weavejester/clout

15:58 I guess compojure provides a pretty interface over clout

15:59 LauJensen: I think what happened was, they were splitting compojure up into compojure.hiccup compojure.clout etc, and then lein kept stopping them saying "no *jure names", and then they finally broke down and gave up :(

15:59 its sad, but its not the first time...

16:00 tomoj: haha

16:00 riddochc: I thought lein was banning further *jure names? ;)

16:00 Right, sorry, helps to keep reading.

16:00 LauJensen: hehe :)

16:03 riddochc: On the one hand, if Google implemented partial word search functionality, it presents a possible solution to the rather full software project namespace problem. Search for the sort of library you want, and "jure", and there'd be a better chance of finding a clojure library. ;)

16:04 So, how long before lein decides to ban "clj-*" names?

16:05 LauJensen: I think the clj- syntax makes a lot of sense

16:05 so... 2 weeks? :)

16:07 riddochc: As amusing as it is, I'm not sure lein should be enforcing project name policy.

16:09 TimMc: Was there a flag to disable that behavior, like lein ... --ImNotCreativeEnoughToComeUpWithANameThatDoesntHaveJureInIt ?

16:10 tomoj: clj- seems bad to me

16:10 I don't want a bunch of projects clustered right there in tab-completion space

16:10 -clj seems OK though

16:10 LauJensen: tomoj: you got fuzzy completion

16:11 tomoj: not in bash :(

16:12 LauJensen: eshell? :)

16:26 scottj: Is there a form for defining several things at once, like (def a 1 b 2 c 3)?

16:28 Chousuke: no, but it's pretty easy to make

16:28 The-Kenny: It'd be just a simple macro with a call to partition

16:29 kotarak: scottj: (defmacro multi-def [& pairs] `(do ~@(map (fn [[k v]] `(def ~k ~v)) (partition 2 pairs))))

16:30 Chousuke: though generally globals shouldn't be so numerous that you would need such a construct

16:30 that is, if writing defs is too much work for you, probably you have too many :)

16:30 TimMc: heh

17:14 digash: ,(binding [*warn-on-reflection* true] (bit-and 1 (long 2)))

17:14 clojurebot: 0

17:14 digash: uses reflection

17:14 but not here

17:15 (binding [*warn-on-reflection* true] (bit-and 1 (int 2)))

17:15 why is that?

17:22 kotarak: digash: because there is a native method for int, but not for long.

17:22 arohner: digash: bit-and calls the class clojure.lang.Numbers.and(x,y)

17:23 which defines arities for (int,int), and (Object, Object), (and a few others) but not (int, long)

17:23 korre: Integer types is the suported type for clojure.lang.numbers its says

17:24 arohner: right, but Number is a boxed class, while long is a primitive

17:25 digash: ,(binding [*warn-on-reflection* true] (+ (long 1) 1))

17:25 clojurebot: 2

17:25 digash: no reflection

17:26 i think it should it be patched

17:26 arohner: digash: then patch it

17:27 korre: so only need to extend clojure.lang.Numbers i gess

17:37 arohner: lein is reproducibly downloading two different versions of the same library

17:37 I thought that wasn't supposed to happen?

17:38 pedroteixeira: arohner: guess that can happen because you have projects that depend on two different versions

17:44 scottj: Is clojure.contrib.string a 1.2.0 thing? I've seen several libs that require it and I get a file not found error with clojure&contrib 1.1.0. Doesn't contrib 1.2.0 require clojure 1.2.0?

17:47 lancepantz: scottj: yes

17:47 technomancy: arohner: could be a dev-dependency pulling in another version

17:47 lancepantz: it was moved from contrib for 1.2

17:48 scottj: lancepantz: thanks

18:04 dysinger: yo dawg - I heard you like parens

18:04 korre: i do :D

18:17 AWizzArd: Can contrib.io help me to download .JPGs via http?

18:22 dysinger: AWizzArd: use clojure-http-client

18:22 on githubs

18:22 or clojars

18:24 AWizzArd: dysinger: well yes, I have httpunit in my classpath, which can also easily do this, I just thought that maybe a reader+spit or something like that could this job also done

18:25 dysinger: AWizzArd: it's super ultra easy w/ clojure-http-client

18:25 one line of code

18:26 AWizzArd: yes, with htmlunit maybe a few more, plus I have nothing to download ;)

18:26 but.. is there a setting for *default-encoding* which basically is like saying "binary"?

18:33 lpetit: hi

18:33 anybody here using ccw and being currently annoyed by the issue #6 "cannot delete file" problem ?

18:34 r2q2: Hi I'm having issues doing hello world with compojure on google app engine

18:34 right now it can't compile the clj file even though its specified to be there

18:34 or not that it can't but it doesn't compile the clj file

18:35 lpetit: r2q2: answering to me, or talking about a different issue ?

18:35 r2q2: Talking about a different issue

18:35 http://github.com/zitterbewegung/main-site-aconsapart

18:35 If someone could point me to a tutorial to a good version of compojure or a good tutorial to use that would be appreciated.

18:37 korre: do you need a tuturial on compilation?

18:46 ok so are you still here r2q2?

18:46 i gott it working

18:51 r2q2: korre: Yea i'm still here sorry

18:51 korre: I didn't see your message

18:52 korre: so i dont hawe a tuturial butt to get it working you need to add compojureongae.core to namespaces in project.clj

18:53 i also dident get lein deps to work with [com.google.appengine/appengine-api-1.0-sdk "1.3.4"]

18:53 i used the jar from my version of the sdk

18:54 r2q2: ok

18:55 oh i think i know what happened

18:55 my project.clj file doesn't have the correct namespaces.

18:55 * r2q2 hits himself on the forehead

18:55 replaca: KirinDave: you coming to the clojure meetup tonight?

18:56 TimMc: replaca: Is that somewhere in Europe?

18:56 replaca: TimMc: no, SF (& there's one in Seattle tonight too)

18:56 korre: its 1 in the morning in europe so

18:58 lancepantz: how many people usually go to the sf meetup

19:00 KirinDave: replaca: When/where?

19:00 I wasn't invited

19:00 tomoj: hmm, my boss might be in SF tonight

19:01 technomancy: oops; forgot to post about the seajure meeting

19:01 TimMc: korre: Point.

19:01 technomancy: any seattle people: come to http://seajure.technomancy.us tonight!

19:01 or rather: come to the meeting, not just the web site.

19:02 TimMc: I'll have to settle for just the website. :-(

19:04 tomoj: only 3 people on the austin clojure.meetup.com waiting list :/

19:08 powr-toc: Hmmm... just been looking at moustache... is it any better than compojure?

19:08 KirinDave: They're different.

19:09 powr-toc: KirinDave: how so?

19:09 KirinDave: powr-toc: Trivially. :)

19:10 powr-toc: lol...

19:10 tomoj: the main difference I've noticed is routing style

19:10 moustache uses destructuring

19:11 powr-toc: tomoj: yeah... moustache looks like it might be more powerful than compojure... but how about clout?

19:11 tomoj: compojure uses strings

19:11 compojure uses clout

19:13 powr-toc: tomoj: ahh yeah, I'd forgotten that

19:13 tomoj: I'm not sure whether it's more powerful, but destructuring for routing seems awesome to me

19:14 r2q2: could i use moustache instead of compojure?

19:14 powr-toc: I have an app written as a mixture of GWT (with rpc servlets written in clojure) and compojure routes (currently)...

19:14 tomoj: if you like

19:17 powr-toc: I didn't want to use web.xml and war files for deployment... as I want an easy repl into the thing for maintainance, and I have an aversion to web.xml... so I was forced to wire the thing together by hand with jetty

19:18 it's not too bad... but I wish there was a DSL that abstracted across servlets and ring handlers, allowing you to do routing across the whole app

19:19 it's also not entirely dry, as some of the routes are partially repeated for jetty's ServletHolders

19:22 and I also find compojure's wrap! macro a pain in the arse, as it overwrites the handler with the wrapped version, meaning if you re-evaluate the handler you all of a sudden lose your middlewares and have to eval the wrap! call again :-(

19:23 maxhodak: print-dup seems to serialize vectors-of-vectors using clojure.lang.MapEntry/create

19:23 clojure.lang.MapEntry/create doesn't seem to exist?

19:25 korre: no i dont se a static method there in 1.1

19:26 tomoj: ,(binding [*print-dup* true] (println [[:foo :bar]]))

19:26 clojurebot: [[:foo :bar]]

19:26 tomoj: ,(binding [*print-dup* true] (println (seq {:foo :bar})))

19:26 clojurebot: (#=(clojure.lang.MapEntry/create [:foo :bar]))

19:28 tomoj: so the problem is that maps' seqs don't print-dup readably

19:32 maxhodak: hmm

19:32 tomoj: what's the solution? use the 1.2 snapshot?

19:32 or is it not there either?

19:32 i guess i could override the print-dup method?

19:33 tomoj: the 1.2 snapshot I'm using has the same problem

19:33 r2q2: Now i think i got swank-clojure working at least

19:33 tomoj: it's possible the only solution is not to print-dup maps' seqs.. :/

19:34 maxhodak: is there's another serialization method?

19:34 i've written a memoize macro that uses memcached rather than process memory

19:34 and i need to reliably serialize and deserialize arbitrary data structures

19:34 tomoj: that will be difficult, I think

19:35 maxhodak: grr

19:35 korre: yea simple maps are easy butt otherwize you need to do something funky

19:35 maxhodak: i can rewrite my application logic to not use seqs of maps

19:35 it works for everything else ive tested on now

19:35 tomoj: structs still seem to be broken :/

19:36 maxhodak: i'm not using structs anywhere

19:36 tomoj: that's good

19:40 maybe you could define a print-dup method for MapEntries?

19:40 and make it print #=(clojure.lang.MapEntry. k v) instead of /create

19:43 it looks like maps and their seqs are Serializable

19:45 KirinDave: Hmm

19:45 http://news.ycombinator.com/item?id=1402755

19:45 I'm having problems stating clearly why an ad-hoc if cascade is worse any more clearly.

19:47 defn: if I have ((\a \b \c)) how do I map across the inner vals

19:48 KirinDave: Do you want to preserve the structure or not?

19:48 defn: yes

19:48 preserve please

19:49 tomoj: arbitrarily deeply nested?

19:49 KirinDave: defn: You'd recurse.

19:50 defn: ewwwwww

19:50 * defn makes a face

19:50 KirinDave: defn: Would you prefer an uglier method?

19:50 defn: clearly im approaching this the wrong way

19:50 :)

19:50 KirinDave: I mean, if you have an arbitrary tree of data as lists, you recurse or iterate.

19:51 defn: If you hate recursion, you may be in the wrong channel.

19:52 defn: KirinDave: lol KirinDave -- im just thinking my approach to the problem is wrong because i think there's a way to do this without

19:52 KirinDave: defn: Why?

19:52 tomoj: how would you do that recursion without possibly blowing the stack?

19:53 KirinDave: tomoj: You can't preserve the structure without a stack

19:53 i'm willing to bet I could provide that it is so.

19:53 tomoj: oh, hmm

19:53 defn: then i dont need to preserve the structure

19:53 KirinDave: (map my-fn (flatten my-nested-seq))

19:54 technomancy: defn: or destructure higher up

19:56 defn: yeah tech

19:57 basically i have ((\a \a \r \o \n) ...), and I am going to get the val of each \char which is 1-26, and then add up the value of each name

19:57 KirinDave: Oh

19:57 Is it always depth 1?

19:57 defn: yes

19:57 KirinDave: Then you just map across it.

19:57 defn: if i flatten i lose the separation between names

19:58 KirinDave: You have a fn that give (\a \a \a) returns your sum

19:58 Then say (map my-counter-fun my-collection-of-words)

19:58 That's fixed size.

19:58 I was under the impression you had variable unknown depth

20:00 TimMc: Wait wait wait... Clojure doesn't do tail call optimization?

20:01 WTF.

20:03 replaca: KirinDave: sorry - doing real work :-)

20:04 KirinDave: It's at WeatherBill, 420 Bryant @ 7

20:04 KirinDave: Ah

20:04 7?

20:04 fuuu

20:04 replaca: ish

20:04 KirinDave: TimMc: When the jvm does it, so will clojure.

20:04 TimMc: In the mean time you can use the recur trampoline for self tail recursion.

20:06 TimMc: Hrm... I suppose that is the price to pay for targeting JVM.

20:07 tomoj: a price I'm very willing to pay :)

20:07 KirinDave: TimMc: It is a price.

20:08 replaca: KirinDave: was that "fuuu" a yes or a no :-)

20:08 ?

20:08 KirinDave: Too late

20:08 can't go

20:09 replaca: KirinDave: ah, bummer

20:09 has to be later so folks from outside the city can come

20:10 KirinDave: I can do it that late if I have warning

20:10 but not off the cuff

20:15 replaca: it's organized through a meetup group: http://www.meetup.com/The-Bay-Area-Clojure-User-Group/

20:15 ceptorial: hi all. i'm just starting to play around in clojure and just tried to do a simple function, but it looks quite ugly/hard to read.. wondering if someone can suggest how to make it more readable http://gist.github.com/424699

20:15 replaca: meeting are once a month, alternating between SF and Mt. View

20:16 defn: i just started a meetup group for Madison, WI -- lonely clojurist seeks friendship, sexps

20:19 tomoj: ceptorial: (-> row (rename-keys {:user_id :id}) (select-keys [:id :login :created]) (assoc :type "user"))

20:19 then you can break those into multiple lines so it's readable

20:20 ,(doc ->)

20:20 clojurebot: "([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

20:23 ceptorial: tomoj: very fascinating. the doc language is talking about the list in the way that code is data, right... so in (rename-keys row {:user_id :id}) row is the second "item" of the "list"

20:24 tomoj: right

20:24 ceptorial: so this mostly works because of some convention that says that seq functions should generally take the seq as the first param?

20:24 is there a better way to say that / is that written somewhere

20:24 tomoj: basically, yeah

20:24 ceptorial: *first argument

20:24 tomoj: except, some seq functions don't

20:24 e.g. map, filter, etc

20:25 so there is also ->>

20:25 ceptorial: is there an easy way to interleave them

20:25 defn: (interleave ...)

20:25 ceptorial: if i had a filter in the middle of those other calls

20:25 tomoj: not really

20:25 I wrote a macro for that once

20:26 https://gist.github.com/43e7d7d5248e6d639eea

20:26 ceptorial: actually like (into {} row) in the example

20:26 tomoj: but it's pretty ugly

20:26 do you really need the (into {} row), anyway?

20:27 if clojureql is returning something that doesn't already act like a hash-map... it's dumb

20:27 ceptorial: yes if i want to modify the struct to remove keys that were part of the original database record

20:27 which it seems that contrib.sql is enforcing

20:27 even though at this point that i have the data, i don't care anymore, i want to do other things with it as pure data

20:27 tomoj: can you do (class row) on the struct that's returned?

20:28 oh, I guess I see what you mean

20:28 ceptorial: clojure.lang.PersistentStructMap

20:29 tomoj: you would need to do something like (-> (into {} row) (rename-keys ...) ...) I guess

20:29 ceptorial: right

20:29 why do you think that the macro is ugly?

20:30 tomoj: for one thing, it requires you to specify -> or ->> every time

20:30 would be better if it would just stick with the last thing you said

20:30 but even if it did that, I'm not sure I'd like it..

20:30 hmm, why not a macro that lets you pick with % ?

20:31 like (<3 row (into {} %) (rename-keys % {..}))

20:31 ceptorial: right

20:31 would be slick

20:31 tomoj: I feel like that's been discussed before

20:36 ceptorial: well, http://gist.github.com/424699 is working quite nicely. as long as i dont have to use filter or map somewhere inside there

20:36 tomoj: if you do, you'd probably have to break it up with let, I guess

20:38 konr: Is there a way to find out how many arguments a function requires?

20:42 tomoj: not really

20:42 at least, not that I know of

20:42 but if it was defn'd, you can inspect the metadata

20:43 ,(:arglists (meta map))

20:43 clojurebot: ([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])

20:43 tomoj: ,(:arglists (meta (fn [x] x)))

20:43 clojurebot: nil

20:44 konr: interesting! thanks!

20:47 tomoj: not as simple as just (map count (:arglists (meta f))) unfortunately...

21:00 ceptorial: tomoj: http://gist.github.com/424699 last two are with a filter

21:00 is that what you meant by lets

21:02 tomoj: something like that

21:02 but don't use -> or ->> unless you actually need them

21:02 ceptorial: right right

21:02 just POC

21:03 tomoj: and let can have multiple bindings

21:03 ceptorial: if i had filter + map, etc.

21:03 oh right, and they can read off of each other as well

21:03 tomoj: so e.g. I would write that last as https://gist.github.com/4409a999e2d35b29dec4

21:04 ceptorial: very cool

21:04 tomoj: the (filter :required_param) is just a dummy example to play with style, I guess?

21:05 ceptorial: yeah

21:05 i guess it doesn't work on a single map, it would need a seq of maps?

21:05 well

21:05 that makes sense

21:05 tomoj: you can filter a map, but not using a keyword as the fn

21:05 ceptorial: right right

21:06 tomoj: I mean, you can do it, but you won't get anything :)

21:07 ,(filter :foo {:foo :bar})

21:07 clojurebot: ()

21:07 ceptorial: how would you filter out pairs that had a specific key or value

21:07 tomoj: ceptorial: http://www.tbray.org/ongoing/When/200x/2009/12/01/Clojure-Theses#c1259757504.65713

21:07 ceptorial: for key you could use dissoc i guess

21:07 tomoj: that is an enlightening comment by right

21:07 er, by rich I mean

21:07 in response to #2 on that list, related to your original question

21:08 MadWombat: Hello

21:08 tomoj: for keys, select-keys works, I think?

21:08 ,(filter #(> (val %) 3) {:foo 1 :bar 2 :baz 4 :bing 5})

21:08 clojurebot: ([:baz 4] [:bing 5])

21:09 tomoj: oh, you mean the opposite of select-keys, hmm

21:10 MadWombat: I am trying to do some dev with GAE and jetty, so far everything works except one annoying little thing, seems like once run-jetty is executed (either forking or not) there is no way to stop it. I can send it .stop, but it doesn't restart the thread, it just suspends it. Any advice?

21:10 s/jetty/ring/

21:10 sexpbot: I am trying to do some dev with GAE and ring, so far everything works except one annoying little thing, seems like once run-ring is executed (either forking or not) there is no way to stop it. I can send it .stop, but it doesn't restart the thread, it just suspends it. Any advice?

21:10 MadWombat: damn

21:11 tomoj: ,(into {} (filter (comp (complement #{:foo :baz}) key) {:foo 3 :bar 4 :baz 5 :bing 6}))

21:11 clojurebot: {:bar 4, :bing 6}

21:12 tomoj: err..

21:12 ,(into {} (remove (comp #{:foo :baz} key) {:foo 3 :bar 4 :baz 5 :bing 6}))

21:12 clojurebot: {:bar 4, :bing 6}

21:12 replaca: turns out the clojure SF meeting started at 6 - my mistake

21:13 ceptorial: this language is crazy

21:13 ,(doc comp)

21:13 clojurebot: "([f] [f g] [f g h] [f1 f2 f3 & fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

21:13 ceptorial: that's crazy

21:14 hiredman: there is nothing crazy about function composition

21:15 it's just crazy hard to do without functions

21:15 ceptorial: pretty neat

21:17 hiredman: have you seen -> and ->> yet?

21:18 ceptorial: yeah tomoj just walked me through it: http://gist.github.com/424699

21:18 very cool stuff

21:18 tomoj: ceptorial: also, try not to do that (-> (->> ) (-> ) ...) stuff :(

21:19 ceptorial: i supposed https://gist.github.com/4409a999e2d35b29dec4 is the best option?

21:19 redalastor: Are we getting close to the release of 1.2 or it's just an impression I have?

21:19 ceptorial: even if i had filter then map, i could do (->> there for that 2nd let and it would still look pretty good...

21:25 konr: Anybody knows how to "uninitialize" QT's QApplication so I can launch it again without restarting the JVM? QApplication/exit does the job but then the canvas becomes blank and unresponsive

21:26 redalastor: konr: Catch the exception and throw it away.

21:27 konr: reinitializing Qt does no harm beside throwing an exception.

22:42 pedroteixeira: it seems that a public macro cannot call a private function, that's it, right?

22:49 tomoj: pedroteixeira: the macro shouldn't expand to something which calls a private function

22:49 the macro itself can call private functions to generate the expansion

22:53 pedroteixeira: tomoj: never thought about that.. was thinking if there were any patterns to handle that.. only wanted to expose the macro :p

22:55 tomoj: if you're using helper functions behind a macro, it's good practice to expose them anyway

22:55 by "behind" I mean "in the expansion of"

22:56 so that other people can use them without being forced through your macro

23:02 pedroteixeira: tomoj: for this case, the function relies on a binding to mark a unit of work.. but ok, users will get an exception if they use it function solely

23:16 progski: Is there a way to get the basis of a struct?

23:21 pedroteixeira: progski: basis? you mean its keys?

23:22 progski: yep

23:22 pedroteixeira: ,(doc keys)

23:22 clojurebot: "([map]); Returns a sequence of the map's keys."

23:23 pedroteixeira: progski: AFAIK, a struct is a map

23:23 progski: right, what I'm looking for is a way to ask for the basis of a struct, so what keys are required by this struct?

23:24 (defstruct foo :name)

23:24 pedroteixeira: (defstruct A :a :b) (keys (struct A))

23:24 progski: how can I find out that to create foo I ned to pass name

23:25 nice, thanks

23:25 pedroteixeira: progski: but you don't need to pass all the args, you can be lazy: (merge (struct A :a 1) {:b 2})

23:25 progski: okay, yea I'm asking for purposes of testing

23:26 I have a macro that creates a struct

23:26 I want to verify it made the right basis

23:26 pedroteixeira: progski: defrecord is more strict, with version 1.2, it seems people will move towards records instead of structs.

23:27 progski: yea, I haven't had time to really follow all the new 1.2 stuff, so for now I'm working with structs, I imagine moving from one to the other shouldn't be too painful?

23:28 pedroteixeira: progski: records implements the map interface also. the only annoying thing I'm seeing that seem it generates a java class, one needs to import all types explicitly (since there is no import *)

23:29 progski: do records have a significant speed increase over stucts?

23:29 because that would be nice

23:29 I'm building millions of instances

23:34 pedroteixeira: progski: supposely, accessing the keys (= fields) of a record are faster than keys of a struct.

23:35 progski: and guess would save up memory space also. but you might want to confirm with experts in the room

23:35 progski: hmm, well I am using 1.2, so I might as well take a look since I'm still early in development

23:36 pedroteixeira: (defrecord A [a b]) (A. 1 2)

23:37 progski: can I hang metadata on A?

23:37 pedroteixeira: progski: yep.. will be all the same, expect for constructing and importing.

23:38 progski: cool, okay, you've convinced me to take a look then

23:38 pedroteixeira: i created a factory macro for make it more dynamic, it might interest you also:

23:38 (defmacro record "Dynamic factory for defrecords." ([name] `(record ~name {}) ) ([name vals-map] `(let [con# (first (.getDeclaredConstructors ~name)) num# (alength (.getParameterTypes con#))] (merge (.newInstance con# (make-array Object num#)) ~vals-map))))

23:39 you can the use (record A {:a 1})

23:40 progski: cool, thanks

Logging service provided by n01se.net