#clojure log - Jan 10 2011

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

1:10 TakeV: How well does the .NET port of Clojure work?

1:19 cheezey: does drop-last have some weird side effect

1:20 cuz after i try to conj a list that's been drop-lasted, it conjs backwards :\

1:20 if that makes any sense

1:21 amalloy: &(doc drop-last)

1:21 sexpbot: ⟹ "([s] [n s]); Return a lazy sequence of all but the last n (default 1) items in coll"

1:21 amalloy: cheezey: it conjs to the front of the list, just like it does to every list

1:22 &(conj (drop-last 2 (range 10)) 1)

1:22 sexpbot: ⟹ (1 0 1 2 3 4 5 6 7)

1:22 cheezey: whoops, i meanet to say cons*

1:22 amalloy: the only thing that ever conjs to the end is a vector: ##(conj (vec (drop-last 2 (range 10))) 1)

1:22 sexpbot: ⟹ [0 1 2 3 4 5 6 7 1]

1:23 amalloy: cheezey: doesn't matter. cons glues onto the head too

1:23 &(cons 10 (range 2))

1:23 sexpbot: ⟹ (10 0 1)

1:27 cheezey: let's see..

1:27 &(conj [0 1] 2)

1:27 sexpbot: ⟹ [0 1 2]

1:27 cheezey: &(conj (drop-last [0 1]) 2)

1:27 sexpbot: ⟹ (2 0)

1:28 cheezey: i guess i don't get it :|

1:28 amalloy: cheezey: ##(class [0 1]) ##(class (drop-last [0 1]))

1:28 sexpbot: (class [0 1]) ⟹ clojure.lang.PersistentVector

1:28 (class (drop-last [0 1])) ⟹ clojure.lang.LazySeq

1:29 amalloy: vectors are the *only* thing that adds at the end, and once you do something lazy to it like drop-last, you don't have a vector anymore

1:30 cheezey: oh ok.

1:31 amalloy: &(class (seq [0 1]))

1:31 sexpbot: ⟹ clojure.lang.PersistentVector$ChunkedSeq

1:31 amalloy: &(conj (seq [0 1]) 2)

1:31 sexpbot: ⟹ (2 0 1)

1:33 TakeV: So, protocols are interfaces, and records are classes, essentially?

1:33 cheezey: amalloy: is there a way to "revector" them o_O

1:34 amalloy: cheezey: sure, but you're blowing your performance to hell if you do that

1:34 see instead ##(doc subvec)

1:34 sexpbot: ⟹ "([v start] [v start end]); Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, defaults to (count vector). This operation is O(1) and very fast, as the resulting vector shares structure with the original and no trimming is done."

1:34 amalloy: TakeV: umm. more or less, but if you try to translate an OOP program using those rules you'll be in for pain and you'll be missing the point of clojure

1:36 cheezey: hey amalloy the lists are going to be like a maximum of size 10

1:36 im ok right :P

1:37 amalloy: cheezey: if you don't care about performance, just use concat

1:37 cheezey: oh

1:38 amalloy: and it will probably be more efficient than going to and from vectors over and over

1:40 cheezey: the fact that this is getting complicated should make you reconsider whether you're doing it the right way

1:41 cheezey: amalloy: i would like to drop the last element from a list and be able to append to it

1:41 i dunno how much simpler it could get.

1:42 amalloy: cheezey: i mean, why it is you want to be able to do that. but hey, if that's what you need to do, then concat and (drop-last and/or take) are your friends

1:42 cheezey: amalloy: i guess you can think of it as a stack O_o?

1:43 honestly, it doesn't matter if it's the front or back as long as im adding/removing from the same side..

1:43 amalloy: cheezey: so conj onto a subvec, or cons onto a sublist

1:48 cheezey: ahhh.. i just realized im doing other stuff with the list

1:48 i guess i need to get the first/last (again, only need to "modify" one side though)

1:48 and "rest" in both ways

1:49 tufflax: (assoc v i (inc (v i))) <- is this really the best way to increase an element in a vector by 1?

1:50 amalloy: tufflax: update-in

1:50 &(update-in [1 2 3] [1] inc)

1:50 sexpbot: ⟹ [1 3 3]

1:51 tufflax: thanks

1:53 cheezey: anyway, thnx amalloy im not used to clojure obv

1:53 =P

2:00 TakeV: amalloy: Oh yes. It seems like a good tool to have, not something one should pidgin hole everything into though.

2:01 amalloy: TakeV: protocols are largely for performance and interop. for general-purpose clojure code, multimethods are more flexible

2:01 Clinteger: no, please pigeonhole everything

3:02 notsonerdysunny: Can I suppress the repl in slime printing the return value by default?

3:05 LauJensen: amalloy: Im thoroughly disappointed to see people in here asking questions about ClojureQL which you are unable to answer *frown*

3:06 amalloy: LauJensen: i'm a rebel

3:06 LauJensen: You're incompetent

