#clojure log - Feb 17 2011

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

0:24 simard: bortreb: hum I only get to 87 ms

0:24 were you serious about 3 ms ? ;)

0:47 tomoj: why aren't sorted sets and maps IEditableCollections, I wonder?

0:48 bortreb: I was doing the coderloop problem, which goes much higher than the euler ones

3:14 TobiasRaeder: morning

4:48 iwillig: is there a protocol that I can extend a Java class to take advantage of ISeq ?

5:03 Dranik: is there a way to save the current clojure application state and load it like in lisp?

5:23 _2x2l: Dranik: how would you do it in CL?

5:24 Dranik: _2x2l, I don't know CL so well but I'm sure it is possible to save the current state and restore it after a while

6:28 zmila: #join compojure

7:17 bmh: I'm thinking of implementing sampling from the conditional multivariate normal distribution in Incanter and I want to make sure I get my interface right. Anyone involved with Incanter around?

7:27 zmila_: aoeu

8:59 Cozey: Hi! I'm using 'contexts' with cake. Will I be able to set some configuration in a later generated jar? when I do cake jar @context it doesn't seem to place the cake namespace inside the jar

9:14 _fogus_: Looks like the documentation for #= has vanished. :-(

9:38 ejackson: _fogus_: the LHC is rumoured to be emitting particles of antidocumentrons.

9:39 Fossi: that'd be funny

9:57 _fogus_: CURSE YOU LHC!

9:58 ejackson: its always the French.

10:13 octe: i've noticed a pattern when i write clojure utils, i'll make a create/init function that returns a state-object that is usually a ref to a map, and a destroy/close function that releases any resources the state contains, and then a bunch of functions that takes the state as an argument and does various things

10:13 is this a good pattern?

10:16 Chousuke: hmm

10:17 if the functions operating on the actual ref is low, then I guess.

10:18 your main concern should be writing functions that operate on the values of the ref, not functions that operate on the ref :)

10:19 though I have to say that sounds a lot like you're just emulating object-orientation

10:19 with a constructor, methods, mutable state, and a destructor :P

10:23 octe: Chousuke, yeah, that's the feeling i get too.

10:24 say for example i'm writing an irc client, i'll need to at least keep track of the socket (in the state object then)

10:24 it feels inevitable

10:25 1

10:29 Chousuke: octe: you can't avoid state entirely, the point is isolating it from the non-stateful stuff.

10:29 octe: which includes most processing of data

10:30 octe: yes

10:30 Chousuke: if you can tell which functions are stateful and which aren't given arbitrary parameters, you're doing fine I think :P

10:31 octe: well when there's io involved, they're all stateful i guess

10:31 Chousuke: in a stereotypical OO program, there's just no reliable way to tell wtf exactly is happening. :)

10:31 octe: yeah

10:31 Chousuke: octe: only the IO itself is stateful, processing the stuff you read is not.

10:31 octe: feels like im falling into that trap with my state-objects

10:32 ah well

10:38 dnolen: octe: you could create a small paste gist isolating the particular pattern you find yourself using. it sounds unidiomatic to me.

10:54 raek: octe: I think one example could be to write (defn parse-line [s] (.split s ",")) (parse-line (read-line rdr)) instead of something like (defn get-and-parse-line [rdr] (.split (read-line rdr) ","))

10:54 i.e. to as often as possible to all data processing in pure functions

11:09 jkdufair: anyone working/worked with appengine-clj?

11:11 TobiasRaeder: the freiheit one?

11:11 or appengine-magit

11:12 *magit

11:12 but i guess that would be appengine-magic and not -clj ;)

11:12 TimMc: *magic

11:12 TobiasRaeder: ty

11:12 lol

11:12 but yeah actually i do

11:13 ev4l: hi there! did anyone here experienced the following error with swank-clojure: "swank-clojure-reset-implementation: Symbol's function definition is void: aput"

11:13 it happens when run 'swank-clojure-project' to change the current project directory

11:14 *it happens when i run*

11:17 jkdufair: i've been playing with appengine-magic but discovered appengine-clj. there are several forks and i wondered if anyone had experience with any of them. the datastore features in the r0man fork and below look pretty tasty

11:18 TobiasRaeder: i just know the original (smartrevolution) one which is in kind of a big overhaul right now which is nearly done

11:19 raek: ev4l: haven't heard of that problem, but I would recommend trying durendal (https://github.com/technomancy/durendal)

11:20 it lets leiningen take care of starting swank, rather doing that from emacs

11:20 jkdufair: i've been using durendal and it works nicely

11:21 raek: I think you could say that it's the successor of swank-clojure.el

11:21 TobiasRaeder: @jkdufair you need any help with appengine-clj?

11:21 raek: "Previous versions of Swank Clojure bundled an Elisp library called swank-clojure.el that provided ways to launch your swank server from within your Emacs process. While swank-clojure is still distributed with the project, it's a much more error-prone way of doing things than the method outlined above."

11:21 "If you have configured your Emacs to use M-x swank-clojure-project then it should still work, but it's not recommended for new users."

11:22 when I started using durendal, I also had to add a lein symlink in /usr/local

11:23 jkdufair: TobiasRaeder: not help, per-se. just in choosing a fork. looks pretty self-explanatory otherwise. i'm building a RESTful JSON frontend to appstore entities

11:23 raek: since it wouldn't use my custom PATH from by .bashrc

11:23 jkdufair: wrote a bunch of macros and such which look like was done better by appengine-clj

11:24 TobiasRaeder: @jkdufair okay, well i think the smartrevolution should be really nice specially after the next update (gonna try to force that to be published soon)

11:25 jkdufair: TobiasRaeder: Are you referring to smartrevolution/clj-gae-datastore?

