#clojure log - Sep 19 2010

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

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: http://github.com/Raynes/cake-autodoc

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:12 clojurebot: special forms are http://clojure.org/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:33 :)

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 hello?

10:00 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline ranjit_c

10:02 jjido: is anyone ready to give advice for improving my code? http://pastebin.ca/1944174

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:08 jjido: http://gist.github.com/586791

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:15 Vinzent: hm, looks like I have a trouble. When I do lein test, no test runs, this is the output: http://gist.github.com/586797, but test are defined in those namespaces

10:16 and *load-tests* is true

10:17 jjido: it is not here http://clojure.org/data_structures still looking for info

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:21 Vinzent: jjido, http://vimeo.com/11236603

10:24 LauJensen: jjido: http://bestinclass.dk/index.clj/2010/04/prototurtle-the-tale-of-the-bleeding-turtle.html - very simple

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:06 somewhere

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:10 right?

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 fliebel: http://gist.github.com/586836

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 [1]] (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: http://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started#Mac_OS_X!

14:06 http://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started#Mac_OS_X

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:20 http://pastebin.com/WyP7uggz

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:14 bbl

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:55 Raynes: solussd: http://groups.google.com/group/clojure/browse_thread/thread/c3fae246e06ffd7e/2f52400ca5a374dc

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 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 :P

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 :P

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 brb

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:52 Chousuke: apeda__: see http://java.ociweb.com/mark/clojure/article.html

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:12 what am I doing wrong? I commented out the loop and it works fine, I basically want to run that piece of code 5 times. http://pastebin.com/UEz6jEnj

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:23 apeda__: http://pastebin.com/ZzjTK2FP

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 apeda__: http://pastebin.com/68K9JSHF

17:27 Chousuke: you have the syntax wrong

17:27 apeda__: where

17:28 oh sorry

17:28 def = defn

17:29 Chousuke: http://pastebin.com/Gc7yzeyF like this

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:30 fixed..

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 yeah.

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:39 I am probably a bit off here: http://pastebin.com/Unv8dxB7

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:46 apeda__: this is what I have so far: http://pastebin.com/458WAVpw

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 so

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 http://pastebin.com/u8hw3NDW

17:50 oops

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:53 apeda__: http://pastebin.com/c36ymFnu

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 apeda__: http://pastebin.com/FV7SqrWv

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 apeda__: http://pastebin.com/tBrLMAR5

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:02 apeda__: now the if is outside let: http://pastebin.com/k1Fb7vm6

18:03 Chousuke: yeah, it needs to be inside /:

18:03 what about this is confusing you?

18:03 apeda__: http://pastebin.com/spam.php?i=Y2LUC1AM

18:04 Chousuke: anyway, this is what it needs to look like http://pastebin.com/pyhGD6he

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:07 hm

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__: spoilers http://pastebin.com/fftm2GXE

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:21 http://pastebin.com/SuAdiZUK

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:38 Chousuke: apeda__: http://pastebin.com/d3ab4mr2 I think this works

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 apeda__: http://pastebin.com/fuYnUp97

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:35 amalloy: um, i dunno. i don't know how pastie amendments work. try http://pastebin.com/JAVdt81c

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

Logging service provided by n01se.net