#clojure log - Jul 12 2011

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

0:13 gstamp: A little gotcha... *ns* seems to point to clojure.core when you run as a gen-class compiled classfile.

0:45 hiredman: gstamp: why do you think it would be set to something else?

0:48 when you compile a file a dynamic binding is pushed for *ns*, and effectively is set! to a given namespace by ns or in-ns

0:48 the set! value is popped off when compilation is complete

0:49 when you are running anywhere but in a repl *ns* is almost always clojure.core

2:32 ihodes: coolest piece of software i've recently used: VMWare Fusion.

3:49 chitsubr: Anyone know a way to get tab completion of clojure keywords in emacs?

3:56 kumarshantanu: chitsubr: autocomplete.el ?

3:56 chitsubr: but it works off a TAG file AFAICT

3:57 chitsubr: kumarshantanu: ah right. Thanks, I'll look around for tag files for clojure.

4:10 kumarshantanu: chitsubr: apparently the latest autocomplete.el already has the clojure.core tags

4:14 chitsubr: kumarshantanu: I will update my autocomplete.el then, thx

5:02 shtutgart: Is it correct to def things inside a defn?

5:03 e.g. (defn foo [x] (def bar x))

5:03 lnostdal-laptop: that should be fine

5:05 shtutgart: it works, but is it idiomatic?

5:06 lnostdal-laptop: hard to tell with no context

5:07 Chousuke: that's usually completely the wrong thing to do :/

5:08 shtutgart: It's for building gui. Function creates form, and inner defs are widgets.

5:08 Chousuke: all defs are top level, and most of the time doing them from a function makes no sense (since you're not supposed to def the same var multiple times)

5:08 use let for local variables

5:10 the only situation where defs from a function make sense is an "init" function that sets up your program/library and gets called exactly once (even then it's somewhat icky)

5:10 lnostdal-laptop: i guess you want them to stick around after the function ends then .. perhaps using a structure in a variable (atom/ref) defined only once would work too

5:10 Chousuke: avoid that too

5:10 lnostdal-laptop: ..then setting that ref/atom

5:11 Chousuke: just return whatever you want to keep from the function

5:11 lnostdal-laptop: yes, return and set

5:12 shtutgart: I was using let, but I need access to widgets from other functions, with let they anyway have to be defined in the defn, so I'll be ended up with ALL my functions and widgets defined in the one let form, which is hard to read and understand

5:12 Chousuke: in general, the number of functions *not* dealing with atoms or refs should be significantly higher than the number of functions that do have state.

5:13 shtutgart: Chousuke: return all widgets from the function?

5:13 Chousuke: shtutgart: yes. in a container, if you have to

5:14 if you need access to other widgets, have the other functions return them

5:14 then collect it all together in one function

5:14 using modifiable globals is brittle and unidiomatic. :/

5:15 shtutgart: But then I will have all my namespaces with all my definitions wrapped in one bug and messy let form

5:15 Chousuke: why?

5:15 clojurebot: why not?

5:15 Chousuke: clojurebot: shut up

5:15 :P

5:15 clojurebot: Titim gan éirí ort.

5:16 shtutgart: because I need access to widgets in other functions

5:16 lnostdal-laptop: you could use a map structure bound to a let

5:16 in a let*

5:16 Chousuke: shtutgart: I don't understand what the problem is

5:16 shtutgart: lnostdal-laptop: map with widgets?

5:16 lnostdal-laptop: sure .. i guess they have IDs

5:17 id -> widget-instance .. and i like having stuff like this in a top-level global so my top-level function can return to the repl and i can inspect things freely .. there's no problem with this

5:17 shtutgart: but... we already have namespaces for this purpose, why should I create another one map?

5:18 Chousuke: ok. let me paste an example

5:18 Chousuke: in that case you can do something like... (defn make-widget ....) (defn make-all-widgets ...) (def widgets (make-all-widgets))

5:25 shtutgart: something like this: http://paste.lisp.org/display/123219

5:26 also note that I need forward declaration to define widgets in right order

5:28 lnostdal-laptop: i really don't understand why you do not use a map for this

5:28 Chousuke: yeah, a map would be fine

5:28 shtutgart: I can't see why to wrap widgets in another map. We already have namespaces! What's the profit of holding widgets in the map?

5:28 Chousuke: the profit is that you can pass them around easily

5:29 shtutgart: One difference is tha i have to type (:widget *map*) instead of just widget

5:29 Chousuke: no globals

5:29 and you can destructure

5:29 lnostdal-laptop: it's easier to pass around?

5:29 Chousuke: so (let [{:keys [widget names here]} widgets] ...)

5:30 shtutgart: If I use var-per-widget approach, I don't need destructing at all.

5:30 Chousuke: yes but then you have loads of vars that you can never garbage-collects :/

5:30 -s

5:31 shtutgart: Hm, good point

5:32 lnostdal-laptop: well, it's not like the widgets in the map disappear as if by magic either

5:33 (..and clojure has no support for weak hash-tables; if that'd be interesting in this context..)

5:34 Chousuke: lnostdal-laptop: but you can just lose your reference to the map

5:34 I'm not saying def it into a var

5:35 lnostdal-laptop: sure, but that'd happen if he def'ed over his many vars also; the old bindings would be GCed

5:35 ..not sure i'm using the proper terms her, but anyway

5:36 Chousuke: yeah but that's ugly

5:36 and not guaranteed to work anyway I think, at least in 1.3

5:36 lnostdal-laptop: it should work

5:36 but this is beside the original point anyway

5:36 Chousuke: perhaps only for dynamic vars

5:37 lnostdal-laptop: ..it'd be a bug in clojure if it didn't work, and even if it did work it isn't interesting..

5:37 Chousuke: no, it's not a bug. The behaviour will change in 1.3

5:37 vars will be more like constants

5:37 so you can't just go ahead and def them again

5:37 lnostdal-laptop: i'm jusing 1.3 .. i know

5:37 using*

5:38 of course you can def them again

5:39 they are not constant; they are instead not dynamic by default

5:39 ..IIRC

5:39 i can redefine plan unearmuffed vars for sure at least

5:39 plain*

5:39 but forget this ....sheesh... it's not interesting in this context anyway .. :}

5:41 shtutgart: hm, then, what can you advice me about forward declaration? Should I write macro that first lets all widgets to nil? And what about bindings? Should I write another macro and renounce the use of bindings?

5:42 Chousuke: you don't need a macro

5:42 (declare whatever you want)

5:42 :P

5:43 I'm still not sure that it's a good idea to def widgets globally but whatever :)

5:43 shtutgart: Chousuke: I mean macro that will be automatically let all widgets to nil first

5:43 lnostdal-laptop: i wouldn't do that at all, shtutgart .. i'd use a single top-level dynamic ref-variable bound to a map.. whenever my top-level function returns i'd ref-set it

5:43 Chousuke: shtutgart: what for?

5:43 lnostdal-laptop: ..and i'd using the binding form for the rest of the call tree

5:44 Chousuke: shtutgart: if you let them to nil you could just as well let them be the actual widget objects

5:45 since let bindings are lexical and constant, you can only "change" the binding by shadowing it

5:46 shtutgart: lnostdal-laptop: ok, I'll try it

5:47 Chousuke: I want to define widgets in right order (think of html) and that requires some forward declaration, that's why i'm talking about letting to nil

5:54 lnostdal-laptop: shtutgart, http://paste.lisp.org/display/123220 .. something like this i think .. typed in a hurry tho

5:55 ..i wonder if clj has something like prog1

5:58 shtutgart: lnostdal-laptop: thank you, i'll look into it

5:59 bsteuber: shtutgart: I assume you use a java gui framework

6:00 so why not just use mutation to cennect the widgets?

6:00 s/cenn/conn

6:00 sexpbot: <bsteuber> so why not just use mutation to connect the widgets?

6:00 shtutgart: bsteuber: it can't be done; constructors require parent widget

6:01 bsteuber: so let the parent first

6:02 or do you want to build all in one nice expression?

6:02 which framework is it?

6:02 shtutgart: yep

6:02 swt

6:03 bsteuber: oh didn't know

6:04 seems like you need a macro for that, with all the drawbacks macros have..

6:26 shtutgart: bsteuber: I already have macros here and there, so another one doesn't make much difference :)

6:29 bsteuber: lol

6:31 another idea would be to not return swt objects immediately

6:31 but rather have your widget functions build clojure data structures

6:31 that get "compiled" to swt all at once

6:32 maybe that'd be cleaner than macro hell

6:37 shtutgart: bsteuber: hm, then user's action functions can also operate on clojure data structures, and framework will then generate setters calls for changed values (I guess I read about such approach somewhere on the clojrue google group)

6:39 bsteuber: sth. like that

6:39 maybe I should've done the same for my swing wrapper ^^

6:40 well I don't need to set parents most of the time, so I don't have your problem

6:40 but a lot of other ones :)

6:43 shtutgart: no, Im talking not about parent, but about any changeable values. Like, your action-listener should be widgets-map -> widgets-map function, where widgets are immutable clojure records, and framework should take the diff of the input and output and generate setters for changed fields

6:43 then holding widgets in a map makes complete sense, now I see

6:43 bsteuber: yes sounds elegant

6:44 but you'll probably get other problems ^^

6:45 shtutgart: definitely! :)

6:45 bsteuber: I sometimes dream of starting a pure clojure gui framework

6:46 that's lying on top of a pure clojure graphics/layouting framework

6:46 but...

6:47 shtutgart: btw, have you seen envydon?

6:49 bsteuber: no, what's that?

6:51 shtutgart: hm, I've lost the link, let me google that...

6:52 gfrlog: good morning europe

6:57 shtutgart: ah, it calss indyvon: https://bitbucket.org/kryshen/indyvon

6:57 *it's called

7:03 bsteuber: sounds interesting

7:34 jcromartie: indyvon looks like "immediate mode" giu

7:34 gui

8:03 clgv: what's the easiest way to find a given item in a nest clojure data structure consisting of hashmaps and vectors?

8:03 s/nest/nested/

8:03 sexpbot: <clgv> what's the easiest way to find a given item in a nested clojure data structure consisting of hashmaps and vectors?

8:08 bsteuber: clgv: maybe manually flatten it first

8:08 clgv: bsteuber: hm I guess I might not have to search for the items - seems I had some update-compilation problem

8:09 I should do "lein clean" more often

8:22 bsteuber: clgv: just for the fun of it: https://gist.github.com/1077871

8:23 clgv: bsteuber: the problem didnt vanish - so I'll give that one a try.

8:24 bsteuber: bot sure if you just want to check for existence or return the value or whatever

8:24 not :)

8:25 clgv: I have data I want to serialize and get a NotSerializableException - but in advance I have code that converts the deftypes to standard clojure data - seems somehow one or more objects of the deftype manage to hide somewhere they shouldnt

8:25 bsteuber: ah

8:26 clgv: I dont find them manually

8:26 bsteuber: so then instead of true you'll want to return x

8:27 clgv: true. will be sufficient for the first check

8:28 (rec-find #(instance? bla.blubb.Mytype %) data-map) returns nil. so where are they hiding? :/

8:38 humm serializing lazy sequences could be an issue... :/

8:38 Hodapp: yes.

8:38 clgv: really stupid mistake^^

8:38 Hodapp: psssh, it happens

8:38 clgv: guess I have to write that "eager" "map!" command now

8:39 Hodapp: like when I forget I'm on a remote server and I do a DHCP release

8:39 clgv: I needed it at least 5 times now, thats big enough as threshold ;)

8:39 Hodapp: oh thats epic ;)

8:39 bsteuber: wyh exactly do you need to be eager?

8:39 some external resources involved?

8:40 clgv: bsteuber: so that the conversion takes place bevor the serialization - otherwise the lazyseq object is serialized with the uncoverted data it seems

8:42 bsteuber: one dorun not enough?