3:07 (crude joke, sorry, hope you're not weeping now)

3:08 amalloy: LauJensen: i'm running out of tissues

3:08 LauJensen: amalloy: So sorry - I'll make a blogpost flaming Scala if that'll cheer you up

3:08 amalloy: *laugh* that sounds fantastic

3:08 notsonerdysunny: I remember the return values of expressions evaluated in the repl were automatically bound to some vars..

3:08 amalloy: maybe i'd learn something about scala

3:08 notsonerdysunny: what are those vars .. google isn't helping ..

3:08 amalloy: *1

3:09 notsonerdysunny: thanks amalloy

3:09 can I suppress the return values from being automatically printed ...

3:10 LauJensen: notsonerdysunny: (do (your form) nil)

3:10 notsonerdysunny: right now I add a (def _ s-exp) to achieve that...

3:10 amalloy: notsonerdysunny: you just want to do a bunch of stuff with side effects?

3:10 (= (whatever))

3:10 notsonerdysunny: yes right .. I am just interested in the debug prints ..

3:11 printing the return value is just flooding the repl ...

3:13 why isn't *1 showing up when I do a (ns-publics *ns*)

3:13 amalloy: it's not an interned var

3:14 it's a repl convenience

4:18 rrc7cz: how do you guys feel about translating http error responses (client 4XX or server 5XX) into typed RuntimeExceptions (e.g. BadGatewayException) for a REST client lib?

4:25 AWizzArd: rrc7cz: my first thought would be that this introduces unnecessary complexity.

4:26 LauJensen: rrc7cz: Would make some code easier, ie. assuming everything goes well and just catch exceptions instead of testing on the result

4:28 rrc7cz: so I'm not considering it for Clojure clients of the lib. I use conditions and I like it

4:28 I throw a map like {:status 422, etc} and I can have my handle-case dispatch on :state instead of :type

4:29 but I'm thinking about how Java clients should be supported by the library. And having them catch a single Condition type isn't very friendly

4:29 thinking of the Java code, i think it would be best to have something like "catch (BadGatewayException e)... catch (NotImplementedException e).."

4:30 right now I have an abstract HttpException which extends RuntimeException and contains a factory which accepts a status code and returns an instance of the correct exception.

4:31 Basically I'm thinking I'll have my core clojure code w/condition, then a sort of Java wrapper which translates those conditions to this set of exceptions

4:37 AWizzArd: rrc7cz: When you return a record or map that contains all data, then the users of your lib can just have a look into that record or map.

4:41 Fossi: i think exceptions are ugly for http statuses

4:41 after all it's a valid outcome of a request

4:41 would hate to have to catch all of those

4:41 especially being RuntimeExceptions might screw up your program quite a lot

4:42 loads of users will never catch those

4:43 AWizzArd: Yes, in principle each request needs to be embedded in a try/catch where the catch will have to list all 60 return codes.

4:46 Fossi: well, or just one class those extend from, but still

4:47 AWizzArd: A simple map or record could do well.

4:59 rrc7cz: a map or record is fine for clojure clients, but I'd hate to have a Java client have to parse a map

4:59 no client would have to catch all of those exceptions; they're RuntimeExceptions for that very reason

5:00 just catch what you care about, or catch a superclass like HttpException or ClientException (4XX)

5:00 AWizzArd: rrc7cz: It should be trivial to call get from Java on maps, or access public fields of a record.

5:00 rrc7cz: AWizzArd: sure, but then every usage of the lib forces the client to code for error conditions

5:00 instead of giving them the freedom to ignore it, or to handle it higher up in the call stack

5:01 I mean, I was thinking about error-as-return-type as well, like Maybe/Either in Haskell

5:01 but what I don't like is that without pattern matching, it's kinda ugly forcing every client to check for these error conditions

5:03 Fossi: it's a valid outcome for a request, but in a RESTful API it's also the mechanism by which to signal errors

5:05 Fossi: yeah, but you are trying to fix these problems (having to check for the error) in a non-java way

5:06 rrc7cz: here's a concrete example: POST to /user should create a new user at /users/1, where 1 is the PK of the user (just an example). But imagine POST is not actually allowed on /user because the API requires the client to specify a PK, so only PUT on /user/1 is supported. It will return a 405 Method Not Supported. That's useful and it's an invocation error. How would your client lib handle that?

5:06 Fossi: there simply is no maybe/either, there is (almost) no "handling it higher up the callstack" and there is no pattern matching

5:06 those are not your/your library's faults, so don't try to cleverly fix em

5:07 in your scenario the "user" would never try to invoke that

5:07 and never handle that error

5:07 rrc7cz: actually looking at my example, I think it's a bad one because it shows a problem with the client lib rather than the data supplied to the client lib

5:07 hm

5:07 Fossi: because i assume they would have documentation and remove "flawed" calls

5:08 then again, if something changed unnoticed, i want to get thrown a "hard"/typed error

5:08 so i can deploy a new version

5:09 but on a more realistic senario, the api may be down/overloaded for a while

5:09 rrc7cz: it exception idea works in other contexts though. Look at JPA/Hibernate. If you try to persist() an entity whose PK already exists in the DB, you would get a RuntimeException

5:09 Fossi: i don't want that to throw me out of some loop, because i "forgot" to catch runtimeexception

5:10 yeah and that is *horrible* in practice

5:10 rrc7cz: ?

5:10 Fossi: i rarely know anybody who hasn't complained about it once

5:10 it's such a bad pattern

5:10 rrc7cz: how would you have designed it?

5:10 AWizzArd: rrc7cz: the clients are forced to implement *something* anyway if they want to react to errors. In some cases they want to write into a log file, in the other case a little Swing window should pop up, etc.

5:11 Fossi: that we almost always wrap it either by rethrowing a checked exception or not binding to it/using sql

5:11 then again, if the DB is down, *that* is a useful case for an exception

5:11 rrc7cz: AWizzArd: correct, I'm just arguing that by making it a RuntimeException, you're giving the client the freedom to a) choose what to handle and what to ignore and b) where to handle it

5:11 Fossi: as in, somebody has to do something about it

5:12 runtime exceptions will almost never be caught from my experience

5:12 they will just fall through and cause somebody to be called late night

5:12 just to notice an enduser fiddeled with a url on your site somewhere

5:26 rrc7cz: well the good news is, I'm writing the Java client code as well. So I'll try both approaches and see which one feels better/less painful

