#clojure log - Jan 26 2011

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

3:06 TobiasRaeder: morning

3:12 Scriptor: morning TobiasRaeder

5:28 edoloughlin: I keep getting a notice from sexpbot saying I have a new message and should 'use the mymail or mail commands without'. Excuse my ignorance, but what on Earth is this?

5:31 mrBliss`: edoloughlin: have a look at https://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/mail.clj

5:33 edoloughlin: mrBliss: Sorry, I've been a developer since 1992 but never used IRC for whatever reason until I started using Clojure. How do I send a command to sexpbot?

5:35 mrBliss`: edoloughlin: I think it is "/query sexpbot", but I'm not sure.

5:35 edoloughlin: Thanks

6:01 Leonidas: I have a global configuration (immutable) that I want to read from a JSON file and access in all functions. what is the best way to handle this? global variable? parameter to each function? a dynamically bound variable?

6:09 ejackson: Leonidas: I think a dynamically bound variable is the accepted answer, but not sure.

6:10 Leonidas: ejackson: I am thinking about posting it on the mailing list as it is not a technical problem but rather one of various pros and cons.

6:10 ejackson: I think if you search the IRC logs first, you'll find this discussed before

6:11 clgv: Leonidas: I made a configuration Object but also played with the thought of dynamically bound variables

6:11 ejackson: in fact, I'm almost certain of it

6:11 Leonidas: ejackson: the problem is, I don't know the proper search terms to get any useful results

6:39 AWizzArd: ~seen rhickey

6:39 clojurebot: Pardon?

6:39 AWizzArd: $seen rhickey

6:39 sexpbot: rhickey was last seen quitting 2 weeks and 1 day ago.

6:43 ejackson: sexpbot: rhickey is not a quitter - how DARE YOU SIR !

6:49 clgv: lol!

7:05 Leonidas: http://paste.pocoo.org/show/327135/ why does this fail in json-read? I thought json-read returns the value when encountering an EOF?

7:08 clgv: A tricky question: when I open a repl in code that runs in the java Swing GUI thread I get an exeption that I am not allowed to use (in-ns) - does someone know why?

7:09 it's the debug-repl of George Jahad and Alex Osborne

7:09 raek: are you running a repl session in the swing thread?

7:09 won't that block all gui events?

7:18 clgv: yes it will. it is a debug-repl to see why certain GUI code fails ;)

7:19 Leonidas: fun, I ran into a read-json bug

7:19 http://dev.clojure.org/jira/browse/CONTRIB-99

7:19 clgv: it works in general but I cant change the namespace to the surrounding ns of the macro with (in-ns)

7:25 The exceptions says: Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Can't change/establish root binding of: *ns* with set

7:25 raek: I though that bug had been fixed

7:25 http://dev.clojure.org/jira/browse/CONTRIB-91

7:30 there is a patch for it, but maybe it never got in...

8:26 Leonidas: get-votes-and-filter (fn [line] (remove (fn [[k v]] false) (get-votes line)))

8:26 this always fails with clojure.lang.LazySeq cannot be cast to clojure.lang.Associative. Why?

8:26 the remove-call should be a no-op

8:29 timvisher: hi all

8:30 AWizzArd: Hi timvisher.

8:32 timvisher: is there an easy way to write compound filters? i.e. (filter (and #(.isFile %) (complement #(.isHidden %))) ...)

8:33 possibly even a filter that works on a #{} of predicates?

8:35 l0st3d: timvisher: as in (filter #(and (.isFile %) (not (.isHidden %))) ...) ?

8:36 timvisher: l0st3d: you know, I had a tickling feeling at the back of my skull that all I'd have to do was make the whole and a function...

8:37 thanks!

8:37 still new at this. :)

8:37 Leonidas: (fn [line] (remove (fn [[k v]] false) (get-votes line))) why does calling this result in a clojure.lang.LazySeq cannot be cast to clojure.lang.Associative error?

8:37 l0st3d: timvisher: me too ;)

8:38 clgv: timvisher: though a (filter-all #{ .isHidden isFile } ...) would be nice too ;)

8:38 l0st3d: timvisher: there's something called comp that will compose fns for you

8:38 clgv: s/#{ .isHidden isFile }/[.isHidden .isFile]/

8:43 raek: Leonidas: what happens if you just eval (get-votes line)?

8:44 Leonidas: raek: {"Foo" {:upvotes 0 :downvotes 1}}

8:45 strange things happen

8:45 raek: ,(fn [] (remove (fn [[k v]] false) {"Foo" {:upvotes 0 :downvotes 1}}))

8:45 clojurebot: #<sandbox$eval628$fn__629 sandbox$eval628$fn__629@e5590e>

8:45 raek: ,(remove (fn [[k v]] false) {"Foo" {:upvotes 0 :downvotes 1}})

8:45 clojurebot: (["Foo" {:upvotes 0, :downvotes 1}])

8:46 raek: I think the problem is somewhere else..

8:46 Leonidas: yeah, there is a [ ] there

8:46 where does the vector in the result come from?

8:47 raek: it's actually a MapEntry

8:47 they implement IPersistentVector

8:47 ,(seq {:a 1, :b 2})

8:47 clojurebot: ([:a 1] [:b 2])

8:47 Leonidas: I wanted to remove items which fail a certain perdicate from a dict, but what remove does is something... else.

8:48 is there a way how I can get a map out?

8:48 raek: ,(let [m {:a 1, :b 2}] (into (empty m) (remove (fn [[_ v]] (odd? v)) m)))

8:48 clojurebot: {:b 2}

8:49 raek: this will also the preserve the map type (hash-map/sorted-map)

8:50 Leonidas: what is the point of this strange behaviour?

8:51 raek: what behaviour?

8:51 remove operates on sequences. it automatically calls seq on its argument to get a sequence for it.

8:52 Leonidas: that mapentries get generated? I thought that when I 'remove' on a map I get a map of the same shape out

8:52 raek: it could be possible that they are the same map enties used internally in the map

8:53 conj, into, disj, pop, peek are polymorphic and return a datastructure of the same kind

8:53 the sequence functions are seq-in seq-out

8:54 Leonidas: ah, hmm, I see. Much I have to learn, still

8:56 raek: (seq x) for data structure -> sequence and (into (empty x) ...) for sequence -> data structure lets you use the same functions for any type

8:58 zippy314: Hi, I'm looking on thoughts on best practices in Clojure for handling inheritance. I've been reading The Joy of Clojure on prototyping and UDP, and I've implemented a few protocols/records. What I think I'd like to do is create a record/type that mixes in new methods, and can itself be inherited from. But I'm wondering if anybody have any pointers to best-practices/idiomatic ways of doing this in clojure?

9:02 ejackson: zippy314: i don't think it can be done. I tried before and ended up using macros to kludge it. However the more skilled present may know otherwise.

9:03 clgv: zippy314: afaik there is no such thing as inheritance between types or records in clojure.

9:04 zippy314: cigv: ejackson: is that because it shouldn't be done in clojure because there's a better way to accomplish the same functionality, or because it's a limitation of clojure? That's what I'm trying to figure out.

9:05 ejackson: ah, its not possible in clojure, deliberately I think.

9:06 zippy314: I'm reading in the docs this: "Concrete derivation is bad" (http://clojure.org/datatypes) and I'm trying to wrap my head around that.

9:06 and also this "Tying polymorphism to inheritance is bad"

9:07 clgv: in general you can use a written function on every data that has the "attributes" that are need by the function

9:08 timvisher: i'm getting a weird issue when I try to run `lein test`.

9:08 clgv: you can do dispatch via multimethods

9:08 timvisher: it's saying that `to-file-name-suffix` cannot be resolved

9:08 zippy314: Yah. It looks like since you can simply define a record based on multiple protocols, that you can get the same effect just by mixing in lots of interfaces into one record.

9:08 timvisher: but `to-file-name-suffix` occurs nowhere in the code

9:09 it used to, but I recently renamed it

9:09 zippy314: timvisher: you might need to do 'lein clean'

9:09 timvisher: zippy314: just had that idea. tried it and it didn't make a difference

9:10 raek: maybe ~ files lying around

9:10 zippy314: timvisher: also, maybe unsaved file so your search works, but on disk it's different

9:11 timvisher: Ah!

9:11 I'm i'm an idiot as usual

9:11 the core.clj file the error is referring to is my now _stale_ test/core.clj

9:11 :)

9:11 thanks as always, everyone

9:25 no_mind: which is a good tutorial for starting web development with clojure ?

9:26 dnolen: no_mind: http://mmcgrana.github.com/2010/03/clojure-web-development-ring.html

9:26 no_mind: thnxs

9:35 when I run lein deps , it downloads clojure and clojure-contrib forr every new project. is there a way I can avoid this ?

9:36 jkdufair: I'm a longtime emacs user and have some decent exposure to clojure. I'm on windows and want to set up a production grade development env with Emacs/swank/lein. Recommendations re: native vs. cygwin?

9:36 ejackson: hmm, I thought it would pull them from your ~/.m2

9:37 jkdufair: I did this, but was painful. I used the powershell for lein etc, and normal emacs. I think cygwin should work too, but I had COM stuff in the mix that prevented me from doing it.

9:38 jkdufair: ejackson: thx. i'm leaning toward cygwin and have had some success so far, but just a bit of weirdness with lein

9:39 ejackson: yes, that's where I spent most of my time gnashing my teeth. There is a port for the script to powershell which worked fine.

9:39 if maven works I'd suggest you just use that

9:40 jkdufair: you prefer maven over lein?

9:40 ejackson: yeah

9:40 jkdufair: pros/cons?

9:40 ejackson: maven has plugins for a bunch of stuff that i do and integrates nicely with my CI

9:41 jkdufair: cool. thx

9:41 ejackson: the XML is a pain intially, but nothing dramatic.

9:50 shortlord: I have written 2 functions and now want to use them from another namespace. Both functions use a lookup table as an argument, this lookup table is defined in their namespace. What is the most functional way to use these 2 functions now? using both functions + the lookup tables and always passing these tables in other namespaces sounds like a bad idea. Should I make some light wrappers in the original namespaces that supply th

9:50 e lookups automatically?

9:54 ejackson: shortlord: I dunno why passing the lookup is a bad idea. But, if you arrange your argument order correctly you could partial over the lookup tables perhaps ?

9:54 for you wrapper that is

9:54 tonyl: can you just require the ns where your fns and lookup tables in the current ns you want to use them?

9:54 shortlord: ejackson: yep, building the wrapper is easy, the lookup table is the first argument

9:55 ejackson: well, that seems reasonable, i guess.

9:56 shortlord: tonyl, ejackson: well, my problem is this: When should I use a wrapper/closure and when should I supply all the arguments every time? I'm pretty sure that the lookup table won't change for the whole application, but just wrapping the function does not seem to be very functional/pure

9:57 I could of course just use the functions without a wrapper, but that would mean that I'd need to pass more arguments every time that I call such a function

9:57 ejackson: I think a partially applied function is very functional indeed

9:58 tonyl: then i agree with ejackson, it seems that that would benefit you

9:59 shortlord: ejackson: so where should I put this partial function? just defn a function in the namespace that uses the original function with the same name and just a (partial lookup-table old-function)?

9:59 ejackson: yeah

9:59 shortlord: or should I put this wrapper function in the old namespace, where both lookup tables and functions are contained?

10:00 ejackson: sorry, the latter. put it in the original namespace

10:00 shortlord: ejackson: ok. Is there any standard name scheme for simple wrapper functions? like wrapped-<function-name> or something like that?

10:01 ejackson: no, I'd go with something like standard

10:01 standard-<function>

10:01 of default-<function>

10:01 but there is no reason to suspect that this is in any way more than my own opinion

10:04 shortlord: ejackson: ok, thx a lot :)

