#clojure log - Nov 26 2011

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

0:00 amalloy: lonstein: subvec patch is at http://dev.clojure.org/jira/browse/CLJS-107 - feel free to upvote it if you're excited, although i don't know if anyone on /core pays attention to upvotes

0:04 technomancy: voting is for democracies

0:10 * brehaut voted

0:10 brehaut: for an actual democracy though

0:12 amalloy: technomancy: btw, i haven't gotten an email from jira about creating this issue. i'm starting to wonder if maybe i didn't actually create it

0:13 technomancy: better comment on it just to make sure you didn't imagine it!

0:20 amalloy: too risky. if i didn't get a confirmation of that comment i'd be stuck forever

1:56 accel: is there any efforts to write a mathematica clone (i.e. symbolic mathematics) fully insdie of clojure?

1:56 less incanter (numerical)

1:56 more symbolic

2:28 ischyrus: how does one check if a value is an atom?

2:32 R4p70r: The ActionListener code here: http://clojure.org/jvm_hosted looks a bit verbose. Since there’s only one addActionListener() overload defined to take an ActionListener with one method. Can we simplify this somehow by not writing the interface and method name? Perhaps with some helper code?

3:53 G0SUB: Photos from Clojure/conj 2011 are here - http://www.flickr.com/photos/ghoseb/sets/72157628155919755/

4:46 Raynes: &(type (atom 0))

4:46 lazybot: ⇒ clojure.lang.Atom

4:46 Raynes: &(instance? clojure.lang.Atom (atom 0))

4:46 lazybot: ⇒ true

4:46 Raynes: ischyrus: ^

5:20 alexbaranosky: where can I find a 1.3 compatible library with macrolet in it?

5:37 I've been experimenting with using the let family of macros for scoping, rather than defn- /def ^{:private true} -- anyone have any opinions on this? I think it is a much nicer way to show visually the dependencies between various functions

8:19 MrHus: Hi I have a question regarding agents. I've got an agent that calls itself every one second. To create a loop. However since I've put the function inside a defrecord and made the method "live" a protocol in Actor. It does't work anymore. Here's what I've got: http://pastebin.com/3bW1XAM5

8:36 Bahman: Hi all!

8:37 Does 'nil?' returns TRUE for Java 'null' values?

8:53 ,({:a 1, :b 2, :c 3} (symbol ":c"))

8:54 clojurebot: nil

8:54 Bahman: ,(symbol ":c")

8:54 clojurebot: :c

8:54 Bahman: Would anyone please explain this to me?

8:56 Raynes: Bahman: A symbol is not a keyword.

8:56 &(type :c)

8:56 lazybot: ⇒ clojure.lang.Keyword

8:56 clojurebot: flatten |is| rarely the right answer. What if your "base type" is a list

8:56 Raynes: &(type (symbol ":c"))

8:56 lazybot: ⇒ clojure.lang.Symbol

8:57 Bahman: Raynes: I see. So is it possible to get a value from a hash map using a string?

8:58 Raynes: Sure.