5:27 I could end up with a compromise: just stick with clojure's condition lib and leave it to the Java code to catch a http error condition (4XX or 5XX) and parse the "status" field of the map themself if they care about handling a particular value

5:27 that would save me from writing a big class hierarchy

5:30 it's pretty quiet in the EU timezone :-) It seems it's usually only AWizzArd and Lau. Fossi where you located?

5:31 Fossi: Hamburg, DE

5:32 generally picks up a few hours from now

5:32 but lots of lurkers as well :)

5:32 rrc7cz: I have good memories of the fish market at 5am

5:32 Fossi: (including me usually)

5:32 rrc7cz: I miss currywurst :-(

5:33 the best I ever had was in Hamburg, thought the smoked eel from the market was awesomet oo

5:33 Fossi: berlin is quite famous for currywurst

5:33 but we have quite a few good ones here at well

5:33 rrc7cz: I tried it there too, but it wasn't as good. I had a native Hamburger host though so he knew where to go

5:36 mduerksen: *lurk*

5:37 rrc7cz: so it's up to 5 now :-)

5:40 LauJensen: Guys, you're making me sick with all this talk of German food :(

5:41 Fossi: german food is awesome

5:41 rrc7cz: :-D sorry, but I thought Danish food was basically the same, especially in the sea-front Hamburg

5:41 Fossi: actually danish food is quite nice as well

5:41 ejackson: don't complain - I have to eat English food.

5:42 rrc7cz: I imagine pickled herrring

5:42 ejackson: you win. Blood pudding cannot be beat, even by the Germans

5:42 Fossi: yeah, english food sucks mostly :o

5:43 ejackson: just as well the the girls are so pretty here, or there'd be no reason to stay...

5:43 rrc7cz: ejackson: I hope you're joking... English girls???

5:43 good lord. You need to come here to the Czech Republic. I think you'd enjoy it :-)

5:43 ejackson: oh yeah... I'm joking :)

5:49 LauJensen: rrc7cz: Yea I wasn't boasting about the danish food culture :( And AFAIK the only pretty girl in the UK is ejackson :((

5:50 ejackson: LOL ! yes, she's a stunner

5:51 rrc7cz: lol tragic

5:51 ejackson: actually I was drinking Gemmeldansk on saturday night, you have nothing to boast about !

5:51 and that was after the bizarrely named Fishshot, also from your part of the world LauJensen

5:52 LauJensen: ejackson: You mean Fishermans friend?

5:52 rrc7cz: Carlsberg is also terrible.

5:52 ejackson: well, Fishermen's friend is the solid phase, this was a liquid that tasted identical

5:54 LauJensen: ejackson: okay, I know which one you're talking about. Its very refreshing

5:54 ejackson: lol, it claimed on the bottle to be the most popular shot in the world, which was highly commendable lying.

6:01 krumholt: hi. i am looking for a function that retrives the first occurence of an element. i could use filter and first but i need the index and not the value

6:05 raek: krumholt: an exact function for that is not in core, but how to make it is explained in the first chapter of Programming Clojure: http://media.pragprog.com/titles/shcloj/flow.pdf

6:05 mrBliss: ,(.indexOf [1 2 3] 3)

6:05 clojurebot: 2

6:05 raek: hrm

6:06 there's no function wrapping that, right??

6:06 LauJensen: ,(letfn [(find-idx [k c] (reduce #(if (= %2 k) %1 (inc %1)) 0 c))] (find-idx :y [:x :y :z]))

6:06 clojurebot: 2

6:07 krumholt: thanks all

6:08 LauJensen: krumholt: wait, scratch that, reduce doesnt stop when it gets a hit

6:10 go with stu's

6:13 raek: (defn index-of [coll x] (some (fn [[idx val]] (when (= val x) idx)) (indexed coll)) ;; version using Stuart Halloway's indexed, but some instead of first + filter

6:14 some has the advantage here that it can check for one thing and return another

6:25 LauJensen: pepijndevos: whats with the nick ?

6:38 pepijndevos: LauJensen: I'm trying to change it.

6:39 Raynes: pepijndevos: What trouble are you having doing so?

6:40 pepijndevos: Raynes: I'm not sure. It seems to work, but it still shows fliebel in some places

6:40 Raynes: pepijndevos: I'm going to spend the next week or so trying to figure out how to pronounce your name.

6:41 pepijndevos: Raynes: harhar, both ie an ij er pretty much Dutch sounds. Thoug i and y are close in some ways.

6:41 raek: I like the dutch "ij"

6:43 pepijndevos: I wonder what the relation is between nickname and user name. Colloquy now shows my nick to be fliebel, and user to be pepijndevos.

6:44 raek: in irc?

6:44 pepijndevos: raek: yes

6:45 raek: nickname is basically the only thing that's used

6:45 the other fields (login and real name) is for /whois lookups

6:46 currently, you are registered at nickserv as "fliebel". but that only affects channel admin stuff on freenode

6:47 pepijndevos: raek: So, I'm still registered as fliebel, but displayed as pepijndevos?

6:47 raek: yes

6:48 pepijndevos: okay, I can live with that :)

6:48 raek: I only saw the string "fliebel" in the whois lookup. nowhere else.

6:49 pepijndevos: http://pastebin.com/hPyLFkuu

6:51 pepijndevos: raek: Thanks

7:45 AWizzArd: rhickey: Good morning.

8:00 Swing users? When I grab the handles of my window and resize it manually to become bigger then my UI grows. But when I open a fresh JFrame with it and hit maximize then the components don't grow in x-direction. Any ideas? (.validate (.getContentPanel frame)) didn't help.

8:01 nevermind

8:02 pepijndevos: AWizzArd: What was it?

8:02 Chousuke: Sounds like OS X

8:04 AWizzArd: pepijndevos: was Windows XP with MigLayout. ML will only resize automatically in x direction if *all* column constraints contain a "[grow]".

8:05 pepijndevos: MigLayout... I've heard a bit about it, but never used it. Is it good?

8:07 AWizzArd: It is indeed very good. It basically removes the need for all other Layouts that come with Swing.

8:11 StartsWithK: http://paste.pocoo.org/show/317723/ can some one tell me is this a bug in clojure? (if it was already anwsered, i'm sorry didn't see it)

8:14 raek: the first one looks weird...

8:15 as for the second exception: it seems like remove-ns does not remove used vars and aliases from other namespaces

8:16 (those can be done manually with ns-unmap and ns-unalias)

8:16 if that is intentional, I do not know

8:58 pepijndevos: What is the state of logic programming in Clojure? There are 2 mini kanrens and one hadoop lib, as far as I know.

8:59 kumarshantanu: pepijndeos: Fogus is working on unification library, did you consider that already?

9:03 pepijndevos: kumarshantanu: No, where does it live?

9:06 dakrone: pepijndevos: https://github.com/clojure/core.unify

9:07 LauJensen: pepijndevos: that link to my website you put on HN yesterday, just left the frontpage minutes ago :)

9:08 pepijndevos: LauJensen: ASCII version of your stats of the past day: /^^^^\__

9:08 LauJensen: (and generated about 15 - 16.000 hits)

9:08 pepijndevos: dakrone: I just arrived there as well, thanks :)

9:15 But, core.unify does not do the rule thing that datalog does, or does it?

9:18 kumarshantanu: datalog can go hit a data source (on the disk), which is interesting

9:19 pepijndevos: kumarshantanu: But, can I do the classic family relations in core.unify? I don't think I understand unification completely yet...

9:20 kumarshantanu: core.unify lets you only unify vars and values...it doesn't know about facts AFAICT

9:23 LauJensen: ejackson: heads up! I think your blog has stalled :(

9:31 pepijndevos: Whoa, another one! http://clojure.github.com/clojure-contrib/datalog-api.html

10:08 dsop: hmm how to check if an obj implements a certain type created with deftype?

10:08 ah satisfies

10:08 tonyl: (type obj)

10:08 maybe

10:12 cemerick: dsop: instance? is what you're looking for. satisfies? checks whether a type has been extended to a protocol

10:19 markskilbeck: In the Programming Clojure book, it says "Avoid direct recursion." What's the difference between direct and indirect recursion?

10:20 Chousuke: markskilbeck: indirect just means using recur

10:21 You shouldn't do recursion "directly" by calling the function because that causes stack growth.

10:21 dsop: as clojure doesn't have a tail-call optimization

10:22 Chousuke: I think it actually depends on the JVM

10:22 if the JVM guaranteed TCO then Clojure wouldn't need recur, but it unfortunately doesn't :/

14:10 mprentice: ok, got it working now, thanks for the help qbg and technomancy

14:26 Berengal: Two things: First, I love how many "magic" things are implemented using macros. Makes it very easy to see how they're implemented. Second, my very preliminary proxy-mocking code already feels like I'm not only dissecting objects, but removing most of the organs and replacing them with a very steampunk machinery of ratchets, coils and spring, including a cockpit for me to sit and drive in.

14:28 * Berengal builds a frankenbean

14:29 * qbg prepares to revise the description mechanism in syntax-rules for at least the third time

14:34 pepijndevos: Berengal: Have you figured out a default-proxy macro already? :)

14:35 Berengal: pepijndevos: just create an "empty" proxy, and use init-proxy to add functions to it

14:36 pepijndevos: Berengal: I mean, the abstract-subclass thing you asked for earlier.

14:37 Berengal: pepijndevos: As in create a subclass of an abstract class, not just an instance to it?

14:38 markskilbeck: What's the difference between when and if?

14:38 qbg: when has only a true branch and allow for multiple forms in it

14:38 pepijndevos: Berengal: I don't know. You asked about something for poking at Java and generating stub classes.

14:38 Berengal: pepijndevos: Ah, that's what I'm working on

14:39 And init-proxy is how I create the stubs

14:40 markskilbeck: qbg: Ah! Bitte.

14:52 * qbg thinks "Hmm... That was easy to implement..."

14:52 pepijndevos: Can I say I hate function - and macros even more - that take &rest arguments? Sure, I can use apply and reduce for most, but not with macros.

14:53 qbg: Why don't you like & arguments on macros?

14:54 If your writing a macro that expands to a macro usage, just use ~@

14:56 amalloy: and if you were writing a function that uses a macro with & args, you couldn't do it anyway - the arguments to the macro would have to be known at compile time as literals anyway

14:57 pepijndevos: amalloy: Exactly.

14:57 amalloy: pepijndevos: i think you missed my point. macros can't really take a seq of arguments

14:58 try rewriting a macro from (defmacro foo [a & more]) to (defmacro foo* [a more]) and you'll have the same problem

14:58 so i don't see what you think would be an improvement

15:01 pepijndevos: amalloy: *rereads everything, again, and again* I don't get it...

15:01 amalloy: pepijndevos: maybe i'm the one who doesn't get it

15:02 could you give an example of a macro with a &rest argument that causes you problems?

15:02 pepijndevos: amalloy: Uuhm, let me thing, I think Enlive had a few.

15:04 amalloy: There. They make me want to resort to (eval (macroexpand)) tricks sometimes. https://github.com/cgrand/enlive/blob/master/src/net/cgrand/enlive_html.clj#L554

15:07 amalloy: pepijndevos: and how would you propose improving this? (defmacro transformation [forms]) won't be any good. not knowing anything about this library, the sheer number of macros-instead-of-functions makes me nervous, but i don't think there's anything wrong with the macros themselves other than (possibly) the fact that they're macros

15:10 pepijndevos: amalloy: That is the solution, tell people to stop using macros, and tell them someone at the other end of the globe is going to hate them when he needs to jump through hoops to make their macro run with a seq of arguments.

15:11 amalloy: pepijndevos: that's fine. it's just you're complaining about macros with & arguments, when really what's bothering you seems to be macros

15:14 pepijndevos: amalloy: Macros are fine it's just that sometimes I want to stuff a seq of arguments through one, and it can't be done. There is no solution to it, I just don;t like it.

15:16 qbg: I suspect that using what ever macro you are trying to use wouldn't really make sense at runtime anyways

15:17 opqdonut: I think it's good style to offer function versions of macros where possible

15:18 qbg: I think Enlive already has functional versions of a lot of things already

15:18 After all, it was used in CGrand's (not= DSL macros) talk IIRC

15:18 pepijndevos: I once had a mega-macro that did a lot and was very messy, but when I broke it up in functions, I could not get all the ends tied together, and resorted to this. It was temporarily, but then the project stalled. https://github.com/pepijndevos/utterson/blob/develop/src/utterson/compile.clj#L76

15:20 qbg: iirc I had to dig deep down to find a function for what I did, but that was a looong time ago.

15:32 mduerksen: what could be the reason i need to use gen-class in 1.3, while i didn't need it in 1.2?

15:38 hmm, gen-class didn't work either - ClassNotFoundException during runtime

16:08 interesting - when compiled with lein-stable, everything works fine.

16:12 _na_ka_na_: hellos, how do i create a non-top level var

16:14 intern will create a top (ns) level var

16:14 tonyl: you can use let

16:15 amalloy: _na_ka_na_: do you actually mean var, as in like #'foo, or do you just want a local binding?

16:15 _na_ka_na_: amalloy: a var

16:15 amalloy: _na_ka_na_: i don't think you can do that

16:16 and it's not really clear why you would want to. if you want a binding, you have let; if you want mutability, you have atoms/refs

16:17 _na_ka_na_: amalloy, i want to keep a var of my app's compojure routes, so i can change it dynamically, i would have gladly used an atom if it worked

16:18 tonyl: just rebind the symbol of the var to a new var

16:18 amalloy: _na_ka_na_: use a closure around an atom?

16:19 (let [real-route (atom whatever)] (set-compojure-routes-function (fn [] (@real-route))))

16:19 note that i don't know anything about compojure so the actual words i used there are nonsense, but i hope you get the idea

16:21 _na_ka_na_: amalloy, i dont understand what you mean

16:22 amalloy: _na_ka_na_: if you want something that you can rebind, but don't want to create a top-level var (which is the only kind of var), you can create an atom that stores the real data, and pass that around / modify it as needed

16:22 _na_ka_na_: so routes is just a function .. say. . (def *routes* (fn ...)) .. then here's how i'll start the server .. (start *routes*)

16:23 and inside compojure will just call the function as (*routes* request)

16:23 so if I start my server as : (start (var *routes*)) .. I can rebind it and changes will be reflected

16:24 is is because ((var some-fn) ..) works ..

16:24 ,((var +) 1 2)

16:24 clojurebot: 3

16:24 amalloy: yes, i'm aware

16:25 aside from the fact that i don't know why you want to avoid creating a var, you can close around an atom and then swap/reset the atom

16:25 _na_ka_na_: but i'm not aware of any utility as 'set-compojure-routes-function'

16:26 i'm just being fussy .. i want to avoid a top level name coz its not really required

16:26 I'll just do (declare *routes*)

16:29 aren't vars reference types like atoms/refs/agents, why can't we create them like we do the others?

16:31 chouser: you can craete vars using with-local-vars

16:32 amalloy: chouser: no kidding? neat

16:33 _na_ka_na_: chouser, but it works only if used from the same thread

16:33 ,(with-local-vars [a 10] (future (var-get a)))

16:33 clojurebot: #<core$future_call$reify__5500@1e60601: :pending>

16:33 _na_ka_na_: ,(with-local-vars [a 10] @(future (var-get a)))

16:33 clojurebot: java.util.concurrent.ExecutionException: java.lang.IllegalStateException: Var null/null is unbound.

16:36 amalloy: _na_ka_na_: what i'm talking about is this: https://gist.github.com/b4ff52ae5f0d50db15bd

16:36 chouser: works in 1.3 :-)

16:36 _na_ka_na_: yeah i know :/ even binding is multithreaded in 1.3

16:37 chouser: but of course it's unbound in another thread. That's how vars work.

16:37 ,(with-local-vars [a 10] @(future (with-bindings {a 20} (var-get a))))

16:37 clojurebot: 20

16:38 _na_ka_na_: amalloy, nice i understand now !

16:38 thanks

16:38 amalloy: imo this is a disgusting solution and you should just use vars like god intended

16:38 but if you don't want to, there's the answer

16:39 _na_ka_na_: hmm you're right, I'll just use a var, I was just curious about creating a var like other reference types

16:40 chouser: Well, this isn't Clojure-related, but it's what I was up to this weekend: http://blog.n01se.net/?p=237

16:41 _na_ka_na_: chouser, that-is-awesome

16:41 chouser: :-) thanks. Surely it's been done before, but it was fun to make myself.

16:45 _na_ka_na_: do we have a 1.3 clojure-bot ?

16:45 i think it may be useful

16:45 to have a bot running latest beta

16:45 or alpha

16:46 amalloy: _na_ka_na_: we don't

16:47 chouser: fwiw, it works on my droid x, but only with one finger

16:47 if i use two fingers, neither one draws anything

16:47 _na_ka_na_: amalloy, can i help create one in any way

16:48 amalloy: _na_ka_na_: http://github.com/Raynes/sexpbot - just change the dependencies to use whatever clojure version you want, and run it on your computer

16:49 you'll probably want to (surprise!) read the readme, which has a pretty good getting-started guide

16:52 _na_ka_na_: amalloy, I'll take a look

17:14 Raynes: Assuming sexpbot will run on 1.3

17:14 Never actually tried.

17:15 I intend to make it so we can evaluate code in both 1.2 and 1.3 from the same bot using classlojure.

18:06 david`: hi

18:06 anyone here work at Relevance

18:06 by chance

18:09 redinger: david`: Several of us do, what's up?

18:09 david`: oh, I was thinking of applying

18:10 I was emailing with someone named Andrew but I don't see that person on the site

18:10 redinger: david`: Ah, cool; Yeah, we don't have Andrew up there

18:11 david`: oh ok

18:11 thanks redinger

18:11 are you going to the Ruby meetup on the 18th?

18:11 redinger: Sure am

18:11 david`: nice!

18:12 redinger: We also have the TriFunc meeting tomorrow in our office. Aaron's speaking

18:12 david`: oh really

18:12 I've never heard of ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAnkld+J8ySCvnjBPXcNpFlnI6TIZvLcdFgw0mdMNeW/rIdUNNQBQuC4QXv+P2WhnECS9m1tJV2SvvyvGnjOz1RkUTIucrolskhwxu2cr50eThb7vvH9xBVTIZ4nWoaorTAaThqN8KZYmRGyl3g9oP2ROipDBIR4qaHtutGj4vjXcRr9pG8GCDx0JUy8xZjGDGKa1fcbH65vUkytbRwIkZfHB0AI2XNejbaZ8lTOofXZ74eWpZVwsI15Fhn6AqOtjl1Df3PSoKVutWNY2ksXt0FlMOaC9Mp4MqqTAw/B8AyJ1bf4uD3ugDC4jDXhyATL9A5Xyt2LYpVRRSzL+HNK4Zww== david@darthmaul

18:12 fuck

18:12 TriFunc

18:12 copy and paste on ubuntu sucks

18:13 oh cool, aaron = incanter

18:14 I was reading up on Incanter this past weekend

18:14 redinger: Aaron's talking about incanter. David L = incanter

18:14 david`: oh ok

18:14 redinger: The TriClojure group is also kicking off tomorrow (at TriFunc): http://www.meetup.com/TriClojure/calendar/15938227/

18:15 david`: awesome, I was thinking about how there was no Functional meetup group in the triangle

18:15 Raynes: redinger: Did you ever get my reply to your email?

18:15 david`: I was talking to one of my coworkers about starting one

18:16 redinger: Raynes: I did, thanks for getting back go me!

18:16 s/go/to

18:16 sexpbot: <redinger> Raynes: I did, thanks for getting back to me!

18:16 Raynes: Just making sure my email client didn't decide he hated me.

18:18 redinger: For the record, there is a new draft that you'll want to grab before reading it. Recently made a huge move to pandoc and fixed a lot of things in the earlier chapters. Read page 5 of that new draft before anything else, it'll give you a feel for the status of the book.

18:18 Same link (always the same link).

18:18 Prettier fonts. :>

18:18 redinger: Cool, I'll take a look through it

18:19 Raynes: I have a friend who has agreed to copy edit it, so I'm doing well in the editing and review department.

18:56 bytecolor: how would I bring java.lang.Math/cos into my namespace so I can (cos x, not (Math/cos x)? I've tried all manner of :use, :import, :require, etc.

18:57 Raynes: You can't.

18:57 bytecolor: oh? well that's interesting

18:57 Raynes: What you want to do is create a function that wraps it.

18:57 (defn cos [x] (Math/cos x))

18:57 Then you can just call your own function.

18:57 bytecolor: aye, I see

18:58 raek: this can be used too http://richhickey.github.com/clojure-contrib/import-static-api.html

18:58 Raynes: raek: Stop stealing my spotlight.

18:58 ;)

18:58 raek: :-)

