#clojure log - Nov 22 2010

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

0:36 LauJensen: Morning

0:53 Derander: LauJensen: good morning

6:35 noidi: is it possible to use zippers for maps?

6:35 the docs say that "All it takes is a 4-5 line function to support other data structures."

6:36 maybe someone has already written the function for supporting maps? :)

6:53 fbru02: can i tell lein "use this pom , from this url " ?

7:00 or how can i tell him to use this pom ? http://mirrors.ibiblio.org/pub/mirrors/maven2/org/apache/mahout/mahout/0.4/mahout-0.4.pom because [org.apache.mahout/mahout "0.4"] will go to mahout/0.4/mahout instead of what i need

8:10 noidi: In my program I have a tree made up of nested maps. Now I need to add references from nodes to their parents. In a language with mutable state I'd just do something like `node.parent = self` in the recursive function constructing the nodes.

8:12 But with maps I obviously can't do this, because both the parent and the child would need to be created first so the other could refer to it.

8:12 How can I solve this problem in Clojure? Do I need to scrap my map-tree approach and replace it with zippers?

8:13 pdk: create the parent with the field you want to reserve for the child blank then assoc it to a new map with the reference to the parent?

8:15 noidi: pdk, hmm. yes, that should work. unlike zippers, it will lose data when traversed upwards, but that's fine for my use case.

8:15 pdk, thanks!

8:20 Ah, nope. Now that I think about my use case a bit more, I will need to be able to walk the tree back to the child.

8:21 So I guess I'll need to look into zippers after all.

8:53 chouser: noidi: probably the best way to handle cyclic directed graphs like that is to give each node a 'name', and then they can refer to each other by that name

8:54 {:the-parent {:parent nil, :child :the-kid}, :the-kid {:parent :the-parent, :child nil}} ... or whatever

8:57 noidi: chouser, thanks, I'll think about that

8:58 chouser: so I'm trying to use congomongo via maven, and apparently there's a binary version incompatibility

8:58 NoSuchMethodError clojure.core$meta.invokeStatic(Ljava/lang/Object;)Ljava/lang/Object; clojure.contrib.def/defmacro- (def.clj:39)

8:59 what are my options for resolving this?

9:00 jweiss_: anyone have any pointers on how to add java annotations to a clojure fn (to be used with gen-class)? the only way i can get it to work is by adding it to the gen-class :methods list, not the metadata of the fn itself

9:01 chouser: jweiss_: I think that's the only way that's supported.

9:01 dnolen: chouser: can you't just do a source checkout of congomongo and run 'maven install' from the source dir ?

9:01 chouser: the fn's themselves aren't examined while doing the static class generation.

9:01 jweiss_: chouser: it's not supported in the ns form either? i tried that and it didn't work

9:02 chouser: jweiss_: oh, it should work in the ns form

9:02 jweiss_: hm, ok i'll play around w that some more. thakns

9:02 chouser: dnolen: I'll try that

9:03 though that sounds a lot like failure to me. :-)

9:04 mister_roboto: chouser: usually you have to find the correct version to list as your dependency when there is such a change in the API between versions. don't you have another version to try from the repo?

9:06 chouser: resorting to build from source is a very un-Maven solution :)

9:06 chouser: mister_roboto: I believe I'm using the latest release of congomongo, contrib standalone, and clojure.

9:07 oh, the latest congomongo is listing 1.2-SNAPSHOT deps for clojure and contrib. :-P

9:07 mister_roboto: chouser: is it possible you're trying to use an API method that no longer exists in the new version and, therefore, would have to list an older version to get your code to work?

9:08 ahhh, well there you go :)

9:09 chouser: so the current "solution" would be to use out-dated clojure, until such time as clojure libs stop binary compiling themselves by default.

9:09 * chouser chooses an alternative

9:11 mister_roboto: chouser: you could always build the jar and put it in your local repo cache, keeping the build exactly the same. except for putting your own version that you "install"ed locally

9:12 chouser: that's what I'm pursuing now

9:13 dnolen: chouser: heh - I thought the convention to package up non-compiled jars was well-established by now.

9:13 chouser: this is not easier than resolving dependencies myself and building a classpath by hand.

9:13 mister_roboto: it's kind of like using programs from your linux distro repository: if you wanna stick with the standard packaging for your system, you use what is available in the repo. otherwise you have to mutate your local system away from the standard repo to be on the bleeding edge :)

9:16 dnolen: even if they weren't compiling the jars, if the repo only has the older version of the dependency, it's not going to work

9:16 the new method would still be missing

9:16 chouser: yes. I can ask apt-get to fetch and install all dev deps for a source package, and fetch and prepare the source package itself, so I all i have to do is make my changes and install.

9:17 I wonder if maven supports that workflow.

9:17 mister_roboto: chouser: i don't know but that would make it infinitely harder to support the transitive dependencies, i would imagine

9:18 or not, if you're only changing the leaf node on the dependency list...

9:19 dev deps are what SNAPSHOTs are suppsoed to be

9:19 chouser: grr

9:20 fliebel: morning

9:22 chouser: the jar is empty

9:22 of course, because the pom created by lein can't be used to build the jar

9:22 jweiss_: is there a way to reload a gen-class'd class at the repl?

9:23 it doesn't seem to pick up the new version by importing it again

9:23 chouser: jweiss_: I don't think so. gen-class itself is unfortunately very static in nature

9:24 you can load in new method definition fns, but the gen-class itself has to be re-AOT-compiled and a new JVM started up

9:25 jweiss_: chouser: ok thanks, that should save me some time futilly (is that a word) trying to get it to work :)

9:26 mister_roboto: http://new.clojars.org/repo/congomongo/congomongo/0.1.3-SNAPSHOT/

9:26 can't you just use that chouser?

9:26 chouser: mister_roboto: well ... it just started working

9:26 I'm not sure why.

9:27 cemerick: what's this *new*.clojars.org?

9:27 mister_roboto: hmmm that's usually not a good thing!

9:27 cemerick i have no idea, i just google'd congomongo maven jar to find a repo with maybe some newer artifacts

9:27 chouser: I noticed one of the several snapshot jars in my .m2 had only .clj files, no .classes, and I thought, "well, that should have been working all along"

9:28 so I cleaned all the congomongo stuff from my .m2, re-ran mvn clojure:repl in my own project, and new I no longer get the original exception.

9:29 oh, I know why. I'm no longer specifying a 1.3 contrib.

9:29 so this is clojure 1.3a3 and contrib 1.2

9:29 I bet. Though I don't know how to find oue.

9:29 out

9:33 cemerick: chouser: `mvn dependency:tree` is nifty

9:34 Having a decent maven-capable environment gives you a nice interactive UI for the same data rather than the asciiart, but whatever. :-P

9:36 chouser: I'm not yet willing to admit that dep management is the primary focus of my time in front of the computer. I still like to pretend I'm mostly about writing code.

9:37 cemerick: chouser: Well done, sir! :-D

9:37 chouser: heh

9:37 but I'm probably just lying to myself

9:38 LauJensen: "cemerick - of indian root, means He that does not tire nor give up" :)

9:40 cemerick: LauJensen: and secondarily, He that gives succor to the poor and disenfranchised fellow traveler. ;-)

9:40 LauJensen: I want to buy your vocabulary, but until its available online I'll google 'succor'

9:40 cemerick: And lord knows, maven users need succor. :-P

9:41 LauJensen: oh I see. Well, let me put it this way: You do good screencasts :)

9:43 mister_roboto: cemerick: if you're using a lot of java libs on a large project, letting maven manage all those transitive deps is easier than doing it manually! don't you think?

9:43 edw: I'm trying to use xml/parse to ... parse some xml, and I'm having trouble parsing a string. How do I create a StringInputStream in Clojure? (java.io.StringInputStream. "foo") gives me a "class not found" error.

9:44 chouser: mister_roboto: that's the wrong fight or with the wrong cemerick, that is.

9:44 mister_roboto: not fighting, just asking :)

9:44 chouser: mister_roboto: he's on your side

9:44 tonyl: morning

9:45 LauJensen: mister_roboto: cemerick never writes clojure code directly himself, he's made a maven task for that as well

9:45 mister_roboto: lol

9:45 cemerick: the people that run freenode are really missing opportunities -- they should "embrace and extend" irc to support profiles, message history, global and channel-specific logging, etc.

9:45 LauJensen: He has a 4 year CS education, majoring in XML

9:45 cemerick: LauJensen: Dude, I dropped out. :-P

9:45 LauJensen: cemerick: funny you mention that, I was just thinking about writing that server myself the other day