8:58 &({:a 1, :b 2} (keyword "c")

8:58 lazybot: java.lang.RuntimeException: EOF while reading, starting at line 1

8:58 Raynes: &({:a 1, :b 2} (keyword "c"))

8:58 lazybot: ⇒ nil

8:58 Raynes: Duh.

8:58 &({:a 1, :b 2} (keyword "a"))

8:58 lazybot: ⇒ 1

8:58 Raynes: Or, if your string is a string representation of a keyword (like your example)...

8:59 &({:a 1, :b 2} (read-string ":a"))

8:59 lazybot: ⇒ 1

8:59 Bahman: Thank you Raynes.

9:00 Raynes: &(-> ":a" (subs 1) keyword) ; another option for getting a keyword from a keywordy string.

9:00 lazybot: ⇒ :a

10:33 goodieboy: i'm trying to decide on the interface of a dsl i'm playing with. I'm torn between using the hiccup/envlive approach (vectors, keywords) or using normal function calls.

10:34 I like the envlive approach because the syntax can be much shorter: [:or [:< 10] [:= "test"]] compared to (any-of (lt 10) (exactly "test"))

10:36 The normal function approach is simple to implement, but i have to be careful with naming. Anyone have a feeling on which style to use?

10:39 Raynes: I think I'd encourage functions in this case.

10:39 You can always add the vector stuff on top of that later.

10:42 goodieboy: Raynes: Good point, so build a solid, function-based library then something on top, if desired.

10:43 Raynes: That's generally the way to go in most situation.

10:43 situations*

10:43 goodieboy: makes sense

10:56 marcusl: I would like to get started w/ Clojure. Which one should I read: "Programming Clojure" or "Joy of Clojure"?

10:57 _ulises: marcusl: read "joy of" once you're already up and running w/clojure I'd say

10:58 marcusl: What about the other one?

10:58 _ulises: I read that one as a first and it was ok

10:58 ok as in, it is a good first start

10:58 I've only read those two clojure books so I cannot compare to any other book though :)

10:58 marcusl: ok, thank you.

10:59 _ulises: sure

12:07 quick question, I'm trying to bind to a symbol foo with a function so that I can test several implementations of foo with (binding [foo foo-v-1] (run-tests)) however clojure 1.3 is complaining. I have (declare foo) at the top of the file and I'm wondering whether I should replace (declare ...) with (def ^{:dynamic true} ...)?

12:07 alrenatives are of course welcome

12:07 alternatives even

12:12 raek: _ulises: with-redefs

12:12 _ulises: thanks

12:13 am I right to think that dot are not allowed in symbol names?

12:14 well, I mean, compilation fails if I have foo-0.2 so ...

12:29 raek: _ulises: yes, dots are reserved

12:29 _ulises: thanks again

12:34 does lein test work with clojure 1.3?

12:34 kij: _ulises: works fine here

12:35 _ulises: but my usage is not that complicated.

12:35 _ulises: mine is the simplest on earth too :/

12:35 single test, etc.

12:35 I suspect difftest is the culprit

12:35 so I'll rephrase, does difftest work with clojure 1.3? :)

12:36 kij: ;)

12:38 _ulises: hum, it's trying to load contrib stuff (Could not locate clojure/contrib/str_utils2__init.class or clojure/contrib/str_utils2.clj)

13:24 kij: Is there an nailgun-client for vimclojure 2.3, or is 2.2 fine ?

13:24 Raynes: difftest should be fine.

13:24 kij: What version of difftest do you have?

13:25 Version 1.3.5 is the newest and is totally contrib free.

13:29 kij: Raynes: Sorry, my reply was to the "lein test" question.

13:29 Raynes: kij: Right, I actually meant to direct that at _ulises

13:29 _ulises: Raynes: probably have an old version, thanks

13:30 Raynes: _ulises: If you've got it installed as a lein plugin, look at ~/.lein/plugins

13:30 It'll be listed there with the version in the name.

13:30 _ulises: another question while we're at it, can one have different :pre and :post conditions for different arities of a function?

13:32 along the lines of (defn foo ({:pre ...} [p] ...) ({:pre ...} [p1 p2] ...) ... )

13:35 * _ulises just updated difftest and it's all fine

13:50 bobhope: hello clojuristas

13:50 I'm having issues with lein and core.logic

13:50 I added core.logic's clojars repo to my project.clj

13:50 and I ran "lein deps"