18:58 Raynes: First time I've heard of import-static.

18:58 bytecolor: I thank you both equally ;)

18:59 Raynes: <3

18:59 raek: (inc Raynes)

18:59 sexpbot: ⟹ 3

18:59 Raynes: (inc raek)

18:59 sexpbot: ⟹ 3

18:59 amalloy: get a room, guys

19:00 tonyl: imported as macros, wonder if there is an option for importing as fn

19:00 raek: import-static could be updated to emit a definline instead

19:09 rata_: hi

19:09 how do you get a unique temporary file in clojure?

19:09 amalloy: &(java.io.File/createTempFile "pre" "suff")

19:09 sexpbot: java.lang.SecurityException: Unable to create temporary file

19:10 amalloy: ,(java.io.File/createTempFile "pre" "suff")

19:10 clojurebot: java.lang.SecurityException: Unable to create temporary file

19:10 amalloy: bah. but rata_, ^

19:10 rata_: thanks amalloy =)

19:11 do you use that with with-open?

19:12 amalloy: rata_: do whatever you want with the File object it gives you

19:13 rata_: I ask that because I don't know how to use a File object

19:14 raek: rata_: if you want to read text, create a Reader. if you want to read raw bytes, create a InputStream.

19:14 rata_: you can use 'reader' and 'input-stream' from clojure.java.io to do that