11:26 TobiasRaeder: @jkdufair i thought there was an appengine-clj from that user aswell but doesn't seems that way. im kinda confused now :D gonna see if i can find what i mean

11:26 @jkdufair because i thought there was more then just a datastore api

11:27 octe: raek, yeah, i try to do that

11:33 ejackson: Lets say I download some clojure library (say clojure-redis). Is it horrendous just create symlinks from my src/main/clojure/.... ?

11:33 cemerick: ejackson: yes, just a bit :-)

11:33 ihodes: ejackson: yes

11:33 ejackson: I want to keep them separate, but also want to be able to use clojure-redis in my project without building and deploying jars each tim

11:33 so what's the technnique ?

11:33 ihodes: ejackson: use lein, please

11:34 cemerick: ejackson: lein, maven, gradle, ant……really, anything other than synlinks.

11:34 ejackson: lets assume maven

11:34 now what ? (sorry for this stupid question)

11:34 cemerick: heh

11:35 ejackson: do I mvn package the clojure-redis

11:35 mvn install it

11:35 cemerick: ejackson: one would hope it's in a repo somewhere already

11:35 ejackson: and then use it as a dep in my pom.xml for the main project ?

11:36 cemerick: ejackson: essentially, yes

11:36 maybe this is what you're after? http://clojars.org/redis-clojure

11:36 ejackson: this was just a minimal example. Really I have two projects that rely on substantially amounts of my own code

11:37 i've been balking at pulling those shared sections into independent libraries

11:37 clojurebot: libraries is http://clojure.org/libraries

11:37 ejackson: symlinks are a cute solution, but felt evil

11:38 cemerick: They are. It doesn't seem like it in the small and while you're working solo, but as soon as either change, it's a disaster.

11:38 fliebel: morning

11:38 ejackson: cemerick: thanks for the tips. I'll buckle down and sort this out...

11:39 cemerick: ejackson: FWIW, of course. :-)

11:46 ejackson: cemerick: am I correct in thinking that converting to a multi-module maven project is a reasonable approach ? It would allow me to make a .jar for each module of the current project, deploy em to the binary repo and use elsewher.

11:47 To press my luck on the questions: Would bringing in some existing projects (like redis-clojure) and a module into a big project be a good move ?

11:48 s/and a/as a/

11:48 sexpbot: <ejackson> To press my luck on the questions: Would bringing in some existing projects (like redis-clojure) as a module into a big project be a good move ?

12:08 technomancy: ejackson: FWIW that's what "checkout dependencies" are for in lein

12:08 ejackson: technomancy: thanks, I'll examine that.

12:09 technomancy: that way changes in the checkout are available without doing the repackage/restart dance

12:10 ejackson: yeah, that's what's irritating me right now

12:25 fliebel: What is a good data structure for storing positions where adjacent positions are nearby and easy to get to?

12:25 AWizzArd: fliebel: you can think about sorted-set-by

12:25 for those and on sorted-map-by's you can do subseq

12:27 fliebel: AWizzArd: Sorted by what?

