#clojure log - Sep 06 2011

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

0:02 mindbender1: please why do I keep getting this error message on ccw with eclipse on my first hello.clj file

0:02 => (hello "you")

0:02 #<CompilerException java.lang.Exception: Unable to resolve symbol: hello in this context (NO_SOURCE_FILE:1)>

0:07 please help

0:07 user317: so is hello a symbol?

0:09 seancorfield_: mindbender1: did you load the file into the REPL and then switch the REPL to that namespace? (two steps)

0:12 user317: whats the difference between using :use in your namespace and calling use, ie (use 'lamina.core) seems to work but :use 'lamina.core doesn't

0:12 :use in your namespace for files in your project, and (use <lib>) for external deps?

0:13 brehaut: user317: (use …) is mostly only useful in the repl, and (:use …) in your ns for project specific libs or deps

0:19 user317: so (ns myns :use 'foobar) is the same as (ns myns); (use 'foobar)?

0:20 brehaut: (ns myns (:use foobar)) is

0:21 michaelr525: hey

0:21 brehaut: or perhaps (ns myns (:use [foobar]))

0:21 i forget if the vector is optional on :use forms

0:23 yeah the vector should be optional according to (doc require)

0:23 mindbender1: seancorfield_: the tutorial I was following didn't point that out please can you point out the directions for me

1:05 user317: anyway to get around leins slow startup time? when i run it in interactive mode it hangs on any compiler errors

1:36 user317_: how do i set a java class's field name? i am new to java, does it have automatic getter/setter functions for members?

1:56 tomoj: &(->> #(rand) (repeatedly 2) #() (repeatedly 3))

1:56 lazybot: ⇒ ((0.19066336225889235 0.46004763443354735) (0.40565071223177274 0.48848509803591755) (0.20556681440024904 0.037729850401373))

1:56 tomoj: :/

1:57 pmbauer: user317_: no automatic setters.

1:57 If there is method "setFoo" on object of class Bar, you can call it: (.setFoo myBar aFoo)

3:17 robermann: ciao muffetta :)

3:24 michaelr525: hello!

3:31 khaliG: hi michaelr525

3:34 humourous: is it possible to view the source of multimethods through the repl?

3:37 ibdknox: http://news.ycombinator.com/item?id=2964419

3:37 this keeps coming up

3:38 khaliG: ibdknox, why does it?

3:39 ibdknox: My argument would be that no one is purely focused on improving the overall experience of using Clojure

3:39 clojure/core is improving the language and trying to expand its reach

3:41 but ClojureScript is perfect example of not focusing on the experience of using the language

3:43 khaliG: so people can't get started or they get stuck

3:50 khaliG: ibdknox, you're referring to the "Set up" point in the article?

3:50 ibdknox: khaliG: the two main points people bring up about clojure are errors and documentation

3:51 the last bay area clojure group was basically a long rant about those two things

3:52 every article talks about those two issues when going over the practicality of clojure

3:52 khaliG: ibdknox, i'm fairly new to clojure myself and can relate to that somewhat - but I think the stacktraces aren't too bad, you get good at reading them

3:52 ibdknox: khaliG: I agree, but you shouldn't have to ;)

3:54 khaliG: ibdknox, has someone articulated how they should be technically better?

3:55 ibdknox: khaliG: it's a well known problem that has been discussed a great deal

3:56 khaliG: ibdknox, ah sorry i'm not familiar with those exchanges - would be interesting to see how they propose things need to be improved

3:56 ibdknox: khaliG: sorry, that wasn't meant to be dismissive at all, I was just saying that it's something that the "right people" know about :)

3:57 and solutions have been discussed

3:57 khaliG: gotcha

3:57 pyr: morning

3:58 ibdknox: It comes down to someone needing to own the experience of writing a clojure app from end to end

4:09 thorwil: hmm, i didn't see the documentation to be that lacking. however, error messages are about the only thing where i see clojure as a step down from python

4:09 ibdknox: thorwil: some of the documentation is pretty obtuse if you don't already have a firm grasp of functional programming

4:10 still

4:10 compare clojure.org to ruby-lang.org

4:10 documentation isn't just API docs, it's also things like "Ruby in twenty minutes..."

4:11 thorwil: ice brick vs campfire :)

4:12 khaliG: it does lead to the question whether clojure is suitable as a first language? maybe it isnt?

4:12 ibdknox: khaliG: I don't buy that :)

4:12 TheMoonMaster: I wouldn't give someone clojure as their first language. :P

4:14 ordnungswidrig1: I'd recommend scheme as a first language. the tight integration with java is distracting.

4:14 TheMoonMaster: Yeah, my main thought would be Java interop confusing them.

4:14 ibdknox: eh, to just start programming, you don't need any of the Java stuff

4:14 when you start with python

4:15 or any other language, you rarely do things that interact with the host

4:15 ordnungswidrig1: ibdknox: but java shines through everywhere in clojure. e.g. at stack traces, error messages and so on

4:15 I think scheme would be nicer

4:15 TheMoonMaster: I'd throw Ruby or Python at someone interested in general programming.

4:15 ibdknox: ordnungswidrig1: those are solvable problems I think, but yes, in its current state

4:16 thorwil: i guess it's hard to compete with racket for a scheme and an introduction to programming

4:16 ordnungswidrig1: ibdknox: yes, when there is cinc, then clojure will be nicer as a first lang

4:17 ibdknox: anyways guys, I've ranted enough for one night :)

4:17 g'nite!

4:17 khaliG: ibdknox, night

4:19 ordnungswidrig1, so would you say you need to know Java first?

4:19 ordnungswidrig1: khaliG: not, necessarily

5:04 michaelr525: hey wunki

5:04 why are you connecting from amazon machine?

5:11 wunki: michaelr525: I installed a bouncer on the free instance you can get from AWS

5:18 michaelr525: cool

5:18 free instance..

5:18 where is that?

5:24 wunki: michaelr525: you get one free EC2 micro instance when you sign up for AWS

5:34 bendlas: Good day, folks!

5:35 I just wondered: Is there a way to intern the same Var in two different namespaces?

5:35 i.e. is there a way to intern an existing var object in a namespace?

5:42 raek: bendlas: don't think so, but you can always refer the var

5:43 but that doen't allow other namespace to refer the refered var

5:45 bendlas: raek: that would have been my use case

5:45 a transitional aid in refactoring

5:45 but I can imagine, that it would open the door to too much dynamic-binding wierdness

5:46 thanks, anyway

5:47 raek: yeah, something like that would make it possible to rename a namespace and keep the old one for backward compatibility

5:48 but afaik there is no obvious way to do that

5:50 there is 'immigrate' from old contrib, but it creates new vars. so if you update vars in the one namespace that change won't propagate into the other

5:50 bendlas: ack

5:51 the real solution will be a proper refactoring tool

5:53 mindbender1: greetings

6:29 clgv: Is there already a hierachical clustering algorithm implemented in clojure? I didn't find anything in incanter.

6:34 mindbender1:

6:56 scottj: clgv: maybe infer

6:56 clgv: scottj: which lib is that?

6:57 https://github.com/getwoven/infer?

6:57 clojurebot: eg, https://github.com/clojure/tools.logging is the new version of clojure.contrib.logging

6:58 scottj: clgv: yeah

7:04 wunki: can someone help me how to supply a function with extra parameters when a condition is met. For example: https://gist.github.com/5075886377eb27feaeed

7:04 thus, if condition x, also add these parameters to the function call.

7:05 ordnungswidrig1: (apply f arg1 arg2 arg3 (if (condition [arg4 arg5] []))

7:06 wunki: sth like that?

7:08 wunki: ordnungswidrig1: let me try that

7:09 ordnungswidrig1: passing [] to the function causes it crash, wrong amount of arguments

7:09 kzar: I've messed up the recursion in this little function somehow, any ideas? http://paste.lisp.org/display/124505 (It's running off forever even if I do (take 5...))

7:09 wunki: I think I need an if, or else do nothing, don't return nil also

7:11 Chousuke: kzar: that lazy-seq is pointless. recur is not lazy.

7:11 ordnungswidrig: wunki: you'll need sth like (apply validate letter [:title...] ... [:body...] (if (:reply letty) [[:reply objectid?...] [:reply...]] []))

7:13 kzar: Chousuke: Ah right, I'll go read about lazy-seq methinks

7:14 Chousuke: (defn reductions [f init coll] (lazy-seq (let [res (f init (first coll))] (cons res (reductions f res (rest coll))))))

7:15 hm, that probably fails at the end of the reductions

7:15 your job to fix it :)

7:16 the point being, usually you don't want to use recur if you want a lazy seq

7:17 you just use regular recursion, which is made non-stack-growing by the laziness of lazy-seq

7:39 wunki: ordnungswidrig: I wasn't able to make it work.

7:40 ordnungswidrig: wunki: gist your code

7:40 wunki: https://gist.github.com/2c86bec2f2249d69c4ed

7:40 I stripped apply again, to start clean

7:42 ordnungswidrig: wunki: https://gist.github.com/a9da42cfda88499f47f6

7:42 wunki: this should work

7:42 wunki: ordnungswidrig: trying it right now

7:43 ordnungswidrig: ,(apply println :foo :bar (if true [[:baz :qux]] []))

7:43 clojurebot: :foo :bar [:baz :qux]

7:51 wunki: ordnungswidrig: checks don't seem to work anymore. I'm now always getting `null` returned

7:59 mccraig: are there functions for manipulating file-paths anywhere in core/contrib : something like ruby's File.dir/basename/dirname/expand_path/join ?

7:59 kzar: Chousuke: Gotya, got it working :) http://paste.lisp.org/display/124505#1

8:05 raek: mccraig: clojure.java.io/file

8:06 if you pass it multiple string or File arguments, it will join them with the serparator of the platorm

8:06 it returns a java.io.File instance, which has methods for more advanced stuff

8:07 mccraig: raek: ah, ok… and then use e.g java.io.File.getCanonicalPath for expand_path

8:07 raek: yeah

8:07 mccraig: raek: thx

8:07 raek: the file function basically just wraps the constructor of File, which is a pain to use

8:08 (you can only join two segments)

8:42 wunki: ordnungswidrig: excuse me, it was some other code that caused the error. Thank you for your help, it worked!

8:43 ordnungswidrig: wunki: I'm glad I could help

8:53 khaliG: i've got a png image i use as an icon - is there a clojury way of referring to it from code?

8:55 ordnungswidrig: khaliG: you can load it from the class path using getResourceAsStream

8:56 khaliG: ordnungswidrig, so where shall i store it in my lein project - in src? or somewhere else?

8:56 raek: khaliG: put it on the classpath (e.g. in resources/, which leiningen adds to the classpath automatically) and use clojure.java.io/resource to get a handle to it

8:56 src/ works too, but it can be nice to separate these things

8:56 khaliG: so in $PROJECT/resources raek?

8:56 raek: yes

8:57 khaliG: ok thanks

8:57 raek: if that dir did not exist when you started clojure, you might need to restart it

8:57 khaliG: yeah i've got no such directory :/

8:57 i was about to create it by hand

8:58 raek: yes, you have to do that

8:58 khaliG: ok understood

8:58 raek: (resource "foo/bar/file.png") will access $PROJECT/resources/foo/bar/file.png

8:58 khaliG: excellent, that's very nice and neat :)

8:59 raek: in the string you give to resource, always use forward slashes as separators and don't include one in the beginning of the string

9:01 khaliG: also, you can give the thing you get from the resource call directly to the constructor of ImageIcon

9:01 johnbendi:

9:03 khaliG: raek, that worked beautifully. I need to take a closure look at clojure.lang.io to see what other goodies lie there

9:06 gtrak: a closure look? lol