8:42 erm doall

8:42 clgv: yes, I put a doall there now

8:42 bsteuber: well that's probably not recursive

8:43 Cozey: What's a better keyword counterpart for a camelCasedName? :camelcasedname or :camel-cased-name

8:43 digash: blist

8:43 clgv: but (doall (map ...)) is really lame. I just could write a different map command that just evaluates everything ;)

8:44 babilen: Cozey: I would say :camel-cased-name -- but listen to the gurus here

8:44 (i.e. not me)

8:44 Cozey: ok:-)

8:44 it seems to be more readable

8:45 on the other hand leaving dashes out is not much less readable, and is less typing

8:45 shtutgart`: vote for :camel-cased-name

8:45 babilen: typing? use a proper editor that allows completion :)

8:49 Cozey: i use one

8:53 digash: blist

9:17 clgv: my eager do-map can be found here: http://pastebin.com/eyN0uzPB - I wrote it somehow similar to map. any comments on it?

9:19 pdk: (vec (map f colls)) :p

9:19 also putting )'s on their own lines is usually bad form unlike with }'s in C

9:20 clgv: pdk: yeah ok. except formatting^^ It's my thing - you might reformat it as you please :P

9:20 Chousuke: no-one will like reading your code if you write it like that though

9:20 clgv: (vec (map f colls)) has syntactic and runtime overhead

9:21 Chousuke: mmh

9:21 are you sure?

9:21 pdk: everyone ends up letting the editor space stuff for them in the end with lisp anyway so just run it through autoformat after you're done writing it i guess

9:21 tomoj: syntactic overhead?!?

9:21 Chousuke: I mean, (def do-map (comp vec map))

9:21 clgv: I dont know an autoformat tool

9:21 Chousuke: pdk: that's not an option if you're collaborating on something though

9:22 shtutgart`: Do you remember that Steve Egge's thread about saying "yes"? ;)

9:23 Chousuke: the runtime overhead for the one-line implementation of do-map is a couple extra short-lived objects.

9:23 the JVM excels at working with those.

9:23 so they're basically free.

9:24 doing it manually is a decent exercise I guess but not exactly efficient use of programmer-time :)

9:26 clgv: Chousuke: well do-map was written in 5-10mins - so the programmer-time was reasonable ;)

9:26 Chousuke: clgv: that's pretty bad compared to the 2 seconds it took for me to write my version :P

9:27 clgv: Chousuke: well I am currently measuring runtime difference ;)

9:29 shtutgart`: Hm. Is it right that we do not have a naming convention for globals? I've just spent 5 minutes to figure out where an IllegalArgumentException comes from, and finally discovered that I have local binding shadowing global var...

9:31 Chousuke: shtutgart`: most globals are supposed to be constants and as such don't need anything special

9:31 lnostdal-laptop: pdk, it'll indent horizontally allright, but the vertical space is lost

9:32 Chousuke: rebindable globals are called *foo*

9:32 shtutgart`: Chousuke: I know. But such constant can also be atoms or refs.

9:33 Chousuke: shtutgart`: it's still a constant

9:33 shtutgart`: Chousuke: I know, but it's global!

9:33 Chousuke: shtutgart`: what does that matter?

9:33 shtutgart`: if it's a ref, its mutability is clear from how you use it anyway

9:34 shtutgart`: Chousuke: see my first message :) Well, likely it's just my inattention

9:35 Chousuke: of course, no-one will stop you if you really want to use some naming convention for globals

9:36 lnostdal-laptop: shtutgart`, perhaps you're using (let .. ) where (binding ..) should be used?

9:37 ... and i think *this-is-the-style-for-dynamic-globals* and for the other more traditional globals there is no convention .. i'm -using-this-style-for-them-though-

9:38 shtutgart`: lnostdal-laptop: no, I just had local with the same name as var (and got confusing exception with no line number known)

9:38 chouser: in some lisps +this+ is used for globals

9:38 lnostdal-laptop: that's constants, is it not, chouser ?

9:38 shtutgart`: -this-style- looks really better than +this+

9:38 chouser: lnostdal-laptop: oh, probably

9:39 but in Clojure, global namespaced vars are used for all our functions too -- surely you're not going to put dashes around all of them?

9:39 lnostdal-laptop: in CL i used +this+ for constants, -this- for globals (only some CL implementations supported that tho; i.e. SBCL), and *this* for dynamic globals

9:39 chouser: they're in no less danger of be shadowed than other vars

9:40 lnostdal-laptop: hm, yeah, lisp-1

9:40 clgv: Chousuke: for input colls of length 100 measuring over 100 repetions my do-map needs only 3/4 of vec+map. for colls of length 1,000,000 and 100 repititions do-map only need 60% of vec+map

9:41 lnostdal-laptop: uh, but since the naming style for vars and functions differ it'll be ok i guess

9:42 shtutgart`: chouser: right, but I can't remember any problems with functions (don't know why, maybe functions usually have more unique names (e.g. in my example i had var named files))

9:42 lnostdal-laptop: agree

9:42 lnostdal-laptop: a-function -a-global- *a-dynamic-global* less chance of clashes there than in the a-function and a-global case

9:43 shtutgart`: but @-an-atom- is not so good; maybe @an-atom- or smth like?

9:43 chouser: shtutgart`: I actually am more likely to have problems with functions, wanting to name locals things like str, map, vec, list...

9:45 shtutgart`: chouser: but there is naming conventions for such stuff (like s, m, v, lst, etc)

9:48 although, even clojure.core doesn't follow this style regularly; e.g., assoc takes map, key and val, when update-in takes m and k

9:50 pdk: stick the- in front of everything

9:50 problem solved!

9:54 shtutgart`: indeed it's a good idea

9:55 chouser: shtutgart`: hm, I suppose that is a naming convention.

9:59 shtutgart`: chouser: never seen the-globals style in someone's code

9:59 chouser: sorry, I was away. I meant those single-letter locals are a naming convention

10:01 shtutgart`: That's exactly what I mean

10:01 chouser: yes, I was agreeing

10:03 shtutgart`: ah, ok :) my english is not very good, I don't always understand what people mean

10:13 jweiss_: can someone recommend a way to take a zipper where the current loc is some arbitrary place in the tree, and return one whose loc is the root? (can either rebuild a new zipper with the root node, or repeatedly call up until you hit the root)

10:14 i'm not sure which one is more expensive

10:14 they both seem pretty inefficient actually

10:36 whidden: Are there any issues/contexts with using send?

10:37 The reason I ask is that I'm getting a ThreadPoolExecutor$AbortPolicy.rejectedExecution exception.

10:41 jweiss_: i get the feeling i'm using zippers wrong, i keep wanting the node, but without the children - but i get the entire tree and end up with much larger data structures than i really need

10:42 gfrlog: there isn't any jsonp middleware for ring is there?

10:42 whidden: The stacktrace I'm getting is here: git://gist.github.com/1078109.git

10:43 hmmm better link is; https://gist.github.com/1078109

10:46 cemerick: It's ironic that the ML thread discussing my survey results post, which talks about the ML going off the rails, has gone off the rails.

10:47 paraseba: What are the plans for c.c.swing-utils? is going to be converted to its own project? is there any successors I'm not aware of?

10:50 shtutgart`: paraseba: seesaw?

10:52 ejackson: cemerick: humans - as if entropy alone weren't enough to ensure chaos.

10:54 paraseba: shtutgart`: it seems a lot bigger

10:54 shtutgart`: it is

10:55 mprentice: do you guys know of a function that works like clojure.xml/emit but will safely escape attribute values and string contents?

10:59 jweiss_: i've been doing quite a bit of xml tree walking lately. you need help?

11:05 sritchie: hey all -- does anyone have an example of how to use gen-class to define a nested class?

11:08 jweiss_: mprentice: yeah, i guess what i'm missing is a way to get the node minus the children

11:09 mprentice: jweiss_: so just the tag name and the attributes?

11:09 jweiss_: mprentice: it's not an xml zipper, just a generic one

11:10 but yeah, that's the xml equivalent

11:11 mprentice: jweiss_: you can filter by (complement branch?)

11:12 that should get you all the children of the current node that are leaf nodes

11:12 jweiss_: mprentice: no, because in my zipper, all the nodes are branches

11:12 which is why i'm starting to think i may be doing it wrong

11:13 should a branch just have children and no other info of its own?

11:14 mprentice: jweiss_: not necessarily. but you do need to know the structure if it has other info. do you have an example?

11:16 jweiss_: mprentice, my structure is like this - a map where one of the keys is a list of children: {:name blah :description "hi there" :children [{:name "child1"} {:name "child2" ]}

11:17 i suppose i could just dissoc :children

11:17 but i thought there was some build-in zipper way to do this

11:21 gtrak`: so, say I have a clojure ring web-app, and I'm required to integrate a security framework to enable x509 and PKI, what's the least evil approach? I'm considering spring security but this would require deployment within a servlet container

11:30 mprentice: jweiss_: dissoc children sounds like the way

12:06 paraseba: seancorfield: Sean, I just added a new patch for JDBC-11. The patch is working for me, and I thing it's a pretty urgent issue

12:19 jfkw: Just attempted an install on Ubuntu Server 11.04 of clojure dependencies for use with Leiningen. I am finding it diffucult to pull in a jre/jdk without X on that system. Any suggestions or URL?

12:20 semperos: jfkw: you mean you're trying to use apt-get or aptitude to install a JDK?

12:23 if you want to use a JDK available within the Ubuntu repo's, you can do a "sudo aptitude search jdk" to see a list of available ones, then install the one you want

12:24 if you want to install the Sun/Oracle one, you can download the self-extracting installer here http://download.oracle.com/otn-pub/java/jdk/6u26-b03/jdk-6u26-linux-i586.bin

12:25 this post, though old, provides instructions for installing Java using the installer: http://dhruba.name/2009/07/13/installing-java-scala-and-vim-support-on-linux/

12:26 jfkw: didn't see you dropped off

12:26 if you want to install the Sun/Oracle one, you can

12:26 download the self-extracting installer here

12:26 http://download.oracle.com/otn-pub/java/jdk/6u26-b03/jdk-6u26-linux-i586.bin

12:27 this post, though old, provides instructions for

12:27 installing Java using the installer:

12:27 http://dhruba.name/2009/07/13/installing-java-scala-and-vim-support-on-linux/

12:27 cky: You can also add the "partner" repository in Ubuntu and add the sun-java6-jdk package.

12:28 jfkw: semperos: and cky thanks, will check these out.

12:28 technomancy: maybe openjdk-6-jre-headless ?

12:29 cky: jfkw: Oops, I missed seeing your "no X dependency" part. Please disregard my comment.

12:29 jfkw: technomancy's comment is better.

12:29 amalloy: jweiss_: isn't zip/root the way to get back to the root? you asked about that earlier

12:30 and Chousuke, shtutgart`: (comp doall map) is going to be more efficient than (comp vec map), since apparently he cares about efficiency

12:31 jfkw: techomancy: thanks openjdk-6-jre-headless will work well. I didn't realize it initially, but maven2 package is the one pulling in all of X probably through its own dependencies.

12:32 Is it the right presumption that a system packaged maven2 commonly used? Or do I build a non-system maven{2,3} under my home directory?

12:43 technomancy: jfkw: yeah, maven2 has a huge pile of unneeded deps... by default it will pull in gcj, groovy, and rhino (!)

12:44 I wouldn't bother building your own unless you want new features that aren't in apt yet

12:44 gtrak`: jfkw, you can download the maven binaries too

13:00 clgv: &(map (fn [_] (map rand (range 5))) (range 5))

