#clojure log - Jul 14 2011

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

0:00 amalloy: then the whole problem just reduces to ##(partition-by identity [1 1 2 1 1 1 3 3])

0:00 sexpbot: ⟹ ((1 1) (2) (1 1 1) (3 3))

0:01 jamiltron: Ah that's interesting.

0:01 amalloy: also if you find yourself using first/rest much, step back and consider destructuring

0:03 jamiltron: I need to get more practice at destructuring.

0:06 amalloy: &((fn [[head & tail]] {:head head, :tail tail}) '(some list with stuff))

0:06 sexpbot: ⟹ {:head some, :tail (list with stuff)}

0:15 amalloy: jamiltron: you might also like a couple things i've written. basically case studies of iterative refactoring in clojure: http://hubpages.com/hub/The-evolution-of-an-idea and http://groups.google.com/group/clojure/browse_thread/thread/ac2c7ce8d57f36bb/7aed5adae7bb3450?show_docid=7aed5adae7bb3450

0:17 jamiltron: Nice, I'll bookmark those.

0:17 Thank you.

0:26 zakwilson: Is there a way with sandbar.stateful-session to get at and modify a list of all the sessions? I'm writing code to block users and I want to destroy their session if they're logged in.

0:34 ihodes: zakwilson: why not just invalidate their session server-side?

0:34 zakwilson: you're talking about actually changing their cookie? that isn't secure.

0:35 zakwilson: I'm talking about writing a function that says "if user ID 5 is logged in, log them out"

0:55 ihodes: zakwilson: i think it's in the sandbar-session atom in the stateful-session namespace. take a peak in there

1:00 zakwilson: ihodes: sandbar.stateful-session/sandbar-session is unbound except in threads called from the function returned by its wrapper.

1:12 amalloy: zakwilson: actually destroying ring cookies sounds hard. why not just insert another middleware between you and ring, which you can add "destroyed" sessions to? then if it sees an incoming request associated with a destroyed session, unset the session before calling the rest of your stack

1:13 zakwilson: amalloy: that was plan B.

2:21 amalloy: does a macro exist in core to transform (something expr1 expr2) into something like (map (fn [f] (f)) (list (fn [] expr1) (fn [] expr2)))? that is, take a series of expressions and return a seq that lazily evaluates them?

2:22 i saw a form that looked like (or (f expr1) (f expr2) (f expr3)) and wanted to transform it into (some f [expr1 expr2 expr3]), but if any expressions are costly that ruins the short-circuiting. i wrote the macro myself to enable (some f (lazily expr1 expr2 expr3)), but if it's in core i'd rather use it

2:44 tsdh: Stupid question, but are the current clojure java api docs online somewhere?

2:45 There's pacific.mpi-cbg.de/javadoc/, but isn't there some official site?

2:47 amalloy: tsdh: the clojure java api docs?

2:47 aja: tsdh: the canonical java API would probably be on Oracle's site.

2:48 amalloy: $javadoc String

2:48 sexpbot: http://download.oracle.com/javase/6/docs/api/java/lang/String.html

2:48 amalloy: is where the ordinary javadoc is

2:48 tsdh: Sure the clojure java API docs. :-)

2:48 amalloy: but if you're looking for something clojure-specific you're unlikely to find it, especially if you don't clarify what "clojure java api docs" means :P

2:48 tsdh: $javadoc IPersistentCollection

2:48 sexpbot: Javadoc not found. Try http://download.oracle.com/javase/6/docs/api/

2:49 amalloy: nobody wrote javadoc for that stuff

2:50 tsdh: amalloy: Yes, but still you'd have at least a listing of signatures.

2:50 amalloy: reading the source for interface declarations is pretty easy. for concrete implementations, that's harder

2:50 there's also clojure.contrib.repl-utils/show

2:51 tsdh: Ok, nevermind.

2:54 aja: tsdh: That interface isn't part of the java api, as far as I can tell. It's from clojure. Google doesn't seem to have trouble finding docs.

2:55 tsdh: Yes, it's a clojure interface and you can find it with google. But that's no official clojure site, so I cannot know what version that is.

2:57 amalloy: tsdh: clone the clojure git repo

2:57 that's how i answer questions about clojure internals

2:58 aja: tsdh: Clojure.org is as close to a dt

2:59 amalloy: dt?

2:59 tsdh: amalloy: Yeah, *I* have it. We (my working group) want to switch from standard java collections to persistent, immutable collections in our graph library. So it seems there are 2 candidates: clojure's stuff and pcollections. On the one hand, I'm somewhat in favour of pcollections, because of their nicer java interface (generics). On the other hand, lately I use more and more clojure working with that library...

2:59 aja: tsdh: Standard as you'll be able to find. As amalloy said, internals are basically from the reference implementation.

3:01 mikesomething: why do i get this?

3:01 CompilerException Either this object does not exist, or this user does not have permission to access it.

3:02 amalloy: i'm guessing you're trying to work with an object that either doesn't exist or you don't have permission to access. without more details, it's hard to guess anything more useful

3:02 tsdh: amalloy: haha!

3:02 mikesomething: (def rept_utils (new com.google.api.adwords.lib.utils.ReportUtils user (long 1234)))

3:02 #'google/rept_utils

3:03 sorry, i'll do a pastie

3:04 http://pastie.org/2211207

3:04 how do i get permission to access?

3:06 amalloy?

3:06 amalloy: maybe that's clojure telling you not to access non-public members? i dunno

3:06 clojurebot: amalloy: therfor I return [previous] if rest is empty

3:07 mikesomething: it is a public member

3:07 http://google-api-adwords-java.googlecode.com/svn-history/r171/trunk/docs/com/google/api/adwords/lib/utils/ReportUtils.html

3:07 amalloy: clojurebot: you can't at least find a juxt quote?

3:07 clojurebot: syntax-quote is very hairy

3:08 amalloy: *shrug*

3:09 mikesomething: can i use reflection to call that?

3:20 amalloy: clojurebot: amalloy is <amalloy> just use juxt, it'll be great

3:20 clojurebot: Alles klar