13:51 but when I open the repl and do (use 'core.logic), it fails saying it couldn't find it

13:56 duck1123: it's clojure.core.logic

14:36 djh__: I'm having trouble trying to download .JPG files using my clojure code, the images I download don't seem to be readable/corrupted

14:37 I initially started with slurp -> spit

14:37 that downloaded the file (as such) but the files aren't readable by any image application

14:38 any ideas how I can accurately download an image from the web and store it locally?

14:53 tomoj: djh__: https://gist.github.com/f11bb40e7bd951dbd77a looks like this works

14:55 slurp/spit goes through string encoding/decoding which is screwing up the image data

14:55 Raynes: djh__: (io/copy (io/input-stream "http://raynes.me/hfiles/chocolat.png") (io/file "local.png"))

14:55 You wouldn't dream of using slurp and spit for this anyways.

14:55 tomoj: is it needed to close the input-stream? wasn't sure

14:56 djh__: oh man

14:56 thanks to you both

14:56 seriously

14:56 Raynes: Yes, you should close it.

14:56 djh__: i've spent hours searching for this stuff

14:57 Raynes: Psh. I > any search engine.

14:57 tomoj: but with io/file it must close the output-stream on its own?

14:57 Raynes: tomoj: Right.

14:58 djh__: i was under the assumption (with-open) closes the file at the end

14:59 tomoj: yeah, I wasn't sure whether you needed a with-open with copy

15:24 quotemstr: Is it possible to write native-looking OS X programs in Clojure?

15:31 kij: quotemstr: there should be some qt/java bindings. Might be a try worth.

15:32 rcg1: there is http://qt-jambi.org/

15:33 and afaik some guys try to port swt to qt on basis of qt-jambi

15:34 btw. i dunno if the stock swt has native OS X look right away

15:35 so you might even give swt a try http://eclipse.org/swt/

15:36 there's also a short "hello world" written in clojure and swt http://kevinoncode.blogspot.com/2009/01/creating-clojure-gui-application-with.html

15:37 which also has some helpful notes for running it on a mac

15:38 quotemstr: Cool, thanks.

15:51 Hrm. Swing seems to work well enough.

16:54 devn: "If Prolog is the Answer, What is the Question? or What it Takes to Support AI Programming Paradigms" Daniel G. Bobrow, 1985 -- IEEE Transactions on Software Engineering, Vol SE-11, No. 11, November 1985

16:55 dnolen: ^^

16:55 amalloy: what a nice coincidence then, that prolog lets you derive questions from answers

16:55 devn: :D

16:57 amalloy: the paper raises some interesting questions in my mind: "How are the paradigms integrated into the enviroment?"

16:57 dnolen: devn: nice

16:58 devn: "Coordination of environmental tools, such as debuggers and editors, are necessary. For example, to the extent that the editor understands something of the syntax of one paradigm, it must be extended to deal with all paradigms. Finally, one wants to be able to save and restore entities wirtten in new sublanguages, maintaining their user readable format."

16:58 I hadn't given much thought to that particular aspect of using prolog in clojure. He talks about lisp throughout.

17:01 quotemstr: Is (new foo) or (foo.) preferred?

17:01 rads: I've been playing with Noir a bit. thinking in terms of MVC, it seems that Noir "views" serve as both a view and a controller. does anyone else think this is wrong? perhaps they should be called "actions", and if you want to split them up, you can make separate view and controller namespaces?

17:01 devn: quotemstr: I think (foo.), but if you want to be really explicit (new foo)

17:03 Bahman: There is no line number information when my program throws an exception..it is always like

17:03 Backtrace:

17:03 devn: rads: I don't know if I think it's "wrong". I think it passes on a bit of complexity by not separating them by file, but then again you could wind up in the same predicament even with different namespaces

17:03 Bahman: 0: extractor.core$do_decrypt_index.invoke(NO_SOURCE_FILE:1)

17:03 1: extractor.core$_main.doInvoke(NO_SOURCE_FILE:1)

17:03 duck1123: rads: That's kind of the direction I took with my MVC library. Views and actions are two separate things. And then I have filters (for lack of a better name at the time) that convert the request params into calls on the action

17:04 dnolen: devn: one interesting part of miniKanren is that mostly an illusion. You can freely mix Clojure and miniKanren code.

17:04 Bahman: How can I enable verbose exception information?

17:04 dnolen: devn: most of the macros are just sugar around functions

17:04 devn: dnolen: yeah, i viewed this paper in a lot of ways as a confirmation of what core.logic is doing

17:04 but it also raised a couple of questions that I hadn't considered

17:05 rads: devn: it's fine to keep things in the same file (for the small sites), but it seems like calling them views will cause confusion for anyone familiar with MVC's definition of views rather than Noir's

17:06 devn: rads: I can see why that is a little bit of a cognitive annoyance. You can propose it via the issues queue on github and state your case. I think you're mostly right. It isn't a "view" in the traditional or (by folklore) "correct" sense.

17:07 Where logic is kept "out of the view".

17:08 When someone says "the view" there is an ambiguity about what constitutes the logical view. In the frameworks most people have used, they are two separate files which I think aids the distinction between the two.

17:10 rads: if you grow out of the single file setup, which will happen for a site more than a few pages, you're going to have to have controllers and views. but the views in that context are different than the views that Noir sets you up with. I think that's why it could be very confusing

17:10 devn: rads: then again, playing devil's advocate: Is the naming of a thing worth producing extra code organization?

17:11 duck1123: devn: often times you want that extra level of orginization

17:11 rads: feel free to check out my framework and see if it can work for you. https://github.com/duck1123/ciste

17:12 rads: i.e. the progression is: models and views -> models, views, and controllers. the problem is the views on the left and the right are two different things

17:12 duck1123: I'm interested to see if it can work for anyone other than me

17:12 devn: duck1123: That's fair, but where does it end? Do we also create a controller-specific lib namespace by default as well?

17:12 Since that is important for large sites?

17:12 "helpers", etc.

17:13 Do we assume a large site will need utilities.clj and generate that by default as well?

17:13 Etc. etc.

17:13 rads: well, I'm not sure what ibdknox has planned for Noir, but anyone who wants to build a bigger framework on top of it (something that could fill Rails's shoes) would have to distinguish between Noir's views and the traditional MVC views