13:00 sexpbot: ⟹ ((0.0 0.8441228844049946 0.7772274956553189 0.7283555804898323 2.0675454024470383) (0.0 0.04178595345506553 0.192762651873303 2.786763908112922 0.8947957998984526) (0.0 0.6043441057133377 0.2693049014431528 1.1875086636781094 0.2383735279084469) (0.0 0.8743459153161... http://gist.github.com/1078419

13:01 clgv: why is the first entry always zero (0.0)?

13:02 kumarshantanu: jfkw: are you trying to run Java as a daemon?

13:02 clgv: I guess I have to use repeatedly. but the behavior with map is odd, anyway

13:04 cemerick: clgv: because ##(rand 0) is always 0

13:04 sexpbot: ⟹ 0.0

13:04 zerokarmaleft: hiredman: is conduit able to connect with a password?

13:04 clgv: cemerick: lol right.^^

13:07 khebbie: My first clojure code https://github.com/khebbie/PET - any comments?

13:08 Gamli: Hi all - I am new here in this IRC-channel and I have a question about the arguments of a "deftype".

13:08 Is it right that the arguments MUST NOT have hyphens since they are compiled as java classes?

13:08 e.g. is it wrong if I declare a type as this:

13:08 (deftype Cow [cows-phrase])

13:08 ?

13:08 ups - sorry about the 5 lines

13:08 joegallo: khebbie: (defn foo "docstring goes here" [] (do-some-stuff))

13:08 amalloy: Gamli: hyphens are fine

13:08 clgv: nope. it is legal to use hyphens.

13:08 joegallo: that got me for a long time too

13:09 amalloy: it gets turned into cows_phrase

13:09 you can put ! and ? in there too - they get munged the same way functions=>classnames do

13:09 khebbie: joegallo: You say i should adddocstrings?

13:09 Gamli: amalloy: but if i use it it always says that the field is not defined when it is an REPL-output

13:09 joegallo: dc-create, db-insert and db-query-for-today have something that i think is probably intended to be a docstring, but instead is just a string in the body of the function

13:10 amalloy: khebbie: you have (some of) the docstrings in the wrong place

13:10 joegallo: exactly

13:10 amalloy: Gamli: you'

13:10 jfkw: technomancy: gtrac kumarshantanum, I'm trying to configure a colleague's ubuntu laptop to experiment with clojure, and a spare ubuntu server to figure out the no-X dependency chain, which looks pretty grim once I pull in maven. I would definitely undertake building maven from source/bin to avoid the X dependencies.

13:10 khebbie: Ok

13:10 amalloy: re probably using deftype wrong. do you want a type or a record?

13:10 khebbie: amalloy: Where

13:11 amalloy: everywhere that joegallo just said :P

13:11 khebbie: Ok

13:11 technomancy: jfkw: bummer; doesn't sound like fun. is it really worth all that hassle to avoid X?

13:11 or is it a matter of principle at this point? =)

13:11 joegallo: khebbie: minor complaint -- closing parens should not be on their own line (some people disagree with that)

13:12 technomancy: joegallo: some people are wrong

13:12 amalloy: people who disagree are loons

13:12 joegallo: hehehehe

13:12 khebbie: amalloy: Ok, im a c# guy so i kinda use them as }

13:13 amalloy: in his case though i can kinda see the point: to clarify that each if has no else branch. which leads me to....use when instead of if, granted that you want no else

13:13 jfkw: technomancy: both ;) If we use clojure, it would be deployed on dozens of servers, so avoiding the X dependency is essential IMHO to keep server management under control. I know it's going to be less than fun.

13:13 technomancy: jfkw: deployment != dev environment

13:13 no reason to put mvn on your servers; all you need is a jre

13:13 jfkw: technomancy: Good point, deploy jars only.

13:13 khebbie: amalloy: Whats the diff between if and when?

13:14 technomancy: (or maybe a JDK if you want to run the CDT debugger server-side)

13:14 amalloy: &(doc when)

13:14 sexpbot: ⟹ "Macro ([test & body]); Evaluates test. If logical true, evaluates body in an implicit do."

13:14 joegallo: khebbie: matter of style, but you can do this (Class/forName "whatever")

13:14 khebbie: amalloy: Aha

13:15 Ok, well got something to work on then

13:15 Thx all

13:15 amalloy: khebbie: thinking of ) as } is a handicap to understanding. in C# (for example), "if" is a statement, while "+" is part of an expression. clojure has only expressions, so having *some* of your constructs get "special" ending-) and not all of them is confusing

13:15 khebbie: amalloy: Ok

13:17 Gamli: amalloy: this is somehow strange. it is all ok as long as i just use the types in code. but as soon as the REPL should print the result (I'm using CCW for eclipse) i gat the "No matching field found" exception

13:17 * amalloy doesn't debug when there's no code or stacktraces :P

13:17 joegallo: khebbie: you might not need that Class/forName call at all, it looks like c.c.sql handles it for you https://github.com/clojure/clojure-contrib/blob/b8d2743d3a89e13fc9deb2844ca2167b34aaa9b6/src/main/clojure/clojure/contrib/sql/internal.clj#L84

13:18 Gamli: amalloy: was that for me? (the code/stacktrace comment)

13:18 amalloy: indeed

13:18 khebbie: joegallo: Ok

13:19 clgv: Gamli: post your code at pastebin.com or something ;)

13:19 Gamli: ok - i'll put together a small example

13:21 joegallo: khebbie: you can combine those (:require) forms in your ns

13:21 fyi -- almost everything i've said has been just nitpicking, overall the code looks pretty good

13:22 might want to look at sql/insert-values

13:23 Gamli: amalloy: hope it is ok to post code here

13:23 (deftype Cow [cows-phrase])

13:23 (defn run [] (Cow. "Moo I'm a Coo"))

13:23 if i call "run" it throws the exception

13:23 args - again sorry for the 4 line *G*

13:23 khebbie: joegallo: Yeah have been thinking bout insert-values

13:24 amalloy: it's probably complaining that it doesn't know how to print your bare type

13:24 if you used defrecord (as i suggested), that comes with a lot of built-in features

13:24 Gamli: but it works if i replace the hyphen with an underscore

13:24 khebbie: joegallo: Hoping to work on it a bit more and build up queries in code

13:25 amalloy: that's pretty weird

13:25 Gamli: yeah - thats what I thought

13:25 I mean - I could just replace the hyphens but... you know

13:26 amalloy: what clojure version?

13:26 cemerick: amalloy: it's a bug in core_print.clj; the print-method handler for types isn't munging field names.

13:26 Gamli: by the way - I'm using 1.2.0-alpha8

13:27 amalloy: Gamli: i don't think 1.2.0 ever had eight alphas. maybe you mean 1.3>'

13:27 Gamli: cemerick: ah ok - so I just HAVE TO replace the field-names?

13:27 cemerick: core_print.clj, line 246; throw in (namespace-munge fld) instead of just fld, and it works as it should

13:27 Gamli: amalloy: sorry, 1.3.0-alpha8

13:27 cemerick: Gamli: At the moment; it's a bug, but only related to printing of the types. You almost certainly want to be using defrecord to start with though, as amalloy suggested.

13:27 Gamli: cemerick: ok - I'll try that

13:28 cemerick: Gamli: in general, see: http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

13:28 unlogic: Anyone uses emacs-clojure-vagrant?

13:29 Gamli: amalloy, cemerick: ok, I'll try both (changing the code and using defrecord). thx in advance :)

13:31 amalloy: cemerick: it's a new-in-1.3 problem? i don't see it on 1.2.1

13:31 Gamli: amalloy: yeah a colleague said the same a minute ago to me :)

13:32 cemerick: amalloy: yeah; 1.2.x didn't have readable types/records

13:32 amalloy: oh, it's for the #user.Test[4] notation

13:33 i thought that was just for print-dup, not for repl printing

13:33 dnolen: unlogic: I tried it, interesting but it's a pretty incredibly long install process.

13:33 unlogic: dnolen: well, I managed to go through that process but I kind of got no idea what to do next

13:34 dnolen: unlogic: what OS are you using?

13:34 unlogic: I logged to virtual machine via "vagrant ssh", but there is only lone unconfigured emacs

13:34 I use ubuntu

13:35 dnolen: unlogic: yes, so ran into this as well. for some reason the .sh in the repo doesn't get run. I copied it into the VM, chmod u+x and ran it and then I had a working setup.

13:35 cemerick: bah, the compiler needs tweaks too

13:36 unlogic: dnolen: Oh, yeah, how do you copy files into the virtual machine? "vagrant scp" doesn't work for me)

13:36 dnolen: unlogic: copy and paste :)

13:36 technomancy: unlogic: the directory containing the Vagrantfile is mounted as /vagrant on the VM

13:36 so if there were problems running the provisioning script, you can cd /vagrant && sudo clojure_emacs.sh

13:37 unlogic: technomancy: Ah, I get it now:) Thanks

13:41 Gamli: amalloy, cemerick: I just tried out the 1.3.0-beta1 and it doesn't work either. so I'll go with your ideas (really this time)

13:41 cemerick: no one trusts poor ol' cemerick :-P

13:42 unlogic: technomancy: OK, script has finished now. I see jark and lein have beein installedm, but emacs still looks virgin

13:42 Gamli: cemerick: did you state something about the beta1? if so, im sorry that i read over it ;)

13:43 amalloy: cemerick: i doubt your previous statement

13:44 whidden: If I assoc a new key-val pair to a defrecord the type of the resulting value is still the original defrecord. Is this expected?

13:44 cemerick: amalloy: I'm being cheeky. :-)

13:44 amalloy: cemerick: me too! observe how i was mistrusting you

13:44 whidden: yes

13:44 cemerick: ah, crap. I've been irc punk'd.

13:45 amalloy: i will frame this chat log and place it on my wall

13:45 whidden: amalloy: fizzlesticks, guess i need another hat.

13:45 unlogic: I still don't quite get it: should I use this vagrant vm just to run swank and connect to it from emacs on my host OS? Or is it designed to hack everything inside?

13:45 amalloy: ...hat?

13:46 technomancy: unlogic: the idea is it's self-contained

13:46 unlogic: M-x package-updates will pull in the packages once you're inside emacs if the provisioning script didnt get them

13:49 cemerick: Gamli, amalloy: the ticket to watch for the deftype field name issue, if you're so inclined: http://dev.clojure.org/jira/browse/CLJ-819

13:50 whidden: Why would one want to use a 'defrecord' over a hash map?

13:50 unlogic: techmonancy: Thanks a lot, finally got it working.

13:50 amalloy: whidden: good question. too many people use defrecord just because it feels OO

13:50 see, eg, http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

13:51 Gamli: cemerick: thx - nice to see somone care about such stuff. its a real pain in the ass during development if you don't know where the error comes from :)

13:51 whidden: amalloy: ooh its been updated.... :) thanks

13:52 cemerick: Gamli: We generally try to man the counter decently around here. :-)

13:52 mprentice: hmm is there a clojars or maven repository for GATE (gate.ac.uk)?

13:53 cemerick: whidden: I put the first version of it together when I was in a particularly interop state of mind.

13:54 technomancy: mprentice: $ lein search gate 2 # => [uk.ac.gate/gate-core "6.0"] among others

13:54 amalloy: cemerick: i can't think of a case when you need methods not specified by interfaces

13:54 whidden: so the question i have is what is performance sensitive?

13:54 amalloy: but i assume such cases exist: have an example handy?

13:54 Gamli: amalloy: there are such cases

13:54 amalloy: whidden: code whose performance you, personally, care about

13:55 whidden: amalloy: I care about all my code ;)

13:55 amalloy: then stop it :P

13:55 Gamli: amalloy: trying to put together some example

13:55 cemerick: amalloy: Client defines the API, or a library requires particular method names and signatures without providing an interface. You want to write the thing in Clojure. Thus, additional methods, and gen-class.

13:56 amalloy: oh, sure

13:56 Gamli: amalloy: here is the example -> what cemerick said ^^

13:56 amalloy: haha