5:14 clgv: I wonder whether I should prefer anonymous function closures over partial or vice versa? (limited to the case where partial is applicable, i.e. #(do-something outer-val ...) vs (partial do-something outerval) )

5:19 bsteuber: clgv: probably just a matter of taste, but I prefer #() for brevity and consistency with cases where partial doesn't apply

5:20 clgv: ok.

5:23 ejackson: i'm the opposite, I ilke partial as it clues me in to the semantics of what I'm doing

5:34 ZabaQ: I'm toying with Clojure, but one aspect I'm finding hard to work with is the error messages..I'm finding it hard to work backward from a jvm runtime error to a clojure bug..any tips for debugging welcome..

5:34 I'm from a CL background, not a Java one ..

5:35 bsteuber: ZabaQ: yeah, that's really one of clojure's current weaknesses

5:36 but when you have a specific exception, you can always ask here

6:09 tsdh: Is there an i>

6:09 ups...

6:09 Is there an integer division function in clojure?

6:10 Ah, `quot'.

6:29 * fliebel learnt something new from tsdh

6:51 shtutgart: Is it possible to specify ranges for Incanter chart? e.g. I want to always have numbers from 1 to 100 on the y-axis

6:55 tsdh: Why does (class (int (+ 1 1))) return java.lang.Long in clojure 1.3?

7:00 talios: ,(class (int (+ 1 1)))

7:00 clojurebot: java.lang.Integer

7:00 talios: good question.

7:00 Dranik: hi all!

7:00 how can I idiomatically set utf8 charset through :content-type in ring?

7:01 tsdh: talios: That's clojure 1.2, isn't it?

7:02 clgv: tsdh: yes it is clojure 1.2

7:02 ,(clojure-version)

7:02 clojurebot: "1.2.0"

7:02 tsdh: Hm, ok. What works (but is ugly) is (class (Integer/valueOf (+ 1 1)))...

7:02 shtutgart: Dranik: I have (defn wrap-codepage [handler] #(content-type (handler %) "text/html; charset=utf-8"))

7:03 Dranik: shtutgart: let me try...

7:04 shtutgart: thanks!

7:04 shtutgart: np

7:46 Gamli: $findfn even? [2 4 6 20 90] true

7:46 sexpbot: [clojure.core/not= clojure.core/some clojure.core/distinct? clojure.core/every?]

7:56 aleonhardt: hi, everyone. i'm building a toy project in clojure that requires http ("rest") communication. if possible at all, i want to avoid using apache httpcomponents directly. what's the "state of the art" for clojure http client libraries?

7:57 it's hard to tell which forks of which projects are abandoned, and which ones are not.

7:57 talios: aleonhardt: https://github.com/neotyk/http.async.client - built ontop of the awesome async-http-client

7:59 aleonhardt: talios: cheers. would you recommend that over clj-http?

8:00 talios: i've not tried the http.asynch clojure port, but I use asynch all the time. much nicer. been awhile since i've used clj-http tho so not sure. but I think it will be, as asynch uses nio and futures and all concurrent goodness

8:25 fliebel: Is there any Clojurey thing for doing tf-idf, k-means and all these things?

8:39 ejackson: fliebel: what is tf-idf ?

8:41 oh. Well the JVM is pretty weak all round for machine learning and math, actually

8:50 fliebel: ejackson: some bag-of-words metric. Why is the JVM weak for this?

8:51 ejackson: lack of libs

8:51 fliebel: ejackson: Hm, then I'll have to write my own.

8:51 ejackson: the best I came across was weka

8:52 which has an associated book

8:56 clgv: fliebel: there is a parallel implementation of a kmeans https://github.com/johannkraus/McKmeans

8:57 fliebel: clgv: pre-lein?

9:00 clgv: But yea, k-means can easily be split up into k tasks I guess.

9:00 I think I'm just going to port the "mining the social web" code.

9:00 clgv: fliebel: seems so. dont complain - you aksed - I remembered ;)

9:01 fliebel: clgv: Thanks for remembering, I might use it as a reference :)

9:05 ejackson: MacKays book has a good discussion k-means and suggests an algo to do it (newton raphson) that you could take as a reference too. The book is free online.

9:09 of course, the point of his discussion is that you should *not* use kmeans... :)

9:09 fliebel: ejackson: huh?

9:09 ejackson: yeah, its a probability density optimising algo, so has lots of pathologies.

9:10 put a cluster centre over a data point and lets its stdev go to zero and you get infinity probability density

9:10 oopsie !

9:11 so if you newton raphson bit actually work, you should find this as the maximum likelihood solution

9:16 fliebel: ejackson: this ? http://www.inference.phy.cam.ac.uk/mackay/itprnn/ps/284.292.pdf

9:17 ejackson: that's the first bit of it where he introduces kmeans

9:18 he then uses it in the following chapters as an example of a maximum likelihood algo and shows it blowing up

9:18 i think he actually print *KABOOOM* somewhere ;)

9:18 fliebel: ouch

9:19 ejackson: so he's make a much more general point

9:19 fabulous discussion

9:22 clgv: ejackson: but despite that the algorithm should remain applicable in certain problems?

9:23 ejackson: i would probably say no

9:23 clgv: application problems are often much easier than the worst-case theorists are concerned about

9:24 ejackson: but i'm a little strident

9:24 fliebel: clgv: So you're saying that running with k-means might be just fine?

9:25 clgv: fliebel: kmeans is still taught in some university lectures so I cannot imagine that it has entirely no use.

9:26 the question will be which characteristic your data has and how kmeans performs on that

9:27 fliebel: clgv: The only way to know is to try...

9:29 ejackson: the problem with machine learning stuff is exactly this. It might work, it might not, we might be able to determine if it has worked, but we might not... its too unsettling for me :)

9:30 * ejackson returns to being a crusty grumbler

9:31 clgv: ejackson: his kaboom is related to "soft k-means", if he describes another variant, he does not relate the problem to it.

9:31 ejackson: no, the point is general

9:32 clgv: but he says "Soft K-means can blow up"

9:32 would have to search the scipt to see which versions he defines

9:32 * ejackson reaches over for the book to see what he's no doubt misunderstood

9:32 clgv: no time for that right now ;)

9:33 ah there is an enhancement described in 22.3

9:33 ejackson: but trust me on this, any ML algo will bite you in the eye eventually

9:34 clgv: I dont do clustering .... yet ;)

9:34 jweiss: is there a better way: (last (take-while f (iterate g 0)))

9:34 clgv: what is your ML algo?

9:34 jweiss: i just want the last value, but don't want to traverse the list

9:35 clgv: jweiss: recursion with loop-recur?

9:35 ejackson: clgv: what is my ML algo ?

9:36 jweiss: clgv: yeah, i suppose i meant a functional way :)

9:36 i guess i could try trampoline

9:36 clgv: ejackson: yeah. you used that abbreviation

9:36 ah any ^^

9:36 ejackson: oh sorry, maximum likelihood

9:36 jweiss: actually that won't really help me

9:38 ejackson: clgv: lots of probability space have points of infinite density, but no mass, and any maximum likelihood algo, if it works, will find these, despite the fact that they are useless.

9:39 be it k-means, soft kmeans, or whatever.

9:41 clgv: ejackson: but that doesnt mean in general that the specific problem I have has these points

9:41 ejackson: not does it tell you that it does not

9:41 and you have no way of knowing up front if this is the case

9:42 unknown unkown, Rumsfeld style.

9:42 clgv: If I have means to analyse the properties of my problem instance I might be able to tell

9:44 ejackson: sure, and I'd encourage that. But the suck it and see attitude the pervades a lot of what passes as research in machine learning is a one way ticket to a self applied lobotomy.

9:44 ooh, dear, I am getting stident :)

9:45 clgv: lol

10:02 fliebel: what do cake/lein do when finding a conflicting version? Especially for Clojure itself.

10:03 clgv: fliebel: evil grinning at you ;)

10:04 ejackson: KABOOM

10:04 :P

10:04 fliebel: clgv: That's the thing, it just seems to swallow hard and make a decision. I never had a conflict.

10:05 clgv: fliebel: I didnt actually try it.

10:11 fliebel: The reason I want to know is because I'd like to use 1.3, but I don't know what will happen with dependencies.

10:30 technomancy: fliebel: whatever's closer to the root of your dependency tree wins

10:38 edw`: Is it gauche to name a non-func with a question mark e.g. (let [required? (:required options)] ...)?

10:41 jweiss: is this a bug in clojure.zip? seems you cannot edit a loc when you're at the 'end'. (-> (zip/seq-zip [1]) zip/next (zip/edit identity))

10:41 gives "clojure.lang.Keyword cannot be cast to clojure.lang.Associative"

11:06 fliebel: technomancy: Thanks, so I guess that means that if 1.3 does not break things, I can use it.

11:11 devn: cemerick: what, you don't want (fn) aliased to (ƒ)?

11:11 cemerick: ;)

