#clojure log - Jan 01 2012

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

5:02 lypanov: hey, is there a way to set a variable like this "(def *vm-session-type* "headless") from another file?

5:03 i imagine its basic clojure knowledge. but i don't have time to finish my joy of clojure and need to get something working today ;)

5:03 * lypanov forked the project for the moment :P

9:39 Somelauw: Happy new year

9:40 I wanted to write a pokerhand recognizer in clojure. This is the code I ended up with for recognizing a full house: http://pastebin.com/q0Z5xBYK. What do you think of it?

10:22 wingie: how can i know what a function do in the repl and what args it takes?

10:24 gko: (doc function)

10:24 clojurebot: Titim gan éirí ort.

10:24 gko: ,(doc print)

10:24 clojurebot: "([& more]); Prints the object(s) to the output stream that is the current value of *out*. print and println produce output for human consumption."

10:25 wingie: gko: thanks

10:25 (doc function)

10:25 clojurebot: Excuse me?

10:25 wingie: (doc print)

10:25 clojurebot: "([& more]); Prints the object(s) to the output stream that is the current value of *out*. print and println produce output for human consumption."

10:26 wingie: (prn 1)

10:26 :)

10:31 ordnungswidrig: hi allo.

10:45 djh__: has anyone ever used clj-http

10:45 I'm struggling to get my head around one thing

10:46 I'm trying to login to a website

10:46 using POST

10:46 I can login with my credentials which returns a cookie

10:46 but I don't know how to "put" that cookie into subsequent requests

11:05 wingie: why isn't another delimiter used to create a list instead of having it like this: (list 4 3 2 1)

11:06 {} and [] are not used using a macro .. so why did they made a decicion that list should also be for execute the first one as function/macro ?

11:07 Chousuke: (foo bar) already is a list. it just evaluates as a function call.

11:07 [foo bar] is a vector, aand vectors have different evaluation rules.

11:08 you need to either quote the list (to prevent evaluation) or construct the list dynamically via a function call.

11:09 wingie: Chousuke: I see

11:09 could you say that a vector is like an array in other langs?

11:12 Chousuke: ,(let [foo {:bar 'test} bar :bar] ['[foo bar] '(foo bar) [foo bar] (foo bar)]) ; like this

11:12 clojurebot: [[foo bar] (foo bar) [{:bar test} :bar] test]

11:12 xcv: wingie: The underlying data structure is quite different, in order to preserve performance guarantees while staying immutable, but apart from the immutable properties, it feels a lot like a python/ruby array

11:13 Chousuke: I'm in a train and this internet connection is really laggy :P

11:13 took me a minute to write that example.

11:14 ssh is not the most pleasant tool to use with a connection that has 500ms average lag.

11:15 wingie: :)

11:15 xcv: right

11:17 Chousuke: anyway, the important thing to understand is that (foo bar) is a list, you just can't use them "as is" like vectors because a list is an operator call in clojure.

11:18 kzar: I want to import [org.apache.commons.lang RandomStringUtils] but I'm not having much luck, do I need to add something to project.clj? (I'm not really clear how you figure that out for Java libraries.)

11:18 Chousuke: in most cases where you'd want a literal list a vector will do just fine anyway

11:19 it's very rare to see actual calls to list in clojure code (it's more common in other lisps because they don't have vectors with useful evaluation semantics like clojure's)

11:19 xcv: wingie: As to the question of why lists are evaluated like they are, that comes back to lisp code being represented as lists: the function call reader interpretation for the list (list-as-code) is assumed to be more common than the list-as-data interpretation, so it gets the simpler syntax of the two.

11:21 wingie: Lists are basically singly-linked lists, with most of their performance characteristics (linear lookup etc) while arrays behave pretty much like you'd expect arrays to.

11:21 Chousuke: rather, it's impossible to have lists be function call forms while evaluating to themselves at the same time.

11:21 xcv: haha! Yep, that would definitely be tricky :P

11:22 Chousuke: if you have some other syntax for function calls that still somehow used lists, Clojure would lose its homoiconicity.

11:22 of course, you could have vectors be the function calls but then you'd just have the same problem with vectors instead of lists :P

11:53 solussd: is using a defn inside of a let good form? I have a bunch of functions that all need to reference the same "global", but I'd rather not put a 'def' at the namespace level