9:07 Wild_Cat: stupid question: why does get not work on lists when nth works on vectors?

9:08 gtrak: get is associative, vectors are also associative from ints to vals, I don't think lists are associative

9:08 bpsm: Wild_Cat: "get" is supposed to imply O(1), efficient random access, while nth implies sequential O(n) cost.

9:09 Wild_Cat: bpsm: does nth have O(n) cost on vectors as well?

9:09 gtrak: ,(get ['a 'b 'c 'd] 1)

9:09 clojurebot: b

9:09 gtrak: ,(get '('a 'b 'c 'd) 1)

9:09 clojurebot: nil

9:10 gtrak: ,(nth '('a 'b 'c 'd) 1)

9:10 clojurebot: (quote b)

9:10 gtrak: ,(nth ['a 'b 'c 'd] 1)

9:10 clojurebot: b

9:10 bpsm: I expect that nth will have O(n) cost on vectors as well (though clojure could special-case it, I don't think it does.)

9:10 johnbendi: what the best site for clojure business-related open source projects?

9:11 gtrak: bpsm, why wouldn't it special case it?

9:11 bpsm: because that just muddies the waters when you want to communicate get is O(1), nth is O(n).

9:11 gtrak: clojure always tends practical

9:12 O(1) doesn't muddy the O(n) waters, it dilutes them :-)

9:12 and big-o is always worst case

9:12 chouser: nth doesn't promise fast access in general, but does provide it on vectors.

9:14 bpsm: Yup. I just found that out too by reading the definition of nth in https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java It special cases for things that implement Indexed (like Vector).

9:15 Wild_Cat: I see. Thanks for the info.

9:16 I'm not convinced of the usefulness of having separate get and nth functions, but at least I see the reasoning behind it.

9:16 gtrak: in fact Indexed only has an nth and a count() method

9:16 Wild_Cat, get works on maps

9:16 nth on a map gives you an entry I believe

9:16 Wild_Cat: gtrak: sure. What I mean is, why not just have get work on all collections and get rid of nth entirely?

9:17 gtrak: ,(nth {:a 1 :b 2 :c 3} 1)

9:17 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap>

9:17 Wild_Cat: I come from an OO background -- code to the interface, not the implementation, and performance characteristics are an implementation artifact ;)

9:17 gtrak: ah, it just fails, I think get and nth are conceptually different, the same argument is, why have vectors when a vector is just a map of ints to vals?

9:17 just use maps instead

9:17 Wild_Cat: gtrak: because maps are unordered.

9:18 and because maps may be sparse

9:18 gtrak: you can have a non-sparse ordered map if you like

9:18 Wild_Cat: gtrak: yeah, it's called a vector :p

9:18 manutter: wait, get and nth do different things, don't they?

9:19 gtrak: they only do the same thing on vectors

9:19 which makes sense

9:19 manutter: get == "look up a value in a map (associative array) with an optional default value if the key is not found"

9:19 nth == "retrieve an item in a list based on position"

9:19 right?

9:19 clojurebot: to be fair I dunno that I've ever had code out right rejected, it just sits in jira or assembla or where ever, or if I ask if there is any interest (before writing any code) I get told to go write alioth benchmarks

9:20 manutter: botsmack

9:20 gtrak: Wild_Cat, I think many of clojure guys come from OO background :-). At some point it's worth drawing a line, and they draw it at performance guarantees. Sometimes you want a map, sometimes you want a vector.

9:21 the abstraction for both is called collection

9:21 mprentice: gtrak: vectors and maps are different data structures with different characteristics, appropriate in different situations

9:21 Wild_Cat: gtrak: like I said, I understand the reasoning. I don't agree with it, but I understand it ;)

9:21 gtrak: Wild_Cat, I think you *should* agree with it :-)

9:21 not to be dogmatic

9:22 Wild_Cat: gtrak: well, my point of comparison here is Java's own LinkedList and ArrayList

9:22 which both support the List interface.

9:22 but widely different performance characteristics.

9:22 gtrak: there's a common interface if that's what you need

9:23 mprentice: gtrak: oops sorry, i think i jumped in talking to the wrong person :P

9:23 gtrak: mprentice, yes, I agreed with what you said

9:23 Wild_Cat: gtrak: still, what I get of all this is that get shouldn't be used on vectors either. If you want a list interface use nth, and if you want a map interface use get.

9:23 (that way vectors and linked lists can be swapped out for each other at will without needing to rewrite the code that accesses them)

9:24 gtrak: Wild_Cat, you can still swap out vectors and linked lists, though you might have to run seq on the vector

9:25 http://clojure.org/sequences

9:25 mprentice: i usually treat vectors as tuples. i haven't done any performance sensitive stuff so that list performance is a problem.

9:25 Wild_Cat: gtrak: whereas if you avoid get altogether you don't have to do anything other than replace the list with a vector (or the opposite) where it's instantiated

9:26 of course, if you find out a map is what you really needed you're screwed, but IME it's more common to swap lists/vectors than vectors/maps or lists/maps.

9:26 (then again, ME doesn't include any actual Clojure work, so...)

9:26 gtrak: Wild_Cat, ... they're all trees anyway

9:26 Wild_Cat: God is a hash map ;)

9:27 gtrak: anyways, you should probably check out Rich Hickey's seqs video: http://blip.tv/clojure/clojure-sequences-740581

9:28 Wild_Cat: gtrak: will do. Cheers.

9:30 jweiss: how is "tail position" defined? I'm returning a vector literal, and i'm calling recur inside the literal. but the compiler doesn't think that's the tail position.

9:31 gtrak: jweiss, if you want an accumulator, make an extra binding in the loop

9:31 like (loop [out [] input start] or something

9:32 jweiss: gtrak: i don't think i want an accumulator. i'm turning a list of trace log statements into nested vectors: http://fpaste.org/QXoo/

9:34 gtrak: jweiss, well that's not the tail position because it has to keep track of the prior stack frame to be able to build it up, if you can refactor it to use assoc-in, it'll work

9:35 jweiss: gtrak: i am not seeing how assoc-in helps, it's not a map, it's a vector

9:36 gtrak: it's how you update nested structures more easily

9:36 mprentice: gtrak: i'm not familiar with assoc-in, but it sounds interesting. can you point me to some examples?

9:36 gtrak: vectors are maps of ints to vals

9:36 jweiss: gtrak: ah ok i see what you are saying, i can accumlulate the vector and insert where necessary

9:37 gtrak: http://clojuredocs.org/clojure_core/clojure.core/assoc-in

9:39 looks like it won't automatically create the nested vector for you, it works best on maps

9:39 (assoc-in {} [:bob :bob2] :bob3)

9:39 ,(assoc-in {} [:bob :bob2] :bob3)

9:39 clojurebot: {:bob {:bob2 :bob3}}

9:40 gtrak: ,(assoc-in [] [:bob :bob2] :bob3)

9:40 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Key must be integer>

9:40 jweiss: gtrak: i think i don't even need recur, since i'm processing trace logs, if the fn call depth didn't blow the stack, my processing the log won't either.

9:40 gtrak: ,(assoc-in [] [0 1] :bob3)

9:40 clojurebot: [{1 :bob3}]

9:40 gtrak: jweiss, might as well do it iteratively if you can

9:40 chouser: right. currently to use assoc-in on vectors you need the vectors to exist already

9:40 gtrak: you don't want a time-bomb

9:40 chouser: ,(assoc-in [[]] [0 1] :bob3)

9:40 clojurebot: #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>

9:41 chouser: ,(assoc-in [[:x0 :x1]] [0 1] :bob3)

9:41 clojurebot: [[:x0 :bob3]]

9:41 chouser: there has been talk (but no action afaik) on an assoc-in-like thing that lets you specify how to create new collections

9:43 mprentice: gtrak: ahh i see. assoc-in seems related to a zipper, so you can pass in a path and do a deep udpate

9:43 gtrak: super nifty!

9:43 gtrak: assoc-in is cool stuff, try to write that in java

9:45 mprentice: jweiss: this might be hopelessly dated, but i would have fn processor take an accumulator param

9:45 jweiss: mprentice: that would seem to make the fucntion a lot more complex, since I'd also have to keep track of the current insertion point

9:46 seems like using recursion is what would make this a lot simpler

9:46 mprentice: jweiss: ah yeah i'm taking a closer look at the structure of what you're building

9:48 jweiss: mprentice: here's the same paste with the input i'm going to give it added: http://fpaste.org/Qm4S/

9:48 gtrak: jweiss, I assure you, any recursive algorithm can be made iterative :-)

9:49 jweiss: gtrak: i'm aware of that :)

9:49 http://fpaste.org/ybT2/

9:50 mprentice: iteration with immutable trees is the situation zippers were made for. clojure.contrib.zip-filter.xml

9:50 http://richhickey.github.com/clojure-contrib/zip-filter-api.html

9:51 jweiss: mprentice: yeah, i tried that first, but zipper docs are not clear on how i'm supposed to turn a leaf node into a branch and add a child

9:51 append-child just complains about child on a leaf node

9:52 mprentice: would it be terrible advice to do it recursively and leave a note to do it iteratively with a zipper? :P

9:53 ;; TODO: iterate with zipper for log file > 100KB

9:54 jweiss: mprentice: i don't think recursive could ever blow the stack, just by virtue of the data i'm giving it - it's stack data. if it was > maxdepth, the stack would have blown while creating the data before this fn could ever see it

9:54 but yeah i DID try to use zippers first

9:55 mprentice: jweiss: i learned how to use xml zippers because i was dealing with big-ish xml files :P

9:55 jweiss: mprentice: were you creating xml or parsing it

9:56 mprentice: jweiss: converting from one xml format to another

9:56 jweiss: the sort of thing xslt is supposed to solve but always makes me want to tear my eyeballs out whenever i have to use any programming logic

9:56 jweiss: mprentice: do you have an example you could point me to

9:56 chouser: If you're sure the data is small enough, a recursive solution is almost always prettier in Clojure than an iterative solution, especially if that requires manual use of zippers.

9:57 mprentice: chouser: indeed

9:57 jweiss: lemme see

9:58 gtrak: you could probably do tail recursion if you save off the data for later in a bunch of closures

9:58 chouser: I've been doing a lot of small tree rewriting at work recently and although seq-tree, walk, and zippers are all alluring, in the end a plain ol' recursive function ends up being succinct, flexible, and fast.

9:58 er, tree-seq

10:00 mprentice: chouser: i used walk a few months ago. if you have to update values inside an xml tree, it's soooo good.

10:01 chouser: yep

10:01 mprentice: jweiss: i have a file that walks through an xml tree and prints it out in a .dot file. i dunno how useful it is if you're not familiar with the input xml it's using.

10:01 jweiss: chouser: i ended up here because i'm writing a log file, and writing logs as a tree structure is bad because you can't know when to close open tags (or braces). so i elected to write the logs as a flat structure with the depth as one field in each entry. now i am trying to convert back to a tree

10:02 (after the file has been closed)

10:02 chouser: I didn't mean to detract from any of those. They each are very powerful in their place. Walk is expecially good with "mixed" trees of various clojure stuctures (maps, vectors, etc.)

10:03 jweiss: ah, so converting a sequence back into a tree.

10:03 I wrote a function for just such a situation, specifically to convert a sequence of XML SAX events into a DOM-like tree.

10:04 I haven't documented it properly. It deserves a talk or blog post.

10:04 mprentice: i also solved a very similar problem

10:04 where dependencies came in in any order, but had to be output in a specific order

10:06 jweiss: i would go the recursive route with a note

10:06 jweiss: mprentice: that's what i'm trying now :)

10:06 chouser: Not sure if seq-tree would be convinient when the input includes depth rather than up/down events: http://bit.ly/o8ArdK