10:14 is it possible to use something like :as in the namespace definition to rename functions in a :use expr? like (:use [clojure.set :only (difference :as diff)])?

10:15 mattmitchell: anyone know a nice way to convert a hash-map with string values to keyword values?

10:15 Chousuke: I think you need another vector

10:15 ie. :only ([difference :as diff])

10:16 but I'm not sure, so check the docstring on use

10:17 mattmitchell: (into {} (map (fn [[k v]] [(keyword k) v]) original-map)) is probably the shortest way without any extra functions.

10:18 mattmitchell: Chousuke: excellent thanks!

10:18 Chousuke: note though that that may produce illegal keywords

10:18 if the strings have spaces in them for example

10:19 if you have string keys, it's often best to just keep them that way :)

10:20 mattmitchell: Chousuke: yes ok. the values are coming from a yaml file, so always come in as strings but will only ever be valid keywords

10:26 momos: Hello. How to check / modify classpath in clojure?I'm trying to write a cake task which uses my project dependent jar's, but my normally working code fails to import java dependencies. How to debug this?

10:28 mattmitchell: How can I make a "public" defonce or def? I'd like my other namespaces to have access to this value.

10:29 tonyl: def is public

10:29 just either require the namespace where the binding is

10:30 require or use whichever form fits you best

10:30 mattmitchell: tonyl: oh i see. so i can't just go into a diff namespace and call the other like (other/some-def) ?

10:31 tonyl: ahh ok i got it! it's not a function :)

10:31 tonyl: thanks

10:32 tonyl: yes, and it could be a function or a special case in the ns form whichever you prefer

10:32 mattmitchell: tonyl: ok i see

10:35 LauJensen: Chousuke: I prefer reduce ##(reduce #(assoc %1 (keyword (%2 0)) (%2 1)) {} {"string" 5 "str" 10})

10:35 sexpbot: ⟹ {:str 10, :string 5}

10:59 symuyn: Let's say that I have a map: string keys → vectors of string keys.

11:00 So it represents a directed network, and loops are allowed. If a vector contains a string A, the vector’s own key is connected *to* A.

11:00 I want to create another map: string keys → sets of string keys, such that the sets only contain all of the string keys that are directly connected to it (but not from it)…including the key itself.

11:00 (Eventually, I’d like to be able to calculate the keys’ distances too, but that can be later.)

11:00 I can't think of a good way to start, though. Is there a library or simple function that can help me?

11:01 ejackson: does to-from make any sense in an looping network ?

11:01 symuyn: I believe so

11:01 Think of recursive functions

11:01 ejackson: A -> B -> C -> A

11:02 is C connected to or from A ?

11:02 symuyn: Oh dear, I think I typoed: "If a vector contains a string A, the vector’s own key is connected *from* A."

11:02 ejackson: well, both

11:02 symuyn: Hmm

11:02 ejackson: Yes, both. Which it will always be, in a loop

11:03 hoggarth: symuyn: does this help? http://richhickey.github.com/clojure-contrib/graph-api.html

11:04 symuyn: hoggarth: Do you know the data format that the library's graphs are supposed to be in? I can't find it.

11:04 How do you make a graph?

11:05 ejackson: symuyn: this might throw you off course, but I made a little dijstra toy algo last year. https://github.com/ejackson/dijkstra/blob/master/src/main/clojure/net/edmundjackson/astar.clj It makes graph, connects nodes etc, might be helpful. </end blowing own's trumpet>

11:06 hoggarth: :nodes ; The nodes of the graph, a collection

11:06 :neighbors)

11:06 oops

11:06 symuyn: (defstruct directed-graph

11:06 :nodes ; The nodes of the graph, a collection

11:06 :neighbors)

11:06 symuyn: hoggarth: I see, a struct.

11:06 Pity it doesn't show up on the documentation.

11:06 ejackson: I'll look at that, thanks

11:06 mec_: Is there a good way to filter for unique values while keeping the sequence in order?

11:06 ejackson: of course, cgrand has one too: http://clj-me.cgrand.net/

11:07 tonyl: mec_: has it happened to you otherwise?

11:08 chouser: (doc distinct)

11:08 clojurebot: "([coll]); Returns a lazy sequence of the elements of coll with duplicates removed"

