#clojure log - Dec 29 2010

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

1:03 hippiehunter: how do you put java annotations on a class you're implementing in clojure? I looked at the java interop page but I dont see any reference to "annotation"

1:14 tomoj: should println be considered blocking?

1:30 yes

4:12 zvrba: oh, this article on finger trees was illuminating: http://scienceblogs.com/goodmath/2009/05/finally_finger_trees.php

5:01 ejackson: Morning folks

9:23 Dranik: I wanna create an ejb. how to add anotation to gen-class?

9:31 rhickey, hello Rich! is there any description on how to add a java annotation to clojure-generated class?

9:32 according to your post here http://groups.google.com/group/clojure/browse_thread/thread/d2128e1505c0c117 the annotations are implemented already

9:32 rhickey: Dranik: you mean in a genclass?

9:32 Dranik: yep

9:32 rhickey: https://gist.github.com/377213

9:32 Dranik: thanks!

9:33 rhickey: Dranik: I'm not sure if there is a genclass-specific description, that work followed afterwards

9:33 https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/genclass/examples.clj

9:34 Dranik: the last was helpful!

9:47 sarcher|work: are there any good clojure web frameworks out there?

9:47 cemerick: sarcher|work: yes, many

9:47 sarcher|work: I've heard of compojure, but when I look at the examples it generates the html inline which doesn't seem like a good approach.

9:47 Raynes: Check out Compojure or Moustache as a few examples.

9:47 cemerick: ring is foundational; many people stack compojure or moustache on top of it

9:48 sarcher|work: That's hiccup -- and I agree, HTML "inline" leaves a sour taste in my mouth. You can use compojure with any templating engine you like.

9:48 Raynes: Compojure doesn't generate HTML at all. You're probably looking at a separate templating library called hiccup.

9:48 Dranik: sarcher|work, well, to my mind all pure clojure web-frameworks are in early stage

9:48 * cemerick is just going to let Raynes do the talking from here on out ;-)

9:48 Raynes: Compojure has bee around for quite a while.

9:49 sarcher|work: Ok, I figured there was a way to generate html without doing it inline.

9:49 Raynes: cemerick: You actually beat me there. My message was longer-winded. :p

9:49 sarcher|work: I just didn't know what to use.

9:49 cemerick: sarcher|work: enlive is generally considered the clojure-"native" templating system. It's quite amazing.

9:50 Raynes: cemerick: Speaking of enlive, thank you so much for that section of your book. I finally 'get' enlive.

9:50 cemerick: Beyond that, you could use stringtemplate, velocity, jsp, or any of the others from Java-land, if you prefer.

9:53 Dranik: Raynes, is the book published already?

9:54 Raynes: Dranik: No. I was doing tech review.

9:54 Dranik: :-(

9:54 Raynes: cemerick: Speaking of that, do you have any dates in your mind for when the book might be finished?

9:56 Speaking of books, I should really work on mine. /yawn

9:56 So much to do, so many ways to avoid it.

9:58 * fliebel is confused by all the Clojure books, and tends to forget which book is from who.

9:59 Raynes: fliebel: I'm pretty sure that outside of my (relatively large) viewer circle, nobody knows the title of my book. It's mostly a working title and likely to change before I finish it.

9:59 s/viewier/reviewer/

9:59 cemerick: fliebel: It's only going to get "worse". That's a good thing. :-)

10:00 * Raynes gives up

10:00 Raynes: I woke up like 30 seconds ago.

10:00 fliebel: cemerick: So which one is with Enlive stuff in it?

10:01 cemerick: fliebel: The one I'm working on; I'd bet @marick's ring book will cover it too.

10:02 fliebel: cemerick: Okay, so I haven't really missed anything, since I'm not a reviewer of any books.

10:02 rhickey: cemerick: are there drafts of your book somewhere?

10:03 cemerick: rhickey: not publicly yet, no

10:03 Raynes: fliebel: You're welcome to take a gander at mine, if you so desire.

10:03 cemerick: I suspect it'll hit O'Reilly's "rough cuts" store sometime next month.

10:03 rhickey: cool

10:03 fliebel: Raynes: I don't know what gander is, but I think so...

10:04 Raynes: $dict gander

10:04 sexpbot: Raynes: noun: The male of any species of goose.

10:04 Raynes: Not quite what I was looking for, but sure.