11:53 e.g. (let [something "some value"] (defn* ….)

11:58 Somelauw: I wanted to write a pokerhand recognizer in clojure. This is the code I ended up with for recognizing a full house: http://pastebin.com/q0Z5xBYK. The double transformation to a hashmap annoys me a little.

12:00 weavejester: The fullhouse function seems a little heavy for what its doing

12:00 Somelauw: Heavy?

12:00 Can it be done simpler?

12:00 weavejester: Well, if you just wanted to check if someone had a full house, then...

12:00 Somelauw: Oh, but I also want to return the fullhouse.

12:00 weavejester: (and (contains-pair? hand) (contains-three? hand))

12:01 Ah, presumably the highest fullhouse too?

12:01 Somelauw: Since I want to compare which fullhouse is best.

12:01 Yes, the highest

12:01 weavejester: I'd probably split it up into two problems then...

12:02 (defn fullhouse? [hand] (and (pair? hand) (three? hand)))

12:02 Somelauw: And a implicit precondition is that there are no quads in the input of fullhouse.

12:02 weavejester: (defn highest-fullhouse [hand] (if (fullhouse? hand) (concat (highest-pair hand) (highest-three hand))))

12:02 Somelauw: But if there are 3A's and 3J's, a fullhouse can be made by taking only 2 jacks.

12:04 weavejester: Hm... yes, a 3A 2J beats a 3J 2A

12:04 So...

12:05 Maybe something to take the cards

12:05 Somelauw: But a hypothetic highest-pair function will either ignore the 3J's or return the aces.

12:05 weavejester: Yes, you'd have to use partitioning

12:07 Really you want a form of state...

12:09 Somelauw: The input could consist of 7 cards: 5 on the table and 2 held.

12:09 weavejester: Hold'em, presumably?

12:09 Somelauw: yes

12:11 state? why?

12:13 weavejester: Well, you'd want to ensure that the pair and three are different, but perhaps there's a better way to do that.

12:15 It almost feels like a combinations function would be good here.

12:16 Maybe your function is the best way of doing it. Let me take a look...

12:17 Somelauw: You mean trying all permutations of 5 cards? That would probably be slower but work as well.

12:22 weavejester: Hm... It makes sense to have a (pairs hand) which returns all the valid pairs, and a (threes hand) which returns all valid three of a kinds

12:23 bsteuber: Somelauw, weavejester: I'd do it like this: https://gist.github.com/1547828

12:23 weavejester: So then the question becomes, do this pair and three overlap or not?

12:23 Somelauw: If I make three-of-a-kind return all remainders as well in a map, I could run pair on the remainders.

12:23 bsteuber: I'll take a look

12:24 weavejester: bsteuber: Does that account for the case where you have overlaps, e.g. 3J 3A ?

12:26 Somelauw: pair would return the highest triple or pair and do (take 2 on the output).

12:26 carlos1: hello!

12:26 weavejester: bsteuber: Yeah, it looks like it might cover all cases

12:26 carlos1: hello!

12:28 carlos1: where can I have a good explanation of "when"?

12:29 weavejester: I'd be tempted to write a function (defn independent? [xs ys] (empty? (set/intersection (set xs) (set ys))))

12:29 Somelauw: carlos1: (doc when)?

12:30 weavejester: carlos1: It's like "if" but all the forms after the condition execute in sequence

12:30 carlos1: So... (when true (println "Hello") (println "World")) would print "Hello" then "World"

12:30 carlos1: weavejester, but in (when true 1 2 3), only 3 seems to be executed

12:31 ordnungswidrig: carlos1: only 3 is returned.

12:31 weavejester: carlos1: All are evaluated, but only the last evaluated form is returned from an expression

12:31 carlos1: ha ok. now everything makes sense. thank you

12:31 weavejester: (when x y z) is equivalent to (if x (do x y))

12:32 ordnungswidrig: carlos1: the REPL can be confusing in this regard. compare (print 1) vs. 1

12:32 carlos1: it's OK haha

12:33 I understand. just a simple way of make an imperative if

12:40 weavejester: Somelauw: Maybe something like https://gist.github.com/1547883

12:41 Though I'm not sure if the order of the full-houses is correct...

12:43 Maybe the order should only be calulated at the end with a (sort-by (comp sum rank))

12:46 Somelauw: I came up with: http://pastebin.com/8dE8Bw49

12:46 weavejester: I'll take a look

12:48 weavejester: Just added an overall-rank function for sorting

12:48 Somelauw: bsteuber: Thanks for your idea

12:56 I'm not sure but when determining the overall rank of a fullhouse, I thought first the triples are compared and then the pairs.

12:57 yoklov: if i wanted a fifo queue in clojure… can I get that? or should i just write my own

12:57 Somelauw: Thanks for helping me

12:57 afk

12:58 tscheibl: yokov: clojure.lang.PersistentQueue

12:58 yokov: you must create an empty one using PersistentQueue/EMPTY

12:58 yoklov: Oh, alright, huh.

13:01 tscheibl: yokov: look here: http://fiji.sc/javadoc/clojure/lang/PersistentQueue.html ... for some reason they still haven't wrapped it in idiomatic clojure but it's there and I've been using it for some time now

13:01 yokov: howeer, after creation you can use it like any other collection

13:01 however..

13:02 yoklov: hm?

13:04 tscheibl: yoklov: you can use "peek" to get the most recent element you added with "conj" and use "pop" to get a new collection with this element removed

13:05 yoklov: oh okay, right, no mutation, pop would have to return a new queue

13:05 instead of just the top value

13:06 tscheibl: yep

13:06 it's an immutable persistent collection like the others

13:06 yoklov: you know, coming from scheme i thought that wouldn't trip me up as much as it has.

13:08 tscheibl: maybe that's the reason why it's still "not officially" in clojure... it feels somewhat awkward

13:09 yoklov: haha, maybe. I sorta meant in general though.

13:10 but yeah, queues are inherently imperative so it sorta makes sense that it would be a weird thing.

13:10 tscheibl: yoklov: you could also try lamina from ztellman (u find it on github).. it provides a somewhat statefull "channels" based abstraction..

13:11 yoklov: hm. strange.

13:13 I'm not really looking for more state, to be honest. I think of my scheme (racket) code as typically being fairly stateless but when programming in clojure I tend to realize "oh yeah i'd usually use a set! here"

13:16 Oh, you mean for a queue

13:16 tscheibl: use atoms in these cases... or alter-var-root if you want to change the root binding of vars that don't get changed very often

13:16 ..instead of set! :)

13:17 yoklov: yeah u could use lamina channels like queues

13:17 yoklov: Oh, it's not a queue of things which need to be done, it's representing some data that when it changes it adds to the front and removes from the end.

13:18 so i think persistent queue is more of what i want.

13:18 tscheibl: probably

13:18 channels are propably to "heavy weight" for that purpose

13:18 yoklov: Right

13:21 so atoms are for when a thing needs to change? what are vars for then?

13:21 tscheibl: .. too ... damn keyboard :p

13:26 Vinzent: hm, I don't know it too - what's exactly the difference between swap!-ing the atom and altering-var-root?

13:26 tscheibl: yoklov: changing the root binding of a var generally isn't a very idiomatic practice

13:27 i beleive alter-var-root is primarily accomplished using locks (although I haven't looked at the code) yet

13:28 atoms use STM which should be better for performance

13:28 yoklov: oh okay, i thought there was another way of changing a var for some reason.

13:28 tscheibl: ..and you can use atoms everywhere... just bind it to any symbol.. locally scoped or dynamically

13:29 carlos1: "user=> (new FileReader "source.txt")' opposed with this syntax sugar "user=> (FileReader. "source.txt")" is there any reason for the usage of that shortcut?

13:29 Vinzent: tscheibl, yeah I also think it's locks, but I'm not sure... Also, strictly speaking, atoms don't use STM, only refs do

13:29 carlos1, second is idiomatic

13:30 AWizzArd: Hello technomancy, please have a look into your query windows, thanks :-)