13:57 cemerick: whidden: an example of "performance sensitive" is accessing slots in a hot loop. Maps will kill you, defrecords with :keyname accessors will get close to Java perf, and .field access *will* be Java perf.

13:58 amalloy: cemerick: hah, my comment is awaiting moderation

13:59 mprentice: technomancy: ah, thanks! i don't have something setup right, i get maven error from lein plugin install lein-search 1.0.0-SNAPSHOT

13:59 cemerick: amalloy: where? on my blog?

13:59 amalloy: yeah, i posted it just now

13:59 technomancy: mprentice: it's built-in to lein 1.6.1

13:59 mprentice: mmmk, i'm on 1.5.2. i'll try upgrading.

13:59 cemerick: amalloy: first time commenters are put in moderation. You'll go straight through next time.

14:00 unlogic: technomancy: and the last question, sorry for wasting your time. is there a chance to run X application inside vagrant, or this OS image is terminal-only?

14:00 amalloy: technomancy: i seem to have gotten a "development/hacking" version of lein, which refuses to upgrade itself. what do i need to do to get a stable one?

14:00 technomancy: amalloy: want to try my .debs?

14:01 amalloy: hey, if you need testers, sure

14:01 if it breaks, i still have cake :P

14:01 technomancy: git fetch && git checkout 1.6.1 will upgrade your checkout though.

14:01 lemme see

14:01 amalloy: technomancy: but i don't have a git checkout anywhere i can find, is my problem

14:01 whidden: cemerick: crap... I think I've painted myself into a corner. Time to use another color.

14:02 amalloy: i did a lein self-install, i'm pretty sure

14:02 technomancy: oh, you did a wget of bin/lein from master; I see

14:02 amalloy: yeah, probly

14:02 technomancy: lemme know if these work for you: http://p.hagelb.org/lein-debs.tar

14:02 lightly-tested

14:03 else just rm it and wget from the stable branch

14:03 amalloy: technomancy: to delete the existing version, just kill ~/bin/lein?

14:03 technomancy: right

14:04 I've tested it on sid, but as long as you install the other debs in the tarball you should be fine on any relatively-recent apt system

14:05 amalloy: technomancy: ugh. it wants me to install clojure 1.2 system-wide? i've been brainwashed too well to tolerate that

14:05 technomancy: oh bugger, yeah that's not going to work outside debian unstable/testing

14:05 forgot about that part

14:06 amalloy: as long as you consider it a user-level application, putting jars in /usr/share/java is just fine

14:06 amalloy: technomancy: have you considered setting "stable" to the default branch for lein? might prevent more mistakes like mine

14:07 technomancy: "default branch"?

14:07 amalloy: the one that people see when they browse the repo

14:07 clojurebot: max people is 317

14:07 amalloy: and also gets checked out by default in clones

14:07 (not really nice to have the two of those conflated together)

14:07 technomancy: yeah, definitely don't want it for clones

14:07 the readme on the master branch links to the stable branch; I think that's good enough

14:08 scgilardi: well, easy enough to git checkout master after cloning

14:08 amalloy: yeah, probably

14:11 jcromartie: Is there a good solution for cross-thread var-binding/earmuffs? I really like the idea of something like CL's special vars... but once you throw a thread in the mix you can't use them that way.

14:11 amalloy: jcromartie: that changes in 1.3, i'm told

14:11 jcromartie: I mean maybe some kind of careful application of macros could do it?

14:11 or what

14:12 amalloy: doesn't seem worth the pain

14:12 jcromartie: I am thinking of things like web apps with *session* or *user* or *client* and things like that

14:13 I think Sandbar does something like that?

14:13 technomancy: (doc bound-fn)

14:13 clojurebot: "([& fntail]); Returns a function defined by the given fntail, which will install the same bindings in effect as in the thread at the time bound-fn was called. This may be used to define a helper function which runs on a different thread, but needs the same bindings in place."

14:13 hiredman: those don't seem like thread locals, so why would you use threadlocal bindings for them?

14:14 jcromartie: I guess I am just wishing for CL's special vars

14:15 but guess anything that might be used that way would probably not play well cross-thread anyway

14:15 like *in* or *out

14:15 *

14:17 whidden: technomancy: If I use lein swank to run/debug my code i get thread-pool exceptions, this also happens if I use lein run, but not if I use lein repl, using latest lein of course. Any ideas whe?

14:17 *why?

14:18 technomancy: whidden: I don't know. it works fine for me, but others have reported the same behaviour you're seeing.

14:18 I don't have enough data to reproduce the problem.

14:18 clojurebot: agent thread pool

14:18 clojurebot: the agent thread pool is kind of a problem in Clojure, see http://tech.puredanger.com/2010/06/08/clojure-agent-thread-pools/ and http://p.hagelb.org/shutdown-agents.jpg

14:18 technomancy: ^ is the root cause of the problem

14:19 amalloy: technomancy: i don't get it, though. surely you're never calling shutdown-agents in lein?

14:19 mdeboard: whidden: I had the same problem last night sir.

14:19 technomancy: amalloy: I have to

14:19 scgilardi: jcromartie: for things that are (truly) jvm-wide you can use a var in a namespace bound to an atom and set its value with swap! or reset! when it should change.

14:19 mdeboard: whidden: On a different project

14:19 technomancy: otherwise the process will never exit

14:20 amalloy: this is after all the in-project code has finished, of course.

14:20 mdeboard: lol @ scumbag agents

14:20 whidden: <sigh>

14:20 technomancy: amalloy: but it only shuts down after the in-project code is "done" running

14:20 amalloy: makes sense, i guess

14:20 whidden: makes debugging a bit of a pain.

14:20 technomancy: in-project code needs to block on the main thread if it wants to keep running, otherwise there's no way to work around this Clojure bug

14:21 whidden: technomancy: hmm i guess I can do that.

14:21 amalloy: technomancy: or start up some other non-daemon thread

14:21 technomancy: amalloy: that will keep it alive, but if it doesn't block then shutdown-agents will still run

14:22 and there's bloody no mechanism for restarting the agent thread pool. grrrrrr

14:22 amalloy: interesting

14:22 technomancy: it really does suck

14:22 mdeboard: surprising too

14:22 technomancy: surprising it's gone this long without being addressed

14:22 amalloy: i was trying to imagine some mechanism for this when i was reading your ML thread, but didn't come up with any clever ideas

14:22 technomancy: it's Google Code issue 120, which tells you something about how long it's been ignored.

14:23 amalloy: except one that doesn't work because it involves making threads change daemon/non-daemon status

14:26 mdeboard: whidden: By any chance, are you running in a VM? Virtualbox, vagrant, etc.?

14:26 hiredman: clojurebot: scope?

14:26 clojurebot: scope is at http://paste.lisp.org/display/73838

14:26 whidden: mdeboard: no... i'm doing a lot of dbus interactions through a java proxy :(

14:27 technomancy: whidden: you can block in your -main by using @(promise)

14:27 whidden: swank already does that though, so no idea why it's still falling through to shutdown-agents

14:28 whidden: technomancy: I tried that and it still fails in the same place.

14:35 mdeboard: technomancy: fwiw I can reproduce the problem 100% of the time. Is there any reports or other data I can generate and put... somewhere to help diagnose?

14:35 Are there any*

14:36 My error case was that I'd forked uh

14:37 4clojure.com to try my hand at implementing some UI tweaks I'd been whining about, I started up mongo and `lein run`, which both responded just fine. But when I tried to connect via the browser it threw the thread exceptions

14:37 technomancy: mdeboard: maybe add a println to the point right before shutdown-agents is called in leiningen.compile/get-readable-form

14:38 mdeboard: technomancy: Will do, once I get home

14:39 technomancy: could also add one to swank.swank/start-server after the .join doseq

14:39 maybe get-thread-list isn't finding your thread for whatever reason

14:56 jcromartie: Hey, #clojure, thanks for not being jerks.

14:57 (after spending time in some *ahem* less civilized language/framework channels)

15:06 Munksgaard: ihkhgkjgkugui

15:06 i am horny

15:10 paraseba: why is reduce implemented in terms of next instead of rest? Is it a performance optimization?

15:11 next is "less lazy" than rest, since it needs to check if there are more elements remaining. Of course, reduce doesn't need to exploit the full lazyness, since is going to traverse all the seq

15:11 amalloy: paraseba: it's going to be calling seq anyway, so there's no point using rest-then-seq

15:13 paraseba: I had some buggy code, that worked with 1.2.1 but not with 1.3.0. It somehow depended on reduce getting only one element at a time

15:13 I was curious about where that behavior changed, but I can't find it

15:14 amalloy: that sounds like a pretty hard bug to introduce

15:15 paraseba: amalloy: I was generating a lazy seq of "user actions", and then using reduce to process the seq as it happens

15:15 now with 1.3.0 I need two events for the first call to the reducing function

15:16 because, of course, next needs to process 2 events. But I can't understand why it was working with 1.2.1

15:16 amalloy: huh? why does it need to process two events?

15:17 this doesn't sound at all related to rest/next

15:18 dans: i'm having trouble installing clojure-contrib, i get the error: Unable to find resource 'org.clojure:clojure:pom:1.2.0-master-SNAPSHOT' in repository clojure-snapshots (http://build.clojure.org/snapshots)

15:18 can anyone help me on this?

15:18 technomancy: dans: switch to version 1.2.0

15:18 no sense in using a snapshot

15:18 dans: i've just pulled the master branch from the git, so i have to specify the version?

15:18 amalloy: might as well be 1.2.1 by now

15:18 paraseba: amalloy: because reduce does something like (recur (next s) f (first s)). So, first wont return until we have the first event, and next wont return until we have the second

15:18 technomancy: dans: the master branch of what?

15:19 dans: this is the procedure i've followed http://riddell.us/ClojureOnUbuntu.html

15:19 technomancy: =(

15:19 amalloy: blog posts get out of date very quickly

15:19 dans: git clone git://github.com/richhickey/clojure-contrib.git

15:19 technomancy: clojurebot: getting started?

15:19 clojurebot: getting started is http://www.assembla.com/wiki/show/clojure/Getting_Started

15:19 technomancy: dans: try that instead

15:19 dans: alright, cheers

15:20 technomancy: many a prospective user has been befuddled by those dang riddell.us pages

15:20 cemerick: it still references github.com/richhickey — can't be too recent

15:20 technomancy: clojurebot: riddell.us is a great source of outdated, unnecessarily-complicated, and confusing instructions.

15:20 clojurebot: In Ordnung

15:22 scgilardi: I'm not sure there is a 1.2.1 build of contrib. I've been using 1.2.1 of clojure with 1.2.0 of contrib.

15:22 paraseba: amalloy: if reduce used rest instead, that could return before the second event. I think...

15:23 zakwilson: It just came to mind that ClojureQL makes it very easy to ask for things that don't make any sense whatsoever, like a join between two different databases.

15:24 amalloy: scgilardi: there isn't, but he was having trouble resolving clojure, not contrib

15:24 paraseba: yes, i suppose it could. interesting

15:25 scgilardi: amalloy: gotchya, thanks.

15:25 dans: Clojure is unlike most language in that you don't generally install Clojure itself ?

15:26 paraseba: amalloy: I'm using reduce for something it's not intended, processing a seq as it gets produced. But, I can't find why it works before 1.3.0

15:26 amalloy: paraseba: but if you really don't care about more than one element at a time, you should use doseq or dorun/map

15:26 cemerick: dans: Generally, no. Clojure is "just" a Java library.

15:27 paraseba: amalloy: yes, but I'd be implementing reduce, exactly reduce, just that using doseq.

15:28 amalloy: It's a swing app, all state is passed through events with this reduce

15:28 reduce seemed like the perfect choice for this

15:29 each even "handler" receives the previous state of the application, and produces a new state. Each element in the collection is a user "action"

15:29 but ... it's broken ... reduce won't work ... it needs 2 events to start processing

15:29 schauerlich: can you start off reduce with a null action?

15:30 paraseba: schauerlich: I could, I guess...

15:31 and what's driving me crazy is, that it shouldn't work on 1.2.1, but it does. Can't find out why

15:31 1.2.1 also uses next in reduce

15:31 maybe some change in lazy-seq ... but can't find it

15:33 hiredman: paraseba: I would definitely bring that up on the mailing list, seems like a big change in behavior

15:33 babilen: dans: I would recommend to use leiningen -- there will even be Debian/Ubuntu packages soonish and it will make ease your life tremendously.

15:34 paraseba: hiredman: good idea, I'll "reduce" this to a simple example that shows the behavior change

15:37 dans: babilen: yes, im looking at that now (just got clojure running)

15:37 planning on trying out noir

15:40 babilen: dans: That way you can just run "lein new ; lein repl

15:40 dans: It also works well with vimclojure and/or swank if you use vim or emacs.

15:51 dans: yes babilen, im using vimclojure :)

