#clojure logs

2010-09-19

00:15coldheadi'm looking at this line (.. '(1 2) getClass getProtectionDomain getCodeSource getLocation)
00:15coldheadi can't think what the equivalent Java would be
00:16coldheadany tips?
00:18RaynesThat could also be written as (.getCodeSource (.getProtectionDomain (.getClass '(1 2))))
00:19coldheadright, but i'm trying to think how i'd do it in java
00:19coldheadits apparently getClass().getProtectionDomain().getCodeSource().getLocation()
00:19RaynesSomething like that. I don't know Java. :\
00:20coldheadthe order was confusing me
01:53Rayneshttp://github.com/Raynes/cake-autodoc
01:57seancorfieldi'm reading joy of clojure and on page 229 it has (. ~(binding 0) ~'close)
01:57seancorfieldwhat exactly do (. x y) do
01:57seancorfield(i'm sure it's just late and i'm missing something obvious)
01:58seancorfieldi can see that ~(binding 0) is the bound local name (page in the example)
01:59seancorfieldand that ~'close returns the symbol close
01:59seancorfieldbut 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)
02:12hiredmanclojurebot: special forms?
02:12clojurebotspecial forms are http://clojure.org/special_forms
02:19seancorfieldhiredman: 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
02:19seancorfieldmaybe the book just isn't clear - i'll ask fogus / chouser next time they're around (or post on the manning forum)
02:34seancorfieldjoy of clojure says "Because Clojure namespace names are tied to the directory in which they reside,"... but that's not actually true is it?
02:35seancorfieldi seem to be able to declare any namespace in a file, regardless of its directory structure
02:35bobo_seancorfield: but can you include it in another ns?
03:06seancorfieldbobo_: ok, experimentation has now convinced me... thanx... not sure why that didn't seem to be the case before :(
03:06bobo_:-)
03:06seancorfieldmaybe i'll simplify cfmljure to rely on that :)
03:07bobo_whats cfml?
03:08bobo_ah cold fusion
03:09seancorfieldyeah, cfmljure is a bridge project to make it seamless to use clojure from cfml
03:09seancorfieldcfml is a pretty good web templating language
03:10seancorfieldand i use railo - which is a jboss community project that provides a free open source cfml engine
03:10bobo_:-)
04:04LauJensenGood morning all
04:24neotykGood morning Lau
04:28hamza`morning
05:20_ulisesmorning
06:20zmyrgelhow can I split a long string after each 8th character?
06:20zmyrgelI need to add '/' to my string after each 8 char seq
06:29raekit is possible to do it like this, but there are probably more elegant ways of doing it:
06:29raek,(->> "abcdefghijklmnopqrstuvwxyz" (partition 8 8 nil) (interpose [\/]) (apply concat) (apply str))
06:29clojurebot"abcdefgh/ijklmnop/qrstuvwx/yz"
06:31noidiI don't think you need the last two arguments to partition
06:32noidi,(require 'clojure.string)
06:32clojurebotnil
06:33noidi,(clojure.string/join "/" (partition 8 "asldfkjasdlfkjjasdflkj"))
06:33clojurebot"clojure.lang.LazySeq@71ff9be7/clojure.lang.LazySeq@a675bbe2"
06:33noidi,(apply clojure.string/join "/" (partition 8 "asldfkjasdlfkjjasdflkj"))
06:33clojurebotjava.lang.IllegalArgumentException: Wrong number of args (3) passed to: string$join
06:33noidiokay, that didn't work >(
06:33noidi:)
06:34LauJensen,(reduce #(str %1 (when (zero? (mod (count %1) 8)) \/) %2) "" "this is a long string")
06:34clojurebot"/this is/ a long/ string"
06:35zmyrgelok, the reduce seems a good option
06:35zmyrgelI'll try to see if I it is clearer to add the '/' chars while building the string
06:36raek,(partition 8 "abcdefghijklmnopqrstuvwxyz") ; ignores the last letters
06:36clojurebot((\a \b \c \d \e \f \g \h) (\i \j \k \l \m \n \o \p) (\q \r \s \t \u \v \w \x))
06:37noidiah, ok
06:37raek,(partition 8 8 nil "abcdefghijklmnopqrstuvwxyz")
06:37clojurebot((\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))
06:37raeka bit weird default behaviour...
06:37zmyrgelah, never mind. Just noticed that '/' won't go after each 8 chars all the time
06:38zmyrgelHave to get my string builder loop to handle the insertion at proper places
06:39LauJensenzmyrgel: thats the nice thing about reduce, just change the predicate and it still works
06:42zmyrgelLauJensen: well, its harder to use reduce as the rules for / insertion aren't obvious
06:58bonegaI am making a tetris in clojure.
06:58bonegaMy problem is: If I evalute my state in the REPL it gets very sluggish for a period of time.
06:58bonegaThis seems directly related to *print-level* - any ideas?
07:04Vinzenthm, what's the right way to remove an element from the vector by index?
07:15raekyou cannot remove an element from a persistent vector in constant time (other from the end)
07:16raekyou can create subvecs of the parts before and after the index in constant time
07:16raekbut merging them is O(n)
07:19raek,(let [v [:a :b :c :d :e]] (into (subvec v 0 2) (subvec v 3 5)))
07:19clojurebot[:a :b :d :e]
07:31Vinzentraek, yes, now i does exactly that, but anyway thanks for your irrefragable answer
07:52LauJensen zmyrgel: (reduce with-my-complex-rules "" string), then just write your rules in a cond/condp statement. Should be very simple
09:01shanmuhaHi, I am trying to use clojure.contrib.lazy-xml
09:11BahmanHi all!
09:15LauJensenHi
09:20mrBlisshow 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)
09:22LauJensenmrBliss: I think suffixing -test reads very intuitively
09:23mrBlissLauJensen: thanks
09:28LauJensennp
09:45LauJensenThis is fascinating
09:45LauJensen,((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))
09:45clojurebot((fn [x] (list x (list (quote quote) x))) (quote (fn [x] (list x (list (quote quote) x)))))
09:45LauJensenEspecially thinking back on the first C quine I ever saw
09:59ranjit_ce
10:00ranjit_chello?
10:00clojurebotBUENOS DING DONG DIDDLY DIOS, fRaUline ranjit_c
10:02jjidois anyone ready to give advice for improving my code? http://pastebin.ca/1944174
10:04jjidoI am new to Clojure, don't know all the idioms yet
10:06LauJensenjjido: Pastebin isn't loading and in any case, I prefer gists :)
10:07jjidoLauJensen: gists URL?
10:07LauJensengithub.com
10:07LauJensenBut 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:08ranjit_cso 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:08ranjit_cit seems a lot slower than the equivalent in python
10:08jjidohttp://gist.github.com/586791
10:09LauJensenjjido: 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:09mrBlissLauJensen: I didn't know about gist-fetch yet, good to know!
10:10LauJensenmrBliss: Find gist.el on github
10:11mrBlissLauJensen: I'm already using it for posting my gists, now I'll use it also to read others people's gists :)
10:11LauJensenah ok
10:12LauJensenjjido: 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:14jjidoLauJensen: what is a good way to do a new type?
10:14LauJensenjjido: defrecord/deftype
10:15Vinzenthm, 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:16Vinzentand *load-tests* is true
10:17jjidoit is not here http://clojure.org/data_structures still looking for info
10:19VinzentI'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:20jjidoI can see it in the API page but no examples :-( any suggestion where to learn about defrecord and deftype?
10:21Vinzentjjido, http://vimeo.com/11236603
10:24LauJensenjjido: http://bestinclass.dk/index.clj/2010/04/prototurtle-the-tale-of-the-bleeding-turtle.html - very simple
10:25jjidothx
10:28fbru02so 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:33Vinzentseems so
10:34raekdidn't lein install do something like that?
10:35Vinzentprobably lrin install installing lein projects
10:37raekI guess you could also place the jar in the lib/ directory
10:37raekif it isn't a maven artifact
10:38fbru02raek: yes, the problem often they are maven artifacts , i'm tired of dealing with maven-deploy-plugin and others
10:38mrBlissraek: don't you lose the jar when you execute lein deps?
10:39fbru02mrBliss: i think you lose the entire lib directory??
10:40raekhrm, yes
10:40raekif you develop multiple clojure projects in parallel, you can use the checkouts feature
10:43Vinzentanyway i think it's a good idea to write a lein plugin that will do it
10:46florianjunkerWill compojure 0.4.1 work with ring 0.3.0, or will I have to keep using ring 0.2.6?
11:01jjidoOnce I have an instance of (defrecord SimpleList [values]), how do I get to its values?
11:03jjido,(:values (do (defrecord SimpleList [values]) (SimpleList. []))
11:03clojurebotEOF while reading
11:03jjido,(:values (do (defrecord SimpleList [values]) (SimpleList. [])))
11:03clojurebotDENIED
11:03jjido,(:values (doseq (defrecord SimpleList [values]) (SimpleList. [])))
11:03clojurebotjava.lang.IllegalArgumentException: doseq requires a vector for its binding
11:04fliebel,(first (lazy-seq (println :a) (println :b)))
11:04clojurebot:a :b
11:05fliebelHow do I get that to only print :a?
11:05LauJensenjjido: (defrecord tmprec [f1]) => (tmprec. 1) => (:f1 inst) => 1
11:06jjidook so I am right. I get a NPE :(
11:06jjidosomewhere
11:10LauJensenjjido: 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:10jjido(:values instance)
11:10jjidoright?
11:11LauJensen(vals instance)
11:14fliebel,(first (cons (println 1) (lazy-seq [(println 2)])))
11:14clojurebot1
11:15fliebelthat works… any better way?
11:15LauJensenfliebel: of doing what exactly?
11:16fliebelLauJensen: Defining a lazy seq of a series of expressions.
11:17jjidoI get a NPE when I try to do a doc string for my extend-protocol function
11:21fliebelLauJensen: concat is lazy, but it does evaluate the expressions.
11:23LauJensenfliebel: Rarely do I see people chaining expresses without wrapping them in a thunk
11:24fliebelLauJensen: thunk?
11:24LauJensen(fn [] (+ 2 2)) or something similar
11:26fliebelLauJensen: 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:27LauJensen[5 (fn [] (println "doing io"))]
11:28fliebelLauJensen: 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:30LauJensenYea 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:30raekfliebel: this is a validator library I'm working on. the functions cons-validator-step and concat-validator-step might be inspirational
11:30raekfliebel: http://gist.github.com/586836
11:30raekbasically, create a new fn that may or may not call the fn of the next step
11:30raekthe whole chain becomes one fn
11:31raekunfortunately, I don't have time to explain more today. hope you find something useful in it
11:31fliebelthanks
11:32chouserfliebel: your (cons x (lazy-seq [y])) looks fine to me.
11:32chouserI might use (list y) instead of [y] in this particular case, but I'm not sure it's actually any better.
11:32LauJensenchouser: why list?
11:33chouserbecause then you're creating a thing that actually implements Seq, which is the whole point.
11:33chouser[y] is a vector, which then gets wrapped in a chunked-seq
11:34LauJensenah right
11:34chouser,(let [ys (list 1)] (identical? (seq (lazy-seq ys)) ys))
11:34clojurebottrue
11:34chouser,(let [ys [1]] (identical? (seq (lazy-seq ys)) ys))
11:34clojurebotfalse
11:34chouserusing a vector means there's an extra allocation
11:35chouserbut like I said, I'm not sure which is actually more idiomatic.
11:35fliebelI like the list better, I think it makes sense.
11:36chouserbbl
11:38fliebelIt works :) Sweet!
12:00fliebelHow bad is it to leave files open? which if the effect of not consuming a complete line-seq, if I'm correct.
12:14technomancyfliebel: it's a resource leak; there's a hard limit to the number of files you can have open
12:14technomancyjust means you might not be able to open files in the future if you leak too many
12:35fliebeltechnomancy: Thanks I don't think I'll open that many.
12:56brandonzhi 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:18LauJensenGents, 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:54LauJensenHmm, seems its another oddity of setContentPane
14:03octagonhi! i'm looking for a good link for getting started with clojure, slime, emacs, etc on osx.
14:06phobbshttp://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started#Mac_OS_X!
14:06phobbshttp://en.wikibooks.org/wiki/Clojure_Programming/Getting_Started#Mac_OS_X
14:06octagonawesome thanks
14:10fliebelHuh… 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:14fliebel*adds an ampersand*
14:19kumarshantanuhi, I am trying to find out what is clojure.lang.Cons
14:19fliebel,(doc cons)
14:19clojurebot"([x seq]); Returns a new seq where x is the first element and seq is the rest."
14:20kutkuI want to solve this problem in clojure, can anyone give me a hint on where to start?
14:20kutkuhttp://pastebin.com/WyP7uggz
14:22fliebelkutku: 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:25sproustfliebel: are you looking for a lazy version of (do)?
14:27LauJensen,(Math/sin 5)
14:27clojurebot-0.9589242746631385
14:27fliebelsproust: No
14:29kutkuwhat if I calculate the X and Y coordinates and divide them by /2 and calculate the square
14:34sthuebner,(and () ())
14:34clojurebot()
14:35sthuebner,(true? (and () ()))
14:35clojurebotfalse
14:35sthuebner,(if (and () ()) :a :b)
14:35clojurebot:a
14:35sthuebnerhm, that seems odd!
14:37mrBlisssthuebner: (true? x) is only true when x is identical to true
14:37mrBlissthe same with false?
14:37sthuebnerso 'if doesn't check for true?
14:37LauJensensthuebner: if/when runs their (first) body if the predicate is non-nil and non-false
14:37LauJensen(if (seq ()) :a :b)
14:37LauJensen,(if (seq ()) :a :b)
14:37clojurebot:b
14:38LauJensennil punning is not encouraged, instead wrap your sequence in a call to seq which evals to nil if its empty
14:38sthuebnerah! That's the reason for all those seq calls in labrepl!
14:39sthuebnerI was wondering about that
14:41sthuebnerthanks, mrBliss + LauJensen
14:41LauJensennp
14:42fliebelThis is insane… user=> (fcopy app)
14:42fliebeljava.lang.IllegalArgumentException: Wrong number of args (2)
14:50sproustLauJensen: the seq wrapping for boolean context has to be the most inelegant part of clojure I know of.
14:51LauJensensproust: Thats because you dont know enough Clojure :)
14:51sproustMaybe.
14:52sproustIt's an idiomatic way of resolving boolean context that is not intuitive. I had the same questions as sthuebner the other day.
14:53sproustWhat's the benefit of treating empty collections as boolean true?
14:53sthuebneryeah! I agree! In Common Lisp () is false
14:53fliebelI'm not sure I understand, can't you just use (boolean)?
14:54LauJensenI think it was a trade we did, to get fully lazy sequences
14:54LauJensenchouser will certainly remember the details :)
14:55sproustLau: you mean that otherwise you'd have had to evaluate the lazy sequence?
14:55LauJensensproust: yea, or at least consume an item
14:56sproustSeems like a bad tradeoff to me. All those (seq) calls everywhere...
14:56fliebelLauJensen: Makes sense :) I think it's good
14:57sthuebnerHas the use of 'next over 'rest the same roots?
14:57LauJensensproust: 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:57LauJensensthuebner: yes, introduced at the exact same time
14:57sproustHey wait... don't you have to evaluate an element anyway if you wrap with seq?
14:59sproust,(let [lseq (map prn (range 3))] (if (seq lseq) (prn 'a) (prn 'b)))
14:59clojurebot0 1 2 a
14:59sproustSo how does wrapping with seq help in any way?
15:10chouserempty list was never actually false
15:10chousereven before the "lazier" changes
15:10chouserif an empty list is false, then shouldn't an empty map, set, and vector be as well?
15:10chouserwhat about empty strings?
15:11chouserthat way lies madness. Only two things are false: nil and false
15:11chouserbefore "lazier" many things returned nil instead of an empty lazy seq. This included filter, etc.
15:13chouserbut 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:14chouserso no map, filter, etc. always return lazy seqs which may be empty instead of nil, and empty seqs are still not false.
15:14chouseryou 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:14chouserbbl
15:21Raynessproust: ^ In case you missed it.
15:24fliebel*applauds for chouser's e-lecture*
15:54solussdhow do you unload everything added to the namespace using 'use' ?
15:54Chousukeyou can use ns-unmap
15:55Chousukebut there's no automatic way
15:55solussdif I did, say, a (use 'clojure.contrib.repl-utils) how can I unload all the symbols that interned into my current namespace?
15:55solussdcan ns-unmap take a wildcard? :)
15:55Raynessolussd: http://groups.google.com/group/clojure/browse_thread/thread/c3fae246e06ffd7e/2f52400ca5a374dc
15:56solussdthanks raynes
16:04sproustsolussd: remove-ns also works well.
16:11vishsinghhaving some issues getting swank-clojure working today, would appreciate any ideas.
16:11vishsinghi've basically got to the point where i can do "lein swank" in a project directory, and get a swank server running.
16:12vishsinghand 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:13vishsinghunfortunately 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:14vishsinghthe 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:19laurusI'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:20Chousukecake can do it for you
16:20Chousukeit keeps a JVM instance running
16:20laurusHmm, ok I'll check it out!
16:21laurusOh, it's yet another build tool, heh.
16:21laurusChousuke, is there a way to do it with cljr, or just plain Java?
16:21Chousukelaurus: well, yes, but you'd end up reimplementing cake anyway I think :P
16:22laurus"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:22laurusI want to use it for scripting! Hehe
16:22Chousukewell, yeah
16:22laurusAww, ok, I guess I'll keep these Python scripts around then.
16:22LauJensenlaurus: try java -client
16:22Chousukeunless you keep a JVM instance running at all times, running fast scripts is not very feasible
16:23Chousukesince the startup is at best a second :P
16:23Chousukesometimes longer.
16:23laurusChousuke, well I don't mind leaving it running at all times, unless there's a drawback to it I'm not aware of.
16:23laurusLauJensen, what does that do?
16:23Chousukelaurus: well, other than taking up memory, not really.
16:23laurusMaybe cljr is the bottleneck and not the JVM startup.
16:23LauJensen$ time java -cp clojure-1.2.0-master-20100813.160144-94.jar -client clojure.main -e '(println "hello")'
16:23LauJensenhello
16:23LauJensen
16:23LauJensenreal 0m1.174s
16:23sexpbotLauJensen: The time is now 2010-09-19T20:20:58Z
16:23LauJensenuser 0m1.320s
16:23LauJensensys 0m0.060s
16:23LauJensen
16:24LauJensenI guess you can suffer 1 second boot time
16:24laurusLauJensen, well it's more like 5 seconds on this computer for some reason
16:24LauJensenlaurus: with the above line?
16:25laurusLauJensen, I get "real 0m0.019s"
16:25laurus:P
16:25LauJensenThats nice :)
16:25laurus"time cljr run hello-world.clj" gives me "real 0m3.324s"
16:26laurus"time java -jar clojure.jar hello-world.clj" gives me "real 0m1.391s."
16:26laurusSo I guess cljr is the slow one here.
16:26laurusIt's too bad because I wanted to use cljr to run Clojure from anywhere since it already does that
16:26LauJensenjava doesnt run anywhere?
16:26laurusAt the same time, how important is 2 seconds really :P
16:27laurusLauJensen, I mean, I have to specify the path to the Clojure jar, right?
16:27LauJensenlaurus: yea it needs to know where it is
16:27laurusRight, cljr takes care of that already.
16:27RaynesLauJensen: Try cake.
16:27LauJensenunless you install it in the jvms boot lib, which I think is possible but haven't tried
16:27RaynesEr, laurus.
16:27LauJensenRaynes: stop it, you're making me hungry
16:28RaynesCake uses persistent JVMs, and can do the same thing, only faster.
16:28laurusRaynes, that's true, but then I'd have to install ruby
16:28LauJensenRaynes: You're pretty much repeating Chousuke's advice from above
16:28RaynesI didn't check the backlogs.
16:28laurusRaynes I appreciate it
16:28RaynesAnd why is that such a big problem? :o
16:28LauJensenlaurus: if you're on linux, installing Ruby takes like... 20 secs in Ubuntu and 5 in Arch ?
16:28laurusI don't know, I hate having to install more stuff
16:28LauJensenI think I'd make the investment
16:28laurusI like how cljr is a jar itself, that seems neat to me.
16:29LauJensenlaurus: So make your script into an uberjar
16:29LauJensenA self-executable jar
16:29LauJensendoesn't need anything from the host except the jvm
16:29laurusLauJensen, oh, that's a neat idea.
16:29LauJensenAnd if you're feeling really motivated, finish the gcc-gcj project and compile to native :)
16:29laurusHahahahaha :)
16:29laurusDespite having read two Java books in the past, I didn't know about self-executable jars.
16:30LauJensenlaurus: 'cake uberjar' turns a project into an executable jar, which only depends on itself
16:30laurusOh, wow.
16:30laurusSo why doesn't everyone use cake instead of the other two then?
16:30RaynesLeiningen can do the same thing.
16:30LauJensenIt requires a gen-classed namespace with the function (defn -main [& args] (do something)) in it
16:30RaynesAnd cake is new.
16:30RaynesVery, very new.
16:30Chousukecake is also written in ruby ;P
16:30RaynesOnly partially.
16:30LauJensenlaurus: well... I think a lot of us are, and more are starting all the time
16:30RaynesIt uses Ruby for the same thing that Lein uses bash for.
16:30laurusI see :)
16:30LauJensenChousuke: It has a small Ruby bootstrap, thats it
16:31RaynesMost of it is actually written in Clojure.
16:31laurusWell I'll check it out when I have some time then!
16:31laurusThanks for all the tips.
16:31LauJensenIts like lein, only with more features and a cool task/dependency system to boot
16:31LauJensenalso, it doesn't censor your names, you can call your projects whatever you want
16:31RaynesMan, you're still worked over about that? :P
16:31laurusLauJensen, good to know
16:32LauJensenRaynes: Well - I dont like Censjureship :)
16:32LauJensenSo I think, if that was the only thing which set them apart, I'd still go with Cake
16:32LauJensenBut now that I have cross-platform and that fantastic task system, its pretty much a done deal
16:33Chousukelein doesn't do censorship
16:33Chousuke:P
16:33Chousukeit merely gives good advice
16:33LauJensenChousuke: Not so
16:34Chousukeit still works with badly named projects
16:34laurusActually, there's another way to do this that I should have thought of in the first place.
16:34laurusJust have a cljr repl open at all times!
16:34apeda__how do I increment a variable by 1 ?
16:34laurusAnd use it just like one would a bash terminal.
16:34LauJensenapeda__: (let [my-var (atom 0)] (swap! my-var inc))
16:34apeda__thanks
16:35laurusLauJensen, what do you think of that idea?
16:35LauJensenapeda__: 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:35LauJensenlaurus: I cant tell, it depends on your use case.
16:35LauJensenbrb
16:35laurusGood point :)
16:38Chousukeapeda__: note, that for most algorithms you shouldn't need to increment a variable. :)
16:39Chousukeie. try to avoid mutability if you can.
16:40LauJensenapeda__: 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:46apeda__how do I define a variable that I later on can use "inc" on to increment
16:48LauJensenapeda__: 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:48apeda__ok thanks
16:48nexhow can i pass the values from lists when making a struct-map?
16:52Chousukeapeda__: see http://java.ociweb.com/mark/clojure/article.html
16:53Chousukeor well, that kind of skips the functional programming part :P
16:54apeda__how do I cast a integer to float? I tried (float var)
16:56hiredmanwhy do you need to cast an integer to a float?
16:56apeda__becauase when I divide it returns the ratio
16:57apeda__e.g. 22/7
16:57hiredmanand why can't you use a ratio?
16:57apeda__because I want the answer as floating point
16:57LauJensen,(float (/ 22 7))
16:57clojurebot3.142857
16:57apeda__,(float 33)
16:57clojurebot33.0
16:58apeda__i got different res on my repl..but ok
16:58apeda__maybe I did smth wrong
17:12apeda__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:13LauJensenapeda__: that is just so wrong
17:13LauJensenYou should read a little about functional programming and the virtues of immutability
17:14Chousukeapeda__: you're writing imperative code
17:14Chousukeapeda__: Clojure is not designed for that :)
17:15Chousukeapeda__: 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:15Chousukeapeda__: what you need to do is design your algorithm so that you can implement it in a recursive manner
17:16Chousukehere you have two things that "change"; 'rsquared and 'hits
17:16Chousukeand x and y which are random values
17:16apeda__ok im a bit lost .. and I am reading upon this.
17:17apeda__Chousuke: ok.
17:17Chousukeapeda__: don't worry. functional programming is a big paradigm shift.
17:17apeda__Chousuke: I guess :)
17:17Chousukebut it's not impossible to learn as long as you keep at it.
17:17apeda__Chousuke: so where do I start in fixing my algorithm.. whats step 1?
17:18Chousukehmmh
17:19Chousukewell first you need to figure out what calculations you could do if you could start with a "chosen" value
17:19apeda__ok, I will define x as 0.3 and y as 0.5
17:19Chousukeso your rsquared is now a value. ie, immutable
17:20apeda__yes
17:20Chousukeit would be useful to make a function for it, so you can call (r-squared x y)
17:20apeda__yes
17:20apeda__let me do that then, brb
17:20Chousukeso there you have one mutable thing done away with
17:23apeda__http://pastebin.com/ZzjTK2FP
17:24Chousukenow you wrapped all the code in a function (and the parameters are wrong)
17:24Chousukeyou should've done it only for the rsquared calculation
17:24apeda__ok ill fix it :)
17:26jjidoI defined a function in a protocol that does not take an instance as first parameter. Is that allowed? How to invoke it?
17:26Chousukeyou can't do that.
17:26jjidoChousuke: ok :-(
17:27Chousukeor rather, it makes no sense to do that
17:27Chousukesince there's nothing to dispatch on :P
17:27Chousukeso it's the same has a plain defn
17:27apeda__http://pastebin.com/68K9JSHF
17:27Chousukeyou have the syntax wrong
17:27apeda__where
17:28apeda__oh sorry
17:28apeda__def = defn
17:29Chousukehttp://pastebin.com/Gc7yzeyF like this
17:29Chousuke[x y], not [x] [y] :)
17:30apeda__ok thanks.
17:30Chousukebut then you need a loop as well, to deal with the hits
17:30apeda__i have an unmatched deliminer
17:30Chousukenot a for loop
17:30apeda__trying to find it.
17:30Chousukehmm yeah, probably. :P
17:30Chousukeprobably the last one
17:30apeda__it was!
17:30apeda__fixed..
17:31Chousukeanyway, 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:31Chousukeclojure provides "loop" for this
17:31apeda__I am lsitening.
17:31Chousukeit works like (loop [hits 0] code-here)
17:32Chousukeand in the "code-here" part somewhere you can call (recur (inc hits))
17:32hiredmanapeda__: you should consider reading too
17:32Chousukeand the loop restarts as before, but with hits now having a one larger value
17:32Chousukenote that nowhere are we mutating hits, we're just restarting the loop
17:32Chousukewith a new value
17:33Chousukethis is very important
17:33apeda__that means I can take this out right: (def hits 0.0)
17:33Chousukebecause that's what you'll do most of the time
17:33Chousukeyeah.
17:33apeda__ok
17:34Chousukethe problem with your example is that it's not possibly to make completely functional because of the random values
17:34Chousukebut it'll do.
17:35Chousukeanyway, 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:35Chousukelet is another important operator. it creates local bindings. again, immutable.
17:35apeda__im trying
17:39apeda__I am probably a bit off here: http://pastebin.com/Unv8dxB7
17:40Chousukeyeah, you forgot parentheses from let
17:40Chousukeapeda__: stop thinking about statements
17:40apeda__ok..I added parathesis
17:41Chousukeapeda__: clojure has only expressions. that means code that does (do (let [x 1]) (let [y 2]) x) is completely ineffective
17:41Chousukeyou need to do (let [x 1, y 2] x)
17:41Chousukethe bindings are effective only *within* the let calll
17:41Chousuke(that comma is optional btw)
17:42Chousukealso you should put the defn outside the loop
17:43apeda__what does this do: (let [x 1, y 2] x)
17:44Chousukereturns 1
17:44Chousuke,(let [x 1] 1)
17:44clojurebot1
17:44Chousuke,(do (let [x 1] 1) x); note
17:44clojurebotjava.lang.Exception: Unable to resolve symbol: x in this context
17:45Chousukethat's the same as doing (do 1 x)
17:45apeda__why do I need it in my algorithm?
17:45Chousukebecause you need some place to put the random values
17:45Chousukeand they are local to the loop
17:46apeda__so I put that code before my (let [y (rand)]) ?
17:46Chousukewhat code?
17:46apeda__this is what I have so far: http://pastebin.com/458WAVpw
17:47Chousukeno, see, you're still thinking that those let statements affect code further below
17:47Chousukethey don't
17:47Chousukebecause they're not statements
17:47apeda__I need to get out of the old way of thinking.
17:47Chousukethe syntax of let is (let [some-bindings here] code-where-bindings-work)
17:48Chousukeapeda__: start thinking of everything as an expression.
17:48Chousuke*everything* returns a value
17:48Chousukethe let expression returns a value too
17:48Chousukeit returns whatever the code-expression returns.
17:48Chousukeso
17:48Chousuke,(let [x 1] (+ 5 x))
17:48clojurebot6
17:48Chousukelet returns 6
17:49apeda__yes
17:49Chousukesimilarly, the loop I showed you earlier is another expression
17:49Chousukeit returns a value just like let does
17:49Chousukebut now you have a let inside the loop, so the loop returns whatever the let does!
17:49apeda__ok, whats missing in my code now
17:50apeda__I need to call r-squared from the loop right?
17:50Chousukeyeah
17:50Chousukehttp://pastebin.com/u8hw3NDW
17:50Chousukeoops
17:50Chousukeforgot a closing ]
17:50Chousukeafter the y (rand)
17:50laurusDo any Clojure people use JNode?
17:51Chousukeapeda__: you must basically do your if-check within the let now
17:51apeda__so right after that missing ] i will call my r-square function
17:51Chousukethat's where you call r-squared.
17:52apeda__yes
17:52Chousukeand then you need the special thing to restart the loop, ie. recur
17:52Chousukeit works like (recur new-value-of-loop-parameter)
17:52Chousukelike a recursive function
17:53Chousukeand if you don't want to restart the loop, just return a value
17:53Chousukethe loop ends
17:53Chousukeand the value is returned
17:53Chousukeie. just put the return value in the other branch of the if
17:53apeda__http://pastebin.com/c36ymFnu
17:54apeda__i got it..
17:54apeda__let me work on that
17:54Chousukeyou have no if there. :)
17:54apeda__I have no if?
17:55Chousukein what you just pasted
17:58apeda__http://pastebin.com/FV7SqrWv
17:58Chousukenow you have another def there
17:58Chousukethat's wrong
17:58Chousukedefs inside functions are never correct.
17:58apeda__ur right sorry
17:58apeda__how do I capture the return value
17:59Chousukeyou can put it in the let
17:59Chousukebut you could also just use it directly in the if
18:01apeda__http://pastebin.com/tBrLMAR5
18:01apeda__im not getting errors, but I think I have my parenthesis wrong somewhere.
18:01Chousukethe if code is not inside the lets. (and you could've used the earlier let)
18:01Chousukeand the defs are still wrong
18:02Chousukeyou're looking to make the loop return pi, not define anything
18:02clojurebotcompiling clojure is rarely necessary to do yourself.
18:02Chousukeclojurebot: thanks :P
18:02clojurebotI don't understand.
18:02apeda__now the if is outside let: http://pastebin.com/k1Fb7vm6
18:03Chousukeyeah, it needs to be inside /:
18:03Chousukewhat about this is confusing you?
18:03apeda__http://pastebin.com/spam.php?i=Y2LUC1AM
18:04Chousukeanyway, this is what it needs to look like http://pastebin.com/pyhGD6he
18:04Chousukenow the loop expression returns pi
18:04Chousukedoesn't print it though
18:04Chousukebut you could wrap the entire loop expression in println to get it printed :)
18:05Chousukeof course, that's a silly thing to do
18:05Chousukebetter to make the loop into a function
18:05Chousukefortunately, that's easy
18:06apeda__ok let me try to work on that.
18:06ChousukeI just noticed throws is undefined
18:07Chousukehm
18:08Chousukedamn, does the number of throws affect the algorithm?
18:08Chousukebecause if it does, then that does something else :P
18:09Chousukeapeda__: spoilers http://pastebin.com/fftm2GXE
18:09apeda__basically, I want to pass throws, e.g 100 throws.. and get how many hits I got
18:09Chousukeah, in that case you'll need to change that a lot
18:10Chousukeright now it just throws until it gets > 0.25
18:10Chousukeand then quits
18:10Chousukethere's a better way though.
18:10Chousukeyou should make a "throw-once" function
18:12apeda__so a single function that returns hit or miss?
18:12apeda__and then call it 100 times and capture its return values?
18:12Chousukeor r-squared
18:13Chousukeif you have a throw function, you can make a sequence of throws easily
18:13Chousukeliek this
18:13Chousuke,(take 10 (repeatedly rand))
18:13clojurebot(0.29019485547826773 0.24552194880643585 0.9978153461256136 0.48390336312321436 0.24757279827241707 0.36504819362606034 0.7135505090005937 0.27129678042771666 0.9895945815698848 0.23363070686385035)
18:14Chousukethat take is necessary because otherwise clojurebot would get stuck calculating an infinite number of rand values... for ten seconds :P
18:16Chousukeapeda__: I have to go now. keep trying
18:16apeda__thanks for all the help!!
18:16apeda__I will try to solve this
18:16Chousukeapeda__: the best advice I can think of is to forget everyhing you know about programming :P
18:16apeda__lol
18:16apeda__i guess so :)
18:16Chousukebecause, really, functional languages work nothing like C, python or java.
18:16Chousukethere's a really fundamental difference in approach
18:17Chousukeand before you can grasp the basics of that approach, you'll have a really hard time with clojure
18:17apeda__im trying to make the throw-once function
18:18Chousukeremember: expressions, not statements
18:19Chousukefunctions return the last expression they evaluate
18:19Chousukeall 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:19apeda__ok thanks!
18:21apeda__http://pastebin.com/SuAdiZUK
18:23Chousukehm.
18:24Chousukethat won't actually restart the loop since there's no recur
18:24Chousukealso it won't return a useful value (the return value of println is nil)
18:25Chousukeprinting things is a side-effect too btw
18:25Chousukeso you should avoid it until you need it
18:26Chousukewhen calculating pi, you don't need to print anything
18:26Chousukeyou only need to print the result :)
18:27apeda__ah..
18:28apeda__ill go nutse by the time im done lol
18:28Chousukemaybe you should try with something even simpler
18:28Chousukejust to get used to the idea of working with expressions
18:29apeda__but im so close
18:29Chousukejust try evaluating ifs and lets and other things in a repl
18:29apeda__I think once I have this problem done and study it ill have a better understanding
18:29Chousukewhat you want to do is structure the code so that the value you want is at the "tail" somewhere
18:30Chousukeso when you simulate the code in your mind, the expression your want to return is the last one evaluated
18:30apeda__can u wrap this up so I can take a look at how u do it
18:31apeda__im just not used to this way of thinking although I have a good understanding of the actual problem
18:31tomojI had never really thought about simulation of code in our minds
18:38Chousukeapeda__: http://pastebin.com/d3ab4mr2 I think this works
18:39Chousuke(don't call it with <0 throws, I sacrificed robustness for legibility :P)
18:40apeda__hold on...
18:40apeda__I got that running
18:40apeda__but what is the return value?
18:40apeda__amounth of hits?
18:40apeda__how can hits be a non integer val?
18:40Chousukepi.
18:40Chousukehits is not?
18:40apeda__oh ur right
18:40apeda__hold on 1 sec.
18:41Chousukethe cond there is a three-branch conditional
18:41Chousukeit works like (cond condition1 then1 condition2 then2 condition3 then3...)
18:42Chousukeit evaluates the conditions in order and evaluates the corresponding then expr for the first condition that is true
18:42Chousukesee the :else there? that's an "always-true" condition
18:42Chousukeit's last, so it's the else branch :)
18:43Chousukeso 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:44Chousukeotherwise, it calls recur
18:44Chousukewhich restarts the loop, with new values
18:45Chousukeand t is the number of throws you want to do
18:46Chousukeit doesn't change at all.
18:46florianjunkerLooks like ring sessions aren't working
18:47apeda__i fixed it
18:47apeda__(* 4.0 (/ hits t));
18:47florianjunkerThey set cookies, but I can't put anything inside and get it out again.
18:47apeda__t hits should be hits t
18:47apeda__thanks for all the help I got it working!!!
18:47apeda__im going to study this now
18:47apeda__so i get a better grasp
18:47Chousukeapeda__: yeah, do that
18:47Chousukeapeda__: try going through it in your mind a few times
18:47Chousukesee how it works
18:48Chousukebut now I need to go.
18:49apeda__thanks a lot man!!
18:49apeda__great great help thakns!
18:56florianjunkerdamn. ring sessions don't work with ring reloading. is there a workaround?
19:20apeda__http://pastebin.com/fuYnUp97
19:20apeda__whats wrong with that?
19:25amalloyapeda__: recur only works if it's in the "tail position" - ie it is the last thing you will do before returning
19:26apeda__makes sense
19:26pdkif 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:26pdkthen don't expect recur to work
19:27pdkoften functions can be restructured to fit this bill though
19:28amalloyapeda__: 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:31apeda__ok
19:31apeda__im just playing aroudn trying to get a better grasp, thakns for all help.
19:32apeda__I didn't think the clojure community would be this big.
19:33amalloyapeda__: i submitted an amendment for you
19:35apeda__same url?
19:35amalloyum, i dunno. i don't know how pastie amendments work. try http://pastebin.com/JAVdt81c
19:36amalloyspeaking of which, consider using pastie instead of pastebin - it has clojure syntax highlighting
19:39apeda__I will in the future, im off for a little break.
19:39apeda__thanks for everything
19:39pdkitd be nice to add some more of these handy links in the topic line
20:56amaevisis 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:57amaevisin java
22:21laurusRaynes, could you tell me about the editor you were building in Clojure?
23:18amalloyhey 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:19clojurebot"([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@rhickeyoh, no flat update
23:19amalloyright
23:20@rhickeyno good reason, it has been requested before
23:46tomojis the planet clojure feed broken?
23:51tomojto match assoc/assoc-in I guess you'd want (update foo bar baz bing bang)
23:51tomojwhich doesn't seem very useful at all
23:51cais2002how does multimethod work if some implementations are located in a different namespace than the one with defmulti ?
23:51amalloyhiredman: you could use (assoc-in foo [bar] baz) too, but we have assoc for that
23:53hiredman*shrug*
23:54hiredmanI think I would actually use (update-in foo [bar baz] (constantly bloop)) before thinking to use assoc-in
23:57amalloytomoj: i suppose you're right, an update with the same parameter style as assoc would be silly
23:58amalloybut eg (update m f & keys) would be useful, maybe? or something like it