10:04 fliebel: rhickey: Are you in the mood to explain me why there is no interface for Atom and the others?

10:05 Raynes: "a look or glance" is what mine says.

10:05 Raynes: fliebel: I'm uploading a new draft right now. I'll PM you a link to it in a few.

10:05 fliebel: cool

10:06 rhickey: ,(ancestors clojure.lang.Atom)

10:06 clojurebot: #{clojure.lang.IMeta clojure.lang.ARef java.lang.Object clojure.lang.IRef clojure.lang.IDeref :clojure.contrib.generic/any clojure.lang.IReference clojure.lang.AReference}

10:06 rhickey: fliebel: ^^

10:09 fliebel: rhickey: I don't see something like IAtom? And swap! has a type hint like ^clojure.lang.Atom.

10:11 rhickey: fliebel: ah, I see, right no interfaces, probably should be

10:15 fliebel: are you envisioning another implementation?

10:18 fliebel: rhickey: It fits the CouchDB model rather nicely. Couch is also MMVC and upon updating does basically a compare-and-set! I already did the basic thing using a custom protocol: https://github.com/pepijndevos/couch-atom

10:20 rhickey: fliebel: patch welcome for IAtom

10:21 fliebel: rhickey: You need my contributors agreement for that

10:21 s/that/that?/

10:21 sexpbot: <fliebel> rhickey: You need my contributors agreement for that?

10:21 rhickey: must be Java

10:21 fliebel: yes

10:24 fliebel: rhickey: I'm fine with Java, but I need to give the idea some more thought. Sad thing there aren't any interfaces in java.util.concurrent.atomic. What about ref and agent? I don't know to much about those, nor do I know if an interface is appropriate there.

10:24 cemerick: fliebel: That's pretty clever :-)

10:25 Raynes: fliebel is extra clever on Wednesdays.

10:26 fliebel: cemerick, Raynes: Huh? What? Thank you, I guess?

10:26 cemerick: fliebel: I'd almost want to have the entire database in the atom, not just one document.

10:27 (swap! db-atom update-in ["foo" :bar] inc), etc.

10:27 fliebel: cemerick: Thinking about it already… You'd almost want swap-in!

10:28 cemerick: (swap! db-atom assoc "some _id" {:new :doc})

10:28 swap-in!? Which would do....?

10:29 rhickey: fliebel: more thought always welcome :)

10:29 fliebel: cemerick: 80% of the time you'll be doing update-in, so it'd be a convenience wrapper that needs less arguments.

10:29 cemerick: oh, i see

10:30 eh, I'd almost prefer keeping things explicit

10:30 fliebel: rhickey: I'll try to get you my agreement, and at some point, a patch.

10:30 rhickey: ok

10:31 fliebel: cemerick: Okay :) I'll keep thinking.

10:31 cemerick: fliebel: I'll be tinkering with it, I'm sure. Would you be open to contributing it to clutch, pending what Tunde thinks of it? Conceptually, it'd make for much more pleasant usage than the with-db boilerplate.

10:31 (If it were a db-in-an-atom, rather than limited to document-scope, that is.)

10:33 fliebel: cemerick: I contacted him, but I think he was under the impression I was asking a basic Couch question, along the lines of "how do I update a document?"

10:34 cemerick: fliebel: A google group was just created for clutch; perhaps post there? I can chime in if necessary. http://groups.google.com/group/clojure-clutch

10:36 fliebel: cemerick: I'll look at it. First step is more hammock time and a patch for Clojure. Once I have done that I'll fork Clutch and see where it goes.

10:47 rhickey: One question about Atom. Why does swap call validate and notifyWatches? It calls compareAndSet, which does both already.

10:49 rhickey: fliebel: no, it calls state.compareAndSet, i.e. on the AtomicReference

10:51 * fliebel looks better

11:01 fliebel: rhickey: For performance reasons? In my opinion, the atom interface has only compareAndSet and reset. Swap is built on top of that. Reset could also be based on compareAndSet, but this comes at to high a cost. Currently Atom has a HAS-A relation to AtomicReference, would it be a sensible thing to make it an IS-A relation? Not sure about the practical side of that, but swap! could work for anything in java.util.concurrent.atomic.

11:03 rhickey: fliebel: look harder

11:06 KirinDave: Damn

