#clojure log - Jan 27 2009

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

1:31 Cark: clojurebot: log?

1:31 clojurebot: logs is http://clojure-log.n01se.net/

3:55 AWizzArd: Moin

3:55 clojurebot: max people

3:55 clojurebot: max people is 129

4:01 ecret: (ns app.hello (:gen-class)) (defn -main [& args] (println "application works")) I am trying to make a class in clojure. The file is hello and its in the app folder but I am unsure of how to tell clojure to start in the folder before the app folder. When I try to compile it gives me an error.

4:02 so my question is, how do I check and set the project folder where it looks for those classes?

4:12 ayrnieu: it's behaving oddly for me. I can (require 'app.hello) successfully, but (compile 'app.hello) yields java.io.IOException: No such file or directory (hello.clj:1) , which is not the "java.io.FileNotFoundException: Could not locate app/hello__init.class or app/hello.clj on classpath: (NO_SOURCE_FILE:0)" that you get when the file is legitimately not there.

4:13 ecret: yeah same

4:13 i need to know where to put the app/hello.clj file

4:14 or how to set the environment to the master path or at least check what it currently is

4:21 AWizzArd: And how do you try to compile?

4:22 Did you set the right *compile-path*? As in: (binding [*compile-path* "/home/ecret/mystuff/"] (compile 'Hello))

4:22 ayrnieu: the exception is thrown by clojure.lang.Compiler.writeClassFile , calling java.io.File.createNewFile ; probably it's trying to create the class files in a directory that you're expected to have set up

4:23 ecret: (compile 'app.hello)

4:23 AWizzArd: ,*compile-path*

4:23 ,(print *compile-path*)

4:23 ecret: AWizzArd: i did not. Do I do this in clojure?

4:23 clojurebot: nil

4:23 ayrnieu: AWizzArd, http://clojure.org/compilation should emphasize this

4:23 AWizzArd: Yes, check what is in *compile-path*

4:24 ecret: ,(print *compile-path*) returns: classes

4:24 clojurebot: nil

4:24 AWizzArd: 1-2 days after compilation was introduced to Clojure I also had the problem that I couldn't compile my .clj files, because I did not point to the directory into which the corresponding .class files should go to.

4:25 well, the comma is not needed in Clojure, it is just for the clojurebot in this channel, to run my forms.

4:26 ecret: try to set *compile-path* with (binding ..) to a path that is in your classpath.

4:29 ecret: AWizzArd: I did (binding [*compile-path* "/home/eli/nlp/csphinx/"] (compile 'junk.hello)) my path to the file is /home/eli/nlp/csphinx/junk/hello.clj, still doesnt work

4:30 is that what I should of done?

4:31 java.io.FileNotFoundException: Could not locate junk/hello__init.class or junk/hello.clj on classpath: (NO_SOURCE_FILE:0)

4:31 [Thrown class clojure.lang.Compiler$CompilerException]

4:31 ayrnieu: http://paste.lisp.org/display/74340

4:31 ecret, you get that because it tries to load the class that it's just created, and *compile-path* isn't in your CLASSPATH

4:37 AWizzArd: ecret: do (System/getProperty "java.class.path") in your repl

4:38 ecret: tried that ,heres a jar file : /home/eli/clojure/classpaths/RM1_8gau_13dCep_16k_40mel_130Hz_6800Hz.jar

4:38 i copy pasted the folder into /home/eli/clojure/classpaths/csphinx/junk/hello.clj

4:40 AWizzArd: You should have /home/eli/clojure/classes/ in your CP (create that dir if it does not exist yet), and /home/eli/nlp/csphinx/ as well in CP.

4:40 Then you can bind the *compile-path* to the .../classes/ dir and compile 'junk.hellp

4:40 hello even

4:40 ecret: in my .emacs file, swank-clojure-extra-classpaths (directory-files (concat concourse-dir "clojure/classpaths/"

4:42 AWizzArd: Did you decide into which directory the .class files should go that result from compiling .clj files?

4:42 This could be for example /home/eli/clojure/classes/

4:43 As soon you decided which dir will be the target, put that into your classpath (for example by adding it to your swank-clojure-extra-classpaths).

4:44 Now inside a possibly completely different directory create a subdir "junk". Into that put your hello.clj which begins with (ns 'junk.hello ...)

4:45 And put the dir in which you created junk also into your CP. Then you can compile.

4:49 ecret: AWizzArd: i am hesitant to change my .emacs file since I had a rough time getting it to work in the first place with the jar classpaths. How would I change swank-clojure-extra-classpaths (directory-files (concat concourse-dir "clojure/classpaths/") t ".jar$") to have the classes folder?

4:50 AWizzArd: make a copy of your .emacs file to which you could go back any time

4:55 ecret: here is an example of how your .emacs file could begin: http://nopaste.ch/9869fa857c1cbef.html

4:58 ecret: AWizzArd,ayrnieu thanks for the help.

6:00 Lau_of_DK: Gents, regex question

6:00 (re-find #"\b[Author: +]\b.*" "Author: Jack Daniels <jd@drink.org>")

6:00 I want to extract only "Jack Daniels <jd@drink.org>" How do I do ?

6:04 (re-find #"\b[Author: ]\b+.*" "Author: Jack Daniels <jd@drink.org>")

6:04 " Daniels <jd@drink.org>"

6:04 This is a little closer, but it misses Jack

6:17 holly: (re-find #"(Author:\s+)(.*)" "Author: Jack Daniels <jd@drink.org>")

6:17 3rd element is the desired one...

6:20 With (re-find #"(?>Author:\s+)(.*)" "Author: Jack Daniels <jd@drink.org>") it's the second...

6:21 rfgpfeiffer: (re-matches #"Author:\s+(.*)$" "Author: Jack Daniels <jd@drink.org>")

6:24 cgrand: holly: what's the difference between ?: and ?>

6:37 holly: That I have only just learned about ?> but not yet about ?:

6:37 http://www.regular-expressions.info/atomic.html is what I looked at

6:40 http://www.regular-expressions.info/brackets.html seems to indicate that ?: does the same as ?>

6:42 Hmmm. Not quite maybe -- ?> seems to be like the cut from Prolog -- throws away all backtracking info from withing that group. For this regecp that shouldn't make a difference -- we want the greedy behaviour.

6:42 Compare (re-matches #"(?>Author:\s+)( .*)" "Author: Jack Daniels <jd@drink.org>") with (re-matches #"(?:Author:\s+)( .*)" "Author: Jack Daniels <jd@drink.org>")

6:43 (note that now we want to match one space in front of "Jack" -- with ?> we don't find this as it first greedily matched all spaces and then couldn't backtrack

6:44 cgrand: holly: thanks I didn't know of ?> and the javadoc for Pattern left me nonplussed

6:46 holly: :-) There are obviously advantages to being a Java newbie and not knowing about javado

6:46 cgrand: I understand now ?> is as greedy as possible even if it causes the rest of the regex to fail: you can't backtrack -- that's what they meant by "independent"

6:48 holly: You cannot backtrack *into* that group -- it can still backtrack to *before* that group

6:51 cgrand: indeed, thanks for the clarification!

6:54 Lau_of_DK: holly, I was out to lunch, thanks alot for helping out

6:55 holly: NP -- glad I can add something here instead of just lurking

6:57 Lau_of_DK: It was a big help - I fail at regex almost every time :|

7:21 rfgpfeiffer: (comp) should be identity

7:21 ,((comp) 3)

7:21 clojurebot: java.lang.NullPointerException

7:25 AWizzArd: no, but it could perhaps throw an exception instead

7:30 rfgpfeiffer: it would be consistent with + and *

7:34 AWizzArd: Those are defined as such

7:34 empty sum and multiplication

7:36 cgrand: in the same vein (-> x) should expand to x

7:41 AWizzArd: But what should (->) do? ;-)

7:44 cgrand: thinking more about it: identity is only the neutral element for unary functions not for all function -- comp is indeed irregular: its rightmost arg can be any function but other args have to be unary functions

7:46 AWizzArd: I still would like to have the functional equivalent to ->, namely (defn pipe [& fs] (apply comp (reverse fs)))

7:47 ,(defn pipe [& fs] (apply comp (reverse fs)))

7:47 clojurebot: DENIED

7:47 rfgpfeiffer: fixed versions: http://gist.github.com/53325

7:49 cgrand: I have a composition function for n-ary fns: http://gist.github.com/51768 before-advice

10:54 scottj: What is an xrel and a rel?

10:54 Chouser: scottj: where are you seeing those?

10:55 scottj: Chouser: clojure.set/index

10:56 That only references xrel, but the function above it, rename, references both

11:10 cgrand: scottj: it seems that a rel is a set of key-values (N:N) while xrel is a map (N:1)

11:11 cgrand: forget what I said

11:12 * Chouser is suddently confused

11:12 Chouser: suddenly

11:15 * karmazilla would rather write code than configure BI servers

12:09 knapr: anyone with an example of a gui using JFileChooser?

12:11 jwinter: This has a JFileChooser (I just saw it today): http://github.com/ynd/mona-clojure/blob/master/mona-clojure.clj

12:16 cgrand: wow: you can try clj libs without even downloading them!

12:16 (add-classpath "http://github.com/Lau-of-DK/clojureql/raw/master/src/&quot;)

12:16 (require '[dk.bestinclass.clojureql :as ql])

12:16 Chouser: ah, sweet.

12:17 rhickey: that's neat

12:17 cgrand: chouser: if there is a proper directory structure (didn't work with textjure)

12:18 cooldude127: that's awesome!

12:18 Chouser: that also means you get the latest version each time your run. ...I hope you trust that URL.

12:18 cgrand: yeah, textjure is just a "script", not a lib.

12:18 rhickey: Chouser: well, he'd never put add-classpath in his app, right?

12:19 danlarkin: wow that is a really really neat trick

12:19 Chouser: hm, can't use URLs on the -cp command line, I guess.

12:19 knapr: lol thats supersweet

12:22 cgrand: If you are unlucky I guess you could get an inconsistent snapshot

12:48 knapr: what is textjure?

12:48 drewr: knapr: Clojmacs.

12:51 danlarkin: shame that validator-fns are supposed to be side effect free

12:51 I'd feel bad giving mine side effects

12:51 knapr: sun.awt.shell.Win32ShellFolder2 cannot be cast to java.lang.String

12:51 danlarkin: so I must find a different way

12:53 knapr: clojmacs? you mean clojure-mode for emacs?

13:01 are GUIs naturally statefula nd using globals is normal? or is that just becuas eim using Swing which anturally is a OO-oriented framework?

13:01 i used Tkinter with python and before seem to force the use of globals

13:06 Chouser: knapr: GUIs are indeed stateful, but don't necessarily need globals.

13:06 cooldude127: knapr: look at some of the haskell gui libraries to see how they are trying to unstateful guis

13:06 it's hard to wrap your head around, i know i don't get it

13:07 Chouser: i guess you can try to pretend it's not stateful, but the thing you're looking at on the screen sure seems like it's a "state"

13:08 cooldude127: it is, but it can be represented functionally, it's just really confusing

13:09 danlarkin: it's a gui monad! *boggle*

13:09 cooldude127: yeah maybe it would have made more sense if i could actually understand macros

13:09 s/macros/monads

13:11 nymsy: hello

13:11 danlarkin: nymsy: hello!

13:11 cooldude127: nymsy: hi

13:14 knapr: damn collision betwen paths, FileChooser uses \ and I use / , why is windows so stupid?

13:17 nymsy: so, I might loose connection... I'm in afghanistan, using a nokia phone for internet.. over a... maybe a 5 kbps link (little k)

13:18 Thought I'd swing through irc and see how it was... webpages take forev' but this seems to work decent

13:18 Chouser: nymsy: interesting!

13:19 nymsy: Chouser: yea, makes for some interesting stress testing

13:20 noidi: a newbie question: what's the difference between a list and a vector? after some googling I gather that the former's a linked list while the latter is an array of references...

13:20 nymsy: So, I've been in transit for about 2 weeks, on my way out for a deployment in A-stan, and I've been working on a clojure app, to kill time while I wait

13:21 Chouser: noidi: there are a couple differences. lists grow on the left, vectors grow on the right (when you conj)

13:21 hiredman: vectors are indexed (like an array)

13:21 ,([:a :b :c] 1)

13:21 clojurebot: :b

13:22 hiredman: ,(get [:a :b :c] 1)

13:22 clojurebot: :b

13:22 Chouser: noidi: vectors provide constant-time random access to any element (by index) while lists can only be scanned in linear time

13:22 WizardofWestmarc: use vector when you want ~0(1) access time to any element in the list.

13:22 hiredman: ,((list :a :b :c) 0)

13:22 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

13:22 * WizardofWestmarc shakes his fist at Chouser for being faster.

13:22 hiredman: :(

13:22 noidi: thanks!

13:23 nymsy: So, I'm going to go off and open up my code and get back here and ask some of the questions I've been burning to ask for 2 weeks... :)

13:23 Chouser: nymsy: and you have it running on your phone, right?

13:27 cooldude127: wow lists really don't implement IFn?

13:27 i guess that's to encourage you to use vectors for those situations

13:27 hiredman: yes

13:30 noidi: ,"testing"

13:30 darn :)

13:30 nymsy: Chouser: clojure or the internet?

13:30 noidi: ,([:a :b :c] 1)

13:30 clojurebot: :b

13:30 Chouser: noidi: clojurebot ignores you unless there are parens

13:30 noidi: ,(identity "testing")

13:30 clojurebot: "testing"

13:30 Chouser: nymsy: your clojure app runs on your phone, right? In fact, it's your IRC client? ;-)

13:30 noidi: cool :)

13:34 nymsy: heheh.. actually.. you could say I'm writing a simplified irc app

13:34 but no, this runs on my computer.. I'm tethering.

13:44 First question: what are the ways to get a value from a set?

13:45 I saw select

13:46 Chouser: you can use 'get' or just treat the set as a fn.

13:46 ,(#{:a :b :c} :b)

13:46 clojurebot: :b

13:46 Chouser: ,(#{:a :b :c} :d)

13:46 clojurebot: nil

13:46 nymsy: the comma.. is that clojure?

13:47 Chouser: no, that's clojurebot

13:47 durka42: commas are whitespace

13:47 nymsy: ah

13:47 Chouser: , is whitespace in clojure

13:47 durka42: clojurebot evalutes lines beginning with commas

13:47 nymsy: rgr

13:47 Chouser: ,#{:a,:b,:c}

13:47 ,(prn #{:a,:b,:c})

13:47 clojurebot: #{:a :b :c}

13:48 nymsy: yes, but why would I want to return :b from #{:a :b :c} if I already have :b? It's nice to know that it's there and all...

13:49 I guess I'm wanting set to be more like a map

13:49 * gnuvince declares PHP to be the most retarded language in existance

13:49 nymsy: Whereas, map already acts a little like a set, with unique keys

13:49 Chouser: nymsy: perhaps I misunderstood your question. A set contains only "keys" if you will, no values. Or the keys *are* the values.

13:49 danlarkin: gnuvince: s/language/state machine/

13:50 nymsy: Chouser: right

13:50 noidi: why can't you use a map then?

13:51 nymsy: let me think of an example of what I'm trying to do

13:51 noidi: ,({:key :value} :key)

13:51 clojurebot: :value

13:51 nymsy: by the way, does clojurebot have cycle turned off? ;)

13:52 durka42: you mean infinite loops?

13:52 Chouser: ,(take 7 (cycle [:chicken :egg]))

13:52 clojurebot: (:chicken :egg :chicken :egg :chicken :egg :chicken)

13:53 Chouser: he's got some protection against attempts at evilness.

13:54 nymsy: aye... so I've got a (def *clients* (ref #{}))

13:54 for my irc like chat program

13:55 (this is, by the way, based off of somebody's code from the list)

13:56 and client is a (defstruct client-t :socket :output :reader :nick :uid :last-action-time)

13:57 Chouser: you want to be able to find the client struct from a given nick

13:57 ?

13:58 nymsy: yes, but nicks can change, so each :nick starts as a (agent "anonymous")

13:58 so I have to do derefing while searching the #{}

13:58 Chouser: yeah

13:59 knapr: anyone good with Java, swing and threads? When I play an mp3 it eats up all the "authority" of the app. apparently im messing with main event dispatch threa dor something

13:59 Chouser: it seems likely to me that the nicks should be refs instead of agents

14:01 nymsy: Chouser: this is one area I'm lost in.. knowing when to use each of the mutability tools

14:01 I've read the differences, but I don't yet understand what exactly is being described

14:02 Chouser: I don't have an extremely firm grasp on it myself...

14:02 nymsy: I've dealt a little with locking in Java, but I'm still a noob

14:03 what pastebin do you guys use?

14:03 Chouser: but agents for for values that are independant of each other. The fact that the nicks are in a collection that is itself in a ref suggests to me that the *clients* collection and the nick values themselves need to be coordinated with each other.

14:03 durka42: clojurebot: paste?

14:03 clojurebot: lisppaste8, url

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

14:03 Chouser: "agents are for values"...

14:04 the only coordinated reference type is the ref.

14:04 nymsy: Ok, so a collection of refs inside of a ref is normal?

14:05 Chouser: nymsy: it can be, though you could just have the top-level ref and swap out the whole collection when you update a nick

14:08 nymsy: I'm afraid that solution might get heavy, but I'm not sure if clojure optimizes for that... doesn't that copy all the clients and their sockets, readers, writers, etc?

14:08 if the server became big, how big would that operation become?

14:09 Chouser: no, it doesn't. clojure collections share as much data as they can with earlier versions of themselves

14:09 nymsy: so a ref-set is as efficient as, say, an assoc inside of a ref?

14:09 (erm, on a ref inside the ref)

14:11 Lau_of_DK: Good evening all

14:11 nymsy: ok, watch out.. here comes some ugly code

14:12 lisppaste8: nymsy pasted "blah.clj" at http://paste.lisp.org/display/74360

14:13 nymsy: most of these functions are in transition, so they're ugly

14:13 The arity in most is accommodating either access to global state, or more pure function

14:14 One of my problems is the the filter-for and its sister function filt-for-deref.. cause I couldn't figure out how to get filter-for to do both

14:15 Chouser: I think that changing a item in a collection inside another collection inside a ref would be slower than if you had another ref at the lowest level, but only by a constant factor of the depth.

14:16 that is, the collections themselves could get many times larger without either solution becoming a whole lot slower.

14:17 nymsy: ok

14:17 noidi: is anyone else here using VimClojure?

14:18 Chouser: (filter-for #(deref (:nick %)) "joe" *clients*)

14:19 nymsy: What if the value I'm looking for isnt a ref?

14:20 Chouser: then leave out the 'deref' part as you already do.

14:21 nymsy: I want a general function to dip down into the nested collection I've created and sometimes grab the value of a normal value and sometimes grab the derefed value of a ref value

14:21 Chousuke: (doc get-in=)

14:21 clojurebot: excusez-moi

14:22 Chousuke: (doc get-in)

14:22 clojurebot: returns the value in a nested associative structure, where ks is a sequence of keys; arglists ([m ks])

14:22 nymsy: Chousuke: works for maps inside of sets?

14:22 Chouser: oh. Well, I suppose you could add a phrase to filter-for: (if (instance? clojure.lang.IRef x) @x x)

14:23 Chousuke: nymsy: hm, I don't think so.

14:23 nymsy: since to get the map, you need to have the map already

14:23 ,(get-in {:m [:a :b {:c :d}]} [:m 2 :c])

14:23 clojurebot: :d

14:23 Chouser: it probably does work on sets, but since you'd have to supply the whole value you're looking for, it would help much.

14:25 nymsy: if i'm looking for one nick in all the clients in a ref, I've been using for to go through every item in the set

14:25 so I could get-in on the for

14:25 Chousuke: maybe you should index the clients by their nickname? :/

14:25 a map of nicks to the client data

14:26 Chouser: but he also sometimes looks them up by :uid, and the :nick can change.

14:26 Chousuke: hmm

14:26 nymsy: right, sometimes

14:26 Chouser: sets of maps may not be too terrible -- I can't quite decide what would do better.

14:27 nymsy: I guess get-in with for is useless, since I've already dug down

14:27 Chouser: it *might* make sense to maintain two maps -- one from uid to client-struct, the other from nick to client-struct.

14:27 it would make lookups faster and more convenient

14:27 presumably uids don't change, so that'd be fine.

14:28 nymsy: would each collection point to the same set of objects?

14:28 Chouser: when you update a nick, though, you've have to fix up both maps. That might still be easier than what you're doing.

14:28 Chousuke: if the client struct is wrapped in a ref, keeping them in sync would be easy too

14:28 Chouser: nymsy: either that, or the uid could be the "canonical" map, and you could have a separate map of nick to uid

14:29 Chousuke: hm, that sounds better.

14:29 could have multiple nicknames that way, too :P

14:29 nymsy: aye

14:29 how would this seperate map work?

14:30 Chousuke: just (def nick-to-uid (ref {}))? :)

14:30 Chouser: I guess it'd be another global. *clients* would now be a map instead of a set, and you'd also have *nicks* which would look like {"joe" 123, "bob" 456}

14:30 right, in a ref.

14:32 nymsy: So, to send bob a message, (*nicks* "bob") > 9833498 and then (send-message-to 9833498 "msg")

14:32 kinda deal

14:33 Chouser: right

14:33 nymsy: and maps ensure that there can only be one "bob" in *nicks* and only one uid in *uid*s

14:34 Chouser: still faster and more convenient than walking the set of all clients looking for a "bob"

14:34 nymsy: true

14:35 * durka42 envisions a program sifting through a stack of s-exps, muttering "bueller... bueller..."

14:36 nymsy: I wonder if one could do a two-key-one-value map, where it was like {key-nick key-uid value, &}

14:36 durka42: i mean, you could emulate that with two maps, or a list of triplets

14:37 Chouser: well, you can put the nick and uid in a vector, and use the vector as the key. ...but then you'd have to know both to look up anything.

14:37 nymsy: with performance comparable by a constant factor to normal maps...

14:38 what about {(or this that) value}

14:39 Chouser: you could put the value in there twice: {key-nick value key-uid value}

14:39 nymsy: or {#(or (= % this) (= % that)) value}

14:40 durka42: ,(first (filter #(or (= "bob" %1) (= "bob" %2)) {["alex" 134] :alex, ["bob" 532] :bob, ["joe 1395876] :joe}))

14:40 clojurebot: Eval-in-box threw an exception:EOF while reading string

14:40 durka42: ,(first (filter #(or (= "bob" %1) (= "bob" %2)) {["alex" 134] :alex, ["bob" 532] :bob, ["joe" 1395876] :joe}))

14:40 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--802$fn

14:40 durka42: whoops

14:40 ,(first (filter #(or (= "bob" %) (= "bob" %)) {["alex" 134] :alex, ["bob" 532] :bob, ["joe" 1395876] :joe}))

14:40 clojurebot: nil

14:40 durka42: i should test these things

14:40 ,(first (filter #(or (= "bob" (first %)) (= "bob" (second %))) {["alex" 134] :alex, ["bob" 532] :bob, ["joe" 1395876] :joe}))

14:40 clojurebot: nil

14:40 * durka42 retreats to a real repl

14:40 Chouser: yes. you should. :-)

14:41 * cooldude127 learns about b-trees omg

14:41 nymsy: *as freenode crashes*

14:41 durka42: ,(second (first (filter #(or (= "bob" (first (first %))) (= "bob" (second (first %)))) {["alex" 134] :alex, ["bob" 532] :bob, ["joe" 1395876] :joe})))

14:41 clojurebot: :bob

14:42 durka42: ,(second (first (filter #(or (= 134 (first (first %))) (= "bob" (second (first %)))) {["alex" 134] :alex, ["bob" 532] :bob, ["joe" 1395876] :joe})))

14:42 clojurebot: nil

14:42 durka42: never mind

14:42 that got way too unwieldy

14:42 don't do that

14:44 nymsy: ,({#(or (= % "bob") (= % 111)) "socket"} "bob")

14:44 clojurebot: nil

14:44 nymsy: hmm

14:44 Chouser: yeah, that's not going to work.

14:44 hiredman: well when data structures get unweidly, you build new functions to wield them

14:45 Chouser: ,({"bob" "socket" 111 "socket"} "bob")

14:45 clojurebot: "socket"

14:45 Chouser: just as good, and actually works.

14:45 nymsy: rgr

14:45 Chouser: :-)

14:45 nymsy: is there a way to make both "socket"s point to the same socket?

14:46 so as to mitigate doubling the actual size in memory?

14:46 Chousuke: nymsy: just bind it to a name first and use that name as the value.

14:46 instead of a literal

14:46 WizardofWestmarc: actually might the JVM be smart enough to not double use literals?

14:46 Chousuke: probably, but that's not guaranteed.

14:46 WizardofWestmarc: should be possible to find out

14:47 nymsy: they won't be literals in practice

14:47 if by literals you mean those strings

14:47 WizardofWestmarc: right

14:47 Chouser: if you do (assoc *client* "bob" socket 111 socket), they'll both point to the same socket object

14:47 it's not going to copy it.

14:47 nymsy: they'll be complicated structs

14:47 Chousuke: nymsy: even better then: they won't be copied.

14:47 no assignment in java ever copies anything; except primitives.

14:48 WizardofWestmarc: Chouser: what about :a "bob" :b "bob"?

14:48 does bob show up twice in memory?

14:48 Chousuke: WizardofWestmarc: that's probably an implementation detail

14:48 nymsy: hmm

14:48 WizardofWestmarc: it could be specified in the jvm specification

14:48 Chouser: ,(apply identical? (map val {:a "bob" :b "bob"}))

14:48 clojurebot: true

14:48 WizardofWestmarc: so that all VMs would require it

14:49 Chouser: but I think Clojure is providing that and doesn't guarantee it.

14:49 nymsy: so where might this scheme cause a hicup?

14:49 Chouser: ,(apply identical? (map val {:a (String. "bob") :b "bob"}))

14:49 clojurebot: false

14:49 hiredman: ,(apply identical? (map val {:a (Object.) :b (Object .)})

14:49 clojurebot: Eval-in-box threw an exception:EOF while reading

14:49 hiredman: ,(apply identical? (map val {:a (Object.) :b (Object .)}))

14:49 clojurebot: java.lang.Exception: Expecting var, but Object is mapped to class java.lang.Object

14:49 hiredman: bah

14:50 Chousuke: the answer is going to be false :p

14:50 hiredman: strings are sort of magic

14:50 yeah

14:50 Chouser: nymsy: if you want to change something in a socket struct, you'll have to do that double-assoc again.

14:50 Chousuke: strings are guaranteed to be immutable so the JVM can optimise literals to be the same object.

14:51 Chouser: Chousuke: I think it's Clojure that's deciding to intern the strings. I don't think it's always done that.

14:51 hiredman: clojurebot: max people?

14:51 clojurebot: max people is 129

14:52 Chouser: nymsy: while if you had *nicks* that only pointed to uids, then you'd only have to update *clients* for changes to client struct.

14:52 Chousuke: unless you use refs; like (def a (ref {:a 1})) (def b a), (dosync (commute a assoc :b 1)) @b ; -> {:a 1 :b 1}

14:52 nymsy: Ok, better than socket, lets say (assoc *clients* "bob" client-struct-1 111 client-struct-1)

14:53 Chouser: sorry, I meant "client struct" not "socket struct"

14:54 nymsy: oughtn't, if I make changes to client-struct-1, elsewhere, "bob" and 111 both point to the new client-struct-1 that reflects those changes?

14:54 Chousuke: nymsy: no.

14:54 Chouser: but if client-struct-1 is just a struct (and not a ref as Chousuke is suggesting) you can't actually change it. you can only make a new one based on the old one

14:54 nymsy: hmm.. associng "bob" to a new value will leave the old value attached to 111

14:55 Chouser: ...in which case you have to put that new struct back into the map in all the appropriate places.

14:55 nymsy: right.

14:55 Chousuke: nymsy: that's exactly how it's supposed to be.

14:55 nymsy: so (assoc *client* "bob" struct-ref 111 struct-ref)

14:56 Chousuke: nymsy: that might work.

14:56 hiredman: so you write a double-assoc fn

14:56 Chousuke: but I'd rather do two separate maps.

14:56 one with nicks to ids and one with id -> struct

14:56 then, whenever I want to "modify" a struct, I actually just do assoc-in on the id->struct map

14:57 yielding a new id->struct map

14:57 hiredman: is there a reason why you need both? why not have nick or uid as part of the struct?

14:57 and the other as the key?

14:57 Chousuke: hiredman: he needs to look them up using either.

14:57 hiredman: :(

14:58 sounds like two maps then

14:58 nymsy: I could look them up as uids most of the time, and then scan the whole think when nicks are needed, or vice versa, which is what I'm doing now

14:59 Chousuke: having two maps is easier IMO :/

14:59 Chouser: do you ever need to go from uid to nick?

14:59 nymsy: When updating nick

14:59 Chouser: or only from (nick or uid) to struct

14:59 Chousuke: but having the nick and UID in the *same* map as keys pointing to a struct is wrong, IMO.

15:00 because then you need to update both

15:00 or use refs, but that's a bit ugly too

15:00 hiredman: ,(let [x (ref :somestruct)] [{111 x} {"bob" x}])

15:00 clojurebot: [{111 #<Ref clojure.lang.Ref@8730b8>} {"bob" #<Ref clojure.lang.Ref@8730b8>}]

15:01 Chousuke: yeah, that would work, but is rather ugly.

15:01 hiredman: Chousuke: if you don't println it, it won't see it :P

15:01 nymsy: Whys it ugly? I think it's pretty

15:01 Chousuke: you'll have lots of refs though :/

15:04 nymsy: here's another aspect of the program that needs consideration... a) it's going to be p2p.. each user will have server code, which synchronizes with all other user's servers, and distributes messages.. b) I still have to implement rooms

15:04 hiredman: !

15:05 nymsy: a server can have more than one client hanging off of it, but the normal use case will be one gui client connected to the server code locally

15:05 yes! :)

15:05 so thats another ref for *rooms*

15:05 and another for *servers*

15:07 so how to manage nicks and uids is important

15:08 do I map uids to rooms and servers, or nicks? probably uids

15:14 fffej: If I have two functions A and B that both call each other, how should I declare them in a CLJ file such that I don't get a "unable to resolve symbol" error when I compile them?

15:14 Chouser: (doc declare)

15:14 clojurebot: defs the supplied var names with no bindings, useful for making forward declarations.; arglists ([& names])

15:14 fffej: thanks!

15:14 nymsy: hmm. typo in the message struct. :dest and :room are the same. anyway, if a client sends text into a room, the client code puts the room name in :dest/:room. Then the server does a doseq on the room collection with .println to the :output of each

15:19 Or I could add a :rooms key to the client struct

15:19 hiredman: it might be easiest to have rooms as a special type of user

15:20 Chouser: so then a msg to a room would require walking the list of all clients, checking each to see if their in the target room?

15:20 nymsy: and pass *clients* to broadcast-to-room [clients msg]

15:20 hiredman: so when a user sends to a :room user, it gets sent to all the other users that are talking to that room

15:20 WizardofWestmarc: that or keep an updated list of users by room

15:21 so when they move room remove from old room add to the new room

15:22 nymsy: WizardofWestmarc: I'm thinking the server won't deal with context switching between rooms, only the client rendering code will, if you know what I mean

15:22 WizardofWestmarc: then just write a macro to both change the structure's room # and update the room list's info

15:22 eh

15:22 if you want to send info to specific rooms from the server I would keep that info server side as well

15:23 nymsy: well, a user can be in many rooms

15:23 cooldude127: i thought clojure-mode was fixed to work for imenu stuff, but i only get one symbol, a defstruct (because it's also used in CL)

15:23 WizardofWestmarc: ah

15:23 still

15:23 then just remove the always remove constraint

15:23 but I'd STILL keep a hash of rooms that contain a list of users in that room

15:24 hiredman: nymsy: someone, technomancy?, is doing some kind of clojure tutorial writing a muc, which might be interesting to look at

15:24 nymsy: right, thats the other option

15:24 hiredman: wilco

15:25 WizardofWestmarc: yeah Technomancy's doing it

15:25 it's in his github acct

15:25 hiredman: orly

15:25 cooldude127: ya rly

15:25 where is that guy anyway?

15:26 hiredman: ah http://github.com/technomancy/mire/tree/master

15:26 nymsy: that other option: a map of rooms to lists of users.. a map of servers to lists of users.. a map of nicks, to uids, and a map of uids to clients

15:27 Chouser: nymsy: that strikes me as the most natural approach.

15:28 nymsy: the other option is to use a #{} with a client struct that has all of those specific key values, and just scan the set for those desired keys each time, passing the whole *clients* in to each function.. (which seems more functional, than maintaining all these globals.. though it seems less efficient)

15:28 Chouser: on the other hand, I'm curious about the possibility of having a set of maps (like you did originally) as the "canonical form" of everything. Then when something changes use clojure.set/index to recreate the various maps.

15:29 nymsy: clojure.set/index?

15:29 hiredman: ,(doc clojure.set/index)

15:29 clojurebot: "([xrel ks]); Returns a map of the distinct values of ks in the xrel mapped to a set of the maps in xrel with the corresponding values of ks."

15:29 hiredman: mine just exploded

15:29 my head just exploded

15:29 nymsy: me too :)

15:29 Chouser: I've not written anything in that style, and I don't know how convenient or efficient that might be.

15:30 durka42: sounds similar to group-by

15:30 nymsy: I'd like, also, for this to be an example of doing distributed text chat in a functional way

15:30 minimizing global state and maximizing the sharing of immutable messages

15:31 hiredman: you could do trees with zipper :P

15:31 Chouser: yikes

15:31 nymsy: Chouser: I see the doc, but I don't really see it.. can you explain how indexing helps here?

15:33 Chouser: the way we've desribed all these global maps suggests that any code that makes changes to them would have all the logic built in to go update each of the things that must be kept in sync.

15:33 right?

15:33 nymsy: right...

15:33 hiredman: ,(doc defonce)

15:33 clojurebot: "([name expr]); defs name to have the root value of the expr iff the named var has no root value, else expr is unevaluated"

15:33 hiredman: no kidding

15:34 Chouser: like an update-nick function would have to know to fix *nicks* and also go find the right client struct in *clients* and update the :nick value there.

15:34 that might be the most complicated one, which still isn't too terrible.

15:34 nymsy: exactly

15:35 Chouser: but if there are more interconnected changes that have to be made, and more functions to make these changes, the possibility of a bug in one of them that gets things into a "wrong state" becomes more likely

15:36 nymsy: right.. that's what worries me about the copulating *maps*

15:36 Chouser: so one way to reduce that likelihood would be to store a canoncial state of things with no duplicate information, so that there can be no "bad" state.

15:36 nymsy: right

15:36 Chouser: so, for example, the layout you had at the beginning. a set of structs.

15:38 then anywhere that wants to make any change at all to the state of the world would start with that set, muck around with it until it reflects the new state of the world, and pass it to a single make-it-so fn

15:38 nymsy: which is how it is now?

15:39 Chouser: make-it-so could then use clojure.set/index to compute new nick-to-client, uid-to-client, room-to-client, etc. maps, and in a dosync swap refs to point to this new state.

15:40 nymsy: oh... wow

15:40 Chouser: that way all your lookups are still fast and convenient

15:40 all the 'read' code would be quite simple, and even the 'update' code would be more simple than the alternative.

15:41 nymsy: hmm.. index attaches an index number to each item in the set? at the top level?

15:41 Chouser: the downside (or one of them, I think) would be that make-it-so would be O(n) on clients. :-/

15:41 nymsy: ah, on, it pulls out a key from the set of maps, and makes a map to go from ...

15:42 hang on...

15:44 ,(let [myset '#{{a 1 b 2} {a 3 b 4} {a 5 b 6}}, idx (set/index myset '[b])user=> (let [myset '#{{a 1 b 2} {a 3 b 4} {a 5 b 6}}, idx (set/index myset '[b])] (idx {'b 6}))

15:44 clojurebot: Eval-in-box threw an exception:EOF while reading

15:44 cooldude127: someone has unbalanced parens :)

15:45 or just too much stuff copied

15:45 Chouser: nasty paste error. sorry

15:45 ,(let [myset '#{{a 1 b 2} {a 3 b 4} {a 5 b 6}}, idx (set/index myset '[b])] (idx {'b 6}))

15:45 clojurebot: #{{b 6, a 5}}

15:45 Lau_of_DK: Chouser: If you chat from ERC you get Lisp highlighting in your chat :)

15:45 Chouser: ok, so there's your canonical set, "myset"

15:46 nymsy: rgr

15:46 Chouser: using set/index gives me a map from

15:46 from {b ..whatever..} to the whole struct

15:46 knapr: http://cpp.ninjacodemonkeys.org/5080 , is that starting the player before ti starts the thread and thus the player doesnt run in the thread?

15:47 Chouser: so then it's easy to look things up based on values of b

15:47 but I could just as easily produce as many indexes for as many different keys as I want.

15:48 hiredman: knapr: you most likely want #(.play player)

15:48 nymsy: ok.. so it kinda does better what my for-filter did.. return the map in which the given has a given key with a given value

15:48 hiredman: knapr: unless (.play player) returns a Runnable

15:49 Chouser: nymsy: right, very similar, but instead of doing a linear lookup each time you need something, this takes that linear hit once and returns a map that you can use for any number of lookups

15:49 hiredman: Thread. will take 0 or 1 arg, the one are being a function of no arguments

15:49 Chouser: ...until someone changes rooms or nicks, and then you have to reproduce all the maps.

15:49 hiredman: which #(.play player) will give you

15:50 knapr: hiredman: ok and then it is started when i start the thread?

15:50 hiredman: yes

15:51 nymsy: Chouser: here's my idea on world-view consistency... once someone hits the enter key on the keyboard, *clients* and msg become frozen for that msg

15:51 knapr: hiredman: thanks! that works.

15:51 nymsy: so I deref *clients* once for each message

15:52 Chouser: nymsy: sounds reasonable.

15:52 nymsy: the rest of the pathway logic assumes that worldview.. so would it hurt to reindex on each message creation?

15:53 Chouser: might be more work than necessary, if multiple messages are sent between world state changes, which seems likely.

15:54 hiredman: you toggle a dirty bit when you dirty something

15:54 Chouser: I'm mostly uncomfortable with the O(n)'ness of the whole thing. Everything's going to slow down the more users you've got, even if they're only one person is talking to one other person.

15:54 nymsy: well, theres one key that updates often

15:55 the new one that isn't used yet, :last-action-time ... which I thought I'd use to create a connection time-out facility

15:56 BigTom: Hi

15:56 nymsy: hello

15:56 drewr: Has anyone had any problems using clojure.contrib.sql with postgres?

15:56 BigTom: I am doing something dumb

15:57 nymsy: Chouser: how bad is O(n) ?

15:57 BigTom: I think

15:57 Chouser: nymsy: double the number of users, double the processing time.

15:57 BigTom: I am getting a stack overflow on a recur but I cannot see why

15:57 Chouser: now the theorists are going to hang me, but that's the idea anyway.

15:57 nymsy: Oh.. log(n) is the better one, right?

15:57 Hun: why? it's correct.

15:58 but you should always look at the constants

15:58 Chouser: nymsy: O(1) < O(log(n)) < O(n) < O(n*log(n)) < O(n*n) ...

15:58 BigTom: are there any common mistakes that do that?

15:58 Hun: when n are only your users, and you're thinking about people, O(n) might cut it

15:58 hiredman: BigTom: lets see some code

15:58 Chouser: those are the commone ones.

15:59 Hun: as the growing of population will sooner or later stop. usually before O(n) on it becomes a problem

15:59 hiredman: Hun: and people die

15:59 Chouser: Hun: are you a theorist? Are you not hanging me!?

15:59 Hun: Chouser: computer science student, 7th semester

16:00 BigTom: hmm, hang on, I'm on two machines

16:00 Chouser: BigTom: i think we're going to have to see the code.

16:00 oh, sorry, someone already asked.

16:00 Hun: i've seen enough theorists forget to mention that you also have to look at the order of magnitude of n

16:00 hiredman: fewer than are born

16:00 growth is still an exponential curve. that means it will sooner or later crash :)

16:00 Chouser: Well, I thought someone would complain that I said "processing time" instead of "complexity" or something.

16:00 BigTom: how much can I post on here?

16:01 Chouser: BigTom: use lisppaste for more than 1 line

16:01 hiredman: clojurebot: paste?

16:01 clojurebot: lisppaste8, url

16:01 nymsy: if you have to ask...

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

16:02 hiredman: clojurebot: what is the most horrible thing?

16:02 clojurebot: the most horrible thing is http://themosthorriblething.com/index.php?h=my+algorithm+is+O%28n*n%29

16:02 lisppaste8: BigTom pasted "recur problem" at http://paste.lisp.org/display/74372

16:02 nymsy: so... since this is a "distributed" p2p chat room.. the mesh couldem have hundreds of rooms... but the user will only be in 1 to maybe 10 or th

16:02 Hun: Chouser: the complexity ain't gonna change

16:03 that problem is intrinsically bound by O(n)

16:03 you sooner or later have to see every entry in the relation user <=> room for doing a dispatch

16:03 nymsy: not all the time

16:04 Hun: so you can't get lower. you can just cut it for dispatching only on the current room

16:04 and if it's just O(n) for a single room, so be it

16:04 nymsy: only users you see in rooms your in, at a constant rate.. for interactive consistency

16:04 Hun: there are a lot bigger fish to fry until profiling

16:05 AWizzArd: I think it was on reddit where I read that until recently Clojure represented closures internally as anon Java classes. And those can't be garbage collected.

16:05 Do I remember that correctly?

16:05 nymsy: those people you don't see, you don't need to interact with immediately.. so I could use other logic for trying to find a user, by nick, that is not in my main *clients* list, for example, right?

16:06 Chouser: AWizzArd: a compiled fn still is a Java class, but if created via 'eval' will now be GC'd

16:06 Hun: AWizzArd: i think (not sure) that are the closure class, not the instance

16:07 so your code won't leak if you use closures in a loop, but memory consumption will be constantly sligthly higher

16:07 knapr: what I dont understnad is how to stop or pause the thread from executing. stop is deprecated. I tried interrupt but it doesnt do anything.

16:07 hiredman: do you know how to pause a thread?

16:07 AWizzArd: knapr: from outside of a thread you mean?

16:08 hiredman: BigTom: I am not sure, but you may want to filter (rest ns) not ns

16:09 AWizzArd: knapr: check out http://java.sun.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

16:09 "What should I use instead of Thread.stop?" is your question

16:09 hiredman: knapr: I am bet the player has some sort of pause method, I would recommend using that instead of pausing the thread

16:10 nymsy: yea, I'm not overly worried about the O(n) of it. As long as *clients* doesn't list all clients in the web, just those in the rooms your connected to. I mean, on average, how many people do you see, if you add up all the people in all the rooms you're in on irc, on average?

16:10 hiredman: AWizzArd: he is writting an mp3 player, and, having gotten it to play, he wants to get it to pause

16:10 nymsy: (I'm probably a less than average case)

16:11 AWizzArd: knapr: also think about Rich Hickeys "ants.clj" example, where he uses the variable *running* for signalling a stop.

16:11 BigTom: hiredman: Doh! Told you it was something stupid

16:11 hiredman: thanks

16:11 hiredman: there are 647 people in #haskell

16:11 BigTom: did that fix it? I said I wasn't sure

16:11 AWizzArd: clojurebot: max people

16:11 clojurebot: max people is 129

16:11 nymsy: youch

16:12 AWizzArd: let's not forget this number was around 80 a few months ago

16:12 hiredman: clojurebot's max people was broken for a day or two

16:12 Hun: nymsy: about 1200, all channels i'm in combined. with about 200 collisions

16:12 hiredman: so maybe it missed everyone

16:12 BigTom: hiredman: yes, still slow as hell, it was frustrating because this is where I am starting from

16:13 nymsy: Hun.. Would you say you're average?

16:13 (in terms of irc connectedness?)

16:13 Hun: not really. considering irc, most people are way fewer

16:13 BigTom: ah, spoke too soon, its just happening later on

16:13 Hun: bad english. most people are in fewer channels

16:13 at least those i know. i'd say about 400 might be a good average case

16:14 BigTom: hiredman: I put the whole thing up, it is breaking somewhere between 10,000 and 100,000

16:14 Lau_of_DK: Is the code on Sourceforge still current ?

16:15 nymsy: right... then people have their instant messaging going on.. so we'll say a liberal average is 500?.. so 500 clients.. say, 10 keys per client struct...

16:15 AWizzArd: hiredman: btw, does the clojurebot automatically deny all forms in which *compile-path* is used?

16:15 ,*compile-path*

16:15 ,(print *compile-path*)

16:15 clojurebot: nil

16:16 nymsy: any ninjas out there able to discern the complexity of an indexing operation on 500 clients with 10 keys?

16:16 AWizzArd: hmm, funny, some hours ago it responded with ,,denied"

16:16 nymsy: for this particular situation?

16:16 Hun: nymsy: neglectable for now

16:16 nymsy: Hun: I agree

16:16 Hun: you'd have a hard time measuring it with 10000 test users

16:16 BigTom: Should you ever get StackOverflow with recur? if it is coded correctly?

16:17 Hun: should be easy with 100000 users. get to that point before optimizing :)

16:17 nymsy: heh

16:18 Chouser: BigTom: the 'recur' itself can't be consuming any stack, but that something being done within each pass of the loop could indeed consume stack.

16:18 nymsy: anyone guestimate how long it would take to scan a set of 500 structs with 10 keys each?

16:18 Chouser: no need to guess.

16:18 Hun: nymsy: what do you mean by scan?

16:18 hiredman: nymsy: compared to the time to send/recv messages? none at all

16:19 by that I mean network io

16:19 BigTom: Chouser: so something is hanging onto stack frames somewhere?

16:20 hiredman: clojurebot: Sieve?

16:20 clojurebot: No entiendo

16:20 hiredman: clojurebot: google Genuine Sieve of Eratosthenes

16:20 clojurebot: First, out of 850 results is:

16:20 The Genuine Sieve of Eratosthenes

16:20 http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

16:21 BigTom: hiredman: is that for me?

16:22 hiredman: BigTom: it may help

16:22 BigTom: :-)

16:22 Chouser: ,(time (let [myset (reduce #(conj % {0 %2 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0}) #{} (range 500)), idx (set/index myset [0])] (idx {0 99})))

16:22 clojurebot: #{{0 99, 1 0, 2 0, 3 0, 4 0, 5 0, 6 0, 7 0, 8 0, 9 0}}

16:22 "Elapsed time: 121.706 msecs"

16:22 hiredman: I think the code is all in haskell, so it may just kill you

16:23 BigTom: ah well

16:23 Chouser: one tenth of a second to create the set and all the maps from scratch, index them, and look up one of them.

16:23 BigTom: I knew I would have to have a proper go at it eventually

16:24 It can go on the pile with the pythagorean triples

16:25 nymsy: wow

16:25 thats ninja right there

16:26 Chouser: yeah, clojure is definitely too fast. Rich should sneak in a spin delay somewhere so he can "add speed" later as needed.

16:27 ecret: AWizzArd: I am trying to compile hello.clj to try to get classes working in clojure. I have the file in /home/eli/clojure/classes/junk/hello.clj to compile it I go (binding [*compile-path* "/home/eli/clojure/classes/"] (compile 'junk.hello)) but this does not work. I get java.lang.Exception: namespace 'junk.hello' not found after loading '/junk/hello' (NO_SOURCE_FILE:0)

16:27 Any idea what is wrong? I did what yoou suggested, i added /home/eli/clojure/classes to my classpaths

16:30 BigTom: Just to clarify something, recur is not a total substitute for Tail call is it?

16:30 Hun: it isn't

16:30 a tail call can call another function

16:30 BigTom: You cannot build results on the climb out from the recursion

16:30 knapr: hmm but isnt there jsut a simple way to kill a thread forever?

16:30 and the damn player only has stop the player nad play it so not a very complete library. and doing stop on the player doesnt work

16:30 BigTom: so you have to use some kind of aggregator

16:30 nymsy: so, out of 500 users, where events are nick changes and room enter/leave ... how many events happen per second? probably less that ten... but I could put all change events in a queue and, if there's traffic, the cpus running hot, theres lots to do, i could throttle events at 5 a second.

16:30 Hun: that means that you can have f => g(x) and g => f(x)

16:30 and it works

16:31 BigTom: that's the trick in tail recursion

16:31 Chouser: BigTom: no, building values while returning isn't a tail call, so won't be optimized by normal TCO either.

16:31 knapr: how do i pronounce sieve?

16:31 Hun: it works well if you have an iterative algorithm. that means `doesn't need to do anything to clean stuff up'

16:31 hiredman: BigTom: as far as I am aware, in proper tail calls you also need an accumulator

16:31 Hun: hiredman: nope.

16:32 Chouser: knapr: dunno how you pronounce it, but I say "siv"

16:32 hiredman: Hun: ok, you don't need, but you would need one to do what he is talking about

16:32 Hun: the accumulator is needed to translate a recursive algorithm into a tailrecursive into an iteration

16:32 yep

16:32 BigTom: MAybe I am misremembering

16:32 nymsy: i think its seeve.. like, to _leave_ something some where

16:32 Hun: and using an accumulator is /very/ pointless

16:32 hiredman: clojurebot: whose job is to current hiredman when he says something that is not completely 100% correct?

16:32 clojurebot: that is scode's job

16:33 hiredman: Hun: see, it isn't even your job

16:33 Hun: you're exchanging the system's tested and good stack implementation for your own ad-hoc one

16:33 hiredman: so what? :)

16:33 hiredman: :P

16:34 Chouser: "sieve" rhymes with "give": http://en.wiktionary.org/wiki/sieve

16:34 Hun: i'm having an exam tomorrow and want to hang out in irc to forget it for now :)

16:34 BigTom: Hun: confused now, if I want to accumulate a value via recursion and TCO what do I do?

16:34 Hun: BigTom: you might as well just use recursion

16:34 Chouser: nymsy: I really wouldn't worry about throttling and such until you see it.

16:34 Hun: when you need an accumulator for tail recursion, you need /exactly/ as much space and time as when using recursion

16:34 hiredman: BigTom: you might as well use reduce

16:35 Hun: (in a proper working compiler at least)

16:35 BigTom: and think about it

16:35 Chouser: nymsy: regardless if you've got an O(1) or O(n) algorithm underneath. :-)

16:35 Hun: when your problem is so hard that you can't use one of the usual combinators, it's usually to hard to be expressed in a simple recursion either :)

16:35 hiredman: ,(reduce + 0 (range 10))

16:35 clojurebot: 45

16:36 nymsy: Chouser: aye

16:36 hiredman: ,(reduce conj [] (range 10))

16:36 clojurebot: [0 1 2 3 4 5 6 7 8 9]

16:36 nymsy: Chouser: I think you hit the nail on the head with the indexing

16:36 kotarak: ,(into [] (range 10))

16:36 clojurebot: [0 1 2 3 4 5 6 7 8 9]

16:36 nymsy: I appreciate the help

16:36 hiredman: kotarak: I was demonstrating recude

16:36 Chouser: nymsy: well, I'd be curious to know how it goes.

16:36 hiredman: reduce

16:37 BigTom: Thanks, maybe I need to rethink stuff

16:37 My scheme days are long past

16:37 Hun: that's the proper way to think :)

16:37 Chouser: nymsy: like I said, I've not actually used that kind of pattern yet.

16:37 kotarak: hiredman: geez. Rich had to show me this twice before I remembered into. :]

16:38 BigTom: Hun: so when do you use recur?

16:38 nymsy: chouser: it seems more functional, right? I think it's the way to go.. also easier than keeping track of all those globals

16:41 If there were a way to update the indexes automatically, without having to rebuild the whole thing, it'd make for a good pattern in general

16:41 Hun: BigTom: i usually don't. i try to use the normal combinators, or build a full-fetched state-machine

16:41 bakkdoor: hi.

16:41 hiredman: fetched?

16:41 BigTom: Hun: fair enough

16:41 Hun: for the state-machine, recur is good enough

16:42 BigTom: Hun: this is my first hard core foray into Functional approaches so I'll take all the advice I can

16:42 bakkdoor: is there an easy way to cast numbers to chars? for example, i have a sequence of hexadecimal numbers and want to convert it into its corresponding character string

16:42 Hun: if you tried it once, a state machine can be expressed pretty well by recursion when you have TCO

16:42 hiredman: I think I used different seq functions more then recur for project euler stuff

16:42 BigTom: hiredman: interesting

16:42 hiredman: filter, map, for

16:43 BigTom: hun: what are the normal combinators?

16:43 hiredman: like for primes I have a lazy seq that sieves out non-primes

16:43 Hun: map, reduce, filter (and specializations of those)

16:43 hiredman: I think I may have stole that from the google group though

16:43 Hun: i'm not sure what extended versions are in clojure right now.

16:43 combinators are fun :)

16:43 hiredman: apply

16:44 BigTom: Thanks, I have another avenue to study

16:44 hiredman: hmmm

16:44 looking at my euler.clj I did use recur for #10

16:44 Hun: map and filter are easy. take your time with reduce. it's mighty and a bit non-intuitive

16:45 BigTom: Hun: funnily I am fairly happy with reduce, I think it is hard in most languages so I worked on it

16:46 I think I really need to get my head around laziness

16:46 Hun: yep. i suggest reading the stream chapter in SICP

16:46 hiredman: clojurebot: sicp

16:46 clojurebot: sicp is http://www.codepoetics.com/wiki/index.php?title=Topics:SICP_in_other_languages:Clojure:Chapter_1

16:46 Hun: eye-opening for lazy stuff

16:46 hiredman: gah

16:46 BigTom: hiredman: gah?

16:46 hiredman: clojurebot: don't you know where the pdf is?

16:46 clojurebot: Titim gan �ir� ort.

16:46 Hun: read the text and the code. reading just one doesn't really work

16:47 nymsy: hiredman: it took me months to find the pdf

16:47 hiredman: clojurebot: google sicp pdf

16:47 clojurebot: First, out of 18900 results is:

16:47 Structure and Interpretation of Computer Programs

16:47 http://deptinfo.unice.fr/~roy/sicp.pdf

16:47 nymsy: hmm

16:47 Hun: you're doing something wrong.

16:47 nymsy: heheheh

16:48 hiredman: yeah I watched the videos years before I ever found the pdf

16:48 nymsy: maybe it was the other one

16:48 the other four letter acronym, functional programming book

16:49 htpc

16:49 Hun: paip?

16:49 cooldude127: i wrote an AVL tree in clojure yesterday. today i wrote a red-black tree in clojure as well. the two files have the exact same number of lines. WEIRD

16:49 Hun: htwp

16:49 nymsy: how to program computers? or something?

16:49 Hun: write programs

16:49 nymsy: ah

16:49 Hun: it's nice, but doesn't have much depth

16:49 hiredman: cooldude127: be sure to throw salt over your left shoulder

16:49 nymsy: clojurebot: google htwp pdf

16:49 clojurebot: First, out of 255 results is:

16:49 cooldude127: hiredman: ?

16:49 clojurebot: HTWP - TORQUE WRENCH PUMPS

16:50 http://www.hi-force.com/Pages-download/Catalogues/English%20main%20pages/Page-089.pdf

16:50 Hun: hmm

16:50 ah

16:50 hiredman: Nice

16:50 Hun: how to DESIGN programs

16:50 cooldude127: well i need to go to class

16:50 Hun: paip is also very nice :)

16:50 BigTom: clojurebot: google how to design programs

16:50 clojurebot: First, out of 254000000 results is:

16:50 How to Design Programs

16:50 http://www.htdp.org/

16:50 nymsy: ahah

16:50 knapr: cooldude127: can you please post the code to your avl tree and redblack tree?

16:51 cooldude127: can you please post the code to your avl tree and redblack tree?

16:51 bakkdoor: is there an easy way to cast numbers to chars? for example, i have a sequence of hexadecimal numbers and want to convert it into its corresponding character string

16:51 nymsy: too late

16:51 hiredman: ,(map char (range 80 90))

16:51 clojurebot: (\P \Q \R \S \T \U \V \W \X \Y)

16:51 BigTom: Thanks for all the help, hacve to go

16:51 Hun: hf

16:52 bakkdoor: ah thanks

16:52 nymsy: bakkdoor: java can do it too, i think

16:52 knapr: how do I perform some actions when the user presses close in a GUI?

16:52 hiredman: char's in java are, I think, unsigned shorts

16:53 so int <-> char is fairly easy

16:53 nymsy: .onClose?

16:53 Hun: knapr: bind something to that event

16:53 knapr: is there something like : gui.onDestroy(doStuff); ?

16:53 nymsy: something like that

16:53 most swing tutorials, fwir, have it in there somewhere

16:53 hiredman: by faily easy I mean a nop

16:59 nymsy: ,(({"pr" (fn [x] (pr x))} "pr") "hi")

16:59 clojurebot: "hi"

16:59 nymsy: sweet

17:00 been thinking of setting up commands that way, in one large map

17:00 Hun: might be ok if your commands are computer generated. pretty bad for humans

17:00 nymsy: why?

17:00 Hun: ,(({"pr" (fn [x] (pr x))} "Pr") "hi")

17:00 clojurebot: java.lang.NullPointerException

17:01 Hun: any questions?

17:01 Chouser: ,(({"pr" pr} "pr") "hi")

17:01 clojurebot: "hi"

17:03 nymsy: true, true.. Hun: (def [msg "/nick nymsy"] (({"/nick" ... etc

17:04 Hun: parsing quasi-structured input is pretty hard

17:05 nymsy: aye, I made first-word and rest-words to parse the commands

17:05 works pretty good

17:06 Hun: did 2 parsers for a debugger. the first one was an ad-hoc one (homegrewn regexes with HUGE casetables), the second one uses a proper grammar

17:06 i lost one feature (being able to have pr expand to print), but the code got a whole lot better expandable

17:07 nymsy: yea, I'm not quite there yet :)

17:07 Hun: the completion was cool. (filter #(starts-with (car x) command-string) command-table)

17:07 more or less

17:08 Chouser: Hun: Clojure? Or some other lisp?

17:08 Hun: if more than one matches (s could be save or step), the list was of length > 1 and an error was signalled

17:08 Chouser: 'car' nm.

17:08 Hun: Chouser: CL

17:08 losely translated. it's hard to lose your car, you know

17:09 Chouser: but #() is hard to ignore. :-) ...or does CL do that too?

17:09 Hun: mine did

17:09 Chouser: :-)

17:09 Hun: that macro is pretty easy to write, you know. my implementation took 20 lines

17:09 * Chouser nods

17:10 Hun: though it used _1 and _2 instead of %1 and %2

17:10 i thought if adding key args to that would be nice (like (#(foo _bar) :bar 5) => 5

17:10 nymsy: well, gents.. it's been swell... **Chouser: thanks again for the index tip.. I'm racking out. see yall later

17:10 Hun: but that was a bit to hard

17:11 have fun

17:11 Chouser: nymsy: good luck in the deployment

17:11 nymsy: US? Nat'l guard? Anyway, I wish you well.

17:41 knapr: it seems to use windowlistener i have to implement a java interface, is that correct? how do I do that in Clojure?

17:41 Cark: ,(doc proxy)

17:41 clojurebot: "([class-and-interfaces args & fs]); class-and-interfaces - a vector of class names args - a (possibly empty) vector of arguments to the superclass constructor. f => (name [params*] body) or (name ([params*] body) ([params+] body) ...) Expands to code which creates a instance of a proxy class that implements the named class/interface(s) by calling the supplied fns. A single class, if provided, must be first. If not

17:42 Cark: or you could use genclass

17:42 walters: one trick that rhino does that *really* helps in java integration is for functions to transparently implement single-method interfaces, i don't see why clojure fns couldn't do that

17:42 Cark: or make a namespsace which will become your class

17:44 hiredman: walters: I think it is a performance deal breaker

17:44 but I forget

17:44 someone was here and asked rhickey about it

17:46 I imagine you could do that, but not completely transparently with a macro

17:46 (mk-interface java.some.Interface fn)

17:47 knapr: if i want to make an executable file for my mp3, do i first use compile then i use jar on that?

17:47 walters: yeah, that's equivalent to how groovy does it, you have to say { foo, bar -> stuff(); } as java.some.Interface

17:48 hiredman: knapr: http://clojure.org/compilation under "gen-class Examples" has an example stand alone jar

17:48 quick, name a single method java interface off the top of your head

17:48 walters: hiredman: FilenameFilter

17:50 hiredman: also, two of my personal projects make extensive use of them

17:50 AWizzArd: ,(print *ns*)

17:50 hiredman: ,(:name (bean (first (.getMethods java.io.FilenameFilter))))

17:50 clojurebot: #<Namespace sandbox>

17:50 "accept"

17:50 AWizzArd: ,(print (ns-publics 'sandbox))

17:50 clojurebot: {}

17:51 hiredman: ,(symbol (:name (bean (first (.getMethods java.io.FilenameFilter)))))

17:51 clojurebot: accept

17:52 hiredman: and then you just have the macro generate the relevent proxy form around that

17:52 AWizzArd: ,(count (ns-map 'sandbox))

17:52 clojurebot: 541

17:54 ecret: I am able to compile clojure classes but the whole reason I wanted to do that was so that java.lang.Class.forName("clojureclassname") would work in the java jar file that I called. But I am unable to (Class/forName "clojureclassname") as a test. I get java.lang.ClassNotFoundException: transcriber The brief code is at http://paste.lisp.org/display/74380

17:55 Does clojure support this mechanism?

17:56 AWizzArd: ecret: great, so you managed it to compile to .class files :-)

17:57 ecret: yes ! took 5 hours but it worked. I am not totally 100% sure which of the things I did fixed it but I am not going to meddle :>

17:57 AWizzArd: ;-)

17:57 ecret: pretty sure it was just the class path + the *compile thing* though

17:57 AWizzArd: yup

17:57 knapr: man i always get suck on the damn java classpath as soon as i dont use it for a while i get confused

17:57 AWizzArd: once you found out how they play together it can be done within seconds to minutes

17:58 ecret: yep

17:59 AWizzArd: ecret: so why do you want to do Class/forName? Is your goal to use code that you have written in Clojure inside of Java?

18:00 ecret: sort of. A Jar file I am accessing has this line : Class cls = Class.forName(className); where className is specified in a config.xml file that needs to belong to the caller of the jar file

18:02 the caller is the transcription.clj so transcription.class

18:07 scottj: What software could one use to make it easy to define a macro that takes an equation and outputs a function for each variable that solves for that variable?

18:07 knapr: if i have: C:/clojure/classes/progs/comex/ and in comex i have compileexample.class et al. then i ahve C:/clojure/progs/ and i ave progs.comex.compileexample.clj, how do i run that?

18:20 if i have: C:/clojure/classes/progs/comex/ and in comex i have compileexample.class et al. then i ahve C:/clojure/progs/ and i ave progs.comex.compileexample.clj, how do i run that?

18:42 cooldude127: technomancy: hey did something change in clojure-mode (or at least the one in emacs-starter-kit) to make clojure-enable-paredit not work?

18:43 technomancy: cooldude127: yeah, upstream didn't like the idea of making that a flag

18:43 check the comments in the clojure-mode header

18:43 cooldude127: ok

18:43 technomancy: the way he switched it to work is pretty reasonable

18:43 cooldude127: technomancy: that's the way it works for every other lisp actually

18:44 technomancy: oh cool

18:45 cooldude127: technomancy: do you ever notice yourself doing C-c C-c on elisp expressions and expecting it to work?

18:47 technomancy: cooldude127: I actually end up using C-c C-l most of the time

18:47 just my habit; need to spend some more quality time with the slime manual

18:47 cooldude127: oh, i'm addicted to compiling individual top-levels

18:48 but the real one to use is C-c C-k if you want to do the whole file

18:48 technomancy: what's the difference?

18:48 cooldude127: one prompts you for the file, and is evaling it i think (not sure about that), but C-c C-k just compiles it like you did C-c C-c on everything in the file

18:49 knapr: is how to deisng programs aimed at beginners?

18:49 cooldude127: knapr: i think so

18:49 knapr: it seems bsic just skimming through it?

18:49 dude:post your avn and redblack tree please

18:50 what is a good book on how to deisgn complex programs, preferrably in a functional way

18:50 cooldude127: knapr: k, but my RB tree doesn't do deletes yet btw

18:51 hiredman: cooldude127: you using clojure.zip for the trees?

18:51 cooldude127: hiredman: no, but i really should look at that

18:51 hiredman: they're pretty naive implementations, i'm just learning this stuff

18:51 technomancy: cooldude127: nice; one step fewer I guess

18:52 cooldude127: knapr: here they are: http://gist.github.com/53671

18:52 technomancy: yeah, i'm all about the efficiency

18:53 hiredman: holy shit, what are these zippers?

18:54 knapr: ok

18:54 cooldude127: hiredman: it's a good thing i didn't know about these before i wrote the avls, i had to translate that back to java, and zippers would not have made that easy

18:54 lol

18:54 hiredman: heh

18:55 so far I have avoided actually trying to figure out the intermediate output of munging stuff with zippers

18:55 cooldude127: hiredman: what do you mean?

18:57 hiredman: cooldude127: zippers sort of turn a data structure insideout as you move through it

18:57 and when you are done you "zip" it back up

18:58 cooldude127: oh jesus

18:58 yeah i'm not ready for that

18:58 knapr: so

18:58 how can I run

18:58 hiredman: it is neet because you move through a ds using ->

18:58 cooldude127: ok what do i do to make it so i can refer to clojure.zip as just zip?

18:58 hiredman: er ->

18:58 damn it

18:58 "->"

18:58 cooldude127: lol

18:59 i knew what you meant

18:59 hiredman: (require '[clojure.zip :as zip])

18:59 cooldude127: hiredman: in a ns form that would be (:require [clojure.zip :as zip]) ?

19:00 hiredman: yes

19:00 cooldude127: k

19:00 ok back to my avl tree, cuz no way am i mucking around with the RB tree when i barely understand both RB trees and zippers

19:01 can't mess with two things i don't understand at the same time

19:02 lisppaste8: knapr pasted "compiling java is hell" at http://paste.lisp.org/display/74384

19:02 knapr: someone can explain ^^ ? just how to run compiled clojure...

19:04 hiredman: knapr: on the compilation page where you saw that example, right under that example

19:04 java -cp ./classes:clojure.jar clojure.examples.hello Fred

19:05 knapr: where ./classes:clojure.jar is instead C:/clojure/clojure.jar? so why doesnt that work?

19:05 hiredman: ./classes needs to be replaced with the path to your classes directory and clojure.jar with the path to your clojure

19:05 knapr: and from where shouls it be run?anywhere?

19:05 hiredman: the classpath seperator on windwos is ;

19:05 not :

19:06 if you have full paths then you can run it from anywhere

19:12 knapr: sigh i cant get it to work, noclassdeffounderror

19:17 about function composition

19:17 (comp map map)

19:17 def that

19:17 (mmap inc [[1,2,3,4,5]])

19:17 java.lang.IllegalArgumentException: Wrong number of args passed to: core$map (NO_SOURCE_FILE:0)

19:18 in haskell that works

19:20 hiredman: well

19:20 this is not haskell

19:20 map, takes two args each time

19:21 and outputs a single value

19:21 so the first map outputs a single value, the second map gets a single value

19:21 but map takes two args

19:21 so no dice

19:22 ,(map (patial map inc) [(range 10) (range 20 30)])

19:22 clojurebot: java.lang.Exception: Unable to resolve symbol: patial in this context

19:22 hiredman: ,(map (partial map inc) [(range 10) (range 20 30)])

19:22 clojurebot: ((1 2 3 4 5 6 7 8 9 10) (21 22 23 24 25 26 27 28 29 30))

19:27 hiredman: clojurebot: for?

19:27 clojurebot: for is not a loop

19:27 hiredman: clojurebot: for is also not used often enough

19:27 clojurebot: Roger.

19:33 hiredman: my euler.clj is so embarresing

19:33 knapr: clojurebot: for?

19:33 clojurebot: for is not used often enough

19:33 knapr: clojurebot: for?

19:33 clojurebot: for is not used often enough

19:33 knapr: clojurebot: hiredmans euler.clj is so embarassing

19:33 clojurebot: 'Sea, mhuise.

19:34 knapr: clojurebot: hierdmans?

19:34 clojurebot: It's greek to me.

19:34 knapr: clojurebot: hiredmans?

19:34 clojurebot: hiredmans euler.clj is so embarassing

19:34 knapr: why?

19:35 clojurebot: meaning of life?

19:35 clojurebot: excusez-moi

19:35 knapr: clojurebot: meaning of life is to become one with Lisp

19:35 clojurebot: In Ordnung

19:35 knapr: clojurebot: meaning of life?

19:35 clojurebot: meaning of life is to become one with Lisp

19:35 hiredman: knapr: careful about over writing stuff

19:37 knapr: ok'

19:38 clojurebot: OO is to programming what astrology is to astronomy

19:38 clojurebot: Alles klar

19:38 knapr: clojurebot: OO?

19:38 clojurebot: OO is to programming what astrology is to astronomy

19:40 Cark: tss =)

19:41 gnuvince_: hahaha

19:56 cooldude127: hiredman: when using zippers, what's the best way to represent a binary tree? i was imagining vectors kinda like the example, but then i wondered what order to put elements in

20:01 knapr: http://paste.lisp.org/display/74384

20:02 cooldude127: knapr: that hasn't gotten worked out yet?

20:02 durka42: wouldn't you just do: java compleexample

20:02 compileexample

20:03 cooldude127: you need clojure on the classpath

20:03 durka42: with clojure.jar on the $CLASSPATH

20:03 knapr: i get wrong name

20:03 cooldude127: knapr: what do you mean?

20:03 durka42: NoClassDefFound?

20:04 knapr: yes

20:04 durka42: even though you have both clojure.jar and ...../prog/comex on the classpath

20:04 cooldude127: knapr: you should be in the classes folder, and run java -cp path/to/clojure.jar progs.comex.compileexample

20:04 knapr: Caused by: java.lang.ClassNotFoundException: C:.clojure.classes.progs.comex.comp

20:04 ileexample.class

20:05 cooldude127: java -cp .;c:\clojure\clojure.jar progs.comex.compileexample

20:06 knapr: ayay sir!

20:06 thanks

20:06 cooldude127: no problem

20:09 knapr: and when i have abig program with reuires and imports i add :gen-class the same way?

20:13 durka42: clojurebot: where's my list of exceptions?

20:13 clojurebot: http://paste.lisp.org/display/74305

20:14 lisppaste8: durka annotated #74305 with "errors" at http://paste.lisp.org/display/74305#1

20:14 durka42: ,(+ 840 92)

20:14 clojurebot: 932

20:19 knapr: woot i managed to compile and run my mp3player!

20:20 durka42: sweet

20:20 knapr: now i just need to make it executable without hocus-pocus

20:20 durka42: hocus pocus?

20:23 knapr: java classpath

20:31 gnuvince_: There's no literal syntax for longs, is there?

20:38 knapr: should I put my mp3player up at some wiki or something?

20:39 it contains quite a lot of interest for the CLojure-curious. GUI(swing+miglayuout+using clojure-contrib). basic threading. playing sound. a lot of interopearting with Java etc.

20:42 there is a lot of things being generated and created when compiling and running

20:42 which file/files do i need in the jar? just compileexample.class?

20:43 what about compileexample_init.class?

20:48 durka42: knapr: yeah, put it up on a wiki or github or lisppaste somewhere

20:48 you might also need clojure.jar

20:51 you might want to look at how gorilla does it

20:51 it has an ant script with an option for standalone build (unzips clojure.jar into gorilla.jar)

20:58 knapr: gorilla?

20:58 you mean it has a build.xml?

20:59 durka42: yes

21:01 http://bitbucket.org/kotarak/gorilla/src/

21:20 cooldude127: is there anymore documentation clojure's zippers besides what's on the site?

21:21 hiredman: I spent alot of zip flipping back and forth with zip.clj

21:21 hah

21:21 a lot of time flipping

21:21 cooldude127: lol

21:27 hiredman: i'm trying to figure out how to write a zipper that will let me get at the data in the tree and still get at the left and right nodes using zip/left and zip/right, idk what i'm doing tho

21:28 hiredman: ,(require '[clojure.zip :as zip])

21:28 clojurebot: nil

21:29 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip)

21:29 clojurebot: [(+ 1 3 (* 2 4)) nil]

21:29 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/down)

21:29 clojurebot: [+ {:l [], :pnodes [(+ 1 3 (* 2 4))], :ppath nil, :r (1 3 (* 2 4))}]

21:29 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/down zip/node)

21:29 clojurebot: +

21:29 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/down zip/right zip/node)

21:29 clojurebot: 1

21:31 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/down zip/right zip/right zip/right zip/node)

21:31 clojurebot: (* 2 4)

21:31 hiredman: wheee!

21:31 cooldude127: hiredman: that's not what i want tho, i want to be able to go down, then go left or right to the the left or right subtree

21:31 gnuvince_: ,(doc get)

21:31 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

21:32 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/down zip/node)

21:32 clojurebot: +

21:32 gnuvince_: Is there a reason to use get instead of using a map as a functin?

21:32 function*

21:32 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/children)

21:32 clojurebot: (+ 1 3 (* 2 4))

21:32 Chousuke: gnuvince_: perhaps its clearer in some cases?

21:33 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/lefts zip/node)

21:33 clojurebot: java.lang.NullPointerException

21:33 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/lefts)

21:33 clojurebot: nil

21:33 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/rights)

21:33 clojurebot: nil

21:33 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/down zip/rights)

21:33 clojurebot: (1 3 (* 2 4))

21:33 hiredman: ,(-> '(+ 1 3 (* 2 4)) zip/seq-zip zip/down zip/lefts)

21:33 clojurebot: nil

21:33 hiredman: hmm

21:34 cooldude127: hiredman: i guess what i want is for it to start at the data, then be able to go left or right from there, instead of always starting at the beginning

21:34 hiredman: ,(-> '((1 1) 1 3 (* 2 4)) zip/seq-zip zip/down zip/lefts)

21:34 clojurebot: nil

21:35 hiredman: you are at a leaf, and want to head left from the leaf?

21:36 bradbev: Hi guys. How much memory does an instance of a struct-map consume?

21:36 cooldude127: hiredman: i want something like this: [[[1] 2 [3]] 4 [[5] 6 [7]]] for a binary tree, and for it to start in the middle

21:36 hiredman: dunno

21:38 bradbev: I want to write a memory logging application, each alloc should be represented by a struct-map, with about 7 keys, so I'd guess 7*4 = about 28 bytes. I want to put every alloc into a map keyed on its address, and keep a list of all maps through time. That should be ok due to structure sharing.

21:38 hiredman: (-> [[[1] 2 [3]] 4 [[5] 6 [7]]] zip/vector-zip)

21:38 ,(-> [[[1] 2 [3]] 4 [[5] 6 [7]]] zip/vector-zip)

21:38 clojurebot: [[[[1] 2 [3]] 4 [[5] 6 [7]]] nil]

21:38 hiredman: ,(-> [[[1] 2 [3]] 4 [[5] 6 [7]]] zip/vector-zip zip/down zip/node)

21:38 clojurebot: [[1] 2 [3]]

21:38 bradbev: The problem is that my 7 key struct injected into a map 750,000 times is about 438Mb

21:39 cooldude127: hiredman: see that should be 4 in my ideal case

21:39 lisppaste8: knapr pasted "making an exec jar" at http://paste.lisp.org/display/74391

21:39 hiredman: ,(-> [[[1] 2 [3]] 4 [[5] 6 [7]]] zip/vector-zip zip/down zip/left zip/left zip/node)

21:39 clojurebot: java.lang.NullPointerException

21:39 bradbev: if I inject 750,000 ints into a vector, then it is only a handful of MB

21:39 hiredman: ,(-> [[[1] 2 [3]] 4 [[5] 6 [7]]] zip/vector-zip zip/down zip/node)

21:39 clojurebot: [[1] 2 [3]]

21:39 hiredman: ,(-> [[[1] 2 [3]] 4 [[5] 6 [7]]] zip/vector-zip zip/left zip/left zip/node)

21:39 bradbev: so, I'd guess structmaps are huge

21:39 clojurebot: java.lang.NullPointerException

21:39 bradbev: any thoughts?

21:40 hiredman: ,(-> [[[1] 2 [3]] 4 [[5] 6 [7]]] zip/vector-zip zip/down zip/right zip/node)

21:40 clojurebot: 4

21:40 hiredman: duh

21:40 cooldude127: hiredman: yeah i know you could do it that way, but it feels counter intuitive

21:41 hiredman: sorry I meant duh for myself

21:41 cooldude127: i figured

21:42 hiredman: i considered doing it prorder, like [data left right], but then it's still right and right -> right, instead of left and right

21:43 bradbev: Hmm, OK ref object appear to be quite large

21:44 hiredman: cooldude127: you can make your own zipper

21:44 cooldude127: hiredman: yeah i'm looking into figuring out how to make that work correctly

21:47 knapr: http://paste.lisp.org/display/74391 , <- i cant get it to work(making an exec jar). i looked at gorilla but it was to complicated

21:49 cooldude127: hiredman: damnit this is confusing

21:50 hiredman: Yes

21:50 but that does make it less cool

21:51 cooldude127: hiredman: is there anyway to make a zipper go down, and then be able to make an immediate left? at all?

21:52 hiredman: ,(doc zip/down)

21:52 clojurebot: "([loc]); Returns the loc of the leftmost child of the node at this loc, or nil if no children"

21:52 cooldude127: hiredman: so no?

21:52 hiredman: down should hit the left

21:53 cooldude127: hiredman: maybe i just write my own left and right functions that do the right thing?

21:54 hiredman: you could do that

21:55 knapr: wheres does the expr hiredman come from?

21:55 i heard it in the office

21:56 hiredman: I borrowed it from a gibson book

21:57 Count Zero, I believe

22:08 * gnuvince_ sucks at macros

22:10 johan1: hmm, I still don't get Java interop. I'm trying to call a method setCoordinates(arg), where arg is int[]. In Clojure I try (.setCoordinates [1 2 3]) which doesn't work. Any idea on how to create a int[] argument from clojure?

22:10 durka42: you didn't pass the object

22:10 {what?}.setCoordinates()

22:10 johan1: that's a typo

22:10 it is correct in my code, but the argument is wrong

22:10 durka42: oh ok

22:11 in that case i'm not sure

22:11 maybe:

22:11 (doc make-array)

22:11 clojurebot: Creates and returns an array of instances of the specified class of the specified dimension(s). Note that a class object is required. Class objects can be obtained by using their imported or fully-qualified name. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE.; arglists ([type len] [type dim & more-dims])

22:11 cooldude127: also:

22:11 (doc into-array)

22:11 clojurebot: Returns an array with components set to the values in aseq. The array's component type is type if provided, or the type of the first value in aseq if present, or Object. All values in aseq must be compatible with the component type. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE.; arglists ([aseq] [type aseq])

22:11 durka42: ,(into-array [1 2 3])

22:11 clojurebot: #<Integer[] [Ljava.lang.Integer;@1f9b804>

22:12 johan1: ok, I will give it a try

22:12 hiredman: vectors are not java arrays

22:12 cooldude127: they are objects

22:12 ,(class [1 2 3])

22:12 clojurebot: clojure.lang.LazilyPersistentVector

22:12 hiredman: ,(class (into-array [1 2 3]))

22:12 clojurebot: [Ljava.lang.Integer;

22:12 hiredman: so are java arrays

22:12 you most likely want ints not Intergers

22:13 so you want

22:13 cooldude127: hiredman: autoboxing should make that ok tho

22:13 hiredman: ,(into-array Integer/TYPE [1 2 3])

22:13 clojurebot: #<int[] [I@92eb76>

22:13 cooldude127: ,(into-array Integer/Type [1 2 3])

22:13 clojurebot: java.lang.Exception: No such namespace: Integer

22:13 * gnuvince_ is a noob

22:13 cooldude127: lol

22:13 hiredman: oh i messed it up

22:14 hiredman: ,(class (into-array Integer/TYPE [1 2 3]))

22:14 clojurebot: [I

22:14 hiredman: Indeed

22:24 johan1: it works. thanks

22:25 hiredman: ,(class 1)

22:25 clojurebot: java.lang.Integer

22:30 dreish: ,(gensym)

22:30 clojurebot: G__1270

22:30 dreish: ,(gensym)

22:30 clojurebot: G__1274

22:30 dreish: ,(= (gensym) 'G__1278)

22:30 clojurebot: true

22:31 dreish: Is this a bug?

22:31 hiredman: ,(= (gensym) (gensym))

22:31 clojurebot: false

22:31 durka42: gensym creates a new symbol

22:31 you inferred the algorithm for naming said symbol, an implementation detail

22:31 doesn't seem like a bug

22:32 hiredman: ,(let [a (gensym)] (= a (gensym)))

22:32 clojurebot: false

22:32 dreish: Yes, and maybe the bug is in my expectations, but in Common Lisp, a gensym cannot be equal to any other existing symbol.

22:32 hiredman: ,(= nil 'a)

22:32 clojurebot: false

22:32 hiredman: ,(= (gensym) 'a)

22:32 clojurebot: false

22:32 dreish: If you begin an expression (= (gensym) ...) in CL, there is nothing you can type to make it true.

22:32 Sorry, (eq)

22:33 durka42: hmm

22:33 hiredman: ,(str (gensym) " " (gensym))

22:33 clojurebot: "G__1299 G__1300"

22:33 hiredman: hmmm

22:33 knapr: has anyone managed to create an executable jar of a clojure-program? could you show me?

22:33 durka42: did you look at gorilla?

22:33 after you do "ant -Dstandalone=true" gorilla.jar is runnable with java -jar

22:33 i don't know how but kotarak presumably does

22:34 dreish: i guess, the arguments to = are evaluted first, so the symbol exists before gensym creates its new one

22:34 hiredman: knapr: jars are never "executable", windows is just typically setup to, when you click on X.jar, to run java -jar X.jar

22:35 durka42: Gorilla=> (let [a 'G__1963] (prn (gensym)) (prn a))

22:35 G__1963

22:35 G__1963

22:35 nil

22:35 that does seem strange

22:35 dreish: RIght, so it ought to be no problem to create a different one. But I think I remember seeing that the reader is side-effect-free, and that symbols aren't interned (but keywords are). So I guess it would be impossible for gensym to be as clean as it is in Common Lisp, and it would presumably just be the responsibility of the programmer to avoid creating symbols beginning G__.

22:35 Which I guess is reasonable enough.

22:36 knapr: i see

22:37 hiredman: ,(doc gensym)

22:37 clojurebot: "([] [prefix-string]); Returns a new symbol with a unique name. If a prefix string is supplied, the name is prefix# where # is some unique number. If prefix is not supplied, the prefix is 'G__'."

22:37 dreish: That actually seems a little more troubling, now that I think about it, because it means any symbol with a number at the end could potentially collide with a gensym.

22:38 I'm sure I must be wrong about that.

22:38 durka42: so in CL, it looks like gensym'd symbols are a completely different type from regular symbols?

22:39 dreish: I think they're regular-enough symbols, but they print in a form that doesn't read back to the same symbol.

22:40 That might be the answer, though. Make them somehow something that can't be produced through the reader, or by calling symbol.

22:41 gnuvince_: Could anybody lend me a hand with a macro?

22:41 I think I've almost got it, but I can't put the finishing touch.

22:42 hiredman: clojurebot: macro help?

22:42 clojurebot: macro help is http://clojure-log.n01se.net/macro.html

22:42 hiredman: :P

22:42 durka42: isn't that captcha circumvention?

22:42 dreish: I can help you move a macro up a flight of stairs if it weighs less than about 150 lbs.

22:42 durka42: (because that captcha is so advanced...)

22:43 be careful, parentheses are slippery

22:43 and quasiquotes are sharp

22:45 lisppaste8: gnuvince pasted "parse-buffer macro" at http://paste.lisp.org/display/74394

22:47 dreish: Why is this a macro?

22:47 gnuvince_: Cause I don't want to manually call .get, .getShort, .getInt, etc.

22:48 I want to write a description of the buffer's structure and have all right calls made

22:49 dreish: I just don't see why this could be a function that does exactly the same thing.

22:49 couldn't

22:51 gnuvince_: Because it looks exactly like something macros are used for.

22:51 hiredman: clojurebot: who's the man is <reply> ?(^_^)?

22:51 clojurebot: Alles klar

22:51 hiredman: clojurebot: who's the man?

22:51 clojurebot: ?(^_^)?

22:51 danlarkin: intense

22:51 durka42: nice unicode

22:52 gnuvince_: Anybody?

22:52 hiredman: I just stole it from someone in #haskell

22:52 gnuvince_: I just need to figure out how to write the ~forms part in the mapcat call

22:53 hiredman: yeah, macros are for code manipulation

22:53 which this is not

22:54 lisppaste8: durka annotated #74394 with "expansion of the actual macro" at http://paste.lisp.org/display/74394#1

22:54 hiredman: gnuvince_: I think you need to quote the stuff that gets put into & forms

22:55 gnuvince_: hiredman: quote it where? in my call?

22:55 hiredman: which is a sign of not macrohood

22:55 yeah

22:55 gnuvince_: Fuck

22:55 dreish: It's a function trapped in a macro's body. Won't you help?

22:55 hiredman: because ~form just turns into a seq of attempted function calls

22:56 dreish: I like Stu's "rules of macro club": #1: don't write macros.

22:56 gnuvince_: So *how* would I write this without the calling code looking like fucking Java crap?

22:58 Same definition except with defn and call with (parse-buffer buf [:field 1 :byte #(...)] ...)?

22:58 dreish: That's where I'd start.

22:59 danlarkin: ditto!

23:00 dreish: Probably use brackets for the lists instead of parens so you don't have to quote.

23:00 hiredman: sounds like a plan

23:00 danlarkin: vectors

23:00 not brackets

23:00 dreish: Right. When I'm especially tired I also call them square thingies.

23:00 danlarkin: important to know that vectors != lists

23:01 dreish: Little square data structures floating around in the computer.

23:01 hiredman: then once you have that, you can make a macro that turns lists into vectors and passes them to your function :P

23:01 durka42: this macro known as [

23:02 hiredman: actually it is a function know as vec

23:02 ,(vec '(:a :b :c))

23:02 clojurebot: [:a :b :c]

23:03 durka42: (defmacro vecm [xs] `(vec '~xs))

23:05 lisppaste8: gnuvince pasted "Using a function" at http://paste.lisp.org/display/74395

23:06 gnuvince_: For the curious

23:06 dreish: Does it work?

23:06 durka42: btw: you can annotate pastes

23:07 gnuvince_: dreish: it does.

23:07 dreish: Woohoo!

23:07 Another problem solved by not-macros!

23:07 gnuvince_: Gonna need to try it with my real data

23:07 But not tonight

23:26 brianh: emacs noob here

23:26 i just updated my clojure-mode & it deleted the clojure-auto file

23:27 what's the new alternative?

23:29 gnuvince_: brianh: look in clojure-mode.el

23:29 the two lines are there

23:29 There's an autoload and an add-to-alist call

23:31 brianh: k thx

23:49 durka42: how do you write a constructor for :gen-class?

23:52 :int

23:52 :init i mean

23:55 hiredman: uh, I think the init function returns a tuple (vector)

23:56 the first element is a vector of args to pass to the superclass constructoor

23:57 the second element is the starting state

23:58 lisppaste8: knapr pasted "macro-problem" at http://paste.lisp.org/display/74398

23:58 knapr: clojurebot: OO?

23:58 clojurebot: OO is to programming what astrology is to astronomy

23:58 knapr: some macro-gurus here? ^^

Logging service provided by n01se.net