#clojure log - Oct 24 2009

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

0:21 hiredman: ,(macroexpand '(lett [x 1 y 2] (+ x y)))

0:21 clojurebot: ((clojure.core/fn [x] (sandbox/lett [y 2] (+ x y))) 1)

0:26 qed: how do you use clojure.contrib.combinatorics

0:27 or any library

0:36 hiredman: (use 'clojure.contrib.combinatorics) will make everything available in the current ns

0:37 (require 'clojure.contrib.combinatorics) will load the library, but you will need to prefix calls to fns from the library with the libraries namespace

0:37 there are various variations on the two

0:38 qed: hiredman: should it return nil

0:41 hiredman: yep

0:42 ,(require '[clojure.zipper :as zip])

0:42 clojurebot: java.io.FileNotFoundException: Could not locate clojure/zipper__init.class or clojure/zipper.clj on classpath:

0:42 hiredman: ,(require '[clojure.zippers :as zip])

0:42 clojurebot: java.io.FileNotFoundException: Could not locate clojure/zippers__init.class or clojure/zippers.clj on classpath:

0:42 hiredman: bah

0:42 ,(require '[clojure.zip :as zip])

0:42 clojurebot: nil

0:43 hiredman: ,(-> '(a (b c (d e) f) g) zip/seq-zip)

0:43 clojurebot: [(a (b c (d e) f) g) nil]

0:43 hiredman: ,(-> '(a (b c (d e) f) g) zip/seq-zip zip/next zip/next (zip/replace 'X))

0:43 clojurebot: [X {:changed? true, :l [a], :pnodes [(a (b c (d e) f) g)], :ppath nil, :r (g)}]

0:43 hiredman: ,(-> '(a (b c (d e) f) g) zip/seq-zip zip/next zip/next (zip/replace 'X) zip/root)

0:43 clojurebot: (a X g)

0:51 qed: (phmmm

0:51 i have (def nums (range 1 100))

0:52 im trying to use (reduce fn (nums))

0:52 hiredman: nums is not a function

0:52 qed: oh duh

0:52 hiredman: basically im trying to add the squares of 1 to 99

0:52 1^2 + 2^2, etc

0:53 whats a good way to do that

0:53 could i be fancier in how i use (range 1 100)

0:55 hiredman: ,(-> 1 (range 100) ((partial map (comp (partial apply *) (partial repeat 2)))) ((partial apply +)))

0:55 clojurebot: 328350

0:56 hiredman: :P

0:56 qed: haha

0:56 i dont understand your partial stuff

0:56 but thanks for the code

0:56 hiredman: ,(doc range)

0:56 clojurebot: "([end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0 and step to 1."

0:56 qed: ill study it

0:56 hiredman: partial is partial application

0:56 ,(partial + 1)

0:56 clojurebot: #<core$partial__4965$fn__4967 clojure.core$partial__4965$fn__4967@19a12cb>

0:56 hiredman: ,((partial + 1) 1)

0:56 clojurebot: 2

0:57 qed: ah ha

0:57 thanks for your help man

0:57 and congrats on solving the 3rd easiest problem on project euler in one line on irc in 5 minutes

0:57 hiredman: oh, well, I've eulered before

0:57 but was before my -> addiction

0:58 qed: what is ->

0:58 hiredman: it's the thrush combinator

0:58 qed: wow that is awesome

0:59 hiredman: ,(-> 1 inc inc)

0:59 clojurebot: 3

0:59 hiredman: ,(inc (inc 1))

0:59 clojurebot: 3

0:59 qed: very cool

0:59 thanks for the info

0:59 back to euler :)

1:03 tomoj: dammit

1:03 I can't start sbcl slime anymore because it automatically tries to require clojure.test

3:32 hiredman: ugh, syntaxquotereader is so gnarly looking

5:34 tomoj: ambient: are you the one doing sound stuff with clojure?

5:44 G0SUB: I think there is some problem with c.c.http-agent.

5:44 (http-agent "http://yahoo.com/&quot; :handler (fn [a] (string a)))

5:45 why is this returning an agent error?

5:45 #<Exception java.lang.Exception: Can't await in agent action>

5:45 any ideas?

5:54 arsatiki: g0sub: don't use string (or bytes or stream) in the handler, since they all call result in the end

5:55 which calls await. and that raises the error

5:56 no wait

5:56 I was wrong

5:57 G0SUB: arsatiki: how does this work? http://freegeek.in/blog/2009/10/downloading-a-bunch-of-files-in-parallel-using-clojure-agents/

6:00 ttmrichter: It's too anxious for the agent to act? (Seriously: no idea. Just like the error message.)

6:05 arsatiki: it seems stream is fine, bytes and strings less so.

6:05 snowwhite07: Doesn't lazy-cons exists?

6:11 hoeck1: snowwhite07: lazy-cons was superseded by lazy-seq in the 1.0 release

6:11 snowwhite07: hoeck1, oh, thanks

7:19 adityo: how will i convert a stream to a string?

7:53 got it

9:09 tomoj: is it true that structmaps don't know what kind they are?

9:09 or, that they can't tell me, I mean?

9:11 notallama: pretty sure it's just a hashmap, but with optimizations.

9:12 tomoj: looking at the source, it appears they know, but the field is not public and there's no accessor

9:12 guess I should use :type metadata

9:16 eh, clojure-json won't call the multimethod on structmaps anyway

9:19 notallama: clojure.lang.Script doesn't seem to print anything. (i have just a print statement in the script). any idea what's up with that/how to change it?

9:32 tomoj: notallama: try clojure.main

9:32 notallama: ok, found the problem. print doesn't automatically flush

9:33 tomoj: weird

9:34 when running with clojure.main, it does, but not with clojure.lang.Script

9:44 heh, I stared at "(= codepoint 0x7D) object ; }" for a minute confused by the unmatched "}" and wondering if ";" was some weird reader construct I hadn't seen before

9:44 I need sleep :)

9:46 notallama: i was confused by it as well. :V that just made me realize how little i use comments.

9:47 i guess with docstrings, i don't need them much

9:47 tomoj: I think the spacing makes it more confusing too

9:48 if it were "(= codepoint 0x7D) object ; }" I would've understood it immediately I bet

9:48 notallama: what changed?

9:49 tomoj: more space before the comment

9:49 so that ; and } aren't spaced like forms usually are

9:50 notallama: ah. irc ate the extra space, i guess

9:50 tomoj: test (this is in the middle of lots of spaces) test

9:51 notallama: all single spaces there.

9:51 tomoj: weird

9:58 notallama: pointfree style is pretty fun. so i just made a bunch of functions to support it (i stole >>>, &&&, ***, ||| and +++ from haskell, basically). perhaps this is a project for github/contrib if people like it.

9:59 rhickey: notallama: got some sample code using it?

10:02 hmmm... could support dynamic defclass where class visibility was limited to the same file

11:02 hvesalai: just coded my first line of clojure

11:02 durka42: welcome!

11:02 * durka42 wonders what the one line did

11:02 hvesalai: is (Integer/parseInt s) an idiomatic way to turn string into number?

11:03 durka42: probably

11:03 hvesalai: or is there something in clojure API for the same task?

11:03 chouser: hvesalai: yep

11:03 nope

11:03 hvesalai: ok

11:04 is it so that I have to code clojure "bottom up" i.e. define functions before I can use them in the definitions of an other function

11:04 i.e. i cannot say (defn b [x] (a x)) (defn a [y] (+ y 1))

11:05 rhickey: hvesalai: you can use declare to make names available before definition

11:05 durka42: yes, except for declare and letfn

11:05 hvesalai: ok

11:05 rhickey: chouser: did you see: rhickey: hmmm... could support dynamic defclass where class visibility was limited to the same file

11:06 chouser: rhickey: no! reading logs now...

11:06 rhickey: i wonder about the utility, in the new branch I just made it so all code loaded in same file shares a classloader

11:07 so a defclass could install the class in the dynamic classloader loading the file, where it could be found by subsequent calls to new and .field etc

11:07 chouser: instead of one classloader per ... what, top-level form? per "load" call?

11:07 rhickey: however, partial recompilation (select block, eval) as is common in interactive dev, wouldn't work well

11:07 per load call

11:08 not important to expose now, I needed it for deftype

11:09 chouser: REPL classloader would be unable to see the defclass's dynamically loaded via a 'load' or 'require'?

11:09 rhickey: chouser: right

11:10 chouser: that sounds ... well, really confusing. :-)

11:10 worse than rootloader

11:11 rhickey: yeah, probably no need given fully dynamic deftype

11:11 I'm pulling apart reify now...

11:11 deftype will be defined in terms of defclass

11:12 chouser: let us know when you're ready for help with hashcode, equals, etc.

11:12 rhickey: chouser: will do, thanks

11:13 one more issue was the fact that when using deftype, you;ll need a factory function that can set all of the fields, including meta and extmap, else you can;t really write functions that construct new instances

11:13 chouser: I'm hopeful it will be done (enough) in time to cover it in the book.

11:14 rhickey: I hope to get through the bulk of it today, with the same limits currently for reify (type of this, covariant return bridges not emitted)

11:15 chouser: are bridge methods too hairy for others to help out? proxy does them already, doesn't it?

11:16 rhickey: so, the type factory fn might look like this: (fn ([the fields you supplied] ...) ([the fields you supplied meta extmap] ...))

11:16 chouser: unfortunately I copied gen-class and not proxy when I did reify :(

11:16 but yes, the logic is in proxy

11:17 right now I just want to simplify as much as possible, getting rid of complexity relating to concrete supers

11:17 (which is not much, as I didn't support ctors with args/protected/supercalls yet anyway)

11:19 also I want to make it so the bulk of the generated impls (hashCode, equals, meta, type, etc) are done not by direct ASM emit, but by Java code emitting forms subject to normal compilation

11:22 so I'm concerned about the second form of the factory fn above

11:23 chouser: it doesn't look very scary to me -- so obviously I don't understand sufficiently. :-)

11:24 rhickey: something like that is needed so you can write fns that create complete values, but I wonder if people will constantly have to wrap it in order to get what they have with struct-map

11:25 are people often creating structs with struct-map, i.e. with extra/partial field sets?

11:26 chouser: auto imeta impl will mean with-meta will Just Work, right?

11:26 and similar for assoc/dissoc?

11:26 rhickey: ith-meta is IObj

11:26 with-meta

11:27 IMeta is just meta

11:27 ILookup gives you get

11:27 chouser: ok. you weren't planning on providing easy support for with-meta?

11:28 hvesalai: so can I convert strings into keywords (for adding keyword,value pairs into a map)

11:28 rhickey: and Associative assoc

11:28 chouser: yes, with-meta via IObj

11:28 chouser: hvesalai: you can use strings as keys in maps, but you can use the fn 'keyword' if you want to convert.

11:28 ,(keyword "foo")

11:29 hvesalai: thanks

11:29 chouser: rhickey: so the extra ctor has to be there to support Associative and IObj methods. What wrapping would users feel they need beyond those?

11:30 rhickey: chouser: well, and protocol that was like that, i.e. that required you to create a new 'modified' value, would require you to copy all fields

11:30 any protocol

11:30 hvesalai: is anybody using the counterclockwise eclipse plugin to generate java classes?

11:31 I didn't find any way to make the classes appear in the classes directory other than running (compile 'mynamespace) in REPL

11:31 is there a way to make ecplise do that for me automatically?

11:34 rhickey: chouser: think of using deftype to define PersistentMap where IPersistentMap was a protocol, you wouldn't have the auto-generated Associative, but you'd need to define fns that created new instances from old, propagating all stuff. In Clojure impl that stuff was usually just meta

11:35 and meta went first

11:35 [meta the fields you supplied]

11:37 expando complicates things, but without being built in it would mean every impl having to do the lookup work

11:42 chouser: that does complicate things when they are trying to implement IPersistentMap themselves.

11:42 without closures you can't really share utility methods, can you.

11:43 rhickey: chouser: if the implement IPersistentMap/Assoc/ILookup they don't get expando or impls of those

11:44 chouser: the thing is the lookup will be custom compiled per class, thus really fast, so not generic code that can be reused

11:44 I want lookup to be much faster than structs right now

11:45 right now - lookup index in map of key->index, then lookup field val in array at index

11:45 types/classes: generate a switch statement based on key hashes

11:46 inline code returns .field

11:47 find perfect hash and pack for tableswitch

11:47 in any case, custom code per type/class

11:53 mgarriss: Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i. (i.e. an accumulator generator)

11:54 in javascript: function foo (n) { return function (i) { return n += i } }

11:54 trying to figure out how to do it in clojure

11:55 in ruby: def foo (n) lambda {|i| n += i } end

11:55 chouser: right, custom code, but possibly via macro instead of asm (assuming tableswitch can be exposed sanely I suppose?)

11:56 rhickey: chouser: not a macro until cinc

11:57 * chouser collapses in metacircular confusion

11:57 chouser: mgarriss: both your examples mutate a local -- clojure locals are immutable

11:58 rhickey: almost of of the versions here: http://www.paulgraham.com/accgen.html are broken in the face of concurrency

11:58 chouser: mgarriss: so instead you'll want to choose a Clojure reference type, probably an atom

11:58 rhickey: and the whole premise in unsoundly stated - " returns n incremented by i"

11:59 but as chouser says, you can make a threadsafe version in Clojure with atom

12:00 if n is a number it can't be incremented as distinct from plus. One can't increment 42 in the sense he states, so there's a presumption of holes in environments etc

12:01 Like the Erlang/Haskell/Mozart examples there, Clojure correctly requires you put the state in an explicit container

12:03 since holes in environments are usually bereft of concurrency semantics

12:03 tomoj: (defn accumulator [n] (let [acc (atom n)] (fn [i] (swap! acc + i)))) ?

12:04 rhickey: tomoj: right

12:04 mgarriss: tomoj: that works

12:04 rhickey: and of the concurrency correct versions, the shortest and simplest

12:06 tomoj: clojure makes me happy

12:06 solussd: ,(str "[" (apply str (interpose "] [" (range 10)) "]"))

12:07 mgarriss: i've never used atom or swap! before

12:08 rhickey and chouser: i'm still having problems thinking in a immutable way, thanks for the pointers

12:08 tomoj: maybe you mean (str "[" (apply str (interpose "] [" (range 10))) "]") ?

12:10 rhickey: and in a golf match for brevity with the other versions there: (defn foo [n] (let [a (atom n)] #(swap! a + %)))

12:10 mgarriss: ok, an algorithm problem: can i write a function that returns the intersection of two collections that is better than O(n^2) ?

12:11 tomoj: certainly

12:12 maybe I'm just hallucinating from sleep-deprivation, but I can't even imagine an O(n^2) algorithm

12:13 the naive solution, I think, is O(n)

12:13 mgarriss: what would that be?

12:14 in pseudo-code is fine

12:14 tomoj: oh, I see what you mean I think

12:14 solussd: i cant think of one that is O(n). :)

12:14 tomoj: if it takes O(n) to see if something's inside, then it's O(n^2) I guess

12:15 you could get best-case O(n log n) by sorting first I suppose

12:15 mgarriss: i'm thinking about creating a hash with the second coll and using that to compare against, not that's better

12:15 *not sure that's

12:16 tomoj: probably a set would be better

12:16 ah yes, you can make a set out of one of them, which has (I think?) constant time lookup, then run down the other for O(n)

12:16 spuz: mgarriss: Clojure already has such a function: http://clojure.org/api#toc659

12:16 mgarriss: sorting is not an option, the collection it heterogeneous

12:17 tomoj: you can certainly make a set, though

12:18 mgarriss: spuz: this is a question i got passed on in an interview, i want to know the algorithm used

12:18 -got

12:19 spuz: heh ok

12:19 tomoj: hmm

12:20 spuz: I imagine if the set lookup is O(1), then intersection is O(n)...

12:20 tomoj: clojure.set/intersection seems worse than linear

12:23 solussd: the naive implementation is an order of magnitude faster than clojure.set/intersection: (defn intersection [a b] (filter #(contains? a %) b))

12:23 tomoj: why is clojure.set/intersection slow?

12:27 oh, I think I might see why

12:28 solussd: ?

12:29 tomoj: well, I'm not really sure, but it looks like what it's doing is looping through the longer set and for each item, checking whether it is in the second, and if not, disj'ing it from the accumulator

12:29 maybe disj is worse than constant time?

12:31 mgarriss: the hash idea in ruby: def intersection(a, b) h = a.inject({}){|m,e| m[e] = true; m}; b.delete_if{|e| !h[e]} end

12:31 that's better then n^2 i htink

12:31 tomoj: that's pretty much what set/intersection does

12:31 if I understand it right

12:32 mgarriss: make a hash like hash[key] = true for the one coll, then use that to compare against the second

12:33 i can't figure out the big O level of it however, it's been too long since i was in school

12:33 is it 2n ?

12:33 creating the hash is n

12:34 chouser: clojure.set/intersection returns a set -- solussd's naive implementation returns a seq

12:34 Chousuke: why would you need a separate hash? /:

12:35 mgarriss: Chousuke: i don't know how else to do it

12:35 Chousuke: the fastest interjection would be (into #{} (filter shorter-seq larger-seq))

12:36 et

12:36 shorter-set of course

12:36 solussd: yep.. returning a set definitely would make the time difference. :)

12:37 Chousuke: though I suppose that would fail if there are nils or falses in the set :)

12:37 tomoj: but making a set should only be roughly O(n), yes?

12:38 solussd: yes

12:39 Chousuke: yeah. intersection should be O(n)*lookup

12:40 tomoj: I'm trying to graph my results of set/intersection to see better if it's really more than O(n)

12:40 Chousuke: ~def intersection

12:40 oh shoot

12:44 tomoj: I think it is actually linear

12:49 spuz: is it possible to use 'loop' to make an infinite sequence?

12:52 ambient: this interests me too

12:53 (defn foo[] (lazy-seq (loop [n 0] (recur (inc n))))) don't seem to work

12:55 tomoj: (loop [] (iterate inc 0)) :P

12:55 ambient: which does not use loop/recur :/

12:55 tomoj: I can't imagine how or why you'd use loop for an infinite seq

12:56 except if calculating the values requires looping

12:56 spuz: hmm

12:57 tomoj: oh, I see

12:57 well

12:57 (defn foo [] (loop [n 0] (lazy-seq (cons n (recur (inc n))))))

12:57 but you can't do that

12:57 because you can only recur from tail position

12:58 lazy-seqs make loop unneeded

12:58 you can just call the function and the stack won't blow

13:00 lisppaste8: spuz pasted "Inifnite mandelbrot set" at http://paste.lisp.org/display/89213

13:01 tomoj: (defn foo [] ((fn rec [i] (lazy-seq (cons i (rec (inc i))))) 0))

13:01 spuz: Well, I'm trying to optimize that function, while keeping it lazy

13:02 if say I call (nth (mandelset -0.123 -0.234) 100000) I believe the multiple function calls and maps are slowing it down

13:02 chouser: lazy seqs can't be made of primitives, nor can you avoid allocating memory as the seq is walked.

13:03 you can however use chunked seqs which reduces the number of allocations per item.

13:04 tomoj: iterate doesn't chunk?

13:05 lisppaste8: rhickey pasted "reify/deftype syntax unification" at http://paste.lisp.org/display/89214

13:06 rhickey: the macro-izable versions are pretty verbose

13:06 plus I really like implicit this

13:07 defclass same as deftype

13:10 lisppaste8: rhickey annotated #89214 "another reify possibility" at http://paste.lisp.org/display/89214#1

13:13 rhickey: I guess it's a wash for simplest things:

13:13 (proxy [ActionListener] [] (actionPerformed [evt] ...))

13:13 (reify [ActionListener (actionPerformed [evt] ...)])

13:14 chouser: hm, so listing the interfaces separately from the methods complicates providing macros that do both for you

13:14 rhickey: chouser: I think so, also methods in blocks vs a la carte

13:15 else you'd need to, e.g., unroll do in macroexpansions that emit multiple methods

13:16 the whole macros for methods is a bit speculative right now

13:16 it's certainly more declarative to have the interfaces listed together

13:17 div`: when doing methods in an interface block, isn't it more confusing when 2 or more interfaces have a common method

13:17 rhickey: div`: yes, that's a potential issue

13:18 can't really do validation per block due to potential overlap

13:18 div`: my gut feel is to prefer interfaces grouped together

13:18 but that may be because of the java background too :)

13:18 rhickey: but if you wanted to use macro to generate overlapping method sets you simply couldn't, not a big limitation IMO

13:19 div`: not a limitation, but may be confusing to a reader

13:20 rhickey: another possibility is to go proxy-style and use some sort of escape (~ ?) to trigger macroexpansion

13:21 div`: wooosh :<

13:22 lisppaste8: rhickey annotated #89214 "reify proxy-ish with macro escape" at http://paste.lisp.org/display/89214#2

13:22 spuz annotated #89213 "Implementation using loops but no infinite sequences" at http://paste.lisp.org/display/89213#1

13:23 spuz: tomoj: that implementation is about 5 times faster but it will only ever calculate values up to *max-iters*

13:23 tomoj: well, that's what you're probably doing for mandelbrot anyway, huh? :)

13:23 spuz: so, ideally, I'd want the best of both but I have no idea how to turn this looping version into an infinite version

13:24 tomoj: yes exactly, but just from a functional point of view I'm wondering what the best way to do it is

13:26 div`: rhickey: that looks nice. Would be very handy to abstract away a generic implementation in a macro like that

13:26 without having to sacrifice an extends

13:41 toups: What is the idiomatic way to represent a homogeneous vector in clojure such that the compiler can optimize it?

13:41 I can see that you can type annotate arguments to functions

13:41 But what if the argument is a vector of doubles?

13:41 Should I just use a java array?

13:42 rhickey: toups: there aren't specializations of, e.g. vectors, for primitives yet

13:44 toups: So would it be reasonable to expect a java array to provide better performance?

13:46 rhickey: for many things yes, but you can't add to the end of an array, and they are not threadsafe under mutation

13:47 toups: That isn't an issue for this problem.

13:47 So I should be ok

13:47 Really, I am prematurely optimizing.

13:47 Performance is really not crucial at this point.

13:48 But I am just considering future possibilities.

13:53 ambient: i tried using both infinite lazy-seqs and atoms in my program, but array beat them both by a factor of 100

13:55 toups: How do I type hint, for instance, an array of doubles?

13:55 ambient: #^doubles

13:56 toups: My

13:56 That is nice

13:56 Thanks

13:57 ambient: you might find this useful: http://bitbucket.org/amb/clojure-snippets/src/tip/src/amb/synth.clj

14:00 it's currently unfortunately unreadable :(

14:00 i don't know how to make array code more immediately apparent

14:00 c-like structures might be useful

14:01 perhaps there is a way to build light-weight java classes. but that seems very un-clojur-ish to me

14:03 the whole mutable arrays concept, accessing values by index, almost looks like anathema, but it's way faster than anything else as far as I can tell, because every variable in my program needs to be modifiable in runtime, anytime, anywhere, anyhow

14:07 rlb: Is there a clever idomatic clojure way to create a map with optional elements, i.e. elements that should only be in the map if some test is true?

14:08 (per-element)

14:13 kunley: Hi folks.

14:15 chouser: rlb: the best I've seen so far is (-> {} (conj (when foo [:k1 v1])) (conj (when foo2 [:k2 v2])))

14:15 rlb: chouser: OK, thanks -- I was just playing with (-> (hash-map required-bits) ...)

14:16 chouser: ambient: light-weight java classes is a reasonable way to describe what rhickey is desiging as we speak.

14:17 ambient: cool :)

14:17 toups: I find myself "map" ing and then immediately forcing the result into a vector.

14:18 qed: Why doesn't clojure-mode auto-indent?

14:18 toups: Is there a built-in function that allocates the output of map right into a vector?

14:18 ambient: qed you tried pressing tab?

14:18 there was a way to make it auto-auto-indent but can't recall :(

14:20 qed: ambient: im sure tab works

14:20 but yeah i wanted it to do fancy auto-auto

14:20 it used to do it

14:20 not sure why it doesnt now :\

14:21 chouser: huh. 'vec' uses neither chunks nor transients?

14:22 toups: chouser: I am not sure I understand your question.

14:22 Correct me if I am wrong, but map returns a seq

14:22 ?

14:23 Is there a map-alike that returns a vec without the laziness or conversion steps that (vec (map ...)) would have?

14:23 Doesn't matter, really

14:23 I am writing it now

14:23 chouser: yes, map returns either a chunked or regular seq

14:25 oh, it does use transients.

14:26 toups: chouser: does the use of transients effect the present situation?

14:26 chouser: so, if you map over a chunked seq and use 'vec' to put the results into a vector, that will almost certainly run faster than doing a non-chunked map into a non-transient vector.

14:26 toups: chouser: still seems like it would be less efficient than just writing a special version would put the output directly into a vector, no laziness.

14:27 chouser: that seems counter-intuitive

14:27 chouser: toups: feel free to try it and let us know how it goes.

14:27 toups: Is there someplace I can read about transients and mapping to get a sense for their performance profiles?

14:28 ambient: efficiency and dynamicity are often at odds with each other

14:28 qed: am i the only one in here who can't quit telling their CS friends to learn clojure because it makes all other languages look like worthless sh*t

14:28 or is that common?

14:28 toups: I think Haskell and Clojure are pretty neck and neck.

14:29 Very arguably, Haskell is more elegant, even if it is harder to wrap one's head around.

14:29 Chousuke: maybe it's counterintuitive because map and vec optimise things behind the scenes

14:29 chouser: what is Haskell's library story?

14:29 ambient: i wouldn't recommend clojure for anybody just yet, only for the hardcore enthusiast.

14:30 qed: Haskell is great and all

14:30 but the whole monad thing sort of sucks

14:30 if I wanna do I/O in clojure, I can, without all of the extra garbage that goes on in Haskell

14:31 there are some weird edge cases where monads become a huge headache IIRC

14:31 Chousuke: monads are a neat construct though.

14:31 chouser: toups: if you write a fn that takes only Indexed collections and produces a vector via transients, you might be able to beat the speed of (vec (map ...)) by a bit.

14:31 Chousuke: being *forced* to use them isn't so cool :/

14:31 qed: yeah, neat construct, but pretty constrictive

14:31 exactly Chousuke

14:32 im the programmer -- i dont need a forcing me to do my job in a certain way

14:32 language forcing*

14:32 chouser: ambient: what would clojure need for you to start recommending it?

14:32 Chousuke: one thing I don't like about haskell is the large number of almost identical functions

14:32 qed: yeah that is a little annoying, i agree

14:33 i havent sspent a ton of time on haskell, so i cant really speak with much authority on that

14:33 Chousuke: you have foldl, foldl', zip, zip2, zip3, mapM, mapM_... icky :/

14:33 toups: Yeah

14:33 qed: yikes

14:33 toups: Strong typing I guess.

14:33 ambient: chouser robustness, documentation, trial by fire etc... i just don't trust _any_ new technology by default for production use

14:34 qed: ambient: i know people like you

14:34 :)

14:34 solussd: ambient: do you trust java?

14:34 qed: im the opposite (depending on what kind of stuff you're doing in "production", though)

14:34 i say use what works

14:34 new or old

14:35 chouser: ambient: ok, thanks.

14:35 ambient: chouser anyway, it's a hard question. mainly just FUD

14:35 clojure hasn't done enough to assure me

14:35 qed: what if chouser holds your hand? :)

14:37 * chouser is unavailable for hand-holding

14:38 chouser: ambient: that's fine -- just curious what Clojure needed to close the deal with you. Sounds like docs and time. Both are being worked on. :-)

14:45 AWizzArd: http://www.roberthalftechnology.com/SearchJobs?5_jobSearch.request_type=ViewJobDetail&5_jobSearch.job_number=41891821&5_jobSearch.single_job=true&specificJob=41891821

14:52 ambient: i don't disagree that clojure looks like the best thing since sliced bread. it's just very "raw"

14:52 qed: i think that's how lisp has always been

14:53 raw is what makes it so flexible

14:53 ambient: raw as in very limited set of tools

14:53 qed: see i just disagree with that because Java kind of renders that argument null

14:54 ambient: in theory it does. but the java interop is not without its problems

14:54 i digress, i should write more code, talk less :)

14:57 qed: hehe

14:58 im using it to do the euler project right now

14:58 it's going pretty well

14:58 ive finished most of the first page with clojure

14:58 Chousuke: I doubt anyone would disagree that Clojure is still rough around the edges. :P

15:02 somnium: are there any test-coverage tools for java that can analyze the .class files that clojure outputs?

15:02 tomoj: that's a good question

15:04 somnium: after a week of hacking in the repl I have a usable library but about 6 assertions :( (all the functions worked at repl, I swear)

15:54 toups: What is up with not being able to use -'s in clojure filenames

15:55 I know it is trivial, but it sort of grinds my gears.

15:55 Chousuke: JVM limitation

15:55 qed: it's a "c'mon son!" moment

15:55 dreish: I'm not a fan either, but at least it isn't rhickey's fault.

15:56 Chousuke: I think it could be worked around but it's more work than it's worth I guess :P

15:56 dreish: Underscores are teh s uck.

15:56 toups: Is there any convention?

15:56 Like do people just avoid using names that have dashes, or do they just use underscores in the filename and dashes in clojure?

15:56 Or do we use just underscores everyone in library names?

15:56 Chousuke: you need to name your files using underscores instead.

15:56 toups: Or is it a big mess.

15:57 Chousuke: no, all clojure-facing names have normal dashes.

15:57 just the filenames get underscore treatment

15:57 dreish: (use 'my-lib) => my_lib.clj

15:57 chouser: the filenames use underscores so that they can be valid Java package and classnames.

15:58 toups: Thanks

16:15 qed: how would i turn a large number into a sequence of digits?

16:15 ambient: ,(str (int 101010))

16:15 hmm no clojurebot? :(

16:16 well at least for me the class that the aforewritten piece outputs is java.class.String

16:16 qed: looks like i doesnt

16:16 ambient: thanks

16:16 that's really awesome, i guessed it would be harder

16:17 ambient: you can loose the int part

16:17 if you already know your type

16:17 chouser: lose

16:18 ambient: thank you, language police

16:18 chouser: sorry

16:18 qed: hmm why doesnt: user> (reduce + (seq (str (factorial 100))))

16:18 work?

16:19 chouser: qed: + is for numbers not Characters

16:19 qed: ah, hmm

16:19 ambient: (map int your-seq) i'd think

16:20 if you want to sum the ascii codes

16:20 qed: i want to sum the digits of 100!

16:26 chouser: you want to do it via strings and characters, or via math (dividing by 10s)?

16:26 qed: either way is fine

16:27 chouser: qed: you know about the project euler clojure wiki?

16:27 qed: yeah im not trying to cheat just yet

16:27 if you can give me a hint on a function to use

16:27 chouser: good. :-)

16:27 qed: to turn my seq of chars back into ints

16:27 that'd be cool

16:27 chouser: int

16:27 qed: k thanks :)

16:27 chouser: (int \0) ==> 48

16:28 qed: which problem number is this?

16:28 qed: it's so early on im going to embaress myself

16:28 i think it's like #20

16:29 yeah #20

16:29 chouser: hm, never did 20 in clojure.

16:29 qed: i need to get \9 to be 9

16:29 not 57

16:29 i was gonna do (reduce + (seq (str (factorial 100))))

16:29 chouser: I've a gap between 14 and 24 where I only used scala

16:29 qed: something like that

16:30 chouser: (- 57 48) ==> 9

16:30 qed: ahhhhh, yes

16:31 somnium: is it worth going through all the problems in clojure? I did the first 10 or so until I started getting comfortable, then I got programming clojure and just started hacking.

16:32 chouser: I didn't lose interest until around 50, though I've done a few others above that.

16:33 though I didn't switch from scala to clojure until around 30, and went back and did the first few over again in Clojure later.

16:36 somnium: Can you recommend any good sources for pattern matching in clojure? I watched most SICP, but I don't think I quite got it.

16:37 tomoj: there's pattern matching?

16:37 ambient: this is what i came up: (reduce + (map #(mod % 10) (take-while #(>= % 1) (iterate #(int (/ % 10)) 123456789))))

16:38 somnium: in SICP they implement pattern matching in scheme, its not built in

16:38 tomoj: ah I see

16:43 qed: how do i do something like: (map (- 48) sequence-of-ints)

16:43 dreish: (map #(- % 48) ...)

16:44 Or if you want to be flashy, (map (partial + -48) ...)

16:44 somnium: lol

16:45 tomoj: hmm

16:45 why + -48 instead of - 48?

16:45 somnium: im not sure if that qualifies as flashy or something else

16:45 dreish: Wrong argument order.

16:45 tomoj: oh, yeah

16:45 dreish: somnium: Tell that to the Haskell people.

16:45 tomoj: (-48) :(

16:46 qed: oh right, a little lambda

16:46 im so used to having lambdas hidden from me

16:46 tomoj: guess it would have to be (- 48) eh

16:46 somnium: I've been putting off learn Haskell because I'm afraid I won't be able to enjoy monad tutorials anymore

16:46 tomoj: I'm learning haskell because the monad tutorials make no sense to me

16:47 qed: haha

16:47 Chousuke: I need to reread monad tutorials periodically to refresh my enlightenment.

16:48 qed: that's a running joke in #haskell

16:48 how many monad tutorials do you need to read to understand it

16:48 Chousuke: I think I kind of get gist of monads but I still wouldn't be able to use them effectively :P

16:48 qed: yeah same here

16:48 dreish: How many monad tutorials does it take to screw in a light bulb?

16:48 qed: i dont know, how mnay?

16:48 many*

16:48 dreish: I don't know. That was the punchline.

16:49 qed: oh i thought youd have some slick haskell code

16:49 :)

16:49 Chousuke: dreish: well, seeing how screwing the light bulb is quite side-effecty, I'd guess at least a dozen

16:49 dreish: Trying to do some simple state change, like screwing in a light bulb, spending two weekends in a row staring at monad tutorials ...

16:49 qed: yeah, a light bulb into a socket, sounds like IO to me

16:50 ambient: (swap! old-bulb new-bulb) :p

16:50 dreish: I think it would be (swap! bulb change-bulb)

16:51 Or (reset! old-bulb new-bulb).

16:52 somnium: I think new-bulb was a variadic function that spontaneously creates a new light-bulb

16:52 dreish: I guess that works.

16:53 qed: what does % do in #(- % 48)

16:53 ambient: (fn [x] (- x 48))

16:53 dreish: It's the argument to the lambda.

16:54 qed: ahhhh thanks dreish

16:54 its a special variable then?

16:55 somnium: # <- is a reader macro

16:55 dreish: It's technically reader syntax.

16:55 Try '#(+ % %)

16:55 ambient: you can also use %1 %2 %3 etc

16:56 (fn [x y z] (+ x y z)) => #(+ %1 %2 %3)

16:56 dreish: Don't forget %&

16:56 ambient: what does that do?

16:56 somnium: then it really starts to look like perl

16:56 danlei: ((fn [%] %) 1) is almost the same as (#(%) 1), but the latter won't work

16:57 dreish: '#(list %& %) => (fn* [p1__1852 & rest__1851] (list rest__1851 p1__1852))

16:58 somnium: ,(#(%) #(+ 2 3))

16:58 hmm, he must be off today...

16:58 dreish: Now you're thinking with lambdas.

16:59 qed: ahhhh

16:59 thanks

17:01 somnium: I have this library, maybe 200 - 300 lines, and this feeling it could be one function, that takes one value and 20 keywords, and does (apply comp .....)

17:02 I need to reread SICP

17:03 qed: SICP is sort of dated IMO

17:03 i know that's heresy

17:03 :X

17:04 lpetit: hvesalai: still struggling with counterclockwise to have your classes compiled automatically ?

17:06 somnium: some of it, like environment and objects, is almost ridiculous nowadays, but the functional parts are still mind-expanding for me

17:24 toups: PS - the best way to get monads is to implement them in your favorite language.

17:24 http://github.com/VincentToups/emacs-utils

17:25 This may be of interest to clojure users

17:25 It is an implementation of clojure style destructuring binds for function definitions and let forms for emacs lisp.

17:25 Also included is a simple implementation of monads ala the clojure-contrib library.

17:26 I wrote it because I didn't want to re-implement common-lisp style destructuring just to get lexical functions, and the destructuring syntax in clojure is simpler.

17:27 But it also provides non-lexical versions of defn and let.

17:41 Kjellski: Good evening..

17:41 =)

17:43 AWizzArd: Na Kjell, alles klar?

17:46 Kjellski: Hö? Jow bei mir is alles klar... woher kenne ich Dich?

17:46 ^^

17:51 Sorry for german... but that´s confusing, do I know you?

17:55 We´ve got it private, nevermind...

18:00 danlei: Wie klein die Welt doch manchmal ist ;)

18:00 Kjellski: Wieso?

18:01 danlei: Ah, dachte ihr hättet euch grad zufällig getroffen ...

18:02 Kjellski: Kannten uns nicht, aber er hat an meinem ".de" Login erkannt das ich wohl auch aus Deutschland komme und mal Nabernd gesagt ^^

18:03 danlei: achso .)

18:04 Kjellski: *lach* den Smiley merk ich mir .)

18:16 qed: so in clojure a conj adds to the end when appropriate

18:17 and a cons always adds to the ead

18:17 head*

18:17 ?

18:17 the way it says conj adds to different "places" as appropriate is a tad confusing

18:17 if i conj onto a set, it wont go to the end or the beginning, right?

18:17 well, it could, but not every time

18:18 rhickey: conj adds to a collection. hash sets don't have places

18:21 qed: rhickey: thanks -- im new to the cons cell, but i can see now after a little trial-by-fire how it works

18:22 notallama: excellent. it works: http://paste.lisp.org/display/89224 (curry function)

18:22 rhickey: qed: no cons cells in sets/vectors/maps

18:24 qed: rhickey: only in lists then?

18:24 rhickey: right

18:24 Kjellski: in others it just can not make sense right?

18:26 But you could think of it when you use sorted-map or sorted-set?

18:27 rhickey: Kjellski: they are ordered, but not linked lists

18:27 qed: Kjellski: I saw something in Rich's talk with Beckman about how conj works fwiw

18:27 btw rhickey -- I really enjoyed that screencast

18:27 rhickey: great

18:28 just think of conj as add and remember that all the collections are different data structures, even if they all can be accessed sequentially

18:30 Kjellski: Uups, yes.

18:30 Where can I find that cast?

18:30 blip?

18:34 qed: Kjellski: let me find you the link

18:34 Kjellski: http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Rich-Hickey-and-Brian-Beckman-Inside-Clojure/

18:35 Kjellski: pay no attention to the "Install Microsoft Silverlight" thing, just click on the Media Downloads link and get the WMV or whatever

18:35 Kjellski: qed: thanks!

18:35 qed: Kjellski: no problem, if you find any neat references/videos/etc. let me know :)

18:36 Kjellski: qed: Sure =)

18:38 gone for watching...

18:38 qed: Kjellski: enjoy :)

18:49 Kjellski: FWIW the conj/cons stuff is at about T+25min

18:58 Kjellski: qed: thanks... I´m getting there soon

19:04 ambient: the thing is, lisp is only like one third of what one has to learn in clojure

19:05 i still haven't grokked all the concurrency constructs

19:08 defn: weird. why doesn't lazy-cons exist for me?

19:08 ambient: it's lazy-seq now afaik

19:08 defn: oh, thanks

19:08 ambient: and it works a bit different

19:25 chouser: lazy-cons is from pre-1.0 clojure. If you find it documented somewhere, you might write the author so they can update it.

19:39 qed: im gonna re-write the code with lazy-seq and then post it to my blog and reference the original article

19:39 http://clj-me.cgrand.net/index.php?s=Primes is where i found it

19:40 im trying to make a lazy sequence of primes using def

19:49 Kjellski: rhickey: That was a great talk... have you talked on after the recording?

19:49 rhickey: Sounded pretty fancy what Brian told you about his RTOS at the end...

19:50 rhickey: Kjellski: yes, Brian's a neat guy

19:50 qed: How could you not like a guy with a cowboy hat and sunglasses?

19:51 That wasn't a subtle jab, btw-- I think it's great.

19:55 Kjellski: I enjoyed it quite a bit -- I've actually used it as an intro to clojure/lisp for a few of my friends

19:56 It sort of gives a brief conversational history of some common things you'd find in lisp, how they work in clojure, etc.

19:56 I think the main thing I took away from it was some of the language and how you'd express some of the ideas in clojure in a conversational way

19:59 fanatico: qed: link?

20:00 djork: qed: what do you use as an intro?

20:00 Kjellski: http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Rich-Hickey-and-Brian-Beckman-Inside-Clojure/

20:02 djork: is it wrong to make a nondeterministic seq?

20:02 Kjellski: Yes, the introduction is pretty nice... that´s what I say too, just to overwhelm people with argument why I really _needed_ to learn just _another_ language (which normally takes a conversation in a "You´ve definitly have too much time" like thing...) ^^

20:03 djork: heh

20:14 Kjellski: What should I do if I want to go through a vec and if the element meet some criteria, I want that one to be changed? Sorry, but I don´t know how to explain what I mean in a immutable way...

20:15 +s

20:15 djork: start with thinking "how should I build the result"

20:15 so you've got three parts, the beginning, the element you want to change, and the rest

20:16 Kjellski: Wait, I´ll post the problem and my textual solution...

20:16 djork: Side note: it would be immensely helpful, but also hard to pronounce, to have a "The Little Clojure-er"

20:16 or maybe Clojurist

20:18 Kjellski: http://paste.lisp.org/display/89229

20:18 Yap, I would love to have that too... /annotate

20:18 ^^

20:22 djork: Kjellski: I'd just return a new vector with the new value for each bacteria and any new 5s that spawn... pretty simple I'd think.

20:23 Kjellski: djork: just not trying to make that all at one?

20:23 ce

20:25 djork: the resulting population from a given population is pretty simply defined there

20:25 you just have to think in terms of the next population

20:25 Kjellski: I´m just not in functional thinking you know... that´s my whole problem here

20:26 djork: yeah I know what you mean :)