17:14 devn: rads: that's a great point

17:15 rads: regarding this: duck1123: That's fair, but where does it end? Do we also create a controller-specific lib namespace by default as well?

17:15 perhaps that should be an option in the "lein noir" generator

17:15 devn: rads: but then we get talking about sensible defaults...what is the default for noir?

17:15 rads: right

17:16 duck1123: currently, clojure web dev doesn't have that many patterns, and there are no common rules about namespace layout

17:16 devn: I don't know the "one size fits all" answer, just trying to get some conversation going.

17:17 clojure web dev seems to be growing up and gaining a mini pattern here or there depending on what people like or dislike about a particular framework

17:17 rads: yeah

17:18 devn: which is why at the end of the day I end up feeling like, because clojure gives you this ability to build your own framework, I sort of prefer that, but there is no question in my mind that we need some kind of coherent "we made some good decisions ahead of time for you." web dev setup for new users

17:18 build your own framework with relative ease*

17:19 rads: as heavy as rails is, it does get rid of a lot of the grunt work for you

17:19 I think there's room for something in clojure like that

17:20 just a lot simpler

17:21 alexbaranosky: dangit, I'm playing with the fedex online print service - they estimate my OnLisp printing to cost $55.61

17:21 devn: rads: yeah, simple is hard when it comes to web dev. one of the big problems I think being: "Big or small project? How much organization is actually helpful? Are there modular components not included in the base of the framework so I can drop in replacements?"

17:23 rads: not to mention questions like what your javascript setup will be, framework considerations there, etc. The list goes on and on. Rails provides a pretty heavy base, but still defers to third party authentication systems, pagination, etc.

17:23 duck1123: having a bunch of middleware that you can grab helps, but sometimes you want stuff that just won't work well as middleware

17:23 rads: indeed. these are big questions

17:24 the question is whether Noir is intended to be used as a base to build those kind of frameworks on top of

17:25 and I don't see why it shouldn't. the views thing is just a stumbling block

17:25 devn: That's a question for ibdknox

17:25 rads: yeah, I'm going to raise an issue on github

17:25 duck1123: I think Noir is intended to be just another layer in the onion

17:25 devn: I think it is worth talking about what we want to make our simplest possible unit of web development: Think something like sinatra.

17:26 Noir on the top, ring at the bottom, something like that

17:28 rads: I think it could be both. you can start out with something small, but right now it's also easy to decouple the routes, controllers, views, which is what I'm doing in my own app right now

17:28 the decoupling could just be another layer on top

17:28 devn: rads: I think generators are probably a logical conclusion

17:29 and then some dead simple configuration for the type of generation you'd like to do

17:29 speaking of the clojure web story, Bobby Calderwood did something cool:

17:29 https://github.com/bobby/trail

17:30 https://github.com/bobby/trail/tree/master/src/cljs/example

17:32 rads: clojurescript is really exciting. I'd love to write entire apps in clojure, and even share view templates between the server and the client

17:32 devn: "It's all happening, man."

17:32 rads: a framework that helps you set that up could be clojure's killer app like rails was for ruby, I think

17:33 devn: Things will solidify and we'll end up with some really fantastic examples of apps written entirely in clojure and clojurescript

17:33 rads: yeah I think that's right.

17:34 alexbaranosky: I agree that that would be a really great web-development experience

17:35 devn: i think it's going to be somewhat dependent on whether people choose to use clojurescript with their clojure app, or if they use clojurescript as a drop-in replacement for something like coffeescript in their existing <language-goes-here> app

17:36 making it drop-dead simple to drop some clojurescript into your clojure web app is going to be a big part of the narrative I think

17:37 On that note I think I've exhausted my hypotheticals for the day-- going to go mess around with core.logic a bit.

17:37 Happy clojuring.

17:38 rads: thanks for the discussion!

17:42 duck1123: I think I'm beginning to regret making the switch to Closure Templates for my front-end. Everything is so much easier when it's a quick Hiccup vector

17:43 Although I will admit that the separation of logic it required was good for me.

17:47 ejackson: duck1123: have you tried enlive ?

17:47 or you doing this in cljs ?

17:48 duck1123: ejackson: I've looked at enlive. The main goal I had was to be able to define a template once, and be able to reference it for both server-side and javascript use

17:48 Not that I've gotten around to much JS coding yet

17:48 quotemstr: Is it possible to generate a proxy with named functions instead of inline functions providing the method implementations?