13:30 carlos1: Vinzent, I would expect that, but I cannot seem to familiarize or find any reason for the decision, which makes it counter intuitive for myself

13:30 tscheibl: Vinzent: why wouldn't they? they have the same semantics as refs?

13:31 they just automatically commit

13:31 yoklov: So, sorry about all the questions, but what's the relationship between refs and atoms?

13:31 is there any?

13:31 tscheibl: isn't it?

13:32 yoklov: you can change multiple refs in one transaction and commit them atomically

13:32 yoklov: Right, and you can't do that with atoms?

13:33 tscheibl: atoms just allow you to change their value atomically

13:33 yoklov: alright.

13:33 Vinzent: carlos1, well, it's 3 chars shorter! :) I don't know the details behind this decision, but I'm used to it very quickly

13:34 tscheibl, I thought STM refers to dosync and transactions, that's why it is software transactional memory :)

13:35 carlos1: Vinzent. maybe because dot at the end means instantiation, as opposed to dot in the middle which means namespace escalation

13:35 yoklov: Its really interesting how well integrated concurrency is into clojure. I'm getting into it not for that but because it's a more modern lisp that runs on the jvm which seems quite well thought out, but it's very cool that it has all of these language-level concurrency semantics.

13:35 Vinzent: tscheibl, and if they just automatically commit, then why the perfomance is higher with atoms?

13:35 tscheibl, but actually I don't know, maybe you right

13:36 tscheibl: Vinzent: hmm.. you may be right...

13:36 Vinzent: but they have the "retry" semantics in common with refs

13:37 Vinzent: although they obviously don't use STM in the background

13:38 actually I've still never really found a reason to use refs in my projects...

13:39 .. atoms always did the job

13:39 yoklov: are refs the one that maintain a history?

13:41 Vinzent: tscheibl, yeah, the same for me. I guess I just haven't faced such problems

13:43 tscheibl: yoklov: changing refs within a dosync creates a local copy of the changed refs and only commits the changes if not one of them was changed in the meantime.. otherwise the transaction retries

13:44 ... it's the same with an atom.. just you don't do it in a dosync

13:44 yoklov: Oh hm, so thats what the ref-history-* functions mean?

13:45 tscheibl: .. so you can't change multiple atoms synchronously

14:05 Somelauw: Hm, does clojure sort lazily?

14:08 AWizzArd: Somelauw: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L2679

14:08 The sort fn forwards sorting to some eager JVM methods.

14:09 So, sort is not lazy.

14:14 Somelauw: AWizzArd: okay, thanks

14:37 graphbum: howdy..i'm trying to abstact some stuff (a graph library) into a protocol but i hit a roadblock. is anyone willing to hear me out?

14:38 Raynes: ~anyone

14:38 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

14:39 yoklov: is it more idiomatic clojure to use defstruct for a simple data structure to just use a map?

14:40 Vinzent: defstruct is kinda deprecated in favor of defrecord

14:40 Raynes: It is never idiomatic Clojure to use defstruct. It was generally replaced by records in 1.2. Furthermore, you almost always just want a map.

14:40 yoklov: i see

14:40 thank you

14:40 Raynes: "Is there any reason for me to use defrecord?" is a good question to ask.

14:40 Yourself, I mean.

14:41 If the answer isn't technical, then you probably want a map.

14:43 AWizzArd: In most cases I want a record. A map is interesting if I want to hold tons of key/value pairs.

14:43 Also records are able to hold any number, like maps. It is only that their access is a few nanoseconds slower.

14:44 Raynes: Why create a type for the sake of creating a type?

14:44 yoklov: what benefits does it hold?

14:45 AWizzArd: It depends on the situation. If you have a function which just wants to return some data, and it makes sense to return it in a key/value fashion, then a map is perfect.

14:45 graphbum: how can a protocol be modified, or properly utilized, account for different constructors? For instance, most operations on immutable structures can be represented as returning "new" structures via some base constructor function. I want to separate the underlying data storage mechanisms for a graph from the abstract operations on a graph (the graph protocol), so that I can create effecient implementations for various graph stru

14:45 AWizzArd: A record is interesting if you want to have a typed map, and when you know the keys already.

14:45 Records should hold the core data of your application.

14:46 graphbum: protocols dispatch on the type of the first arg, so defining something like (make-graph [g nodes arcs]) inside the protocol doesn't quite work, since g might be implemented as a record (currently), but might be an array later

14:47 Vinzent: graphbum, you can use kind of factory or multimethods

14:47 graphbum: is there a significant performance penalty associated with multimethods that non-extended protocols avoid?

14:47 AWizzArd: yoklov: also records can be used in combination with Protocols.

14:47 Raynes: yoklov: Here is an excellent flow chart that will help you decide what to use. https://github.com/cemerick/clojure-type-selection-flowchart/raw/master/choosingtypeforms.png

14:48 yoklov: I'd mostly just focus on what it says.

14:48 yoklov: haha, alright: regular map

14:49 Vinzent: graphbum, yeah they are slower, but does it really matters in your case?

14:51 graphbum: I have strayed away from using multimethods for high-traffic or performance sensitive calls, so I cannot answer that definitively at the moment

14:53 I've tried sticking with protocols defined inline with defrecords as needed, for both inherent performance and for defining consistent operations

14:55 are there any benchmarks on the performance hits for using multimethods? maybe something similar to Rich Hickey's transients vs. vectors benchmarks?

14:58 yoklov: graphbum: err, i'm not really a clojure programmer but that sounds a lot like premature optimization to me.

14:58 Vinzent: graphbum, I don't know about benchmarks, but you can use factory protocols like this https://gist.github.com/1548186 if you doubt

15:00 graphbum: vinzent, thanks. you're swtiching to reificiation to avoid the problem then. that's useful.

15:00 Vinzent: np

15:03 graphbum: yoklov: it's not premature...there are cases, particularly in graph algos, where arrays are ideal. to me, it makes sense to be able to change the underlying representation as neeeded to exploit effeciencies. I'd like to deal with everything as a lazy sequences, but that only goes so far.

15:03 yoklov: right, i was talking about reluctance to use multimethods