11:11 scgilardi: jweiss: http://www.exampler.com/blog/2010/09/01/editing-trees-in-clojure-with-clojurezip/ says "Notice also that I explicitly wrapped the tree in a seq. If you use seq-zip on an unwrapped vector, you’ll get confusing results."

11:12 that does seem to solve it

11:13 cemerick: devn: snowman would be funner :-D

11:13 scgilardi: (-> (zip/seq-zip (seq [1])) zip/next (zip/edit inc) zip/root)

11:13 cemerick: devn: I distinctly remember there being discussions a long while ago about how λ should be defined in clojure.core as an alias for fn.

11:13 tsdh: Is there something better than (first (for [a (lazy-seq) b (lazy-seq) :when (pred a b)] [a b])) to get the first a and b matching pred?

11:13 cemerick: Didn't go far, as you can imagine.

11:14 devn: cemerick: the klingon destroyer UTF char!

11:14 fliebel: cemerick: I've seenan emcas setup that abbreviated to it.

11:14 cemerick: devn: wait, what?

11:16 devn: cemerick: http://www.evertype.com/standards/csur/klingon.html

11:17 if we're going to bring UTF into the fold as aliases for function names we might as well go all out!


11:18 enterprisey: fancy.

11:18 tsdh:

11:18 What a huge char...

11:18 enterprisey: hay guys I hav a featur request clojure should make str work like SQL! for enterprise programming!

11:18 (defn enterprise-str [& xs] (if (some nil? xs) nil (apply str xs)))

11:18 devn: bahahaha

11:19 jcromartie: seriously WTF is up with SQL

11:19 is that just T-SQL

11:19 ?

11:19 devn: &(inc jcromartie)

11:19 sexpbot: java.lang.Exception: Unable to resolve symbol: jcromartie in this context

11:19 devn: (inc jcromartie)

11:19 sexpbot: ⟹ 2

11:19 devn: there we go...

11:19 cemerick: devn: oh, private use range, OK. I thought I'd have known about it if it were a recognized char already. :-)

11:19 jcromartie: I think it is just Microsoft. It's because they are enterprise class.

11:20 devn: cemerick: :)

11:34 scgilardi: jweiss: see also vector-zip

11:35 jweiss: scgilardi: that was just an example, it does the same with my own zipper as well

11:35 not sure why it doesn't fail with vector-zip

11:36 scgilardi: have you looked at the source for seq-zip and vector-zip?

12:04 technomancy: wait, klingon is just a new orthography for latin letters?

12:04 I'm so disillusioned!

12:05 Scriptor: isn't the vocabulary different?

12:05 well, dumb question, they clearly have their own vocabulary

12:06 ejackson: technomancy: that's just federationocentric propoganda.

12:07 Scriptor: I'm never gonna understand emacs's C-x o

12:07 it switched between two irc chan buffers 6 times before going to another

12:59 cemerick: The ML is actually worse than I thought.