17:49 That is, instead of (proxy [Foo] [] (bar [x] (do-bar x))), (proxy [Foo] [] do-bar)

17:57 amalloy: quotemstr: i think you can do it with ##(doc update-proxy)

17:57 lazybot: ⇒ "([proxy mappings]); Takes a proxy instance and a map of strings (which must correspond to methods of the proxy superclass/superinterfaces) to fns (which must take arguments matching the corresponding method, plus an additional (explicit) first arg corresponding to... https://gist.github.com/1396437

18:00 quotemstr: Ah, cool.

18:00 amalloy: ,(let [impl (fn [this] 10), p (proxy [java.util.List] [])] (update-proxy p {"size" impl}) (.size p))

18:00 clojurebot: 10

18:00 quotemstr: Also, with other Lisps, it's common to use Lisp code _as_ the configuration file syntax. Is anything wrong with this practice in Clojure programs?

18:00 amalloy: no

18:00 alexbaranosky: quotemstr, in fact it is awesome

18:01 quotemstr: Great. :-)

18:01 amalloy: sometimes situations can arise in which it's better to use a .properties file and let java do the very-simple parsing, but most configs are .clj files

18:01 * quotemstr is writing his first real standalone Clojure program, an IMAP biff.

18:07 rads: if anyone was following the conversation we had about Noir's views earlier, I created an issue on GitHub for it: https://github.com/ibdknox/noir/issues/49

18:37 dnolen: hmm is not possible to get the last element of a sorted-set in constant time?

18:38 amalloy: dnolen: ##(doc rsubseq)

18:38 lazybot: ⇒ "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a reverse seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true"

18:39 amalloy: (though as with anything in a sorted-set/map, that's logN time)

18:40 dnolen: amalloy: yes, yes :)

18:42 devn: is there a generic way to destructure keys: (def foo {:a 1 :b 2 :c 3}) (with-destructured-foo (do-something a b c))

18:42 dnolen: amalloy: thx, that's what I was looking for

18:43 devn: Specifically I'm reading in a config file that has keys which are credentials that are passed to a function which creates a full map of credentials

18:43 amalloy: dnolen: yeah, subseq and rsubseq are surprisingly little-known

18:43 given how dang awesome they are

18:44 dnolen: amalloy: yes, I actually only need rseq, but this is good to know.

18:44 devn: so I end up with (let [{:keys [a b c]} creds] (do-something a b c))

18:44 the repetition is mildly annoying

18:44 amalloy: oh yeah, rseq. silly me

18:54 hansengel: Hi, I'm trying to solve problem #14 of Project Euler with Clojure but am

18:54 having some performance issues.. my code: http://pastie.org/2926143

18:55 I found a Java class which does the same thing in 6.1 secs (mine has been

18:55 running for 30 minutes): http://rianjs.net/2011/05/java-solution-to-project-euler-problem-14

18:55 is there something obvious I'm missing here? I've added every optimization I

18:55 know of as a Clojure noob.. but my script is very very slow

18:57 or is there a easier / faster way to solve this with Clojure?

18:58 amalloy: hansengel: can you configure your irc client not to split your long message up into so many dang messages?

18:59 devn: amalloy: be nice

19:00 amalloy: also, lines 28&30 are the most obvious egregious-performance issues

19:00 hansengel: amalloy: sorry, new to ERC as well :)

19:00 devn: i figured it was probably a screen width issue

19:00 amalloy: yeah, it's always erc that does that

19:00 craziest default setting ever

19:00 anyway, seqs don't have random access - you're walking across the whole chain every time you call nth

19:00 devn: yeah that is a weird default

19:01 tolstoy: insta-flood?

19:01 devn: anyone here use twitter-api much?

19:02 amalloy: yeah, that's another good one. if you accidentally try to send (say) ten thousand messages, erc's default behavior is: "Oh, I'm sure he meant to send all those. But if I send them all at once, flood-protection will silence him. So i'll send one per second."

19:03 hansengel: amalloy: ah right, I remember learning this - so iterate is not the way to go? how would I substitute vectors in?

19:03 amalloy: iterate is fine, vectors are crazy

19:03 but nth is wrong

19:03 just loop over the seq calling first/rest