10:06 mprentice: jweiss: so when it breaks later, you or someone else can shake your fist and say "damn you lazy asshole!"

10:07 jweiss: mprentice: i'm pretty sure it's safe to use recursion here. as long as someone doesn't try to use this function to process some other kind of data, which i don't see ever happening :)

10:08 chouser: it also has up/down events, i probably don't even need the depth, i just have a boolean which is whether the line is for a fn entry or exit

10:09 seq-tree might do what i want - looking

10:09 mprentice: jweiss: famous last words. "nobody will ever need more than 64K of stack..."

10:09 jweiss: mprentice: but my data is traced fn calls

10:09 how can processing them blow the stack but didn't blow the stack when the trace was run?

10:10 chouser: different JVM settings? :-/

10:10 jweiss: chouser: yeah, that is true

10:10 ok ok you guys win

10:11 mprentice: jweiss: i was advocating expediency! i was just also pointing out that it could potentially cause difficulties later

10:11 chouser: I agree with mprentice :-)

10:12 recursive is good! If your log parser blows up they can tweak their JVM settings and it'll work.

10:12 khaliG: (.darker (java.awt.Color. 100)) works as expected in the repl; but the same line in code gives Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: java.lang.IllegalArgumentException: No matching field found: lighter for class java.awt.Color - any ideas?

10:13 gtrak: maybe we can create a stackless clojure

10:13 jweiss get on it

10:13 jweiss: chouser: i'm not sure seq-tree would work, since i don't have any "node events", just enter/exit subtree

10:14 i guess i could pre-proccess the data to make it have node events

10:15 khaliG: oh i see, i was actually calling .lighter on nil - my mistake, nevermind

10:16 chouser: jweiss: if you either give up on seq-tree or manage to make it work, I'd be curious to see how far you get. seq-tree was written specifically for XML, but I'd like it to be as general as possible.

10:22 jweiss: your enter subtree event has all the details you would want for the subtree?

10:25 jweiss: chouser: no, my events are just fn enter and fn exit (the former has the fn name and args, the latter the return value)

10:26 so basically the enter has half the node info, the exit has the other half

10:27 chouser: hm.

10:28 jweiss: well, i'm not sure what a node is in this case, i suppose a node can be either the fn call or the return value

10:28 in which case each entry is either [enter-subtree node] or [node exit-subtree]

10:29 chouser: ,(seq-tree #(when (not= %1 :up) (vector %1 %2)) #{:up} identity [:a :b :up :c :d])

10:29 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: seq-tree in this context, compiling:(NO_SOURCE_PATH:0)>

10:29 chouser: oh, heh.

10:30 anyway, that has the down-event data in each node without pre-processing the seq

10:30 jweiss: chouser: cool i'll give that a shot

10:30 thanks

10:30 chouser: but it's missing data from up events

10:32 a key requirement for seq-tree was to be as lazy as possible. requiring the exit event of a subtree in order to return the subtree pretty well defeats that

10:32 but that doesn't mean it could work. hm..

10:34 yeah, seq-tree doesn't allow for the existence of any useful data in exit events. a weakness.

10:35 jweiss: chouser: i control the data being produced here, so i could easily change it - what do you recommend?

10:36 my only restriction is i can only write to the data on fn call/exit

10:36 so i could write [enter node] and then [node exit] ?

10:37 juhu_chapa: hi folks, i am a beginner. i have been reading some clojure code and sometimes i have found "->" and a do not understand how is used, somebody can help me?

10:37 jweiss: juhu_chapa: yeah that was pretty mindbending for me too when i first started

10:38 imagine your forms as those russian nested dolls. using -> lets you put the dolls side by side, and it'll automatically nest them all for you

10:39 http://revolutioniz.com/revolutioniz/wp-content/uploads/2010/04/russian_dolls.jpg

10:39 although that image is sort of backward, in clojure you'd put your smallest doll first

10:40 chouser: jweiss: possibly. Your best solution might still be your own recursive function. But I'd like to better understand the problem space of converting seqs to trees.

10:40 jweiss: Having data in the exit event makes perfect sense for your problem space, so I'm trying to think about how seq-tree could accomodate that.

10:47 gtrak: juhu_chapa, http://blog.fogus.me/2009/09/04/understanding-the-clojure-macro/

10:48 there's also a ->> that threads into the last spot

10:49 ,(-> 4 (conj 6) str)

10:49 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IPersistentCollection>

10:50 chouser: [4]

10:51 jkkramer: srid: prompted by your question a couple days ago about finding all projects that depend on X, i built this: http://clojuresphere.herokuapp.com/

10:51 gtrak: ,(-> [] (conj 4))

10:51 clojurebot: [4]

10:52 gtrak: ,(->> 4 (conj []))

10:52 clojurebot: [4]

10:52 gtrak: ,(conj [] 4)

10:52 clojurebot: [4]

10:52 gtrak: get it?

10:52 chouser: jweiss: (seq-tree #(when (symbol? %) {:name %1 :exit (:x (last %2)) :kids (drop-last %2)}) #{'up} identity (mapcat #(if (= 'up %) [(meta %) %] [%]) '[a b ^{:x :foo} up c d up up ^{:x :last} up]))

10:53 That uses mapcat to preprocess the event stream, putting a special node event before each exit event, which the 'parent' fn then extracts.

10:53 clumsy. seq-tree should provide the exit event to the parent function somehow.

10:54 jweiss: chouser: nice, only problem with that i can foresee is it would read my whole log into memory

10:54 Mike|home: Why doesn't Clojure perform tail call optimization at compile time like Scala does?

10:55 juhu_chapa: thank you very much to all

10:55 chouser: jweiss: yep. to process the first node, it would read to the exit event of that first node.

10:55 gtrak: Mike|home, recur will error at compile-time if it's not in tail position, that's better than doing it implicitly, no?

10:55 jweiss: chouser: i'm not sure that the solution i come up with won't end up doing that too, though :)

10:55 chouser: jweiss: after that, since it's a lazy seq, that first node could get GCed, but each whole node will be in memory

10:56 Mike|home: Do Scala people envy that feature, gtrak?

10:56 gtrak: who cares? :-)

10:56 Mike|home: Hahaha. Thanks. Question answered :)

10:56 chouser: Mike|home: It seems to me there is already plenty of confusion about what "tail position" means.

10:57 jweiss: yeah i asked about that an hour ago :)

10:57 chouser: Clojure's approach means when you're wrong you get a clean error that says you were wrong about tail position.

10:57 (and we all know how much Clojure concentrates on clean error messages. :-P)

10:57 Mike|home: chouser: I agree, that does help the developer an awful lot.

10:57 Haha

10:57 jweiss: apparently [1 2 (recur a b)] is not tail position because the overall vector is evaluated last, not the recur?

10:58 chouser: If Clojure converted tail-position recursive calls into 'recurs', when you're wrong you would get a runtime error, but only on sufficiently large data.

10:58 I wonder how much Scala code has stack overflows waiting to happen...

10:59 Mike|home: Hahaha, I never thought of that, chouser

10:59 chouser: jweiss: right. "tail" in this case doesn't mean "syntactically last"

11:00 jweiss: chouser: yeah that's what is confusing about "tail" since it sounds rather spatial to me, when really it's temporal

11:00 chouser: hm. maybe.

11:04 Only expressions which may wholly be returned by a form are in the tail position of that form.

11:05 * jweiss trying to process that ^

11:05 chouser: so in (let [a b, c d] e f g), only g is in the tail position

11:05 because none of b, d, e, nor f will be returned by the let

11:05 jweiss: chouser: ah so that is why literals are different

11:05 since what's returned is the entire literal

11:05 chouser: right

11:06 jweiss: maybe we should call it "return position" :)

11:07 chouser: so in (fn [a b] (prn :hi) (+ 1 2 3)) the call to + is in the tail position, but none of its args are.

11:07 cemerick: anyone know what an "intrinsic predicate" is?

11:09 chouser: cemerick: "Identity of relation may, *of course*, be taken to indicate an intrinsic predicate which the terms have in common" -- Bertrand Russell

11:09 cemerick: in other words, I have absolutely no clue.

11:09 cemerick: mmm, right

11:09 So, something between Russell and https://github.com/clojure/clojure/commit/e92978783e1ba7ac0e2617fdabfed576209d7fa4

11:09 approximately :-P

11:10 chouser: ha!

11:13 cemerick: http://java.comsci.us/etymology/type/intrinsic.html

11:14 synonym for "primitive type" I think

11:14 cemerick: Must have been introduced to improve clarity.

11:14 chouser: heh

11:15 cemerick: In any case, not knowing my ASM as comprehensively as I probably should, I've no idea what that code does.

11:16 chouser: That table is fascinating. It looks like it may be replacing calls to various static methods with special JVM opcodes

11:17 cemerick: Oh, not having to go through c.l.Numbers for stuff like shifts, I think…

11:17 right

11:17 chouser: had no idea that was in there.

11:17 cemerick: committed yesterday (!)

11:18 hugod: must be a bugfix then ;)

11:21 chouser: heh

11:25 juhu_chapa: guys, here with another beginner question: i am using the function read-properties from the contrib: (read-properties file-able)

11:25 after that how can i read the properties?

11:25 where are they?

11:26 technomancy: jkkramer: I've totally been wanting to build that for a while now

11:26 did you base it on the clojars sql dumps?

11:26 jkkramer: technomancy: me too. finally got around to it yesterday

11:27 technomancy: rsync -av clojars.org::clojars clojars

11:27 technomancy: slick

11:27 jkkramer: i wasn't sure how to get sql dumps, which would've probably been a lot less to download

11:28 technomancy: I wonder if that could be integrated into clojars at some point

11:28 jkkramer: i was wondering the same

11:28 chouser: clojars scares me

11:28 technomancy: http://meshy.org/~ato/clojars-test-data.sql.gz

11:28 jkkramer: is clojars under community control?

11:28 technomancy: chouser: as a codebase or as a service?

11:28 jkkramer: technomancy: is that kept up to date?

11:28 chouser: service. I know nothing of its codebase

11:29 technomancy: jkkramer: so far it's been _ato, but he's pretty open to having others help out. nobody's really taken him up on it so far though

11:30 chouser: the SPOFiness?

11:30 jkkramer: my first thought was to make a clojars patch, but there are so many forks & branches, i wasn't sure where to start

11:30 chouser: the unsigned, first-in-wins, namespace clashiness

11:31 cemerick: its use as a personal sandbox…

11:31 we've been through all this before, though

11:31 * clgv doesn't like that it's hard to figure out what's the official jar of a project on clojars sometimes...

11:31 coopernurse: juhu_chapa: read-properties returns a java.util.Properties object that you can reference

11:32 pjstadig: chouser: why does it have to be unsigned?

11:32 juhu_chapa: :O

11:32 thorwil: jkkramer: http://clojuresphere.herokuapp.com/ is remarkably well laid out :)

11:32 coopernurse: eg: (def p (read-properties "/tmp/foo.properties"))

11:32 juhu_chapa: is really simple

11:32 thanks coopernurse

11:32 coopernurse: (.getProperty p "my prop")

11:33 technomancy: jkkramer: does your site just check :dependencies or is it :dev as well?

11:33 jkkramer: thorwil: thanks

11:34 technomancy: both. the data is separated in the underlying store, but displayed combined

11:34 i wasn't sure off-hand how i wanted to provide a UI filter

11:35 technomancy: yeah, it's not a straightforward problem

11:35 jkkramer: maybe just a site-wide toggle in the header or something

11:36 technomancy: could also probably use a "see all" truncation widget

11:37 jkkramer: part of the reason we don't have more people hacking on clojars is that it's hard to set up with nailgun and the separate user account. hiredman has a branch to make all that go away