11:08 chouser: mec_: ^^^

11:08 tonyl: but if you want unique values, maybe hash-set's or sorted-sets' would work for you

11:09 mec_: yes but they need to remain the way they are ordered, sets will change order

11:09 chouser: thanks a bunch

11:09 ejackson: distinct ! cool.

11:10 symuyn: hoggarth: Yes, this will do; I can't use the library directly, but it shows me how

11:10 Thanks a lot

11:10 mec_: i seem to always pick the wrong synonym for what i want

11:11 chouser: mec_: note that if you walk to the end of the seq returned by distinct, you will end up with the whole (non-dup) collection in memory, even if you aren't holding the head of the seq

11:12 shortlord: there is no built-in operator that does the opposite of 'frequencies', so (map #(repeat (val %) (key %)) my-map) would be the easiest way, right?

11:12 (+ a flatten in front of it)

11:13 mec_: chouser: that should be fine

11:14 symuyn: What is the hash code of a lazy sequence? What happens when it's used as a hash map's key?

11:16 tonyl: &(hash (range))

11:16 sexpbot: Execution Timed Out!

11:16 tonyl: mm good quesiton

11:16 *question

11:18 symuyn: Seems kind of weird

11:19 tonyl: not necessarily it needs to know the values of the lazy-seq to make a hash of it, so the values are trying to be realized

11:19 chouser: shortlord: mapcat instead of map

11:20 symuyn: &(count (assoc {} (range) 1 (range) 2))

11:20 sexpbot: Execution Timed Out!

11:20 symuyn: So it tries to fully evaluate

11:21 tonyl: yes, that is my understanding of hashcode in java, but it's been a while

11:21 chouser: a lazy seq hashes to the same as a list or vector with the same contents, so it has to realize the whole thing

11:22 shortlord: chouser: how would mapcat help there? It is only one map that I want to transform into one seq

11:22 chouser: shortlord: then you don't need the flatten or a concat

11:25 shortlord: chouser: you mean like (mapcat repeat (vals foo) (keys foo))?

11:27 chouser: sure, or (mapcat #(repeat (val %) (key %)) foo)

11:27 shortlord: chouser: nice solution, thx

11:28 chouser: I dislike flatten, and (apply concat (map ...)) always suggests (mapcat ...)

11:30 symuyn: flatten does seem a little inefficient

11:31 chouser: well, it's a big hammer

11:31 ,(mapcat #(repeat (val %) (key %)) {:a 2 :b 2 [:c :d] 3})

11:31 clojurebot: (:a :a :b :b [:c :d] [:c :d] [:c :d])

11:31 chouser: ,(flatten (map #(repeat (val %) (key %)) {:a 2 :b 2 [:c :d] 3}))

11:31 clojurebot: (:a :a :b :b :c :d :c :d :c :d)

11:32 chouser: if it's actually what you want, fine, but in my experience it rarely is.

11:38 pdk: (doc xor)

11:38 clojurebot: Gabh mo leithscéal?

11:38 chouser: (doc bit-xor)

11:38 clojurebot: "([x y]); Bitwise exclusive or"

11:39 pdk: i was thinking logical xor to use alongside or/and but hey

11:40 chouser: yeah, I don't think Clojure's got that

11:40 pdk: funky

11:41 chouser: it couldn't short-circuit or do anything useful varargs like or/and

11:51 zippy314: is there a way to give defrecord a doc string so that it will show up in autodoc?

11:54 tonyl: zippy314: AFAIK there isn't

11:54 zippy314: hmmm gripe.

11:56 mec_: ,(str (doall (range 10)))

11:56 clojurebot: "clojure.lang.LazySeq@9ebadac6"

11:57 chouser: zippy314: usually the public face of a defrecord is a factory function, which can of course have a docstring

11:57 ,(pr-str (range 10))

11:57 clojurebot: "(0 1 2 3 4 5 6 7 8 9)"

11:57 zippy314: chouser: right!

11:58 mec_: ah that works, but what am i thinking wrong about doall?

11:59 chouser: str and pr-str do the same thing in a lot of cases. strings and lazy-seqs are a couple of the relatively few exceptions

11:59 ,((juxt str pr-str) [1 2 [3 4] '(5 6)])

11:59 clojurebot: ["[1 2 [3 4] (5 6)]" "[1 2 [3 4] (5 6)]"]

11:59 chouser: ,((juxt str pr-str) "hi")

11:59 clojurebot: ["hi" "\"hi\""]

12:00 pdk: is there a way to capture a full java stack trace say to a file

12:00 vs having it print to the command line and get cut off

12:03 zakwilson: danlarkin: that NoSQL presentation you posted last night was interesting. When put in the terms the presented used, it seems likely that I do have a single question I usually want to answer and Mongo is probably a good fit for the problem.

12:03 tonyl: maybe binding *err* to a reify'ed PrintWriter and change the method that outputs to write to a file

12:03 zakwilson: s/presended/presenter

12:04 tonyl: pdk: ^^ just the first thought that came to me

12:04 so it might be wrong

12:04 zippy314: pdk: (binding [*err* (java.io.PrintWriter. (writer "/your/file"))]

12:05 danlarkin: zakwilson: cool, I'm glad you found some value from it, and glad you've come to an evidence-based conclusion :)

12:05 tonyl: simpler zippy314

12:05 zippy314: :pdk, then (.printStackTrace e *err*)

12:06 zakwilson: And if I'm lucky, scaling will be a concern.

12:06 symuyn: Another question! Pre- and post-condition are idiomatic, and that Clojure style guides says they're supposed to be ubiquitous.

12:06 Is there any way to turn them off, though?

12:07 (When you're not debugging, for production runs)

12:10 mattmitchell: is it possible to "use" namespace B in namespace A, then from namespace C, access the B functions "through" A?

12:12 ohpauleez: mattmitchell: Take a look at potemkin

12:13 Typically, what you're asking for you wouldn't do, but potemkin allows you to man-handle the namespaces and imports

12:14 mattmitchell: ohpauleez: oh cool ok. that's exactly what i'm looking for.

12:14 ohpauleez: You would normally just use, B and A in C. I personally prefer require, or use-only so that it's clearly documented what I'm using, and where it came from.

12:14 mattmitchell: awesome! Glad I could help

12:14 mattmitchell: ohpauleez: ok so another related question, is it possible to define a function in a different namespace?

12:15 ohpauleez: mattmitchell: http://clojuredocs.org/clojure_core/clojure.core/in-ns

12:16 actually, with-ns is probably what you want

12:16 &(doc with-ns)

12:16 sexpbot: java.lang.Exception: Unable to resolve var: with-ns in this context

12:16 ohpauleez: it's in contrib

12:17 mattmitchell: http://clojuredocs.org/clojure_contrib/clojure.contrib.with-ns/with-ns

12:17 mattmitchell: ohpauleez: excellent thanks again!

12:17 ohpauleez: np, glad I could help!

12:42 momos: Perhaps a lot of you is developing in Clojure at work or for commercial projects. do you publish your code on github etc? if yes, how do you link the commercial and open-source side? under what license do you publish the code?

12:45 ejackson: momos: a good example of this is Bradford Cross's stuff. Check out https://github.com/getwoven. I guess the license is in there somewhere if you look.

12:45 momos: hmm I've seen this repo somewhere

12:47 ejackson: it used to be called clj-sys

12:48 momos: the license isn't very noticeable.... can't find it

12:48 maybe there's a default one for clj :P

12:49 ah.ok. there are a bunch of mit licenses just on some projects

12:51 ohpauleez: momos: I'm sure you'll see mostly EPL or MIT/BSD licenses for things

12:51 you can then take those, and use them in a private, proprietary project

13:26 amalloy: pdk: if you're looking for logical xor: ##(apply not= (map boolean [:a :b]))

13:26 sexpbot: ⟹ false

13:27 pdk: GASP

13:44 defn: 'lo

13:47 * chouser waves

13:47 bobo: if im handed a vector thats realy a map ie [key1 val1 key2 val2] whats the simplest way to turn it into a real map?

13:47 cant figure something simple out

13:47 mefesto: bobo: vec i think

13:48 ,(vec [:a 1 :b 2 :c 3])

13:48 clojurebot: [:a 1 :b 2 :c 3]

13:48 mefesto: oops, what am i thinking :)

13:48 bobo: :-)

13:48 mattmitchell: could someone show me how i could "dry" this up? https://gist.github.com/797191

13:48 mefesto: ,(apply hash-map [:a 1 :b 2])

13:48 clojurebot: {:a 1, :b 2}

13:49 bobo: mefesto: ofcource! thanks

13:49 mattmitchell: the only differences between the 2 are the names of the database table and a mapping in "m"

13:50 chouser: mattmitchell: (db/partners (documentor m/partner))

13:50 then just write your documentor function

13:54 mattmitchell: chouser: oh right. so pass in the functions, don't immediately execute them

14:03 KirinDave: It's so cute when someone is like, "Oh dang, macros are pretty weird." for the first time.

14:03 e.g., http://brandonbyars.com/2008/02/12/understanding-syntactic-macros/ that is making its way around hackernews

14:06 mattmitchell: how do i get a reference to a function in another namespace and pass it off as a callback to something else?

14:07 Scorchin: Hey guys, I sent in a pull request a while back to clojure-contrib and it's not been merged. I realise it's probably because it's not considered good enough, but I'd love to know why so I don't make the same mistake again. Pull request here: https://github.com/clojure/clojure-contrib/pull/4

14:08 chouser: mattmitchell: just use its name

14:08 hiredman: Scorchin: you should read the guid for contributing on the clojure website

14:08 chouser: , clojure.core/filter

14:08 clojurebot: #<core$filter clojure.core$filter@1c0035b>

14:08 hiredman: Scorchin: clojure and clojure-contrib don't take pull requests

14:08 Scorchin: hiredman: Thanks! That makes a lot of sense

14:09 mattmitchell: chouser: oh that's embarrassing, thanks :)

14:10 nishant: how can I start swank with a bigger heap?

14:20 nevermind

14:52 pauldoo: how do I zip two sequences together? e.g. turn [[1 2 3] [4 5 6]] into [[1 4] [2 5] [3 6]]

14:52 chouser: ,(map vector [[1 2 3] [4 5 6]])

14:52 amalloy: &(map vector [[1 2 3] [4 5 6]])

14:52 clojurebot: ([[1 2 3]] [[4 5 6]])

14:52 sexpbot: ⟹ ([[1 2 3]] [[4 5 6]])

14:52 chouser: wow

14:52 amalloy: haha

14:52 &(apply map vector [[1 2 3] [4 5 6]])

14:52 sexpbot: ⟹ ([1 4] [2 5] [3 6])

14:53 chouser: exactly the same mistake at exactly the same moment

14:53 amalloy: i was even thinking "do i need apply here? no, not for this instance, because map works on a sequence"

14:53 chouser: pauldoo: hi, btw.

14:54 amalloy: pauldoo: there's also ##(apply zipmap [[1 2 3] [4 5 6]]) if you want it as a map instead of an ordered set of pairs

14:54 sexpbot: ⟹ {3 6, 2 5, 1 4}

14:54 pauldoo: aha! the vector function is useful! :)

14:54 cunning!

14:54 chouser: hello to you to. :)

14:55 semperos: incanter does something similar

14:57 __name__: sexpbot: (contains? '(1 2 3) 1)

14:57 &(contains? '(1 2 3) 1)

14:57 sexpbot: ⟹ false

14:57 fogus`: pauldoo: And also ##(apply interleave [[1 2 3] [4 5 6]]) if you don't want them grouped in vectors. ;-)

14:57 sexpbot: ⟹ (1 4 2 5 3 6)

14:57 __name__: why does it just randomly say false instead of failing?

14:58 pauldoo: fogus`: right-o

14:58 I'm twatting about reimplemting "separate" so that the filter function is only called once per element

14:58 chouser: __name__: well, it has no keys at all, so I guess it doesn't have a key of 1

14:59 pauldoo: (defn separate [f s]

14:59 (let [t (map vector (map f s) s)]

14:59 [ (map second (filter first t)), (map second (filter (complement first) t)) ]))

14:59 is the best I have so far

14:59 amalloy: __name__: there is nothing random, and it is not failing

15:00 contains? is for seeing if a map contains a key, not if a list contains a value

15:00 you want ##(doc some) for that

15:00 sexpbot: ⟹ "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

15:00 __name__: amalloy: why does it work on a list then?

15:01 fogus`: __name__: This explains it well. http://en.wikibooks.org/wiki/Clojure_Programming/FAQ#Why_doesn.27t_contains.3F_do_what_I_expect_on_vectors_and_lists

15:01 amalloy: &(some #{1} '(1 2 3))

15:01 sexpbot: ⟹ 1

15:01 __name__: i know that that is how it is done, but why does the compiler not tell?

15:02 amalloy: $source contains?

15:02 sexpbot: contains? is http://is.gd/60Qkhn

15:02 __name__: ah

15:02 i see

15:02 now it makes sense, thanks

15:02 amalloy: welcome

15:03 shortlord: is there some operator like for that travesers multiple bindings parallel? like (for [x [1 2 3 4] y [1 2 3 4]] [x y]) => [[1 1] [2 2] [3 3] [4 4]]

15:03 chouser: shortlord: map

15:04 ,(map vector [1 2 3 4] [1 2 3 4])

15:04 clojurebot: ([1 1] [2 2] [3 3] [4 4])

15:04 chouser: amalloy: where were you?

15:04 shortlord: chouser: not as easliy understandable with big expressions as functions, but I guess it has to do

15:05 amalloy: chouser: jeez sorry, i guess i have to quit my job to keep up with you

15:05 shortlord: you can do this with for also

15:05 chouser: shortlord: I've thought about how to add that as a feature of 'for' somehow, but I haven't come up with anything that isn't clearly worse.

15:05 amalloy: or...no, maybe you can't

15:05 chouser: amalloy: well, it was the same answer as we tied on last time. I assumed I was racing you again. ;-)

15:06 shortlord: chouser: well, there are already tags like ':let', right? something like ':parallel' would be nice

15:06 amalloy: &(for [[x y] (interleave [1 2 3 4] [:a :b :c :d])] [x y])

15:06 sexpbot: java.lang.UnsupportedOperationException: nth not supported on this type: Integer

15:07 chouser: shortlord: but how would you use it that doesn't end up looking like just a 'map' inside the 'for'?

15:07 nickik: first we should get the pmap stuff write (fj) then we can start build parallel everything on top of that.

15:07 chouser: different kind of parallel

15:08 amalloy: chouser: but wouldn't it be so much fun to combine them

15:08 shortlord: chouser: what do you mean? you could just use something like [x y] inside the for, which should be quite nice in cases where you have large expressions that otherwise would have to be defined as functions previously

15:09 chouser: shortlord: do you have an example in mind of how you could use it?

15:12 shortlord: chouser: I have an application where I have a vector that holds a lot of similar maps (it's a field made up of fields with quite a few attributes). Now I am using a token that marks one field; this token is a ref that stores the vector index of the field that it references

15:12 amalloy: shortlord: i think he means, write a for statement using the syntax you wish existed

15:12 chouser: shortlord: I guess I'm talking about about the syntax than the semantics. Do you have a little code snippet of how you'd use for with :parallel?

15:13 * amalloy wins this time, chouser

15:13 chouser: :-)

15:15 shortlord: chouser: I'm not sure whether I understand what you want. The syntax should be as simple as that: https://gist.github.com/797350 If you want a usecase, that's what I've tried to describe

15:16 chouser: shortlord: so :parallel would group the previous binding (x in your example) with the following (y)

15:17 if you had more than two in the group, you would pu :parallel between all of them (like infix notation)?

15:17 :when and :while would be illegal inside such groups?

15:19 tonyl: that is a very big macro

15:19 for

15:19 chouser: yes. yes it is.

15:20 shortlord: chouser: ':parallel' would be used equal to :let, so :while and :when should still be allowed. :parallel would just make the bindings after it run at the same index as the main binding in for. But yes, having several bindings in the main for block zould be a problem

15:21 amalloy: shortlord: there is no "main" binding

15:21 shortlord: amalloy: I mean the normal binding pair without any tags

15:22 mefesto: this is to avoid (map vector xs ys zs) ?

15:23 shortlord: mefesto: in case the function is a simple as vector, map is clearly a good choice. but for with such a tag could be nice for larger expressions

15:23 chouser: right. (for [[x y] (map vector [1 2 3 4 5] [1 2 3 4 5])] [x y]) would be one way to write that gist currently

15:23 mefesto: (for [[x y z] (map vector xs ys zs)] [z y x])

15:25 chouser: Maybe (for [[x y z] :parallel [xs ys zs]] ...) :-)

15:32 tonyl: if there are lager expressions, just pull them up as a function

15:37 shortlord: tonyl: yeah, I guess that should do the job well enough

15:38 what is the recommended way to create a map for a small collection of things? array-map?

15:38 amalloy: chouser: not sure if you were serious with your last suggestion but that would mess up the binding-partitioning

15:39 tonyl: hash-map

15:39 &(hash-map 1 2 3 4)

15:39 sexpbot: ⟹ {1 2, 3 4}

15:39 __name__: why can i not add metadata to an integer?

15:39 amalloy: shortlord: probably (into {}), which will decide for you whether to use an array

15:39 &(instance? IObj 1)

15:39 sexpbot: java.lang.Exception: Unable to resolve symbol: IObj in this context

15:40 amalloy: &(instance? clojure.lang.IObj 1)

15:40 sexpbot: ⟹ false

15:40 __name__: or, rather, how can i attach it?

15:41 chouser: amalloy: yeah, I wasn't very serious

15:43 amalloy: __name__: put it on something other than an integer :P

15:44 __name__: amalloy: I guessed that.

15:44 amalloy: &(-> 10 vector (with-meta {:name "frank"}) ((juxt first meta)))

15:44 sexpbot: ⟹ [10 {:name "frank"}]

15:46 shortlord: how random is clojure's shuffle? it does not seem to shuffle a seq a lot

15:47 amalloy: shortlord: as random as pseudorandom gets. it calls java.util.Collections.shuffle

15:48 $source shuffle

15:48 sexpbot: shuffle is http://is.gd/xc6JDT

15:48 shortlord: amalloy: ok. I guess it just seems not very random at times... normal paranoia ;)

15:49 amalloy: indeed. humans are terrible at randomness

15:50 hiredman: I suggest running some stats

15:53 __name__: $source with-meta

15:53 sexpbot: with-meta is http://is.gd/D0GjxE

15:58 __name__: &(with-meta 1/1 {:k "v"})

15:58 sexpbot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IObj

15:58 __name__: &(with-meta 1/2 {:k "v"})

15:58 sexpbot: java.lang.ClassCastException: clojure.lang.Ratio cannot be cast to clojure.lang.IObj

16:04 robonobo: __name__, you can private message sexpbot if you want to use it's services without flooding the channel

16:04 pdk: (doc repeatedly)

16:04 clojurebot: "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it"

16:04 __name__: i did not flood the channel, did i?

16:04 pdk: (doc repeat)

16:04 clojurebot: "([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs."

16:04 robonobo: __name__: no, but you were of risk of doing

16:05 __name__: robonobo: why?

16:05 robonobo: just use sexpbot here if it's pqrtof dicussion

16:06 __name__: robonobo: it was, kind of.

16:06 robonobo: oh, i see, cqrry on, my apologies good sir

16:07 brehaut: robonobo: you need to get your \a key checked

16:07 semperos: perhaps he's using a French keyboard

16:08 thuner: He everyone!

16:08 I followed the instuction if https://github.com/richhickey/clojure-contrib/blob/master/README.txt, however the command "mvn package" did not created the target directory. Anyone had the same issue?

16:09 amalloy: thuner: richhickey's repository is quite out-of-date. i don't know if it will fix your specific problem but you should use the clojure/clojure-contrib repo

16:10 thuner: thank's I'll give a look at it

16:19 __name__: amalloy: is there no way to wrap an integer in something that implements IObj if one wants metadata?

16:19 amalloy: __name__: what's wrong with the vector-wrapping snippet i gave?

16:20 __name__: amalloy: that it returns [int meta] instead of the int with the meta attached?

16:21 tonyl: __name__: you could reify your own "box" I don't know how that would affect your algorithm

16:21 amalloy: &(-> 10 vector (with-meta {:name "frank"}))

16:21 sexpbot: ⟹ [10]

16:21 amalloy: the ((juxt first meta)) at the end is to unwrap that into the original integer and the meta you attached to the vector

16:22 chouser: you'd have to decide what operations on the number retain which metadata

16:22 amalloy: not that this is really a great idea anyway. instead of attaching meta to an integer, why not just use a real datastructure that stores the information you need

16:27 semperos: learning ring-based web application in Clojure, using enlive and moustache

16:27 I define an enlive template (deftemplate) called "index"

16:27 deftemplate returns a lazy seq of strings

16:28 I then use ring.util.response/response to put that into the :body of a response

16:28 (response (index))

16:28 __name__: amalloy: it's more of a principle thing really.

16:28 amalloy: I just wished i could attach metadata without caring what type the data is.

16:28 semperos: on the repl, the lazy seq is evaluated, and I see what I expect

16:29 but when I run it in my web app, I just get a string representation of the lazy seq, "clojure.lang.LazySeq@dd5c324b"

16:29 brehaut: semperos: i use (defn render [s] (apply str s)) from dnolen's enlive tutorial

16:29 semperos: yeah

16:29 I nkow I can do apply str all over the place :)

16:29 but the Ring spec says it takes an ISeq

16:29 of strings

16:29 in addition to a plain string

16:29 was wondering if I was missing something obvious

16:30 about the evaluation of a deftemplate's lazy seq of strings

16:34 brehaut: semperos: ring.uril.servlet/set-body does check for seq's

16:34 semperos: https://github.com/mmcgrana/ring/blob/master/ring-servlet/src/ring/util/servlet.clj#L79-83

16:35 semperos: right

16:35 it works at the repl, when I give the :body a seq of strings

16:36 just not in the app

16:36 brehaut: does (seq? (index ...)) return trye?

16:36 semperos: yes

16:37 in the app, the :body is actually set to "clojure.lang.LazySeq@xxxxx"

16:38 brehaut: which is what you would expect if str is called on the lazy-seq directly

16:38 (str (lazy-seq [1 2]))

16:38 bah

16:38 $(str (lazy-seq [1 2]))

16:38 chouser: use & or ,

16:38 semperos: &(str (lazy-seq [1 2]))

16:38 sexpbot: ⟹ "clojure.lang.LazySeq@3e2"

16:38 brehaut: thanks

16:39 semperos: yep, I get that

16:39 I'm sure I'm just missing something very basic

16:40 so (response) takes anything that is allowed by the Ring spec as part of the response :body

16:40 and sticks it in there

16:40 so at the repl, if I do (response (index)), I get everything evaluated correctly

16:40 doesn't do the same when I add it to a route with moustache

16:40 [""] {:get (fn [req] (response (index)))}

16:41 that's my confusion

16:45 LauJensen: For the Emacsers in here: http://offtopic.bestinclass.dk/post/2942525776/my-emacs-color-theme

16:46 semperos: nice

16:49 robonobo: LauJensen: your server seems to be down

16:49 LauJensen: robonobo: ?

16:49 robonobo: http://www.downforeveryoneorjustme.com/

16:50 neilcj: not down for me ;)

16:50 __name__: neither

16:51 neilcj: LauJensen: pretty theme, thanks for sharing

16:51 robonobo: it's back after a few tries (it was a maximum bandwith exceededthing, but with nicer layout)

16:52 pdk: did i ever mention

16:52 the parens matching in vimclojure has a really bad case of alzheimer's

16:53 brehaut: semperos: what middleware are you using (if any)

16:53 semperos: stacktrace, keyword-params, reload, and a custom one; going to try without the custom one

16:54 gah

16:55 well, that pinpoints where the error was

16:55 brehaut: :)

16:55 semperos: not surprisingly, my own mess

16:55 LauJensen: neilcj: np :)

16:56 pdk: Thats fair enough, since you yourself have got to have a pretty bad case of alzheimers to be using Vim in the first place

16:56 brehaut: LauJensen: theme looks nice

16:56 LauJensen: brehaut: thanks - notice how the foreground != the background. You could learn a few things :)

16:56 brehaut: LauJensen: could do with some more eye searing yellow though

16:56 LauJensen: brehaut: its got plenty yellow - I even got a complaint on twitter about it

16:56 brehaut: haha

16:56 classic

16:56 pdk: wellllll

16:56 granted!

16:59 ohpauleez: I use wombat, and still love it: http://dengmao.wordpress.com/2007/01/22/vim-color-scheme-wombat/

17:00 I made a 256 color scheme for it

17:02 LauJensen: ohpauleez: You can paint Vim... but its still Vim :(

17:03 ohpauleez: haha you're relentless LauJensen

17:03 LauJensen: Indeed :)

17:03 Its called Persistent

17:03 ohpauleez: paredit.vim + vimclojure + vim + zsh seems to do the trick for me

17:04 LauJensen: oh, you didn't tell me you were a beginner.. Beginners are allowed to evaluate their tools

17:05 wolverian: there's a paredit.vim? oh my.

17:05 oh, slimv.

17:06 I never managed to get vimclojure and slimv working together. slimv would force lisp syntax highlighting on my buffers.

17:06 chouser: experts must accept LauJensen's word without question

17:06 LauJensen: You can trust chouser, he's been here forever

17:10 ohpauleez: wolverian: I just yanked paredit.vim out of slimv

17:10 haha LauJensen I just caught myself up

17:11 LauJensen: ohpauleez: So you're using Emacs now?

17:11 ohpauleez: I always *HAVE* used it. Clojure is the first Lisp I feel comfortable editing in vim, and do most of my day to day edits in vim. But yes, I use both

17:11 there, I admitted it :)

17:12 brehaut: ohpauleez: clojure is the first lisp i have felt comfortable editign in emacs

17:12 LauJensen: :D

17:13 I gotta take off gents, but as always, it was fun hanging out with you :)

17:13 brehaut: gnite lau

17:13 ohpauleez: later

18:04 __name__: http://paste.pocoo.org/show/327503/

18:05 how do i prevent this from happening?

18:07 brehaut: __name__: which clojure are you using?

18:07 __name__: 1.3?

18:07 __name__: brehaut: 1.2

18:07 oh, wait

18:07 it's 1.3

18:08 brehaut: *clojure-version*

18:08 thats why

18:08 __name__: yes, i typed it into the wrong repr. i am deeply sorry.

18:08 brehaut: no problem

18:09 __name__: oh, and of course `map second`

18:10 note to self: do not code in an unfamiliar language when not well-rested, and if you do, do not annoy nice irc people.

18:12 amalloy: __name__: transitioning from common-lisp, it looks like? or maybe scheme?

18:12 __name__: amalloy: python, actually :-)

18:12 brehaut: that would explain your handle :)

18:13 __name__: amalloy: what made you think i am a schemer or clisper?

18:13 amalloy: __name__: interesting. i know python has [a b c] list literals, so i'm a bit puzzled as to why you're not using clojure's

18:13 (list blah blah) and '(blah blah) are easily replaced by [blah blah]

18:13 __name__: amalloy: because they are vectors?

18:13 amalloy: if i am not completely mistaken it's not the same thing

18:14 amalloy: __name__: vectors are almost always better for handling data

18:14 __name__: But in this case a vector is better.

18:14 amalloy: i mean, it doesn't matter for tiny-little lists

18:14 __name__: because i am not doing any stuff that you would use linked lists for.

18:14 amalloy: but the syntax is more convenient for vectors, and it rarely matters which you use if you're not adding

18:14 __name__: Yes, that's what I meant.

18:15 amalloy: __name__: plus, vectors support fast adding to the end, while lists support fast adding to the front

18:15 so even if you're using it as a linked list you have to choose

18:15 chouser: now's your chance! sell us all on finger trees!

18:16 __name__: amalloy: http://paste.pocoo.org/show/327511/ is this better?

18:16 amalloy: yep

18:17 __name__: i'm amazed i've come up with this :)

18:17 amalloy: depending on how comfortable you are with destructuring, you can make it still-more readable

18:17 &(fn fib [[a b]] [(+ a b) b])

18:17 sexpbot: ⟹ #<sandbox11874$eval14090$fib__14091 sandbox11874$eval14090$fib__14091@b94d90>

18:18 __name__: amalloy: Thank you.

18:18 amalloy: I just meant to try that myself :)

18:19 i guess defn fibs [] (map second (iterate (fn [[x y]] [(+ x y) x]) [1 1]))) is too much of the good

18:19 amalloy: __name__: http://rosettacode.org/wiki/Fibonacci_sequence#Clojure

18:19 is in fact what you've just done

18:20 __name__: Yep

18:20 amalloy: (i added the commented version a few months ago)

18:20 brehaut: ,(let [f (lazy-cat [1 1] (map + ff (rest ff)))] (take 5 ff))

18:20 clojurebot: java.lang.Exception: Unable to resolve symbol: ff in this context

18:20 brehaut: i am a muppet

18:21 ,(let [f (lazy-cat [1 1] (map + f (rest f)))] (take 5 f))

18:21 clojurebot: java.lang.Exception: Unable to resolve symbol: f in this context

18:21 amalloy: anyway nice work __name__. it's impressive to come up with the strategy of using iterate to store temporary data

18:21 brehaut: unequivocally so apparently

18:21 __name__: amalloy: i started with recursion, and saw that it's no use for tail calls …

18:22 arohner: according to visualvm, it appears my app is spending a significant chunk of time in PersistentHashMap$HashCollisionNode.findIndex(). Are there any clever strategies for reducing the number of hash collisions in my data?

18:22 (I assume that hitting a different node type in PHashMap will improve my performance)

18:23 brehaut: __name__ the nerdy name for the solution you came up with is a hylomorphism

18:24 (roughly)

18:25 ie, converting a recursive algorithm into a stream generator and a stream consumer

18:26 __name__: brehaut: thank you for your elaboration. i appreciate it.

18:28 brehaut: __name__ no problem

18:31 __name__: also, (nth n ...) is (first (drop n...))

18:32 although i think i have the args backwards

18:32 __name__: I ended up with (defn fibs [] (map second (iterate (fn [[x y]] [(+ x y) x]) [1 0]))) by now

18:32 i had forgotten the 0

18:32 Am I right in believing that at any point in time there's only x and y in memory?

18:33 brehaut: yup

18:33 __name__: yay

18:34 thanks for putting up with my ignorance :)

18:35 brehaut: nah, ignorance is when you type stupid crap into clojure bot rather than a repl

18:35 and then make the same mistake again

18:35 __name__ how familiar are you with generators, generator expressions and itertools in python?

18:35 __name__: brehaut: very

18:36 amalloy: er, no. only x and y are *required* to be in memory. the gc won't clean them up till it needs to

18:36 __name__: amalloy: Oh; Sorry for being vague, I meant that.

18:37 amalloy: __name__: preface: i don't think the following is actually better than your version

18:38 oh actually i take it back, this version is awesome

18:38 you could implement (fn [[x y]] [(+ x y) x]) as (juxt (partial apply +) first))

18:39 __name__: amalloy: would you mind explaining, i looked at the doc of juxt (and know what partial does), but do not seem to grasp it.

18:40 brehaut: ,((juxt inc dec) 1)

18:40 clojurebot: [2 0]

18:40 amalloy: well, ideally it would be just (juxt + first), which makes more sense

18:41 but because [x y] is a list, you need to ##(apply + [1 2])

18:41 sexpbot: ⟹ 3

18:41 __name__: amalloy: are you a haskeller?

18:41 amalloy: (partial apply +) wraps that up in a new function that will add the list it's passed

18:41 __name__: no, but i keep hearing i should be

18:41 i think point-free is nice

18:41 brehaut: the haskell solution ported to clojure is

18:42 (def fibs (lazy-cat [1 1] (map + fibs (rest fibs))))

18:43 turns out i was right previously but i (obviously) need a var in the road, to make it self recursive

18:43 amalloy: &with-local-vars

18:43 sexpbot: java.lang.Exception: Can't take value of a macro: #'clojure.core/with-local-vars

18:43 __name__: amalloy: I understand

18:44 brehaut: ,(with-local-vars [fib (lazy-cat [1 1] (map + fibs (rest fibs)))] (take 10 fibs))

18:44 clojurebot: java.lang.Exception: Unable to resolve symbol: fibs in this context

18:45 amalloy: brehaut: the var doesn't exist until its init expr is done

18:46 brehaut: also i typod

18:46 amalloy: &(with-local-vars [fibs nil] (var-set fibs (lazy-cat [1 1] (map + (var-get) fibs (rest (var-get fibs))))) (take 10 (var-get fibs)))

18:46 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (0) passed to: core$var-get

18:46 amalloy: blah whatever

18:47 &(with-local-vars [fibs nil] (var-set fibs (lazy-cat [1 1] (map + (var-get fibs) (rest (var-get fibs))))) (take 10 (var-get fibs)))

18:47 sexpbot: java.lang.IllegalStateException: Var null/null is unbound.

18:47 brehaut: amalloy: im glad its not just me :/

18:47 arohner: more info on my hash collision problem. I have a map w/ 33k keys, but 6.7k distinct hash codes (according to (->> my-map keys (map #(.hashCode %)) distinct count

18:47 amalloy: &(with-local-vars [fibs nil] (var-set fibs (lazy-cat [1 1] (map + (var-get fibs) (rest (var-get fibs))))) (doall (take 10 (var-get fibs))))

18:47 sexpbot: ⟹ (1 1 2 3 5 8 13 21 34 55)

18:47 __name__: yay

18:47 amalloy: brehaut: solved!

18:48 vile though it is

18:48 brehaut: (inc amalloy )

18:48 sexpbot: ⟹ 2

18:48 brehaut: woo :-)

18:48 yeah remarkably so

18:48 the basic concept is so tidy too

18:49 Leonidas: __name__: I'm not haskeller either and partial and thread-last are seriously nice ;)

18:49 amalloy: partial is...really handy, and way too verbose

18:49 __name__: Leonidas: oh hey

18:49 brehaut: amalloy: thats why we have % ;)

18:49 err #

18:50 Leonidas: __name__: hi :)

18:50 __name__: I'm currently in clojure-hack mode :D

18:50 amalloy: one day i'll cross over to the dark side and (def ##(char (rand-int 0xffff)) partial)

18:50 sexpbot: ⟹ \練

18:50 __name__: Leonidas: i'm in ‘i should go to sleep’ mode.

18:51 brehaut: amalloy: i apparently dont have that glyph

18:51 amalloy: brehaut: i don't either, it's too high in the code charts

18:51 Leonidas: __name__: same here. and "i should learn for exams" mode. this is the one time in the semester when I start to hack productively :)

18:51 __name__: Leonidas: :)

18:51 amalloy: &(char (rand-int 0x8fff))

18:51 sexpbot: ⟹ \佗

18:51 brehaut: hah awesome

18:52 amalloy: although FAB0 is the best random character ever

18:52 it's FAB0LOUS!

18:52 __name__: &(char 0xdead)

18:52 sexpbot: ⟹ \?

18:53 Leonidas: ,(char 0xFAB0)

18:53 clojurebot: \練

18:53 amalloy: that's how haskellers roll, isn't it? define single-unicode-character names for the useful functions?

18:53 Leonidas: which of these bots is actually to prefer?

18:54 brehaut: nah, its more like a like a crazy pipe of 2 to 5 punctiation characters as a binary op

18:54 amalloy: Leonidas: sexpbot imo, but i'm biased as i've been helping write/maintain him for months now

18:55 Leonidas: amalloy: :)

18:55 brehaut: amalloy: your homework is to explain the difference between (.) (>>>) and (>=>)

18:57 valid answers do include 'not much'

18:58 arohner: &(.hashCode {62 0, 75 1720, 73 1})

18:58 sexpbot: ⟹ 1913

18:58 arohner: &(.hashCode {75 1717, 62 1, 61 1})

18:58 sexpbot: ⟹ 1913

18:59 amalloy: arohner: (hash x) is the same as (.hashCode x)

18:59 arohner: amalloy: thanks, but not my issue ATM

18:59 amalloy: *laugh* i know

18:59 arohner: &(hash {75 1099})

18:59 sexpbot: ⟹ 1024

19:00 arohner: &(hash { 69 24 61 1 75 812})

19:00 sexpbot: ⟹ 1024

19:00 arohner: I can do that 28k more times

19:00 out of 33k maps

19:01 amalloy: have you looked at the source of map.hash?

19:02 arohner: yeah. it doesn't look very random (though I could have told you that empirically )

19:02 amalloy: it looks like it's pretty bad, yeah

19:03 arohner: you could probably make it sufficiently good just by adding hash *= 13 before the +=

19:05 perhaps that just slows things down too much for rich

19:08 arohner: amalloy: if you think computing hashes is expensive, you should try dealing with hash-collisions :-)

19:08 amalloy: I'll try out a build with *= 13, and we'll see what happens

19:08 amalloy: arohner: that's only an issue if maps containing elements with weak hash functions are stored inside of another mapo

19:09 so i doubt it comes up much in practice

19:09 arohner: &(hash 1238907)

19:09 sexpbot: ⟹ 1238907

19:10 arohner: my data is not distributed randomly. The keys are db ids, and the values are ids of enums that users have selected

19:11 amalloy: arohner: yes, i understand why it comes up for you

19:12 my point is that it may not come up often enough in general to merit slowing down map hashing; the hit there might be worse than the occasional reduction in collisions

19:16 __name__: thanks, especially amalloy and brehaut; good luck with the exam, Leonidas. good night all.

19:17 Leonidas: __name__: goodnight.

19:22 symuyn: Is a vector's hash code calculated when the vector is created, or is it lazily calculated when hash or = is called?

19:24 amalloy: symuyn: on hash

19:24 symuyn: When hash is called?

19:24 amalloy: yes

19:24 symuyn: Good, that makes sense

19:24 By the way, does vector's isEquals use hash codes?

19:24 isEqual, I mean

19:25 amalloy: symuyn: bizarrely enough, the answer is "sometimes"

19:25 symuyn: Hmm

19:26 amalloy: for List and PersistentVector, it checks their hash codes

19:26 for Sequential objects it goes straight to comparing

19:26 symuyn: Aren't List and PersistentVector inside Sequential?

19:26 Oh wait, they can override

19:27 But what doesn't override Sequential.isEqual?

19:27 amalloy: &(some #{clojure.lang.Sequential} (supers (class [])))

19:27 sexpbot: ⟹ clojure.lang.Sequential

19:27 symuyn: Yeah

19:27 Oh well. Clojure does a good job of hiding this stuff anyway

19:28 amalloy: symuyn: the persistent data structures have a doEquiv and doEquals

19:28 symuyn: I forgot: are all Sequential objects persistent?

19:28 amalloy: equiv is what's called by (= foo bar), and it never checks hash codes b/c it needs [1 2] to equal (1 2)

19:29 symuyn: I thought that [1 2] and (1 2) had equal hash codes; I was told that yesterday

19:29 @(= (hash [1 2]) (hash '(1 2)))

19:29 amalloy: they probably do, but that's not really a guarantee

19:30 symuyn: Ugh

19:30 &(= (hash [1 2]) (hash '(1 2)))

19:30 sexpbot: ⟹ true

19:30 amalloy: &(map hash ["" 1] #{"" 1})

19:30 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$hash

19:30 mefesto: anyone use clojure-rabbitmq in here?

19:30 amalloy: &(map hash [["" 1] #{"" 1}])

19:30 sexpbot: ⟹ (962 1)

19:31 amalloy: &(apply = [["" 1] #{"" 1}])

19:31 sexpbot: ⟹ false

19:31 amalloy: well, that's good at least

19:31 &(apply = [[1 ""] #{"" 1}])

19:31 sexpbot: ⟹ false

19:31 amalloy: anyway i think it's a complicated issue

19:31 symuyn: Wait, really?

19:31 &(= #{} [])

19:31 sexpbot: ⟹ false

19:31 symuyn: Huh. Sets and vectors aren't equal.

19:32 That might bite me someday

19:32 I wonder what the rationale is

19:32 brehaut: symuyn: that makes sense though right? vectors have additional information encoded in them than sets

19:32 symuyn: Ah, right.

19:33 I need to think of collection equality as sequence equality

19:33 Wait, that might not work for sets to sets

19:33 brehaut: ,[(hash (lazy-seq [1 2 3])), (hash (lazy-seq [3 2 1]))]

19:33 clojurebot: [30817 32737]

19:34 brehaut: i dont know why i made those lazy

19:34 amalloy: brehaut: an extra sprinkling of awesome

19:34 brehaut: amalloy: i like how you think

19:36 symuyn: i think realistically you need to have much crisper notions of equality

19:38 symuyn: brehaut: I think that sequentials vs. non-sequentials are fine. "All sequentials are equal if blah, blah, but are never equal to non-sequentials. Non-sequentials are equal if they contain the same elements, but are never equal to sequentials."

19:38 brehaut: symuyn: what about a sorted set compared to a vector?

19:38 symuyn: &(= (sorted-set 1 2 3) [1 2 3])

19:38 sexpbot: ⟹ false

19:39 symuyn: Yeah, okay

19:39 brehaut: yeah, and even worse

19:39 symuyn: Well, so much for consistency

19:39 brehaut: is (sorted-set 1 2 3) different to [1 2 2 3]?

19:40 symuyn: &(= (sorted-set 1 2 3) [1 2 2 3])

19:40 sexpbot: ⟹ false

19:41 brehaut: really, you need to convert one side of your test into the other type

19:41 ,(= (sorted-set 1 2 3) (apply sorted-set [1 2 2 3]))

19:41 clojurebot: true

19:42 symuyn: Ugh, apply is so slow; it's been the bottleneck of my programs in the past

19:42 brehaut: ,(= (vec (sorted-set 1 2 3)) [1 2 2 3])

19:42 clojurebot: false

19:42 symuyn: Thank goodness for vec

19:43 Do you know if there's a way to turn off pre/post-conditions, like tests?

19:43 brehaut: symuyn: the point being though, depending on how you are viewing _the same data_ equivalence can change dramatically

19:43 symuyn: Yeah

19:43 brehaut: (same excluding collection information)

19:43 amalloy: &(time (apply + (range 1e5)))

19:43 sexpbot: ⟹ "Elapsed time: 26.930893 msecs" 4999950000

19:44 amalloy: symuyn: apply really isn't slow, i don't see what problem you're experiencing

19:44 &(time (reduce + (range 1e5)))

19:44 sexpbot: ⟹ "Elapsed time: 30.868435 msecs" 4999950000

19:44 brehaut: amalloy: i imagine applying a collection constructor to a large collection is going to be a slow operation ;)

19:44 symuyn: amalloy: It happened twice a year ago. Perhaps I'm wrong, but I'm pretty confident

19:45 amalloy: brehaut: sure, but not any slower than (doall (map identity coll))

19:45 brehaut: amalloy: oh for sure, its not the result of apply that its slow

19:47 amalloy: symuyn: you found that (foo x y z) was substantially faster than (apply foo [x y z])? i guess i could see that, if foo had a lot of different arities defined

19:47 symuyn: Why would the number of arities matter?

19:49 brehaut: symuyn: a function call can choose the implementation at compile time, an apply call has to determine the implementation at runtime

19:50 symuyn: Yes, but does the search time depend on the number of arities? Maybe it's constant to the number. But the again, I've no idea.

19:52 brehaut: symuyn: i cant intuit how it could be constant time

19:53 $source apply

19:53 sexpbot: apply is http://is.gd/AklWob

19:53 brehaut: i must confess to that not clearing things up for me

19:54 symuyn: The source there doesn't show the implementation of arity selection.

19:54 It doesn't really matter that much anyway

19:54 I'd think that we'd have to look in clojure.lang.IFn (or .Fn?) but I don't like looking in Clojure's guts

19:55 brehaut: https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/AFn.java#L154

19:55 symuyn: Ah, now that's interesting

19:55 hiredman: ,((fn [& x] (first x)) (iterate inc 0))

19:55 clojurebot: (0 1 2 3 4 5 6 7 8 9 ...)

19:55 hiredman: erm

19:55 ,(apply (fn [& x] (first x)) (iterate inc 0))

19:55 clojurebot: 0

19:55 symuyn: Now, doesn't collection counting have near-constant-time?

19:55 hiredman: apply doesn't count

19:56 symuyn: Wait, no

19:56 hiredman: ^- apply to an infinite seq

19:56 brehaut: apply does magic

19:56 symuyn: The arglist is an ISeq

19:56 Sequence counting is linear

19:57 hiredman: That's interesting

19:57 brehaut: https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/RT.java#L1184

19:57 symuyn: That kind of boggles my mind, actually

19:57 Yes, and there we have it

20:01 brehaut: also im presuming that Util.ret1 at https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/AFn.java#L151 is used to let java release the seq?

20:03 hiredman: yes, java doesn't have a way of clearing the jvms method frame while keeping a reference on the method's stack

20:03 brehaut: hiredman: cheers

20:22 symuyn: relevant to the discussion http://groups.google.com/group/clojure-dev/browse_thread/thread/c58ec42d78209ee0

20:24 symuyn: brehaut: Thanks; that's very interesting

20:24 Oops, wrong punctuation

20:26 brehaut: symuyn: and by experimention i gather than sorted-sets test equality as sets by default, and seqs if you wrap them seq; YMMV of course, ididnt read the code

20:26 symuyn: I think you're right in that I should just convert to the same type before comparing

23:09 pdk: (doc doseq)

23:09 clojurebot: "([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."

23:09 pdk: (doc while)

23:09 clojurebot: "([test & body]); Repeatedly executes body while test expression is true. Presumes some side-effect will cause test to become false/nil. Returns nil"

23:16 amalloy: that's a weird docstring for while

23:16 brehaut: is it weird that i didnt even know there was a while?

23:16 amalloy: "Presumes some side-effect will cause test to become false/nil" suggests that it is an error to write (while true (...)), because you are violating while's assumption/precondition

23:17 brehaut: yeah, i've never used it either

23:17 pdk: it's an infinite loop at any rate

23:17 amalloy: pdk: clearly. but there's nothing wrong with writing an infinite loop if that's what you want

23:18 technomancy: be honest, who reads the docstring for while?

23:18 amalloy: technomancy: pdk, it seems

23:18 and now me, to my chagrin

23:19 brehaut: is there an sexp-grep for clojure?

23:20 (ie, for grepping clojure source)

23:20 amalloy: brehaut: how would that be different from plain old grep?

23:21 brehaut: amalloy: knows about trees rather than lines

23:21 grep is probably the wrong term

23:21 xpath is a better one

23:21 sexpath

23:21 probably didnt need to go there

23:21 amalloy: like...sgrep (if (magic))? it's not clear to me how i'd specify useful sexps for this

23:22 technomancy: sounds like you want a zipper

23:22 brehaut: yeah i probably do

Logging service provided by n01se.net