19:05 R4p70r: hansengel, (if (= 1 (first chain)), (recur (rest chain))

19:05 dnolen: hansengel: that memoize looks suspicious as well

19:06 amalloy: memoize is probably a win here

19:06 hansengel: dnolen: my attempt at a performance improvement, but I guess I was fixing the wrong problem

19:06 dnolen: hansengel: that's lot of overhead for a cheap calculation

19:06 amalloy: how? there's just prim arithmetic there

19:07 amalloy: dnolen: it's recursively calling itself a lot of times, though

19:07 R4p70r: amalloy, applay-chain does?

19:07 amalloy: (and if he's not on 1.3 the arithmetic isn't primitive)

19:07 dnolen: amalloy: apply-chain is not itself recursive.

19:08 hansengel: wow, running again with first / rest now.. so much faster

19:08 amalloy: fine, but iterate does it

19:08 hansengel: probably about 500000 times faster :P

19:09 hansengel: I think I should drop this `for ( int i = 0; i < length; i++ ) foo[i]` mindset in clojure :)

19:11 amalloy: dnolen: it looks like you're right, actually. i think i discovered that myself when i did this problem ages ago and mis-remembered the result

19:14 hansengel: i'd rather write it without a loop at all, then you can't be tempted to do something silly

19:14 R4p70r: hansengel, You could also use something like (count (take-while ...

19:15 amalloy: eg, https://gist.github.com/1396561

19:21 hansengel: amalloy: great! I was wondering if I could use take-while, but I couldn't think of how to track a count for some reason..

19:21 I'll try that implementation - my loop (without nth) is running just as slow by ~350,000

19:29 pandeiro: is there a simpler way to add a key/value to every map in a vector than using (vec (for [v vect] (assoc v :thekey "val"))) ?

19:30 hansengel: wow, even faster, this seems like constant time

19:30 I like the `(complement #{1})` trick as well! thanks very much amalloy, dnolen, R4p70r :)

19:33 amalloy: pandeiro: if you're treating it like a seq, you probably don't need it to be a vector anyway

19:35 pandeiro: amalloy: it's cljs and i'm doing datatype conversion from vectors to JS arrays, so i need it to be... just checking there's no shortcut syntax somewhere i don't know yet

19:35 nybbles: hey could someone please tell me how to install clojure.tools.trace?

19:35 like what line should i put in my project.clj so that leiningen will fetch it

19:35 amalloy: probably org.clojure/tools.trace

19:36 nybbles: hmmm

19:36 awesome thanks

19:36 R4p70r: pandeiro, your code won't evaluate to a vector as amalloy said

19:36 nybbles: i also just clued in that the pom.xml has this info :)

19:36 amalloy: R4p70r: yes it will

19:36 R4p70r: pandeiro, wait you have vec in there sorry

19:37 amalloy: but he doesn't need the input to be a vector, since he's calling map on it

19:44 dnolen: after a week of Scheme, it's fun to be writing Clojure again

19:44 tolstoy: Man oh man. Trying to find out when to use a threaded server vs a trendy node.js-style async server (use cases for each) is difficult.

19:44 So many claims!

19:45 R4p70r: dnolen, Scheme was no fun?

19:45 dnolen: R4p70r: Scheme is plenty fun, but I really miss function polymorphism there.

19:46 also the lack of ready-to-use fast data structures

19:46 that said, I do love me some syntax-rules

19:54 nybbles: could anyone please point me to a library or function to do string template substitution?

19:55 like the equivalent of python "%s blah blah blah %d" % ("foo", 1)

19:55 tolstoy: (format "%s blah blah %d" "foo" 1)

19:55 nybbles: ah ok cool thanks :)

19:56 tolstoy: I was thinking you wanted something like "blah blah #{some-var} blah".

20:01 quotemstr: Is there a way to get Emacs to properly indent proxy functions?

20:05 amalloy: quotemstr: if you have a version of clojure-mode that's not a hundred years old it should work fine

20:06 quotemstr: out of curiosity what class is it that you're proxying?

20:14 quotemstr: amalloy: MessageCountChangeListener from JavaMail.

20:16 amalloy: quotemstr: http://javamail.kenai.com/nonav/javadocs/javax/mail/event/MessageCountListener.html? that's an interface, so you can (and generally should) use reify instead of proxy

20:19 quotemstr: amalloy: Ah, okay.

20:21 amalloy: proxy is a bit of a black sheep - it provides one feature you can't get from reify (extending concrete classes), but it's ugly and (comparatively) slow, and its older syntax doesn't match with the newer interface-extension methods

