0:15 coldhead: i'm looking at this line (.. '(1 2) getClass getProtectionDomain getCodeSource getLocation)
0:15 i can't think what the equivalent Java would be
0:16 any tips?
0:18 Raynes: That could also be written as (.getCodeSource (.getProtectionDomain (.getClass '(1 2))))
0:19 coldhead: right, but i'm trying to think how i'd do it in java
0:19 its apparently getClass().getProtectionDomain().getCodeSource().getLocation()
0:19 Raynes: Something like that. I don't know Java. :\
0:20 coldhead: the order was confusing me
1:53 * Raynes takes off to watch a movie and go to sleep.
1:57 seancorfield: i'm reading joy of clojure and on page 229 it has (. ~(binding 0) ~'close)
1:57 what exactly do (. x y) do
1:57 (i'm sure it's just late and i'm missing something obvious)
1:58 i can see that ~(binding 0) is the bound local name (page in the example)
1:59 and that ~'close returns the symbol close
1:59 but i'm having a hard time figuring out what (. page close) does (especially given the comment in the book that this example works for non closable resources)
2:12 hiredman: clojurebot: special forms?
2:19 seancorfield: hiredman: then all it's doing is calling page.close() - but that contradicts what the book says about non-closable resources which is why i asked
2:19 maybe the book just isn't clear - i'll ask fogus / chouser next time they're around (or post on the manning forum)
2:34 joy of clojure says "Because Clojure namespace names are tied to the directory in which they reside,"... but that's not actually true is it?
2:35 i seem to be able to declare any namespace in a file, regardless of its directory structure
2:35 * seancorfield is puzzled
2:35 bobo_: seancorfield: but can you include it in another ns?
3:06 seancorfield: bobo_: ok, experimentation has now convinced me... thanx... not sure why that didn't seem to be the case before :(
3:06 bobo_: :-)
3:06 seancorfield: maybe i'll simplify cfmljure to rely on that :)
3:07 bobo_: whats cfml?
3:08 ah cold fusion
3:09 seancorfield: yeah, cfmljure is a bridge project to make it seamless to use clojure from cfml
3:09 cfml is a pretty good web templating language
3:10 and i use railo - which is a jboss community project that provides a free open source cfml engine
3:10 bobo_: :-)
4:04 LauJensen: Good morning all
4:24 neotyk: Good morning Lau
4:28 hamza`: morning
5:20 _ulises: morning
6:20 zmyrgel: how can I split a long string after each 8th character?
6:20 I need to add '/' to my string after each 8 char seq
6:29 raek: it is possible to do it like this, but there are probably more elegant ways of doing it:
6:29 ,(->> "abcdefghijklmnopqrstuvwxyz" (partition 8 8 nil) (interpose [\/]) (apply concat) (apply str))
6:29 clojurebot: "abcdefgh/ijklmnop/qrstuvwx/yz"
6:31 noidi: I don't think you need the last two arguments to partition
6:32 ,(require 'clojure.string)
6:32 clojurebot: nil
6:33 noidi: ,(clojure.string/join "/" (partition 8 "asldfkjasdlfkjjasdflkj"))
6:33 clojurebot: "clojure.lang.LazySeq@71ff9be7/clojure.lang.LazySeq@a675bbe2"
6:33 noidi: ,(apply clojure.string/join "/" (partition 8 "asldfkjasdlfkjjasdflkj"))
6:33 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (3) passed to: string$join
6:33 noidi: okay, that didn't work >(
6:34 LauJensen: ,(reduce #(str %1 (when (zero? (mod (count %1) 8)) \/) %2) "" "this is a long string")
6:34 clojurebot: "/this is/ a long/ string"
6:35 zmyrgel: ok, the reduce seems a good option
6:35 I'll try to see if I it is clearer to add the '/' chars while building the string
6:36 raek: ,(partition 8 "abcdefghijklmnopqrstuvwxyz") ; ignores the last letters
6:36 clojurebot: ((\a \b \c \d \e \f \g \h) (\i \j \k \l \m \n \o \p) (\q \r \s \t \u \v \w \x))
6:37 noidi: ah, ok
6:37 raek: ,(partition 8 8 nil "abcdefghijklmnopqrstuvwxyz")
6:37 clojurebot: ((\a \b \c \d \e \f \g \h) (\i \j \k \l \m \n \o \p) (\q \r \s \t \u \v \w \x) (\y \z))
6:37 raek: a bit weird default behaviour...
6:37 zmyrgel: ah, never mind. Just noticed that '/' won't go after each 8 chars all the time
6:38 Have to get my string builder loop to handle the insertion at proper places
6:39 LauJensen: zmyrgel: thats the nice thing about reduce, just change the predicate and it still works
6:42 zmyrgel: LauJensen: well, its harder to use reduce as the rules for / insertion aren't obvious
6:58 bonega: I am making a tetris in clojure.
6:58 My problem is: If I evalute my state in the REPL it gets very sluggish for a period of time.
6:58 This seems directly related to *print-level* - any ideas?
7:04 Vinzent: hm, what's the right way to remove an element from the vector by index?
7:15 raek: you cannot remove an element from a persistent vector in constant time (other from the end)
7:16 you can create subvecs of the parts before and after the index in constant time
7:16 but merging them is O(n)
7:19 ,(let [v [:a :b :c :d :e]] (into (subvec v 0 2) (subvec v 3 5)))
7:19 clojurebot: [:a :b :d :e]
7:31 Vinzent: raek, yes, now i does exactly that, but anyway thanks for your irrefragable answer
7:52 LauJensen: zmyrgel: (reduce with-my-complex-rules "" string), then just write your rules in a cond/condp statement. Should be very simple
9:01 shanmuha: Hi, I am trying to use clojure.contrib.lazy-xml
9:11 Bahman: Hi all!
9:15 LauJensen: Hi
9:20 mrBliss: how should I name a test for xy->i? (question mark isn't part of the name) xy->i-test or stick with the original name? (test is in namespace project.test.core)
9:22 LauJensen: mrBliss: I think suffixing -test reads very intuitively
9:23 mrBliss: LauJensen: thanks
9:28 LauJensen: np
9:45 This is fascinating
9:45 ,((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))
9:45 clojurebot: ((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))
9:45 LauJensen: Especially thinking back on the first C quine I ever saw
9:59 ranjit_c: e
10:00 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline ranjit_c
10:04 I am new to Clojure, don't know all the idioms yet
10:06 LauJensen: jjido: Pastebin isn't loading and in any case, I prefer gists :)
10:07 jjido: LauJensen: gists URL?
10:07 LauJensen: github.com
10:07 But what I like about it, is I select the region of code I want to gist, then hit M-x gist-region, and if you post a gist in here, I hit M-x gist-fetch id
10:08 ranjit_c: so is this a reasonable way to initialize a 2d array in clojure; (def A (into-array (map double-array (partition L (repeat (* L L) 1)))))
10:08 it seems a lot slower than the equivalent in python
10:09 LauJensen: jjido: Right now I have all of your code loaded in a buffer next to this chat, with proper highlighting etc, and if I want I can eval your functions and test them in the repl, hows that for integration?
10:09 mrBliss: LauJensen: I didn't know about gist-fetch yet, good to know!
10:10 LauJensen: mrBliss: Find gist.el on github
10:11 mrBliss: LauJensen: I'm already using it for posting my gists, now I'll use it also to read others people's gists :)
10:11 LauJensen: ah ok
10:12 jjido: So it looks like you've introduced a new type SimpleList and do so via bundling its interfaces in defstructs, which I doubt was ever idiomatic, but with the coming of protocols and records definitely isnt the way to go
10:14 jjido: LauJensen: what is a good way to do a new type?
10:14 LauJensen: jjido: defrecord/deftype
10:16 and *load-tests* is true
10:19 Vinzent: I'm putting tests and code in same namespaces, but different files (that allows me to test private functions), may the problem be in that?
10:20 jjido: I can see it in the API page but no examples :-( any suggestion where to learn about defrecord and deftype?
10:24 LauJensen: jjido: http://
10:25 jjido: thx
10:28 fbru02: so when i want to include a jar file from disk the only way is letting lein frail and add it to the ~/.m2 folder using mvn?
10:33 Vinzent: seems so
10:34 raek: didn't lein install do something like that?
10:35 Vinzent: probably lrin install installing lein projects
10:37 raek: I guess you could also place the jar in the lib/ directory
10:37 if it isn't a maven artifact
10:38 fbru02: raek: yes, the problem often they are maven artifacts , i'm tired of dealing with maven-deploy-plugin and others
10:38 mrBliss: raek: don't you lose the jar when you execute lein deps?
10:39 fbru02: mrBliss: i think you lose the entire lib directory??
10:40 raek: hrm, yes
10:40 if you develop multiple clojure projects in parallel, you can use the checkouts feature
10:43 Vinzent: anyway i think it's a good idea to write a lein plugin that will do it
10:46 florianjunker: Will compojure 0.4.1 work with ring 0.3.0, or will I have to keep using ring 0.2.6?
11:01 jjido: Once I have an instance of (defrecord SimpleList [values]), how do I get to its values?
11:03 ,(:values (do (defrecord SimpleList [values]) (SimpleList. ))
11:03 clojurebot: EOF while reading
11:03 jjido: ,(:values (do (defrecord SimpleList [values]) (SimpleList. )))
11:03 clojurebot: DENIED
11:03 jjido: ,(:values (doseq (defrecord SimpleList [values]) (SimpleList. )))
11:03 clojurebot: java.lang.IllegalArgumentException: doseq requires a vector for its binding
11:04 fliebel: ,(first (lazy-seq (println :a) (println :b)))
11:04 clojurebot: :a :b
11:05 fliebel: How do I get that to only print :a?
11:05 LauJensen: jjido: (defrecord tmprec [f1]) => (tmprec. 1) => (:f1 inst) => 1
11:06 jjido: ok so I am right. I get a NPE :(
11:10 LauJensen: jjido: I dont know if you're right or not, but get the values by calling the keyword with the instance, or get all keys my calling (vals instance)
11:10 jjido: (:values instance)
11:11 LauJensen: (vals instance)
11:14 fliebel: ,(first (cons (println 1) (lazy-seq [(println 2)])))
11:14 clojurebot: 1
11:15 fliebel: that works… any better way?
11:15 LauJensen: fliebel: of doing what exactly?
11:16 fliebel: LauJensen: Defining a lazy seq of a series of expressions.
11:17 jjido: I get a NPE when I try to do a doc string for my extend-protocol function
11:21 fliebel: LauJensen: concat is lazy, but it does evaluate the expressions.
11:23 LauJensen: fliebel: Rarely do I see people chaining expresses without wrapping them in a thunk
11:24 fliebel: LauJensen: thunk?
11:24 LauJensen: (fn  (+ 2 2)) or something similar
11:26 fliebel: LauJensen: I have a function that returns 2 parts, where both involve io, but sometimes I need only the first part, so I'm seeking a way to return both results in a lazy manner, so that only the first part is computer if the second part is not requested.
11:27 LauJensen: [5 (fn  (println "doing io"))]
11:28 fliebel: LauJensen: But then the other side has to call the second fn to get the result? I thought I could just create a lazy seq for the results, which is what I did with the cons above,
11:30 LauJensen: Yea I guess you can. Just saying you dont see that a lot. In fact I dont think Ive seen it done that way before
11:30 raek: fliebel: this is a validator library I'm working on. the functions cons-validator-step and concat-validator-step might be inspirational
11:30 basically, create a new fn that may or may not call the fn of the next step
11:30 the whole chain becomes one fn
11:31 unfortunately, I don't have time to explain more today. hope you find something useful in it
11:31 fliebel: thanks
11:32 chouser: fliebel: your (cons x (lazy-seq [y])) looks fine to me.
11:32 I might use (list y) instead of [y] in this particular case, but I'm not sure it's actually any better.
11:32 LauJensen: chouser: why list?
11:33 chouser: because then you're creating a thing that actually implements Seq, which is the whole point.
11:33 [y] is a vector, which then gets wrapped in a chunked-seq
11:34 LauJensen: ah right
11:34 chouser: ,(let [ys (list 1)] (identical? (seq (lazy-seq ys)) ys))
11:34 clojurebot: true
11:34 chouser: ,(let [ys ] (identical? (seq (lazy-seq ys)) ys))
11:34 clojurebot: false
11:34 chouser: using a vector means there's an extra allocation
11:35 but like I said, I'm not sure which is actually more idiomatic.
11:35 fliebel: I like the list better, I think it makes sense.
11:36 chouser: bbl
11:38 fliebel: It works :) Sweet!
12:00 How bad is it to leave files open? which if the effect of not consuming a complete line-seq, if I'm correct.
12:14 technomancy: fliebel: it's a resource leak; there's a hard limit to the number of files you can have open
12:14 just means you might not be able to open files in the future if you leak too many
12:35 fliebel: technomancy: Thanks I don't think I'll open that many.
12:56 brandonz: hi all. i was wondering if anyone had any experience with jgir. i was trying to use it to bring up some java-clutter bindings but seem to be failing.
13:18 LauJensen: Gents, Im having a problem with JFreeChart, where the chart only will render in a JTabbedPane (and not either JPanel or JScrollPane), any idea whats up ?
13:54 Hmm, seems its another oddity of setContentPane
14:03 octagon: hi! i'm looking for a good link for getting started with clojure, slime, emacs, etc on osx.
14:06 * phobbs had a typo
14:06 octagon: awesome thanks
14:10 fliebel: Huh… calling a fn with a signature of [[markdown static]] with a list of 2 as argument will result in having markdown and static, right? I get "Wrong number of args (2)", while I'm only passing a list. It almost seems like there is a hidden apply in there, or I got my expansion wrong.
14:14 *adds an ampersand*
14:19 kumarshantanu: hi, I am trying to find out what is clojure.lang.Cons
14:19 fliebel: ,(doc cons)
14:19 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."
14:20 kutku: I want to solve this problem in clojure, can anyone give me a hint on where to start?
14:22 fliebel: kutku: You'll need to get some sin and cos functions somewhere, I think Java has a Math module, also ctonains a PI constant if I'm correct.
14:25 sproust: fliebel: are you looking for a lazy version of (do)?
14:27 LauJensen: ,(Math/sin 5)
14:27 clojurebot: -0.9589242746631385
14:27 fliebel: sproust: No
14:29 kutku: what if I calculate the X and Y coordinates and divide them by /2 and calculate the square
14:34 sthuebner: ,(and () ())
14:34 clojurebot: ()
14:35 sthuebner: ,(true? (and () ()))
14:35 clojurebot: false
14:35 sthuebner: ,(if (and () ()) :a :b)
14:35 clojurebot: :a
14:35 sthuebner: hm, that seems odd!
14:37 mrBliss: sthuebner: (true? x) is only true when x is identical to true
14:37 the same with false?
14:37 sthuebner: so 'if doesn't check for true?
14:37 LauJensen: sthuebner: if/when runs their (first) body if the predicate is non-nil and non-false
14:37 (if (seq ()) :a :b)
14:37 ,(if (seq ()) :a :b)
14:37 clojurebot: :b
14:38 LauJensen: nil punning is not encouraged, instead wrap your sequence in a call to seq which evals to nil if its empty
14:38 sthuebner: ah! That's the reason for all those seq calls in labrepl!
14:39 I was wondering about that
14:41 thanks, mrBliss + LauJensen
14:41 LauJensen: np
14:42 fliebel: This is insane… user=> (fcopy app)
14:42 java.lang.IllegalArgumentException: Wrong number of args (2)
14:50 sproust: LauJensen: the seq wrapping for boolean context has to be the most inelegant part of clojure I know of.
14:51 LauJensen: sproust: Thats because you dont know enough Clojure :)
14:51 sproust: Maybe.
14:52 It's an idiomatic way of resolving boolean context that is not intuitive. I had the same questions as sthuebner the other day.
14:53 What's the benefit of treating empty collections as boolean true?
14:53 sthuebner: yeah! I agree! In Common Lisp () is false
14:53 fliebel: I'm not sure I understand, can't you just use (boolean)?
14:54 LauJensen: I think it was a trade we did, to get fully lazy sequences
14:54 chouser will certainly remember the details :)
14:55 sproust: Lau: you mean that otherwise you'd have had to evaluate the lazy sequence?
14:55 LauJensen: sproust: yea, or at least consume an item
14:56 sproust: Seems like a bad tradeoff to me. All those (seq) calls everywhere...
14:56 fliebel: LauJensen: Makes sense :) I think it's good
14:57 sthuebner: Has the use of 'next over 'rest the same roots?
14:57 LauJensen: sproust: Well. The problem is, Rich decided to solve a performance problem by introducing chunks. So if you consume one item, you can actually end up consuming 32 items, making an if statement potentially expensive. I dont know if this goes away when chunks go away.
14:57 sthuebner: yes, introduced at the exact same time
14:57 sproust: Hey wait... don't you have to evaluate an element anyway if you wrap with seq?
14:59 ,(let [lseq (map prn (range 3))] (if (seq lseq) (prn 'a) (prn 'b)))
14:59 clojurebot: 0 1 2 a
14:59 sproust: So how does wrapping with seq help in any way?
15:10 chouser: empty list was never actually false
15:10 even before the "lazier" changes
15:10 if an empty list is false, then shouldn't an empty map, set, and vector be as well?
15:10 what about empty strings?
15:11 that way lies madness. Only two things are false: nil and false
15:11 before "lazier" many things returned nil instead of an empty lazy seq. This included filter, etc.
15:13 but in order to get the lazier behavior, something had to give. You can tell there's no more in a lazy seq without asking for the next thing, which would force that step
15:14 so no map, filter, etc. always return lazy seqs which may be empty instead of nil, and empty seqs are still not false.
15:14 you have to explicitly ask for the next step if you want to find out if it's empty or not. 'seq' does that, as does 'next' (as opposed to 'rest')
15:21 Raynes: sproust: ^ In case you missed it.
15:24 fliebel: *applauds for chouser's e-lecture*
15:54 solussd: how do you unload everything added to the namespace using 'use' ?
15:54 Chousuke: you can use ns-unmap
15:55 but there's no automatic way
15:55 solussd: if I did, say, a (use 'clojure.contrib.repl-utils) how can I unload all the symbols that interned into my current namespace?
15:55 can ns-unmap take a wildcard? :)
15:56 solussd: thanks raynes
16:04 sproust: solussd: remove-ns also works well.
16:11 vishsingh: having some issues getting swank-clojure working today, would appreciate any ideas.
16:11 i've basically got to the point where i can do "lein swank" in a project directory, and get a swank server running.
16:12 and i can do Alt-X slime-connect from emacs, and it successfully connects to the swank server. the slime-repl comes up, everything seems awesome.
16:13 unfortunately when I type a clojure form and hit enter.. nothing happens. it's just like I hit enter in a regular buffer, my cursor moves down.
16:14 the enter key is bound to the right thing.. slime-repl-return or whatever it is. something is clearly wonky and I don't know what.
16:19 laurus: I'm running a simple "Hello, World!" script using cljr, and it's quite slow. Is this because it needs to "start" Clojure every time? Is there a way to have Clojure more "ready" in the background for running scripts? I'm on GNU/Linux if that matters.
16:20 Chousuke: cake can do it for you
16:20 it keeps a JVM instance running
16:20 laurus: Hmm, ok I'll check it out!
16:21 Oh, it's yet another build tool, heh.
16:21 Chousuke, is there a way to do it with cljr, or just plain Java?
16:21 Chousuke: laurus: well, yes, but you'd end up reimplementing cake anyway I think :P
16:22 laurus: "Clojure also suffers from the JVM's slow startup time. This pretty much rules Clojure out for one-off scripting and other stuff where startup time can be a hindrance." Is that really true?
16:22 I want to use it for scripting! Hehe
16:22 Chousuke: well, yeah
16:22 laurus: Aww, ok, I guess I'll keep these Python scripts around then.
16:22 LauJensen: laurus: try java -client
16:22 Chousuke: unless you keep a JVM instance running at all times, running fast scripts is not very feasible
16:23 since the startup is at best a second :P
16:23 sometimes longer.
16:23 laurus: Chousuke, well I don't mind leaving it running at all times, unless there's a drawback to it I'm not aware of.
16:23 LauJensen, what does that do?
16:23 Chousuke: laurus: well, other than taking up memory, not really.
16:23 laurus: Maybe cljr is the bottleneck and not the JVM startup.
16:23 LauJensen: $ time java -cp clojure-1.2.0-master-20100813.160144-94.jar -client clojure.main -e '(println "hello")'
16:23 real 0m1.174s
16:23 sexpbot: LauJensen: The time is now 2010-09-19T20:20:58Z
16:23 LauJensen: user 0m1.320s
16:23 sys 0m0.060s
16:24 I guess you can suffer 1 second boot time
16:24 laurus: LauJensen, well it's more like 5 seconds on this computer for some reason
16:24 LauJensen: laurus: with the above line?
16:25 laurus: LauJensen, I get "real 0m0.019s"
16:25 LauJensen: Thats nice :)
16:25 laurus: "time cljr run hello-world.clj" gives me "real 0m3.324s"
16:26 "time java -jar clojure.jar hello-world.clj" gives me "real 0m1.391s."
16:26 So I guess cljr is the slow one here.
16:26 It's too bad because I wanted to use cljr to run Clojure from anywhere since it already does that
16:26 LauJensen: java doesnt run anywhere?
16:26 laurus: At the same time, how important is 2 seconds really :P
16:27 LauJensen, I mean, I have to specify the path to the Clojure jar, right?
16:27 LauJensen: laurus: yea it needs to know where it is
16:27 laurus: Right, cljr takes care of that already.
16:27 Raynes: LauJensen: Try cake.
16:27 LauJensen: unless you install it in the jvms boot lib, which I think is possible but haven't tried
16:27 Raynes: Er, laurus.
16:27 LauJensen: Raynes: stop it, you're making me hungry
16:28 Raynes: Cake uses persistent JVMs, and can do the same thing, only faster.
16:28 laurus: Raynes, that's true, but then I'd have to install ruby
16:28 LauJensen: Raynes: You're pretty much repeating Chousuke's advice from above
16:28 Raynes: I didn't check the backlogs.
16:28 laurus: Raynes I appreciate it
16:28 Raynes: And why is that such a big problem? :o
16:28 LauJensen: laurus: if you're on linux, installing Ruby takes like... 20 secs in Ubuntu and 5 in Arch ?
16:28 laurus: I don't know, I hate having to install more stuff
16:28 LauJensen: I think I'd make the investment
16:28 laurus: I like how cljr is a jar itself, that seems neat to me.
16:29 LauJensen: laurus: So make your script into an uberjar
16:29 A self-executable jar
16:29 doesn't need anything from the host except the jvm
16:29 laurus: LauJensen, oh, that's a neat idea.
16:29 LauJensen: And if you're feeling really motivated, finish the gcc-gcj project and compile to native :)
16:29 laurus: Hahahahaha :)
16:29 Despite having read two Java books in the past, I didn't know about self-executable jars.
16:30 LauJensen: laurus: 'cake uberjar' turns a project into an executable jar, which only depends on itself
16:30 laurus: Oh, wow.
16:30 So why doesn't everyone use cake instead of the other two then?
16:30 Raynes: Leiningen can do the same thing.
16:30 LauJensen: It requires a gen-classed namespace with the function (defn -main [& args] (do something)) in it
16:30 Raynes: And cake is new.
16:30 Very, very new.
16:30 Chousuke: cake is also written in ruby ;P
16:30 Raynes: Only partially.
16:30 LauJensen: laurus: well... I think a lot of us are, and more are starting all the time
16:30 Raynes: It uses Ruby for the same thing that Lein uses bash for.
16:30 laurus: I see :)
16:30 LauJensen: Chousuke: It has a small Ruby bootstrap, thats it
16:31 Raynes: Most of it is actually written in Clojure.
16:31 laurus: Well I'll check it out when I have some time then!
16:31 Thanks for all the tips.
16:31 LauJensen: Its like lein, only with more features and a cool task/dependency system to boot
16:31 also, it doesn't censor your names, you can call your projects whatever you want
16:31 Raynes: Man, you're still worked over about that? :P
16:31 laurus: LauJensen, good to know
16:32 LauJensen: Raynes: Well - I dont like Censjureship :)
16:32 So I think, if that was the only thing which set them apart, I'd still go with Cake
16:32 But now that I have cross-platform and that fantastic task system, its pretty much a done deal
16:33 Chousuke: lein doesn't do censorship
16:33 it merely gives good advice
16:33 LauJensen: Chousuke: Not so
16:34 Chousuke: it still works with badly named projects
16:34 laurus: Actually, there's another way to do this that I should have thought of in the first place.
16:34 Just have a cljr repl open at all times!
16:34 apeda__: how do I increment a variable by 1 ?
16:34 laurus: And use it just like one would a bash terminal.
16:34 LauJensen: apeda__: (let [my-var (atom 0)] (swap! my-var inc))
16:34 apeda__: thanks
16:35 laurus: LauJensen, what do you think of that idea?
16:35 LauJensen: apeda__: Since Clojures data is immutable, you need to use an agent, a ref or an atom. Or hook into Java directly. Or a promise for edge cases
16:35 laurus: I cant tell, it depends on your use case.
16:35 laurus: Good point :)
16:38 Chousuke: apeda__: note, that for most algorithms you shouldn't need to increment a variable. :)
16:39 ie. try to avoid mutability if you can.
16:40 LauJensen: apeda__: yea, something like (iterate inc 0) or (range) will do the same by way of making an infinite sequence of numbers always incrementing by one. This is functional programming.
16:46 apeda__: how do I define a variable that I later on can use "inc" on to increment
16:48 LauJensen: apeda__: I think you need to spend some time on the basics of Clojure, functional programming and the concurrency semantics available in Clojure. Start at clojure.org
16:48 apeda__: ok thanks
16:48 nex: how can i pass the values from lists when making a struct-map?
16:53 or well, that kind of skips the functional programming part :P
16:54 apeda__: how do I cast a integer to float? I tried (float var)
16:56 hiredman: why do you need to cast an integer to a float?
16:56 apeda__: becauase when I divide it returns the ratio
16:57 e.g. 22/7
16:57 hiredman: and why can't you use a ratio?
16:57 apeda__: because I want the answer as floating point
16:57 LauJensen: ,(float (/ 22 7))
16:57 clojurebot: 3.142857
16:57 apeda__: ,(float 33)
16:57 clojurebot: 33.0
16:58 apeda__: i got different res on my repl..but ok
16:58 maybe I did smth wrong
17:13 LauJensen: apeda__: that is just so wrong
17:13 You should read a little about functional programming and the virtues of immutability
17:14 Chousuke: apeda__: you're writing imperative code
17:14 apeda__: Clojure is not designed for that :)
17:15 apeda__: one rule of thumb is, that if you're writing a def anywhere else but on the top level (ie. inside a function or a loop) you're doing something wrong. def'd vars are not supposed to change.
17:15 apeda__: what you need to do is design your algorithm so that you can implement it in a recursive manner
17:16 here you have two things that "change"; 'rsquared and 'hits
17:16 and x and y which are random values
17:16 apeda__: ok im a bit lost .. and I am reading upon this.
17:17 Chousuke: ok.
17:17 Chousuke: apeda__: don't worry. functional programming is a big paradigm shift.
17:17 apeda__: Chousuke: I guess :)
17:17 Chousuke: but it's not impossible to learn as long as you keep at it.
17:17 apeda__: Chousuke: so where do I start in fixing my algorithm.. whats step 1?
17:18 Chousuke: hmmh
17:19 well first you need to figure out what calculations you could do if you could start with a "chosen" value
17:19 apeda__: ok, I will define x as 0.3 and y as 0.5
17:19 Chousuke: so your rsquared is now a value. ie, immutable
17:20 apeda__: yes
17:20 Chousuke: it would be useful to make a function for it, so you can call (r-squared x y)
17:20 apeda__: yes
17:20 let me do that then, brb
17:20 Chousuke: so there you have one mutable thing done away with
17:24 Chousuke: now you wrapped all the code in a function (and the parameters are wrong)
17:24 you should've done it only for the rsquared calculation
17:24 apeda__: ok ill fix it :)
17:26 jjido: I defined a function in a protocol that does not take an instance as first parameter. Is that allowed? How to invoke it?
17:26 Chousuke: you can't do that.
17:26 jjido: Chousuke: ok :-(
17:27 Chousuke: or rather, it makes no sense to do that
17:27 since there's nothing to dispatch on :P
17:27 so it's the same has a plain defn
17:27 Chousuke: you have the syntax wrong
17:27 apeda__: where
17:28 oh sorry
17:28 def = defn
17:29 [x y], not [x] [y] :)
17:30 apeda__: ok thanks.
17:30 Chousuke: but then you need a loop as well, to deal with the hits
17:30 apeda__: i have an unmatched deliminer
17:30 Chousuke: not a for loop
17:30 apeda__: trying to find it.
17:30 Chousuke: hmm yeah, probably. :P
17:30 probably the last one
17:30 apeda__: it was!
17:31 Chousuke: anyway, to deal with "hits" you need a recursive loop. ie. instead of changing hits, you have it be an immutable parameter of the loop, and you "restart" it with a *new* value at the end.
17:31 clojure provides "loop" for this
17:31 apeda__: I am lsitening.
17:31 Chousuke: it works like (loop [hits 0] code-here)
17:32 and in the "code-here" part somewhere you can call (recur (inc hits))
17:32 hiredman: apeda__: you should consider reading too
17:32 Chousuke: and the loop restarts as before, but with hits now having a one larger value
17:32 note that nowhere are we mutating hits, we're just restarting the loop
17:32 with a new value
17:33 this is very important
17:33 apeda__: that means I can take this out right: (def hits 0.0)
17:33 Chousuke: because that's what you'll do most of the time
17:33 apeda__: ok
17:34 Chousuke: the problem with your example is that it's not possibly to make completely functional because of the random values
17:34 but it'll do.
17:35 anyway, in the loop you'll need to make two local values x and y, with rand. use (let [x (rand)...] rest-of-the-code-here) for this
17:35 let is another important operator. it creates local bindings. again, immutable.
17:35 apeda__: im trying
17:40 Chousuke: yeah, you forgot parentheses from let
17:40 apeda__: stop thinking about statements
17:40 apeda__: ok..I added parathesis
17:41 Chousuke: apeda__: clojure has only expressions. that means code that does (do (let [x 1]) (let [y 2]) x) is completely ineffective
17:41 you need to do (let [x 1, y 2] x)
17:41 the bindings are effective only *within* the let calll
17:41 (that comma is optional btw)
17:42 also you should put the defn outside the loop
17:43 apeda__: what does this do: (let [x 1, y 2] x)
17:44 Chousuke: returns 1
17:44 ,(let [x 1] 1)
17:44 clojurebot: 1
17:44 Chousuke: ,(do (let [x 1] 1) x); note
17:44 clojurebot: java.lang.Exception: Unable to resolve symbol: x in this context
17:45 Chousuke: that's the same as doing (do 1 x)
17:45 apeda__: why do I need it in my algorithm?
17:45 Chousuke: because you need some place to put the random values
17:45 and they are local to the loop
17:46 apeda__: so I put that code before my (let [y (rand)]) ?
17:46 Chousuke: what code?
17:47 Chousuke: no, see, you're still thinking that those let statements affect code further below
17:47 they don't
17:47 because they're not statements
17:47 apeda__: I need to get out of the old way of thinking.
17:47 Chousuke: the syntax of let is (let [some-bindings here] code-where-bindings-work)
17:48 apeda__: start thinking of everything as an expression.
17:48 *everything* returns a value
17:48 the let expression returns a value too
17:48 it returns whatever the code-expression returns.
17:48 ,(let [x 1] (+ 5 x))
17:48 clojurebot: 6
17:48 Chousuke: let returns 6
17:49 apeda__: yes
17:49 Chousuke: similarly, the loop I showed you earlier is another expression
17:49 it returns a value just like let does
17:49 but now you have a let inside the loop, so the loop returns whatever the let does!
17:49 apeda__: ok, whats missing in my code now
17:50 I need to call r-squared from the loop right?
17:50 Chousuke: yeah
17:50 forgot a closing ]
17:50 after the y (rand)
17:50 laurus: Do any Clojure people use JNode?
17:51 Chousuke: apeda__: you must basically do your if-check within the let now
17:51 apeda__: so right after that missing ] i will call my r-square function
17:51 Chousuke: that's where you call r-squared.
17:52 apeda__: yes
17:52 Chousuke: and then you need the special thing to restart the loop, ie. recur
17:52 it works like (recur new-value-of-loop-parameter)
17:52 like a recursive function
17:53 and if you don't want to restart the loop, just return a value
17:53 the loop ends
17:53 and the value is returned
17:53 ie. just put the return value in the other branch of the if
17:54 i got it..
17:54 let me work on that
17:54 Chousuke: you have no if there. :)
17:54 apeda__: I have no if?
17:55 Chousuke: in what you just pasted
17:58 Chousuke: now you have another def there
17:58 that's wrong
17:58 defs inside functions are never correct.
17:58 apeda__: ur right sorry
17:58 how do I capture the return value
17:59 Chousuke: you can put it in the let
17:59 but you could also just use it directly in the if
18:01 im not getting errors, but I think I have my parenthesis wrong somewhere.
18:01 Chousuke: the if code is not inside the lets. (and you could've used the earlier let)
18:01 and the defs are still wrong
18:02 you're looking to make the loop return pi, not define anything
18:02 clojurebot: compiling clojure is rarely necessary to do yourself.
18:02 Chousuke: clojurebot: thanks :P
18:02 clojurebot: I don't understand.
18:03 Chousuke: yeah, it needs to be inside /:
18:03 what about this is confusing you?
18:04 now the loop expression returns pi
18:04 doesn't print it though
18:04 but you could wrap the entire loop expression in println to get it printed :)
18:05 of course, that's a silly thing to do
18:05 better to make the loop into a function
18:05 fortunately, that's easy
18:06 apeda__: ok let me try to work on that.
18:06 Chousuke: I just noticed throws is undefined
18:08 damn, does the number of throws affect the algorithm?
18:08 because if it does, then that does something else :P
18:09 apeda__: basically, I want to pass throws, e.g 100 throws.. and get how many hits I got
18:09 Chousuke: ah, in that case you'll need to change that a lot
18:10 right now it just throws until it gets > 0.25
18:10 and then quits
18:10 there's a better way though.
18:10 you should make a "throw-once" function
18:12 apeda__: so a single function that returns hit or miss?
18:12 and then call it 100 times and capture its return values?
18:12 Chousuke: or r-squared
18:13 if you have a throw function, you can make a sequence of throws easily
18:13 liek this
18:13 ,(take 10 (repeatedly rand))
18:13 clojurebot: (0.29019485547826773 0.24552194880643585 0.9978153461256136 0.48390336312321436 0.24757279827241707 0.36504819362606034 0.7135505090005937 0.27129678042771666 0.9895945815698848 0.23363070686385035)
18:14 Chousuke: that take is necessary because otherwise clojurebot would get stuck calculating an infinite number of rand values... for ten seconds :P
18:16 apeda__: I have to go now. keep trying
18:16 apeda__: thanks for all the help!!
18:16 I will try to solve this
18:16 Chousuke: apeda__: the best advice I can think of is to forget everyhing you know about programming :P
18:16 apeda__: lol
18:16 i guess so :)
18:16 Chousuke: because, really, functional languages work nothing like C, python or java.
18:16 there's a really fundamental difference in approach
18:17 and before you can grasp the basics of that approach, you'll have a really hard time with clojure
18:17 apeda__: im trying to make the throw-once function
18:18 Chousuke: remember: expressions, not statements
18:19 functions return the last expression they evaluate
18:19 all previous expressions are completely ignored (though if they have side-effects they might affect the latter ones. but in general you want to avoid side-effects)
18:19 apeda__: ok thanks!
18:23 Chousuke: hm.
18:24 that won't actually restart the loop since there's no recur
18:24 also it won't return a useful value (the return value of println is nil)
18:25 printing things is a side-effect too btw
18:25 so you should avoid it until you need it
18:26 when calculating pi, you don't need to print anything
18:26 you only need to print the result :)
18:27 apeda__: ah..
18:28 ill go nutse by the time im done lol
18:28 Chousuke: maybe you should try with something even simpler
18:28 just to get used to the idea of working with expressions
18:29 apeda__: but im so close
18:29 Chousuke: just try evaluating ifs and lets and other things in a repl
18:29 apeda__: I think once I have this problem done and study it ill have a better understanding
18:29 Chousuke: what you want to do is structure the code so that the value you want is at the "tail" somewhere
18:30 so when you simulate the code in your mind, the expression your want to return is the last one evaluated
18:30 apeda__: can u wrap this up so I can take a look at how u do it
18:31 im just not used to this way of thinking although I have a good understanding of the actual problem
18:31 tomoj: I had never really thought about simulation of code in our minds
18:39 (don't call it with <0 throws, I sacrificed robustness for legibility :P)
18:40 apeda__: hold on...
18:40 I got that running
18:40 but what is the return value?
18:40 amounth of hits?
18:40 how can hits be a non integer val?
18:40 Chousuke: pi.
18:40 hits is not?
18:40 apeda__: oh ur right
18:40 hold on 1 sec.
18:41 Chousuke: the cond there is a three-branch conditional
18:41 it works like (cond condition1 then1 condition2 then2 condition3 then3...)
18:42 it evaluates the conditions in order and evaluates the corresponding then expr for the first condition that is true
18:42 see the :else there? that's an "always-true" condition
18:42 it's last, so it's the else branch :)
18:43 so if the cond goes and sees that there are no throws left (as indicated by the loop parameter), then it returns (* 4.0 (/ t hits))
18:44 otherwise, it calls recur
18:44 which restarts the loop, with new values
18:45 and t is the number of throws you want to do
18:46 it doesn't change at all.
18:46 florianjunker: Looks like ring sessions aren't working
18:47 apeda__: i fixed it
18:47 (* 4.0 (/ hits t));
18:47 florianjunker: They set cookies, but I can't put anything inside and get it out again.
18:47 apeda__: t hits should be hits t
18:47 thanks for all the help I got it working!!!
18:47 im going to study this now
18:47 so i get a better grasp
18:47 Chousuke: apeda__: yeah, do that
18:47 apeda__: try going through it in your mind a few times
18:47 see how it works
18:48 but now I need to go.
18:49 apeda__: thanks a lot man!!
18:49 great great help thakns!
18:56 florianjunker: damn. ring sessions don't work with ring reloading. is there a workaround?
19:20 whats wrong with that?
19:25 amalloy: apeda__: recur only works if it's in the "tail position" - ie it is the last thing you will do before returning
19:26 apeda__: makes sense
19:26 pdk: if the function you're trying to make tail recursive does anything with the return value of its recursive call other than simply return it back up
19:26 then don't expect recur to work
19:27 often functions can be restructured to fit this bill though
19:28 amalloy: apeda__: i don't think that's the "reason" this doesn't work, though. it looks like you're pretending that your loop is a (cond)
19:31 apeda__: ok
19:31 im just playing aroudn trying to get a better grasp, thakns for all help.
19:32 I didn't think the clojure community would be this big.
19:33 amalloy: apeda__: i submitted an amendment for you
19:35 apeda__: same url?
19:36 speaking of which, consider using pastie instead of pastebin - it has clojure syntax highlighting
19:39 apeda__: I will in the future, im off for a little break.
19:39 thanks for everything
19:39 pdk: itd be nice to add some more of these handy links in the topic line
20:56 amaevis: is there any way to maintain a collection of all of the instances of a class without holding a reference forever and blocking garbage collection?
20:57 in java
22:21 laurus: Raynes, could you tell me about the editor you were building in Clojure?
23:18 amalloy: hey rich, is there a reason we have assoc(-in) and get(-in), but only update-in (ie, no update)?
23:19 rhickey: ,(doc update-in)
23:19 clojurebot: "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."
23:19 rhickey: oh, no flat update
23:19 amalloy: right
23:20 rhickey: no good reason, it has been requested before
23:46 tomoj: is the planet clojure feed broken?
23:50 * hiredman uses (update-in foo [bar] baz) and doesn't see (update foo bar baz) as a huge improvement
23:51 tomoj: to match assoc/assoc-in I guess you'd want (update foo bar baz bing bang)
23:51 which doesn't seem very useful at all
23:51 cais2002: how does multimethod work if some implementations are located in a different namespace than the one with defmulti ?
23:51 amalloy: hiredman: you could use (assoc-in foo [bar] baz) too, but we have assoc for that
23:53 hiredman: *shrug*
23:54 I think I would actually use (update-in foo [bar baz] (constantly bloop)) before thinking to use assoc-in
23:57 amalloy: tomoj: i suppose you're right, an update with the same parameter style as assoc would be silly
23:58 but eg (update m f & keys) would be useful, maybe? or something like it