#clojure log - Aug 28 2011

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

0:19 semperos: still trying to get my read function to work with clojure.main/repl; when I add a "\n\r" newline to the end of my LineNumberingPushbackReader, I only have to press enter once to get the results at the REPL, but I still don't understand why I have to press enter an additional time at all

0:20 amalloy: semperos: \n\r? nobody uses that. unless you mean \r\n, i suspect that \n<anything> would work as well as \n\r

0:26 semperos: yeah, I keep mixing the order up

0:27 it just feels like I'm so close, and based on a bit of informal debugging, the default read function gets called (the LispReader code), but then it just hangs before printing the value, as if it's waiting for more input

0:37 klutometis: dgreensp: That's a perfect example of something ungoogleable, I think.

0:37 I take that back, actually: http://www.google.com/codesearch#search/&amp;q=defmacro-%5CW&type=cs

0:37 But nothing is Clojure-specific.

0:38 amalloy: clojuredocs.org

0:38 klutometis: I take that back, too: http://www.google.com/codesearch#F-ttn8kjUJ4/modes/clojure/clojure-contrib/src/clojure/contrib/def.clj&ct=rc&cd=26&q=defmacro-%5CW&sq=

0:38 amalloy: Thanks.

0:41 amalloy: &(doc get-method)

0:41 lazybot: ⇒ "([multifn dispatch-val]); Given a multimethod and a dispatch value, returns the dispatch fn that would apply to that value, or nil if none apply and no default"

0:42 amalloy: neat. thanks, clojuredocs

1:27 tufflax: are there any macro problems on 4clojure?

1:27 guess it wouldnt work that well now that i think about it

1:28 the way most problems work

1:41 amalloy: tufflax: no, there aren't. we spent some time trying to imagine how we could write one

1:44 might be interesting to use macrolet

1:45 tufflax: couldnt you just use defmacro? "write a macro m that does this" and then u show like "(= (m bla bla) (something))"

1:45 amalloy: we don't allow any defs

1:45 tufflax: hm

1:46 amalloy: and i like it that way; even if we could allow defs just for macros, i like reminding people that you can do everything with closures, without the need for any defs

1:47 tufflax: but that is not common for macros, is it?

1:47 amalloy: no

2:27 klang: Can clj-http.client (one of the 9 masters there are) do the same as clojure.contrib.http.agent? .. or what is the prefered method for making http requests from clojure?

3:50 BBHoss: Hello all, what's the best place for an existing developer to try out Clojure? I have clj/contrib installed, I just need something to do with it now, something to show me the power.

3:52 khaliG: what kind of power do you have in mind?

3:53 BBHoss: khaliG: dunno, I guess I'm looking for the killer application of Clojure

3:54 scottj: "if william wallace were here..."

3:54 BBHoss: or even just a good tutorial that does a good job of introducing the language

3:54 scottj: BBHoss: what kind of apps are you into?

3:55 khaliG: BBHoss, personally I was drawn to being able to write swing apps in a lisp language coming from a java/lisp background

3:55 BBHoss: scottj: I do rails apps right now, but I don't want to limit myself to that necessarily

3:55 thorwil: BBHoss: have a look at http://java.ociweb.com/mark/clojure/article.html

3:55 khaliG: BBHoss, so a one liner putting a swing gui on the screen impresses me - but you may have different ideas of what's cool

3:56 scottj: BBHoss: so for web stuff noir has a nice page http://webnoir.org/ clojurescript is very cool, pacman is cool http://mjg123.github.com/pacman/pacman.html

3:57 BBHoss: khaliG: JRuby can do that too :), I just see Clojure blowing up in the Ruby community, and I want to understand why

3:57 Just got back from a Ruby conference where I saw a TON of people with Clojure t-shirts on, so something is up :)

3:58 thorwil: that looks quite in depth, I will be sure to read through that tomorrow

4:02 night/morning all

4:07 khaliG: scode, damn that pacman is addictive

4:07 scottj, rather

4:08 scottj: khaliG: it was actually the first time I've ever actually played pacman :) after I eat all the things how do I finish the level?

4:09 khaliG: scottj, same! ive eaten them all - i guess it has somethign to do with that bright line in the middle? dunno

4:10 oh cool you can zoom in

4:11 amalloy: haha in real pacman, once you eat them all you go on to the next level

4:11 khaliG: oh its a tarp! :P

4:12 scottj: so maybe this only has a single level

4:13 source has data for 21 levels

4:13 amalloy: dunno, then

4:15 man, i thought i was young. haven't played pacman? suddenly i'm telling kids to get off my lawn

4:19 scottj: oh I just leveled up when I won without dying at all

4:21 amalloy: bug report, then? "can't go to next level after dying"?

4:24 scottj: yeah

4:25 khaliG: hmm. one thing i dont like about using proxy is that a change to any of the methods requires recreating a new instance of the object :/

4:26 is there a workaround?

4:28 amalloy: &(doc update-proxy)

4:28 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 ... http://gist.github.com/1176420

4:29 amalloy: there are lots of reasons to not like using proxy, but that is not one of them

4:33 khaliG: amalloy, update-proxy is interesting but I don't think it helps in the use case i had in mind - modifying a running app while developing it

4:34 amalloy: i don't understand. you want to change a proxy, so you call update-proxy

4:34 how does that not help?

4:35 khaliG: amalloy, say i don't have easy access to the proxy at the repl

4:35 amalloy: then there's nothing proxy-related you could do to change it

4:35 khaliG: right

4:35 amalloy: instead, have your proxy call a var

4:36 then when you redef the var, the new value will be seen

4:36 khaliG: its tricky because my methods close over some objects