15:04 That… doesn't have anything to do with seqs, unless i'm misunderstanding something

15:04 Which is quite possible, as I said, I don't really know clojure.

15:06 graphbum: yoklov: multimethods pose a design problem as well. the times I have used them, I ended up realizing I'd just defined a protocol (in pieces), but with a guaranteed performance hit. I tend to end up refactoring them into protocols (if I don't need an uber dispatch function).

15:07 yoklov: that sounds pretty reasonable.

15:07 graphbum: yoklov: I shouldn't say problem.

15:10 yoklov: Is there a way to map over a, err, map?

15:11 so (map #(* % 2) {:a 1 :b 2 :c 3}) => {:a 2 :b 4 :c 6}

15:11 graphbum: you're mapping over the vals in the map

15:11 yoklov: right.

15:11 is there a way to do that?

15:12 raek: yoklov: one way is (zipmap (keys m) (map f (vals m)))

15:12 graphbum: a map is a seq of [key val]

15:12 beat me to punch

15:12 Vinzent: and the other one is ##(into {} (for [[k v] {:a 1 :b 2 :c 3}] [k (* v 2)]))

15:12 lazybot: ⇒ {:a 2, :c 6, :b 4}

15:12 raek: another is (into (empty m) (for [[k v] m] [k (f v)]))

15:13 yoklov: is the ## just to make the bot eval it?

15:13 Vinzent: raek, don't know about empty, thanks

15:13 yoklov, yes

15:13 yoklov: okay

15:14 graphbum: there's also fmap in clojure.contrib.genric.functor

15:14 but it's getting into other things you probably don't need. I use zipmap most of the time

15:15 yoklov: haha, i'll use zipmap i think, after all this isn't haskell :p

15:15 graphbum: the fact that it can quite nicely approximate haskell is fascinating (to me)

15:15 there's a monad lib

15:15 yoklov: yeah, it's quite pure and has the required laziness

15:17 Vinzent: it's sad that pattern matching isn't integrated in the language

15:17 yoklov: right i was gonna say that

15:17 which makes porting code much more awkward

15:18 or, i imagine it would.

15:20 AWizzArd: Well, you could simply include core.match into your Leiningen project.clj file and have pattern matching…

15:20 https://github.com/clojure/core.match

15:20 yoklov: I see, I had no clue that existed.

15:21 AWizzArd: Yes, it is just a one-liner away (:

15:22 Vinzent: AWizzArd, yeah, and it's very cool, but if I could use it with all my lets and defns it'd be even more cooler

15:23 AWizzArd: Vinzent: could you give a minimal example of what you would like to do?

15:25 Vinzent: AWizzArd, e.g. define functions like in other functional languages, something like (defn fac ([0] 1) ([n] ...))

15:26 graphbum: pattern matching in the definition itself

15:26 Vinzent: yep

15:27 graphbum: I think that has to do with the choice arity in clojure

15:28 it would be really nice though....

15:28 still, match is pretty cool

15:29 thanks for linking it AWizzArd

15:29 AWizzArd: core.match will do most useful stuff already. And if anyone has good additions that would fit I am sure the original author would like to talk about it.

15:30 graphbum: that's in 1.3 ?

15:32 Vinzent: graphbum, I believe it works with 1.2 too

15:33 By the way, is there a way to create project templates in leiningen? So e.g. it'd automatically add midje and core.match to all new projects

15:34 I saw some conversations about this feature on irc...

15:51 tscheibl: ,(map (fn [[k v]] [k (* v 2)]) {:a 1 :b 2 :c 3})

15:51 clojurebot: ([:a 2] [:c 6] [:b 4])

15:52 tscheibl: ,(into {} (map (fn [[k v]] [k (* v 2)]) {:a 1 :b 2 :c 3}))

15:52 clojurebot: {:a 2, :c 6, :b 4}

15:53 tscheibl: why do you people always use "for"?

15:54 graphbum: I wondered that too for a while

15:54 in some cases, it's clearer

15:54 AWizzArd: for can do map and filter at the same time.

15:54 graphbum: although you dip into a little language to do it

15:54 AWizzArd: Yes, it is a DSL for List Comprehension.

15:55 In that sense map and filter are special cases of reduce.

15:55 List Comprehension can do what map and filter offer, but not what reduce can do.

15:55 tscheibl: hmm I wouldn't consider that clearer

15:56 AWizzArd: It only needs to traverse the sequence once, and thus might be more efficient.

15:56 romanandreg: is using a String as a seq of characters a bad idea?

15:56 tscheibl: .. that's a point .... in case of map AND filter usage

15:56 AWizzArd: yes

15:57 That “yes” was for tscheibl, not for romanandreg (:

15:58 tscheibl: romanandreg: nah, seems to be a quite natural approach

15:58 a string is in fact a sequence of characters...

15:58 graphbum: i think there may be times when you want to use native string ops and java strinb builders (ugh) but the seq approach to manipulating strings is great

15:59 romanandreg: tscheibl: so, <performance wise> it would be acceptable

15:59 ?

15:59 I'm developing a parser combinator library and I'm parsing strings as seqs of characters, that's why I'm asking...

16:00 tscheibl: romanandreg: If performance is your concern I would test several possible approaches for your application within a (time)

16:00 .e.g. like Java stringbuf

16:00 reiddraper: Any ideas how to troubleshoot this error I get when "require"ing one of my namespaces? CompilerException java.lang.VerifyError: (class: knockbox/registers/LWWRegister, method: create signature: (Lclojure/lang/IPersistentMap;)Lknockbox/registers/LWWRegister;) Expecting to find unitialized object on stack, compiling:(knockbox/registers.clj:27)

16:00 graphbum: good rule of thumb: go with the obvious seq-influenced route, to get obvious and readable code, then if performance is an issue, spot-optimize with less-general stuff (like string builders etc.)

16:01 if performance ends up not being an issue.. declare victory

16:01 romanandreg: graphbum: cool… I won't do premature optimizations then :-P (just chillax mode)

16:01 graphbum: i was messing with a toy problem a while back.

16:01 based on string stuff

16:02 got a dictionary of words, like 250K

16:02 in a text file

16:02 define the friend of a word w as any other word with levenshtein edit-distance of 1 from

16:02 w

16:03 you can substitute, remove, or add 1 letter

16:03 alexbaranosky: reiddraper, I've never seen that error, sorry

16:03 graphbum: the social network of a word are the friends of its friends, etc.

16:04 problem was to find the social network of an arbitrary word in the dictionary

16:04 used strings-as-sequences just like you described

16:04 reiddraper: alexbaranosky: thanks, google only seems to find one result too...

16:04 graphbum: not a big performance problem.

16:05 then again, I did not go back and optimize using lower-level string operations (did not know enough java at the time, did not want to either).

16:06 tscheibl: ha.. I remember when I started to program in Clojure I used to put typehints almost everywhere (out of performance concerns)....

16:06 I haven't used a single Typehint now for month now...

16:06 .. still no performance issues...

16:06 graphbum: Joy of Clojure had a good section on how typehints can cripple the compiler and hurt performance

16:08 tscheibl: in essence it's really best to start with the most simpe and general approach and spot optimize if you really hit performance problems (as it already has been said)

16:08 graphbum: seems like reflection is the enemy of performance, so you want to stamp that out. type-hinting java classes during interop seems to be an obvious case.

16:09 reiddraper: alexbaranosky: looks like it may be related to this: http://dev.clojure.org/jira/browse/CLJ-837

16:10 Okan: hello .. i have a problem on clojure emacs-slime lein instalation

16:10 i install lein in standalone bat file

16:11 can anybody help me.. i can share the error Message

16:11 Debugger entered--Lisp error: (error #("Could not start swank server:

16:11 \"C:\\Users\\OKan Aky】\\.lein\\self-installs\\leiningen-1.6.2-standalone.jar\" can not be found.

16:11 You can try running \"lein self-install\"

16:11 or change LEIN_JAR environment variable

16:11 or edit lein.bat to set appropriate LEIN_JAR path.


16:11 " 49 253 (charset japanese-jisx0208)))

16:11 signal(error (#("Could not start swank server: \n\"C:\\Users\\OKan Aky】\\.lein\\self-installs\\leiningen-1.6.2-standalone.jar\" can not be found.\nYou can try running \"lein self-install\"\nor change LEIN_JAR environment variable\nor edit lein.bat to set appropriate LEIN_JAR path.\n\n" 49 253 (charset japanese-jisx0208))))

16:12 error("Could not start swank server: %s" #("\n\"C:\\Users\\OKan Aky】\\.lein\\self-installs\\leiningen-1.6.2-standalone.jar\" can not be found.\nYou can try running \"lein self-install\"\nor change LEIN_JAR environment variable\nor edit lein.bat to set appropriate LEIN_JAR path.\n\n" 19 223 (charset japanese-jisx0208)))

16:12 (let ((debug-on-error t)) (error "Could not start swank server: %s" (with-current-buffer ... ...)))

16:12 clojure-jack-in-sentinel(#<process swank> "finished\n")


16:13 graphbum: Okan: where is leiningen-1.6.2-standalone.jar located on your system?

16:14 Okan: inside the c:\user\Okan AKyüz\..

16:15 graphbum: Okan: is LEIN_JAR setup as an environment variable pointing there?

16:15 Okan: or did you modify the path in the .bat file?

16:17 Okan: the path is conrect

16:17 my problem is my surname because it is turkish

16:18 graphbum: Okan: did you run "lein self-install" ?

16:18 Okan: yes i did

16:19 should i move the file and change any environment setup

16:19 graphbum: okan: is lein working by itself? can you do "lein repl"

16:20 Okan: i can run under cmd commond

16:20 i cant reach under emacs with clojure-jack-in

16:21 graphbum: okan: so lein is working fine

16:22 Okan: graphbum: lein is fine but swank

16:23 graphbum: okan: is it possible the characterset is messing with the path?

16:23 okan: or not being parsed properly

16:23 Okan: actually slime runs ccl common lisp fine too

16:25 pmooser: Has anyone managed to get colorized stack traces from swank-1.3.4 with just normal M-x slime-connect (as opposed to clojure-jack-in) ?

16:27 graphbum: okan: sounds like pmooser might be the dude to talk to. I am out of depth.

16:27 pmooser: Whaa ?

16:29 Okan: graphbum: i set the home environment and LEIN_JAR environment

16:30 my problem little bit changed

16:31 graphbum: pmooser: Okan was having trouble getting clojure hooked up in emacs-slime. given the context of your question, I figured you might be able to help.

16:33 pmooser: graphbum: It's reasonably challenging … I think the only real path for someone who doesn't use emacs regularly is try to use as much of the magical package.el stuff that technomancy provides to do their setup … As he describes here: http://technomancy.us/149

16:33 I don't have the option for doing that since at work we can't use leiningen, so I still have to figure out how to do things "the manual way", which is generally not straightforward.

16:35 Okan: i set the lein i guess

16:35 alexbaranosky: reiddraper, oh that looks very promising...

16:35 reiddraper, the link that is

16:35 Okan: i add HOME environment c:\lispemacs

16:36 reiddraper: alexbaranosky: yeah, i had a param called __meta, just changed it to `metad`. I have funcs that wrap the constructors anyway, so it doesn't really matter

16:36 graphbum: pmooser: I ditched and went with CCW/eclipse just to get functional.....although I have been lured by emacs. It's still a ways off for me.

16:36 Okan: i move the .lein folder which is under my user directory to c:\lispemacs\.lein

16:37 after that i set the LEIN_JAR

16:37 environment

16:37 pmooser: graphbum: Ah, hm. I can't use CCW for myself because its builder is slightly strange (to me) in that it seems to require an open REPL.

16:37 Okan: the current problem is swank does not recognize clojure.main()

16:37 pmooser: I'm actually trying to hack my own clojure builder for eclipse right now, but I know nothing at all about eclipse plugins, and it's not very fun.

16:38 graphbum: pmooser: yeah, you compile from the repl.

16:38 pmooser: graphbum: Yeh, our projects at work are largely java-based and I want a builder that doesn't require people who don't use clojure to know what a REPL is.

16:38 graphbum: pmooser: eclipse isn't great, but it's decent enough. CCW has gotten better over time. I'm not doing any huge projects though, mostly research software (no teams to deal with).

16:39 pmooser: got it.

16:39 pmooser: Okan: What do you mean that it does not recognize clojure.main ?

16:39 Okan: pmooser: error code is changed

16:40 Debugger entered--Lisp error: (error "Could not start swank server: java.lang.NoClassDefFoundError: clojure/main

16:40 Caused by: java.lang.ClassNotFoundException: clojure.main

16:40 at java.net.URLClassLoader$1.run(Unknown Source)

16:40 at java.security.AccessController.doPrivileged(Native Method)

16:40 at java.net.URLClassLoader.findClass(Unknown Source)

16:40 at java.lang.ClassLoader.loadClass(Unknown Source)

16:40 reiddraper: alexbaranosky: do you know if travi-ci has the lein-midje plugin?

16:40 Okan: at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)

16:40 at java.lang.ClassLoader.loadClass(Unknown Source)

16:40 Cou

16:40 pmooser: Okan, how are you trying to launch the swank server ?

16:41 alexbaranosky: reiddraper, I'v never heard of travi-ci

16:41 Okan: pmooser: i start lein like lein new prj

16:41 pmooser: under the emacs i C-d to change directory

16:41 triyo: In leiningen, I'm running `uberjar` and have my own log4j.xml file I wish included. However, my question is what happens when dependency libraries get included with their own log4j.xml files?

16:41 reiddraper: alexbaranosky: it's a continuous integration service for open source projects, http://travis-ci.org/

16:42 Okan: and after that clojere-jack-in

16:42 triyo: So question is will my own log4j.xml overwrite the lib ones?

16:43 pmooser: Okan: so you've previously done something like "lein plugin install swank-clojure.1.3.4", and then lein deps ?

16:44 Does just doing 'lein swank' from the command line work for you ? This certainly won't solve your problem but if you are having class path issues I'm curious if lein swank hits the same issues or not.

16:44 Okan: pmooser: let me try

16:44 triyo: And if not, can I indicate in project.clj for the dependencies to exclude the log4j.xml file?

16:45 alexbaranosky: reiddraper, probably doesn't have the plugin -- what would it take to set travis-ci to have it?

16:46 reiddraper, do you have any first impressions or feedback on Midje? I like to hear people's reactions to it -- what they like/dislike, what they miss, etc

16:47 reiddraper: alexbaranosky: actually just including lein-midje in the project.clj might be enough. I'm not sure if it will be able to "interpret" the output though. Maybe it just uses exit code?

16:47 alexbaranosky: i've only written one test so far, but my first impression is that midje is _very_ well documented

16:50 alexbaranosky: ever see this in a test? java.lang.Boolean cannot be cast to clojure.lang.IReference

16:53 alexbaranosky: calling alter-meta! or reset-meta! on a boolean it sounds like ???

16:53 lazybot: alexbaranosky: Oh, absolutely.

16:53 alexbaranosky: reiddraper, by test do you mean fact?

16:53 reiddraper: yes

16:53 alexbaranosky: https://gist.github.com/a550086d332419c55dbc

16:55 pmooser: Okan, any luck ?

16:56 triyo: Ok it actually seems that leiningen will prefer the resources from my project as oppose to the dependencies resources.

16:57 alexbaranosky: reiddraper, I'm not sure what that is

16:57 reiddraper, does it run fine without the with-test?

16:57 reiddraper: alexbaranosky: ah, yep

16:57 hmm

16:58 triyo: so if I have a log4j.xml file, it will prefer it to the dependency lib one when performing uberjar.

16:59 alexbaranosky: reiddraper, I've never used with-test, but looking at the source it seems to expect a body argument to be passed

16:59 reiddraper, http://clojuredocs.org/clojure_core/clojure.test/with-test

16:59 reiddraper, and voila with-test uses alter-meta!

17:00 ahhhhhhhhhh the fact is evaluating to false/true

17:00 and then the macro tries to alter the meta of that

17:00 reiddraper, and thus the exception you're seeing

17:01 reiddraper: ah, yep, that makes sense. I'll see if I just can't get lein midje to work on travis-ci

17:01 so i don't have to wrap with with-test

17:02 pmooser: OK, well, good luck Okan.

17:02 alexbaranosky: reiddraper, cool, keep me posted on the travis-ci stuff

17:03 wingie: what systems are clojure a good fit too and why shouldn't i use node.js?

17:04 technomancy: wingie: evented IO is really only appropriate for a very small set of computationally-nonintensive problems

17:06 edbond: Someone has example of using gloss with files?

17:10 dnolen: wingie: Clojure is a general purpose programming language. It's good for pretty much anything. JVM startup time makes it less than ideal for simple scripting. But you could of course compile to JS w/ ClojureScript and target node.js for that ;)

17:11 yoklov: what is the equivalent of progn or begin (in other lisps) for clojure?

17:12 (those do a bunch of things in order.)

17:12 dnolen: yoklov: do

17:12 yoklov: ah, thanks.

17:14 wingie: dnolen: i read about clojurescript .. is it considered ready?

17:16 technomancy: what intense task would be a good fit for clojure? (can't find anything for me to test it with since im using node.js for web stuff)

17:18 technomancy: wingie: the evented approach is well-suited for tasks that consist of just routing traffic from one socket to another. everything else needs more flexibility.

17:19 wingie: technomancy: yeah im using it as web backend between web app and db

17:19 but cant figure out what else i would need

17:20 perhaps i have no need for clojure yet

17:20 but i wanna use it for something :)

17:22 dnolen: wingie: it's alpha, but it's already useful.

17:23 wingie: dnolen: the only reason for using it would be the scripting flexibility since java has a long start time?

17:23 dnolen: wingie: clojure is equally suited for web stuff. IMHO Clojure is a superior language over JavaScript (and I've been doing JS for a long time)

17:24 wingie: yes

17:25 wingie: dnolen: yeah it seems very capable

17:26 and you learn a lot about proper programming

17:26 you could easily generate bad code in js

17:26 cs (coffeescript) helps a little

17:28 dnolen: wingie: you can generate bad code in Clojure as well. But I think Clojure has saner, simpler semantics and a richer feature set.

17:28 wingie: dnolen: it just seems that when i read js book they don't talk as much about proper coding

17:29 why i wanna learn clojure's fp

17:30 reiddraper: alexbaranosky: got it working, http://travis-ci.org/#!/reiddraper/knockbox

17:31 alexbaranosky: reiddraper, that's really cool, I'll have to check out travis-ci sometime

18:00 wingie: should impure functions be tested too?

18:01 amalloy: "should x be tested" => yes for all x

18:01 technomancy: impure functions need a lot more tests than pure ones

18:23 yoklov: Hrm, should ``for'' be able to iterate over sets?

18:23 Crap, nevermind.

19:23 yes! my code works now!

19:23 https://gist.github.com/1548720

19:24 is that code, uh, good style for clojure code?

19:25 i feel like i am swap!ing too many things

19:25 scottj: yoklov: alignment formatting is uncommon and would be a burden for other people to maintain.

19:26 yoklov: alignment formatting?

19:26 amalloy: yoklov: your let bindings have the valeus lined up

19:26 scottj: (def foo {:bar...) too

19:26 yoklov: oh, right

19:26 amalloy: a style i mostly don't care for, but i do have a hacked version of align-let.el that works on clojure's let

19:27 yoklov: hm, thats sorta a thing i do in almost all code i write

19:27 It's uncommon in clojure?

19:27 scottj: https://github.com/scottjad/align-cljlet

19:28 adds align-map and align-defroutes

19:29 amalloy: yoklov: i mostly like the approach, and it seems like you're making an effort to minimize mutable state

19:29 or localize it, at least

19:29 yoklov: yeah

19:29 scottj: actually origin looks better now https://github.com/gstamp/align-cljlet (except align-defroutes)

19:30 amalloy: but you don't need the food/snake atoms at all - you can have tick return a food/snake pair instead of modifying the atoms

19:30 yoklov: i just use align-regex usually

19:30 really?

19:30 hm

19:31 but then i'd have to change the key-event to work differently

19:31 and the drawing

19:31 which I couldn't figure out how to do so i went with mutating the atoms

19:32 amalloy: well, fair enough

19:32 yoklov: well no, i'd love to ditch the atoms, if you can suggest the way to have that not happen.

19:33 amalloy: because you need it to work in paint(), you do need at least one atom somewhere. my preference would probably be to have that atom be a map (or pair) of snake/food, and deref it before you pass it into anything but paint

19:33 yoklov: and swap it after tick?

19:34 that still doesn't really handle the keypress though

19:37 amalloy: we've made the whole world into a single atom; it's easy for keypress to change the direction

19:38 also, the way you're using @ and swap! a million times in a single function is not safe at all. if this code were actually called from multiple threads you'd quickly lose integrity. it won't be, because swing only calls you from the dispatch thread

19:39 but if you make the whole world an atom, and then swap! it with a single function that makes all the necessary changes, that problem disappears as well

19:39 yoklov: i see.

19:39 * yoklov goes about changing things

19:41 reiddraper: alexbaranosky: are there any examples of programmatically generating tests in midje?

19:47 alexbaranosky: reiddraper, what do mean exactly by programmatically?

19:47 you could use `tabular` or a macro

19:49 reiddraper: alexbaranosky: I've got some test I'd like to test on some list of input, and i'd like to see them pass/fail separately. looking at tabular now

19:49 alexbaranosky: tabular sounds like what you want

19:49 it will give you sane output, letting you know which example failed

19:50 reiddraper: do you have any examples of generating tests with macros?

19:50 i'm kind of a macro noob

19:50 alexbaranosky: nope, I never use them, tabular always does what I want :)

19:51 reiddraper: alexbaranosky: thanks

19:51 alexbaranosky: tabular is 'basically' a macro that makes a fact for each row of the table

19:52 reiddraper: cool, it's looking like what I want

20:00 alexbaranosky: any way i can use (let) in tabular?

20:02 alexbaranosky: have you tried it?

20:02 you can always (I think) wrap the whole tabular form in a let

20:03 reiddraper: got it figured out, i was accidently including the table in my let sexp

20:06 alexbaranosky: a set-based Game of Life implementation: https://github.com/AlexBaranosky/GameOfLife/blob/master/src/retreat1/core.clj

20:07 where the 'cells' are people

20:10 mrb_bk: dnolen: playing with core.match, it's a lot of fun

20:14 alexbaranosky: reiddraper, I"m looking forward to see a proposal of what quickcheck-like testing via Midje might look like

20:15 reiddraper: alexbaranosky: cool. I need to give it some more thought, and play with the Erlang implementation more

20:15 but will do

20:17 alexbaranosky: reiddraper, in general I really like to hear feedback on what works/sucks/is-missing from Midje - it helps me think about improvements

20:18 reiddraper: alexbaranosky: Great. I'm sure I'll have more opinions once I've used it a bit more

20:36 yoklov: alright

20:36 only one atom now

20:36 https://gist.github.com/1548720

20:37 technomancy: alexbaranosky: are you leading up the development of midje these days?

20:37 yoklov: if anybody has any suggestions on how to make that code any better, i'm very interested :)

20:38 alexbaranosky: technomancy, It's basically me and Brian Marick, but Marick's really busy and doesn't do as much as he did in the past

20:38 technomancy: sure

20:41 reiddraper: anyone using deftype find themselves having to use `lein clean` to get new code to run, even without AOT?

20:41 wiseen: Can someone help me figure out how to invoke this function http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind...) ?

20:41 I keep getting java.lang.IllegalArgumentException: No matching method found: register for class sun.nio.fs.UnixPath

20:41 amalloy: why do you have count in your main-loop at all? you never use it

20:43 yoklov: oh, thats let over from debugging

20:43 amalloy: it seems to me it would also lead to nicer code if you represented x/y coordinates as a [y x] pair (or i guess [x y] if you prefer) instead of having to do all this pulling-apart and rebuilding of an x/y map

20:43 yoklov: i uh, forgot it was there, to be honest

20:43 hm

20:43 thats a good point

20:43 wiseen: I tried : (.register dir service (into-array WatchEvent/Kind [StandardWatchEventKinds/ENTRY_CREATE StandardWatchEventKinds/ENTRY_DELETE StandardWatchEventKinds/ENTRY_MODIFY])) and simply passing event kinds as varargs but each time I get the exception

20:43 amalloy: for example, you could do stuff like ##(let [north [-1 0], pos [8 3]] (map + north pos))

20:43 lazybot: ⇒ (7 3)

20:44 amalloy: and write [(dec y) x] instead of {:x x :y (dec y)}

20:45 (case (rand-int 4) 0 :n, 1 :s, 2 :e, 3 :w) => ([:n :s :e :w] (rand-int 4)), fwiw. nitpicky stuff

20:45 yoklov: yeah, i'm sort of blown away by (map +) haha

20:46 amalloy: yoklov: you can use a similar map trick to do bounds-checking

20:47 yoklov: something like (map < [0 0] [x y] [width height])?

20:48 amalloy: right

20:48 https://gist.github.com/1548959 is a snippet from one of my 4clojure solutions using that technique

20:50 yoklov: thats very clever

20:52 alexbaranosky: wiseen, I think the problem might the overloaded method

20:54 wiseen: alexbaranosky, yeah but how do I tried to add a dummy argument for the second overload : nil and (into-array WatchEvent/Modifier [])

20:54 still get the exception

20:55 is there a way to specify the overload explicitly ?

20:55 alexbaranosky: wiseen, I saw a solution to this issue a while back, but cfan't recall it

20:56 I distinctly recall cemerick had the solution, but he isn't online now

20:57 wiseen, maybe this'll help http://stackoverflow.com/questions/2722856/how-do-i-call-overloaded-java-methods-in-clojure

20:58 wiseen: alexbaranosky, saw that :) it's about boxing - that doesn't seem to be my problem since none of the types I'm passing to the function are value types

20:58 amalloy: wiseen: WatchEvent/Kind shouldn't be a valid thing. you mean WatchEvent$Kind?

20:58 wiseen: amalloy, nope , let me try that

21:01 amalloy, tnx. that fixed it

21:01 amalloy: tbh i don't know how WatchEvent/Kind compiled at all

21:01 wiseen: yeah, just goign to say that, it didn't complain about that

22:43 graphbum: is there an idiomatic way to serialize a record?

22:43 as a string that can be evaluated with (read-str)

22:43 amalloy: use 1.3

22:43 graphbum: err read-string

22:45 do the record structures just "work" in 1.3? if I (= myrecord (read-string (print-dup myrecord))) evals to true?

22:47 amalloy: yes

22:47 though i don't know why you're calling print-dup instead of just pr-str

22:48 graphbum: because I am ignorant

22:49 and behind on versions

22:49 thanks

23:12 lnostdal: ... :( sometimes all this cool stuff seems worthless when core stuff doesn't work .. stack-traces that doesn't make sense or even end up outside the debugger because heaven-forbid you're using futures or agents or whatever -- with no stack-frame data for variables etc. ..

23:16 graphbum: I haven't been screwed over by agents yet, but I haven't been using them too much. I hear you on the funky stack traces.....you develop a sixth sense about what errors "really" mean for some things.

23:26 bitops: hi all, clojure newcomer here - I'm playing around at the repl but having some trouble requiring libraries. If I plug in the code at the top of http://richhickey.github.com/clojure-contrib/generic.math-functions-api.html#clojure.contrib.generic.math-functions/pow I get an error. I'm using Clojure 1.3 if that's any help.

23:26 lazybot: Nooooo, that's so out of date! Please see instead http://clojure.github.com/clojure-contrib/generic.math-functions-api.html#clojure.contrib.generic.math-functions/pow and try to stop linking to rich's repo.

23:27 bitops: haha

23:27 it's unfortunate that rich's repo is at the top of google...

23:30 hm…after looking at the pages, maybe I should change my question.

23:30 how do I call the power function? I want to raise some number to another number.

23:30 technomancy: ,(Math/pow 12 3)

23:30 clojurebot: 1728.0

23:31 bitops: technomancy: there's no Clojure pow function?

23:37 n0i: newp, alot of basic stuff like that is still missing from core.. have to go to java for it or write your own

23:38 graphbum: or wrap it

23:39 bitops: no biggie

23:39 it's actually pretty fun to wrap stuff up…learning a lot

23:39 graphbum: I actually went quite a while without running into that, until I sat flabbergasted at one point (trying to write a simulated annealing function) and I couldn't find exp

23:40 amalloy: "still missing" in the sense that there's no real reason to write it. in a hosted language there's really no reason to write strlen again, for example

23:40 technomancy: amalloy: welllll

23:40 Math/pow only returns doubles

23:40 which is why generic-math was written

23:40 graphbum: no ratios

23:40 amalloy: yeah, i agree having a real exp would be nice

23:41 but to say that there's "a lot" of stuff that's "still missing" overstates the case

23:41 graphbum: basic stuff....which requires delegation to the host language

23:44 amalloy: btw technomancy, the way i found the apt package: $ apt-file find -x completion.*git

23:45 bitops: I suppose one could argue that Clojure sort of encourages you to delegate to JavaLand - lots of neat stuff to use there.

23:46 oh, but I'm reminded, so….what's the best way to require stuff? Looking at http://dev.clojure.org/display/doc/Clojure+Contrib it seems much has changed?

23:47 fair to assume that everything in core is auto-required on repl load?

23:52 technomancy: bitops: all of the clojure.core namespace, yeah

23:53 bitops: technomancy: that makes sense - I'll be darned if I can require numeric tower though

23:54 (require '[clojure.math.numeric-tower]) ;; is incorrect?

23:57 …..anyone?….. :)

23:57 technomancy: that should work if it's in your project.clj

23:57 graphbum: bitops, how are you running your repl?

23:58 bitops: graphbum: I'm just starting it via rlwrap java -cp /Users/sebastian/bin/clojure-1.3.0/clojure.jar clojure.main

23:59 (rlwrap just for line editing)

23:59 technomancy: I'm not running in a lein project

23:59 just plain old repl

23:59 does that make the difference?

Logging service provided by n01se.net