9:46 dnolen: edw: http://www.mayerdan.com/2005/04/java_string_to_inputstream.php

9:46 cemerick: LauJensen: well, it'd not get any traction unless you own a big network -- and I presume freenode's the largest

9:46 LauJensen: cemerick: I have a Maven task that does a hostile takeover on freenode, so no worries

9:46 cemerick: That they're still all non-profit, taking donations, just scraping by, etc. is almost criminal.

9:46 LauJensen: <attack>freenode</attack>

9:47 dnolen: edw: there's also w/ with-in-str in core

9:47 ,(doc with-in-str)

9:47 clojurebot: "([s & body]); Evaluates body in a context in which *in* is bound to a fresh StringReader initialized with the string s."

9:47 cemerick: mister_roboto: no one's linked to my shot across the bow (as it were), so: http://cemerick.com/2010/03/25/why-using-maven-for-clojure-builds-is-a-no-brainer/

9:47 edw: dnolen: Thank you!

9:48 I'm also looking at clojure-contrib's io, which has `input-stream'

9:48 .

9:48 * cemerick ironically yearns for the days of yesteryear when #clojure was about language issues and programming in general :-P

9:50 edw: Should (with-in-str "<a>42</a>" (parse *in*)) work?

9:50 LauJensen: cemerick: my only concern is, you start out saying "its this simple" then demo a 40 line XML script, doesnt look too bad, but before the cast its over its grown to something like 140 lines?

9:51 tonyl: edw: why not just (parse "<a>42</a>") ?

9:51 unless parse messes with *in* implicitly in its body

9:51 edw: Because parse interprets that as a filename.

9:51 cemerick: LauJensen: 140 is certainly exaggerating, but if you're focused on LOC, you're missing the forest for the trees.

9:52 tonyl: ok, but *in* is not a file name either

9:52 LauJensen: cemerick: You've read my blog right?

9:52 tonyl: what parse fn are you reffering?

9:53 dnolen: edw: oops, with-in-str binding *in* to a string reader not an input stream.

9:53 cemerick: LauJensen: Indeed. Any time you mention LOC, you lose me. :-)

9:53 edw: dnolen: D'oh...

9:54 cemerick: Sometimes it matters, very often it doesn't.

9:54 dnolen: cemerick: ha, might as well write Java then.

9:54 cemerick: For stuff like builds, it *really* doesn't IMO.

9:54 dnolen: well, if LOC matters, then I should write everything in ML, right?

9:54 LauJensen: cemerick: ClojureQL is only 700 LOC vs Arel (Ruby) which is 4600+ :) Thats counts for something right?

9:54 cemerick: screw this verbose Clojure thing.

9:55 jetienne: q. core devs are paid to work on clojure ?

9:55 mister_roboto: cemerick: as a long-time maven user, with our own artifactory server and CI server, and using Eclipse (all this for java, btw), it sounds like the clojure plugin for maven is a lot simpler than trying to use cake/lein/whatever and trying to work that back into the existing infrastructure

9:55 dnolen: cemerick: Clojure is about as terse as ML.

9:56 tonyl: edw: maybe using (parse (java.io.StringReader. "<a>my text</a>"))

9:56 LauJensen: cemerick: You should really learn J

9:56 Would provide a good counter weight to Maven

9:56 chouser: jetienne: yes, but not full time.

9:57 afaik, generally just Fridays

9:57 jetienne: chouser: oh ok. thanks them for their dedication then

9:57 edw: tonyl: parse doesn't accept readers.

10:00 tonyl: facepalm

10:01 what about this (ByteArrayInputStream. (.getBytes "<a>text here</a>" "UTF-8"))

10:02 cemerick: dnolen: It's not even close, AFAICT…but then, I'm absolutely no ML/haskell/ocaml expert.

10:02 mister_roboto: well, that's what I've used for some time now. I entirely agree.

10:03 tonyl: edw: or maybe clojure.java.io there seems to be some fn's that would help

10:04 edw: tonyl: Thanks.

10:10 tonyl: Problem solved (stream (http-agent URL)) returns an input stream.

10:11 tonyl: nice

10:15 dnolen: cemerick: I'd say it's pretty close, in fact directly inspired. With macros it's even terser.

10:17 * dnolen remember the horror at looking at core.clj for the first time and see m, x, v, re, pb, etc. for var names

10:25 cmiles74: I read an article about literate programming over the weekend and hacked a little script together to generate the most simplistic sort of documentation you can get. https://github.com/cmiles74/lit-doc Does anyone do "literate programming" in real life? I'm mostly just curious.

10:29 insomniaSalt: i happen to have my .emacs configuration organized in org-mode files, if that counts :-)

10:29 "real life"

10:31 cmiles74: I think org-mode with babel-mode definitely counts. :)

10:46 Lajla: &(docs fn)

10:46 &(docs +)

10:46 chouser: (doc fn)

10:46 clojurebot: "([& sigs]); (fn name? [params* ] exprs*) (fn name? ([params* ] exprs*)+) params => positional-params* , or positional-params* & next-param positional-param => binding-form next-param => binding-form name => symbol Defines a function"

10:46 Lajla: No sexpbot

10:46 Chousuke, thanks

10:46 tonyl: &(doc fn)

10:46 apparently not :(

10:47 Lajla: clojurebot ignores me because I'm a douche

10:47 But ehh

10:47 so doc is a special form and not a function?

10:47 How does the evaluation model work that it can also accept special forms?

10:47 tonyl: doc is a macro

10:47 Lajla: It just does a symbol comparison?

10:47 tonyl: uh, i am trying to learn that too

10:47 looking at the code...

10:48 Lajla: I wonder how it gets out fn

10:48 I mean, fn doesn't evaluate to anything, right, it's a speical form

10:48 tonyl, could you evaluate the symbol fn for me.

10:48 because clojurebot ignores me, because I'm a total douche who worships His Shadow too much

10:49 tonyl: I think fn internally is a macro

10:49 let me find it

10:50 https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L42

10:50 what I am trying to find out is where fn* is declared

10:51 Lajla: Hmm

10:51 Maybe fn*

10:51 secretly uses a list

10:51 and not a vector

10:51 for arguments

10:55 paulrosania: fn* is a special form

10:55 Lajla: paulrosania, but a primitive?

10:55 paulrosania: it's implemented on the JVM

10:55 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L3369

10:55 Lajla: And what is its definition?

10:57 How much difference is ther between Java Clojure and .NET Clojure anyway?

11:07 fliebel: Woohoo, my Clojure quiz is done :) https://github.com/pepijndevos/clojure-quiz

11:09 It might be fun to add it to tryclojure or sexpbot later.

11:10 tonyl: yeah fliebel, I'll take a look

11:45 fliebel: tonyl: Still looking? ;)

11:46 tonyl: yeah, in between some stuff i need to do

11:46 no bugs so far, in the code that is. there is some bugs in my clojure knowledge

11:46 :P

11:50 fliebel: tonyl: Yea, especially those things for setting vars and agents nd such

12:24 jaley: hi guys, is there a better way to do this? (:y (bean (:x (bean java-object))))

12:25 Raynes: (-> java-object bean :x bean :y)

12:25 amalloy: jaley: (-> java-object (.getX) (.getY))?

12:25 Raynes: amalloy: Those parens are redundant.

12:26 amalloy: yeah they are

12:26 i was thinking in the wrong context

12:26 jaley: amalloy: Raynes: cool thanks guys

12:26 amalloy: jaley: mine will certainly be faster, and arguably clearer if you just want to get that one sub-bean. if you might want multiple chunks of some object, consider Raynes's

12:26 tonyl: fliebel: now i can't run the quiz script, it run fine the first time. but i'm pretty sure it is me trying to load it with a bash script

12:28 fliebel: tonyl: So it's no bug on my part? Why the bash script?

12:29 tonyl: yeah it's not the code, I am placing it wrong in the command.

12:29 I don't use anything like lein or cake

12:29 just a bash script that runs java with the necessary flags

12:29 it runs something like this java -cp /usr/share/java/jline.jar:/home/tonyl/.opt/jars/clojure-1.2.0.jar:/home/tonyl/.opt/jars/clojure-contrib-1.2.0.jar:/home/tonyl/Projects/clojure-learn/pepijndevos-clojure-quiz/src/clojure_quiz/core.clj jline.ConsoleRunner clojure.main -r

12:30 I am guessing the clojure_quiz/core.clj file doesn't go in the -cp parameter

12:31 fliebel: tonyl: Maybe just ad the dir, and not the file?

12:32 tonyl: maybe, i'll see

12:32 mattmitchell_: I'm getting a "Can't take value of a macro: #'clojure.core/let" error

12:32 how do I assign the value of a macro result to a let binding?

12:32 fliebel: mattmitchell_: You can't use a macro as a function.

12:33 tonyl: fliebel: it worked :)

12:33 mattmitchell_: fliebel: so for example [let my-num (- 10 1)]

12:34 fliebel: mattmitchell_: Don't call it let, and you're out of trouble.

12:34 tonyl: (let [my-num (- 10 1)] ...)

12:34 something like that

12:35 mattmitchell_: oh duh my mistake sorry. i had [let not (let

12:43 i asked this question a few days ago and got a few good answers, but i'm still trying to find the right solution. and seriously can't figure this out: https://gist.github.com/708130

12:48 fliebel: I'm averaging on a 3/1 ratio on my quiz for (name-quiz)

12:49 tonyl: mattmitchell_: maybe using merge-with

12:49 fliebel: name-quiz is the hardest

12:49 fliebel: tonyl: It totally is. What is your score?

12:50 amalloy: mattmitchell_: yeah, merge-with looks applicable. also clojure.set/index might be relevant? it's a little awkward because you have a map rather than a set, but i think it can still work

12:50 mattmitchell_: tonyl: merge-with and concat into the :f vector?

12:50 amalloy: fliebel, tonyl: what is this "quiz" thing. i must take

12:50 fliebel: amalloy: https://github.com/pepijndevos/clojure-quiz

12:51 tonyl: fliebel: I started it, but got a 2 out of 10 so I stopped on that one

12:51 amalloy: fliebel: neat. i see you went a different direction than you were originally going

12:51 tonyl: I am at doc-quiz, but I am starting name-quiz-easy now :P

12:51 mattmitchell_: amalloy: so you think i should use a set instead of a map?

12:51 tonyl: mattmichell_: that could work

12:51 fliebel: amalloy: Yea, the other thing required to much effort for to little fun.

12:53 amalloy: I'm thinking of adding something like this to tryclojure or sexpbot, for much learning fun and multiplayer Clojure quizzing.

12:54 amalloy: fliebel: ratio? surely % is more useful

12:54 tonyl: fliebel: how do you stop a quiz?

12:55 fliebel: tonyl: just kill it.

12:55 tonyl: lol ok

12:55 amalloy: omg doc-quiz is so hilarious. i assume you're just picking three functions at random, getting their docstrings, and randomly choosing one for me to identify?

12:56 fliebel: amalloy: Yea, the top function just spits out a map of a set number of names and doc strings, and you select what you want to question for.

13:01 How do I commit the evil act of changing a var's value?

13:02 tonyl: with (binding

13:02 fliebel: well, I'll use binding for less evilness

13:02 ah, thanks

13:03 tonyl: evil would be def i guess

13:03 fliebel: amalloy_: Try this: (binding [number 5] (doc-quiz))

13:04 Or even this: (binding [number 5 target 'clojure.set] (doc-quiz))

13:06 So you can quiz about contrib, or some specific lib as well :)

13:09 jonaskoelker: (alive? 'channel)

13:09 tonyl: there is people here

13:10 jonaskoelker: true

13:10 cemerick: $max

13:10 sexpbot: The most users ever in #clojure is 317

13:10 tonyl: fliebel: that is a nice touch with the binding of those vars

13:10 jonaskoelker: sexpbot is one small typo away from sounding very dirty... :D

13:11 cemerick: A nice bot feature would be to report on a moving average of active users

13:11 jonaskoelker: you mean like halve-and-add every $interval?

13:11 Raynes: cemerick: Duly noted.

13:13 jonaskoelker: I've had a lot of false starts with various lisps (some CL, elisp, mzscheme). Anyone got a recommendation on how to stick to it?

13:13 cemerick: jonaskoelker: you'd probably want to retain sample data so you can change the window, etc.

13:13 jonaskoelker: cemerick: good point

13:13 I think I see the value of lisp---that is, its unique strengths and when/how/why they will come in handy

13:14 But for some strange reason, lisp just never stuck

13:14 cemerick: jonaskoelker: make sure you are working on a problem where a lisp would offer particularly compelling advantages.

13:14 jonaskoelker: meh, do I _have_ to write a compiler? </caricature> :-P

13:15 seriously though, that's a good point and one well taken

13:15 Lajla: How is fn* defined?

13:15 How is it usd.

13:15 &(doc fn*)

13:15 sexpbot: java.lang.Exception: Unable to resolve var: fn* in this context

13:15 Lajla: Hmm

13:15 &(doc fn)

13:15 sexpbot: ⟹ "Special Form: Please see http://clojure.org/special_forms#fn"

13:15 cemerick: Many (rightly, IMO) believe that a lisp (Clojure in particular, at least in comparison to others, again IMO) provides compelling advantages regardless of the problem.

13:15 Lajla: don't use fn*

13:16 jonaskoelker: I'm with you on the clojure vs. other lisps

13:16 cemerick: jonaskoelker: But if the question is, how to stick with learning it -- make sure the wow-factor is so high that you absolutely can't let up. :-)

13:17 jonaskoelker: :)

13:17 It seems to me like clojure has the right kind of abstractions when it comes to things "in/out of the box"

13:17 Lajla: cemerick, I want to know what it is.

13:18 Apparently fn is defined in terms of it as a macro.

13:18 jonaskoelker: i.e. lazy sequences being "compatible" with plain ol' lists; IOW, there's interfaces and things that "implements" them

13:18 cemerick: Lajla: fn* is the form that ties into the compiler's implementation of fn

13:24 Lajla: cemerick, but how does it work.

13:24 How would you use it.

13:24 amalloy: Lajla: you don't use it. why would you want to?

13:25 cemerick: Lajla: Like I said, you shouldn't use it -- it's entirely an implementation detail.

13:25 Lajla: I don't want to use it

13:25 I want to know how it works

13:25 And why fn itself can't serve that role

13:25 amalloy: Lajla: look in the jvm source

13:25 er, the java source for clojure

13:26 in Compiler.java

13:26 Lajla: Yeah, but I want to know how fn expands to fn* as a macro.

13:26 I heard it does

13:26 amalloy: $source fn

13:26 sexpbot: fn is http://is.gd/hBfAf

13:26 amalloy: like so

13:29 Lajla: &(expand '(fn bla [I Worship His Shadow] (+ I His)))

13:29 sexpbot: java.lang.Exception: Unable to resolve symbol: expand in this context

13:29 Lajla: How do you expand macros?

13:30 amalloy: macroexpand

13:32 Lajla: &(macroexpand '(fn bla [I Worship His Shadow] (+ I His)))

13:32 sexpbot: ⟹ (fn* bla ([I Worship His Shadow] (+ I His)))

13:33 Lajla: Hmm

13:33 &(macroexpand '(fn bla ([I Worship His Shadow] (+ I His)) ([I Worship His Divine Shadow] (+ I His Divine))))

13:33 sexpbot: ⟹ (fn* bla ([I Worship His Shadow] (+ I His)) ([I Worship His Divine Shadow] (+ I His Divine)))

13:34 Lajla: &((fn* [x y] x) 3)

13:34 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: sandbox4394$eval6128$fn

13:34 Lajla: &((fn* [x y] x) 3 4)

13:34 sexpbot: ⟹ 3

13:34 Lajla: How is fn* different from fn?

13:34 amalloy: Lajla: /msg sexpbot if you're going to ask him a lot of questions that you don't need to show other people. it clutters up #clojure

13:35 Lajla: I do need to show it to others? I'm asking quaestions about the results which I don't understand at al..

13:36 amalloy: &(fn* add "adds some stuff" ([x y] (+ x y)))

13:36 sexpbot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.ISeq

13:36 amalloy: &(fn add "adds some stuff" ([x y] (+ x y)))

13:36 sexpbot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Character

13:37 amalloy: &(fn add {:doc "adds some stuff"} ([x y] (+ x y)))

13:37 sexpbot: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap

13:37 amalloy: bah

13:37 anyway fn* won't handle the optional arguments like docstrings

13:37 i suspect

13:38 Lajla: Ahhh

13:38 It won't handle docstrings.

13:38 hiredman: amalloy: fn doesn't take a docstring

13:39 Lajla: If that's all.

13:39 Then I see no real reason to not use fn*

13:39 Espeially for function literals

13:39 Which often lack it.

13:39 amalloy: Lajla: preconditions

13:40 and there's...no reason to use fn* at all? you want to add two keystrokes to each function definition, in order to save a microsecond at compile time?

13:41 Lajla: amalloy, maybe, but that doesn't warrant a 'you shouldn't ever use fn*, it's an implementation detail' statement

13:42 Unless of course fn* has no real spefication and it's just a thing that only this clojure uses as an intermediate step.

13:42 amalloy: Lajla: it is. someday maybe it will do something different, and the fn macro will change to work properly

13:42 Lajla: But as far as I know, clojure has no specs, maybe?

13:42 So fn* is undocumented and unsupported?

13:43 hiredman: how does fn not work properly?

13:43 amalloy: hiredman: if fn* changes in the future, fn will need to change in order to work properly

13:43 Lajla: I never said it didn't, I was just wondering why fn expanded to fn* (answered) and then why fn* "should" not be used. (answered)

13:44 amalloy: but that will happen without us needing to know. if Lajla decides to rely on fn*, s/he will be hurting when that day comes cause nobody will rewrite that code

13:44 Lajla: amalloy, so fn* is unsupported and undocumented at this point?

13:45 amalloy: i'm not exactly a language authority, but yes. * suffixes often mean that, and it seems to here

13:47 Lajla: Ahhh

13:48 Somewhat unhygenic and it could pose a security risk, but I'm cool with that I guess.

13:48 amalloy: ...?!

13:48 kiemdoder: can any one suggest an open source project or something that is a good example of well written clojure code?

13:49 maybe they're all good but I'm just asking

13:49 chouser: it's the lack of docs that indicate fn* is not supported for direct use, not the *

13:50 Lajla: amalloy, well, if there are no docs, then someone could be unaware of its existence. Say someone wants to check input, and then check if the list provided doesn't start with fn, and then feels safe, however, the hacker makes it start with fn* to inject possibily malicious input and influence the runtime

13:55 dnolen: sweet WebSockets works on iPad 4.2, Clojure+Aleph just got that much tastier, http://a6.video3.blip.tv/0210004346955/Dnolen-WebSocketSupportInIPad42656.MOV

13:55 iOS 4.2 rather

13:55 bobo_: dnolen: awesome :-)

13:59 kiemdoder: "rest" and "next" seems to yield the same result

13:59 what is the difference?

13:59 if any

13:59 fliebel: kiemdoder: next return nil for an empt seq, but does realize the first item to do se.

14:03 kiemdoder: fliebel: tx, is see now that (next [1]) returns nil and (rest [1]) returns ()

14:04 I see

14:05 KirinDave: So I see http://www.acunetix.com/blog/web-security-zone/articles/http-post-denial-service/

14:05 And it makes me think that increasingly laziness may be a security feature.

14:21 Lajla: &(symbol? '&)

14:21 sexpbot: ⟹ true

14:22 Lajla: If & is a symbol, then why can't I bind to it/

14:22 I assume it makes bindings assume a rest arg?

14:22 &(let [& 3] (+ & 1))

14:22 sexpbot: ⟹ 4

14:22 Lajla: Ahh

14:22 that does work

14:23 &((fn [& r] &) 1 2)

14:23 sexpbot: java.lang.Exception: Unable to resolve symbol: & in this context

14:23 Lajla: Hmm

14:23 Chousuke: hm

14:23 Lajla: &(macroexpand '(let [& 3] (+ & 1)))

14:23 sexpbot: ⟹ (let* [& 3] (+ & 1))

14:23 tonyl: in a function args it is used for the rest binding

14:23 kotarak: Lajla: binding works for me. fn obviously can't because & has special meaning there

14:23 Lajla: &(macroepand (let* [& 3] (+ & 1)))

14:23 sexpbot: java.lang.Exception: Unable to resolve symbol: macroepand in this context

14:23 tonyl: & is a special form

14:23 sexpbot: java.lang.Exception: Unable to resolve symbol: is in this context

14:23 Lajla: &(macroexpand (let* [& 3] (+ & 1)))

14:23 sexpbot: ⟹ 4

14:23 Lajla: &(macroexpand '(let* [& 3] (+ & 1)))

14:23 sexpbot: ⟹ (let* [& 3] (+ & 1))

14:23 Lajla: Damit

14:24 Hmm

14:24 Let is a primitive/

14:24 pjstadig: is there any plan to release 1.2.1 or get 1.3 out the door to fix issues like this http://dev.clojure.org/jira/browse/CLJ-444 ?

14:24 Lajla: let* I mean

14:24 pjstadig: comes up fairly often

14:24 Chousuke: Lajla: let* is an implementation detail

14:24 Lajla: And a primitive

14:24 Chousuke: yeah

14:24 Lajla: I would have expected that let be defined in terms of fn.

14:24 cemerick: tonyl: it's not a special form, & is just part of destructuring syntax.

14:24 Chousuke: Lajla: that's not efficient

14:25 Lajla: You don't say.

14:25 Hmm.

14:25 Why do all other lisps do it then?

14:25 Is it because of the sequential binding?

14:25 Chousuke: they don't?

14:25 Lajla: They do.

14:25 Chousuke: CL doesn't as far as I know

14:25 kotarak: Lajla: I know at least one Scheme which doesn't.

14:25 Lajla: I'm pretty sure that most if not all CL implementations define let as a macro on lambda

14:25 R5RS also lists let as 'library syntax'

14:25 Not sure what the CL specs says about it.

14:25 Chousuke: Lajla: that's inefficient though.

14:26 Lajla: Chousuke, in what way can let be optimized when you don't work like this then?

14:26 Ohh wait.

14:26 Chousuke: at least unless the compiler is smart enough to figure out it doesn't actually need to create an anonymous function

14:26 Lajla: Pardon me

14:26 I forgot that clojure has no TCO.

14:26 Carry on carry on. :')

14:27 Well, in clojure, functions are functions right?

14:27 As in, Java functions?

14:27 In most lisp implementions I guess that lambdas are lambda abstractions, which are much simpler things than java or C functions

14:27 tonyl: they are objects

14:28 Chousuke: java doesn't have functions :/

14:28 tonyl: they implement IFn

14:28 cemerick: Lajla: Java doesn't have function primitives < java 7

14:28 tonyl: java 7 has them?

14:28 Lajla: Well, let me rephrase.

14:28 hiredman: I don't think so

14:28 Lajla: They are more complex than 'lambda abstractions'

14:28 Chousuke: Lajla: they are more complex than that in any real-world language :P

14:29 jarpiain: CL allows any special form to be implemented as a macro

14:29 Lajla: jarpiain, not 'primitives' though

14:29 Depending on what you call your primitive.

14:29 Chousuke, nahhh, a lot of languages explicitly reduce them for optimization's sake.

14:29 cemerick: tonyl: Either 7 or 8, ostensibly. I haven't yet internalized how they got split.

14:30 tonyl: thanks cemerick

14:30 cemerick: pjstadig: one of the various 1.3 alphas doesn't suit your needs?

14:30 Lajla: Basically, what you only need in the purest sense for such a thing is: an expression, which can be like any expression, formal paramatres, and a pointer to the environment in which it was created.

14:30 Return locations and all that can be hacked away by just passing them as arguments to them.

14:31 Chousuke: Theory is interesting but you should sometimes consider reality as well

14:32 cemerick: Chousuke: wait, what? Where's my sufficiently smart compiler? :-P

14:32 pjstadig: cemerick: well for legacy (production) code bases is it a good idea to move to 1.3 (which is alpha)?

14:32 i know there are lots of changes, but i guess nothing breaking

14:32 Chousuke: Doesn't sound like a good idea :P

14:32 At least test first. :D

14:32 pjstadig: is the numerics stuff in there?

14:32 hiredman: yes

14:33 cemerick: pjstadig: Depends on how badly you want the change, etc. If it's just a single patch you're after, I'd just backport that and run your own build, if it's important enough.

14:33 Lajla: Chousuke, well, this is theory of optimization

14:33 cemerick: I'd be pretty surprised if a 1.2.1 or somesuch made an appearance.

14:33 pjstadig: true, but if it's trivial we could get a 1.2.1 out the door

14:33 Lajla: The reason some languages are 'purely functional' is largely an optimization idea, if you have very little side effects, you can better make it none, and then give the compiler a huge assumption it can always make to optimize

14:34 pjstadig: cemerick: weren't you the one complaining about people living on snapshots... now you're suggesting i move to an alpha release? :)

14:35 kotarak: well, at least not a snapshot. ;P

14:35 cemerick: pjstadig: hrm, doesn't sound like me. I was probably pooh-poohing anyone that complained about breakage while following SNAPSHOT.

14:36 * cemerick lived on nothing but snapshots for a year+ until 1.2.0 was final.

14:36 pjstadig: yeah so did we

14:37 Lajla: &(macroexpand '(-> 4 (a (1 4 4))))

14:37 sexpbot: ⟹ (a 4 (1 4 4))

14:37 cemerick: The discussion about patch releases always goes the same. If it's a trivial set of bugfixes, then it's suggested that one build a local patch release, and use it. If it's not a trivial set of fixes, then the question is who is going to shepard the release.

14:37 Lajla: Why doesn't that insert the 4 after the (1 4 4)?

14:38 cemerick: And that's not even touching the question of who decides the working set to begin with.

14:38 kotarak: Lajla: because that's what ->> is for

14:38 Lajla: Ahhh

14:38 I gues

14:39 pjstadig: cemerick: sure, i don't know the answer, i guess i was wondering if anyone else is seeing issues like this that might be useful to backport to 1.2

14:44 cemerick: pjstadig: No one has, at least AFAIK. By all means, open up a thread on clojure-dev and see if there's a plurality around some key issues people are running into.

14:45 mroessler: Is it possible to pull the first four numbers out of a vector of integers? (def numbers [20101122 20101121]). I want just the 2010. With a string I use: (subs (str 20101122) 0 4). I'm uncertain how to apply to the vector.

14:46 arohner: mroessler: 2010 isn't in the vector. 20101122 and 20101121 are

14:46 pjstadig: (/ 20101122 10000)

14:46 clojurebot: *suffusion of yellow*

14:46 arohner: mroessler: you'll have to convert the number to a string, then string manipulate it

14:47 or pjstadig's answer

14:47 pjstadig: clojurebot!!!!!111

14:48 (int (/ 20101122 10000))

14:48 meh

14:49 mroessler: arohner: thanks. Can I convert each integer in the vector to a string? If I convert the whole vector, I'd get only the first 4 numbers of the entire vector, whereas I'm after the first four numbers in each integer within the vector.

14:50 amalloy: mroessler: ##(map str [12 34])

14:50 sexpbot: ⟹ ("12" "34")

14:51 tonyl: using pjstadig ##(map #(int (/ % 10000)) [20101122 20101123 20101122])

14:51 sexpbot: ⟹ (2010 2010 2010)

14:51 mroessler: Thanks everyone!

14:51 amalloy: tonyl: only works if every number is equally long

14:51 tonyl: true

14:51 amalloy: mroessler: ##(map (comp #(take 4) str) [12231414 346531])

14:51 pjstadig: ,(map #(Integer/parseInt (subs (str %) 0 4)) [20101122 20101121])

14:51 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: sandbox4394$eval6324$fn

14:51 clojurebot: (2010 2010)

14:52 amalloy: mroessler: ##(map (comp #(take 4 %) str) [12231414 346531])

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

14:52 tonyl: &(map #(subs (str %) 0 4) [20101122 20101123 20101122])

14:52 sexpbot: ⟹ ("2010" "2010" "2010")

14:53 pjstadig: ,(map (comp (partial apply str) (partial take 4) str) [20101122 20101121])

14:53 clojurebot: ("2010" "2010")

14:53 pjstadig: err something like that

14:54 mroessler: Thanks all. I'll look at the various suggestions.

14:58 amalloy: mroessler: note that all of the (subs) implementations will fail if the string has fewer than four characters. see clojure.contrib.string/take, which will give you the first up-to-four characters, neatly packaged as a string (unlike the seq of chars core/take gets you)

14:59 mroessler: amalloy: Excellent point. Looking now.

14:59 Lajla: mroessler, http://codepad.org/nv7STxR7 would this also work?

14:59 I don't know, I'm fucked at clojure, but it seemed cleaner to me to make a 'digits'function

14:59 It should take in a number and a base, and return a list of the digits that number has in that base

14:59 clojurebot: chouser: Some high-tech profiling with Activity monitor and println shows that I'm doing 100% of one core and not so much IO, though the number of files being read is huge(I estimate 5 per second).

15:01 mroessler: Lajla: looks suspiciously "anti-functional". I'll look at it.

15:01 Lajla: mroessler, why would it be anti functional?

15:01 It's just a function that takes in a natural and a base and returns a list of numbers

15:02 mroessler: Lajla: Hmm. the loop, if, let, I suppose. But I'm not taking issue with you - I'm grateful for the response!

15:02 Lajla: mroessler, clojure loops are not loops like in C.

15:03 They return a value actually.

15:03 As are ifs

15:03 pjstadig: ~loop

15:03 Lajla: Ifs are expressions, not statements

15:03 clojurebot: Pardon?

15:03 pjstadig: ~for

15:03 clojurebot: for is not used enough

15:03 Lajla: Well, a bit of both I guess

15:03 mroessler, basically, loop sets a recursion point

15:04 The function does not feature any mutable state as far as I can see.

15:04 mroessler: Lajla: no, no mutable state.

15:56 KirinDave: Let's take votes for our most used clojure core functions.

15:56 I vote constantly

15:56 I use that shit like 800 times a day

15:57 tonyl: i use map a lot

15:59 aamar: really? constantly? j/k?

16:00 amalloy: KirinDave: map has to be high on the list

16:00 KirinDave: aamar: You want to swap an atom or ref to a value

16:01 chouser: for atom use 'reset!'

16:01 for ref, use 'ret-set'

16:01 'ref-set'

16:02 amalloy: KirinDave: (reset!)?

16:02 KirinDave: amalloy: Oh, because it's a value passed in

16:02 It isn't always constant

16:02 So I just pass in constantly in my interfaces.

16:02 nickik: does anybody how i can read a file and preserve the äöü?

16:02 KirinDave: Like, for examnple...

16:02 amalloy: though i must say, if you ever find yourself doing this to an atom, it's very rarely right. i'm curious what you're doing that you do this 800 times a day

16:02 KirinDave: amalloy: Oh, not atoms 800 times a day

16:02 hiredman: ~google file.encoding

16:02 clojurebot: First, out of 3100000 results is:

16:02 How can I determine the encoding of a file

16:02 http://developers.sun.com/global/technology/standards/reference/faqs/determining-file-encoding.html

16:02 hiredman: useless

16:02 ~google java file.encoding

16:02 KirinDave: CLothesline services need functions which are often constants in practice

16:02 clojurebot: First, out of 128000 results is:

16:02 jGuru: How do I set a default character encoding for file I/O ...

16:02 http://www.jguru.com/faq/view.jsp?EID=78088

16:03 KirinDave: Come on gist. :\

16:04 amalloy: An example of why I am always using constantly: https://gist.github.com/f8579d7df3ebb2aaaed6

16:04 fogus`: I use syntax-symbol-anchor at least 138 times a month