19:14 they can both take a File object as argument

19:15 (require '[clojure.java.io :as io]) (import 'java.io.File)

19:15 rata_: can I use c.c.duck-streams/write-lines?

19:15 raek: (with-open [rdr (io/reader (File/createTempFile ...))] ...read here...)

19:16 sure

19:16 some of the stuff in c.c.duck-streams has migrated into c.j.io and core

19:17 rata_: I didn't know about c.j.io

19:17 is it in 1.3?

19:17 raek: 1.2

19:18 (if you want to write, you use a writer or a output-stream)

19:20 rata_: thanks

19:21 I just want to write-lines on it and then launch a command line program that reads it

19:22 how do I manually close a File object? I doesn't have a .close method

19:23 raek: the "File" class name is a bit confusing. a File actually represents a file name, rather than an opened file

19:24 calling 'writer' on the File object will create a FileOutputStream under the hood, which will open the file

19:24 Writers and OutputStreams have a .close method, though

19:27 rata_: oh, thanks raek =)

20:19 Derander: raek: I swear your name is a nosql db or something

21:58 cheezey: is it possible to apply map to a function with more than one variable

21:58 (or somehow consolidate two lists together..)

21:59 brehaut: ,(map (fn [a b] [a b]) [1 2 3] [:a :b :c])