12:27 AWizzArd: ,(subseq (sorted-set-by #(< %2 %1) 1 2 3 4 5) < 3)

12:27 clojurebot: (5 4)

12:29 AWizzArd: You can sort by position

12:29 ,(sorted-set-by compare (range 10))

12:29 clojurebot: #{(0 1 2 3 4 5 6 7 8 9)}

12:29 fliebel: I never really understood subseq, but it looks nice :) (as deos a hilbert curve, but I'm not sure that's of any use)

12:29 AWizzArd: ,(apply sorted-set-by compare (range 10))

12:29 clojurebot: #{0 1 2 3 4 5 6 7 8 9}

12:30 AWizzArd: ,(subseq (apply sorted-set-by compare (range 10)) >= 3)

12:30 clojurebot: (3 4 5 6 7 8 9)

12:30 AWizzArd: ,(subseq (apply sorted-set-by compare (range 10)) >= 3 < 8)

12:30 clojurebot: (3 4 5 6 7)

12:30 AWizzArd: those are >=3 and <8

12:31 or you can have

12:31 ,(sorted-set-by #(.compareTo (str %1) (str %2)) :a :b :c :d :e :f :g)

12:31 clojurebot: #{:a :b :c :d :e :f :g}

12:31 AWizzArd: and then subseq on it with >= :c and <= :e

12:32 fliebel: AWizzArd: I am not sure I understand how this is useful, for say a 2D grid.

12:32 AWizzArd: I don't know if it is useful. It is just an idea to fetch nearby objects.

12:34 fliebel: okay, i'll think about it

12:40 ev4l: raek: thx!

12:43 amalloy: AWizzArd: isn't #(< %2 %1) identical to >= ?

12:43 raek: *>

12:44 amalloy: mmf. i guess that's true. i always forget that reversing the order of args isn't the same as negating the operation :P

12:44 &(doc subseq)

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

12:51 fliebel: dnolen: ping

13:02 dnolen: fliebel: pong

13:04 AWizzArd: amalloy: yes, I just wanted to show how it can be used in principle.

13:05 fliebel: dnolen: It's diner time for me now, but after the break, I'd like to discuss some issues with the cond-i problem. some examples in the book do not work because of this.

13:05 any-o for example.

13:10 dnolen: fliebel: yeah, I'm probably not going to address that. it's pretty easy enough to sort out what's going on in those examples anyhow.

13:12 fliebel: Oleg has the version of miniKanren used in the book here, http://kanren.cvs.sourceforge.net/kanren/kanren/mini/mk.scm, copy and paste into Racket.

13:14 LogicBlox use of Datalog seems really interesting: http://www.logicblox.com/research/presentations/arefdatalog20.pdf

13:15 jweiss: i'm trying to figure out how clojure.zip/branch? is throwing NPE. I can't think of any input that would cause that. http://www.fpaste.org/5J8h/

13:16 my branch fn is just #(contains? % :links), which i tested calling it with nil, doesn't throw NPE

13:17 raek: jweiss: the closing paren on line 7 looks suspicious

13:17 amalloy: raek: a fine point

13:18 jweiss: raek: amalloy: it did the same thing before i added line 7

13:18 raek: also, (if x (f x) nil) can be written as (and x (fx x))

13:18 amalloy: raek: damn, beat me to it

13:18 jweiss: you wrote the if on line 7 wrong

13:18 jweiss: i am kinda grasping at straws

13:18 raek: jweiss: your defn contains two expressions: (if (nil? z) nil) and (->> ...)

13:18 amalloy: should be (if (nil? z) nil (->> ...)), not (if (nil? z) nil) (->> ...))

13:19 jweiss: amalloy: doesn't matter. removing line 7 has no effect.

13:19 it was broken before i added it

13:20 raek: jweiss: having that expression there won't affect anything, since you discard the value of the 'if' and eval the ->> anway

13:21 jweiss: raek: so z may in fact be the 'problem' nil on line 6

13:21 raek: look carefully how the parentheses are arranged in amalloy's explanation

13:21 jweiss: let me fix and retry

13:25 raek: amalloy: http://www.fpaste.org/pAXq/

13:25 seems to have fixed my bad "if" but still has the same problem

13:25 it's a zipper problem i think since it's thrown from clojure.zip/branch?

13:26 raek: jweiss: if you reload the file with (reload 'com.redhat.qe.auto.navigate :reload) or (C-c C-k in emacs) you will get line numbers in the stack trace

13:26 ...for you own functions

13:26 *(require ...)

13:26 jweiss: raek: yeah i know, i already know what line # in my own functions it's thrown from

13:27 raek: which line is it in the paste?

13:27 jweiss: it's line 7 in the paste

13:27 amalloy: jweiss: it's a problem with how you're using the zipper, anyway :P. (zip/next nil) will probably throw the same error

13:28 jweiss: amalloy: hm... maybe it's because my zipper predicate returns nil instead of false?

13:30 raek: maybe the lazy-seq from iterate will call zip/next one time too much

13:30 and then it's too late to do the zip/end? test

13:30 jweiss: raek: i don't think so, since zip/end? returns true on the last one

13:31 oh wait i think i may see what you mean

13:31 the way zipper's docs say it, it should be ok

13:31 in fact, if there was a problem that you describe, my find-node would always fail

13:31 but it doesn't

13:33 the doc here is unclear: "children is a fn that, given a branch node, returns a seq of its

13:33 children."

13:33 so i am supposed to return an empty seq if there are no children?

13:34 amalloy: jweiss: nill is probably the same as an empty seq

13:34 raek: maybe the lib will only call that function for nodes where branch? is true

13:34 amalloy: but don't return a seq containing nil

13:36 fliebel: dnolen: easy?! :( Oh, well, I think I'll figure it out. What do you mean by "not going to address"? I don't expect you to make cond-i/e work differently in Logos, but maybe you could explain me a bit about the difference, and and why any-o does not work with Logos, as defined in the book.

13:37 raek: jweiss: have you tried defining a lazy-seq in some way like this: (defn traverse-tree [z] (lazy-seq (when-not (zip/end? z) (cons z (traverse-tree (zip/next z))))))

13:37 I don't know if zippers are designed to be used this way

13:38 (I have barely used tried them)

13:38 jweiss: raek: you mean using next to create a lazy seq?

13:38 i figure next must be there to create a traversal

13:39 raek: I was thinking about putting next and end? at the same place

13:39 to use them both to construct the seq in order to not walk outside the end

13:39 (assuming that was the problem, which mich not be the case anyway)

13:47 dnolen: fliebel: sorry got disconnected.

13:48 fliebel: I just don't have much interesting in supporting depth-first search in Logos. It's existence in TRS purely pedagogical, show you can see the benefits of an interleaving search.

13:49 s/show/so

13:49 sexpbot: <dnolen> fliebel: I just don't have much interesting in supporting depth-first search in Logos. It's existence in TRS purely pedagogical, so you can see the benefits of an interleaving search.

13:50 fliebel: dnolen: I wasn't asking if you could support it, but rather if there is a way to make things like any-o work with your cond-e.

13:51 dnolen: fliebel: can you paste the snippet so I can see what your talking about? I don't have my copy of TRS lying around.

13:51 fliebel: (defn any-o [q] (cond-e (q s#) ((any-o q))))

13:52 dnolen: fliebel: and how are you running that? (run 1 [q] (any-o q) ?

13:53 fliebel: (run 1 [q] (any-o s#) (== true q))

13:53 no, wait...

13:53 yea, like that

13:55 I can imagine the because of interleaving, it tries q, recurs, and never reaches s#, but..

13:55 (defn any-o [] (cond-e (s#) ((any-o)))) has the same result.

14:08 dnolen: fliebel: actually I think you found a legitimate bug :)

14:11 fliebel: I created an issue, the interleaving is not right

14:16 mprentice: happy thursday folks

14:25 whr: Hello, i've got a question. Why doesn't this code: (try (map + '(a b)) (catch Exception ex 42)) catch the exception (it throws ClassCastException)? Similiar code, (try (throw (new ClassCastException)) (catch Exception ex 42)) returns 42

14:28 mprentice: I need to differentiate between a map and a string. Ideally, (somefun {}) will return true, and (somefun "anystring") will return false. What is the idiomatic clojure way to do this? (I have a vector filled with maps and strings and i need to only do a lookup based on a key in the maps)

14:28 Chousuke: (doc map?)

14:28 clojurebot: "([x]); Return true if x implements IPersistentMap"

14:28 mprentice: ahhhhh, durr, yes, thanks much :)

14:39 amalloy: whr: map is lazy

14:39 the exception doesn't occur during the call to map, but in the realization of the lazy seq that map returns, which is outside the lexical scope created by try

14:40 &(try (map + '(a b)))

14:40 sexpbot: java.lang.ClassCastException: Cannot cast clojure.lang.Symbol to java.lang.Number

14:40 whr: amalloy: I see, thank you!

14:40 amalloy: &(try (map + '(a b)) (catch Exception _ 10))

14:40 sexpbot: java.lang.SecurityException: You tripped the alarm! catch is bad!

14:41 amalloy: mutter. anyway, you can put a (doall (...)) inside the try, if you want to catch and don't mind realizing the whole seq at once

14:41 jcromartie: &(take 2 (map inc '(3 9 a b c)))

14:41 sexpbot: ⟹ (4 10)

14:41 jcromartie: &(take 3 (map inc '(3 9 a b c)))

14:41 sexpbot: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.lang.Number

14:44 dnolen: fliebel: should be able to get that fixed later this evening. Looks like I'll be using delay to force interleaving, fun. Thanks for the report.

15:09 jweiss: so (first (filter pred coll)) isn't lazy... how do i lazily find the first matching item?

15:10 raek: what do you mean by not lazy? does it force too many elements?

15:10 jweiss: 'some' is made for that

15:10 (some #(when (pred %) %) coll)

15:11 jweiss: raek: sweet, that's it, thakns

15:11 raek: if the seq is chunked, maybe that won't make any difference

15:16 monora: Hi, I am experimenting with slime-clojure. But can't remember how to get the value of the last evaluated expression. Was it $1, $2,...

15:17 jcromartie: *1

15:17 *2

15:17 monora: Ah! Thanx

15:17 jcromartie: raek: is "some lazy?

15:25 clizzin: quick question about records and type hints: i declared (defrecord Foo [a b]) in (ns foo). then, in (ns bar), i have a function (defn bar [#^Foo f] ... ). but i didn't require or use the foo ns in any way. how come the bar function still compiles with the type hint even though the bar ns shouldn't recognise the Foo type?

15:25 raek: jcromartie: I don't think the term applies to it, since it does not produce a seq. however, I don't think it will force more of the seq than it needs

15:35 jcromartie: it's kind of strange that (first (filter pred coll)) seems to fully evaluate the seq

15:36 &(first (filter #(do (println %) %) (range 5)))

15:36 sexpbot: ⟹ 0 1 2 3 4 0

15:36 jcromartie: those 0 1 2 3 4 are printed

15:37 but filter says it returns a lazy seq

15:39 Scriptor: jcromartie: print forces evaluation, maybe?

15:39 jcromartie: that would be strange

15:39 _fogus_: &(second (filter identity (iterate #(do (println \.) %) 1)))

15:39 sexpbot: ⟹ . 1

15:40 raek: &(first (filter #(do (println %) %) (range 100)))

15:40 sexpbot: ⟹ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0

15:40 jcromartie: hm

15:40 raek: ranges come in chunks of 32.

15:40 jcromartie: it takes 32 eh

15:40 Scriptor: ohh

15:40 right, it's an optimization

15:40 jcromartie: so what's lazy, filter, or range?

15:40 _fogus_: raek: beat me to it! :-)

15:40 jcromartie: what's lazy: filter, or range?

15:41 Scriptor: both, I think

15:41 _fogus_: (inc raek)

15:41 sexpbot: ⟹ 5

15:42 raek: both return lazy sequences, but performing sequence operations of a chunked seq (e.g. one returned by range) happens 32 at a time

15:42 jcromartie: &(first (filter #(do (println %) %) (vec (range 100))))

15:42 sexpbot: ⟹ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 0

15:42 jcromartie: looks like filter is returning a 32-chunked seq

15:42 raek: I don't know much more details than this

15:42 jcromartie: I could just look at the source I guess

15:42 :P

15:42 raek: over to you, _fogus_... :-)

15:42 jcromartie: silly me

15:46 cemerick: OT: Any chance anyone here is an expert in the minutiae of options?

15:46 _fogus_: options?

15:46 stock options?

15:46 cemerick: _fogus_: of the financial sort

15:47 jcromartie: &(type (range 10))

15:47 sexpbot: ⟹ clojure.lang.LazySeq

15:47 jcromartie: &(type (seq (range 10))

15:47 sexpbot: java.lang.Exception: EOF while reading

15:47 jcromartie: &(type (seq (range 10)))

15:47 sexpbot: ⟹ clojure.lang.ChunkedCons

15:48 _fogus_: cemerick: Sorry... not I

15:48 cemerick: _fogus_: yeah, it was a longshot. I've had good luck asking longshot OT questions here, though.

15:50 jcromartie: looks like seq returns chunked seqs

15:50 for some types

15:51 raek: it just returns whatever was wrapped in the (lazy-seq ...) form inside the definition of range

15:59 jweiss: i'm a bit confused about zippers. all my nodes are the name type - a map. each node can have a :links key, whose value is a seq of other nodes (children).

15:59 so isn't my "branch?" function (constantly true)?

16:00 since all my nodes are branches (whether they actually have children or not)

16:00 amalloy: jweiss: yes. why is that confusing?

16:00 and your children function is just :links

16:01 jweiss: amalloy: well, it isn't but the zipper doesn't seem to work. each node (if i call zip/node) still has all the children in it.

16:01 i kinda expected not to see them

16:02 amalloy: what do you mean, still has all the children? zip/node returns the exact data structure that you have it

16:03 jweiss: amalloy: i am confused about the zipper model. it's calling it a node, when the way it behaves seems like it's returning the entire tree for which that node is a root.

16:03 amalloy: so if your map is {:name "test" :size 10 :children [{:name "foo"}]}

16:04 then that map is the node

16:04 jweiss: hm, ok. i was expecting all the nodes to be the same size as i walked from root to leaf.

16:04 but they actually get smaller and smaller.

16:04 amalloy: it doesn't know how to "take out" the children-related data. how could it? it just knows that this map is a data point, and to get the children of that data point, it calls (:children the-map)

16:05 jweiss: amalloy: yeah, i understand. it's the nomenclature that had me thinking the wrong way.

16:05 it's not a node, it's a branch.

16:05 amalloy: only if you want to think of it that way

16:05 robonobo: Hi guys

16:06 How would i find the index of the greatest element in a seq?

16:07 amalloy: robonobo: you can do it, but usually messing with indexes is the wrong way to go

16:07 jweiss: amalloy: what is the point of zip/path then? it returns [entire tree, subset, smaller subset, etc]

16:08 amalloy: jweiss: it gives you zip nodes, not your data elements

16:08 jweiss: the data element of the first item in the path is the entire dataset

16:08 robonobo: amalloy: I know, but it is pertinent in this context

16:08 amalloy: &(first (apply max-key second (map-indexed identity [4 1 6 8 0])))

16:08 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$identity

16:08 amalloy: &(first (apply max-key second (map-indexed vector [4 1 6 8 0])))

16:08 sexpbot: ⟹ 3

16:09 amalloy: &(first (apply max-key second (map-indexed vector [4 1 6 -8 0])))

16:09 sexpbot: ⟹ 2

16:09 amalloy: robonobo: ^

16:09 robonobo: wow, I would have thought that to be simpler

16:11 amalloy: robonobo: perhaps there is a simpler way, but this is straightforward enough for me. why write a standard-library function to do something you should rarely do?

16:11 robonobo: amalloy: true

16:12 amalloy: and it's fairly clear what it's doing. turn a seq of data items into a seq of [idx, data] pairs; find the element with the largest data item; get the index of that element

16:30 simard: is there a way to do something like this (ie.: the problem seems to lie with the % signs) ? (map #(map #(identity %) %) (partition 5 big-number))

16:30 Nested #()s are not allowed

16:30 hum

16:30 clear enough

16:31 fogus_away: simard: You don't need #() around identity

16:31 brehaut: the use of identity there is just a placeholder right?

16:31 simard: brehaut: yeah just to make sure this is working

16:32 brehaut: clojurebot: partition

16:32 clojurebot: partition is probably not what you want; see partition-all.

16:33 amalloy: simard: i think fogus_away's point was that "#(foo %)" can be more concisely written as "foo"

16:33 simard: nah I really want partition :)

16:33 amalloy: brehaut: that's interesting; i usually want partition

16:34 for things like ##(partition 2 1 (range 6)) to get a seq of pairs

16:34 sexpbot: ⟹ ((0 1) (1 2) (2 3) (3 4) (4 5))

16:34 brehaut: amalloy: however a lot of people who dont realise both exists actually want partition-all

16:34 oh yeah for sure, partition-all is messy there

16:35 amalloy: i think partition-all would give me (5) as an extra "pair"

16:35 brehaut: yeah it would

16:37 ossareh: afternoon all

16:37 brehaut: ossareh: its always morning in UGT

16:38 ossareh: UGT?

16:38 clojurebot: ugt is Universal Greeting Time: http://www.total-knowledge.com/~ilya/mips/ugt.html

16:38 ossareh: ah :)

16:38 technomancy: ~botsnack

16:38 clojurebot: thanks; that was delicious. (nom nom nom)

16:39 ossareh: In all my years on IRC I've never heard of ugt - awesome!

17:06 TimMc: I think it has been making the rounds again recently.

17:07 ...unless I first heard about it here, in which case it is not indicative of a trend. :-P

17:12 simard: is it possible to have a seq be indexed through (nth) without all elements before the nth element to be evaluated ? (it would depend of the seq of course, some are recursively defined, but others are not..) could anyone enlighten me on this ?

17:12 or give a pointer anyway

17:17 Cozey: is there some function to updated an element of a list using a predicate to determine which one? (the new value will also be calculated from old value + something else)

17:21 brehaut: Cozey: asside from (defn map-if [pred f s] (map #(if (pred %) (f %) %) s)) ?

17:23 Cozey: brehaut: not bad!

17:23 brehaut: Cozey: it does strike me that a list is the wrong tool for the job though

17:24 Cozey: brehaut: perhaps - but what if i want to manipulate some ordered collection of data? I'd like to keep the order

17:25 brehaut: ordered or sorted ?

17:27 Cozey: ordered

17:29 I have a list of symbols and another equaly long list of classes. I want to create a structure like [ [class1 item1 item2 item3] [class2 item1 item2 item3... ] ... ] with items partitioned for each class. the order of classes should be the same as they 'appear' in list of classes, so if classes are: a c b b a a, it should be: a c b

17:30 (if symbol has the same position as class in it's list, it belongs to that class)

17:35 jweiss: is there some kind of gotcha in writing a closure like this? http://www.fpaste.org/Zz0y/ - the function it returns is behaving really oddly. seems to work fine when called from the repl directly, but when i call another function that calls it (with the same args), from the same namespace, it does nothing.

17:36 it could be a lot of things, but I suspected closure issues

17:37 Chousuke: should work fine

17:37 are you sure there's no laziness involved?

17:37 or dynamic binding :P

17:38 Cozey: contains? for vectors?

17:39 Chousuke: sounds inefficient ;/

17:39 Cozey: :-) should i use a map then?

17:42 brehaut: Cozey: contains? doesnt do what you expect for vectors - it only tells you if the index is contained in the vector

17:43 Cozey: yes but is there a function to check if vector contains a value?

17:43 or should I do this with some

17:43 brehaut: i dont think there is

17:43 you could do it with some

17:43 its linear search though

17:43 Cozey: yes

17:44 brehaut: im sure chouser has a finger trees solution for you ;)

17:47 TimMc: Looks like I can't :use namespace A in both B and C and then :use B in C.

17:47 Can someone confirm/deny?

17:47 brehaut: as long as its not circular i think you should be fine

17:48 amalloy: TimMc: yeah, that should work

17:49 B won't re-export A's symbols, which would be a problem

17:51 TimMc: Hah, I forgot to delete what I moved to A from their original home in C. >_<

17:51 Hitting save would help.

17:53 amalloy: Cozey: if you want to keep an ordered list but also know what's in it at any given time, you can maintain in parallel a hashset of its values

18:00 Cozey: i think this is what i'll do

18:28 pdk: hm

18:28 would there be anything special to worry about for writing a multimethod with multiple arities

18:30 amalloy: pdk: no. your dispatch function just needs to handle all the same arities

18:31 pdk: hm

18:31 in this case arity won't affect the dispatch values

18:31 so if i were to write the multimethod to take [x & y]

18:31 and one of the methods to take ([x] [x y]) i'm hoping it'd still interpret it right

18:32 amalloy: indeed, or [[x]]

18:32 (instead of [x & y])

18:32 pdk: in this case it'll be 1/2 args

18:33 actually would there a quick way to inline default values for optional args with the destructuring syntax

18:33 or do i just stick (or optional-arg default-value) all over the place

18:39 amalloy: pdk: it's easy for args that are passed in a map. i don't know how to do it otherwise

18:39 &(let [{a :value b key :or {a 10}} {:key "hello"}] [a b])

18:39 sexpbot: ⟹ [10 nil]

18:40 amalloy: &(let [{a :value b :key :or {a 10}} {:key "hello"}] [a b])

18:40 sexpbot: ⟹ [10 "hello"]

18:40 pdk: it'd be nice if there was a guide that explained destructuring specifically in the context of fn argument lists

18:40 amalloy: pdk: there's no need to

18:40 pdk: since i'm doubting everything given with destructuring for let bindings still applies with an arg list but

18:40 amalloy: it does

18:41 pdk: \o/

18:41 amalloy: ((fn [a & b] 10) => (let [[a & b] [10]])

18:41 ie, just wrap the formal and actual parameters in a vector, and you're done

18:42 first example should read ((fn [a & b]) 10)

18:45 TimMc: Do :import and :use etc. have the same parameter structure (modulo quoting) that import and use do?

18:46 amalloy: TimMc: yes

18:46 pdk: i've never seen a case where they had to be different

18:46 aside from perhaps not needing '

18:46 TimMc: OK.

18:46 amalloy: and you don't need to quote either import or :import, btw

18:46 TimMc: really?

18:47 amalloy: &(import java.util.ArrayList)

18:47 TimMc: Where can I find an explanation of the complete syntax available in import, require, etc?

18:47 sexpbot: ⟹ java.util.ArrayList

18:47 pdk: it used to be you needed to quote them in early versions

18:47 they're changed to be macros now so you don't anymore

18:47 TimMc: I see a bunch of examples, but no complete grammar.

18:47 amalloy: pdk: no

18:47 &(meta #'import)

18:47 sexpbot: ⟹ {:macro true, :ns #<Namespace clojure.core>, :name import, :file "clojure/core.clj", :line 2617, :arglists ([& import-symbols-or-lists]), :added "1.0", :doc "import-list => (package-symbol class-name-symbols*)\n\n For each name in class-name-symbols, adds a mapping ... http://gist.github.com/832984

18:47 amalloy: oh. hm, maybe so, sorry

18:47 pdk: neener neener

18:48 amalloy: *hang head in shame*

18:48 &(meta #'use)

18:48 sexpbot: ⟹ {:ns #<Namespace clojure.core>, :name use, :file "clojure/core.clj", :line 4871, :arglists ([& args]), :added "1.0", :doc "Like 'require, but also refers to each lib's namespace using\n clojure.core/refer. Use :use in the ns macro in preference to calling\n this di... http://gist.github.com/832985

18:49 amalloy: i don't get why it would be a macro though. i mean, you can use the classnames without quoting; is it just so that you get a symbol instead of a class object?

18:49 &java.util.regex.Pattern

18:49 sexpbot: ⟹ java.util.regex.Pattern

19:17 cdddr: This is probably silly, but is there a magical way of getting a list of common elements on two *sorted* sequences, or am I safe in writing that alone? :)

19:21 TimMc: Ha, someone (in meatspace) was just talking about being asked that as an interview question.

19:21 (given two unsorted sequences, find the common elements -- the answer involved what you're doing)

19:22 cdddr: This *is* trivial in any Lisp for sorted seqs, I'm just wondering if there's a neat way I didn't think of. :)

19:23 Despite: I love catonmat.net's set operations in the unix shell page. intersection is 'comm -12 <(sort set1) <(sort set2) '

19:24 I never realized how often I needed set ops until I read that page

19:24 TheBusby: cdddr: 10 different ways jump to mind. Are you looking for the fastest, shortest, or most clojuresque way?

19:25 cdddr: TheBusby: The clojuresque way, seeing as I'm still learning and this isn't time-critical.

19:26 Also - 10? Hah, I could only think of 3 off-hand. ;)

19:26 TheBusby: are the elements unique in each set?

19:27 cdddr: Yup.

19:27 Ahhh, I see.

19:27 TheBusby: "set" being the keyword ;)

19:28 cdddr: Yeah, I got too focused on the sorted part to notice. :>

19:29 TheBusby: it hides in 'clojure.set so I forget about it frequently as well

19:41 simard: what's better, (apply max (range 1 1000)) or (reduce max (range 1 1000)) ?

19:42 cdddr: I

19:45 Max being explicitly defined with more, I'd go with the former.

19:46 simard: makes sense.. both take the same amount of time

19:46 (though)

19:46 is there a way to measure the memory required ?

19:46 in the same way you measure (time...)

19:47 cdddr: Well, I'd guess max is defined in terms of a macro for more arguments - one that's basically equivalent to the reduce.

19:47 simard: so you'd save one step

19:47 cdddr: So they're likey to work just the same under the hood.

19:47 simard: the macro expansion

19:48 (well, one macro expansion)

19:48 cdddr: I'm with Knuth on optimization - if it works, stop caring. ;)

19:48 simard: sure :)

20:07 Mec_: ,(isa? #() clojure.lang.IFn)

20:07 clojurebot: false

20:07 technomancy: Mec_: you want instance?

20:08 Mec_: ,(instance? #() clojure.lang.IFn)

20:08 clojurebot: java.lang.ClassCastException: sandbox$eval1323$fn__1324 cannot be cast to java.lang.Class

20:08 Mec_: ah

20:08 brehaut: ,(ifn? #())

20:08 clojurebot: true

20:08 technomancy: ,(instance? clojure.lang.IFn #()) ; yay consistency

20:08 clojurebot: true

20:09 Mec_: ah thank you both

20:09 brehaut: Mec_ most of the standard types have predicates like that too

20:10 ,[(fn? #()) (fn? {}) (ifn? {}) (map? {})]

20:10 clojurebot: [true false true true]

20:12 Mec_: What's the difference between an Fn and an IFn?

20:12 brehaut: not all iFns are fns

20:12 you can make anything act like afunction, but that doesnt make it a function

20:13 ,(apropos "?")

20:13 clojurebot: java.lang.Exception: Unable to resolve symbol: apropos in this context

20:13 brehaut: ##(apropos "?")

20:13 sexpbot: java.lang.Exception: Unable to resolve symbol: apropos in this context

20:14 brehaut: ##(use '[clojure.repl :only [apropos]])

20:14 sexpbot: ⟹ nil

20:14 brehaut: ##(apropos "?")

20:14 sexpbot: ⟹ (superset? subset? alert-time? impl-enabled? enabled? logged-in? has-privs? -?>> .?. seqable? -?> is-blacklisted? is-command? leftmost? auto? rightmost? connection? keyword? chunked-seq? instance? sequential? fn? nil? string? sorted? false? true? odd? symbol? thread-... http://gist.github.com/833071

20:14 Mec_: ##(doc -?>>)

20:14 sexpbot: java.lang.Exception: Unable to resolve var: -?>> in this context

20:14 brehaut: -?>> is in clojure.contrib.core

20:15 its like ->> but if any of the forms return nil, the whole expression returns nil

20:15 Mec_: thats what i thought

20:15 I use -> and ->> for everything so I don't have to read inside out, does that mean I'm doing it wrong? :D

20:16 brehaut: nope

20:16 well, depends what you mean by everything ;)

20:16 sometimes just using a let is clearer ;)

20:16 Mec_: just by assigning each step a name?

20:16 brehaut: yeah

20:17 Mec_: makes sense

20:17 brehaut: if each expression is complex its good, because then youve got cognitifve assistence for determing the what and why of each

20:18 also if you are doing something like (-> mapmapmap :a :b :c) consider (get-in mapmapmap [:a :b :c])

20:21 Mec_ and of course, if you have something like (defn foo [a] (-> inc inc)) you could do (def foo (comp inc inc))

20:21 amalloy: brehaut: meh. get-in doesn't strike me as much clearer really

20:21 Mec_: I was just thinking about using comp more, but its still a bit backwards

20:22 brehaut: exactly why thrush should be in core :P

20:23 technomancy: you let one bird in and all the others are going to want in as well; soon we'll have kestrels, larks, even doves clamoring for admission.

20:23 err--wait, we already have kestrel.

20:24 brehaut: hah

20:24 Mec_: whats thrush

20:24 brehaut: ~comp backwards

20:24 clojurebot: the scala compiler | is | <reply> see: http://harrah.github.com/browse/samples/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala.html#65760

20:24 brehaut: wow that isnt something i expected

20:25 Mec_: http://www.angelfire.com/tx4/cus/combinator/birds.html

20:25 Mec_: owe my eyes

20:25 brehaut: http://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/

20:26 TimMc: Given a unary function, how can I easily iterate (f (f (f (f x)))) a set number of times?

20:26 brehaut: 'owe my eyes' is using 'OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO' as shorthand for ">="

20:27 amalloy: TimMc: try: ##(doc iterate)

20:27 sexpbot: ⟹ "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"

20:27 TimMc: And then use nth?

20:28 amalloy: yeah

20:28 TimMc: Ha, OK.

20:28 amalloy: TimMc: or if you want, ##((apply comp (repeat 10 inc)) 2)

20:28 sexpbot: ⟹ 12

20:28 TimMc: I saw iterate, but passed it by -- I need to get more into functional thinking patterns.

20:29 THat's pretty cute.

20:29 amalloy: i stole it from technomancy, i think

20:30 TimMc: comp looks pretty useful.

20:30 Mec_: my favorite use of iterate is ##(take 10 (map first (iterate (fn [[a b]] [b (+ a b)]) [1 2])))

20:30 sexpbot: ⟹ (1 2 3 5 8 13 21 34 55 89)

20:30 technomancy: dinc!

20:31 amalloy: technomancy: yeah, as soon as i hit enter i regretted using 10 instead of 8

20:32 technomancy: amalloy: well to be fair yours is 25% more effective than oinc.

20:32 amalloy: technomancy: moore's law

20:32 it's been a few months

20:33 technomancy: astounding.

20:37 jnymo_: hi

20:38 Mec_: I don't really see the benefit of thrush, it's seems like threading but every form has to be a function

20:38 jnymo_: I wonder if it'd be possible to do multi-threading with web-workers, for that cojure-js thing.

20:46 simard: clojurebot: partition

20:46 clojurebot: partition is probably not what you want; see partition-all.

20:48 technomancy: ~botsnack

20:48 clojurebot: thanks; that was delicious. (nom nom nom)

21:53 simard`: in this example, is def'ining just4 a problem for memory ? (def just4 (repeat 4)) (take 99999 just4)

21:54 amalloy: yes

21:54 simard: yes it's a problem ?

21:56 amalloy: you asked a yes/no question and got a yes answer. what are you looking for by asking me again?

21:57 simard: just to make sure I didn't miss anything when I left the channel actually.. :P

22:22 TimMc: How is (repeat 4) memory-intensive?

22:23 brehaut: TimMc: you are holding onto the head ofthe seq

22:23 (probably)

22:23 eg (let [four (repeat 4)] (take 100000 four)) is memory intensive (take 1000000 four) is not

22:24 TimMc: (take 1000000 (repeat 4)) you mean?

22:24 brehaut: yeah i do mean

22:25 make sense?

22:25 TimMc: I need to learn more about seqs. I thought they were just generators that didn't hold any stuff beyond what they were given.

22:25 brehaut: sort of

22:25 they are (conceptually at least) immutable though

22:26 TimMc: Ah, but internally cache stuff?

22:26 brehaut: nah simplier

22:26 unlike an iterator/generatoe next/rest doesnt modify the seq you have,it returns a new seq

22:26 like a lazy linked list

22:27 TimMc: Oh!

22:27 So you are preventing the GC from collecting the intermediate nodes?

22:27 brehaut: bingo

22:27 TimMc: sneaky

22:28 * TimMc frowns

22:28 brehaut: its teh one gotcha from having really good seqs

22:28 they allow a lot more expressiveness than the traditional iterator

22:28 TimMc: (rest some-seq) holds a pointer to some-seq, yes?

22:29 brehaut: no

22:29 seqs are singly linked

22:29 like a cons cell

22:29 TimMc: I don't understand the object graph then.

22:29 brehaut: (cons 1 (cons 2 (cons 3))) ; the tail of each cons knows nothing about the cell its contained in

22:30 TimMc: sure

22:30 brehaut: rest returns a new thing from a seq

22:30 that new thing is the tail

22:30 TimMc: But a seq like (repeat ...) is not a concrete linked list.

22:30 brehaut: no

22:30 its a conceptual one

22:32 as you realise a lazy-seq it becomes concrete though

22:34 TimMc: OK, so (repeat x) is (lazy-seq (cons x (repeat x)))

22:34 (reading the source)

22:34 brehaut: yup

22:37 TimMc: So wait... walking through that seq builds up a cons chain?

22:37 brehaut: yes

22:37 TimMc: I'm having a little trouble understanding the mechanics behind realization.

22:37 brehaut: ok heres the interface for a seq

22:37 https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/ISeq.java

22:38 i have no idea what more does

22:39 TimMc: lazy-seq just looks like magic to me.

22:39 brehaut: i tried to make an example with reify but i failed

22:39 it is

22:39 ;)

22:39 basicly it creates a 'thunk'

22:39 a thunk is a promise to compute some value later

22:40 TimMc: yes

22:40 brehaut: that is then replaced with that value

22:40 the mechanics of lazy-seq arent actually too important to grok what is going on

22:41 simard: hum nice job on clojars and leiningen.. it's really easy

22:44 TimMc: brehaut: Oh! clojure.lang.LazySeq uses internal mutation.

22:45 I'm not confused anymore.

22:45 brehaut: yeah thats why its conceptually immutable

22:45 TimMc: ...but can still build up an object graph extending from the head.

22:45 brehaut: yeah you can do real tricky stuff with it

22:46 in haskell they have a trick they call 'tying the knot'

22:46 where you make the tail of one list its own head

22:47 TimMc: So... seqs are "immutable" but can still do things that look like mutation, which means you have to treat them like realized lists in some ways.

22:47 brehaut: dont think ofthem as tricky

22:47 they _dont_ look like mutation

22:47 thats the cool part

22:47 the tail of lazy-seq may contain unrealized values

22:48 as soon as its realized (ie observed for the first time) it has a value, and that value never changes

22:49 TimMc: So I should think of any seq as "an existing singly-linked list that may be lazily computed."

22:49 THat covers the holding-onto-the-head problem.

22:50 brehaut: yeah i think thats ok

22:56 tomoj: I wonder if channels and seqs are dual

22:57 similar to IObservable/IEnumerable but better?

22:59 brehaut: could be eh

23:12 simard: how do you guys start your inferior-lisp-process so that the classpath is set properly to that required by your current lein project ?

23:14 amalloy: cake swank

23:14 or lein swank

23:16 semperos: or just set inferior-lisp-program to "lein repl", if you don't use slime

23:37 technomancy: there's also lein classpath

23:37 talios: and mvn clojure:swank

23:38 * talios really needs to kick start some code on that again

23:47 simard: hum running "lein swank" -> "That's not a task."

23:47 swank-clojure is running though

23:47 technomancy: swank isn't used with inferior-lisp-process

23:48 you can just do java -cp `lein classpath` clojure.main as your inf-lisp

23:49 pdk: (doc take)

23:49 clojurebot: "([n coll]); Returns a lazy sequence of the first n items in coll, or all items if there are fewer than n."

23:49 simard: oh these backticks will work directly in that var ?

23:49 nice

23:50 technomancy: simard: err--actually no

23:50 simard: oh well I'm connected with slime-connect to swank-clojure right now

23:52 technomancy: oh sure, if you want to use slime you don't need to set inf-lisp-anything

23:52 pdk: (doc repeatedly)

23:52 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"

Logging service provided by n01se.net