12:59 * cemerick just read the recent build tool thread :-(

13:00 technomancy: cemerick: luckily mike m. seems to be the only one daft enough to respond to wesson in most cases

13:02 cemerick: looks like you missed my answer last night; lein javac should run automatically before clojure AOT if :java-source-path is set in project.clj

13:04 cemerick: technomancy: Right, thanks. And no way to make it run after clojure AOT?

13:04 fliebel: What is this tf-idf impl doing? http://thecomputersarewinning.com/post/simple-tfidf-in-clojure The Py impl from "mining the social web" is much simpler: https://github.com/ptwobrussell/Mining-the-Social-Web/blob/master/python_code/buzz__tf_idf.py

13:05 technomancy: cemerick: for that you need hooks

13:06 cemerick: ah, so you can add a before hook to whatever var holds the AOT "task" and kick off javac yourself?

13:07 technomancy: (add-hook #'leiningen.compile/compile (fn [compile project & args] (apply compile project args) (javac project))) ; something like that

13:08 actually there's an robert.hooke/append macro that basically does that.

13:10 cemerick: technomancy: Got it, thanks. Are the hooks in lein documented anywhere? I'll add a footnote in the book if so.

13:11 technomancy: cemerick: it's not really leiningen-specific, so https://github.com/technomancy/robert-hooke is probably your best bet.

13:11 it just happens to be bundled with lein

13:13 ah, append/prepend won't work if the call you're appending needs access to the args of the hooked function, which javac does.

13:13 no real backwards-compatible way to support that without anaphora.

13:13 I love it when the docs for a library are longer than the implementation.

13:24 amalloy: technomancy: i think i'll start including-by-reference things like War and Peace in all my docs so i can get your seal of approval

13:26 technomancy: hm; I am really not up on my Russians =\

13:26 Brothers K is on my queue, but not near the head.

13:27 but don't let that put you off on your literary references!

13:48 jweiss: anyone know if it's possible to pass jvm args to 'lein run'? as in 'lein run -Dmy.prop=myval'

13:49 that doesn't actually work ^

13:49 amalloy: $google leiningen sample project.clj :jvm-opts

13:49 sexpbot: First out of 254 results is: technomancy/leiningen at master - GitHub

13:49 https://github.com/technomancy/leiningen/blame/master/sample.project.clj

13:50 amalloy: i wonder why it picked a blame

13:53 jweiss: amalloy: that doesn't really help me - i know i can put em in project.clj but i want to pass system properties that might be different for each run.

13:54 unless i can set jvmopts on the cmd line as well?

13:54 amalloy: i dunno what lein's solution to that is. cake has a notion of "contexts", which solve this problem neatly, but i don't know them very well

13:55 technomancy: jweiss: JVM_OPTS=foo lein run

13:55 jweiss: aha, should have thought of that. thanks technomancy

13:55 technomancy: sure

14:16 Dranik: hi all!

14:16 I'm trying to enable utf8 for my webapp using the function: (defn wrap-codepage [handler] #(:content-type (handler %) "text/html; charset=utf-8"))

14:17 I use it here: (def app (-> (handler/site main-routes) wrap-codepage wrap-session))

14:17 but it doesn't work. what I'm doing wrong/

14:17 ?

14:20 this is what I get: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentMap

14:21 amalloy: Dranik: you want to assoc the :content-type, not just return it

14:21 (defn wrap-codepage [handler] (fn [req] (assoc (handler req) :content-type "text/html; charset=utf-8")))

14:22 Dranik: let me try...

14:23 technomancy: have you guys used rep at all?

14:23 I've got to say I am a huge fan

14:23 http://clojars.org/rep

14:25 Dranik: this is what I've got instead of utf8: <html><body>??????, ???!</body></html>

14:26 technomancy, what's that?

14:26 technomancy: it's like repl, but without the l.

14:26 Dranik: are there any differences with usual repl?

14:26 technomancy: yes, it doesn't loop

14:26 mefesto: Dranik: shouldn't your wrap-codepage be returning a function that accepts a request and delegates to the handler?

14:26 Dranik: :-)

14:26 technomancy: don't get me wrong, sometimes you want to loop.

14:26 but

14:26 sometimes you don't!

14:27 Dranik: mefesto: I don't know that stuff well. can you show me how to do that correctly?

14:27 amalloy: mefesto: he does

14:27 note the #

14:27 mefesto: Dranik: https://gist.github.com/1083075

14:28 amalloy: oh i see it now... sry

14:28 Dranik: technomancy, for what tasks do you prefer rep?

14:28 amalloy: i think it's clearer the way i wrote it, with an explicit (fn [req]), but some people like #...there's just no accounting for taste

14:28 technomancy: Dranik: mostly joking, but it's nice for parallel cluster control.

14:53 amalloy: technomancy: i just write my whole program correctly in one go, so there's no need for a loop

14:53 technomancy: now we're talking

14:56 icey: why even bother with the P? you could just have a RE

14:58 Scriptor: really, you just need R

14:58 technomancy: brilliant; relentless pursuit of simplicity.

14:58 amalloy: i think just E is the important one

14:59 you can always malloc/new up the forms the reader produces by hand, and pass those to the runtime

14:59 icey: developing with RE is the "trust me, I got this" mode of development

15:07 amalloy: what's up with http://groups.google.com/group/clojure/browse_thread/thread/dbf4c482d5d7f0e1/963c16209cce044e ? i don't recognize the names, so i'd guess spam, but the group is moderated so maybe these are actual clojure developers?

15:13 dans: i cant get vimclojure to work - no syntax highlighting and nailgun keeps giving connection refused

15:14 https://gist.github.com/1083193 this is the error i keep getting

15:15 and :set ft? brings up filetype=, which is probably why the syntax highlighting doesnt work

15:15 it doesnt recognise a clj file as clojure

15:16 Scriptor: dans: in your vimrc, what do the lines you added for vimclojure look like?

15:20 sjl: dans: Are you running nailgun on your own or having vimclojure run it for you?

15:36 tsdh: Hi. Can someone explain me this protocol error? http://pastebin.com/3uQT9Pwh

15:39 amalloy: tsdh: well, i'd guess ge isn't something Delete-able. as an aside, delete! is easier to implement as (defn delete! [& things] (doseq [thing things] (delete! thing)))

15:40 tsdh: amalloy: But it errors at compile time, not when calling it.

15:41 amalloy: eeeenteresting. well, i don't know that much about protocols, but it compiles fine for me

15:41 (on clojure 1.2.1-

15:41 )

15:42 https://gist.github.com/1083265

15:43 tsdh: amalloy: Yes, that compiles for me, too...

15:44 Who needs Vertex and Edge when he has Integer and Double, right?

15:44 amalloy: indeed

15:46 tsdh: Argh, got it! Wanna guess?

15:46 Starts with A and ends with T.

15:47 amalloy: assault

15:47 tsdh: AOT

15:47 dans: sorry Scriptor , sjl

15:48 here is my vimrc https://gist.github.com/1083276

15:48 sjl: I'm trying and failing at both

15:48 the error i pasted was from within vim

15:48 tsdh: Yesterday, I AOT compiled some classes only to disassemble them to see what clojure creates for classes, but I forgot to "lein clean" afterwards.

15:48 s/classes/namespaces/

15:48 sexpbot: <tsdh> Yesterday, I AOT compiled some namespaces only to disassemble them to see what clojure creates for namespaces, but I forgot to "lein clean" afterwards.

15:52 sjl: dans: do you use lein?

15:54 Scriptor: gah, does vimclojure even have a project page anymore?

15:54 dans: sjl: yes

15:57 sjl: dans: lein plugin install vimclojure 1.0.0 ; cd myproj ; lein vimclojure

15:58 dans: 1.0.0?

15:58 sjl: (it's been a while since I did this, so I might be wrong -- I've switched to SLIMV for Vim+Clojure/Lisp now)

15:59 dans: I think so.

16:00 babilen: sjl: What were your reasons for the switch? I like vimclojure a lot, but have not really played with slimv yet. (I just use slimv's paredit)

16:01 dans: And the project page is https://bitbucket.org/kotarak/vimclojure

16:01 dans: thanks

16:01 i've been on that page

16:02 sjl: babilen: mainly I wanted as similar an environment as possible for Clojure and Lisp

16:02 dans: tried following everything thats said, but it jsut doesnt wanna work

16:02 sjl: I didn't want to have to learn two completely separate interfaces

16:03 and SLIMV's tutorial convinced me it was mature enough to be usable: http://kovisoft.bitbucket.org/tutorial.html

16:04 dans: i think ill try SLIMV then

16:04 does it also do syntax highlighting?

16:06 babilen: sjl: Ok, I can absolutely understand that. I was just curious what slimv would offer me over vimclojure as I like the latter a lot.

16:07 sjl: babilen: If you just do Clojure, then the answer is "not much of anything"

16:08 babilen: dans: vimclojure is a bit tricky to setup, because it basically consists of three parts that have to be present. 1. vim plugin 2. nailgun client 3. nailgun server

16:08 Scriptor: dans: looks like it doesn't, so I'd suggest using vimclojure just for that

16:08 sjl: dans: It does, but to be honest I cheated by forking SLIMV and replacing its Clojure syntax/indent files with the ones from VimClojure :)

16:08 babilen: sjl: heh :)