16:04 KirinDave: fogus`: You Might Be A Clojure Badass If.

16:05 amalloy: KirinDave: okay, i see the idea. you might make clients' lives easier by checking the type of the value and behaving sensibly

16:05 KirinDave: amalloy: Sure, but sometimes it can be tricky to do so

16:05 amalloy: E.g., if something is a map it's an fn too, so...

16:06 I guess I don't know how to uniquely isolate FNs.

16:06 Is there a trivial way I don't know about that wouldn't also include things like maps or sets?

16:06 amalloy: &(doc fn?)

16:06 sexpbot: ⟹ "([x]); Returns true if x implements Fn, i.e. is an object created via fn."

16:06 amalloy: &(doc ifn?)

16:06 sexpbot: ⟹ "([x]); Returns true if x implements IFn. Note that many data structures (e.g. sets and maps) implement IFn"

16:07 amalloy: KirinDave: i hope this is trivial enough :)

16:07 KirinDave: Huh

16:07 fogus`: You know, Rich should have named it konstantly. :p

16:08 KirinDave: For some reason I always assumed fn did what ifn did.

16:08 amalloy: There is one other little problem.

16:08 amalloy: Maybe you can solve all my problems like President Commacho in just 10 minutes.

16:08 amalloy: i want to make it so that it plays nice with java.