20:30 quotemstr: Is there a more idiomatic way of writing (every? #((% arg1 arg2)) seq) ?

20:35 tomoj: seq is a seq of 2-arg functions that return 0-arg functions?

20:36 or do you mean (every? #(% arg1 arg2) seq)?

20:36 quotemstr: Err, yes, I meant that.

20:38 tomoj: oh. well, I can't think of anything better :)

20:39 are arg1/arg2 let bindings or fn params or something else?

20:40 quotemstr: Also, I can't seem to find any obvious way of writing (ns foo (:something some.long.java.package.name bar)) (bar.qux ...). Is that possible? Import will work, but it just aliases the symbols to the ones in the package, yes?

20:41 tomoj: The actual code is (defn monitor [url filters] (let [folder (get-folder url)] (while (every? #(% folder) filters) (.idle folder true))))

20:42 amalloy: quotemstr: more concrete example? i can't tell what it is you're trying to do in your ns

20:43 quotemstr: amalloy: I'd like to use a bunch of types from javax.mail.search, but I don't want to type "javax.mail.search" to fully qualify these types, and I don't want to list all the types I'll use in the import declaration.

20:43 I was hoping to somehow alias "javax.mail.search" to a shorter string.

20:43 amalloy: you're out of luck there

20:43 i tried to tack on a request for that feature to the pending "make ns forms better" ticket, but it was declined in the interests of keeping the patch small

20:45 quotemstr: At least I'm not the only one.

20:45 amalloy: yes, it's a bit silly that require can do this but import can't

21:16 quotemstr: Why does (println foo) seem to flush *out* while (pprint foo) does not?

21:16 (If I add an explicit (.flush *out*) after the pprint, everything works as I'd expect.)

21:17 amalloy: quotemstr: PrintStreams have an implicit flush after a println, iirc; pprint just writes a bunch of characters, the last one of which is a \newline

21:17 $javadoc java.io.PrintStream println

21:17 lazybot: http://download.oracle.com/javase/6/docs/api/java/io/PrintStream.html#println()

21:18 amalloy: hmmmm. the doc claims it flushes when a \n is written, but i dunno how much i'd rely on it

21:19 quotemstr: amalloy: Right; I thought it worked like stdio streams in that respect.

21:22 Ah, it's not that at all. println just calls prn, which has an explicit flush gated on *flush-on-newline*.

21:22 (Shouldn't it be newline itself that issues this flush?)

21:35 Does count run in constant time for sequences that have a precomputed length?

21:40 tomoj: you mean like, if you (def nums (range 1e6)) and (count nums) twice, does the second count call run in constant time?

21:41 counted? returns true for seqables for which count will always run in constant time

21:41 for the former, looks like the answer is no, at least for lazy seqs

21:42 is there a name for the actual domain of count?

21:42 quotemstr: Ah, I see. Thanks!

21:45 tomoj: if two threads try to count a lazy seq at the same time, how do they share the work?

21:46 amalloy: tomoj: by both doing all the work independently

21:47 there's nothing to parallelize - you have to realize elements one at a time because they're recursively defined

21:47 if you want, you can write a lazy-seq that also implements Counted

21:48 tomoj: hmm

21:48 amalloy: &(count (let [data (map prn (range 10))] (reify clojure.lang.Counted (count [this] 10), clojure.lang.ISeq (seq [this] (seq data))))) ;; counts with no printing

21:48 lazybot: ⇒ 10

21:48 tomoj: say I do (def nums (range 1e6)), and start counting

21:49 aren't all the objects reachable from nums getting cached nexts updating as I count?

21:49 amalloy: yes, but nobody's caching their counts

21:49 tomoj: right, I mean the work of realizing the lazy seq

21:49 amalloy: sure

21:50 tomoj: e.g. if there's a side-effect in the lazy seq fn, does it happen for each element realized in both threads?

21:50 I mean, does it happen in both threads for every element

21:50 guess I can just test this

21:50 :)

21:53 amalloy: it does not

21:53 tomoj: so one thread blocks realizing the next element, other threads just sit and wait until it gets realized?

21:55 amalloy: yes

22:16 zakwilson: I want to parse XML from a String. It doesn't appear that clojure.xml wants to do that. I'm guessing I should make an InputStream from my String somehow, but the javadoc for InputStream doesn't directly say how to do so. Suggestions?

22:19 quotemstr: Would you use an agent for a producer-consumer queue?

22:19 amalloy: $javadoc java.io.StringReader

22:19 lazybot: http://download.oracle.com/javase/6/docs/api/java/io/StringReader.html

22:21 amalloy: quotemstr: no, i'd use a java.util.concurrent.LinkedBlockingQueue probably

22:22 quotemstr: amalloy: Ah. Not Clojure primitives then?

22:23 amalloy: not really. you could do it with a ref on top of a persistent queue, but there's no real point in reinventing the plumbing. and an agent has all the wrong plumbing - it's designed for serializing accesses one thread at a time

22:24 quotemstr: amalloy: So an agent is a queue with many writers and one reader, yes?

22:25 amalloy: uhhhh

22:25 i guess that's what it is, but calling them readers and writers is confusing, because anyone who wants to can read the current state

22:25 technomancy: an agent is also a reference type, so it really is designed to be used to model a single stable identity with values that change over time.

22:26 the fact that it happens to be the easiest way to use Clojure's built-in thread pools is coincidental

22:26 quotemstr: Well, my problem is this: I have a bunch of threads producing incremental, independent updates to a global state. The UI needs to re-render this state after each update.

22:27 zakwilson: &(isa? java.io.StringReader java.io.InputStream)

22:27 lazybot: ⇒ false

22:27 quotemstr: So I thought, "Okay, I'll have each thread put its updates on a queue, and I'll have the UI thread retrieve elements from the queue, perform the corresponding update, rerender, and repeat."

22:28 It _sounds_ like an agent will do what I want here.

22:28 technomancy: yeah, that sounds like a good fit

22:28 if you want all the actual updates to the state to happen on a single thread

22:29 you could use a watcher on the agent to perform the UI update, I think

22:29 quotemstr: Another option would be to put the entire state behind a ref and update the state in a transaction, signaling the UI thread to rerender after each update.

22:33 alexbaranosky: curious: what is the reason behind using (if (seq coll) x y) over (id (empty? coll) y x) ?

22:33 id should be if...

22:34 is it because checking for emptyness doesn't work so well for lazy seqs?

22:34 technomancy: alexbaranosky: I'd guess it's because people like to put the "usual" case first in ifs.

22:35 alexbaranosky: I like to put the shortest case first

22:35 quotemstr: Hrm: why do agents have validation functions? Can't the update functions do their own validation?

22:36 technomancy: quotemstr: anyone can send to an agent, but maybe the one who created it wants to be in charge of what's valid.

22:36 quotemstr: technomancy: My first instinct would be to mediate access to the agent in the first place then.

22:37 (defn my-send-off ...)

22:37 technomancy: quotemstr: as well as derefing though?

22:38 quotemstr: Sure. The idea is to expose a higher-level facility that would just happen to be implemented, behind the scenes, with an agent.

22:39 technomancy: might make sense in your case, but in general the fact that every reference type supports a uniform validators interface is pretty handy

22:41 quotemstr: Fair enough.

23:07 moogatronic: I wrote a function to check for balanced brackets, I'm new'ish to functional programming and clojure -- anyone care to critique?

23:07 https://gist.github.com/1396939

23:08 basically looking to see if i violated any obvious "don't do that" sort of stuff... since I seem prone to that. =)

23:10 amalloy: moogatronic: seems kinda pointless to shove a \] onto the stack given that you're never going to remove it

23:11 moogatronic: yeah, but i don't know how to fail fast at that point.

23:11 amalloy: moogatronic: ##(doc reductions)

23:11 lazybot: ⇒ "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

23:11 moogatronic: because if i had []]

23:12 amalloy: will read more, thanks!

23:12 amalloy: (not-any? #{:fail} (reductions (fn [v ch] ... (if bad? :fail (keep-going)))))

23:12 moogatronic: it's a little messy because i want to allow any other characters in the string as well as the '[' and ']'.

23:13 amalloy: so?

23:14 moogatronic: heh, i have no answer to the "so?" question. =) But I will investigate reductions. =)

23:15 ibdknox: Why Noir doesn't have controllers (warning, it's long): http://groups.google.com/group/clj-noir/browse_thread/thread/1718a9b1312156d3

23:27 quotemstr: Is there anything wrong with iterating like this? (loop [[a b & r] foo] (pprint (format "%s-%s" a b)) (when (seq r) (recur r)))

23:30 amalloy: quotemstr: looks like a doseq over a partition

23:30 (doseq [[a b] (partition 2 foo)] (pprint ...))

23:31 quotemstr: Aha!

23:31 amalloy: also, wait, why are you calling pprint on that format?

23:32 seems like you just want printf

23:33 quotemstr: Thanks.

23:33 Though actually, I figured out that I can do what I want with just (apply assoc (my-record. defaults...) arglist)

23:53 cgray`: is there a typehint that you can use to indicate an array?

23:55 I'm using ^java.util.Arrays, but I have a feeling it's not right

Logging service provided by n01se.net