16:08 Scriptor: that's what I use it for anyway, though it's been a year or so since I set it up

16:09 dans: babilen: i'd be happy with just the syntax highlighting for the moment

16:09 nevermind nailgun

16:10 Scriptor: dans: then I think you should be fine just having the files copied to plugins, syntax, etcl

16:11 dans: i should be :(

16:11 Scriptor: hmm, take out anything that uses nailgun

16:11 (from vimrc)

16:13 babilen: dans: What I have done is essentially: 1. Use vundle for vim plugins (https://github.com/babilen/dotfiles/blob/master/vim/vimrc) 2. Compile the ng client from kotaraks repository and "install" it to ~/bin 3. lein-vimclojure from autre + nailgun server -- http://paste.debian.net/122913/ in project.clj -- But note that there is a new version of lein-vimclojure here http://clojars.org/org.clojars.oskarkv/lein-vimclojure

16:14 dans: You can also find the rest of the vimlojure plugin configuration in my vimrc -- There is also a never version of vimclojure-server. I'll try that later, thanks for making me aware of that :)

16:17 dans: ok, ill try with vundle :)

16:17 thanks

16:17 babilen: dans: Having installed that you can start the nailgun server with "lein vimclojure &"

16:17 dans: Good luck -- please also read https://github.com/gmarik/vundle

16:18 dans: As there are new versions around I am not sure if my configuration reflects the current state-of-the-art, but it is working. I'll upgrade later tonight and will let you know.

16:22 dans: babilen, do i have to move ng to ~/bin

16:22 i've put it in ~/.ng/

16:24 and after addings the dependencies, i need to run lein deps right?

16:24 babilen: dans: Fine as well, just make sure to adjust the path in your .vimrc -- vimclojure#NailgunClient

16:24 indeed

16:25 dans: babilen, i've added both lein and ng to my $PATH, so they should run with just lein and ng

16:25 curiously they dont, i get zsh command not found

16:26 sorry, ng is working now

16:26 it's just lein which doesnt

16:26 :/home/daniel/code/cloj/lein:/home/daniel/.ng/ng

16:28 babilen: you add directories to your PATH, make that ":/home/daniel/code/cloj/:/home/daniel/.ng/" -- or ask in #zsh ;)

16:30 dans: hmm ok

16:31 you're right :/

16:35 vim still doesnt recognise the clj filetype

16:38 babilen: dans: This is getting somehow off-topic in here :-\ -- But have you installed the bundles? Do you see VimClojure in ":scriptnames" ?

16:39 dans: yes, and i just loaded vim again and the highlighting randomly appeared :/

16:39 but anyway, working :D

16:40 i have to refresh my vimrc maybe, reopening wasnt enough

16:41 thanks for all your help babilen

16:50 babilen: dans: You are welcome! Do you have a repl? Start it with "\sr" for example

16:57 dans: babilen, i dont yet

16:58 i need to put the nailgun stuff back in my vimrc

16:58 still get the could not determine namespace - connection refused error there

16:59 i have to set up my classpath or something dont i?

16:59 gtrak`: how do you easily navigate in clojure-mode?

17:00 dans: i'm coming from a ror/node.js background, i am pretty new to java

17:13 babilen: dans: you need the ng client in your PATH and you start the nailgun server with "lein vimclojure &". Have you done that?

17:22 dans: That's not a task. Use "lein help" to list all tasks.

17:23 babilen, thats what i get when running lein vimclojure &

17:26 babilen: dans: You ran "lein deps" before that? Could you paste your project.clj (created with "lein new") and the output of "lein deps" to http://paste.debian.net please?

17:27 dans: http://paste.debian.net/122921/

17:28 http://paste.debian.net/122922/

17:28 babilen: Ah, forget that. Lets install it globally. Could you run "lein plugin install org.clojars.oskarkv/lein-vimclojure 1.0.0-SNAPSHOT"

17:32 dans: ok, done

17:33 babilen: dans: Now run "lein vimclojure &" in a directory with project.clj

17:33 dans: I would just create a new one now (lein new) and test with that.

17:33 dans: sucess :)

17:35 now i get a new error with \sr http://paste.debian.net/122923/

17:40 babilen: dans: So, the server started? That should mean that "ng" is not in your PATH -- Could you run "which ng". Does it find ng? Do you have "let vimclojure#NailgunClient = /home/<YOUR_USER>/.ng/ng" and "let vimclojure#WantNailgun = 1" in your vimrc?

17:40 dans: which ng finds it

17:41 its in my path so i just have let vimclojure#NailClient = "ng"

17:41 babilen: server started and those two in ~/.vimrc?

17:41 dans: yeah

17:41 babilen: hmm

17:43 Could you run "ng ng-stop ; lein vimclojure &" and try again? Please paste the output you get, your .vimrc and any error you get when you do "\sr"

17:44 (single paste)

17:44 dans: NGServer started on, port 2113

17:45 http://paste.debian.net/122924/

17:46 and same error with \sr: http://paste.debian.net/122923/

17:47 babilen: dans: You do *not* give the absolute path for vimclojure#NailgunClient. Please look above and replace <YOUR_USER> with your username. You also don't want "10" as value of ParenRainbow

17:47 dans: You did install ng to ~/.ng/ng didn't you?

17:48 dans: yes babilen, but it said in the vimclojure docs that if its in your path, ng is sufficient

17:48 ill try being explicit

17:49 babilen: dans: Hmm, right. Try something like: http://paste.debian.net/122925/ :\

17:52 dekuderp: when I run "lein swank", I get "That's not a task. Use 'lein help' to list all tasks."

17:52 and it was working a half-minute ago

17:53 dans: doesn't work babilen :( sorry, but im gunna have to get to bed, got work in 6 hours

17:53 thanks for your help

17:54 babilen: dans: good night

17:54 dans: night

18:00 krl: how do you map over a vector and get a vector output?

18:01 mefesto: ,(vec (map inc (range 5)))

18:01 clojurebot: [1 2 3 4 5]

18:01 amalloy: if you're mapping over it, you probably don't really care that it's a vector

18:02 Scriptor: krl: use reduce with conj

18:02 although it won't be lazy

18:02 amalloy: vectors have to do quite a bit of housekeeping to keep their performance guarantees, and if you're going to just treat them as seqs anyway, you should strive to only make them vectors when it becomes necessary

18:03 Scriptor: what's the best way to use vectors if not as a seq, collections that will be accessed at any nth place and not just with first/rest?

18:04 amalloy: Scriptor: yes, and/or conjing onto the right

18:05 i mean, using vectors as seqs is great

18:05 but don't turn then back into vectors just for fun

18:05 Scriptor: got it

18:05 krl: hmm. this might be true. i need to get the last n elements of a (potentially very long, and growing) sequence. would this work better with a vector or a list?

18:06 amalloy: &(doc take-last)

18:06 sexpbot: ⟹ "([n coll]); Returns a seq of the last n items in coll. Depending on the type of coll may be no better than linear time. For vectors, see also subvec."

18:06 Scriptor: ,(doc subvec)

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

18:07 krl: ah. i guess i really need to test for a certain condition in the list, and cut off accordingly though

18:08 amalloy: &[(doc drop-while) (doc take-while)]

18:08 sexpbot: ⟹ ["([pred coll]); Returns a lazy sequence of the items in coll starting from the first item for which (pred item) returns nil." "([pred coll]); Returns a lazy sequence of successive items from coll while (pred item) returns true. pred must be free of side-effects."]

18:09 amalloy: see also split-with, partition-by

18:09 krl: ah no take-last-while though? i guess i could store the stuff in reverse order from the start

18:09 amalloy: take-last-while? just combine take-last and take-while

18:10 or something like that. you aren't really clear about what you want

18:10 gtrak`: if you treat the vector as a stack, peek should give you the head, which is the last, right?

18:11 for lists, the head is the front

18:11 krl: gtrak`: yes of course. i should think in terms of a stack. this made it clearer

18:11 gtrak`: there's a peek function already

18:12 Scriptor: krl: so, to go back to the problem, you have to map over a seq to get a new (very large) seq from which you want the last n elements of?

18:12 what type is the original seq?

18:13 krl: i don't need to map it really, that was my confusion

18:13 Scriptor: ah

18:13 krl: so a stack will be sufficient

18:13 problem solved :)