11:37 cemerick: pjstadig: Are there any signed artifacts in clojars?

11:38 pjstadig: cemerick: is there any reason they can't be signed?

11:38 technomancy: signing is the easy part; it's building up the web of trust that I wouldn't know how to do

11:39 pjstadig: the internet is pretty crazy out there

11:39 you can't even be sure the website you're visiting is the one you want

11:39 you have to be responsible

11:39 technomancy: maybe we could outsource that to diginotar

11:40 they've got some pretty cheap certs these days =)

11:40 cemerick: pjstadig: No, but that's not really the point.

11:40 chouser: I don't know that things in clojars *can't* be signed.

11:40 cemerick: As onerous as central's policies are, requiring all artifacts to be signed is unabashedly good.

11:41 ejackson: ooh ooh..... flights to get to the conj have dropped dramatically

11:41 it might even be possible :D

11:41 chouser: but what scares me is if I release a project with deps that are resolved by pulling code from clojars, it seems quite likely that someone using my lib could get exploit code from who know whom via clojars. Maybe there's something I'm unaware of that prevents that. I hope so.

11:42 technomancy: cemerick: so the point is not that it's coming from someone you trust, but that the artifact was signed by the same key as the one that signed earlier releases?

11:42 cemerick: technomancy: Right, you have a *shot* at determining legitimacy.

11:43 ejackson: gotta be there :-D

11:43 technomancy: it certainly would help in the event of a compromised server or the like

11:44 chouser: of course if we could depend on SHA-1's instead of maven coordinates, signing would be a lot less important -- ie, only an issue at dev time.

11:44 technomancy: I wonder if it would be feasible to add that kind of requirement mid-stream as it were

11:44 ejackson: yeah, if I come around early for the training I save 1,500 GBP on flights, which is nutso, so I just might

11:44 technomancy: we do have access to the scp outputstream, so we can insert any kind of deprecation warning

11:44 and once we separate releases and snapshots, the policy would probably only need to apply to releases

11:45 pjstadig: cemerick: all I'm saying is that jar signing is ostensibly a solution to this problem, so complain about jar signing, and not clojars

11:46 if you want to know whether you can trust a message (or jar) that comes through an untrusted channel, then use signing

11:47 cemerick: pjstadig: It's clojars' policies that are problematic. If people aren't signing artifacts as a matter of course (which no one will do unless required by the accepting repository), then there's no point.

11:47 chouser: pjstadig: but it's also a culture. a maven plugin that checkes for signed jars, plus use of it (including I suppose all the signatures I trust) in a lib I release still won't do any good if the deps I need aren't signed.

11:47 er right, what cemerick said.

11:47 cemerick: I can't very well lobby authors of my dependencies to practice good hygiene.

11:48 pjstadig: right, which means you have to be careful and specify to your build system that you only want signed jars

11:48 that's orthogonal to the clojars policy

11:49 it would be nice if every website used SSL and had a trust chain that went back to a CA i trusted, but somehow we manage to survive

11:52 cemerick: That's fine, if you are OK with never using clojars. If clojars doesn't require signed jars, then it will never contain signed jars.

11:52 pjstadig: cemerick: why can't you lobby the authors of your deps? if people don't know that they should be signing jars, then how will they know?

11:52 cemerick: Hopefully, deploying to central will become nearly as trivial as deploying to clojars soon.

11:53 pjstadig: chouser: i don't think that its as bad as you think, once someone claims an groupId on clojars no one else can push to it AFAIK

11:53 chouser: jweiss: actually, there may be a conflict between seq-tree providing access to the exit event from the parent fn and the ability to provide sufficient laziness.

11:54 technomancy: we've had a couple of instances where a misclaimed groupid has been reinstated to its rightful owner through manual intervention.

11:54 cemerick: pjstadig: Sorry, that's just absurd. Even the smallest of my (deliverable) projects involves transitive dependencies on dozens of libraries from different projects/authors.

11:55 * technomancy accidentally claimed org.clojure early on

11:55 jweiss: chouser: i could see that being the case. i'm still trying to write my own recursive fn

11:55 technomancy: despite it being a technical solution to a cultural problem, I think if the tools made it easy we should consider requiring signed releases

11:56 pjstadig: cemerick: i don't see how it is productive to complain about a problem, then not be willing to work to fix it

11:56 besides just getting everyone to sign jars is only the first step

11:56 just because you know its the same person pushing versions doesn't mean you can trust them

11:56 and even people you can trust can introduce nasty bugs

11:56 technomancy: yeah, it's necessary but not sufficient =\

11:56 pjstadig: it's just not as simple as you make it seem, cemerick

11:57 jkkramer: technomancy: are the clojars code changes being discussed on a mailing list, or ad hoc on IRC and such?

11:57 re nailgun & such, not signing

11:58 technomancy: jkkramer: there's a maintainers list: http://groups.google.com/group/clojars-maintainers

11:58 though I don't know if the scp changes are being discussed there yet; currently it's just a hiredman project

11:58 jkkramer: ah, there it is. didn't turn up via google

11:58 technomancy: though I am quite curious about it too

11:58 jkkramer: maybe a different colored background for dev deps?

11:59 jkkramer: technomancy: good idea

12:01 cemerick: pjstadig: The start of "fixing it" is a policy change IMO. Policy changes through discussion, debate, and convincing others. It's not like I can submit a pull request for such things.

12:08 srid: jkkramer: looks like irccloud ate my responses to your message. did you get them?

12:08 jkkramer: srid: no

12:09 srid: ah ok. i like the UI, pretty simple. i'm trying to set it up locally and `lein run -m clojuresphere.preprocess` raises java.lang.NullPointerException

12:10 juhu_chapa: guys, where can i find documentation to run a clojure app in the command line?

12:11 jkkramer: srid: the actual preprocessing steps are in a comment in preprocess.clj. haven't turned it into a runnable thing yet, since they are still a bit messy

12:11 manutter: juhu_chapa: are you using leiningen?

12:11 jkkramer: srid: note that you'll need to download a hefty amount of data to do it - more than a gig from clojars, and thousands of github calls

12:12 hugod: anyone know where strint is in 1.3?

12:12 srid: jkkramer: how long would that take on average? and is the 'update' faster for the github calls?

12:13 technomancy: jkkramer: how much did you find that was available only via github and not clojars?

12:13 cemerick: hugod: "where"? Still in old contrib, AFAIK.

12:13 I think it was OK'd for transition, but I haven't gotten to it.

12:13 technomancy: I'm surprised you implemented both sources already for a project that's a day old =)

12:14 cemerick: Insofar as Rich et al. have said that it's not likely to make it into core, I may just continue development of it outside of the contrib process.

12:14 hugod: cemerick: ok, it was listed under core.incubator on the library names page

12:15 cemerick: oh really?

12:15 * cemerick goes to look

12:15 jkkramer: srid: 15-30 mins maybe. updates are still slow, since there's no easy way to find out which repos changed. i would be reluctant to run the github fetching more than once a day or so, to avoid hitting rate limits

12:15 juhu_chapa: manutter: no, i am using enclojure.

12:16 cemerick: huh, lookit that

12:16 manutter: Hmm, enclojure, I've never built a standalone jar with that...

12:17 jkkramer: technomancy: Raynes' github api helped: just searched for "clojure" with language "clojure"...which leaves some repos out, like clojure itself (written mostly in java)

12:17 cemerick: hugod: I'll have to see what's up there. IIRC, you had some ideas for strint improvement, correct?

12:17 Raynes: jkkramer: Oh cool, you made use of that?

12:17 I was wondering if anybody else on the planet ever would.

12:18 manutter: juhu_chapa: the basic idea is to build a standalone jar file that includes all the libs/jars that your clojure code depends on (including the clojure jar itself)

12:18 jkkramer: technomancy: i haven't run a "difference" query yet to check which exist on one but not the other. there were way more projects on clojars, but that may be because it includes all past versions

12:18 technomancy: jkkramer: naturally

12:18 jkkramer: Raynes: http://clojuresphere.herokuapp.com/clj-github :)

12:18 manutter: juhu_chapa: but I'm not sure what the specifics would be

12:18 technomancy: jkkramer: end-user applications don't necessarily end up on clojars, so there is that

12:19 jkkramer: technomancy: right. only open source

12:19 hugod: cemerick: pallet added some stuff on top to do runtime interpolation - I'll probably just copy the code into pallet.common along with all the other contrib stuff used in pallet that isn't in the new contrib.

12:19 jkkramer: maybe i should say "graph of the open source Clojure ecosystem"

12:19 hugod: cemerick: longer term, I might just switch to using one of the mustache libs

12:19 squidz: what's so good at paredit?

12:19 cemerick: hugod: using eval?

12:20 Raynes: jkkramer: Since someone is actually using it, I'll give it a once over this weekend and see if I can't update/fix any nastiness.

12:20 hugod: cemerick: yes

12:20 jkkramer: Raynes: worked fine for my modest needs

12:22 Raynes: jkkramer: Am I right in that every API function requires a auth argument? That could probably be remedied.

12:23 srid: jkkramer: would be nice to sort the 'Dependents' list itself by their number of dependents. enlive has 63 dependents, and I was most interested in the popular dependents.

12:23 Raynes: It's kind of pointless, given that not everything requires authentication. Hence your very empty github-auth map.

12:23 jkkramer: Raynes: i didn't use auth -- just gave {} as the argument. seemed to work fine

12:23 right

12:24 Raynes: Also, I guess I need to go over my gist stuff, since it was written before the gist API was documented.

12:24 jkkramer: srid: yeah, i will probably do that. or privde options for sort criteria: most-dependents, last-updated, alphabetical, etc

12:24 Raynes: Anyways, this is a lovely website.

12:24 Happy to have helped.

12:25 jkkramer: thanks, it saved me a good chunk of time :)

12:25 * jkkramer starts a to-do list

12:27 srid: will take a look at clojuresphere when i get back home, and contribute something. good way to learn clojure.

12:27 juhu_chapa: manutter: i have installed lein, could you describe please the process of creating a jar?

12:28 manutter: juhu_chapa: ah, that's an easy one: "lein jar" will create a jar with just your app code in it, and "lein uberjar" will create a standalone jar that you can run with "java -jar whatever-you-called-your.jar"

12:30 jkkramer: technomancy: 1384 distinct artifact ids for github projects, 879 of which do not exist on clojars. 1641 ids for clojars, 1136 of which do not exist on github. 505 that exist in both.

12:31 juhu_chapa: manutter: i have created myproject/src directory and i wrote there a helloworld.clj, can you post me a project.clj using clojure 1.2.1 and contrib 1.2?

12:32 manutter: juhu_chapa: if you create your project with "lein new myproject" it will set you up with the right project.clj file automatically

12:34 juhu_chapa: manutter: ohh, let me see.

12:35 srid: i did not realize that i can host more than one app in heroku for free. thought the free 1 dyno == 1 app.

12:36 this makes heroku irresistibly for hobby projects

12:36 irresistibly attractive*

12:38 juhu_chapa: manutter: project creation succeded, there is a core.clj in src, what is the purpose of that file?

12:38 manutter: That is the default source code file, you'd normally put your "hello world" code in there

12:39 but you can delete it if you don't like it, and put your code in a different file if you put a :main def in your project.clj

12:40 There's a lot of leiningen documentation in the example project.clj file (https://github.com/technomancy/leiningen/blob/master/sample.project.clj)

12:41 juhu_chapa: manutter: really simple, thank you for your help.

12:41 manutter: anytime

12:49 jkkramer: srid: i had the same realization recently. the cedar stack is relatively unrestricted (300+ MB ram, threads, etc). not much persistent storage, though