11:19 fliebel: rhickey: Nope, looking as hard as I can, but still not seeing why state.compareAndsSet is used. Here is how I see it: Both have the same signature, only difference being the ARef stuff. The ARef stuff is handled by swap. If swap was to drop that, and let compareAndSet handle the validate and notifyWatches, everyone is happy.

12:59 kaiser: hi, guys

12:59 how do i check if an element is in a vector?

12:59 Guest63497: (contains? [1 2 3] 2) seems not working properly, because the second parameter is an index

12:59 Raynes: &(some #{4} [1 2 3 4 5 6])

12:59 sexpbot: ⟹ 4

12:59 Guest63497: hmmm...

13:00 Raynes: Guest10433: It's working properly, it just isn't designed for what you're trying to use it for.

13:00 Guest63497: yes, Raynes...you're right

13:01 Guest10433: Raynes: wrong guest :D i need to log in here

13:01 Raynes: Oopsy. :>

13:02 Guest63497: thank you Raynes

13:03 how do i remove an item from a vector?

13:04 i'm using (disj (set vector) item)

13:04 but i don't think is a good idea

13:04 amalloy: Guest63497: ##(remove #{3} [5 6 8 3 1 2])

13:04 sexpbot: ⟹ (5 6 8 1 2)

13:05 Raynes: If you know the index of the element, dissoc would work as well.

13:05 Guest63497: thanks amalloy and Raynes

13:05 amalloy: Raynes: really? i thought that wasn't the case unless it's at an edge

13:05 &(dissoc [5 6 8 3 1 2] 2)

13:05 sexpbot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap

13:05 Raynes: &(dissoc [1 2 3] 1)

13:05 sexpbot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap

13:05 Raynes: Color me surprised.

13:05 I could have swore...

13:05 &(assoc [1 2 3] 1 3)

13:05 sexpbot: ⟹ [1 3 3]

13:05 amalloy: Raynes: insert/remove in the middle of a vector isn't fast, so it's not made easy

13:06 Raynes: Bizarre.

13:06 amalloy: seems reasonable to me

13:58 markskilbeck: Hey, guys. When I run 'mvn package', as per these instructions http://riddell.us/ClojureOnUbuntu.html, I get the following output (the build fails). http://pastebin.com/e01je1EN

13:58 How should I proceed?

14:02 mister_roboto: Markskilbeck Looks like u need to add those repositories to your pom file

14:03 Also you don't need snapshot since 1.2.0 is released now

14:04 Maybe that's the only problem. Snapshot probably not in the main maven repo

14:06 markskilbeck: mister_roboto: Domo arigato.

14:35 Hi, all. Say I'm in the directory ~/Documents/code, and in the subdirectory examples/ there are clojure files. How do I get require to see these files?

14:38 tonyl: are the clojure files namespaced? something like (ns examples.file1)

14:39 if that is the case just (require 'examples) should be fine

14:39 markskilbeck: Yup. introductions.clj is namespaced as examples.introduction.

14:40 amalloy: markskilbeck: introductions.clj should be namespaced as examples.introductions (ie, filenames must match exactly)

14:41 markskilbeck: That was a typo on my part - the file is introduction.clj. My apologies.

14:41 http://pastebin.com/EEH1Mckq is the output.

14:43 amalloy: markskilbeck: well, looks like your require command is right. does (System/getProperty "user.dir") return the directory above examples?

14:43 er...wait, that's probably a silly thing to check. the classpath is more interesting than the cwd

14:45 so (System/getProperty "java.class.path") should be some list that includes the directory above examples

14:45 markskilbeck: ^

14:46 markskilbeck: amalloy: http://pastebin.com/dDPu6yL5

14:47 ordnungswidrig: markskilbeck: there should not be the .clj files on the classpath but the directory containing them.

14:47 amalloy: markskilbeck: right

14:49 markskilbeck: ordnungswidrig: amalloy: you're right - I f'd up. Thanks :)

14:50 sarcher|work: Random question, but what types of apps are y'all using clojure to build?

14:50 ordnungswidrig: sarcher|work: web, erp

14:51 sarcher|work: cool I'm just trying to figure out where clojure would be a good fit for me.

14:51 I wasn't sure if people wrote tcp/ip servers, services, webapps, desktop apps or what in clojure.

14:51 amalloy: sarcher|work: a card-game solver/ai, and www.github.com/Raynes/sexpbot

14:51 dnolen: sarcher|work: all of the above

14:52 sarcher|work: At my current job we have a java / tomcat / mysql webapp.

14:52 I'd like to start using clojure some, but I'm still learning and trying to figure out how and where i could use it at the same time.

14:53 ordnungswidrig: sarcher|work: clojure fits all, however desktop apps with swing feel a little unnatural (IMHO) because it's all about mutable state. I did not find a clojure lib which gave be the abstractions on top of swing that "felt right"

14:54 sarcher|work: ordnungswidrig: that makes sense.

14:54 a lot of what i do now is retrieve xml data, parse the data into an object, then maybe filter that data and display it on a page.

14:54 it's pretty straight forward for the most part.

14:54 ordnungswidrig: sarcher|work: that's where fp shines

14:55 sarcher|work: yeah that's what I'd like to learn. how to apply those concepts and clojure to our existing app to make it better.

14:55 gju_: can i pass datatypes to functions? like i have a function which returns some data that has to be in the type i gave to the function or sth like that?

14:55 sarcher|work: I'm reading "Programming Clojure" now

14:56 but I'm only about 50 pages in. And fibinacci numbers are great, but not a real-world example of what I'd like to do with the language :)