15:54 danbell: clojurebot riddell.us

15:55 clojurebot: riddell.us?

15:55 clojurebot: riddell.us is a great source of outdated, unnecessarily-complicated, and confusing instructions.

15:55 babilen: dans: You might be interested in https://github.com/autre/lein-vimclojure in that case

15:56 dans: thanks

16:07 jcromartie: yay for point-free style: (def name-sort (partial sort-by (comp last words)))

16:22 mdeboard: jcromartie: point-free?

16:25 amalloy: mdeboard: (defn add-one [x] (+ 1 x)) has one "point", x. roughly, a named variable

16:25 (def add-one (partial + 1)) achieves the same thing with no points

16:25 mdeboard: ahh ok

16:25 markskilbeck: Is point-free better?

16:25 amalloy: meh

16:26 Scriptor: it's a haskell/(ML?) thing

16:26 amalloy: $google haskell point-free evolution

16:26 sexpbot: First out of 20300 results is: The Evolution of a Haskell Programmer

16:26 http://www.willamette.edu/~fruehr/haskell/evolution.html

16:26 technomancy: I switched away from point-free when I realized I wasn't making high scores any more.

16:26 markskilbeck: Danke.

16:26 Scriptor: basically all code is viewed as a graph, with edges being functions and actual variables being being nodes

16:26 mdeboard: I dunno point-free doesn't seem like consistent syntax

16:26 Scriptor: nodes = points

16:26 dans: im trying to install leinigen, i have lein.sh chmodded and in my path, but im getting command not found

16:27 mdeboard: Can't you do like (+ 1 %) or something

16:27 Scriptor: mdeboard: yea, it's way easier in haskell

16:27 mdeboard: I read it last night but have forgotten :(

16:27 Scriptor: addone = (+ 1)

16:27 technomancy: dans: forget to chmod?

16:27 khebbie: I am using clojure.contrib.sql's with-query-results

16:27 dans: no technomancy

16:27 markskilbeck: If it's 'lein.sh' you'll have to call 'lein.sh', not 'lein', right?

16:27 dans: chmod a+x lein.sh

16:28 technomancy: then it must not be on your path

16:28 markskilbeck: Nvm.

16:28 khebbie: Now in the function where i use it i have to parse the resultset

16:28 Is it possible to return the sequence, and parse in an outer scope

16:28 technomancy: markskilbeck: naturally

16:35 jcromartie: of course point-free can just be code golf

16:35 it doesn't really help anybody to have a file full of defs with no arglists, ets.

16:35 (dec usability)

16:35 sexpbot: ⟹ -1

16:36 amalloy: technomancy: "naturally" except to a windows user

16:37 technomancy: sure, I don't pretend to understand how windows users think.

16:38 mdeboard: lol

16:41 amalloy: (inc technomancy)

16:41 sexpbot: ⟹ 12

16:49 jweiss_: anyone familiar with this class of problem. i'm using a tracing fn i wrote (based on clojure.contrib.trace but uses robert.hooke), but if i enable it in a function, tracing never happens, the hooks are not added. If i run the same sexp in the repl, the hooks get added and tracing works.

16:50 something strange about the repl or swank dealing with vars?

16:59 huh, a doall on the outer for doesn't force the inner for

16:59 that is... odd

16:59 amalloy: that is not at all odd :P

17:00 jweiss_: not sure how the 2nd item in the outer for gets consumed when the inner loop doesn't run

17:00 well it's odd when you're not totally used to thinking lazily

17:00 amalloy: you built a lazy-seq of lazy-seqs

17:01 incidentally, if you think the second item in the outer for depends on the first item of an inner for, you probably don't want to have multiple for's at all

17:01 paste a snippet of some kind?

17:01 jweiss_: amalloy: right, i get it now. just not the kind of thing you'd expect from a non lazy nested loop

17:02 note to self. whenever the repl works and code inexplicably doesn't, THIS IS WHY

17:02 i'm wondering if having the repl implicitly force evaluation is worth it :)

17:02 amalloy: eg, the difference between ##(for [x (range 3)] (for [y (range 3)] [x y])) and ##(for [x (range 3) y (range 3)] [x y])

17:02 sexpbot: (for [x (range 3)] (for [y (range 3)] [x... ⟹ (([0 0] [0 1] [0 2]) ([1 0] [1 1] [1 2]) ([2 0] [2 1] [2 2]))

17:02 (for [x (range 3) y (range 3)] [x y]) ⟹ ([0 0] [0 1] [0 2] [1 0] [1 1] [1 2] [2 0] [2 1] [2 2])

17:03 jweiss_: amalloy: the outer for has a side effect that needs doing before each inner

17:04 amalloy: whoa. it seems unlikely that for will ever really do what you want

17:04 jweiss_: i suppose i could have used doseq

17:05 since enabling trace is side-effecty

17:14 jao: hi. what's the idiomatic way of adding a new key/value to a map only if the key is not already there (i.e., (if (:key m) m (assoc m :key val))?

17:17 Derander: jao: I don't know if this is the idiomatic way to do it, but I tend to do: (merge {:mykey myvalue} some-other-map)

17:18 jao: Derander, looks good enough. Thanks.

17:19 Derander: jao: any time

17:23 ibdknox: I'm looking for any feedback people might have on Noir as I'm thinking of release 1.1.0 soon

17:37 danbell: ibdknox: dang, still haven't tried it out

17:37 ibdknox: danbell: get on it ;)

17:37 haha

17:38 danbell: ha, yeah

17:38 i think everyone who uses clojure for web stuff has a half-featured version of noir

17:38 ibdknox: I suspect so

17:38 lol

17:39 hiredman: clojurebot: ssa is http://wingolog.org/archives/2011/07/12/static-single-assignment-for-functional-programmers

17:39 clojurebot: 'Sea, mhuise.

17:42 ibdknox: it seems like all the "new" languages are getting bought by companies as of late, you guys think Clojure will get grabbed up?

17:45 amalloy: ibdknox: what does noir "do"? the readme is just like "it's a framework"

17:45 ibdknox: amalloy: essentially it's a series of convenience methods over compojure/hiccup

17:45 what it does at a fundamental level is provide a single point for you to start building a website

17:45 technomancy: ibdknox: more than just relevance you mean?

17:46 ibdknox: technomancy: I think so, though I don't know the details of that relationship?

17:47 dnolen: ibdknox: what else has really been "bought up" recently?

17:47 kwertii: Whoa. Noir is awesome. I am one of those people who had half of Noir built manually on top of Ring in every site I made.

17:47 ibdknox: amalloy: basically instead of trying to figure out how to do cookies or stateful sessions by cobbling bits together, it has a very simple API that brings all those little pieces together

17:48 dnolen: ruby was essentially just acquired by heroku

17:48 dnolen: joyent grabbed node.js (whose logo is truly awful now)

17:48 amalloy: whuuuuut, ruby bought by heroku? that sounds like complete nonsense, but i'm not at all ruby-aware

17:49 ibdknox: amalloy: they just got matz

17:49 kwertii: amalloy: they hired matz and several core guys. Heroku being a part of Salesforce.com.

17:49 dnolen: ibdknox: Matz isn't leaving his other posts. and node.js isn't really a language tho right? It's a I/O programming framework.

17:49 ibdknox: amalloy: if you have the architect, you essentially have the language

17:49 Scriptor_: Eh

17:49 ibdknox: dnolen: fair, it's a platform I would argue

17:49 kwertii: Heroku supports Clojure now. Maybe they'll hire Rich Hickey, too

17:49 they certainly seem to have more cash than they know what to do with

17:50 Scriptor_: If matz disagrees with them he wouldbt have a problem getting a job :)

17:50 ibdknox: salesforce is doing extremely well currently

17:50 Scriptor_: I didn't mean it as a bad thing or that they would "control" it per se

17:50 kwertii: seems to be. Heroku cost them $212 _million_. Heroku is cool and all, but ....

17:50 dnolen: kwertii: ibdknox: also rhickey seems like a fairly independent fellow.

17:51 kwertii: dnolen: they'd drive a dumptruck full of money up to his house and say "hey, work on whatever you like, just let us put your name on our website..."

17:51 ibdknox: dnolen: agreed

17:51 dnolen: kwertii: I'm sure he would decline. rhickey seems to prefer to work on his own terms.

17:52 kwertii: dnolen: they'd let him work on his own terms. (the "work on whatever you like" part.) it's a prestige thing for them. they're not going to be telling matz how to develop ruby.

17:52 they just want a trophy for their display case

17:53 this way, they can tell investors, "by the way, we have the author of Ruby on board..."

17:53 ibdknox: lol, I'm not sure how far that would actually go with investors

17:53 also, I don't think they're looking for more money at this point ;)

17:54 kwertii: ibdknox: sadly, much farther than one would rationally expect :p

17:54 dnolen: kwertii: this all ties into a hype side of technologies which are not grounded in reality of the quality/robustness/generality of said technology.

17:54 kwertii: it generalizes to business partners generally. the sales slime at any other big company that they would care to do business with will be impressed

17:54 dnolen: yep, agree 100%.

17:55 why else would they pay matz when they can use his work for free anyway?

17:55 ibdknox: dnolen: *cough* node *cough*

17:55 kwertii: unfortunately, even we programmers need to eat

17:57 how much could they possibly be paying matz? 150k, 200k per year, tops. that's pocket change to Salesforce. well worth the price. they can impress people at power lunches all year for that fee.

17:58 ibdknox: it could easily be more than that

17:59 but yes, it's chump change in the grand scheme of things

17:59 dnolen: kwertii: question is, how does all of this actually help Ruby or the programmers that use it?

18:00 kwertii: according to Google Finance, Salesforce had annual revenue of $1.6 BILLION USD in FY 2010

18:00 dnolen: well, matz gets to sit around and think about Ruby all day, without worrying about where his next meal will come from. but he was doing that anyway.

18:01 technomancy: he'll get more opportunities to practice speaking English

18:01 ibdknox: lol

18:02 amalloy: Thanks for the correction! Any other thoughts?

18:04 kwertii: as a side note, I have been using Heroku for 7 months at work, and technically speaking, it's great. (not $212m great, but still very nice.) my only problem is that they nickel-and-dime you for every little addon, at exorbitant rates.

18:04 ibdknox: kwertii: yeah, the pricing kills, especially when you compare it to the EC2 instance that they're running on

18:04 lol

18:04 I love the workflow, but can't justify the cost

18:04 kwertii: ibdknox: yep. seems great for the low end, testing ideas out phase, but when I hit upon something that works, it's getting moved to Amazon

18:06 I imagine that 50 Heroku clones will pop up over the next year or two and drive the margins down

18:09 Google App Engine would be great if they put some ease-of-use convenience layers on top of it. It's far too baroque to set up and get running for mass adoption

18:09 but Heroku... just push a Git repo and you're up.

18:20 amalloy: ibdknox: not really. i've been enjoying learning/implementing cookies and such myself

18:21 so not really excited about noir

18:21 ibdknox: fair enough :)