12:51 gtrak: srid, someone's been trying to persuade me to do that, any advantages over a local jetty for development?

12:53 srid: gtrak: ?

12:54 gtrak: srid, to check out heroku i mean

12:54 srid: hmm, for development I use jetty via 'lein ring server'. heroku is only for deployment.

12:55 and deploying clojure to heroku is pretty easy. mostly just need a single-line file `Procfile`

12:55 gtrak: srid, so you can show off some stuff I guess, but can you really do anything substantial without storage and db?

12:56 srid: heroku does provide postgresql database (and mongo and others via external addons). only 5MB is free. i don't know about storage; i can probably live without it.

13:05 juhu_chapa: manutter: i am getting the following error: Exception in thread "main" java.lang.ExceptionInInitializerError (NO_SOURCE_FILE:0), what i have missed?

13:05 this when i run: lein compile inside the project dir

13:06 manutter: Can you post your source code in a gist (gist.github.com)?

13:06 I don't think you need to do lein compile, by the way-- lein uberjar will create the standalone for you

13:09 gtrak: does lein uberjar do AOT on everything?

13:10 juhu_chapa: manutter: git clone git://gist.github.com/1198232.git gist-1198232

13:10 manutter: gtrak: I don't think it needs to, does it? Uberjar will include clojure, which will compile the scripts dynamically (I think)

13:11 amalloy: it compiles whatever you say needs to be compiled

13:12 juhu_chapa: a few minutes ago you were asking how to create a project/jar; that's a very strong indicator that you don't need to compile anything

13:14 manutter: juhu_chapa: I don't think you need (:gen-class) in your namespace, and it might be messing you up. You can just run your hello-world code as straight clojure

13:14 (from within the jar)

13:14 juhu_chapa: amalloy: i am trying to break my OOP mindset.

13:15 manutter: I don't think the (read-properties) should be a problem, but that would be the second thing I would comment out if it were still crashing

13:15 amalloy: manutter: first thing i'd do. that's unlikely to work

13:15 manutter: but I'd start by commenting out the :gen-class line and then running lein uberjar

13:16 amalloy: (defn properties [] (read-properties ...)), and then use (properties) instead of just properties

13:17 manutter: amalloy: you're doing that because properties might change at runtime, I'm thinking?

13:17 amalloy: no, because you can't really define the properties at compiletime it's not an object that can be embedded into java code

13:18 hm. my - key seems to be broken? i left out two of them in that

13:19 manutter: a java program that wanted to do the same would have to look like: class Foo { static { properties = ...}} - that's happening when the app starts up, not when you compile it

13:19 you can't just put Some Random Object into the bytecode; you have to include the code to create the object instead

13:20 manutter: amalloy: ah, ok, I wouldn't have expected that (due to my Java inexperience) but I can see it now that you explain it.

13:22 When I try (read-properties) at the repl, it gives me a file-not-found error for "app.properties" -- sounds like it's actually looking for a config file to parse.

13:22 amalloy: well yes

13:22 manutter: maybe I should look up the docs on that puppy :)

13:22 gtrak: manutter, try putting it in the resources dir in your leiningen project

13:22 amalloy: eh, just an empty file will be a legal .properties file

13:23 manutter: gtrak: I'm not the one that's using it, I'm just trying to help juhu_chapa figure out the exception he's getting on lein compile

13:24 ,(doc clojure.contrib.java-utils/read-properties)

13:24 clojurebot: Pardon?

13:24 manutter: clojurebot: :P

13:24 clojurebot: Pardon?

13:24 amalloy: manutter: you can also probably repro if you replace (read-properties "foo") with (java.util.Properties.)

13:25 gtrak: amalloy, so all the things in an ns are compiled to a static initializer block? what determines the order classes are loaded?

13:25 amalloy: (a) no, i'm pretty sure that's not how it works, and (b) i dunno

13:26 gtrak: ah ok, I'm trying to get an intuition for that stuff, but maybe it's best just to dig in

13:26 amalloy: mostly, you should only put functions at the top level, is the answer

13:27 or clojure objects, which i guess can be embedded because they can be shimmed in with pr-str/read? i'm not sure about that. but you can't put arbitrary java objects at the top level if you want to AOT-compile stuff

13:28 juhu_chapa: guys i commented out the :gen-class line and the read-properties line and i am still getting the no source error

13:34 manutter: juhu_chapa: what are you typing on the command line? Just "lein compile"?

13:36 juhu_chapa: the No Source message just means that the error is not located in a source file

13:36 i.e. before it gets to your program code in other words

13:38 juhu_chapa: it's also possible that you have more than one Clojure jar in your classpath, or some other java lib dependency problem

13:41 juhu_chapa: yeah: lein compile or lein uberjar throws the same error

13:41 is there a java version issue with clojure? i am using openjdk7

13:42 amalloy: uhhhh i don't know if 7 is working

13:42 i think it probably is, but i'm not sure

13:45 chouser: 7 is being added to the test matrix. Haven't seen any results yet.

13:47 pjstadig: there's no problem with java7

13:47 not that I've seen

13:48 manutter: pjstadig: sun java7 or open java7?

13:48 pjstadig: what's the diff

13:49 amalloy: well, they're different :P

13:49 eg, cljs doesn't work on openjdk because the compiler is depending on some internal undocumented class

13:50 or, at least, that was the state of things for a while after cljs was announced. maybe someone's fixed that; the point is they're not the same

13:50 pjstadig: yeah i'm not talking about clojurescript i'm talking about clojure

13:53 arohner: pjstadig: openjdk doesn't contain a bunch of stuff due to licensing

13:53 technomancy: arohner: that was true of 6 (mostly font rendering libs) but I don't think it's true of 7

13:54 arohner: technomancy: interesting. Did they get the licenses sorted out, or drop the features? I seem to recall some sound & graphics libs as well

13:55 technomancy: I don't know for sure; I think headius might.

13:56 juhu_chapa: guys, the problem was openjdk7.

13:56 now i am using sun jdk 6

13:56 i all works

13:58 by the way the :gen-class is needed in order to generate the class inside the jar. after run lein uberjar, just typed: java -jar myjar.

14:05 headius: openjdk is 100% open source now

14:06 the IcedTea replacements for the proprietary bits were merged in some time ago, I believe

14:13 manutter: juhu_chapa: Ah, you need the :gen-class to compile the -main function, I forgot about that, sorry!

14:13 gtrak: I'm noticing it's too easy to reinvent stuff when there are elegant ways to do something. I'd love to see a use-case wiki feature added to clojuredocs, anyone thought about anything like that?

14:14 manutter: gtrak: the hard part is figuring out how to classify the use cases so you can find the one that matches what you want to do (or *think* you want to do, which isn't always the same thing ;)

14:15 gtrak: you can get pretty far with text search, but I see what you're saying

14:26 I have a question about 'separate' in this code: https://github.com/amalloy/useful/blob/develop/src/useful/seq.clj

14:26 is using a for lazier than doseq? also, does the vec call defer evaluation?

14:27 hiredman: doseq is not lazy at all

14:27 amalloy: uh. a for is entirely different from doseq

14:27 in that doseq doesn't return any results

14:27 hiredman: an vec builds a vector, so obviously not lazy at all

14:27 and

14:27 gtrak: it builds a lazilypersistentvector, does that have any implications?

14:28 amalloy: no. but i never really understood LPV, so if anyone knows feel free to jump in and tell me about that

14:28 hiredman: vectors are not lazy

14:29 chouser: LPV doesn't really exist anymore

14:29 hiredman: it just has static methods for creating pvecs

14:30 chouser: It used to be a collection type, before transients I believe.

14:30 But I'm not sure it ever would have had anything to do with this question.

14:31 hiredman: the only things that are lazy are sequences constructed using lazy-seq

14:31 chouser: 'separate' there is not in any way lazy, and couldn't be written using doseq without using some kind of mutable object.

14:31 gtrak: ^^^

14:33 it could have been written with loop/recur, which might be more effecient.

14:35 gtrak: more generally, how do you reason about how lazy something is?

14:35 hiredman: I just said

14:35 the only things that are lazy are sequences constructed using lazy-seq

14:35 gtrak: map does that too, yes?

14:36 hiredman: why don't you check?

14:36 (type (map ...))

14:36 gtrak: set a man on fire and he'll be warm the rest of his life

14:37 ,(type (map identity []))

14:37 clojurebot: clojure.lang.LazySeq

14:37 amalloy: chouser: i think you're misreading the implementation of separate; it eagerly produces two sequences, both of which are (mostly) lazy

14:38 chouser: amalloy: ah, indeed. thanks for the correction.

14:39 amalloy: say, chouser, has any version of data.xml been actually released?

14:39 it would be nice to have a 1.3-compatible replacement for prxml: 4clojure could finally get off 1.2.x

14:40 gtrak: so ok, the for creates a lazy seq, does running vec trigger the evaluation of it, whihc returns two lazy seqs (from the map calls)?

14:40 that's what it looks like to me

14:41 hiredman: I do feeling like burning things down this morning

14:41 Raynes: hiredman: I can give you a list of things I'd like to see burned down.

14:45 amalloy: gtrak: yes

14:47 gtrak: amalloy, coolio

14:48 chouser: amalloy: no, none released. I was supposed to look at that this weekend.

14:48 played portal-2 instead.

14:48 amalloy: hah. wholeheartedly excused

14:48 gtrak: you probably should look at the official https://github.com/flatland/useful rather than my fork. actually, my fork probably shouldn't exist

14:49 chouser: amalloy: I need to look at how we're handling comment, cdata, etc. elements, and glance at my todo list

14:49 then it's just docs. We're really pretty close.

14:50 gtrak: amalloy, yea, I was just curious and I saw an implementation of separate, followed it down the rabbit hole since a couple of folks I know were arguing about it

14:50 amalloy: great

14:51 gtrak: I also found out about group-by through that discussion

14:52 arohner: has anyone gotten swank running over heroku?

15:09 amalloy: chouser: well, let me know when you pick a format for representing comments and such; i'll probably want to add a sexp/prxml-ish conversion to that format

15:13 chouser: amalloy: ok. It was gread that prxml supported them -- I don't want it to be a regression moving to data.xml

15:13 great

15:15 amalloy: yeah, agreed. i wonder how you can do it with tag/attr/content - in theory you could just use a namespaced-keyword for the tag, but if you want namespaces to correspond to xmlns declarations, then...i dunno, metadata somewhere?

15:18 chouser: yeah, not sure yet.

15:24 arohner: has anyone got postgres working on heroku?

15:28 lobotomy: hmm, i finished my chess problem solver, and tried to make it multithreaded. run the first round separately, make an agent for each case on the first round, run all the agents recursively from their different starting points

15:28 technomancy: arohner: abedra wrote an article on it; it's in their official docs

15:28 lobotomy: is this a good way do to that?

15:28 arohner: technomancy: yeah, I'm having trouble connecting to the DB

15:28 I think I'm doing what the docs say, and it isn't working.

15:28 lobotomy: if it is, how can i make it actually work? :) my code seems to simply hang after a while

15:31 mprentice: lobotomy: the chess problem space is huge. that approach will have too many threads.

15:31 gtrak: lobotomy, you do know chess is pretty hard to compute fully, yes?

15:31 mprentice, agents use a thread-pool

15:32 lobotomy: yeah, but i'm only making one agent per each choice of square on the _first_ round

15:32 mprentice: gtrak: oh, well, too many agents anyway

15:32 gtrak: yea

15:32 lobotomy, well you make an agent... then you send work to it

15:32 lobotomy: in my example there's one queen and 2-3 of each other piece (but no pawns); so it's basically 64 agents. each agent puts the queen on a different square and then recurses with the rest

15:33 gtrak, as i said, i did that but then it hangs after 2836 solutions