14:57 ordnungswidrig: gju_: can you give an example of what you want to accomplish?

15:00 gju_: i've got a fn that reads n bytes from a file and at the moment it casts it to string and returns it. but there could be data that's not stored in form of a string but for example as an integer. so it would be neat to have the possibility to tell the fn what data type i want to be returned.

15:05 fliebel: gju_: From what I understand, you could pass it a cast function, so you do ((fn [f] (f (read-line))) int) But that might be nonsensical… Never mind.

15:05 gju_: The Clojure reader would return the appropriate type for one…

15:07 &(load-string "1e1")

15:07 sexpbot: java.lang.SecurityException: You tripped the alarm! load-string is bad!

15:12 cemerick: sarcher|work: do look at clojure.xml and clojure.contrib.zip-filter.xml

15:28 ordnungswidrig: how can i parse html into a hiccup-friendly datastructure?

16:09 raek: ordnungswidrig: enlive and https://gist.github.com/633049

16:10 ordnungswidrig: I also once saw a wrapper lib for tagsoup (same as enlive uses) that used the hiccup structure

16:12 mrBliss: raek: https://github.com/brool/beaujiful-soup or https://github.com/antoniogarrote/apricot-soup

16:15 raek: to get clojure.xml to use tagsoup isn't very hard: https://github.com/raek/klouzher/blob/master/src/se/raek/html.clj

16:16 mrBliss: actually, I think it was yet another one I had seen: https://github.com/nathell/clj-tagsoup

16:17 mrBliss: raek: enough soups to choose from :-) Too bad I don't like soup (the one you eat)

17:13 benreesman: anyone here using aleph as an http client?

17:17 amalloy: chouser: it's been a while since i checked - what's the status of finger trees these days?

17:19 pdk: very moist

18:20 Berengal: So I read that vars are supposed to have dynamic scope and that functions are bound to vars, so you could dynamically add e.g. logging around a function. It doesn't seem to work with self-recursive functions.

18:21 Does anyone know why?

18:22 technomancy: recur doesn't involve var resolution

18:23 Berengal: I'm not using recur, I'm using the name

18:23 AWizzArd: Berengal: I am not so sure what you mean. Dynamic scope is one thing, function composition another one. Composition allows you to decorate existing functions with side-effects, such as logging.

18:23 Without recur your recursion is limited.

18:23 raek: vars have static scope, but can be dynamically bound

18:24 qbg: Berengal: Try using #'<fn name> instead

18:24 Berengal: Here http://pastebin.com/2sy4zVdY

18:24 raek: (scope = what variable does the name stand for?, binding = what value does the variable have?)

18:25 qbg: What version of Clojure are you using?

18:25 Berengal: qbg: Yes, that works, but then the rebinding has to be premeditated

18:25 1.2

18:28 raek: hrm. my intuition says that this example should work. but why doesn't it?

18:28 Berengal: Could it be that when defining add-nat it's resolving the actual value, i.e. the original function?

18:29 raek: it should not... I think