21:59 clojurebot: ([1 :a] [2 :b] [3 :c])

21:59 brehaut: like that?

21:59 cheezey: oh my god that's totally not what the docs say LoL

21:59 i prolly should have just tried it out :\

22:00 brehaut: the docs are a wee bit obtuse, but they do say that to me?

22:00 amalloy: cheezey: that is what the docs say

22:00 &(doc map)

22:00 sexpbot: ⟹ "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. An... http://gist.github.com/773949

22:00 cheezey: oh. i misread it fffuuu

22:00 i suck at reading guys.

22:00 amalloy: btw brehaut, ##(map vector [1 2 3] [:a :b :c]) is easier :P

22:00 sexpbot: ⟹ ([1 :a] [2 :b] [3 :c])

22:01 brehaut: amalloy: yeah i almost did that, but figured the explicity function is clearer

22:01 amalloy: brehaut: maybe so

22:25 cemerick: There was a clojure lib floating about that automated (somewhat saner) microbenchmarking. Anyone remember the name?

22:37 cmeier: I just watched Rich Hickey's demo with the ant colony - it rocked my world

22:37 Looking for the actual code ... does anyone know if it is available?

22:38 brehaut: it used to be

22:39 it has been a very long time since i looked for it; its pre-1.0 code

22:39 amalloy: cmeier: http://clojure.googlegroups.com/web/ants.clj