15:34 gtrak: lobotomy, using send or send-off?

15:34 lobotomy: send

15:34 gtrak: hmm, well you can use visualvm to get a stack trace

15:34 lobotomy: thinking maybe i should somehow ensure there's at most say 2-3 agents running at the same time?

15:34 gtrak: lobotomy, I'm not sure 1 agent per square is a good mapping

15:35 lobotomy: is this doable easily with some core function or something, or should i keep track manually?

15:35 me neither, but it's the simplest one, so i just tried that :)

15:35 hiredman: something to keep in mind is sends and send-offs inside an agent action don't run until the action is completed

15:36 lobotomy: guess i should put the squares in a list and feed the first n squares of the list to n agents at a time, or something

15:38 but why does it hang after a handful of solutions?

15:38 robermann: hello. which is the default javadoc site for clojure's Java classes?

15:38 gtrak: lobotomy, to characterize the hang, you need a thread dump

15:38 lobotomy: if there's too many agents, i'd hope it would crash instead, or give some indication of the too-maniness

15:39 gtrak, fair enough. so this suddenly became complicated ;p

15:39 will check that out later, cheers

15:39 gtrak: generally how concurrency goes

15:42 amalloy: robermann: there's not a lot of javadoc for those

15:44 and it's fairly rare that you'd need any. what are you looking for?

15:48 robermann: just trying to understand why (def aaa {:a 'a :a 'nnn } ) fail :) - well I know because fails, but I was thinking to check PersistentHashMap's javadoc

15:49 hiredman: robermann: what do you mean fails?

15:49 robermann: ,(def aaa {:a 'a :a 'nnn } )

15:49 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Duplicate key: :a>

15:49 robermann: the duplicate key

15:49 hiredman: robermann: and?

15:50 seems like the reason it failed is pretty obvious

15:51 lobotomy: i think he's asking where that's documented

15:51 robermann: yes it is obvious :) but I was checking if the corresponding Javadoc documents it

15:51 should be http://pacific.mpi-cbg.de/javadoc/clojure/lang/PersistentArrayMap.html#createWithCheck%28java.lang.Object[]%29 ?

15:52 now I'm forcing to be in Java-mode

15:53 maybe it is a stupid expectation, but I was thinking that putting a key in a map should override an already existing one

15:54 as it is in java maps

15:54 cemerick: robermann: They do.

15:54 raek: assoc does that. you only get the exception for literals

15:54 hiredman: robermann: it will, but for literals it is generally considered a mistake, so it throws an error

15:54 cemerick: ,(assoc {:a 5} :a 6)

15:54 clojurebot: {:a 6}

15:56 robermann: cool! yes it is generally a mistake, and I was just trying it. So is this check executed only on literals?

15:56 cemerick: exactly

15:56 same with sets

15:56 ,#{5 5}

15:56 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Duplicate key: 5>

15:57 robermann: yes, sets are quite obviuos for me

15:57 cemerick: well, a map's keys are a set, so the same semantics should apply :-)

15:58 robermann: yes but in Java you override a key value, you don't get blocked in the insertion

15:59 cemerick: robermann: The same thing happens with assoc (see above). Java doesn't have map or set literals, so it doesn't need to contend with what to do in that circumstance.

16:01 TimMc: ,#{5 (+ 1 4)}

16:01 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Duplicate key: 5>