16:08 Specifically

16:09 For scala and java and others, what can they pass in to these maps that would be fair game for a function?

16:09 amalloy: &(supers Fn)

16:09 sexpbot: java.lang.Exception: Unable to resolve symbol: Fn in this context

16:09 Raynes: fogus`: Mortal Klojure

16:09 KirinDave: java.util.concurrent.Callable

16:09 amalloy: &(supers (class (fn [])))

16:09 sexpbot: ⟹ #{clojure.lang.IObj clojure.lang.Fn java.lang.Runnable clojure.lang.AFunction clojure.lang.IMeta java.util.concurrent.Callable java.lang.Object clojure.lang.AFn java.io.Serializable clojure.lang.IFn java.util.Comparator}

16:09 KirinDave: Runnable is not appropriate.

16:09 amalloy: yeah, that's kinda a pain. callable or runnable

16:10 KirinDave: Runnable does't return a value

16:10 Callable seems right, but uh

16:10 hiredman: callable returns a value but doesn't take one

16:11 KirinDave: Right.

16:11 cemerick: Clojure functions are IFns; the other implemented interfaces are there for interop convenience.

16:11 KirinDave: :)

16:34 nickik: I have a problem if i read in a file the äüö are showed as a ?. Did anybody else have that problem?

16:34 tonyl: you would have to use file encoding that uses those characters

16:41 hoeck: nickik: encoding problem?

16:42 cemerick: nickik: all clojure source files must be in UTF-8

16:42 nickik: its not a sourcefile its a dic

16:42 cemerick: then you need to use the same encoding to read the file as was used to write it

16:46 mabes: does contrib share the same jira project as clojure itself?

16:48 nickik: cemerick: do you know how i convert the file?

16:52 KirinDave: I dunno what debugger-god I pissed off, but cdt-emacs just aint gonna work for me.

16:54 LOPP: nickik use a text editor

16:55 for instance Notepad++

16:55 nickik: using linux :)

16:55 Raynes: KirinDave: You pissed off the Debugods.

16:56 tonyl: nickik: I think you could open the file as a stream and get the bytes by UTF-8

16:57 nickik: thanks all wort with gedit

17:19 ohpauleez: dnolen: Awesome video

17:20 chouser: ring is hurting me

17:20 make it stop

17:20 hiredman: what are you doing?

17:20 * ohpauleez give chouser the safety blanket

17:20 ohpauleez: what's going on?

17:21 chouser: just trying to use wrap-params, but the resulting req still has no :params

17:21 hiredman: have you considered writing a macro?

17:21 chouser: ooh!

17:22 hiredman: are you sure it has no :params?

17:22 you may want to combine wrap-keyword-prams and wrap-params

17:22 chouser: yes, I'm sure.

17:23 hiredman: clojurebot: works on my machine

17:23 clojurebot: http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

17:23 chouser: (def app (-> handle-dump wrap-params wrap-keyword-params my-thing))

17:24 in my-thing I return a :body that includes prn-str of the req

17:24 it has a bunch of stuff in it, including a :query-string, but no :params

17:25 I'm sure I'm doing something stupid, I just don't see what yet.

17:25 amalloy: chouser: welcome to programming

17:25 chouser: backwards.

17:26 hiredman: right

17:26 kotarak: chouser: the order of functions?

17:26 * hiredman fell offline for a moment there

17:27 chouser: man. ok.

17:27 for some reason I was thinking -> was comp there for a while.

17:27 drewr: also, you don't call those functions on app

17:27 you call the fn those fns return on app

17:27 s/app/req/

17:27 sexpbot: <drewr> you call the fn those fns return on req

17:27 drewr: sexpbot: shut your hole

17:28 Lajla: kotarak, which scheme doesn't by the way?

17:29 I think I read a paper once of someone showing that quote was not a primitive.

17:29 But I think he made a mistake.

17:29 Because in his version (quote (bla balalblbalba)) I think also gets macroexpanded

17:29 Like, if you do (quote (and ...)) or something, it expands, instead of getting a list which starts with a symbol and

17:36 kotarak: Lajla: guile doesn't seem to do create function to handle let.

17:37 Lajla: kotarak, guile is an interpreter and not a compiler right?

17:38 kotarak: Lajla: Ah. Now we start being more and more precise.

17:38 Lajla: also, guile is a marvel of ridiculously badly written technology as to be expected from the masters who have us undocumented and inefficient outdated shat that for some reason has become a staple of C compilers.

17:38 kotarak, praecision is my middle name.

17:39 gave us*

17:40 Adamant: Lajla: what's next, a mortuiri salutant?

17:40 Lajla: Adamant, I have no idea what that means.

17:41 Adamant: probably bad Latin for "we who are about to die, salute you"

17:41 Lajla: This is because I am ignorant, beardless, and do not use gNewSEnse

17:41 All unlike Richard Stallman

17:41 Ahhh

17:41 That is incorrect actually.

17:41 Adamant: I figured praecision was Latin

17:41 Lajla: It means 'those who are about to died salute you'

17:42 third person

17:42 Adamant: probably, I would totally get Pythoned in Latin class

17:42 Monty

17:42 I never had one, just picked up shit here and there

17:42 Lajla: I find it amazing that I said I didn't know what it means when I could read it.

17:42 Just shows how lazy I am.

17:42 Unlike Dr. Richard Stallman

17:43 Adamant: the good Doktor

17:43 Lajla: Though his belly might evidence otherwise.

17:43 Adamant: not for a programmer

17:43 Lajla: That is true

17:43 I heard he's actually pretty bad and basically hacks his shit together into unreadable garbage

17:43 Adamant: doubtful

17:43 he is from another, braver era though

17:44 Lajla: A rumour it may be, but what if it's on wikipedia?

17:44 Adamant: then it's just stupid

17:44 Lajla: Yeah, the era people hacked shit together due to performance problems and because Dijkstra hadn't yet risen to being the leader of the illuminati.

17:44 mroessler: I see a lot of examples in Clojure books/sites about comparing quantities: (> 10 5) true. But I am missing how to I combine comparisons, such as greater than 5 AND less than 7?

17:44 Adamant: no, they assumed everyone was a wizard and if you weren't, tough shit

17:44 Lajla: mroessler, use and

17:44 Adamant: also, documentation was for the weak

17:45 Lajla: Or like (< 3 x 7)

17:45 amalloy: mroessler: ##(> 5 6 7)

17:45 sexpbot: ⟹ false

17:45 amalloy: mroessler: ##(< 5 6 7)

17:45 sexpbot: ⟹ true

17:45 Lajla: amalloy, other way around

17:45 mroessler, but if you want it more complex, you can use and

17:45 Like (and (> 3 x) (<= x 9))

17:46 So

17:46 what I get from this ## notation

17:46 Is that every thing I type

17:46 mroessler: Lajla: thanks!

17:46 Lajla: Is parsed by sexpbot?

17:46 Is that right ##sexpbot?

17:46 Ah

17:46 No, it is not

17:46 Or maybe it is

17:46 tonyl: it has to be a form, i think

17:46 Lajla: Is that right ##()

17:46 sexpbot: ⟹ ()

17:46 Lajla: But a symbol is a form

17:47 tonyl: maybe not then

17:47 just what ever is between ##( and )

17:47 sexpbot: ⟹ true

17:47 tonyl: lol

17:47 Lajla: mroessler, take note

17:47 This is a manly lisp

17:47 Here operations are variadic

17:47 So like (+) is 0

17:47 And (and) is true

17:47 And (or) is false

17:48 And ##(and 3 2 4 7)

17:48 sexpbot: ⟹ 7

17:48 Lajla: And ##(or false nil 3 7)

17:48 sexpbot: ⟹ 3

17:49 msilverman2: (+ 3 4)

17:49 clojurebot: *suffusion of yellow*

17:50 msilverman2: ##(+ 3 4)

17:50 sexpbot: ⟹ 7

17:50 tonyl: what's up with clojurebot replying with that :P

17:51 hiredman: legacy feature

17:51 amalloy: tonyl: 0.5% of the time (iirc), he randomly pretends the previous statement was addressed to him

17:51 msilverman2: ##(car (cdr '(1 2 3)))

17:51 sexpbot: java.lang.Exception: Unable to resolve symbol: car in this context

17:51 hiredman: no, math expressions are always interpreted

17:51 msilverman2: ##(first (last '(1 2 3)))

17:51 sexpbot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

17:52 hiredman: from the days when clojurebot was a single gist

17:52 tonyl: ##(first (rest '(1 2 3)))

17:52 sexpbot: ⟹ 2

17:52 msilverman2: ##(first (rest '(1 2 3)))

17:52 sexpbot: ⟹ 2

17:52 mroessler: Double "pound" or "hash" is to get the clojurebot to execute an IRC line? Sorry for the ignorance.

17:52 hiredman: no

17:52 amalloy: mroessler: there are a lot of ways to get the bots in here to talk

17:52 ,"clojurebot"

17:52 clojurebot: "clojurebot"

17:52 amalloy: &"sexpbot"

17:52 sexpbot: ⟹ "sexpbot"

17:52 Lajla: mroessler, watch this:

17:52 ,"Clojurebot"

17:52 clojurebot: Lajla: Cool story bro.

17:52 mroessler: ##(> 5 7)

17:52 amalloy: mid-sentence with ##"magic"

17:52 sexpbot: ⟹ false

17:52 Lajla: ,"Clojurebot"

17:52 clojurebot: Lajla: Titim gan éirí ort.

17:52 Lajla: Cool eh?

17:53 I am such a douche, they made the bot ignore me.

17:53 Adamant: I don't think speaking Irish is ignoring

17:54 they're just still upset about the Hadrian's Wall thing

17:54 msilverman2: car and cdr is too old school, I guess: http://en.wikipedia.org/wiki/CAR_and_CDR

17:54 amalloy: msilverman2: yes, we're aware of what car and cdr are :)

17:54 first and rest replace them, although most of the time you're better off with destructuring

17:55 hiredman: Adamant: hadrian's wall was scotland

17:55 amalloy: &(let [[x & nums] [1 2 3 4]] [x nums])

17:55 sexpbot: ⟹ [1 (2 3 4)]

17:55 Adamant: hiredman: a Celt is a Celt

17:55 msilverman2: new to clojure and haven't touched lisp in about 20 years. It's all coming back to me...

17:55 Adamant: to a Roman, anyway

17:58 Lajla: msilverman2, I think it's more that that clojure does not have cons cells.

17:58 A list is a list.

17:58 The rest is implementation abstracted

17:58 pair? or consp does not exist

17:58 I like car and cdr though, because you can cdadar.

17:59 If you have a binary tree

18:00 msilverman2: lajla: agree on cdadar coolness.

18:00 joshua__: Hey guys. I was wondering how I'm suppose to go about converting the params map given in compojure so that it uses :keys rather than "strings".

18:01 Right not I'm trying to wrap the handler with a ring middleware called wrap-keyword-params and it isn't working.

18:02 pjstadig: ,(ffirst '(foo (bar baz)))

18:02 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

18:02 pjstadig: ,(ffirst '((foo bar) baz))

18:02 clojurebot: foo

18:02 hiredman: joshua__: you have to use wrap-params first

18:02 pjstadig: ,(frest '(foo (bar baz)))

18:02 clojurebot: java.lang.Exception: Unable to resolve symbol: frest in this context

18:02 hiredman: ,fnext

18:02 clojurebot: #<core$fnext clojure.core$fnext@1134c4b>

18:02 pjstadig: right

18:03 ,(fnext '(foo (bar baz)))

18:03 clojurebot: (bar baz)

18:05 eyeris: Is there ever any reason to use a ref instead of an atom in a single-threaded program?

18:05 hiredman: is there a reason to use an atom?

18:05 amalloy: &(let [[a [[b]]] [[1 [2 [3 4]]]]] [a b])

18:05 sexpbot: ⟹ [[1 [2 [3 4]]] nil]

18:05 KirinDave: Man, fuck AOT compilation.

18:05 eyeris: To avoid rebinding vars

18:06 KirinDave: I spend 30m because some compiled module doesn't get a new copy of the function when I reload the module via emacs

18:06 hiredman: KirinDave: family friendly

18:06 eyeris: When I tried to do set! I was continually confused by the distinction between root bindings and thread-local bindings

18:06 KirinDave: hiredman: I'm speaking from the heart here.

18:06 hiredman: sure

18:07 eyeris: why use set!?

18:07 eyeris: not the distiction between what they are, but it was hard to keep track of which global defs I rebound with (binding) just to satisfy the runtime

18:07 hiredman: isn't set! the way you change a var?

18:07 hiredman: eyeris: why change a var?

18:07 KirinDave: eyeris: It's a bit unusual to change a var permanently that way. It's relatively unsafe.

18:08 eyeris: It's preferred to reset an atom.

18:08 hiredman: untrue

18:09 it's preferable not to mutate anything and program with values and functions

18:09 eyeris: hiredman: well I'm making what amounts to a poor-mans message broker. clients can make an HTTP request to establish a new queue. I keep those queues in a map. (def queues {}). In order to add a queue to the map, I need to call assoc and then rebind the queues var to the result of assoc.

18:10 hiredman: eyeris: that definitely should be an atom

18:10 eyeris: Okay. Good. That's what I used.

18:10 technomancy: the only reason vars can be changed is to support interactive programming

18:11 *the only reason var roots can be changed

18:11 eyeris: So what I was asking was whether there was any advantage at all to using a ref in a single-threaded app like this.

18:12 KirinDave: eyeris: Oh, in a single thread? If you can really guarantee that, then there is none.

18:12 eyeris: I was basically looking to reinforce whether or not I made the proper decision.

18:12 KirinDave: eyeris: For that, you could set! a thread local binding to ensure it. It's just... threading has a way of creeping into coding in places you don't expect.

18:12 amalloy: eyeris: i'm not sure single-threadedness is relevant. i've had an instance where, with only one thread, doing what i wanted was much easier with a ref

18:13 eyeris: What were you doing?

18:13 amalloy: eyeris: trying to mutate something, unless the new value would break some postcondition; in which case leave it alone and note a failure

18:14 hard to do with swap!, because the only thing you return from an atom is the atom's new value

18:14 eyeris: I see. In that case you found a use for the post-set hooks that come with refs.

18:15 amalloy: eyeris: no, easier than that

18:15 technomancy: couldn't you use a postcondition on the function you pass to swap!?

18:15 hiredman: atoms come with watchers too

18:15 amalloy: technomancy: that would assert, not "leave it alone and note a failure"

18:16 hiredman: amalloy: the ref mutation functions also only return the value of the ref

18:16 amalloy: (dosync (let [newval (whatever @ref)] (when (condition newval) (set ref to newval))))

18:17 hiredman: but dosync returns whatever you did last

18:17 and lets you test the ref before you mutate it, without breaking atomicity

18:18 hiredman: so would any other function you twiddle the atom in

18:18 eyeris: Is there anything in clojure.test that is akin to the OO unit test framework's setUp() methods, letting me create some state to test against? All of my tests need to create a queue and then, after the test, destroy it.

18:20 amalloy: hiredman: i think it's harder than you're suggesting, but i'd love to be proven wrong. try swapping n with n^2, unless n^2 > 1000; in the code calling the swap, handle the swapped/ignored cases differently

18:21 KirinDave: amalloy: For bonus points, error-kit in there.

18:21 hiredman: (fn [a] (let [x (swap! x som-fn)] (when (some-test x) (do-other-stuff-to a)))

18:21 KirinDave: And yes, I know error-kit is unpopular now. :\

18:22 jweiss_: is the "clojure protocols explained" talk from the conj online anywhere? (video or slides)

18:23 amalloy: hiredman: now you've swapped in a value that is illegal for a. i specified leave the atom's value unchanged if changing it would break a rule

18:23 hiredman: amalloy: no I haven't

18:23 nickik: how to get at post data in compojure?

18:24 jweiss: the videos have not been released

18:24 hiredman: amalloy: for a single thread that is the same as your dosync

18:24 amalloy: hiredman: so some-fn leaves x alone if it's too large? now you can't tell whether someone tried to square 25 and failed, or tried to square 5 and succeeded

18:25 hiredman: fine, call it some whatever from your dosync instead of swap!

18:25 the point is, it is exactly the same

18:26 amalloy: hiredman: you're right. i didn't flesh out the dosync well enough to do exactly what i meant

18:26 hiredman: doesn't matter if you did

18:27 amalloy: (dosync (let [newval (whatever @ref), succeess (cond newval)] (when success (set ref to newval))) success)

18:27 mabes: jweiss_: this video may be of interest to you though: http://www.infoq.com/presentations/Clojure-Expression-Problem

18:27 jweiss_: mabes: thanks

18:27 amalloy: hiredman: i really don't see how you can do this with an atom

18:27 _ato`: did I miss a constraint or isn't that just: (swap! a (fn [old] (let [new (f old)] (if (condition new) new old))))