22:40 brehaut: (inc amalloy )

22:40 sexpbot: ⟹ 1

22:41 cmeier: amalloy: thanks!

22:59 cemerick: I did a bit of irresponsible microbenchmarking, probably going to write up a blog post for fun. Does any of this look fishy to anyone? https://gist.github.com/d3e652e87d76796ab05c

23:00 The map v. HashMap result seems plausible, but the vector v. ArrayList result doesn't.

23:01 qbg: I wonder how ArrayList is implemented

23:01 cemerick: it's just a wrapper around an array, which is why I have to think the result is wrong

23:01 An array dereference can't be slower than a tree traversal, no matter how shallow.

23:02 and yet…

23:03 amalloy: $source get

23:03 qbg: I wonder how they compare if you add the items to the ArrayList manually

23:03 sexpbot: get is http://is.gd/kwSz3

23:04 amalloy: cemerick: the arraylist has to go through several more hoops in RT.get

23:07 apparently because get is intended for associative things, which arraylist is not

23:07 cemerick: try replacing (get) in your benchmark with (.get) - that may be more viable

23:08 cemerick: I just did -- *much* more sensible.

23:08 amalloy: good!

23:09 tbh i don't see how (get) works at all on an arraylist, from reading Rt.java

23:09 cemerick: good catch, thanks -- I wrote it for the map test, and just blindly reused it

23:10 brehaut: cemerick: how much faster does it get?

23:10 cemerick: Yeah, neither do I. It's got to get to nth somehow, but the second clause in the conditional surely is false for ArrayLists.

23:11 amalloy: cemerick: yeah, i'm baffled

23:13 cemerick: brehaut: using .get, (t _ 1e6) is 10.5s for the vector, 5.2s for the ArrayList.

23:14 That seems entirely plausible (and not damn bad for the vector IMO).

23:14 brehaut: cemerick: cheers; i tried to run it but did something dumb and my repl died

23:17 cemerick: Interestingly, the same "benchmark" is consistently ~1s faster for the arraylist under 1.3.0-alpha4.

23:20 ,(get (java.util.ArrayList. (range 5)) 0)

23:20 clojurebot: nil

23:20 cemerick: amalloy: ha-ha! ^^ :-P

23:20 amalloy: ah. it doesn't work :P

23:20 i thought i'd tried that, but i see now that i didn't

23:20 cemerick: We got tarred on that one.

23:20 jeez, there since 2008! https://github.com/clojure/clojure/commit/1c9de854a30e116e502c2d0bebaadce8f80219fb

23:21 * cemerick hangs his head in shame

23:21 cheezey: im doing (map f (map b l) l) where b is a buffer, f is some function and l is a list of numbers

23:21 and f seems to never be called ;x

23:21 er sorry

23:21 b is not a buffer

23:22 b is an associative array (integer -> string)

23:22 qbg: cheezey: map is lazy

23:22 If you never use the result, nothing will be computed

23:23 cheezey: but it looks like im using it :X (in f)

23:23 Scriptor: cheezey: what you need?

23:23 qbg: You can use doall/dorun to force computation

23:24 If this is for side effects only, doseq might be a better choice

23:28 Raynes: cheezey: "lazy" means that none of the function calls that create the new sequence are evaluated until you actually use them. By use them, I mean try to get them out of the collection.