16:02 robermann: yes. I was inquiring if this check of not duplicity ( https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentArrayMap.java#L67 ) is documented in javadoc

16:02 TimMc: set literals, not literals of sets

16:02 s/of/in/

16:02 lazybot: <TimMc> set literals, not literals in sets

16:02 cemerick: Right, it's all values by the time the corresponding data structure is being built

16:04 robermann: Probably not.

16:04 TimMc: cemerick: So, safer to do ##(set [5 (+ 1 4)])

16:04 lazybot: ⇒ #{5}

16:04 cemerick: safer?

16:05 oh, I see what you mean

16:05 TimMc: Yeah, if you are using a set literal that is not made of literal values.

16:05 robermann: ok thanks

16:06 TimMc: Sounds like that could really bite someone.

16:06 cemerick: Seems like a strange thing to worry about. If you end up getting an error you don't expect, then you probably aren't clear on what the offending expression is doing.

16:06 TimMc: Well, it isn't my place to surmise what use someone might have for sets.

16:07 cemerick: Just working around it by using `set` seems counterproductive. That's why the literals have that guard to begin with.

16:07 TimMc: That guard is intentional?

16:08 cemerick: Preventing the duplicate values in literal sets or keys of literal maps? Yes, certainly.

16:08 TimMc: Oh, I see -- it is in Clojure.

16:08 robermann: cemerick: when I have an error in Java, the first thing I do is to check its javadoc

16:08 TimMc: I think it makes perfect sense in ,aps.

16:08 *maps

16:09 cemerick: robermann: Are you using the Clojure data structures from Java?

16:09 TimMc: ,(doc #{}) :-P

16:09 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Symbol>

16:10 TimMc: Where is the canonical definition for behavior of literals?

16:11 cemerick: Official documentation, anyway: http://clojure.org/reader

16:11 amalloy: &(doc read-string)

16:11 lazybot: ⇒ "([s]); Reads one object from the string s"

16:11 cemerick: amalloy: smartass :-P

16:11 robermann: cemerick: no, I'm studying clojure, and knowing that its core is written in Java I was checking its javadoc

16:11 TimMc: heh

16:11 cemerick: robermann: ah; you'll find it to be very thin indeed :-)

16:11 amalloy: cemerick: a real smartass would have used $source read-string

16:11 but this way i get to make the point that it's not really documented, so maybe you're right

16:12 TimMc: amalloy: You're just a fake smartass?

16:12 cemerick: There's a lot in the reader that isn't formally documented.

16:12 * TimMc is a stickler for documentation, and is also slightly belligerant today for no apparent reason

16:13 cemerick: TimMc: As am I, on both counts.

16:13 TimMc: I'm choosing to blame the weather for the latter.

16:14 robermann: maybe you could write an "internals clojure" book ! I should be one of your readers :D

16:15 jkkramer: i've been bitten by this: ##(apply hash-map [:foo "bar" :foo "baz"])

16:15 lazybot: java.lang.IllegalArgumentException: Duplicate key: :foo

16:15 cemerick: robermann: We cover some of the undocumented bits in the book. Hardly "internals", but certainly some of the niceties (2r11, etc)

16:15 jkkramer: you can partition it up into vector pairs, but that's more typing

16:16 robermann: which book?

16:17 cemerick: robermann: http://oreilly.com/catalog/0636920013754/

16:17 TimMc: I suppose the workaround there is ##(into (hash-map) [[:foo "bar"] [:foo "baz"]])

16:17 lazybot: ⇒ {:foo "baz"}

16:17 chouser: 2r11 is documented

16:18 robermann: cool I bookmarked it!

16:18 TimMc: ,2r11e10

16:18 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: "11e10">

16:18 cemerick: chouser: look at that, it is! I don't think it was when I wrote that part in the book.

16:18 chouser: heh

16:18 TimMc: Hrmph, I can never keep number literal formats straight.

16:19 chouser: 2r11 is also detailed on page 22 of http://joyofclojure.com/ :-)

16:20 cemerick: TimMc: That'd be a long binary string, but in any case, you can't use an explicit radix for decimals.

16:21 TimMc: ,2r11

16:21 clojurebot: 3

16:21 TimMc: ,2r1.1

16:21 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.NumberFormatException: Invalid number: 2r1.1>

16:22 TimMc: I see. And e notation turns it into a float?

16:23 Wait, no -- I *was* imagining 1e9 notation in Clojure.

16:27 robermann: ah they are binary literals

16:28 cemerick: ,36r9

16:28 clojurebot: 9

16:28 TimMc: n-ary literals

16:28 cemerick: whoops

16:28 ,36r9z

16:28 clojurebot: 359

16:28 kwertii: anyone have any experiences (good or bad) using CouchDB or Mongo as the backend persistent data store to a Clojure app?

16:29 cemerick: Both are commonly used.

16:30 kwertii: cemerick: but are they good or bad? common doesn't mean good..

16:31 robermann: chouser: by the way I discovered the "key duplicated error" when trying your "(str (build-move :from "e2" :to "e4"))" example (pag 205)

16:31 cemerick: kwertii: I mean, both data stores are used commonly with good results. Whether you prefer one or the other isn't related to Clojure; there are quality client libs for both.

16:31 kwertii: cemerick: ok, cool, thanks

16:31 cemerick: I prefer couch, but for reasons entirely unrelated to Clojure.

16:31 ibdknox: redis!

16:32 robermann: chouser: I tryied a (build-move :from "e2" :from "fake" :to "e4") move to see if what would happen

16:32 cemerick: Er, perhaps not entirely true -- I think there are a number of relevant parallels between the broad philosophies behind couch and Clojure.

16:33 kwertii: cemerick: the Mongo project's "couch vs mongo" page essentially says directly that the only reason to pick Mongo is if you need ultra-high performance at the expense of robustness

16:33 cemerick: kwertii: link?

16:34 kwertii: cemerick: http://www.mongodb.org/display/DOCS/Comparing+Mongo+DB+and+Couch+DB (ok, not directly, but that's what I got out of it at a glance)

16:35 "if we had very high performance requirements we would use Mongo... for a problem with very high update rates, we would use Mongo... in contrast to the above, couch is better when lots of snapshotting is a requirement"

16:35 chouser: robermann: interesting.

16:35 cemerick: kwertii: That interpretation is probably not generous enough, but I won't argue with it.

16:35 kwertii: "Philosophically, Mongo is very oriented toward performance, at the expense of features that would impede performance. "

16:36 chouser: and it's written in C++, so you know it's balzing fast.

16:36 kwertii: "Problems requiring high update rates of objects are a great fit"

16:36 chouser: I meant blazing, but either will do.

16:36 scgilardi: one of those provocative faux typos...

16:37 chouser: we use mongo at work and are happy with it, afaik.

16:37 cemerick: Couch is moving towards an easily partitionable backend as well. BigCouch does that already today.

16:38 kwertii: cemerick: it seems (at a glance, haven't looked into it in depth) that if your application doesn't absolutely require the latest realtime data at every instant, you can use Couch replication to scale

16:39 cemerick: kwertii: True enough, and that's what bigcouch does. Rolling your own partitioning scheme is not fun, tho.

16:40 kwertii: my other question for those of you who are doing this.. it occurred to me that I can set a watch on a ref to a map or a record, update the map anywhere as a normal Clojure map, and rely on that watch to propagate the changes to the DB. is this reasonable?

16:40 TimMc: chouser: C++ isn't a cure-all for performance, of course. I remember the professor posting performance results by language for a semester project, and C++ came in dead last, with Python and Java in the lead. :-)

16:41 chouser: TimMc: I'm totally trolling. Feel free to read as much sarcasm into my statement as you'd like.

16:41 C++ apps are fast, except when they're not.

16:41 technomancy: what are you talking about; c++ is totally balzing fast

16:41 TimMc: chouser: Wasn't entirely sure.

16:41 cemerick: kwertii: very, yes. Functioning as a write-behind log, in that case.

16:42 arohner: kwertii: as long as you're ok with losing data sometimes

16:42 TimMc: chouser: It does tend to have a fast startup time. :-P

16:42 * cemerick is totally going to reuse 'balzing fast'

16:42 arohner: like on shutdown or quick power-off

16:42 chouser: TimMc: indeed

16:43 kwertii: cemerick: how do you handle the reverse case, changes in the DB that need to be propagated to the application? I haven't looked into Couch enough to know whether it has the concept of triggers. I imagine you could fire off a notice to your Clojure app saying "update record x" if it does, or periodically expire data structures somehow if it doesn't

16:43 TimMc: That's an interesting use-case for metadata.

16:43 technomancy: cemerick: best freudian slip I've seen in a while

16:44 cemerick: kwertii: look in the couch wiki for info on the _changes feed

16:44 TimMc: technomancy: While reading out loud the other day I accidentally said "penetrate the thong" (throng)

16:45 That was the best I've done in a while.

16:45 kwertii: arohner: yeah, that's not ideal, of course, but making it more robust is a diminishing-returns problem.. you could never re-use the map and reload it from the DB every time, I suppose, at a huge performance hit that's probably not worth it unless you're trading stocks in realtime or something like that, in which case you'd have practically unlimited resources for hardware anyway

16:45 technomancy: this is even better since it's an example of the speed/consistency trade-off

16:45 kwertii: cemerick: so it can do that.. cool, thanks

16:46 cemerick: kwertii: yeah, you can abuse couch as a message queue pretty easily

16:47 kwertii: cemerick: ideally I'd like an AllegroCache like solution where the db is fused transparently to the data structures

16:48 cemerick: kwertii: Of course, people have spent lifetimes pursuing that.

16:48 kwertii: heh

16:48 and for only the price of a new sports car plus a warrant for your firstborn child, Franz will sell it to you (in CL only)

16:49 cemerick: Plus a new sports car each year, of course.

16:50 robermann: bye

16:52 hiredman: kwertii: those kind of solutions tend to be in the cache space, not the db space, inifinispan provides a more or less transparent shared concurrent hashmap

17:05 acagle``: /

17:16 jweiss: is there a way to read from an input stream and write to a file without using the verbose java way with the byte array or similar?

17:17 amalloy: jweiss: clojure.java.io/copy

17:18 jweiss: amalloy: aha, thanks

17:26 hiredman: ~clojure

17:26 clojurebot: clojure is the bestest programming language available.

17:26 hiredman: ~clojure

17:26 clojurebot: clojure is cheating

17:26 hiredman: ~botsnack

17:26 clojurebot: Thanks, but I prefer chocolate

17:26 hugod: do dynamic vars inherit thread specific bindings in 1.3?

17:29 hiredman: hugod: only via send, send-off, and possible future and pmap

17:30 only if you create or send work to the thread via some clojure mechanism

17:30 https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L1885

17:31 michaelr525: anyone knows whether amazon is charging for the requests when uploading files to s3 from ec2 in the same region? I know they don't charge for data transfer..

17:31 hugod: hiredman: thanks

17:40 writing library code that works on 1.2 and 1.3 is "interesting"

17:51 cemerick: michaelr525: all transfer in is free

17:52 michaelr525: hmm

17:52 I'm asking about ec2->s3

17:53 Not home->s3

17:55 that's what written on their site: "There is no Data Transfer charge for data transferred between Amazon EC2 and Amazon S3 within the same Region"

17:55 But nothing like this is written regarding requests

17:55 cemerick: michaelr525: Scroll down to "data transfer pricing" http://aws.amazon.com/s3/pricing/

17:56 oh, per *request* pricing you mean

17:56 michaelr525: yep

17:56 cemerick: The per-request pricing applies no matter where you're operating from AFAIK.

17:57 michaelr525: that's what I thought, just wanted to make sure.

17:57 srid: what is the buzz-word replacement for saying "clojure". eg: instead of I saying "here is a clojure-based sample app demonstrating our enterprise feature XYZ" I want to say it without frightening folks using the word "clojure". perhaps, i could include the word JVM or even Java as these are enterprise-friendly.

17:58 amalloy: s/clojure-based/<intentionally left blank>

17:58 seems like if you don't want to mention clojure there's not much need to put any words in that space at all

17:58 zilti: Maybe "JVM-based functional sample app"?

17:58 srid: one alternative, yes. but I want to capitalize on this somehow :-)

17:59 amalloy: "sample app we wrote in five minutes instead of five weeks"

17:59 hiredman: you want to capitalize on clojure without saying clojure?

17:59 zilti: Haha nice

17:59 hiredman: sounds dumb

17:59 srid: zilti: the word 'java' is missing though. (folks may not understand what 'jvm' means)

17:59 cemerick: "Here's our app. It runs on Java."

17:59 amalloy: just tell them about this cool language that's a great replacement for java, Erujolc

18:00 srid: i have mentioned clojure several times in our meetings, and the response like "meh".

18:00 amalloy: then, months later, when you unveil clojure, they will be astonished

18:00 zilti: Another reason for maybe not studying computer sciences: You'll have to convince some dumb businessmen knowing nothing but economy theories.

18:00 s/convince/convince all your life

18:00 lazybot: <zilti> Another reason for maybe not studying computer sciences: You'll have to convince all your life some dumb businessmen knowing nothing but economy theories.

18:01 zilti: Nice bot

18:01 coopernurse: srid: so is the real issue that you need a way to sell the use of clojure to your org? or something else?

18:03 srid: coopernurse: i am using clojure (in a sample app) to demonstrate a feature X. when I message it, people respond positively to "X" but respond with a "meh" to clojure part. just wondering if I can change that somehow. i'd probably go with "java/jvm based sample app"

18:03 clojure is not used for anything else, btw. it is just a silly infatuation of mine.

18:14 coopernurse: srid: gotcha. if it's not critical that they buy off on clojure, then I agree with "jvm based sample app" is good.

18:14 kwertii: I'd say "Java virtual machine based," since they probably won't know what a JVM is, but they've very likely been exposed to a decade and a half of marketing for Java

18:15 coopernurse: if you want to convert "meh" to "wow!" then I guess you'd have to show them benefits that they care about (not sure if the meh folks are dev or biz)

18:16 kwertii: or, as suggested, leave out that detail altogether -- if there's not some specific reason why they would care about what language it's in (e.g. they're a huge, deeply invested Microsoft partner), they probably won't care

18:16 coopernurse: right, if it's all sufficiently irrelevant, then I suppose you can just say "look at my demo of feature X"

18:51 ShreeMulay: hey everyone. I've got a question regarding the usage of "include-css" from hiccup.page-helpers in my web development project. Where do I actually place that folder in context of my leiningen prroject?

18:53 ibdknox: ShreeMulay: depends on how you set up your resources route

18:54 ShreeMulay: if you're using noir, anywhere inside of resources/public/ would work, though it's usually best practice to do something like resources/public/css/

20:28 aaelony: I have a future named m1. If I do @m1, I see the future and the data I want to extract. How can I extract the data though? e.g. (#<core$future_call$reify__5382@71d382ab: ["2110401" "426"]> #<core$future_call$reify__5382@7527e2ee: ["2110402" "425"]>)

20:28 I'd like to extract the vectors inside the future

20:29 any help appreciated

20:29 hiredman: you have a future inside some other derefable thing

20:30 aaelony: not sure what you mean.

20:30 hiredman: ,(let [x (future (future 1))] (Thread/sleep 5000) @x)

20:30 clojurebot: #<core$future_call$reify__5733@54a99b: 1>

20:31 hiredman: ,(let [x (atom (future 1))] (Thread/sleep 5000) @x)

20:31 clojurebot: #<core$future_call$reify__5733@10a35db: 1>

20:31 aaelony: I did this to create it:

20:31 hiredman: you are nesting things and not derefing enough to denest

20:31 aaelony: (def m1 (future (get-metric-timeseries "Users" [testfile testfile2])))

20:31 hiredman: what does get-metric-timeseries with out the future result in?

20:31 aaelony: this will go get metric "Users" in all the test files

20:32 which I want to happen asynchronously since I have many metrics.

20:32 hiredman: I don't care what it is, what is the result type?

20:32 aaelony: (class m1)

20:32 clojure.core$future_call$reify__5382

20:32 hiredman: no

20:32 clojurebot: Excuse me?

20:33 aaelony: not sure what you mean.

20:33 hiredman: (type (get-metric-timeseries "Users" [testfile testfile2]))

20:33 aaelony: I am not sure if you can be helped then

20:33 aaelony: clojure.lang.LazySeq

20:34 hiredman: (map type (get-metric-timeseries "Users" [testfile testfile2]))

20:34 you are creating a future with contains a lazy sequence of futures

20:34 aaelony: (clojure.core$future_call$reify__5382 clojure.core$future_call$reify__5382)

20:35 hiredman: each level of future will need to be deref'ed

20:36 aaelony: I see.

20:37 Suppose I want to look inside N files for a particular key as a future, and I want the future to return a sequence of all the values it found for that key.

20:37 I will want one future for each key.

20:40 The irony is that the future I have contains exactly what I am looking for, it's just buried in there.

20:41 thx anyways, I'll tinker away

20:47 humourous: is (apply conj [1 2] [3 4]) better than (vec (concat [1 2] [3 4])) to get a vector form concatenation? (or something else?)

20:48 brehaut: ,(into [1 2] [3 4])

20:48 clojurebot: [1 2 3 4]

20:51 humourous: thank you

21:17 devn: ,(map #(apply str (repeat % "q")) (range 0 10))

21:17 clojurebot: ("" "q" "qq" "qqq" "qqqq" ...)

21:17 devn: better way to write that?

21:19 ,(set *print-length* 20)

21:19 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core$set>

21:19 hiredman: ,(iterate str "q")

21:19 clojurebot: ("q" "q" "q" "q" "q" ...)

21:19 hiredman: hmmm

21:19 ,(iterate (partial str "q"))

21:19 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$iterate>

21:19 hiredman: ,(iterate (partial str "q") "")

21:19 clojurebot: ("" "q" "qq" "qqq" "qqqq" ...)

21:19 brehaut: ,(let [qs (apply str (repeat 10 "q"))] (map #(.substring qs 0 %) (range 10)))

21:19 clojurebot: ("" "q" "qq" "qqq" "qqqq" ...)

21:19 devn: ,(set! *print-length* 20)

21:19 clojurebot: 20

21:20 brehaut: (for a different value of better)

21:20 devn: brehaut: a bit too declarative, no?

21:20 hiredman: ,(iterate (partial str "q") "")

21:20 clojurebot: ("" "q" "qq" "qqq" "qqqq" ...)

21:20 devn: ah-ha!

21:20 beautiful

21:20 thanks hiredman

21:20 bhenry1: nice

21:20 brehaut: devn: hiredmans is better, but i think the substring is more space efficient for large ns

21:20 devn: brehaut: i should really only be going to about 6 in general

21:20 so tiny is preferred

21:21 it's for JFugue -- (q)uarter note

21:22 hiredman: i've actually never seen partial and iterate used like that -- really cool

21:22 Tcepsa: ,(map #(

21:22 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

21:23 devn: there must be at least 50 ways to write it...

21:23 at least...

21:24 Tcepsa: ,(map #(apply str (take % (repeat "q"))) (range 0 10))

21:24 clojurebot: ("" "q" "qq" "qqq" "qqqq" ...)

21:24 Tcepsa: for yet another ;-)

21:24 gfrlog: devn: http://twitter.com/#!/DEVOPS_BORAT/status/109622560559333376

21:24 devn: ?

21:24 bahaha

21:25 "I work on new language call Quattro. If want to do any thing, is exactly 4 way of do it."

21:25 gfrlog: :)

21:25 devn: gfrlog: <3

21:26 obvious now given hiredman's solution, just another way of writing it:

21:26 ,(iterate #(str "q" %) "")

21:26 clojurebot: ("" "q" "qq" "qqq" "qqqq" ...)

21:26 devn: perhaps a bit much in the syntax department, though -- doesn't really give you anything...

21:26 Tcepsa: (though looking more closely, I'm pretty sure mine is just a more verbose version of the original ~wry grin~)

21:27 devn: :)

21:27 I have no doubt -- but there seems to be a limit to amount of shaving before all you're left with is a brittle twig

21:27 brehaut: or at least a very cold yak

21:27 devn: expressive but small -- hiredman's seems quite good in that department

21:27 * gfrlog blinks

21:27 * Tcepsa laughs

21:28 devn: haha

21:28 dinner time! then back to annoying my girlfriend with algorithmically generated muzak! :)

21:28 bbiab

21:29 Tcepsa: devn: Is the code available anywhere? That sounds like something I would enjoy looking at.

21:29 devn: Tcepsa: it's really nothing special but yes I'll put it up this evening

21:30 It's just doing some really rudimentary part-writing techniques

21:30 Tcepsa: devn: Thanks! I've tinkered with JFugue a little but never really got anywhere...

21:30 devn: to generate a simple progression and then play some passing tones with it in a sort of constrained "must-be-a-kind-of-melody" way

21:30 Tcepsa: Neat

21:31 devn: Tcepsa: I keep getting stuck at building small first and then trying to build a nice abstraction

21:31 they all end up feeling too constrained or too random to be expressive

21:31 * Tcepsa grins, "That sounds familiar."

21:32 devn: like (generate-layer (with-instrument :kalimba (generate-notes 16)))

21:32 Tcepsa: "Oh hey, if I make this a protocol then I could...!"

21:32 devn: or somesuch kind of thing

21:32 I don't have a nice sequencer-level abstraction which I think is the key

21:32 need a nice way to sequence parts...

21:32 Tcepsa: :key :F#

21:33 Ahhh, yeah, that makes sense

21:33 devn: on the nth note of layer 1, play from the 3rd to the 7th note of layer 2's first part

21:33 and repeat it 10 times

21:33 that ends up very verbose and not magical enough

21:33 Tcepsa: Hmmm...

21:33 devn: but i suppose this is why composition is hard :)

21:34 the other thing i really desire is a way to "capture" a sequence in order to train

21:34 supervised learning with midi sequences

21:35 anyway, gotta run, Tcepsa drop me a private message and ill ping you a link to the github or at the very least a gist of some ideas

21:35 Tcepsa: Oh I definitely want to chat more with you later; that is something else I have been noodling on

21:35 devn: Tcepsa: :) we should pair! i'll bother you later. ciao

21:36 Tcepsa: Bye!

21:52 jhickner: Hello good sirs. In ClojureScript, is there a way to console.log a clojure datatype in such a way that you can see the contents, like at the repl? A standard console.log of a vector displays as 'cljs.core.Vector' or similar.

21:55 alandipert: jhickner: (js/console.log (.strobj my-obj))

21:55 jhickner: it's a nasty impl. dependent way, and i've only used it with maps... but it might work

21:55 jhickner: ok thanks I'll give it a try

21:58 alandipert: or rather, (.log js/console (.strobj my-obj))

21:59 jhickner: it looks like it works for maps only. vectors and lists are translated to undefined in js

21:59 looks like it's time for a pretty-print util function

22:01 alandipert: ah, there's (.array my-vec)

22:02 see also http://groups.google.com/group/clojure/browse_thread/thread/eba1454e1984bee0 and https://gist.github.com/1141054 and http://dev.clojure.org/jira/browse/CLJS-37 (whew)

22:05 jhickner: any luck?

22:06 jhickner: .strobj works for maps, and it looks like .array works for vectors

22:08 nice, Kevin's functions at the end of that discussion look like a good start

22:08 thanks @alandipert!

22:09 alandipert: np

22:12 solussd: what common interface do vector and list share? How can I tell if something is a indexed sorted thing?

22:12 gfrlog: sequential?

22:12 ,(map sequential? [[] #{} {} '() ""])

22:12 clojurebot: (true false false true false)

22:13 solussd: that'll do nicely

22:19 donpdonp: i have a software package with a project.clj - how do i compile/build the project?

22:20 coopernurse: donpdonp: do you have lein installed? then you can do: lein run or lein jar

22:20 alandipert: donpdonp: https://github.com/technomancy/leiningen

22:20 donpdonp: coopernurse, alandipert: got it, thx!!

22:42 solussd: hmm, can't apply a Record. (apply MyRecord. [args])

22:44 brehaut: solussd: classes arent functions / ifns

22:44 amalloy: more specifically, neither are constructors

22:44 solussd: yeah… (apply make-myRecord [args]). :D

22:48 TimMc: ,(sequential? nil)

22:48 clojurebot: false

22:48 TimMc: ,(sequential? (seq [1]))

22:48 clojurebot: true

22:50 solussd: records just don't feel right… they feel OOPy

22:50 amalloy: yesss if you don't have a clear reason don't use them

22:51 solussd: they exist pretty much soley to implement protocols, right?

22:51 brehaut: they are also faster than maps if you have a constant set of keys

22:52 amalloy: yes, what brehaut said. a constant and *known-at-compile-time* set of keys

22:52 solussd: I have a couple protocols that I need to implement for data stored in maps, but not for all maps, so now I have records

22:52 yeah, these are maps with certain keys

22:52 they'd be structs if I were still allowed to use them. :D

22:52 I like protocols though. I like how they're inside out from protocols in other languages

22:52 amalloy: solussd: but if (apply MyRecord. args) worked, it wouldn't be performant, which is one reason it doesn't exist

22:53 srid: jkkramer: so any idea on the null pointer exception when running preprocess.clj? the stacktrace doesn't tell me the .clj/line information.

22:53 brehaut: solussd: an important distinction between records and OO is that a) they never implement data hiding, inheritance, recieve message and are not namespaces for methods

22:53 solussd: yep. That's what I like. I like how clojure encourages implementation to live in functions not class hierarchies

22:54 and if I want to share implementation I can do it w/ protocols + extend

22:54 amalloy: usually when people want to do crazy stuff like (apply MyRecord. args) or (into (MyRecord. nil nil nil) m), they're just using records for fun and to make their lives harder

22:55 solussd: amalloy: I didn't really want to do it, just noticed it didn't work.

22:55 jkkramer: srid: well, there's no -main fn in that ns. for now i interactively eval the parts in the commented-out area to refresh the project graph

22:56 Tcepsa: Records: kinda-sorta analogous to "pure" JavaBeans?

22:56 solussd: record fields are immutable, right? I guess I haven't tried to set! one yet

22:57 I like to think of them as maps I can have implement protocols, and nothing more.

22:57 srid: jkkramer: got it; running fetch-all-repos now

22:57 ah, it dumped json to stdout

22:58 amalloy: solussd: they are immutable, yeah. if you use deftype instead you can ask for mutable fields if you want

22:58 solussd: i don't. :)

22:58 jkkramer: srid: see the commented parts at the end. each def/defn in that area is a cumulative step

22:59 * srid replaces (comment with (defn -main ...

23:00 jkkramer: that may not work out well :)

23:00 srid: jkkramer: isn't the idea to execute all of the sexps in the (comment block?

23:01 jkkramer: srid: yes, but there's one broken project entry that i edit out by hand; that's mentioned by not included

23:02 srid: clojure-slick-rogue

23:02 jkkramer: right

23:02 srid: perhaps I should filter it out from - what - `github-projects` list?

23:02 jkkramer: that works

23:03 srid: btw, how long is this supposed to take? 15 mins, right?

23:03 jkkramer: the problem is really with my limited project parser

23:03 fetching the repos is quick. fetching the project.clj/pom.xml files form github takes a while...didn't time it

23:04 15-30 mins i think

23:04 srid: 'fetching the repos' == cloning the git repo?

23:04 ok, just project names.

23:05 "/Users/tin/src/clj/clojuresphere/clojars/" <-- hmm. i need to rsync clojars first, it seems

23:05 jkkramer: it does actually pull down the latest github push date, so future updates could take that into account

23:05 yes

23:07 srid: jkkramer: are the .jar files really required? (else, i can skip them for faster rsync?)

23:08 jkkramer: srid: they are not. my rsync-fu is weak so i just grabbed everything

23:10 srid: "- *.jar" ... runs much faster now.

23:11 clojars has static metadata, what a relief -- in pypi (python) one has to use xmlrpc

23:11 brehaut: xmlrpc is the pits

23:11 amalloy: brehaut: i hear it's a necessary evil

23:12 brehaut: sadly

23:12 amalloy: ~rimshot

23:12 clojurebot: Pardon?

23:12 amalloy: sigh

23:12 brehaut: no snack for the bot today

23:14 amalloy: clojurebot: rimshot is <reply> Badum, *ching*

23:14 clojurebot: Ack. Ack.

23:16 brehaut: id be curious how much evil has been propogated due to python having xmlrpc support in the stdlib

23:20 srid: python had worse problems. one has to run a script to get metadata such as project dependencies (that's what I do for pypm). this is being addressed recently. http://tarekziade.wordpress.com/2009/09/12/static-metadata-for-distutils/

23:21 solussd: how do you check if a instance of a record is of a given record type?

23:22 brehaut: ,(instance? String "abc")

23:22 clojurebot: true

23:23 solussd: thx, kept trying to use isa?

23:23 keep forgetting, record == class

23:30 srid: heh. writing back to clojure source (project_graph.clj.gz) instead of using a database.

23:32 brehaut: srid are you importing the resulting file or just reading it?

23:34 srid: not me, jkkramer's project (clojuresphere) .. and it seems to (read ...) it

23:34 i wonder why i'm running preprocess.clj at all, when it is already in git.

23:34 jhickner: ok, so after some screwing around, this seems to work pretty well for converting clj nested datastructures to js: https://gist.github.com/1199700

23:36 at least for maps and sequentials. it doesn't handle sets yet

23:36 brehaut: jhickner: any reason you wouldnt just use a json lib?

23:37 * srid got a local instance of clojuresphere running

23:37 jhickner: this would be for passing structures to js functions

23:37 functions that take object or array args, for instance

23:38 jkkramer: srid: cool. sorry for the goose chase, i thought maybe you wanted cutting-edge project data or something

23:38 srid: i only had to define default PORT.

23:39 i wonder why you are not using 'lein ring server'? it auto restarts the server on file changes.

23:39 jkkramer: i use swank, which can pick up changes after just evaling forms

23:39 amalloy: jhickner: this is not a unique thing to want to do. someone has surely already written this library; i think that's brehaut's point

23:40 jhickner: I agree, I've been looking.

23:40 brehaut: amalloy: once again making sense of my gibberish

23:40 clojure.contrib.json and clj-json are the two main candidates i recall

23:40 amalloy: brehaut: this seems to be a cljs context

23:41 and i don't think those really work for cljs

23:41 srid: jkkramer: is the plan to eventually integrate it to clojars?

23:41 brehaut: oh right

23:44 user317_: is there a way to add a local .jar file as a project dependency

23:45 jkkramer: srid: i'd like to yeah

23:47 amalloy: user317_: the mechanism starts with (1) Realize "oh wait, I didn't really want to do that"

23:47 user317_: well, i depend on this jar file thats released by interactive brokers

23:47 not sure how to get around it, i cant really add it to a public repository

23:48 technomancy: user317_: if you are a solo developer you can get away with mvn install:install-file, if you are on a team then you need to set up an archiva or nexus server

23:48 user317_: technomancy: i am han solo :)

23:49 technomancy: i take mvn is a maven thing?

23:49 technomancy: user317_: just add it to project.clj and run lein deps; it'll spit out an error message containing the mvn invocation that will put it in your local repo

23:52 user317_: technomancy: i am a little slow :) do i add "mvn install:jtsclient.jar" to the :dependencies vector in project.clj?

23:52 technomancy: user317_: no, just add it as if it were yet another jar on clojars

23:53 [mygroup/myid "1.0.0"]

Logging service provided by n01se.net