18:27 ie if the condition fails, swap! in the old value (hence in effect leaving the atom unchanged)

18:28 amalloy: _ato`: the constraint is that you want to be able to know whether the atom changed

18:28 hiredman: amalloy: just make the dosync a do

18:29 amalloy: hiredman: hmm. yes, in a single-threaded app that would be sufficient. good point

18:29 Lajla: amalloy,

18:29 could you give hiredman a hug with my compliments?

18:30 amalloy: i prefer coding for multithreading when using STM, but i did (erroneously, i now see) claim that this was a problem for single-threaded apps

18:33 kotarak: amalloy: watches will tell you whether an atom changed or not, and what it's old and it's new value are.

18:34 nickik: How do i simply get the values from a form i submited with the post method?

18:34 amalloy: kotarak: then you have to deal with asynchronous-like callback semantics

18:36 hiredman: if only there was a set of types and a macro that made async programs look like sync programs...

18:38 eyeris: I have one file blabber/exchanges.clj with (ns blabber.exchanges (:use blabber.queues)) and blabber/exchanges/test.clj with (ns blabber.exchanges.test (:use blabber.exchanges)). The first ns macro runs fine but when I run the second ns macro, it complains "No such namespace blabber.queues".

18:38 Actually, "No such namespace: queues"

18:39 hiredman: circular dependencies are not allowed

18:39 eyeris: There is no circular dependency though. blabber/queues.clj uses (ns blabber.queues (:gen-class))

18:41 Since it dropped the blabber. prefix in the error message, it seems like the resolver is looking for blabber.exchanges.queues

18:46 Ahh, it was complaining about a fully qualified use of a function in that namspace

18:47 that I missed when I changed from :require to :use

18:47 slime just lost that line reference in the backtrace

19:04 Is there any way to add jars to the classpath of swank while it is running?

19:05 raek: there is (add-classpath "file:///path/to/jarfile.jar") but it doesn't work in every case (that's why its deprecated)

19:06 eyeris: Okay

19:07 raek: it has something to do with classloaders, I think...

20:59 coldhead: thanks clojurebot

21:10 abedra: build.clojure.org just got and upgrade to the latest bits

21:11 if anyone experiences any strangeness please let us know

21:46 tonyl: does anybody know if there is a roadmap for clojure-in-clojure

21:49 or maybe is there a plan to use protocols, types, records and/or multimethods to help on this?

21:51 dnolen: tonyl: that's certainly the groundwork for moving a lot of the Java bits into Clojure.

21:53 tonyl: ok, do you know if version 1.3 is a step towards that goal?

21:54 dnolen: those things happened in 1.2

21:54 tonyly: I'm not sure what else is planned for 1.3.

21:54 tonyl: yeah, but to replace some of the java bootstrapping with protocols, types, etc...

21:54 ok

21:54 mmm ...

21:55 I'll have to do some digging

21:57 dnolen: tonyl: I'm have suspicion that c-in-c will be primarily community driven, as c-in-c benefits, for now, a small community.

22:00 tonyl: community driven is the only way clojure is being developed, or at least that is what I thought.

22:00 scottj: tonyl: my guess is pods/scopes/invokedynamic/forkjoin stuff will happen before cinc gets much work

22:01 amalloy: tonyl: community + rich *chuckle*

22:01 and rich is busy

22:01 tonyl: yes, there are a lot of milestones besuce cinc

22:02 * tonyl thought rich was an alien from another planet when he read '+ rich'

22:02 scottj: what's rich so busy with?

22:02 dnolen: tonyl: sure what I meant was that rich tends to lead the language design of most things. c-in-c will probably be less lead by him. could be wrong tho.

22:02 amalloy: speaking of pods, dnolen, any news on what they are? i've only heard vague mutterings about constrained mutability

22:03 dnolen: amalloy: constrained mutability?

22:03 amalloy: dnolen: amendment: vague mutterings that could be total nonsense

22:03 dnolen: amalloy: oh yeah, no I think the gist is still the only concrete implementation of the ideas

22:04 amalloy: "the gist"? is there something concrete on github somewhere?

22:04 dnolen: amalloy: I do note some some similarities between the idea and some sections in the last sections of CTMCP where they discuss Cells (old name), http://www.info.ucl.ac.be/~pvr/book.html

22:04 tonyl: I don't see it in the next.release milestone

22:06 dnolen: amalloy: https://gist.github.com/306174

22:07 amalloy: thanks dnolen. looks interesting

22:24 quizme: I'm having a "lein deps" problem: http://pastie.org/1319114 anybody know what i shoudl do ?

23:18 Licenser: morning

23:18 tonyl: night :P

23:19 trybeingarun: noon :P

23:24 Licenser: night tonyl, noon trybeingarun

23:33 trybeingarun: I am planning to read 1) On Lisp 2) Paradigms of Artificial Intelligence Programming 3) Structure and Interpretation of Computer Programs

23:33 after finishing Programming CLojure

23:33 what order do u guys think would be good/

23:35 dnolen: trybeingarun: PAIP looks pretty hardcore. I know SICP is hardcore, you'll probably need a break between those two.

23:35 coldhead: i'd read 1 and 3 simultaneously

23:35 they're about different things

23:36 trybeingarun: dnolen: have you read SCIP? Is it really worth the credit it gets?

23:36 coldhead: you might get some interesting harmonics between the two

23:37 dnolen: trybeingarun: it is worth and more yes. I worked through all the chapters and almost all the problems of up and including the MetaCircular Evaluator

23:37 7 years ago I didn't see the point of covering lazy eval, logic programming, or the compiler chapter.

23:37 trybeingarun: I am trying to showcase some nice work in Clojure @ work to get more developers interested

23:37 dnolen: I've of course changed my mind about that since then.

23:37 amalloy: trybeingarun: SICP is pretty amazing

23:38 trybeingarun: I want to move in a direction which will get me up and running quickly

23:38 coldhead: most of the exercises in SICP are very satisfying to complete

23:38 dnolen: trybeingarun: neither will do that for you :) On Lisp might be better bet then.

23:38 coldhead: yeah, on lisp is the pragmatic choice

23:38 SICP goes well with a wizard bong

23:39 dnolen: that said I think this is not talked about enough as a rich source for Rich's ideas, http://www.amazon.com/Concepts-Techniques-Models-Computer-Programming/dp/0262220695

23:39 PAIP and SICP are light on concurrency issues

23:39 CTMCP is filled with ideas about concurrency.

23:41 but that's yet another massive tome

23:43 trybeingarun: got disconnected from the chat (actully tripped on my mode and its power chord came off :P)

23:43 *modem

23:43 could you guys repeat your suggestions?

23:44 Licenser: trybeingarun: see your query

23:45 trybeingarun: thanks Licenser :)

23:45 * Licenser bows

23:45 Licenser: if I can't help with suggestions I can with copy & paste ;)

23:46 trybeingarun: is SCIP a good time investment? Lets say, I am able to spend 2 hrs daily on that?

23:46 dnolen: trybeingarun: On Lisp if you want to get moving, SICP and PAIP are for digging in. I recommend Concepts Techniques and Models of Computer Programming for a rich reference for many of Clojure's concurrency ideas. transactions/futures/promises/etc

23:46 trybeingarun: Of course I am considering learning On Lisp also as dnolen had suggested

23:47 dnolen: trybeingarun: SICP great but it's also a rehash of a lot of stuff if you're an experienced programmer.

23:49 amalloy: dnolen, trybeingarun: it goes over some basic stuff, but in a way that is revelatory anyway

23:50 trybeingarun: A few guys (forums) have suggested "How To Design Programs" is "THE CORRECT WAY THAT SCIP SHOULD HAVE BEEN WRITTEN"

23:50 anybody has read that book?

23:52 Licenser: trybeingarun: are you in a big company?

23:53 trybeingarun: I work for ThoughtWorks, if you have heard of that

23:54 it is a medium sized company

23:54 Licenser: hmm

23:55 hmm hmm do you have silly management people?

23:55 trybeingarun: Joined the company last month only dude; so can't say much

23:56 Licenser: heh okay

23:56 trybeingarun: as far as I have observed management's role is to enable and facilitate devs (unlike my previous company *I WONT NAME IT* :) )

23:57 Licenser: was just wanted to suggest how to convince your colegues, show them this http://manager.licenser.net/ and tell them to reload a few times then tell them the code for that are 25 lines clojure that were done during a telco :P

23:57 trybeingarun: 25 lines??

23:58 Licenser: yap

23:58 not including html and dataase

23:58 trybeingarun: i hope it is not like rails; you use the entire framework and nothing counts as a line of code :)

23:58 Licenser: but it randomly generates management like phrases and does it very well

23:59 nah I just did not count 50 lines of html strings in there since it would be lame

23:59 trybeingarun: that is okay. Just the code part is nice

23:59 is there any heavyweight web framework available for clojure?

Logging service provided by n01se.net