4:38 amalloy: (defn f [] 1) ... (let [p (proxy [java.util.ArrayList] [] (size [] (#'f)))] (.size p))

4:38 or do whatever you want. whatever functionality you want to be able to modify, put somewhere mutable

4:39 if you don't know what you'll want to change, *and* won't have a handle to the proxy instance, you are pretty much SOL as far as i know

4:42 (and IMO would deserve any pain you get)

4:43 khaliG: for example, i use (proxy [javax.swing.table.AbstractTableModel TableDataModel] ..) which implements some of my own methods from TableDataModel, and each time i make a change to those, i have to compile the function and restart the app to see the changes. I would like to make changes to a method while the app is running

4:44 if that's possible, perhaps with something other than proxy

4:44 hiredman: khaliG: or have you proxy methods call a fn and just update the fn

4:45 proxy does actually let you update the fns, but yetch

4:47 khaliG: hiredman, yeah that might be a bit obscuring though :/ i'd have to add new parameters to those fns

4:48 hiredman: khaliG: huh?

4:49 khaliG: for example (getValueAt [row column] (my-get-value-at closed-over-foo row column))

4:49 hiredman: what is obscuring about it?

4:50 amalloy: less obscuring than mutating a dang object's behavior

4:50 hiredman: (value-at thing row column)

5:01 fliebel: amalloy: Ah, finally a Geni employee around :) Fuck timezones...

5:02 amalloy: fliebel: yeah, i keep a pretty late cycle, though not as much as lancepantz does

5:02 or Raynes :P

5:03 anyway, what's up? i see you were looking for us earlier

5:03 fliebel: You remember I was trying to run Jiraph? Protobuf still refuses to work.

5:04 amalloy: i don't think anyone but ninjudd really knows how that stuff happens. Raynes might, i suppose

5:04 fliebel: I talked to Raynes, and he was going to talk to ninjudd, but I havn;t heard anything from them. I wrote down my problem here: https://github.com/flatland/clojure-protobuf/issues/8

5:04 Yea, Raynes said ninjudd is the only one who dares to touch Protobuf.

5:05 amalloy: fliebel: have you considered using lazybot's $mail to at least get asynchronous messages instead of waiting to run into someone?

5:07 fliebel: amalloy: I've considered it... If you restart Lazybot, does it persist?

5:07 amalloy: it's supposed to. i haven't tested it recently

5:07 fliebel: Ok, I'll try.

5:08 amalloy: or you could email him, or github message, or...

5:08 fliebel: telepathy...

5:09 amalloy: yeah. ninjudd's pretty busy, and doesn't spend a lot of time in irc. i imagine he'd appreciate a medium where he could respond whenever it's convenient

5:11 fwiw, he and lancepantz both use macos, so it's not like it doesn't work on macs

5:12 fliebel: amalloy: But you only install protoc once, so if it started to break, they would not notice, I guess.

5:12 amalloy: sure, that's possible. it worked as recently as a couple months ago

5:13 fliebel: I'll send hi a github message, as I trust it more than $mail, and I don't have his email.

5:13 Hm, weird.

5:14 My Mac is prey much a "clean" environment, as I just installed Lion, which might as well be the problem itself.

5:15 amalloy: i wouldn't be astonished, because i'm a mac cynic

5:17 fliebel: amalloy: What do you use?

5:17 amalloy: ubuntu

5:18 i guess my self-contradictory attitude could be summed up as: macos is nice, but that doens't mean i have to like it

5:27 fliebel: amalloy: That thing of you, it was called cognitive dissonance, right? ;)

5:27 amalloy: hah

5:28 yes, i suppose so

5:31 MasseR: What does invalid token exception mean?

5:33 amalloy: &foo:

5:33 lazybot: java.lang.Exception: Invalid token: foo:

5:35 Chousuke: MasseR: you're trying to use an illegal identifier somewhere

5:36 MasseR: Thanks. That's it

5:36 I tried to create a map with a colon as a separator

5:38 Uhm. (use 'clojure.contrib.pprint) should work, right?

5:39 Ah it's moved to clojure.pprint

5:47 amalloy: hmmmmm. usually i hate depending on maps to be ordered, but does anyone know if literal maps supplied in source code retain their order regardless of size? like {:a 1 :b 2}, does that always seq as a before b?

5:48 fliebel: amalloy: Only if it's an array-map

5:48 So, not regardless of size

5:49 But I think if you make an (array-map k v k v) direclty, it should work.

5:52 amalloy: sure. i was just fiddling around with a map-based DSL when i realized i care about order

6:30 Norrit: Hello, where can I find the old contrib.io in the new contrib layout?

6:31 hiredman: clojure.java.io

6:32 Norrit: ah, thx

6:39 Clinteger: they weren't kidding about this being messy..

6:47 scode: How do I idiomatically test whethr an object is a byte array?

6:47 (I.e., equivalent of string? for example.)

7:03 fliebel: scode: Uhm, I don't think arrays are real objects in java, but I guess instance? works.

7:03 Or you can compare the-array/TYPE with the TYPE of a bute array.

7:10 &(class (byte-array 0))

7:10 lazybot: ⇒ [B

7:16 scode: The thing is that [B is not a suitable literable in source code :)

7:16 I.e., (instance? [B) obviously doens't work.

7:16 And I don't want to do (Class/forName "[B").

7:29 fliebel: scode: Why not? Well, of you want, you can define a convenient symbol to it, and use that.

7:30 (def ba (Class/forName "[B"))

7:53 Is there still any movement in async in Clojure? http://dev.clojure.org/display/design/Asynchronous+Events http://groups.google.com/group/ring-clojure/browse_thread/thread/243f452c915356c8/

8:12 scode: fliebel: Mostly just because it feels verbose :)

8:37 Norrit: Hi, can someone spot the error? (.start (Thread. (fn [] (println "Test")))) ==> nil

8:38 Shouldn't it print "Testnil"?

8:39 tomoj: you in some kind of fancy repl?

8:40 Norrit: emacs + swank

8:40 tomoj: e.g. `lein swank`

8:40 yeah, check the terminal you started swank in

8:40 problem is just that the bindings to print to the repl aren't set up outside the repl thread

8:41 Norrit: ok, I expected something like that .. thx

8:41 tomoj: I remember you can hack around that, dunno if there is a proper way

8:44 Norrit: I found the stackoverflow question: http://stackoverflow.com/questions/4532862/understanding-output-in-clojure-using-swank-slime

8:58 bsteuber: tomoj, Norrit: another way is (alter-var-root #'*out* (constantly *out*))

8:59 after that all threads' *out* is like in the one executing the line

8:59 so all threads will print to the swank buffer

9:00 Norrit: bsteuber: thx I will try that out, too

9:01 bsteuber: Norrit: the backside is that if you do a lot of debug prints, the repls becomes quite full and it might even become hard to enter new commands

9:32 ambrosebs: how can I get marginalia to recognize a comment nested in a form?

9:33 seems to only render comments on the top level

10:22 Somelauw: Hi, I am trying to write a local recursive list in clojure. In scheme I would have used let-rec, but clojure doesn't seem to have it, so I am wondering what the best alternative would be.

10:23 Netpilgrim: I’ve written a DFS searching for a path from one vertex to another. (https://gist.github.com/1176716) It kind of works but I can’t figure out how to stop the search once the (first) path is found. I’m probably still thinking too much in imperative terms where I would just call return. Any pointers?

10:26 Somelauw: For example (letrec [exponential2 (lazy-cons 1 (map #(* 2 %) exponential2)] (nth exponential2 5))))

10:26 I want a local recursive list.

10:26 tomoj: Netpilgrim: how does that deal with cycles?

10:27 Netpilgrim: tomoj: Cycles are avoided by the definition of children, which excludes vertices already on the current path.

10:28 Somelauw: I'll have to take time to understand this. Where does letrec come from? It's not in clojure.lang.

10:28 tomoj: Somelauw: ##(take 10 (iterate (partial * 2) 1)) ?

10:28 lazybot: ⇒ (1 2 4 8 16 32 64 128 256 512)

10:28 tomoj: or do I misunderstand?

10:28 Somelauw: Or even (letrec [ones (lay-cons 1 ones)] ones)

10:29 Netpilgrim: Somelauw: Or clojure.core or where the usual stuff comes from.

10:29 tomoj: oh, that was just a silly example?

10:29 Somelauw: Netpilgrim: It works with def.

10:29 Netpilgrim: But I don't want to spoil the global scope.

10:30 tomoj: That works, but I am looking for a more generic approach.

10:31 tomoj: &(nth ((fn ones [] (lazy-seq (cons 1 (ones))))) 10000)

10:31 lazybot: ⇒ 1

10:31 tomoj: :/

10:31 Somelauw: In sicp there is a whole chapter about streams. That is the kind of thing I am looking for.

10:32 Netpilgrim: Somelauw: I hadn't thought about making anything lazy in my search. But I guess if I'm really only interested in the first path found, there should be an easier solution?

10:33 Somelauw: Netpilgrim: That seems like the right approach. Return a lazy list and only ask for the first element.

10:34 Netpilgrim: Somelauw: Thats looks like a clean, general solution in any case. I’ll try to implement it. Lazy sequences are still new to me.

10:35 Somelauw: tomoj: I think that would be the best alternative so far.

10:37 tomoj: Netpilgrim: stick around a bit longer

10:39 Netpilgrim: My first experiment with lazy seqs was to get one of primes. Could someone take a look and see if I'm doing it right? (https://gist.github.com/1176126) There is probably a better way to calculate primes but I'm just asking about the code structure.

10:41 tomoj: one problem is that you probably don't want to def primes to the seq itself

10:41 well, I guess it doesn't really matter in this case

10:42 Netpilgrim: tomoj: Why not?

10:42 tomoj: Or in what cases not?

10:42 tomoj: if you def primes to the seq, you will hold the head

10:42 which means none of the seq can ever be garbage collected

10:42 but you carry the whole seq around anyway to generate it, so..

10:43 Netpilgrim: tomoj: Yeah, I thought about that and came to the same conclusion.

10:43 tomoj: BTW: Is there a way to reference all the elements in a seq before the one being constructed?

10:44 tomoj: Basically what I hold in known-primes?

10:44 tomoj: I think you did that the most elegant way I can think of right now

10:45 wait

10:46 what if you instead wrote a function that takes the seq of known primes and returns the next prime, and combined that with iterate?

10:46 Somelauw: I think I don't really like wrapping a lazy list in a function. It doesn't feel right.

10:46 tomoj: or the function conses the next prime

10:46 Somelauw: lazy-seqs are just functions inside seqs, seems appropriate to me

10:47 but I don't have scheme brainwashing :)

10:47 Netpilgrim: Somelauw: What do you mean? Isn't there always a function to generate the seq?

10:48 Somelauw: Also, I am not sure if the list gets properly memoized in your approach.

10:48 tomoj: the letrec version would notice that you only need one seq, and have that seq's more() return itself?

10:49 Somelauw: I am testing it right now on a lazy fibonacci sequence.

10:49 Bronsa: how can i share a Var between two namespaces?

10:49 Somelauw: And it doesn't seem to memoize properly.

10:50 tomoj: I think if you want it 'properly memoized' you will have to do it yourself

10:51 Somelauw: tomoj: I am going to read a chapter about clojure macros in a minute.

10:52 Netpilgrim: I'm still very fuzzy on the whole subject of lazy seqs. I’ll still have to read that chapter in The Joy of Clojure. Hopefully that will make things clearer.

10:53 Somelauw: Although I am first going to google a bit more, because I can't believe there is no alternative.

10:55 tomoj: Netpilgrim: I think I solved your problem

10:55 check out tree-seq

10:56 can gist you my code if you want

10:56 Netpilgrim: tomoj: I would appreciate it.

10:56 tomoj: let me make sure it works first :)

10:58 https://gist.github.com/b6baf208f18d21c2d88e

10:58 Netpilgrim: tomoj: Looking at the documentation of tree-seq, I don't think it can deal with cycles. But it will be interesting to look at the code.

10:59 tomoj: that's why it took me so long :)

10:59 but I already had an attempt written when I realized the cycle problem, so just kept going

11:02 https://gist.github.com/1d43fb74aaf2d16b0ecf might be less confusing

11:02 dunno if you're used to ->> :)

11:02 oh, except that doesn't work

11:03 Netpilgrim: tomoj: I haven't used --> yet but I know how it works (I think).

11:03 tomoj: fixed

11:05 Netpilgrim: tomoj: Than you very much for the effort. I'll have to leave soon for a few hours but I will go over the code and probably learn a lot.

11:06 tomoj: Netpilgrim: I suppose the first arg to tree-seq should really be (constantly true)

11:06 I think passing my children function there may actually do weird things.. not sure

11:07 or at least (comp seq children)

11:14 Netpilgrim: tomoj: Wow, I really need more time to understand what's going on there. Clojure syntax and functional thinking is both new to me. It's a bit frustrating but also really cool, like the first time I learned how to code, which was awesome. :)

11:15 tomoj: I've got to go now. See you later, and thanks again.

11:55 mudge: i can start a clojure web application with lein run

11:55 and my project says which namespace my -main is in

11:55 but how do i stop or restart my web application?

11:56 justicefries: what are people using as far as web frameworks go

11:57 mudge: compojure

11:57 and some use noir which is build on top of compojure

11:57 justicefries: nice okay

11:57 mudge: *built

11:57 justicefries: i'm making the leap from ruby/rails. :D

11:58 coopernurse: justicefries: yes, noir is good. I put a site up on github if you want to look at an example

11:58 mudge: nice job

11:58 i want to look at an example too

11:58 justicefries: yeah!

11:58 coopernurse: https://github.com/coopernurse/votenoir

11:58 deployed to appengine at: http://votenoir.appspot.com/

11:59 not claiming it's amazing code, but it may give you some ideas

11:59 justicefries: whoa defpartial

11:59 coopernurse: yeah, that's a macro noir provides

11:59 justicefries: nice.

11:59 coopernurse: noir docs here: http://webnoir.org/

12:00 justicefries: the biggest thing I'm trying to wrap my head around is code organization with larger projects. reason I say that with any importance is with an OO language, separation of things out into classes is...just what you do.

12:00 so now I have to consider it differently. ;)

12:01 so with noir I don't actually write any html.

12:01 accurate?

12:03 coopernurse: yep, by default noir encourages you to use hiccup - which is like haml in ruby

12:03 justicefries: ah ha.

12:03 very cool.

12:03 coopernurse: which I personally like - I like having everything in one place

12:03 st3fan: coopernurse: happy with GAE?

12:03 justicefries: yeah

12:03 coopernurse: st3fan: the price is right :-)

12:03 st3fan: you mean free?

12:03 well, for small sites

12:03 coopernurse: st3fan: but it's flaky.. stuff randomly fails

12:04 st3fan: yes, free quota is very generous

12:04 st3fan: well that is the google way .. distribute app over many servers so that it does not matter when things fai

12:04 coopernurse: st3fan: so I like to use it for toy apps.. and most of what you write is portable. the datastore is the most unique layer

12:04 st3fan: l

12:05 yeah very cool

12:05 coopernurse: st3fan: yes, but I'm talking about some of their tools breaking.. for example, on friday you couldn't deploy any index changes. 500 error from their servers using their scripts

12:05 st3fan: aha

12:05 mudge: what advantage does defpartial give over just defining your hiccup code with defn?

12:05 coopernurse: I posted to their google group. no answer from google. but one other person on the group said "yeah, I'm getting those errors too"

12:05 mudge: judging from the source, it just prevents you from having to wrap it in (html ..)

12:06 looks like a pretty thin macro

12:06 mudge: coopernurse: how fun, yay

12:07 and defpage replaces using the compojure GET macro?

12:07 coopernurse: justicefries: regarding code organization, it is different than rails, but it's similar to other microframeworks like express in node.js or flask for python (and probably sinatra)

12:07 mudge: yes, exactly

12:07 jnb16: Quick ClojureScript question is someone wouldn't mind helping. Trying to get a clojure macro to run. I have a src folder with a clj and a cljs dir. Inside each of those dirs is a toplevel dir with the same name and then my code. I am getting java.io.FileNotFoundException: Could not locate recipeapp/rmacros__init.class or recipeapp/rmacros.clj. Do I need to pass something special to cljsc? sorry for the wall of text

12:08 justicefries: ah ha.

12:08 mudge: coopernurse: i see, anything else that noir gives that might be good that you know of?

12:09 jnb16: oh, also..I am using :require-macros in my cljs namespace (I think that is right) for requiring the macro

12:09 coopernurse: mudge: the "flash" message feature seems useful. wrapper functions for cookies. simplified middleware bindings. pre/post request filters (good for auth)

12:10 mudge: compojure is good, but very low level. noir provides many of the things you sort of expect to find in a web framework.

12:10 mudge: coopernurse: i see

12:17 thorwil: coopernurse. mudge: afaics defpartial duplicates hiccup's defhtml. though defpartial might well predate the hiccup solution

12:18 mudge: thorwil: thanks, i didn't realize hiccup had defhtml

12:18 thorwil: just saying, as using defhtml makes more sense regarding code organization

12:19 coopernurse: thorwil: as opposed to defpartial? how so?

12:19 thorwil: coopernurse: because it wraps hiccup's html

12:20 mudge: thorwil: where is defhtml? in hiccup? i can't find it

12:20 thorwil: nevermind, i found it

12:21 coopernurse: thorwil: oh, defhtml makes more sense than using (html ) directly? or makes more sense than using defpartial?

12:22 thorwil: coopernurse: second

12:22 mudge: what's the difference between defhtml and defpartial?

12:22 jnb16: no clojurescript gurus I guess..I'll try again later, but if anyone has an idea, feel free to PM me...thanks!

12:22 coopernurse: jnb16: yeah, sorry, haven't tried clojurescript yet

12:23 thorwil: I'd like to hear more. seems they are equivalent

12:23 jnb16: no worries :D

12:23 thorwil: coopernurse: there is not more to it :)

12:23 coopernurse: heh, ok

12:23 mudge: thorwil: why is defhtml better than defpartial?

12:24 thorwil: because the name defhtml is better?

12:24 thorwil: mudge: code organization. having all the html business in/from hiccup

12:25 mudge: but defpartial is also uses hiccup, how is it better organization?

12:25 coopernurse: mudge: right, that was what I was wondering

12:26 mudge: thorwil: is it just nicer to use all hiccup rather than use somethinge else too?

12:26 upwardindex: well since hiccup is coupled to html generation, it makes more sense to use html generations facilities of hiccup

12:26 mudge: I might use defhtml because I like the name better than defpartial

12:27 upwardindex: noir is decoupled from html generation as you can use enliven with it for example

12:27 mudge: upwardindex: yes

12:27 coopernurse: well, if you include noir as your project dependency, hiccup is included transitively, and you can use hiccup directly if you like

12:27 thorwil: this is such a minor detail, not worth this many words. its just a need that follows from hiccup, where hiccup has a solution, so having it all in one place makes sense

12:27 mudge: thorwil: yea, makes sense

12:28 coopernurse: thorwil: agreed, seems more like a matter of aesthetics than anything else

12:28 mudge: or code organization

12:29 in a way

12:30 coopernurse: it seems lots of ruby folks are finding their way to clojure

12:30 thorwil: seeing how i want to update parts of a page asynchronously, i wonder what it would take to write a function that takes a defhtml and returns a javascript function that acts like a template

12:31 coopernurse: thorwil: when you say "acts like a template" - you want to take the server generated html and do further transformation on the client? like token substitution

12:32 or do you want to just use that html fragment to replace innerHTML of a containing element?

12:32 thorwil: i guess as long as all args are strings and there are no conditionals or loops, all needed is some escaping on what hiccup generates

12:32 coopernurse: the js function would take the same args as the defhtml

12:34 coopernurse: thorwil: I suppose an example use case would help - I'm not sure I get it

12:34 thorwil: example: a comments section. i have a defhtml for a single comment

12:35 the js/client side should be able to add a comment locally, with the same html structure

12:36 so i figure a defhtml->js-template-function would be pretty neat

12:36 coopernurse: I see

12:39 seems like that's what clojuresript would be useful for

12:40 obviously that's a bigger undertaking.. regarding tooling

12:47 scottj: you guys have seen pinot right? it has defpartial

12:48 mudge: scottj: bite me a donut, I hadn't seen it before

12:48 scottj: looking at it now, looks good

12:56 coopernurse: scottj: wow, yeah that looks pretty sweet. chris granger is writing some good stuff

12:59 thorwil: looking forward to the day there is a 1.3 release and an updated appengine-magic, so i might take advantage of clojurescript and things like that :)

12:59 srid: apparently some host tutorials on github, https://github.com/swannodette/enlive-tutorial#readme -- IMO, this is better than blogging them, as readers can 'fork and edit' the content.

12:59 coopernurse: ah, does clojurescript require clojure 1.3?

13:01 jblomo: coopernurse: yes

13:05 coopernurse: jblomo: ah, interesting..

13:06 scottj: I think you can have clojurescript in a 1.2 project fine since the cljs compiler and it's 1.3 is separate

13:13 grios: Hello. Why: (class (def m-symb 'a)) => clojure.lang.Var but (def m-symb 'a) (class m-symb) => clojure.lang.Symbol ?

13:13 jblomo: def returns Vars

13:13 typically you don't notice because you're not using the return value of def

13:16 grios: jblomo: okay thanks

13:18 mudge: is there a defonce for functions?

13:18 grios: I'm having some headache trying to disjoin Java-like's "identifiers" concept from Clojure's "symbols

13:21 because I was reading The Joy of Clojure: << symbol’s qualification is a characteristic of evaluation and not inherent in the symbol at all >>. So Vars live in a namespace, but symbols itself do not?

13:24 mudge: how do i check if a var exists?

13:24 like i want to check if the var 'server' exists or not

13:24 dnolen: ,(doc resolve)

13:24 clojurebot: "([sym] [env sym]); same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"

13:24 dnolen: ,(doc ns-resolve)

13:24 clojurebot: "([ns sym] [ns env sym]); Returns the var or Class to which a symbol will be resolved in the namespace (unless found in the environement), else nil. Note that if the symbol is fully qualified, the var/Class to which it resolves need not be present in the namespace."

13:26 mudge: dnolen, cool, thanks

13:27 * srid mistakenly thought Enlive is only a scraping library; it also does templating.

13:42 cemerick: srid: My favorite one, actually :-)

13:49 manutter: ,(doc pmap)

13:49 clojurebot: "([f coll] [f coll & colls]); Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the time of f dominates the coordination overhead."

13:49 manutter: ##(doc pmap)

13:49 lazybot: ⇒ "([f coll] [f coll & colls]); Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the t... http://gist.github.com/1176980

13:51 manutter: ##(doc ->)

13:51 lazybot: ⇒ "Macro ([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."

13:53 manutter: ##(doc read)

13:53 lazybot: ⇒ "([] [stream] [stream eof-error? eof-value] [stream eof-error? eof-value recursive?]); Reads the next object from stream, which must be an instance of java.io.PushbackReader or some derivee. stream defaults to the current value of *in* ."

13:54 manutter: ##*ns*

13:55 ##(pr-str *ns*)

13:55 lazybot: ⇒ "#<Namespace sandbox16249>"

14:06 mudge: in my compojure app i have: (route/resources "/") but it is not finding my stuff in resources/public

14:08 where should my resources directory be located in my compojure application?

14:11 semperos: fairly sure that, by default, resources should be in the root of your project

14:11 the "resources" folder, that is

14:11 mudge: semperos: yes, i think so too, buy my clojure app isn't finding my stuff in project root/resources/public/

14:12 i have this in my routes: (route/resources "/")

14:12 but things are not found in resources/public/

14:13 semperos: the URL is formatted "/public/foo.css" for example?

14:13 mudge: semperos: yes, ahhh, i think figured it out!

14:14 jblomo: yea, you don't need the /public in the URL

14:14 mudge: semperos: i had my urls like that, public/foo.css, my urls actually need to be just: foo.css and it looks in the public directory for it

14:14 yea

14:14 working now

14:14 semperos: :)

14:14 glad to hear it

14:23 jnb16: any clojure*script* gurus around?

14:25 jblomo: i've used it before, not a guru, though

14:25 jnb16: Any experience with getting clojure macros to work?

14:26 jblomo: well, like 'doto'?

14:26 jnb16: Sorry, I meant like writing clojure macros that then work on cljs files during the compilation step

14:27 writing your own defmacro's

14:28 dnolen: holy moly, red-black tree balance checking with object arrays fast - https://gist.github.com/1177009

14:28 jblomo: sorry, no. i thought they worked just like clojure macros?

14:29 dnolen: nice :) I enjoyed your talk on match

14:29 jnb16: ah, yeah. It seems like you need to put the macros in a separate normal clojure file (.clj)...but now cljsc seems unable to find it boo...Thanks tho!

14:29 dnolen: jblomo: thanks!

14:47 hanDerPeder: why do I get nil here? https://gist.github.com/1177035

14:55 thorwil: hanDerPeder: because (str a) can't result in an Integer or Double

14:55 hanDerPeder: thorwil: I dont understand what you mean

14:55 this works though: https://gist.github.com/1177048

14:56 thorwil: hanDerPeder: java.lang.Integer (str a)

14:56 hanDerPeder: you surely meant "java.lang.Integer a"?

14:57 hanDerPeder: I meant, if 'a' is of class integer then return 'a' as a string

14:58 thorwil: right, i was confused

14:59 Somelauw: tomoj: I think I found what I was looking for.

15:00 Clojure has rec-cons and rec-cat.

15:13 thorwil: hanDerPeder: with cond it seems to work: (defn emit-bash-form [a] (let [c (class a)] (cond (= c java.lang.Integer) "int" :else nil)))

15:13 strange

15:17 Somelauw: although it doesn't seem to work in my ancient version of clojure

15:19 hanDerPeder: yea, especially since it works fine when using multimethods

15:35 raek: hanDerPeder: the java.lang.String form is unevaluated, so you actually check for a symbol

15:35 even though a class and a symbol prints the same, they are not the same

15:36 you need to work around this by having class objects instead of symbol objects in the code. this is possible with a macro: https://gist.github.com/997652

15:38 theignorati: how do I properly deploy a compojure app? there's 9000 blogs and they all do it in a different way

15:41 jblomo: theignorati: i think it depends on your infrastructure.

15:41 theignorati: 1 dedi

15:46 floatboth: hi

15:50 chouser: floatboth: hello.

15:50 semperos: howdy

15:50 floatboth: anyone knows why a macro like (defmacro test [& a] `(fn [d#] (-> d# ~@(map eval a)))) results in a java.lang.ExceptionInInitializerError?

15:51 chouser: floatboth: did you try (pst) ?

15:52 floatboth: chouser: what's this?

15:52 chouser: prints the stack trace

15:52 perhaps I should first ask which version of Clojure you're using.

15:53 floatboth: 1.2.1

15:56 when I make it a function and try, the output seems fine: (clojure.core/fn [d__9393__auto__] (clojure.core/-> d__9393__auto__ #<my fn> #<another fn>)) but I can't eval that

15:57 amalloy: $javadoc java.util.Map

15:57 lazybot: http://download.oracle.com/javase/6/docs/api/java/util/Map.html

15:58 amalloy: floatboth: you're probably trying to embed objects into the code that aren't code objects. in any case using eval in a macro is wrong basically 100% of the time

15:58 bumber: ,(var (def a 'a))

15:59 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

16:00 amalloy: bumber: def already returns the var. (var (anything)) is always invalid code

16:01 floatboth: same w/o eval

16:02 raek: floatboth: you probably want (-> d name-of-my-fn name-of-another-fn), i.e. symbols instead of function objects

16:03 floatboth: also, can you describe what 'test' is supposed to do?

16:04 floatboth: raek: I don't have symbols… I want something like apply-macro from contrib to work, impossible?

16:04 raek: how would you use apply-macro?

16:04 the idea of applying a macro doesn't make sense to me

16:05 floatboth: I just want my macro to make a function which will receive an arg and -> it through functions given to the macro

16:06 raek: you don't need a macro for that

16:06 amalloy: floatboth: this is really hard for you because you should just be using ##(doc comp)

16:06 lazybot: ⇒ "([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."

16:07 floatboth: hmm, nice

16:07 thanks, I'll try it

16:07 amalloy: and no matter how hard you try with a macro, it can *never* work, not even with something like apply-macro

16:08 i mean, you can make a macro expand to a use of comp, or splice in the symbols. but you can't do it with eval, because eval doesn't have access to lexical bindings

16:08 bumber: amalloy: thanks for the clarification :)

16:08 floatboth: yeah, got it. thanks everyone!

16:08 amalloy: (let [the-function (if some-test inc dec)] ((test the-function) 1))

16:09 will fail because the macro can't know what the-function's value is

16:11 floatboth: my brain will fail, no, already failed. I wanted something to compose functions and forgot to find-doc this :D

16:13 hanDerPeder: raek: thank you very much for the clarification

16:15 mudge: does it make sense to deploy clojure apps using git?

16:15 hanDerPeder: raek: can you tell me why it works when using multimethods?

16:15 floatboth: mudge: sometimes it's even the only option (heroku)

16:17 mudge: floatboth: i am trying to use git to deploy my clojure web app, but when I push to the repository on my server I am getting an error because I think pushing to the repository doesn't

16:17 update the working directory of the repository

16:18 raek: hanDerPeder: it is because case is a special form that does not evaluate some of the arguments. cond and multimethods always evaluate their corresponding thing

16:19 hanDerPeder: i see, thanks

16:19 raek: here, case is the odd one

16:19 floatboth: mudge: it makes sense to deploy apps in any language using git, actually. for web, try this workflow: http://joemaller.com/990/a-web-focused-git-workflow/ btw you better ask on #git I guess

16:20 mudge: thanks floatboth

16:21 MasseR: How come "(reduce (fn [acc x] (merge-with + {x 1} acc)) {} (lower-case (slurp "/usr/share/dict/words")))" takes 22 seconds? In haskell a similar function returns a lot faster (IIRC)

16:22 coopernurse: anyone successfully written an oauth client with clojure?

16:22 amalloy: ~source frequencies

16:22 $google clj-oauth

16:22 lazybot: [mattrepl/clj-oauth - GitHub] https://github.com/mattrepl/clj-oauth

16:22 coopernurse: amalloy: sorry, I should have added "with app engine"

16:23 looks like clj-oauth uses HTTPClient, which won't fly

16:23 amalloy: MasseR: frequencies will be a lot faster than your by-hand reduce

16:23 coopernurse: looks like a fork of signpost (java) supports appengine..

16:23 but I don't see any clj wrappers

16:23 MasseR: amalloy: :D of course there's already a function

16:24 amalloy: but just slurping the whole thing into memory into a single string will be a bit slow already, i suspect

16:24 MasseR: So slurp reads to memory?

16:24 amalloy: it returns a string. how could it not?

16:25 MasseR: amalloy: I was going to say lazy seq, but .. string, of course

16:28 upwardindex: Is try-clojure.org 502 for anybody else?

16:29 Netpilgrim: upwardindex: Yepp.

16:29 amalloy: $google downforeveryoneorjustme

16:29 lazybot: [Down For Everyone Or Just Me -> Check if your website is down or ...] http://downforeveryoneorjustme.com/

16:29 coopernurse: upwardindex: yeah, it seems busted

16:30 upwardindex: Netpilgrim, coopernurse: thanks I was thinking I might have caught a virus or something

16:30 amalloy: i'll see what i can do

16:31 i'm not sure how Raynes generally launches the thing

16:35 upwardindex: back up for now

16:36 $mail Raynes i restarted try-clojure, but it's running in a cake repl right now so you'll probably want to fix it to whatever clever way you usually run it

16:36 lazybot: Message saved.

16:36 upwardindex: amalloy: yay!

16:38 rata_: hi

16:38 upwardindex: rata_: hello

16:42 rata_: how can I specify the file encoding when I open a URL with (java.net.URL. url)?

16:49 dnolen: vector patterns have landed, pretty syntax for matching primitive arrays are in, https://gist.github.com/1177009

16:51 drewr: your tweet mentioned bits too

16:52 pretty sweet

16:53 dnolen: drewr: yeah the bit stuff needs more work. Need to look deeper into the feature set that Erlang supports and replicate that.

16:55 coopernurse: is there a #clojure meetup planned for strange loop?

16:57 drewr: dnolen: that's exactly why I'm interested.. I'm always jealous of erlang there

17:08 dnolen: drewr: I don't think it'll be very hard. thinking about the syntax: https://github.com/swannodette/match/blob/master/src/match/bits.clj#L34

17:12 drewr: dnolen: quite nice actually

17:13 Somelauw: strange loop

17:16 coopernurse: https://thestrangeloop.com/

17:18 michaelr525: heya!

17:20 Suppose that you were asked to design a scalable architecture that will start very small and later will grow to the size of facebook or amazon store or whatever huge site, where would you start?

17:20 Would you try to sell Clojure as the main platforms for development?

17:21 platform

17:24 Take your time, you don't have to answer right away.. :)

17:25 coopernurse: michaelr525: seems like facebook has proven you can grow almost any language. they use php extensively (although they did end up writing a compiler for it)

17:26 michaelr525: Sure, but I like clojure :)

17:27 jblomo: yes, clojure is mature enough to scale

17:27 michaelr525: And if you are given the chance to start from zero..

17:27 What would you choose?

17:27 upwardindex: michaelr525: One of the major problems for scaling to such a big size is finding people to hire

17:27 jblomo: then i would pick whatever language the team was comfortable with

17:28 michaelr525: jblomo: And if you are the one building the team?

17:30 jblomo: you mean if i had to start building before hiring a team?

17:33 michaelr525: yep

17:33 You start building and as the company grows you hire/grow your team

17:35 jblomo: yea, i'd start in clojure

17:36 upwardindex: could be an interesting idea to lobby the closest school to start teaching clojure for your future expansion :)

17:36 michaelr525: haha

17:36 I think it's a bad idea though :)

17:37 I would only hire people which want to learn it or have already learned

17:38 okay, back to my first question. Anyone has some usefull links on designing scalable web architectures?

17:39 I think the question of DB is even bigger than the question of programming language...

17:40 coopernurse: michaelr525: you might like: http://highscalability.com/

17:41 mrh0057: infoq.com has a lot of presentation from twitter, facebook, and other organizations engineers about their architecture

17:41 michaelr525: thanks

17:50 akhudek: hi, is anyone familiar with clojureql around?

17:50 I'd like to be able to insert a record into a table and have the auto-generated id returned

17:50 this works: https://gist.github.com/1177273

17:50 but is rather crude I would think

18:11 chouser: I thought strangeloop *was* a Clojure meetup this year.

18:18 srid: strangeloop seems like an interesting conference; i hope they will upload the talk videos.

18:19 coopernurse: yeah, I hope to meet some of the folks from this channel there

18:25 dnolen: hmm anybody get :refer-macros working (and is it actually :requires-macros ?) ?

18:26 srid: learning enlive templating seems daunting, but i'll persist

18:26 amalloy: dnolen: looks like :requite-macros

18:27 *require-macros

18:29 dnolen: amalloy: that was it thanks.

18:29 cljs-watch rules

18:30 manutter1: srid: sorry, I'm late to the party, but I just saw you mention enlive -- have you seen Brian Marick's enlive tutorials?

18:31 I thought they were pretty good, so I thought I'd throw in a plug.

18:31 https://github.com/marick/enlive-tutorial

18:32 srid: manutter1: thanks, I'll take a look

18:32 manutter1: Oops, that's the code, but you can follow the link to the tutorial itself.

18:39 dnolen: amazing, match.core almost just works with ClojureScript!

18:41 JS.Next indeed

18:47 mudge: how does leiningen setup the classpath when running lein run? or how can i find this out?

18:54 how do I call java on the command line to run my java program?

18:58 raek: mudge: run "lein classpath"

19:13 scottj: srid: btw strangeloop talks have shown up on infoq during the following year, I suspect that will happen again

19:15 coopernurse: mudge: if you're trying to package your clojure app as a standalone jar you can run on another machine

19:15 then you can run: lein uberjar

19:15 and that will create a single jar with all the dependencies rolled up into a single big jar file

19:17 this article has some good info on packaging up hello world that you can run

19:17 http://zef.me/2470/building-clojure-projects-with-leiningen

19:20 dnolen: pattern matching for JavaScript, er I mean ClojureScript, http://dosync.posterous.com/advanced-pattern-matching-for-javascript

19:22 hugod: dnolen: I was wondering just today if that might be possible… :)

19:23 dnolen: hugod: amazing simple. The main problem is difference between types in Clojure and ClojureScript. Need some way to communicate that to the macro that it's being called by the ClojureScript compiler.

19:23 amalloy: all things are possible, if you just mention to dnolen that "wouldn't it be cool if..."

19:52 mudge: f

19:53 anyone ever stopped an embedded jetty from the command line?

19:55 coppernurse, i am using git to deploy my webapp, and I want to use the command line to start web app remotely

19:57 scottj: can you kill the process and restart it using ssh?

19:57 or you want everything but jetty to remain up?

19:58 mudge: scottj: i want to kill the process

19:59 scottj, but i'm not sure if it is always safe to just kill the process, i wonder if there is a gracefull way to do it

20:02 dnolen: wowzers, https://gist.github.com/1177425, Google Closure optimizing the output of match

20:04 mrh0057: mudge: if you use kill <processid> it will send a stop signal to the program and try to kill it gracefully. There is flag you pass in kill to force quite.

20:06 mudge: mr0057, ah thanks, so I guess i would just write a shell script that finds the webapp/jetty process and then kills it gracefully

20:06 mrh0057: yes you call just a the kill command to stop jetty

20:07 st3fan: what is the easiest way to start a clojure repl in emacs?

20:08 i just want to play with some code .. not have a project with lein

20:08 mudge: st3fan, clojure-jack-in is really easy

20:08 st3fan: of what package is that part?

20:08 scottj: st3fan: recent clojure-mode+swank I think

20:08 amalloy: goodness, dnolen, that is pretty unintelligible

20:09 st3fan: swank-clojure?

20:09 clojurebot: see swank

20:09 bioinformaticsze: Could anyone offer me a suggestion on converting a loop to a lazy sequence?

20:09 mudge: st3fan: https://github.com/technomancy/swank-clojure

20:09 amalloy: bioinformaticsze: sure, that's always fun

20:10 (that said, everyone's life is easier if you just gist some code and ask if anyone can help with ___, rather than asking permission and then making folks wait for the code)

20:10 st3fan: oh th version emacs shows me is super old .. 1.1.0

20:11 scottj: amalloy: sounds like clojurebot needs an asking response ala #emacs

20:11 amalloy: anyone?

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

20:11 scottj: er anyone instead of asking I think

20:11 bioinformaticsze: Sorry. Here is a gist: https://gist.github.com/1177434

20:11 dnolen: amalloy: you think that's crazy, this is the output of the redblack tree balance pattern https://gist.github.com/1177437

20:12 amalloy: scottj: i'm aware of "anyone?", but if someone looks like they're trying to be polite i aim for something a little less rude-looking

20:12 scottj: clojurebot: sales pitch?

20:12 clojurebot: Titim gan éirí ort.

20:12 amalloy: hah. no, we don't have that one

20:12 bioinformaticsze: and what do you want a lazy sequence of? that bytes in the input stream

20:12 ?

20:13 bioinformaticsze: I guess so. I'm trying to download the file and write it to another file.

20:13 amalloy: bioinformaticsze: well, then (a) you don't really want a lazy sequence, and (b) clojure.java.io/copy already does this

20:14 bioinformaticsze: This is the original version I used. But it ran out of memory (HEAP?).

20:14 amalloy: oh and (c) (if-not test (do forms)) is equivalent to (when-not test forms)

20:14 bioinformaticsze: https://gist.github.com/1177441

20:15 amalloy: yes, for a large file that will blow the heap. go look at clojure.java.io/copy

20:15 bioinformaticsze: OK. Thank you.

20:15 I will use that.

20:16 I wish I had asked three hours ago. :(

20:16 TimMc: But then you would have learned less!

20:17 Now you know *why* to use clojure.java.io/copy, not just that you should in this instance.

20:17 bioinformaticsze: Could you tell me what is wrong in this version that is causing the heap to blow? https://gist.github.com/1177441

20:17 TimMc: That's true. Thank you.

20:18 TimMc: bioinformaticsze: I would guess that to-byte-array reads in the entire input stream and tries to represent it as a single byte array.

20:18 If the file is really big, that might not fit in memory.

20:18 bioinformaticsze: I see.

20:18 TimMc: In short, you need to take a streaming approach.

20:19 Currently, you're trying to swallow a wedge of watermelon all at once. You need to bite off smaller pieces!

20:20 bioinformaticsze: How would I convert that into a stream? Adding lay-seq beforehand didn't seem to work.

20:21 TimMc: I presume clojure.java.io/copy uses a loop to read a chunk, write a chunk, repeat.

20:21 st3fan: mmm water melon

20:21 TimMc: You could do the same, or just call the library function.

20:21 coopernurse: bioinformaticsze: do you need a stream, or do you just want it written to a file

20:21 I haven't used copy, but I'm reading the docs here: http://clojuredocs.org/clojure_contrib/clojure.contrib.io/copy

20:22 and it looks like you can pass it a File

20:22 which might make your task a one liner

20:22 bioinformaticsze: I think I know how to write to the file using copy. I was asking so to understand how to use lazystreams better.

20:23 coopernurse: oh, I see.

20:23 TimMc: Lazy streams?

20:23 bioinformaticsze: Sorry. Lazy sequences.

20:24 TimMc: I don't think you want laziness here.

20:24 That's for delaying computation, and it doesn't work well when you are holding open resources, such as file handes and network connections.

20:24 bioinformaticsze: OK.

20:24 TimMc: Anyway, here's how clojure.java.io/copy is actually implemented: https://github.com/richhickey/clojure/blob/8c9b0574a83f6c77576325b724c837cf4143eb33/src/clj/clojure/java/io.clj#L316

20:26 bioinformaticsze: Here is a refactored version using copy: https://gist.github.com/1177434

20:27 TimMc: and above that are some variants for other streams

20:27 bioinformaticsze: Is `to` a File?

20:28 bioinformaticsze: Yes. I think I don't need to make a stream for it do I?

20:28 TimMc: Doesn't look like it.

20:28 bioinformaticsze: Well spotted!

20:28 TimMc: io/copy can take a File for output

20:32 bioinformaticsze: I can use *file* instead?

20:35 amalloy: TimMc: i think programming needs more watermelon metaphors

20:36 ent0: does (for [x [1 2 3] y [4 5 6]] [x y]) have a special name in set theory?

20:37 TimMc: amalloy: I was trying to figure out if the rind could be a header, but I don't consume watermelon slices from that direction.

20:38 ent0: Cartesian join?

20:38 bioinformaticsze: Updated version: https://gist.github.com/1177434

20:38 TimMc: Lookin' sharp.

20:39 Just toss a docstring in there.

20:39 bioinformaticsze: I there a clojure alternative to File. ?

20:39 s/I /Is /

20:39 lazybot: <bioinformaticsze> Is there a clojure alternative to File. ?

20:39 ent0: TimMc: that's it. thanks.

20:40 amalloy: it would be called the cartesian product (maybe join is a synonym?) if you wrapped a (set) around the (for); i think ordering probably makes it a little different

20:41 bioinformaticsze: clojure is a hosted language, in a pretty fundamental way. the clojure way to get file handles is "just use the java built-ins"

20:41 bioinformaticsze: OK. That's good to know

20:41 Thank you.

20:42 Thank you both for your help.

20:44 akhudek: LauJensen: any insight on this? https://gist.github.com/1177273

20:45 I noticed in the clojureql code there is :last-index that seems intended to be put in metadata

20:45 however, the metadata of the result of a conj! is empty

20:47 klutometis: Does anyone know the relative complexities of `cons' and `conj'? In some lisps, for instance, `cons' is O(1) but `append' is O(n). Does anyone know if `conj' is O(n)?

20:47 The following seems to contradict that:

20:47 &(count (time (reduce #(cons %2 %1) '() (range 10000))))

20:47 lazybot: ⇒ "Elapsed time: 12.149319 msecs" 10000

20:48 klutometis: &(count (time (reduce #(conj %1 %2) '() (range 10000))))

20:48 lazybot: ⇒ "Elapsed time: 10.636916 msecs" 10000

20:48 akhudek: klutometis: at least with conj, it depends on what data structure you are conjing

20:48 klutometis: akhudek: I noticed a note to that effect in the docs.

20:52 akhudek: my guess is that for vectors conj would have average time log32n

20:52 for sorted collections log2n

20:52 TimMc: So, constant. :-P

20:54 symbole`: Those two examples should perform similarly. It does on my machine.

20:55 TimMc: klutometis: cons and conj on a list do the same thing.

20:55 Try it with vectors instead.

20:56 akhudek: not to mention that count on a list is O(n)

20:57 symbole`: akhudek: Does a vector know its length?

20:57 TimMc: That's OK, O(n) is a lower bound for concatenation anyway.

20:57 akhudek: yes

20:57 TimMc: Oh right, but it would make that step faster for vector.

20:57 &(find-doc #"count")

20:57 lazybot: ⇒ ------------------------- clojure.contrib.macro-utils/mexpand ([form]) Like clojure.core/macroexpand, but takes into account symbol macros. ------------------------- clojure.contrib.macro-utils/mexpand-1 ([form]) Like clojure.core/macroexpand-1, but takes into a... http://gist.github.com/1177493

20:57 TimMc: meh

20:58 ,(doc counted?)

20:58 clojurebot: "([coll]); Returns true if coll implements count in constant time"

20:59 klutometis: akhudek: I just threw count in there to avoid printing the entire list.

20:59 TimMc: ah

20:59 klutometis: TimMc: You're saying `concat' is O(n)?

21:00 akhudek: I think he meant that it takes at least O(n) to build a list of size n

21:00 no matter the complexities

21:00 TimMc: Iterative concatenation, yes.

21:00 akhudek: of conj

21:00 TimMc: (I.e., you're doing it one element at a time.)

21:00 &(#() (time (reduce #(conj %1 %2) '() (range 10000))))

21:00 lazybot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: sandbox16249$eval18562$fn

21:01 TimMc: hrm

21:01 &(fn([_]) (time (reduce #(conj %1 %2) '() (range 10000))))

21:01 lazybot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

21:01 TimMc: Ugh, too much Java.

21:01 amalloy: TimMc: you can use = there, instead of #(), and it will actually work :P

21:01 TimMc: Oh, cute.

21:01 &(= (time (reduce #(conj %1 %2) '() (range 10000))))

21:01 lazybot: ⇒ "Elapsed time: 12.829725 msecs" true

21:02 Somelauw: Something that keeps confusing me with all sequence functions is the order of the arguments. Sometimes the sequence seems to go first and sometimes the count.

21:02 TimMc: &(= (time (reduce #(conj %1 %2) '[] (range 10000))))

21:02 lazybot: ⇒ "Elapsed time: 11.886005 msecs" true

21:04 st3fan: i'm getting a "loop requires a vector for its binding" error on http://pastebin.com/WJ5pVqnJ .. does anyone see why?

21:04 amalloy: your second loop doesn't supply a vector for its binding :P

21:04 st3fan: oh argh

21:04 s/loop/recur

21:04 amalloy: i assume you meant recur

21:05 TimMc: st3fan: do that to line 5

21:06 symbole`: TCO where art thou?

21:06 amalloy: meh

21:06 i'd like TCO for mutually-recursive functions, but for self-recusion i think explicitly saying recur is nice

21:06 TimMc: symbole`: Surprisingly rarely needed.

21:07 amalloy: TimMc: i wanted it last week for http://stackoverflow.com/questions/7134733/tree-search-saving-execution-state/7134870#7134870

21:07 but, agreed, i rarely care

21:09 st3fan: tco is overrated

21:09 i think recur is much nicer / more explicit

21:10 amalloy: st3fan: except for mutually-recursive functions

21:10 TimMc: amalloy: I haven't fully grokked your SO solution, but all this returning and executing of thunks puts me in mind of trampoline.

21:10 amalloy: *nod*

21:11 TimMc: I guess you basically are writing a variant on that?

21:11 amalloy: the solution is a customized trampoline

21:13 TimMc: just finished rereading Stranger in a Strange Land last night. good book, and it's always nice to be reminded of the origin of the word "grok"

21:25 TimMc: Hmm. Maybe write a parameterized trampoline that takes a custom predicate.

21:26 amalloy: TimMc: sure. but then you have to jump back up to the top level every time; you can't do a bunch of work on a single stack frame

21:28 Somelauw: But you can't make a trampoline of mutually recursive functions that output a function.

21:29 TimMc: Somelauw: You could, with more wrapping.

21:29 amalloy: which i think the docstring of trampoline even mentions? ##(doc trampoline)

21:29 lazybot: ⇒ "([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn,... http://gist.github.com/1177551

21:34 mudge: is running a clojure program like this: java -cp "lib/*:src/" clojure.main src/jobboard/core.clj less efficient than running the clojure program from the compiled files?

21:34 because when I run java -cp "lib/*:src/" clojure.main src/jobboard/core.clj i notice that no class files are generated

21:35 does that mean that the class files are compiled every time on the fly?

21:37 TimMc: I don't know, but it probably doesn't contribute much to the startup time.

21:39 mudge: TimMc: yes, which might not matter because my clojure program is a web application, so it doesn't matter if it is a little slower starting up, it is a long running process

21:39 amalloy: TimMc: it's probably a non-negligible part of the startup time

21:40 but the jvm is gonna start up slow no matter what you do with it

21:41 mudge: amalloy: non-negligible, as in taking up a lot of startup time?

21:41 amalloy: there's a big gap between "non-negligible" and "huge"

21:43 mudge: so it is more than a litte but not a lot

21:43 amalloy: *shrug*

21:43 it's not zero

21:43 more than that, try it and see

21:46 klutometis: Is anyone aware of a mechanism to express infinity in Clojure besides Double/POSITIVE_INFINITY and the like?

21:47 amalloy: is there a way to write infinity other than infinity?

21:47 symbole: klutometis: I suspect Clojure would use what Java offers.

21:49 TimMc: klutometis: Not in an interoperable way.

21:49 klutometis: symbole: Indeed; it's just too bad I can't test against Double/POSITIVE_INFINITY with an integer index without incurring implicit casts.

21:49 devn: hm, neat -- didn't notice until a moment ago that in clojurescript you can use doubles all over the place, like (range 0.1 1.2 0.3)

21:49 klutometis: TimMc: Is there anything non-interoperable, so to speak, on the Clojure side?

21:50 TimMc: I think protocols are pretty much inaccessible from Java.

21:50 but not using Double/POSITIVE_INFINITY would make your stuff unusable from pretty mcuh the rest of Cloure as well

21:50 (don't quote me on protocols)

21:51 devn: TimMc: What about a protocol on an interface?

21:53 (I showed up late to this conversation, 1 buffer with oversized text of context)

21:58 TimMc: devn: Something about Double/POSITIVE_INFINITY and interop.

21:58 klutometis: Can you expand on what's wrong with infinity here?

22:04 klutometis: TimMc: I'm running a tree algorithm, for instance, to discover the number of leaves with an optional `max' parameter; if it encounters more than max, the computation bails out.

22:05 By default, I'd like it to be infinite.

22:05 Sure, we can do something like max: nil, etc.; but I'd rather not special-case it.

22:06 amalloy: so use Long/MIN_VALUE or something

22:06 klutometis: There's also Integer/MAX_VALUE, etc.; but it feels dirty. Also: doesn't Clojure automatically transition to BigInt at some point?

22:06 amalloy: s/min/max

22:06 lazybot: <amalloy> so use Long/max_VALUE or something

22:08 TimMc: lazybot: Not case-sensitive? For shame.

22:08 rata_: hi

22:09 TimMc: klutometis: I think nil is not dirty for this -- you are decaring the absence of a limit value.

22:10 klutometis: &(expt 2 128)

22:10 lazybot: java.lang.Exception: Unable to resolve symbol: expt in this context

22:10 klutometis: Is there a way to make lazybot import clojure.contrib.math?

22:10 Anyway, my REPL gives something like 340282366920938463463374607431768211456; which implies that we've implicitly gone into BigInteger territory, doesn't it?

22:11 TimMc: That may not be conceptually rigorous, but maybe it's the best solution.

22:13 rata_: how can I specify the file encoding when I open a URL with (java.net.URL. url)?

22:15 TimMc: You mean the character encoding?

22:19 Anyway, I suspect what you mean is, you want to send an HTTP GET request to a URL and specify the character encoding of the resulting reader.

22:28 devn: klutometis: I think you want MAX_VALUE

22:29 &(range 0 1 1/3)

22:29 lazybot: ⇒ (0 1/3 2/3)

22:29 devn: &(range 0 1 0.1)

22:29 lazybot: ⇒ (0 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0.9999999999999999)

22:30 devn: not sure why I haven't used those more often.

22:32 TimMc: devn: But with MAX_VALUE, you lose out on auto-promotion.

22:32 devn: TimMc: what's the problem again? heh

22:32 we're talking about POSITIVE_INFINITY and interop

22:32 TimMc: You could end up with a BigInt count greater than Long/MAX_VALUE

22:32 devn: we're talking about MAX_VALUE and promotion

22:32 what's the actual problem?

22:33 TimMc: 22:05 < klutometis> TimMc: I'm running a tree algorithm, for instance, to discover the number of leaves with an optional `max' parameter; if it encounters more than max, the computation bails out.

22:33 devn: ah!

22:34 TimMc: The question is how to appropriately encode "no maximum".

22:35 +Inf means you are dealing with floats, which is inappropriate

22:35 nil means you can't use < directly, so have an additional clause in the guard

22:36 Long/MAX_VALUE means that you don't have infinity anymore, even if the count would normally promote to a bigint

22:38 devn: seems like there ought to be some middle ground where -- could you switch between MAX and +Inf at some reasonable point in the computation?

22:38 Could you promote yourself or something?

22:38 TimMc: ew

22:39 devn: It's a start...

22:39 TimMc: Anyway, I think nil is the most meaningful and correct approach.

22:39 devn: TimMc: Sorry again for the weird buffer, but could you explain why?

22:40 TimMc: (and max (> current max)) is not much worse than (> current max)

22:40 nil is also appropriate to denote the lack of a value

22:40 amalloy: are we really worried that your tree is going to contain more than ##(Long/MAX_VALUE) nodes? that's absurd

22:40 lazybot: ⇒ 9223372036854775807

22:40 TimMc: amalloy: ssh!

22:41 it could be a streaming tree! >_>

22:41 amalloy: next time i have ten quintillion things to count, i'll use Double/POSITIVE_INFINITY

22:41 TimMc: OK, so accept "nil" as a limit and convert it to Long/MAX_VALUE.

22:42 klutometis: amalloy: Heh; practicality rears its ugly head.

22:43 TimMc: Is there +Inf? Scheme has one, to be sure. Is max: `nil' really conceptually accurate, or is it some indirect consequence of infinity?

22:43 It's true, I guess, that `infinity' means boundless; so maybe there's something to be said for a negative interpretation.

22:44 TimMc: +Inf was just a shorthand

22:45 I don't know of a short way of writing it in Clojure.

22:46 (I don't see anything on clojure.org/reader)

22:46 amalloy: there isn't anything

22:49 klutometis: I'm a little nostalgic for Scheme, where (>= +inf +inf) => true; even though I'm not sure that's mathematically correct.

22:55 &(time (let [max nil] (map #(and max (> % max)) (range 1000000))))

22:55 lazybot: ⇒ "Elapsed time: 0.737597 msecs" (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil n... failed to gist: Broken pipe

22:55 klutometis: &(time (let [max Double/POSITIVE_INFINITY] (map #(> % max) (range 10000))))

22:55 lazybot: ⇒ "Elapsed time: 1.307385 msecs" (false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false false fal... failed to gist: Broken pipe

22:55 klutometis: &(count (time (let [max Double/POSITIVE_INFINITY] (map #(> % max) (range 10000)))))

22:55 lazybot: ⇒ "Elapsed time: 0.687695 msecs" 10000

22:55 klutometis: &(count (time (let [max nil] (map #(and max (> % max)) (range 10000)))))

22:55 lazybot: ⇒ "Elapsed time: 0.667645 msecs" 10000

22:56 klutometis: It looks like it's just as efficient to check for the existence of max than compare against our best approximation of infinity.

22:56 Maybe that settles it, then.

22:56 amalloy: klutometis: you weren't timing anything

22:57 TimMc: heh

22:57 klutometis: amalloy: Doh! Lazy maps.

22:59 &(time (let [max Double/POSITIVE_INFINITY] (doseq [x (range 10000)] #(> % max))))

22:59 lazybot: ⇒ "Elapsed time: 2546.715829 msecs" nil

23:00 klutometis: &(time (let [max nil] (doseq [x (range 10000)] #(and max (> % max)))))

23:00 lazybot: ⇒ "Elapsed time: 2495.457683 msecs" nil

23:00 klutometis: That's actually doing some work, isn't it?

23:01 amalloy: yes

23:01 klutometis: (I should have used x instead of the lambda-shorthand.)

23:01 amalloy: i mean, it's doing some work, but not the work you want to compare times

23:02 klutometis: amalloy: How should I set up this experiment?

23:02 TimMc: klutometis: With real data. :-)

23:02 rata_: TimMc: yes, that's what I mean

23:02 do you know how to do it?

23:02 amalloy: or at least, as you said, use x instead of a lambda. returning a lambda takes constant time, regardless of the code

23:03 TimMc: rata_: You'll get an inputstream from URL's API, and you can tell the Reader you pass it to what encoding to use.

23:03 klutometis: &(time (let [max Double/POSITIVE_INFINITY] (doseq [x (range 10000)] (> x max))))

23:03 lazybot: ⇒ "Elapsed time: 2201.290519 msecs" nil

23:03 klutometis: &(time (let [max nil] (doseq [x (range 10000)] (and max (> x max)))))

23:03 lazybot: ⇒ "Elapsed time: 2504.918599 msecs" nil

23:03 rata_: TimMc: but I'm using enlive-html/html-resource

23:04 klutometis: TimMc: For the time being, I think you have the best solution; I'll run it on real data and let you know.

23:04 TimMc: rata_: Not familiar with it, but I suspect there's a shorthand for what you want.

23:04 Bedtime, in any case.

23:04 amalloy: klutometis: that last versino actually timed something, at least

23:04 klutometis: amalloy: Exactly; the difference is probably nominal.

23:05 amalloy: of course

23:19 ibdknox: for those who were asking about my nodeknockout project: http://nodeknockout.com/teams/wrench-labs

23:19 sadly no clojurescript :(

23:22 amalloy: ibdknox: i think you could use a few more sponsors in the right column :P

23:23 ibdknox: lol

23:23 that's for the nko itself

23:23 nothing to do with me :-p

23:32 amalloy: ibdknox: did the purple ovals get explained at the beginning? they seem to jump around kinda randomly

23:33 srid: this channel is being logged publicly ... shouldn't that be put in /topic? http://clojure-log.n01se.net/

23:35 ibdknox: amalloy: yeah it was, they're teleporting ones

23:35 amalloy: or with the theme, they ASLR's :)

23:35 err

23:35 aslr hacks

23:35 devn: srid: i think it used to be

23:37 mudge: is there any solution for using clojure for shell scripting? because bash sucks

23:39 amalloy: hah, the kilobyte currency reminds me of something, ibdknox. last night amazon was trying to sell me a kindle preorder (they succeeded, which is not relevant). what made me laugh was the "5KB filesize" and "1064 page print length"

23:39 ibdknox: hahaha

23:42 devn: just have to throw this phrase out into the ether:

23:42 madison square clabango

23:44 amalloy: ibdknox: so is the coding period over?

23:46 ibdknox: amalloy: yep, ended at 5pm pst

23:47 what's sad is I stopped about midday today to come up with a design and then we didn't implement most of that design :(

23:48 amalloy: well, maybe i'll leave it running for a couple hours and see if my defenses ever become inadequate

23:48 ibdknox: amalloy: I was going to have turrets that had lasting effects :D

23:48 yeah

23:48 it ended up being too easy :(

23:49 amalloy: the first few levels were tricky

23:49 ibdknox: yeah

23:49 there are a bunch of other maps too

23:49 but we didn't hook them up

23:49 amalloy: ouch

23:49 timed coding is tough

23:49 ibdknox: haha, the fragmenter towers are wicked over powered

23:50 yeah

23:50 I think we did well

23:50 our is functional

23:50 and at least moderately entertaining :)

23:58 amalloy: ibdknox: does it scale up to MB if you have enough points? that would be a selling point

23:58 roundabout when you get to wave 150, it looks like

23:59 incidentally, i don't think the orange ones are overpowered. the green guys give more bang for your buck

Logging service provided by n01se.net