18:32 kwertii: as a professional working coder, while it might be fun to mess around with writing my own cookie handler and such, I simply don't have time for that. So, for me, Noir is great.

18:32 I had got the idea to write something like it 5 times over the last year, but never got around to it.

18:39 zakwilson: Is anybody here using clj-record? I'm wondering if I want to.

18:41 kwertii: by the way, if anyone here is in the Santa Barbara, California area, we're having the first meeting of the SB Clojure Users Group at 6 PM today. All are welcome!

18:41 * gfrlog just looked at noir for the first time

18:41 digash: blist

18:47 zakwilson: clj-record seems to want each model to be its own namespace, the way ActiveRecord makes each its own class. I'm not sure this is Good. Namespaces are not classes.

18:48 Sushisource: So, maybe someone can explain a weird problem I'm having that I don't understand

18:49 I'm trying to map a function that uploads nodes to a Neo4j database and index

18:49 amalloy: nooooooo, map+side-effects=:(

18:49 Sushisource: Yeah, I figured

18:49 My clojure style needs workd

18:49 zakwilson: (doall (map ...)) works

18:50 Sushisource: YEah!

18:50 * amalloy bets a dollar that the question ends with "it works in the repl but not in some larger function"

18:50 Sushisource: See because it worked when I wrapped it in this debug macro

18:50 Which I thought was strange

18:50 gfrlog: zakwilson: wouldn't doseq be nicer?

18:50 Sushisource: Okay, so now that I get that, what's the stylistically correct way to do this?

18:50 zakwilson: Very possibly, but it's harder to turn that in to (doall (pmap ...)) when you decide you want it to be magically parallel.

18:51 Sushisource: I feel like a barely undertand transactions at all

18:51 zakwilson: Transactions have nothing to do with this.

18:51 Sushisource: Hence my feelings

18:51 Lol

18:51 zakwilson: doseq is an imperative-style thing that's a lot like map. It is probably the most idiomatic way to do side effects to everything in a sequence.

18:52 Sushisource: Okay, cool.

18:52 If one were to make such an action parallel, which luckily I don't have to do, what would be the right approach there?

18:52 gfrlog: I like indicating side effects with the word do

18:52 amalloy: zakwilson: doall isn't really parallel to doseq because it holds onto the head. dorun is more like doseq

18:53 zakwilson: map returns a lazy sequence; the thing required to generate each element of it is not done until the value of that elemnet is requested.

18:53 doall causes the whole sequence to be generated immediately

18:55 Sushisource: Welp, this totally works

18:55 Thanks for the advice

18:55 zakwilson: I had to look up dorun. I don't think I've ever used it. It is also a reasonable way to do this: the side effects are performed and the return sequence is discarded.

18:55 gfrlog: maybe that's why I like doseq better

18:56 Sushisource: To try to answer myself, if I wanted to parellelize this I'd probably need to use the Neo4j's REST api ro somesuch

18:56 Sounds like effort

18:57 zakwilson: doseq and dorun are the Right Thing if you don't need a return value. Not mingling side effects and things that return values is better style, so yeah, prefer doseq and dorun to doall for this.

18:57 Sushisource: Cool, good to know

18:57 zakwilson: You're actively using Neo4j for stuff. Good. Maybe you can tell me what I should read to learn more about graph databases and when I might want to use them.

18:58 Sushisource: Well, right now I'm actually using it for a DnD character helper, of all things

18:59 It parses in a whole damn lot of various feats/spells/etc/whatever

18:59 And makes links between things that have affects on other things

18:59 Then, if you want to make some particular spell or whatever the best it can possibly be, you do reverse traversal on things that reference it

19:00 And it saves you the time of wading through thousands of pages of books

19:00 zakwilson: I get the feeling a graph database might be a better fit than a relational database for a lot of applications that involve a bunch of things well... relating to each other. I just haven't seen a good intro to graph databases article.

19:00 Sushisource: Yeah, it really feels like that

19:00 I sat down and tried to do this with sqllite

19:00 clojurebot: Cool story bro.

19:00 Sushisource: And I was like "shit, this is impossible"

19:02 zakwilson: I'm building a pretty ordinary database-backed webapp and finding it really tedious to write a zillion joins for relationships like item belongs to user. I'm thinking about using clj-record, but ORM is an antipattern.

19:02 And clj-record is at least ORM-like, even if it isn't making classes.

19:02 ibdknox: zakwilson: store it as objects?

19:02 zakwilson: then it's hard to query

19:03 ibdknox: yeah, it's pretty easy to build your own indexes for things you want to query on

19:03 Sushisource: I really can't speak from much experience yet, because I've just got into it for this, but it really seems like a much more intuitive way to manage complex relationships and searching through them

19:04 My only complaint might be that the documentation is a little sparse

19:04 dnolen: Sushisource: btw, this sounds like a problem that's a good fit for core.logic.

19:04 zakwilson: The thought of using a document store instead of a relational DB crossed my mind, but there really are a bunch of separate entities that relate to each other. Relations make sense. Graphs might make sense if I understood them. Documents/objects really don't.

19:05 dnolen: Sushisource: you just load all your facts into memory and do your querying there, if you're feeling brave https://github.com/clojure/core.logic

19:05 ibdknox: zakwilson: fair enough, I completely agree if there are lots of relationships then it doesn't make sense

19:06 dnolen: Sushisource: basically you talking about an expert system, Prolog is great for building one quickly as long as your dataset can fit reasonably into memory.

19:07 zakwilson: But I think a graph DB might. I want to learn more about them without having to jump in head first, and google/wikipedia are failing me.

19:08 Sushisource: Cool suggestions. My only hesitation of doing something in memory is that there is quite a lot of text attached to this stuff

19:08 Raynes: zakwilson: http://github.com/flatland/jiraph

19:09 Sushisource: The other issue being that the information is parsed from plaintext, so I think my plan is to do it with one script that builds the graph, and another for searchign it

19:09 Raynes: zakwilson: http://jim.webber.name/2011/04/21/e2f48ace-7dba-4709-8600-f29da3491cb4.aspx is a fantastic introduction to graph databases.

19:10 zakwilson: Thanks.

19:10 (inc Raynes)

19:10 sexpbot: ⟹ 5

19:13 danbell: wait does that work?

19:13 (inc zakwilson)

19:13 sexpbot: ⟹ 1

19:13 danbell: for showing it to me

19:18 technomancy: hehe: (in-ns 'safe.module.helper)

19:18 (def i (safe.account/get-id :mysql-id 337))

19:18 (def h (query i "date:[0000-01-01T00:00:00Z TO 1990-01-01T00:00:00Z]"))

19:18 (def h2 (query i "date:[2011-03-22T00:00:00Z TO 2011-03-22T23:59:59Z"))

19:18 (def pfs (set (map :packfile-name (concat h h2))))

19:18 (defn parse-packfile-blob-name [packfile-name]

19:18 (let [[account-uuid _ pf] (.split packfile-name "/")

19:18 coll-id (clojure.string/join "-" (butlast (.split pf "-")))

19:18 chunk-id (last (.split pf "-"))]

19:18 [account-uuid coll-id chunk-id]))

19:18 (doseq [p pfs]

19:18 (apply safe.import.indexing/download-and-index (parse-packfile-blob-name p)))

19:18 dammit

19:19 I meant to say https://github.com/jboner/akka/commit/554bb3eb293fe083dcc4fd0fcb8e0b23bd566e5b#L2R19

19:20 Raynes: technomancy: Paste moar code. MOAR

19:21 ibdknox: technomancy: wow...

19:21 clojurebot: technomancy is to blame for all failures

19:21 hiredman: clojurebot: botsnack

19:21 clojurebot: Thanks! Can I have chocolate next time

19:22 zakwilson: I recently updated leiningen. Now, when I run lein swank and try to create futures in the running program, I get java.util.concurrent.RejectedExecutionException

19:22 technomancy: I put some flood blocking stuff on ERC but I guess I didn't test it.

19:23 hiredman: ANYWAY i think you will appreicate the github link

19:23 ibdknox: technomancy: lol that page is over 15gb

19:23 err

19:23 mb

19:23 hiredman: clojurebot: regale us with tales of scala

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

19:23 hiredman: clojurebot: tell me more about scala

19:23 clojurebot: {((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}

19:24 hiredman: clojurebot: is there anything else I should know about scala?

19:24 clojurebot: Scala often gets in the way when trying to write neat code -- seen in #scala

19:24 hiredman: I see

19:24 zakwilson: clojurebot: it seems you have some opinions on scala

19:24 clojurebot: scala is also<reply>"we are completely screwed on ==." -- seen in #scala

19:24 zakwilson: clojurebot: should I use scala?

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

19:24 hiredman: I should reall fix those factoids

19:26 jweiss_: any clojure libs out there for testing external apps? lazytest etc are really for testing clojure code. looking for a generic test runner

19:27 zakwilson: technomancy: can you tell me anything about lein swank and the above exception? I can't use futures, pmap and probably agents since upgrading leiningen.

19:27 hiredman: technomancy is feuding with the clojure runtime

19:28 you may need to upgrade swank-clojure

19:28 technomancy: zakwilson: I just pushed out 1.3.2 this morning

19:28 if you still have the problem then you are running into a bug that I cannot reproduce on my own machine =\

19:28 clojurebot: agent thread pool?

19:28 clojurebot: the agent thread pool is kind of a problem in Clojure, see http://tech.puredanger.com/2010/06/08/clojure-agent-thread-pools/ and http://p.hagelb.org/shutdown-agents.jpg

19:29 technomancy: trying to work around a shortcoming of clojure and it's not going so well

19:29 zakwilson: [swank-clojure "1.3.2"] is not being found by lein deps

19:30 technomancy: hmm... let me look again

19:30 zakwilson: thanks

19:30 technomancy: hm; I hadn't regenerated the pom when I uploaded

19:31 try again

19:32 zakwilson: That works now. Thanks.

19:32 (inc technomancy)

19:32 sexpbot: ⟹ 13

19:33 technomancy: great

19:34 mdeboard``: technomancy: Earlier you asked me to add a println to compile/get-readable-form right before shutdown-agents is called. What should I be printing?

19:34 technomancy: mdeboard``: first try 1.3.2 and see if that fixes it

19:35 mdeboard``: clj 1.3.2?

19:35 * mdeboard`` just got home from work

19:35 technomancy: swank-clojure 1.3.2

19:38 mdeboard``: technomancy: I assume lein plugin install swank-clojure 1.3.2 will be sufficient? I don't need to uninstall the old one?

19:38 s/assume/home

19:38 hope*

19:39 technomancy: try it; if it doesn't work then try again with the old one deleted

19:39 I'm not sure if the de-dupe goes by file modification time or by version number

19:43 mdeboard``: I actually needed to uninstall/reinstall lein anyway

19:45 technomancy: :O!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

19:45 You beautiful bastard

19:45 I am truly excite.

19:45 technomancy, i am not disappoint

19:45 in other words, it worked.

19:48 (inc (for [x (technomancy amalloy)] x))

19:48 sexpbot: ⟹ 1

19:48 mdeboard``: aw :(

19:48 amalloy: lol

19:48 nobody's ever going to inc that user again

19:49 mdeboard``: ,(inc (for [x (technomancy amalloy)] x))

19:49 clojurebot: java.lang.Exception: Unable to resolve symbol: technomancy in this context

19:50 amalloy: technomancy: want to apply yourself to me as a function, baby?

19:51 mdeboard``: ,(inc (for [x (2 3)] x))

19:51 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

19:51 mdeboard``: fine

19:57 gfrlog: (inc (for [x (technomancy amalloy)] x))

19:57 sexpbot: ⟹ 2

19:59 mdeboard``: is that even right

19:59 gfrlog: mdeboard``: it's incrementing the karma of a user called "(for [x (technomancy amalloy)] x)"

19:59 who hasn't shown up in #clojure too often lately

20:00 mdeboard``: lol, I mean, the logic

20:00 notionally

20:00 gfrlog: well the fact that you have an unquoted list won't help

20:00 mdeboard``: ohright

20:00 amalloy: and inc'ing a list won't either

20:01 gfrlog: (doseq [x [technomancy amalloy]] (inc x)) is probably what you're wanting

20:01 mdeboard``: oic

20:01 gfrlog: in this fantasy-clojure world

20:01 mdeboard``: I'm having a clojure threesome in fantasy clojure world

20:01 gfrlog: I bet

20:02 mdeboard``: snuggled between two big soft parentheses

20:02 gfrlog: parentheses-pillows: worst lisp-gift ever?

20:02 * gfrlog says "lisp-gift" three times fast

20:05 amalloy: gfrlog: i'm super-sad that i can't find those anywhere

20:06 gfrlog: my wife has a body-pillow that could maybe be shaped as a paren

20:07 new project: ranking the ASCII punctuation marks by their value as a pillow-shape

20:07 * gfrlog can't decide if '#' is good or bad

20:08 gfrlog: amalloy: yeah googling for "ascii pillows" is quite disappointing

20:09 mdeboard``: should be googling for unicode pillows anyway

20:10 amalloy: i want one with "&#40;" on it so nobody knows my secret love of parens

20:11 mdeboard``: amalloy: You're among friends, you can come out of the clojet. No one will even notice your lisp.

20:11 amalloy: or "&#40; is #1 in my book"

20:13 * gfrlog tries to construct a joke out of 40, 41, and 42

20:13 gfrlog: parens are the path to the ultimate answer?

20:13 :/

20:14 amalloy: &(char 41)

20:14 sexpbot: ⟹ \)

20:14 amalloy: &(char 42)

20:14 sexpbot: ⟹ \*

20:21 mudge: hello, is it possible to call a macro from java?

20:22 gfrlog: why would you want to do that?

20:22 mudge: gfrlog: because my boss says I have to write in java but there's a clojure library I want to use in Java

20:22 gfrlog: and I am trying to call a clojure macro but I am getting a Wrong number of args error

20:23 gfrlog: what library is it?

20:23 Scriptor: mudge: clojure macros take in clojure data structures for their arguments, so make sure that's what you're passing it

20:23 mudge: gfrlog: so I am calling the clojure functions from with Java, but now I need to call a macro

20:23 hiredman: macros take to implicit args &form and &env

20:23 two

20:23 you can't really call a macro

20:24 mudge: don't do that

20:24 it won't be what you want

20:24 mudge: okay, well here is exactly what I am trying to do, I am trying to call prxml

20:24 from clojure.contrib.prxml

20:24 but clojure.contrib.prxml prints to standar out

20:24 but i want it to return a string

20:25 so normally you wrap prxml with with-out-str, which is a macro

20:25 so I am trying to figure out how to make prxml return a string in java

20:26 gfrlog: hmm

20:26 if you're not allowed to write an inch of clojure code

20:26 mudge: gfrlog: i find out prxml contructs xml is nicer than using Java DOM stuff

20:26 gfrlog: the first thing that comes to mind is pushing/popping thread bindings to set *out* to a string writer

20:27 Scriptor: would there be any way to set *out* using java?

20:27 ^^

20:27 mudge: yea, anyway to set *out* ?

20:27 gfrlog: &(doc push-thread-bindings)

20:27 sexpbot: java.lang.SecurityException: You tripped the alarm! push-thread-bindings is bad!

20:28 gfrlog: wut?

20:28 (dec sexpbot)

20:28 sexpbot: ⟹ -1

20:28 gfrlog: anyhow, I'm 96% sure push-thread-bindings and pop-thread-bindings will do the trick

20:29 mudge: gfrlog, i will take a look at it

20:29 gfrlog: mudge: the canonical example usage is the source for clojure.core/bindings

20:30 Scriptor: ,(doc binding)

20:30 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

20:30 mudge: RT.var("clojure.contrib.prxml", "prxml").invoke("[:funny \"yes\"]") will call prxml, so just need to figure out how to set *out*

20:30 gfrlog: s/bindings/binding

20:30 sexpbot: <gfrlog> mudge: the canonical example usage is the source for clojure.core/binding

20:30 mudge: gfrlog: thanks, I'll check it out now

20:30 Scriptor: damn, binding is a macro too

20:30 mudge: is there a way to call macros from java?

20:31 gfrlog: Scriptor: yeah, that's why gotta push/pop manually. Presumably there could be an in-between function that's just like binding but takes a fn, but that's only helpful if these weird situations come up more often :)

20:32 it could be called clojure.core/binding*

20:32 hiredman: mudge: you can't "call" macros

20:32 Scriptor: mudge: you can always ask the mailing list, bigger audience there

20:32 (regarding the setting *out* part)

20:32 might be someone who's already done this

20:32 hiredman: when you use a macro it is expanded by clojure's compiler and compiled in place

20:33 gfrlog: in the best case, it would mean you'd have to write an eensy bit of clojure code ;-)

20:33 which would presumably get you fired

20:33 mudge: hiredman: what terminology should I use for invoking a macro?

20:33 amalloy: yeah, calling a macro from java is unlikely to be an action that makes you happy

20:33 hiredman: mudge: it's not a terminology thing, what you want to do is not possible

20:33 mudge: use push and pop as people have suggested

20:34 mudge: yea, i don't want to get fired by actually writing any clojure but using libriaries in java is okay

20:34 hiredman: okay, thanks

20:34 gfrlog: dangit if this conversation goes on any longer I'll have to go write binding* myself.

20:34 amalloy: gfrlog: it's not very nice as a non-macro

20:35 gfrlog: amalloy: it couldn't just take some pairs and a fn?

20:35 amalloy: sure

20:35 the need to take a fn is what's not very nice

20:35 gfrlog: which would be much nicer in weird-constraints-java-world

20:35 than pushing and popping

20:35 oh wait

20:35 I'd be writing it in clojure

20:36 Scriptor: mudge: you could make a case that you'd only need a tiny bit of clojure code (write it before-hand) and document it fully

20:36 gfrlog: which wouldn't do him any good

20:36 Scriptor: if it beats implementing the lib yourself

20:36 gfrlog: (defn call-macro [var & args] ...)

20:36 mudge: gfrlog: it's okay if you write it in clojure as long as I can call it from java

20:36 * gfrlog blinks

20:37 gfrlog: so you can use clojure code as long as you're not the author?

20:37 mudge: Scriptor: yes, thanks

20:37 amalloy: i think that if you tried to actually do that, you'd find that's not the rule :P

20:37 mudge: gfrlog: just can't use the clojure language, but I can use libraries in java

20:38 Scriptor: gfrlog: hmm, the boss might just want the jars or something, if he wrote the clojure that'd mean there'd be clojure source in the project

20:38 gfrlog: so I'd have to package it in a "library" for you?

20:38 Scriptor: which he doesn't want to have to find devs to maintain in the future

20:38 mudge: Scriptor: correct

20:39 gfrlog: I guess it's easy enough to "lein jar"

20:39 alright blastit now that we've gone through all this effort...

20:50 mudge: https://github.com/fredericksgary/binding-star

20:50 I put a jar in the downloads section if that's easier

20:51 mudge: thanks gfrlog!

20:52 gfrlog: mudge: you'll have to create a map with a var in it, but I imagine if you're mucking with all the RT stuff then you can probably figure that out

20:53 mudge: gfrlog: yea

20:54 gfrlog: i think i know how to use it, trying it

20:56 jst: \list

20:56 oh, ffs

20:57 Alright, I have a question about Clojure that bothers the hell out of me.

20:57 Who's up to the challenge?

20:57 jcromartie: ok

20:57 amalloy: anyone?

20:57 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:58 amalloy: i think it's hilarious that anyone would think that depending on gfrlog's ten-second-to-write, never-going-to-be-maintained library is deemed better than writing two lines of clojure yourself, mudge

20:58 jst: Alright, why do the bindings in (let ...) need to come in form of a vector?

20:58 Scriptor: jst: it's not quite a vector

20:58 jcromartie: really, that's it?

20:58 amalloy: jst: the alternative being?

20:58 gfrlog: (inc amalloy)

20:58 sexpbot: ⟹ 15

20:58 amalloy: Scriptor: yes it is

20:58 jst: (let (x 1) 1) for example

20:58 A list

20:59 Scriptor: jst: ok, so it's a vector, but the syntax was chosen to visually separate the bindings from the actual code

20:59 amalloy: jst: to reduce the cognitive overload on parens

20:59 so that (x 1) can (almost) always mean "i'm calling x as a function"

20:59 rather than having to parse the surrounding code to decide what the parens mean this time

21:00 mudge: amalloy: yes, I think I am actually just going to write his clojure code in java to do the same thing

21:00 amalloy: but there's no technical reason

21:00 jcromartie: generally (fn-or-macro [bindings or arglist] ...)

21:00 mudge: amalloy: yes, in general it is dumb

21:00 amalloy: mudge: last was directed at jst

21:00 mudge: amalloy: ah, okay

21:00 jst: I'm just confused by all the different types of braces.

21:00 Scriptor: if I have a jar in my lib/ folder, how do I go about figuring out what to actually import?

21:00 amalloy: (defmacro cl-let [argvec & body] `(let ~(vec argvec) ~@body))

21:01 jcromartie: jst: fair enough... there are a lot in clojure

21:01 Scriptor: every combination I've tried so far has returned ClassNotFound

21:01 jcromartie: however almost all of them are just sugar

21:01 jst: But thanks! You, guys, helped.

21:02 gfrlog: mudge: and I'll probably delete that github repo the next time I'm reminded of its existence ;-)

21:02 Scriptor: gfrlog: remember *bind*?

21:02 * bind*

21:02 gfrlog: Scriptor: I have to forget it first

21:04 Scriptor: so, to add a little more detail to my question, I have netflix-java-client-2.1.2.jar under lib/, the project's name is clj-netflix

21:05 what symbol name would I have to use to :use/import it?

21:05 jst: \quit

21:05 ffs

21:05 amalloy: Scriptor: you need to figure out what's in the jar. there's no global answer

21:05 mudge: gfrlog: okay, i got it

21:05 gfrlog: jar -tf

21:06 mudge: now I am wondering how to create a clojure map in java

21:06 amalloy: if the jar has a com.foo.netflix.Server class you want to use, you'll have to import that

21:06 gfrlog: mudge: I would try creating a java map first to see if it takes that

21:06 mudge: gfrlog, okay

21:07 gfrlog: else, the api on the clojure map classes might be easy enough

21:07 or wait

21:07 just call hash-map

21:07 ,(hash-map (var inc) "wut")

21:07 clojurebot: {#'clojure.core/inc "wut"}

21:08 mudge: gfrlog, okay, thanks

21:08 gfrlog: I guess there should have been an alternate signature that takes a var, value, and fn, for the most common use case, but I refuse to edit that project any further :P

21:09 Scriptor: amalloy: no matter what the name of the class, it's prepended with my project's name, right?

21:09 like my-project.com.foo.netflix

21:09 amalloy: uh, no

21:10 gfrlog: Scriptor: not if it's in a java jar

21:10 mudge: gfrlog, that's fine, thanks

21:10 Scriptor: ah

21:10 gfrlog: Scriptor: you import by class name, like you do in java

21:11 Scriptor: "like you do in java" heh...about that

21:12 mudge: wait, can't I just do this to get the *out* variable: Var out = RT.var("clojure.core", "*out*");

21:12 gfrlog: probably

21:13 I've never used clojure from java, that's the only reason I hesitate

21:13 gonna just set it directly?

21:15 cemerick: technomancy: did I just see a github link where unicode arrows work in scala case clauses?

21:16 mudge: gfrlog: i don't know, when I call RT.var("clojure.contrib.prxml", "prxml").invoke("[:p \"data\"]") it does not print to standard out like it should so I am confused

21:19 amalloy: mudge: well that won't work anyway, because prxml wants a vector, not a string that looks kinda like a vector

21:21 mudge: hmm... now I am trying this: RT.var("clojure.core", "print").invoke("data to print")

21:21 but it doesn't go to standard out

21:21 amalloy: println

21:21 mudge: somehow I need to connect clojure with standard out, connect *out* with System.out

21:21 amalloy: print doesn't flush the buffer

21:21 Scriptor: amalloy, gfrlog: thanks guys!

21:22 mudge: amalloy: is there a clojure function that flushes the buffer?

21:22 gfrlog: Scriptor: yessir

21:23 I think you can call .flush on *out*

21:23 amalloy: println

21:23 or flush

21:23 or .flush

21:23 cemerick: OMG, it's true: http://scala-programming-language.1934581.n4.nabble.com/More-unicode-alternatives-for-ASCII-operators-td2008146.html

21:23 old news, but I had no idea

21:25 mudge: amalloy, I'll try flush

21:25 pdk: unicode icons for set operations would be neat

21:25 doesn't forth already use special symbols for those sorts of ops

21:26 cemerick: Neat, yet entirely impractical.

21:26 mudge: amalloy: flush worked!!!!!!!!!

21:26 amalloy: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

21:26 gfrlog: go potty-training

21:27 mudge: amalloy: haha

21:27 so now I will try prxml with flushing

21:27 * gfrlog tries not to make another poo joke

21:30 mudge: prxml works goes to standard out!!!!! but it expects a vector ooop!

21:33 gfrlog: clojure from java: worse than normal-java?

21:34 chouser: that's if the Clojure is doing nothing to help.

21:35 It's fairly easy to write Clojure that allows completely clean, idiomatic Java to work with it.

21:36 mudge: did you figure out how to bind *out* to what you want?

21:36 mudge: yes, I think it is best if I wrote a Clojure utility library and use those from Java

21:36 gfrlog: mudge: well good luck finding a new job ;-)

21:37 mudge: gfrlog, yes, i probably won't do it because of that

21:37 i probably will find another job after my current project

21:37 just want to finish my current project

21:39 chouser: i think that I can do it but I haven't done it

21:39 I want to use prxml in java but I realized I need to make vectors in java

21:39 and I am not sure if it is worth it

21:39 edw`: Anyone here used Noir with Json POST requests?

21:40 amalloy: RT.var("clojure.core", "eval").invoke(RT.var("clojure.core", "read").invoke("(prxml [:a \"data\"])")); // no clojure, just java!

21:42 mudge: amalloy: thanks, I think I can use "eval" to parse the vector string literals into real vectors for prxml --- so I can still use the nice clojure vector syntax for prxml

21:42 jweiss_: trying to make a component of an assert macro that takes a form and returns the form with the locally bound vars replaced with their values. thought a zipper might help, is there a zipper out there that walks clojure expressions?

21:43 seq-zip doesn't descend into vector binding forms for instance

21:43 amalloy: jweiss_: bindings are gonna kill you anyway

21:43 jweiss_: amalloy: what do you mean?

21:43 amalloy: (let [x 1] (assert (= 1 (let [x 5] x))))

21:44 x will be 1 in the &env that assert gets passed

21:44 jweiss_: amalloy: ah well, this is just for informational logging, doesn't have to be perfect

21:44 amalloy: then just use postwalk-replace

21:44 jweiss_: k

21:45 chouser: amalloy: why not stick the binding in the clojure string along with the prxml and vector literals?

21:45 gfrlog: and that's how you call a macro from java

21:46 chouser: you might consider writing some Clojure code to make it all more palatable from Java

21:47 amalloy: chouser: sure, once you're going with read and eval, you might as well write the whole thing in clojure

21:47 chouser: wait, this is all going to suck

21:47 amalloy: but this isn't really my good suggestion

21:47 chouser: yeah, you'll have a giant string (with clumsily escaped double-quotes, probably) for your literal maps and vectors

21:48 you'd be much better off with some kind of fluid builder API in Java, I think, than trying to use prxml

21:48 gfrlog: chouser: hash-map and vector would be decent, wouldn't they?

21:48 mudge: I like the idea of just using eval for the literal vectors and maps

21:48 chouser: or better yet, write your code in Clojure and compile it ahead of time.

21:48 amalloy: augh if i'd known you would like the suggestion i never would have made it

21:49 it is a terrible idea

21:49 mudge: chouser: the reason I don't just write in clojure is because my boss wants me to write in java

21:50 amalloy: then he won't take kindly to "clojure encased in java strings"

21:50 mudge: but I could use clojure and clojure.contrib as java libraries

21:50 amalloy: it has all the disadvantages of clojure and none of the advantages

21:50 gfrlog: amalloy: that's about what I was thinking when I said "worse than normal-java"

21:50 mudge: amalloy: that's why I just like the idea of using eval for vectors

21:50 or maybe for maps too

21:50 gfrlog: mudge: call the vector function?

21:51 ,(vector :foo :foo :foo :foo)

21:51 clojurebot: [:foo :foo :foo :foo]

21:51 mudge: gfrlog: oh yea, good idea

21:51 amalloy: seriously whatever java api you want to use will be easier than this

21:51 gfrlog: you could even write yourself a helper function so your java code is vector(hashmap(...) ....)

22:05 mudge: when i write RT.var("clojure.core", "eval").invoke(RT.var("clojure.core", "read").invoke("(prxml [:a \"data\"])"));

22:06 I get java.lang.ClassCastException: java.lang.String cannot be cast to java.io.PushbackReader

22:12 ah, amalloy, read-string works: RT.var("clojure.core", "eval").invoke(RT.var("clojure.core", "read-string").invoke("(clojure.contrib.prxml/prxml [:a \"data\"])")); // no clojure, just java!

22:15 amalloy: if that code ever makes it into production i will kill myself for suggesting it. no pressure

22:15 anyway, i'm headed home. best of luck, i guess

22:16 cemerick: someone needs to talk me down from posting a Scala linkbait post

22:17 that is, it's entirely unproductive :-( ; but, I don't think I can help myself

22:18 Scriptor: wasn't there a clojure-lounge or something a while back?

22:19 cemerick: There's #clojure-casual, but it's fundamentally unpopulated.

22:22 Scriptor: cemerick: post it! I've found Scala reading to be pretty interesting

22:22 some stuff can still be relevant to clojure

22:38 hiredman: ,scala {((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}

22:38 clojurebot: Any = 1

22:39 Sushisource: So, if I want to apply my function that takes two parameters to every combination of two items in a sequence, what's the pretty way to do that?

22:42 cemerick: hiredman: can't believe you sullied clojurebot like that

22:43 jhickner: hi all, i have a question about idiomatic clojure when dealing with app state

22:43 is it good form to use a ref or atom even when you don't need concurrency? vs just def'ing repeatedly?

22:44 hiredman: the untyped λ calculus is the untyped λ calculus

22:46 Scriptor: jhickner: if you find yourself def'ing repeatedly why not use let?

22:47 hiredman: def repeatedly is always wrong

22:48 jhickner: so if you need to alter something, you should use a ref or an atom even if it's single threaded?

22:48 hiredman: depends

22:48 jhickner: @Scriptor: it's not localized to just one function, it's a state object that's used in a few places

22:48 amalloy: Sushisource: depends what you mean by "every combination"

22:48 hiredman: do you reallt need to alter something?

22:49 jhickner: it's a list of connected clients (to an aleph websocket server) and what group they're part of

22:50 i use a map of group ids to vectors of aleph channels to do things like send messages to a particular group

22:50 tomoj: I use an atom for that

22:51 though I haven't thought about it much

22:51 jhickner: yeah I don't know if there's a better way. an atom makes more sense than a ref though I agree

22:52 amalloy: Sushisource: ie, what would (my-cool-function + [1 2 3 4]) return? [3 7]? [4 5 5 6]?

22:54 jhickner: ok I think I'll use an atom for now. thanks guys

23:13 chrissbx: Is there another way than using a fn to bind multiple variables to values "in parallel", unlike the sequential way "let" does it?

23:14 * chrissbx typing example..

23:14 amalloy: &(let [[x y] [1 2]] (+ x y))

23:14 sexpbot: ⟹ 3

23:14 chrissbx: ah

23:14 good point

23:15 I guess I should ask whether that's slower, though, i.e. heap-allocating a vector.

23:15 amalloy: clojurebot: let* is ##(let [[x y] [1 2]] (+ x y))

23:15 sexpbot: ⟹ 3

23:15 clojurebot: Ok.

23:15 chrissbx: (but I guess an fn would do that, too)

23:16 tomoj: clojurebot: let*?

23:16 clojurebot: let* is ##(let [[x y] [1 2]] (+ x y))

23:16 sexpbot: ⟹ 3

23:16 tomoj: :D

23:16 chrissbx: Note that these let and let* are the other way around in Scheme.

23:16 * amalloy hopes to remember not to answer this question in long-hand next time

23:16 amalloy: chrissbx: yeah, i know

23:16 but when someone asks about it they always mention let*

23:17 chrissbx: I see

23:18 Now, actually the Scheme let is like let* and unlike a lambda, and unlike your solution, in that variable and expressions are together.

23:18 )Just nitpicking :)

23:18 (

23:18 amalloy: so write a macro

23:21 chrissbx: Hm. I'm translating Scheme to Clojure; such a macro would be easy for my translation process, but not sure people would like that.

23:23 (I could turn a Scheme let into a Clojure let as long as it doesn't use previous left-side variable names on the right side. Looses the meaning of "you (human reader) don't need to consider previous variables on the left when reading the expressions on the right",

23:24 but Clojurians would feel at home.)

23:31 Scriptor: chrissbx: as in, a scheme->clojure converter?

23:33 chrissbx: Scriptor: yes

23:33 jcromartie: chrissbx: actually that left-right let issue is not an issues

23:33 not an issue

23:34 Scriptor: chrissbx: cool, what're you using for parsing?

23:34 jcromartie: ,(let [x 1 y x z y] z)

23:34 clojurebot: 1

23:34 Scriptor: well, parsing and lexing

23:34 amalloy: jcromartie: yes it is?

23:34 chrissbx: jcromartie: that's Scheme let*; I'm missing something for Scheme let

23:34 jcromartie: OK maybe I misunderstood

23:35 chrissbx: Scriptor: I'm writing it in Scheme, so I'm just using the parser of the Scheme system.

23:35 amalloy: eg, scheme code might look like (let ((x 1)) (let ((x 2) (y x)) y)) and expect y to be 1

23:35 Scriptor: ah, got it

23:36 jcromartie: really? I would not expect that

23:37 I've been away from Dr(Racket|Scheme) for a while

23:37 amalloy: jcromartie: that's because you're not writing scheme, apparently :P

23:37 jcromartie: yup

23:37 never more than a few toy programs

23:41 amalloy: btw chrissbx, did i get the let syntax right? i only used a non-clojure lisp for a couple weeks

23:42 chrissbx: yes, it's correct

23:44 BTW is there some pretty-printer in Clojure that takes a Clojure s-expr and formats it nicely? (not just reindentationm, but line wrapping as well, with good consideration of the special forms)

23:45 (or, takes a file with Clojure code all in one line, and reformats it)

23:45 amalloy: &(doc clojure.pprint/pprint)

23:45 sexpbot: java.lang.Exception: Unable to resolve var: clojure.pprint/pprint in this context

23:46 amalloy: it takes some finagling, but it has some special-form support if you ask nicely, and pluggability for others you might care about

23:46 chrissbx: ok

Logging service provided by n01se.net