20:26 think of it like this

20:26 your population is [2]

20:27 so the next population is [2 5]

20:27 err sorry

20:27 [1 5]

20:27 Kjellski: sure

20:28 but think of the case you´ve got [3 3]..

20:28 [2 2 5 5]

20:28 and than [1 1 5 5 4 4]

20:31 rhickey: It's alive!! (defclass* begins to breathe)

20:31 Kjellski: how to get the new vector with that decreased one bac?

20:31 rhickey: congrats!

20:32 djork: Kjellski: the idea is to not add the dead bacteria to the new population vector

20:32 remember, you're not mutating the current generation... just creating the next one

20:32 Kjellski: okay. *shame* my brain needs to be rewired by funtional thinking...

20:35 Damned, I think I´ve got it... but how to return 5 and the (dec bac) ?

20:35 ^^

20:50 AWizzArd: rhickey: thanks for this nice message, I will now sleep well :-)

20:50 Kjellski: Good night.

20:54 chouser: rhickey -- writing Java code so we don't have to.

20:56 danlei: what's defclass*? is that related to deftype?

20:57 Raynes: I don't know what either one of those are. :| I've been out of the loop for a while.

20:57 danlei: Raynes: http://www.assembla.com/wiki/show/clojure/Datatypes

21:02 Raynes: Oh. Sort of like Haskell's Data-types... Sort of.