19:39 mdeboard: Anyone have any idea why when I do "clojure-jack-in" the swank buffer only says, "Process swank exited abnormally with code 1\nThat's not a task. Use "lein help" to list all tasks." error?

19:39 On swank-clojure 1.3.2 btw

19:39 oh hm

19:41 No, that's not it

19:51 Additionally, I'm pretty stumped on http://4clojure.com/problem/19

19:51 I tried #(last %) which should work fine but doesn't

19:51 also just "last" :P

19:52 oh, special restrictions :)

19:53 amalloy: mdeboard: yeah, we didn't think that "last" was a very clever solution to that problem

19:54 mdeboard: us poor beginners :(

19:54 amalloy: there are so many interesting ways to implement last, though

19:54 mdeboard: I think I got it though.

19:55 amalloy: (comp first (partial take-last 1))

19:55 mdeboard: stop stop

19:55 I'm trying to do it myself :|

19:55 amalloy: haha i know

19:55 don't use that one

19:55 it's not much of a hint anyway

19:56 just a demonstration of a silly way you could do it

20:00 mdeboard: lol well this feels cheap #(first (reverse %))

20:00 but hey take away last I"l just reimplement it :|

20:02 * technomancy coughs *comp* discreetly

20:02 mdeboard: hrmph

20:03 jamiltron: May I ask for suggestions for a more idiomatic way to solve a 4clojure problem?

20:03 gfrlog`: yes.

20:03 clojurebot: anyone?

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

20:04 jamiltron: https://gist.github.com/1083758

20:05 gfrlog`: hmm

20:06 it doesn't look too bad. one thing is to use destructuring in your let, instead of calling first/rest directly

20:06 (let [[x & xs] n] ...)

20:07 jamiltron: Ah right, I was suggested doing this last night. I suppose it hasn't sunk in yet :P

20:07 On a different problem.

20:08 gfrlog`: there _might_ be stack issues with the use of concat. I can never tell when that's going to happen

20:08 amalloy: mdeboard: i think that's the same as my first solution to last

20:09 jamiltron: gfrlog`: that's kind of what I was wondering. I think the way I do it requires a mix of concat and cons due to the possibility of nested sequences, but I was wondering if there was perhaps some use of map that may be able to take care of it.

20:09 amalloy: gfrlog`: yes, i think there are if you have a seq that's nested a few thousand levels deep

20:10 gfrlog`: jamiltron: mapcat comes to mind, but I think you could only use it to make something equivalent

20:11 I could imagine a creative use of loop that would avoid direct recursion, but I suspect most people here would call that uglier

20:11 (direct? explicit? named? what did I even mean?)

20:11 amalloy: gfrlog`: you would imagine wrong, i think

20:11 gfrlog`: amalloy: you imagine?

20:11 amalloy: this recursive algo needs to keep a stack

20:12 because it's not just iteration dressed up as recursion

20:12 gfrlog`: amalloy: what are we talking about? mapcat or loop?

20:12 amalloy: flatten

20:12 or loop?

20:12 my point is: you can't cleverly use loop to avoid recursion in flatten

20:12 gfrlog`: oooh

20:13 I thought you were objecting to the OTHER half of that statement

20:13 jamiltron: loop/recur on releases the stack if recur is strictly in the tail position, right?

20:14 gfrlog`: amalloy: I didn't mean to avoid any kind of recursion. There would certainly be implicit recursion with a stack. I meant no explicitely calling the function itself again

20:14 given that loop is essentially recursion, it's not that much of a distinction

20:14 jamiltron: yes, and the compiler won't let you put recur anywhere else

20:15 amalloy: gfrlog`: i can't tell. are you claiming/proposing that you can write (defn flat ...impl...) where impl doesn't use the symbol flat?

20:15 gfrlog`: amalloy: yes

20:16 I mean the way you've stated it it's even trivialer than what I was claiming

20:16 amalloy: i mean, obviously that's possible if you define a different named function and recurse on that, but in a non-cheater sense i don't think you can do it. i'd be interested to see if you can

20:16 mdeboard: Wow this is hard to google. What's ->> again?

20:16 gfrlog`: amalloy: I'm trying right now

20:16 mdeboard: `->>`

20:16 ,(->>)

20:16 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$--GT

20:16 amalloy: &(->> (range) (filter even?) (take 5) (reduce +))

20:16 sexpbot: ⟹ 20

20:17 amalloy: &(clojure.walk/macroexpand-all '(->> (range) (filter even?) (take 5) (reduce +)))

20:17 sexpbot: ⟹ (reduce + (take 5 (filter even? (range))))

20:18 amalloy: mdeboard: c'est bon?

20:18 mdeboard: amalloy: oui

20:21 gfrlog`: amalloy: https://gist.github.com/1083792

20:22 amalloy: i see. i would have called that super-extra-explicit recursion (managing the stack yourself), whereas implicit recursion would be more like (map flat (...))

20:22 looks nice though

20:22 gfrlog`: thx

20:22 it all turing complete

20:23 whenever I put adjectives on the word recursion I usually feel like I have no chance of actually communicating anything

20:23 amalloy: *chuckle*

20:25 jamiltron: Thanks for all the help I think this channel is really helping me pick up better Clojure practices.

20:25 gfrlog`: then the channel is well-named

20:26 mdeboard: Will someone hit me if I use commas for white space while I'm learning :(

20:26 gfrlog`: mdeboard: I use commas for whitespace all the time

20:26 mdeboard: (comp keyword, str) makes my brain hurt lses than (comp keyword str)

20:26 amalloy: mdeboard: knock yourself out

20:26 gfrlog`: okay that's weird though

20:26 amalloy: haha yes

20:26 mdeboard: haters

20:26 jamiltron: Like the way I did the compress a sequence problem before was a big consing-self-recursive mess, until amalloy showed me partition-by and I've started practicing using map more.

20:27 mdeboard: (map,,(comp,,keyword,,str),,[1,2,],,),

20:27 ಠ_ಠ

20:27 amalloy: ,,,,,,,,,,,,,,1,,,,,,,,

20:27 clojurebot: 1

20:27 mdeboard: lol

20:27 ,(,,,,,,,,,,,,,+,,,,,,,,,,,,,,,,,,,,,,,,(+,,2,3),)

20:27 clojurebot: 5

20:28 mdeboard: awesome.

20:28 amalloy: i mean, god gave you commas so you can put them wherever you think it makes things clearer

20:28 but you should also try to get over the "need" to put commas everywhere that languages with complicated grammars have

20:28 (and every other language has a complex grammar)

20:29 mdeboard: Yo'ure right, it's just tough for me to analogize

20:29 jamiltron: Is it generally a bad idea to call the various cons, conj, concat functions in a reduce?

20:30 amalloy: jamiltron: cons and conj, knock yourself out. concat...welll...usually that's not a problem

20:30 mdeboard: I guess comp is a more concise/faster way of a for loop

20:30 or even a list generator

20:30 amalloy: mdeboard: eh? they seem unrelated

20:30 mdeboard: list comprehension*

20:30 jamiltron: What is the potential problem with concat?

20:30 amalloy: $google stackoverflow dbyrne sieve

20:30 sexpbot: [recursion - Recursive function causing a stack overflow - Stack ...] http://stackoverflow.com/questions/2946764/recursive-function-causing-a-stack-overflow

20:30 amalloy: jamiltron: that, basically

20:31 je

20:31 er

20:31 he's using loop/filter, but the same concerns apply to reduce/concat

20:32 and you can usually use ##(doc into) instead of reducing with conj/concat

20:32 sexpbot: ⟹ "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined."

20:32 mdeboard: amalloy: re: comp/fo http://dpaste.com/568868/

20:32 jamiltron: Ah! Let me try using into instead

20:32 mdeboard: for mutable state langs

20:34 ->> is like a uh... a signal that what follows is a schematic for how to process raw materials and what to do with it at the end.

20:35 learning hath occured

20:35 ,(->> [1 2 3 4 5] (reverse) (first))

20:35 clojurebot: 5

20:35 mdeboard: alright! gimme five clojurebot!

20:36 ,(->> [1 2 3 4 5] (reverse) (first))

20:36 clojurebot: 5

20:36 mdeboard: awesome

20:37 What's the time complexity of ->>

20:37 gfrlog`: it's a macro

20:37 amalloy: 0

20:37 gfrlog`: O(N)

20:38 it's gotta walk through the args to assemble the output code

20:38 amalloy: gfrlog`: c'mon, O(0) because he's asking about runtime

20:38 gfrlog`: hmm

20:38 I guess

20:38 good point

20:38 macros run at compile time?

20:38 I'm not sure if I knew that or not...

20:39 mdeboard: wait, I think my question was more cmplex than I thought. O(0)?

20:39 gfrlog`: mdeboard: do you know how macros work?

20:39 amalloy: mdeboard: recall my previous example: ##(clojure.walk/macroexpand-all '(->> (range) (filter even?) (take 5) (reduce +)))

20:39 sexpbot: ⟹ (reduce + (take 5 (filter even? (range))))

20:40 amalloy: that all happens *completely before* any code is executed, as if you'd written the latter code to begin with

20:41 mdeboard: so, how come every search engine on earth isn't written in clojure

20:41 amalloy: uh

20:41 mdeboard: obv I'm an idiot so bear with me.

20:41 amalloy: you seem to be conflating "complexity of code that ->> lets you write" with "complexity of ->>"

20:41 mdeboard: I see

20:41 Probably

20:42 amalloy: ->> is nothing but a tool to write your code in a way that's more natural or descriptive

20:43 once it's expanded, it's as if there was no ->> to begin with, and you wrote the non-natural-feeling version

20:43 mdeboard: Ah I see

20:43 ok

20:43 jamiltron: So ->> isn't speeding anything up - it doesn't reduce your algorithm to O(0), it's simply transforming what you wrote to another (possibly) less convenient form.

20:44 mdeboard: ->> seems easier to grok imo

20:44 jamiltron: change possible less to possibly more

20:44 amalloy: mdeboard: only if you use it in cases that it makes easier to grok

20:44 jamiltron: I wrote that incorrectly.

20:45 amalloy: eg, you can write ##(->> :v (list k) (for [k [1 2 3]]))

20:45 sexpbot: ⟹ ((1 :v) (2 :v) (3 :v))

20:46 amalloy: or even, god help us, ##(->> k (list :v) (for [k [1 2 3]]))

20:46 sexpbot: ⟹ ((:v 1) (:v 2) (:v 3))

20:46 amalloy: anyway, that's enough from me. i'm headed home. enjoy 4clojure

20:47 jamiltron: Thanks for the help!

20:47 mdeboard: amalloy: What about with like 5x more commas

20:47 oh

20:48 au revoir

20:48 amalloy: har har

21:51 dekuderp: how does one dynamically add keys to a map?

21:51 I am trying to create a simple 10x10 map

21:52 {:0 {:0 {:item building} ... is what I want to create

21:52 amalloy: assoc?

21:52 clojurebot: then its perfect. but of course, there are a lot of other parts too that changes. so after I make assoc :show, is there a problem I make again (def data (assoc data :list ...)

22:03 dekuderp: ,(assoc :0 (assoc :0 '(1, 2, 3)))

22:03 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$assoc

22:04 dekuderp: ,(assoc {} 'a 1)

22:04 clojurebot: {a 1}

22:05 dekuderp: ,(assoc {} :a 1)

22:05 clojurebot: {:a 1}

22:05 ihodes: there should be a "cool facts about clojure" website

22:06 dekuderp: so do I have to write code to automatically prepend the colon to a given symbol name?

22:06 ihodes: (keyword "h")

22:06 ,(keyword "h")

22:06 clojurebot: :h

22:07 ihodes: ,(keyword 'h)

22:07 clojurebot: :h

22:09 dnolen_: (assoc {} [1 2] 'foo)

22:09 ,(assoc {} [1 2] 'foo)

22:09 clojurebot: {[1 2] foo}

22:14 amalloy: dekuderp: if using keywords as the map keys is inconvenient, then don't use keywords

22:25 dekuderp: amalloy: what do you mean? how could you use something besides a keyword for a map key?

22:26 amalloy: <dnolen_> ,(assoc {} [1 2] 'foo)

22:26 dnolen_: dekuderp: you can use anything for a key.

22:26 dekuderp: ,(keyword '1)

22:26 clojurebot: nil

22:26 dnolen_: dekuderp: a keyword is type of object

22:27 dekuderp: you can use any object for a key.

22:28 ,{["this" #{1 2 3} "is" 'a "krazee" 'key] 'yes-man}

22:28 clojurebot: {["this" #{1 2 3} "is" a "krazee" key] yes-man}

22:33 dekuderp: so is that vector being treated as a key?

22:35 amalloy: &(keys {["this" #{1 2 3} "is" 'a "krazee" 'key] 'yes-man})

22:35 sexpbot: ⟹ (["this" #{1 2 3} "is" a "krazee" key])

Logging service provided by n01se.net