18:29 Berengal: No, not from what I've read, but from what actually happens that's a possible explanation.

18:30 raek: (defn x [] 1) (defn y [] (x)) (binding [x (fn [] 2)] (y)) => 2

18:30 Berengal: Yeah, I tried that as well. Wrapping works, but self-references do not

18:30 raek: ah

18:31 (defn foo [x] ...) becomes (def foo (fn foo [x] ...))

18:31 note the extra foo

18:31 Berengal: So you could make a second function, add-nat*, and just bounce the self-recursion off of that, and it'd work

18:31 Aaah

18:32 cemerick: Berengal: just using #' would be simpler and more future-proof. Vars are no longer dynamic by default in 1.3.

18:32 ossareh: raek++

18:32 qbg: ,(macroexpand '(defn foo [x] (+ x 2)))

18:32 clojurebot: DENIED

18:32 Berengal: cemerick: Using #' would have to be premeditated.

18:33 raek: (def add-nat (fn [x y] ...)) gives the result you expected

18:33 cemerick: Berengal: as I say, all dynamic rebinding will have to be premeditated in 1.3+

18:33 so, might as well get in the habit, is my point :-)

18:33 Berengal: cemerick: Yeah, a bit of a shame. Do you know the reasoning why?

18:33 qbg: Most likely performance

18:34 Berengal: Thought as much

18:35 raek: Berengal: this might be interesting for adding trace printlns: https://github.com/technomancy/robert-hooke

18:35 cemerick: Berengal: see http://dev.clojure.org/pages/viewpage.action?pageId=950293 and http://dev.clojure.org/display/design/Improve+Binding

18:35 technomancy: heh; was about to suggest hooke

18:35 raek: (inc technomancy)

18:35 sexpbot: ⟹ 5

18:36 cemerick: Rich went into the motivations/consequences in detail at the conj; watch for his second talk's video.

18:36 Derander: (inc technomancy)

18:36 sexpbot: ⟹ 6

18:36 technomancy: Berengal: the hooke approach will work across threads in any version of clojure

18:36 raek: hrm, I should use robert.hooke for debugging stateful code more often...

18:36 qbg: Is his second talk up yet?

18:36 cemerick: not yet

18:36 Berengal: technomancy: So one thread could enable logging of function calls in another thread?

18:37 ossareh: ahh, raek I wanted to inc you not ++ you earlier.

18:37 (inc raek)

18:37 sexpbot: ⟹ 2

18:38 technomancy: Berengal: something like this, yes. (add-hook #'add-nat (fn [add-nat x y] (println "args:" x y) (doto (add-nat x y) println)))

18:39 Berengal: but it sounds like what you want is clojure.contrib.trace/dotrace

18:39 well, if you just want it to work. but if you want to understand it, you can reimplement it with ooke =)

18:39 *hooke

18:39 raek: neat. I somehow forgot that doto can be used for other things than java interop.