23:28 cheezey: qbg: can i use doseq with multiple sequences

23:28 because it does not seem like i can D:

23:28 qbg: In a nested fashion yes; in a parallel fashion not as easily

23:28 Raynes: Not like you can with map.

23:29 cheezey: Raynes: yea. i thought by passing it to a function, it would count but i guess not

23:29 qbg: ,(doseq [[x y] (map list (range 10) (range 10 20))] [x y])

23:29 clojurebot: nil

23:29 qbg: ,(for [[x y] (map list (range 10) (range 10 20))] [x y])

23:29 clojurebot: ([0 10] [1 11] [2 12] [3 13] [4 14] [5 15] [6 16] [7 17] [8 18] [9 19])

23:29 qbg: ^ That is just nasty though

23:29 Scriptor: somewhat random question, does anyone know what rich hickey used to make his presentations? I need something that can embed code

23:31 cemerick: Pretty sure he uses keynote.

23:31 Not sure what's used to do the code highlighting. I doubt it's builtin.

23:31 cheezey: qbg: what do you mean by nasty. inefficient?

23:32 qbg: Not very beautiful

23:32 amalloy: disgusting

23:32 cheezey: well is it worse than (dorun (map ..

23:32 ?

23:34 Scriptor: argh, dammit my client lagged out

23:34 sorry to bother, but if there were any responses to my question, could someone repost them?

23:35 cemerick: Pretty sure he uses keynote.

23:35 Not sure what's used to do the code highlighting. I doubt it's builtin.

23:35 Scriptor: hmm

23:35 qbg: You can also embed code in Beamer

23:36 Scriptor: don't have much experience with latext, unfortunately

23:37 cemerick: "and the LaTeX shall rise again" eh ;-)

23:37 cheezey: Scriptor: i think beamer makes the presentation pretty easy even if you don't know latex

23:38 Scriptor: cheezey: really? I'm trying to find some docs for it now

23:39 qbg: You can cargo-cult it to a large degree

23:41 Raynes: cemerick: I recently migrated my entire book to markdown. Using pandoc to generate the latex and pdfs. :D

23:41 cheezey: Scriptor: i only used beamer like twice before but i think so. you might get frustrated by fixing small details since you're new to latex..

23:41 Raynes: It's pretty cool.

23:41 cemerick: Raynes: That sounds very sane. :-)

23:41 We're using asciidoc, which I've come to like quite a lot.

23:41 qbg: Hopefully it is markdown -> latex -> pdf and not just markdown -> pdf

23:42 Raynes: Of course, I still had to touch some latex (just a template) to get it precisely how I want it.

23:42 qbg: Of course.

23:42 * cemerick will get away with never touching latex :-D

23:42 Raynes: How does that work out?

23:43 Someone else typeset it for you?

23:43 cemerick: It's entirely automated. No latex in the process though, either.

23:43 O'Reilly doesn't like latex much, AFAICT. They're big on semantic markup.

23:43 Raynes: asciidoc can, by itself, output that pretty?

23:44 That's insane.

23:44 cemerick: no

23:44 it's asciidoc -

23:44 .

23:44 bah

23:44 qbg: Didn't they use a lot of troff in the past?

23:44 cemerick: it's asciidoc -> docbook -> ???? -> PDF

23:44 Raynes: Oh, docbook.

23:44 Pandoc can generate docbook as well.

23:44 But, since I don't plan to publish with O'Reilly... LATEX!

23:45 cemerick: qbg: don't know about the history. The /Creator of our PDF proofs is "XSL Formatter", so I'll bet they're going from docbook -> FOP -> PDF

23:47 Raynes: I'm happy I found pandoc.

23:48 markdown-mode + emacs + pandoc = Lyx being uninstalled.

23:48 Scriptor: hmm, I just found https://github.com/schacon/showoff

23:48 might just do the trick

23:48 qbg: I'm liking markdown a lot after using on the github wikis

23:49 Raynes: I have equally pretty (if not prettier) output and more control without the clunky and ugly Lyx WYSIWYG editor.

23:49 Scriptor: qbg: same here, it has pretty much everything you'd need to write some simple but good docs

23:50 using it with github pages is a sweet combo

23:50 amalloy: yeah, i have to say i've barely used markdown but it's pretty convenient

23:50 Raynes: schacon's Progit book was written using pandoc and markdown.

23:50 cemerick: As sad as it is, I can *never* remember the order of href/text in markdown links. Never.

23:51 qbg: Then again, I've always liked the simplicity of CLHS

23:51 cemerick: And if I get the order right, I mix up parens and brackets.

23:51 technomancy: it bothers me on some level that markdown is implementation-defined

23:51 with an unmaintained implementation

23:51 Scriptor: cemerick: using it on reddit alot finally hammered it in :)

23:53 cemerick: technomancy: implementation_s_ in the plural. Every impl has its own little extensions. :-(

23:54 qbg: I wonder if there is support for blinking in at least on implementation...

23:55 Derander: qbg: doesn't markdown support arbitrary html?

23:56 qbg: I haven't used markdown much yet

23:56 Raynes: Yes, there is.

23:56 You can embed HTML into it.

23:56 Derander: qbg: then yes, there is blink support :-)

23:56 Raynes: I've used <div style="center">some text</div> to center text in markdown before.

23:56 Derander: I wonder if there is a jquery plugin to add blink support to browsers that no longer include it

23:56 Raynes: align: center, even

23:57 Derander: I still use <center> occasionally

23:57 when I'm feeling really lazy

23:57 :-9

23:57 Raynes: I was tempted, but figured I'd be better off to use the former. I only had to do it twice.

Logging service provided by n01se.net