21:02 Minus the hyphenation.

21:02 I was feeling dashy. :>

21:03 It reminds me of Haskell Datatypes, somehow.

21:03 * Raynes scurries away to watch Drag Me To Hell.

21:03 Kjellski: How can I "unpack" vectors in vectors?

21:04 like [1 [2 3] -> [1 2 3] ?

21:04 err [1 [2 3]] -> [1 2 3] ?

21:05 danlei: Kjellski: clojure.contrib.seq-utils/flatten

21:05 Kjellski: danlei : thanks

21:07 danlei: welcome

21:15 djork: what's the idiomatic way to express "else" in a cond

21:15 ?

21:15 is it to just (def else true) ? :)

21:15 danlei: :else

21:15 djork: ah

21:15 is that in the docs?

21:15 I don't see it in /api

21:16 danlei: actually, everything true will work

21:16 but :else is conventional

21:20 djork: just not documented?

21:20 oh, nevermind I see

21:20 :else is treated as true

21:20 :anything would be

21:22 hmm, so a fn with [x] and [[x & rest]] is the same arity?

21:26 durka42: djork: looks like it

21:33 danlei: (defn foo

21:33 ([x] 'hello)

21:33 ([x & rest] 'goodbye))

21:34 (foo 1) → hello, (foo 1 1) → goodbye

21:35 oh, nevermind :)

22:01 Kjellski: ,(remove nil [1 2 3 nil])

22:01 ???

22:01 This causes a NullPointerException

22:02 danlei: (remove nil? [1 2 3 nil])

22:02 The-Kenny: Kjellski: remove taks a predicate, not an element.

22:02 Kjellski: I seeee ^^ thanks, but why is it not saying that nil is no IFn or so?

22:03 danlei: error messages are just not the best ones atm

22:04 Kjellski: nevermind... just wondered because these seemed to me pretty consistent...

22:18 let me guess, remove is lazy right?

22:18 chouser: yep

22:19 Kjellski: I could just bang my head against a wall ^^

22:21 just like flatten?

22:22 chouser: flatten uses filter and tree-seq, both lazy, so yes.

22:23 Kjellski: Just couldn´t find it in the doc of flatten.

22:25 chouser: yeah, it probably ought to say its lazy.

22:27 it's

22:32 toups: Is there something like with-output-to-file in clojure-contrib or the core that I am missing?

22:51 lisppaste8: rhickey pasted "defclass* begins" at http://paste.lisp.org/display/89234

23:02 qed: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

23:03 (def pal-range (range 900 1000))

23:03 wha?? I was doing this earlier with no problems...

23:11 anyone? this is weird.

23:16 chouser: qed: you're trying (pal-range) ? Try instead without parens.

23:19 rhickey_: is there significance in having it all in one function?

23:37 cema: Hi all. First time here, not sure about the etiquette. I am learning Clojure and have a quick question - anyone available to give me an answer or a hint?

23:38 notallama: perhaps. what's your question?

23:38 rhickey_: chouser: it's jjust a way for me to call new without AOT since the body of the fn will have the same classloader

23:39 chouser: cema: you're welcome to ask

23:39 rhickey_: ah, got it.

23:39 cema: Reading from console in Emacs/Slime versus terminal clj.

23:39 jkoppel: Wow, looks like I had good timing logging in. I was just about to ask how to use AOT

23:39 cema: Specifically, reading the password (but any readLline).

23:40 Can I copy a line of code here?

23:40 chouser: cema: a line or two is fine here, otherwise use paste.lisp.org

23:41 lisppaste8: url

23:41 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

23:41 cema: (def P (.readPassword (java.lang.System/console)))

23:42 Works fine in terminal, but returns a null error in Emacs/Slime.

23:42 So I guess two questions here.

23:42 One, how to read passwords properly in a console-type application.

23:42 chouser: cema: I've never used System/console -- looks handy.

23:43 cema: Two, whether I should avoid the console (and what to use instead).

23:43 Thanks!

23:43 chouser: cema: but I imagine swank starts the JVM process without a console attached.

23:44 cema: *in* is set; is that not sufficient?

23:44 Or should I explicitly start... something (what then?)?

23:44 chouser: probably not -- a pipe may or may not be associated with a console.

23:45 cema: I see. Is there a standard way to attach it?

23:45 (Or a non-standard way?)

23:46 chouser: I would guess if you want to do a password prompt via slime/swank, you'd probably have to do something emacs-specific -- somehow communicate to emacs that it shouldn't echo keystrokes.

23:46 I don't know nearly enough about emacs to help you there though.

23:46 cema: I see. But even .readLine does not work in Emacs.

23:46 notallama: so i'm working on a pointfree library. this is what it looks like now: http://paste.lisp.org/display/89236

23:46 chouser: emacs itself could be running in a graphical mode without any console available I would imagine.

23:47 cema: So I guess I need to see what Emacs (specifically, Swank) does with console?

23:47 Then #clojure may not be the best place to ask. Any place you could recommend?

23:48 chouser: cema: maybe some emacs/lisp person could help you. It seems likelye that whatever solution would work for emacs and Common Lisp, for example, could be made to work for Clojure.

23:49 jkoppel: Alright, I'm trying to AOT compile a project of mine. I just compiled a couple dependencies from contrib just fine, but I'm getting an IOException from File.createNewFile when attempting to compile my own darmani.utils namespace

23:49 I'm using the line: (binding [*compile-path* "projects/clojure/"] (compile 'darmani.utils))

23:49 cema: That is correct, and I think I will now search for the solution towards that direction. Thanks a lot!

23:55 jkoppel: So....can anyone tell me how I should be using AOT compilation?

23:56 chouser: jkoppel: you're sure your "projects/clojure/" directory exists and is writable?

Logging service provided by n01se.net