18:40 technomancy: raek: my favourite: (doto 'clojure.repl require in-ns)

18:40 always makes me smile.

18:40 Berengal: technomancy: Actually, I'm just poking around at internals. I always end up doing that when learning a new language :)

18:40 raek: technomancy: wow.

18:41 Raynes: It would be nice if Clojure automagically make earmuff vars dynamic.

18:41 To, at the very least, give meaning to earmuffs.

18:42 raek: didn't 1.3 do that for a while?

18:43 AWizzArd: Raynes: you want the * to be a reader macro?

18:43 Raynes: I don't know what I want. I really just want earmuffs to have solid meaning.

18:44 tomoj: why should that particular set of symbols have any special meaning?

18:44 cemerick: Given how rare vars are actually used dynamically, that doesn't make a lot of sense.

18:44 ^:dynamic is perfect, IMO

18:45 AWizzArd: At the moment I am with cemerick on this.

18:45 Often those global defs can also be for constants or just parameters of a program.

18:46 Raynes: It's a bizarre convention.

18:46 tomoj: but no earmuffs for those, right?

18:47 Raynes: If you put earmuffs on non-dynamic vars, you're doin' it wrong.

18:47 I guess people still do it though.

18:47 technomancy: yeah, that makes sense to me

18:47 why should the compiler need extra help to figure out something a human can tell at a glance?

18:47 AWizzArd: tomoj: the ** mark global defs. They visually stand out of vars introduced via let

18:48 Raynes: ** marks dynamic defs.

18:48 tomoj: AWizzArd: that's not the orthodox position :)

18:48 Raynes: At least, that's what it said in my memo.

18:49 AWizzArd: It just happens to be the case that a subset of the globally visible vars are used as dynamically bindable.

18:49 tomoj: http://www.assembla.com/wiki/show/clojure/Clojure_Library_Coding_Standards

18:49 "Use *earmuffs* only for things intended for rebinding. Don't use a special notation for constants; everything is assumed a constant unless specified otherwise."

18:49 Raynes: There is no convention for constants.

18:49 AWizzArd: Only because this site says it means that this is something objective.

18:50 The rule is simply „wrong” — in the opinion of some people.

18:50 tomoj: many other symbol styles are available which are hardly if ever used

18:50 AWizzArd: yes

18:50 tomoj: guess there aren't enough useful conventions to use them up

18:51 AWizzArd: tomoj: for example: the suggestion to use type hints only on code that is time critical is also plain wrong. In my opinion that is.

18:51 Raynes: If I had to type hint all of my code, I'd probably stop writing it. :\

18:51 tomoj: naturally people disagree, I meant "orthodox" as a joke

18:52 AWizzArd: I would add to this guide: *warn-on-reflection* should be set to true per default, and all reflection warnings should be eliminated via type hints.

18:52 opqdonut_: except that's impossible with many arrayish things

18:52 AWizzArd: tomoj: several “styles” were used before Clojure. They are not objectively good or bad, it’s opinion.

18:53 opqdonut_: do you have an example?

18:53 opqdonut_: and there's a ton of reflection warnings coming from :use'd libraries

18:53 even non-contrib ones

18:53 Raynes: AWizzArd: ##(class (.getBytes "a b c"))

18:53 sexpbot: ⟹ [B

18:53 technomancy: what's the point of avoiding reflection that only happens during startup for long-lived servers?

18:54 opqdonut_: AWizzArd: it's a good method, but it hasn't worked out that well for our project

18:54 AWizzArd: I type-hint in my code for example: (defn foo [^"[[Ljava.lang.String;" a] ...)

18:54 For a 2d String array.

18:54 opqdonut_: i've had problems with aset and aget not being resolved

18:54 AWizzArd: And ^"[B" seems to be a fine type hint too.

18:54 opqdonut_: especially if one writed general-purpose array-handling functions

18:54 AWizzArd: opqdonut_: yes true, I also had problems with those.

18:55 opqdonut_: err, wrote

18:55 I'm tired

18:55 AWizzArd: Though this seems to be fixable as well, if it is really true.

18:55 I was able to type-hint the reflection warnings for my agets away.

18:55 opqdonut_: I've tried

18:55 anyway, off to sleep ->

18:55 AWizzArd: nighty :)

19:03 ysph: Say I have a function called valid?, which accepts a state and makes a validity determination based on rules it knows about. Obviously, it returns either true or false; however, in the false case, perhaps the client may want to know a reason for declaring the state invalid. To me, this is information about the false case, i.e. metadata. Of course, adding metadata to boolean false is probably a non-starter. Is there any use in pursuing

19:03 such a functionality, or should I just let it return false and be done with it?

19:03 Somelauw: I am checking out clojure.

19:03 So far it seems great.

19:03 AWizzArd: ysph: can you return a defrecord maybe?

19:04 qbg: ysph: Make a not-valid? that returns the reason when it is not valid

19:04 (maybe)

19:04 dsop: is there a way to force clojure.contrib.logging to use java.util.logger instead of apache commons?

19:05 Somelauw: But java is completely different from clojure, I think.

19:05 AWizzArd: Somelauw: depends on what you mean by “completely” (:

19:05 They share an infinite number of things.

19:06 amalloy: ysph: you can either do not-valid? instead, or return something like [validity & reasons]

19:06 Somelauw: dynamic vs static typed, functional vs object orientated, optimized for conditional branching vs tail recursion.

19:06 amalloy: the client who doesn't care why can grab only the first element; the one who does can look at the whole thing

19:06 AWizzArd: Somelauw: Yes, there are major differences in the non-trivial areas.

19:07 ysph: qbg: amalloy: not-valid? would work i think in a majority of cases

19:07 Somelauw: loop - recur seems nice to me, but it probably can't be nested since recur would always recurse to the latter loop.

19:07 AWizzArd: Somelauw: do you mean mutual recursion? Clojure also offers trampolines.

19:08 Otherwise I am not sure what you mean by nested recursion.

19:12 _na_ka_na_: ,(try (finally (doseq [_ []])))

19:12 clojurebot: _na_ka_na_: Gabh mo leithscéal?

19:13 _na_ka_na_: &(try (finally (doseq [_ []])))

19:13 sexpbot: java.lang.UnsupportedOperationException: Cannot recur from catch/finally

19:13 _na_ka_na_: Hey guys where can I report ^^ bug

19:16 Somelauw: I will read about trampolines in that case.

19:25 dsop: has someone experience with logging on appengine?

19:33 amalloy: Somelauw: in a functional context it doesn't make sense to want to recur to any loop but the inner one

19:34 the fact that it's not possible is surprisingly unimportant, if you're used to having labeled break/continues (though even in java those are rarely used)

19:38 Somelauw: amalloy, I am not sure, I will try to make up some code in which I would like to have a nested loop.

19:38 amalloy: Somelauw: great. if you find some, i'd love to be enlightened

19:43 auser: so if I have a map with several keynames, i.e. {:a 1 :b 2}, can I replace one of that map? i.e. something like: (alter {:a 1 :b 2} (fn [table] (assoc table :b 3)))

19:46 amalloy: auser: i don't understand. isn't that what assoc does? are you looking for a way to mutate it in-place rather than get a new, modified version or something?

19:47 Somelauw: amalloy, can clojure do this with loop-recur? http://pastebin.com/C0i8z3zS

19:47 auser: no, I just wanted to make sure that's how it works

19:51 bdesham: sorry for the newbie question, but I just downloaded clojure-contrib from github. where do I need to "install" it?

19:51 the .jar file or whatever else

19:52 amalloy: Somelauw: i don't have much scheme experience. is the desired output 0 1 2 2 3 4?

19:52 Somelauw: I didn't insert spaces or newlines, so it is 01223444234442344423444.

19:52 technomancy: bdesham: clojure doesn't really work that way; you'll have an easier time using something like leiningen rather than manually downloading jars: https://github.com/technomancy/leiningen/blob/master/TUTORIAL.md

19:53 bdesham: technomancy: hmm, okay. thanks!

19:55 Somelauw: It's not hard to understand, a named let works just like a function that is immediately applicated.

19:57 When entering spaces in the outer loop the output becomes: 012 23 4 4 4 23 4 4 4 23 4 4 4 23 4 4 4

19:57 In short, can you nest loop-recur in clojure?

19:58 auser: ah I see amalloy

20:00 amalloy: Somelauw: okay, i think i get it. but your example requires use of the stack, right? i don't see how you could optimize this for tail-calling

20:03 Somelauw: I think scheme will tail-recurse that code, although I am not completely sure.

20:04 amalloy: Somelauw: it can't. you have to call loop2, return, and then call loop1. it needs to keep loop2's data on the stack while calling loop1

20:04 anyway https://gist.github.com/fcd4dc5f2050e65d998c is a direct translation

20:04 loop/recur is intentionally allowed only for cases that can be TCOd

20:07 or i guess it's calling loop2 a lot of times recursively, then unrolling the stack to call loop1 some more. either way, not tail-calling

20:07 sadly i gtg. i'll read your response later though, Somelauw

20:08 Somelauw: Will this work: http://pastebin.com/6t68Bq3z

20:08 Respond me later

20:09 Since the previous link will expire in 24 hours, here is a permanent one: http://pastebin.com/rTSY79bM

20:39 amalloy: Somelauw: i don't get it. isn't that identical to the paste you made before?

20:40 Somelauw: The call to the outer loop is now outside of the named let.

20:40 clojurebot: Roger.

20:41 amalloy: clojurebot: forget The call to the outer loop

20:41 clojurebot: jcall is http://paste.lisp.org/display/67182

20:41 amalloy: ugh

20:43 Somelauw: if you moved the call to the outer loop outside, then yes, you could do it with loop/recur. but when i look at your most recent paste it's byte-for-byte identical to the previous one

20:45 Somelauw: amalloy, my bad

20:45 http://pastebin.com/rTSY79bM

Logging service provided by n01se.net