#clojure log - Apr 03 2011

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

0:12 Havvy: In lein, what would be the groupID/artifactID for http://clojars.org/repo/irclj/irclj/ ?

0:12 amalloy: Havvy: irclj

0:12 or irclj/irclj if you want to be verbose

0:15 technomancy: "If you're not really into the whole brevity thing" as the Dude would say

0:22 Havvy: (inc amalloy)

0:22 sexpbot: ⟹ 7

0:23 amalloy: Havvy: clojars will even tell you the answer to this question

0:24 Havvy: It will?

0:24 amalloy: http://clojars.org/irclj/irclj

0:24 Havvy: Oh, it will.

2:46 Derander: what was that library released recently to handle classpaths on a persistent vm?

2:47 jark

3:23 thorwil: given the code at https://github.com/gcv/appengine-magic/issues/14#issue/14/comment/949920

3:24 using (save-article-1) should work on the repl, after a (doto 'texst.core require in-ns), right?

3:25 but what i get is "java.lang.NoClassDefFoundError: texst/core/Eek (NO_SOURCE_FILE:0)"

3:26 even after pasting (ds/defentity Eek [body]) to the repl

3:29 amalloy: thorwil: it seems to me you will have a much larger pool of helper-people if you can narrow your questions down to involve less domain-specific stuff

3:30 i'd love to help, but i don't know anything about GAE, which iirc is what you're using

3:31 thorwil: amalloy: i wish i could, but the problem *is* specific

3:31 amalloy: does it work if you change defentity to a defrecord-like construct?

3:33 thorwil: amalloy: it works if i put the defentity within the function. but surely gvc (appengine-magic dev) knows what he does, and he placed it outside!?

3:34 amalloy: not seeing how that's relevant to my suggestion. i'm trying to find out whether you're having general classpath issues (which you'd see with defrecord) or something specific to defentity

3:39 thorwil: making sense of the (defmacro defentity ...) in https://github.com/gcv/appengine-magic/blob/master/src/appengine_magic/services/datastore.clj is beyond my level of understanding

3:40 if it's a classpath issue, i wonder if Leiningen 1.4.2 is the culprit

3:43 amalloy: seems tremendously unlikely

3:44 thorwil: the defentity macro is pretty simple. he just defines a record with the name and properties you specify, which implements/extends/satisfies the EntityProtocol

3:46 thorwil: i could just copy (defrecord ~name ~properties ... and fill in the gaps?

3:46 amalloy: indeed

3:46 though get-entity-helper might be private

3:47 thorwil: what's this# ?

3:47 amalloy: having a protocol with multiple arities for the same function kinda smells bad. like he meant to use an interface

3:47 gensym for java's this object

3:47 &`(fn [arg#] (inc arg#))

3:47 sexpbot: ⟹ (clojure.core/fn [arg__10205__auto__] (clojure.core/inc arg__10205__auto__))

5:07 fliebel: To map or not to map, that is the question: Whether 'tis nobler in the mind to suffer the slings and arrows of O(n) lookup, or to take arms agains the a sea of added complexity.

5:10 Or, in normal language, will I store my game objects in a vector or a map. A vector makes things simple, but for a bat to tell the location of the ball, it'd have to go through all the 3 objects to look it up. On the other hand, a map makes this faster and simpler, but makes everything else more involved.

5:19 Can a protocol extend another protocol or interface? Or do all implementations just need to implement both?

6:20 nickik: Has somebody used clojure with couchdb spezially the clojure view server?

6:23 mids: having problems?

6:32 nickik: mids, i just doesn't work and I don't know how i could debug it. I have know idea whats wrong. If I start the server manually it starts and throws no errors or something but if I trie to send a query from the repl nothing happens.

7:10 tomoj: nickik: you're saying you're trying to talk to the view server from the repl?

7:11 or just using a couchdb client from the repl?

7:11 nickik: not direktly

7:11 tomoj: (which happens to be talking to a couch running the clojure view server)

7:11 nickik: threw couchdb

7:11 yes

7:12 tomoj: do you get anything back?

7:12 nickik: like discribed here: http://www.ibm.com/developerworks/java/library/j-couchdb-clojure/?ca=drs-

7:12 tomoj: something besides querying a view

7:12 nickik: no

7:12 yes everything else works

7:12 creating docs etc.

7:13 tomoj: looked at the couchdb logs?

7:13 nickik: no

7:13 (its my first time using cloud)

7:15 not sure what i should be looking for in the logs

7:26 fliebel: nickik: Are you sure the query server is configured?

7:27 The link you gave does not mention starting it, and I do believe Clutch makes Clojure views.

7:28 nickik: yes i see the server in my couchdb config (in futon)

7:29 i did it accourding to the clutch github site

7:30 fliebel: nickik: Hm, I think you might be better helped asking the #couchdb channel. While they might not know Clutch, they do know how to debug malfunctioning query servers.

7:30 nickik: true I figured maybe somebody has had the same problem

7:31 I'm trieng to get some good logs of my problem atm

7:31 fliebel: nickik: What happens if you run the query server yourself? The protocol is really simpel.

7:32 nickik: it just starts it dosn't generate any output or anything

7:32 no errors or something

7:32 fliebel: Okay, now try manually running something… let me see

7:33 http://wiki.apache.org/couchdb/View_server

7:35 nickik: ah intressting stuff happening here while i was reading the view_server crashed. I never let it run manually more then 20s.

7:35 ["fatal","fatal_error","java.lang.IllegalArgumentException: Value out of range for char: -1\n\tat clojure.lang.RT.charCast(RT.java:887)\n\tat clojure.contrib.json$read_json_reader.invoke(json.clj:116)\n\tat clojure.contrib.json$fn__1125.invoke(json.clj:178)\n\tat clojure.contrib.json$fn__1104$G__1099__1115.invoke(json.clj:167)\n\tat clojure.contrib.json$read_json.invoke(json.clj:197)\n\tat com.ashafa.clutch.view_server$run$fn__69.invoke(view_

7:35 server.clj:129)\n\tat com.ashafa.clutch.view_server$run.invoke(view_server.clj:127)\n\tat com.ashafa.clutch.view_server$_main.doInvoke(view_server.clj:146)\n\tat clojure.lang.RestFn.invoke(RestFn.java:398)\n\tat clojure.lang.AFn.applyToHelper(AFn.java:159)\n\tat clojure.lang.RestFn.applyTo(RestFn.java:133)\n\tat com.ashafa.clutch.view_server.main(Unknown Source)\n"]

7:36 fliebel: nickik: I've seen this bug before… Try getting a newer version of JSON.

7:37 nickik: fliebel, my i have standard 1.2

7:37 contrib

7:37 fliebel: I know, let me look it up.

7:39 nickik: http://dev.clojure.org/jira/secure/QuickSearch.jspa

7:42 So, according to stuartsierra this has been fixed.

7:44 nickik: witch bug do refere to?

7:44 contrib-100?

7:45 fliebel: oh, right, post request

7:45 http://dev.clojure.org/jira/browse/CONTRIB-101

7:45 there are quite a few of these.

7:47 nickik: could it be that leiningen is chaching an old contrib?

8:06 fliebel, what should I do? Ask on the group?

8:07 fliebel: nickik: Hm, maybe. But did you try another version of contrib? Maybe there is one for 1.2.1?

8:08 nickik: i thought 1.2.1 should come with 1.3

8:11 fliebel: hm, okay, the 1.2.0 branch is not fixed, but I think the 1.3 version of json will run just fine.

8:15 nickik: ah ok

8:15 lets hope everything else works with 1.3 too

8:15 thx fliebel

8:16 fliebel: nickik: I think you can just use 1.3 json with 1.2 Clojure if you want.

8:17 nickik: fliebel, but then i would have to change the source clutch view server. I can only change the jars I pass in

8:29 raek: you could use [org.clojure/data.json "0.1.0"] too

8:54 fliebel: Does anyone have experience with BufferStrategy? I found one example where they just get a graphic, render, and dispose, but in other examples, there is a lot of cruft about these volatile images. Do I need that?

9:12 nickik: what leiningen project.clj do i need if i want clojure alpha 6 and contrib alpha 6?

9:17 raek: alpha-6 seems to be [org.clojure/clojure "1.3.0-alpha6"]

9:17 and contrib has been split up into separate modules

9:18 you can look around at http://build.clojure.org/releases/org/clojure/ http://build.clojure.org/snapshots/org/clojure/ and http://repo2.maven.org/maven2/org/clojure/

9:19 also, there's this: http://corfield.org/clj/index.cfm

9:19 fliebel: How does alter-var-root work? I can use that to change earmuffs, right?

9:20 raek: fliebel: well, you can use that to change any var, dynamic or not

9:20 to change the thread-local value, use set!

9:20 fliebel: ah, okay.

9:24 raek: I can;t get it to work: user=> (def ^:dynamic *frame-duration* 100) #'user/*frame-duration* user=> (set! *frame-duration* 50) IllegalStateException Can't change/establish root binding of: *frame-duration* with set clojure.lang.Var.set (Var.java:219)

9:24 raek: fliebel: you have to do that inside the dynamic scope of a (binding [...] ...)

9:25 if you just want to configure the value once on startup, maybe redefining the root binding with alter-var-root is better

9:26 fliebel: raek: Okay, but then again, how does it work? It seems it takes a fn like swap!, but just passing it inc game an error that suggested that I need to return a var.

9:26 raek: you need to pass it the var object

9:27 (alter-var-root #'some-var inc)

9:27 fliebel: ah, that way! I was thinking inc should return a var.

9:27 okay, thanks

9:28 So, no need for ^:dynamic on this one?

9:28 raek: not if you don't itend to use binding on it

9:28 fliebel: Okay, I'll leave that open than.

9:28 raek: or let the users of the namespace do that

9:32 mrBliss: excerpt from 'On Lisp': "An ideal world is left as an exercise to the reader." :-)

9:32 ejackson: mrBliss: genius !

10:38 rhickey: I'm thinking about making the default behavior of promise, when an Throwable has been delivered, to re-throw it on deref, with an optional arg to control that - (promise :rethrow bool), default true

10:41 raek: what used to happen / what happens when :rethrow is false?

10:44 when was clojure.lang.IBlockingDeref added?

10:45 rhickey: raek: whatever is put in the promise is returned

10:45 raek: but if the expression throws?

10:45 rhickey: raek: what expression?

10:46 (promise)

10:46 raek: sorry, mixed up this with delay/force

10:47 rhickey: https://github.com/clojure/clojure/commit/84710838d6996d9144d83c5b659bdeda4c656100

10:47 ^added IBlockingDeref

10:47 raek: very nice...

10:48 will read it and update my blog post about clojure and the executor framework

10:49 kephale00: I'll give this question one last shot: Is there a way to control the maximum number of cores a clojure program uses? The doesn't appear to be a JVM argument that will do it. The program uses agents heavily.

10:49 rhickey: kephale00: no

10:50 kephale00: rhickey: a final answer! thank you

10:50 I tried to use cpulimit to start java, and that worked to an extent, but it wasn't strict enough

10:51 rhickey: kephale00: it would have to be on the JVM level, for sure

10:51 kephale00: The situation is I'm running experiments on a cluster with shared nodes, and getting 8 slots on an 8 core machine has near impossible statistics for actually getting the job scheduled.

10:52 rhickey: thats what I figured… ah well, I guess i have to single thread-ify my program (never thought I would have to "devolve")

10:53 raek: rhickey: so this new change provides a way to get a Throwable to be thrown at the deref call? (by delivering a Throwable as the value)

10:54 rhickey: raek: right

10:54 kephale00: rhickey: Thank you though. Now I know I can stop banging my head against the wall

10:56 raek: seems like a useful and reasonable default, since Throwables as values are quite rare anyway (at least in my code)

11:00 rhickey: breaking change though

11:00 opposite default would not be

11:04 TimMc: Alternatively, could you add a new method? As opposed to deliver, one would call (deliver-failure some-promise throwable)

11:05 In-band signalling always makes me twitchy.

11:06 or even a new ariy of deliver: (deliver x :throw throwable)

11:06 *arity

11:07 fliebel: How, evil, a map that implements mapentry :)

11:08 rhickey: TimMc: that's not really out-of-band for the receiver anyway, and takes the policy decision away from him

11:08 fliebel: rhickey: How often do you update the contributing page? I sent you my agreement at the end of the last year, and I'm not yet on it.

11:09 rhickey: fliebel: If your not on it I haven't gotten it - updated several times this year, and recently as well

11:10 you're

11:10 fliebel: rhickey: ouch, okay, then I guess I'll have to send you a new one… Sometime… It's not one of my priorities now.

11:16 TimMc: rhickey: Would implementing both be out of the question? deliver could send an exception to be thrown, and promise could still specify whether exceptions are to be rethrown or simply returned.

11:18 In that scenario, promise would only throw if both ends had opted in.

11:18 rhickey: having played with it a bit, I'm not sure I like it better than (deref-and-rethrow anyref-that-might-have-a-throwable)

11:20 I'm not sure how often people need this (communicate errors through a promise)

11:59 fliebel: When I produce a seq in one thread and consume it in another, where is the actual producing going to happen?

12:00 (let [s (iterate heavy-task 42)] (future (do-heavy-stuff-with s)))

12:02 opqdonut: I'm guessing it's the consuming task

12:03 you can probably verify that quickly with (.. Thread currentThread getId)

12:03 fliebel: opqdonut: I guess so to, but it's not what I was hoping for.

12:03 opqdonut: but if you put futures into the seq...

12:03 raek: fliebel: in the consuming thread

12:04 fliebel: Okay, is there any way around that? Or does that just esentially limit my seq chain to one thred?

12:04 raek: fliebel: you could use a LinkedBlockingQueue do decouple them

12:04 fliebel: raek: What about ##(doc seque)

12:04 sexpbot: ⟹ "([s] [n-or-q s]); Creates a queued seq on another (presumably lazy) seq s. The queued seq will produce a concrete seq in the background, and can get up to n items ahead of the consumer. n-or-q can be an integer n buffer size, or an instance of java.util.concurrent B... http://gist.github.com/900517

12:05 raek: ah, it probably does something like that :)

12:06 it seems to fit your problem description

12:06 fliebel: Now I seriously need to consider how much wiggling room I have. I's almost certainly going to fail if I have the producer get a ahead of the consumer to much. e.g. the producer is not completely functional.

12:06 raek: but you can't control in which thread the processing gets done in...

12:07 fliebel: why not?

12:07 raek: seque will start the forcing of the seq in another thread for you

12:08 you can set set the size of the queue to limit how many elements the producer can get ahead of the consumer

12:10 fliebel: yea, so I need to carefully tweak that, if I happen to need it. I got myself in premature optimisation again :P

12:57 TimMc: Can anyone recommend an Emcas color scheme for working on a laptop in sunlight?

12:58 kephale00: I have no clue, but I'm happy to see that question

13:04 Dantas1:

13:20 TimMc: "Katester" is almost what I want.

13:49 marko_: hi, any enclojure users here?

13:50 fliebel: marko_: Not me, but go ahead and ask what you want to know.

13:51 marko_: i started a new project on netbeans and id like to add external libraries like hiccup, but i just cant find how to add them easily to the new project

13:52 there is a preference to add libraries to netbeans, but not to the project itself

13:54 screenshots on web show a menu add library upon lib folder, but not on mine, i have only dependencies. i cant believe if I need to add every library manually setting up each dependencity on pom.xml, thats not cool job

13:54 fliebel: Oh, right, so you need to add maven deps...

13:55 marko_: i have ten or so libraries i want on project. on eclipse its just a matter of click and select

14:14 ok, i think i got it now. there is an autocomplete box on dependencity window where you pick up right items OR go to the maven repository browser and pick up libraries for project from there

14:15 *dependency

14:22 TimMc: I have a map of keys to functions -- what's a good way to map the function values to their return values, each given the same arguments?

14:22 What I have so far... given (def fs {:a + :b * :c /}), (zipmap (keys fs) ((apply juxt (vals fs)) 2 3)) seems to work.

14:23 raek: so you want a map as the result?

14:23 TimMc: yeah

14:24 raek: (zipmap (keys fs) (for [f (vals fs)] (f 2 3 4))) would be my approach

14:25 TimMc: So you'd still use zipmap?

14:25 jkkramer: or (into {} (for [[k f] fs] [k (f 2 3 4)]))

14:26 raek: either that or what jkkramer just wrote :)

14:26 TimMc: I keep forgetting about for. Thanks!

14:27 jkkramer: for and maps are like pb & j

14:29 fliebel: pb & j??

14:29 jkkramer: peanut butter and jelly

14:29 fliebel: jelly?

14:29 jkkramer: or vegemite & toast...whatever foreigners eat

14:30 TimMc: and juxt is like that tasty new cheese you bought that you try adding to everything even when it doesn't quite go together. :-)

14:31 fliebel: jelly (US) is the juice from boiled-down fruit with pectin added.

14:33 jkkramer: for and maps are like paste made from ground peanuts and juice from boiled-down fruit with pectin added

14:33 fliebel: Clojure in a whole is like applesource in that respect, (young children) add it to everything, and it still tastes good.

14:33 (or whatever you foreigners add to everything)

14:34 jkkramer: ketchup

14:34 this is making me hungry. time for lunch

14:35 fliebel: jkkramer: American huh? Ketchup…

14:35 * fliebel has prejudice

14:41 jhchabran: on fait les porcs

14:41 on go macdo

14:47 fliebel: What is the difference between merge and into?

14:51 ejackson: merge is maps only

14:52 so its probably faster for them

14:56 TakeV: Is there a built in PriorityQueue, either in the core or contrib libraries?

14:56 fliebel: TakeV: Java.util.concurrent has them

14:57 TakeV: Sure, thanks.

14:57 fliebel: ejackson: Thanks

14:57 TimMc: TakeV: There's one coming into contrib

14:57 fliebel: TimMc: Why? Anything wrong with the Java one?

14:57 TimMc: I suspect the Java one is mutable.

14:58 fliebel: oh, true...

14:58 TakeV: A pure clojure version would be nice.

14:58 TimMc: TakeV: This appears to be in development: http://clojure.github.com/clojure-contrib/branch-master/priority-map-api.html

14:58 pdk: couldn't you use a sorted map

14:59 TimMc: pdk: Those sort by keys.

14:59 fliebel: TimMc: Oh, I used that one just yesterday, it works fine.

15:06 devn: hmm, jark looks neat

15:12 Raynes: devn: It's pretty shocking how easy it's been to ignore jark. I really should check it out.

15:30 thorwil: "Warning: :repl-init-script is deprecated; use :repl-init", but just renaming the key in the project file causes leiningen to fail with "java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Character"

15:31 so what does leiningen expect for :repl-init in contrast to repl-init-script?

15:33 jkkramer: thorwil: https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L94

15:38 thorwil: i take it :repl-init expects a namespace, not a path, but how do i translate "src/tlog/init_repl.clj" in this context?

15:40 mids: thorwil: tlog/init-repl

15:41 raek: I would expect tlog.init-repl

15:42 thorwil: mids, raek both fail: Exception in thread "main" java.lang.Exception: No such namespace: tlog (NO_SOURCE_FILE:1)

15:42 mids: err that raek

15:42 thorwil: did you declare the ns in the init_repl.clj file itself?

15:46 thorwil: mids: the ns declared in init_reply.cly used to be user, but changing it doesn'thelp

15:49 technomancy: hi! i'm trying to switch from :repl-init-script to :repl-init, as leiningen 1.5 tells me the former is deprecated

15:51 technomancy: initially i thought i would just have to change from the path "src/tlog/init_repl.clj" to a namespace, maybe tlog.init-repl

15:51 but given the trouble above, i guess there's a conceptual change i'm yet unaware of?

15:56 marko_: how do you implement incrementing value on clojure? say you have a map of ({}{}{}), iterate over it and get the number of current loop index?

15:57 number or count

15:57 raek: marko_: ##(map vector (range) [{:a 1} {:b 2} {:c 3}])

15:57 sexpbot: ⟹ ([0 {:a 1}] [1 {:b 2}] [2 {:c 3}])

15:58 raek: instead of vector, you can have a function that takes the index as the first arg and the value as the second

15:58 amalloy: &(doc map-indexed)

15:58 sexpbot: ⟹ "([f coll]); Returns a lazy sequence consisting of the result of applying f to 0 and the first item of coll, followed by applying f to 1 and the second item in coll, etc, until coll is exhausted. Thus function f should accept 2 arguments, index and item."

16:00 fliebel: Which chars have a literal like \newline?

16:02 amalloy: fliebel: you can see the list in LispReader.java

16:02 looks like the ones with "long" escapes are newline, space, tab, backspace, formfeed, return

16:03 then there's \uXXXX and \oXXX

16:03 raek: it's available in clojure too

16:03 ,char-name-string

16:03 clojurebot: {\newline "newline", \tab "tab", \space "space", \backspace "backspace", \formfeed "formfeed", \return "return"}

16:03 fliebel: Okay, thanks. How would I get to the arrow keys?

16:04 raek: arrow keys?

16:04 fliebel: yea, like \up

16:04 TimMc: fliebel: Those are keys, not chars.

16:04 fliebel: TimMc: But they are represented as chars, or not?

16:04 TimMc: Are you using Swing?

16:05 fliebel: yea

16:05 raek: there are no unicode code points for most non-letter keyboard keys

16:05 TimMc: OK, those have keycodes.

16:05 raek: there are some exceptions, though (enter, backspace, tab)

16:05 marko_: raek, thanks, let me see how it works on my end, seems exactly what I need

16:06 fliebel: raek: When I do .getKeyChar on my event, I sure get something for up...

16:06 TimMc: fliebel: Read the class docs for this carefully: http://download.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html

16:07 raek: fliebel: interesting, do you know which one?

16:07 TimMc: fliebel: is it CHAR_UNDEFINED ?

16:07 raek: if you (int ...) it, what number do you get?

16:07 TimMc: "Virtual key codes are used to report which keyboard key has been pressed, rather than a character generated by the combination of one or more keystrokes (such as "A", which comes from shift and "a"). "

16:07 fliebel: I'll try… It displays as a questionmark, so that's not a good sing I think.

16:08 yuk… I'll have to revisit this code :P

16:10 All arrows return 65535

16:11 really everything return 65535

16:11 except… characters :P

16:12 amalloy: TimMc: i don't really work in sunlight much, but i'd expect high-constrast themes to be useful, no? i use color-theme-tty-dark

16:13 TimMc: amalloy: I used Katester for a bit. However, playing with themes messed up my fonts, so I had to restart Emacs.

16:15 fliebel: Is there some trick to mold these constants into a nice dict?

16:20 raek: fliebel: maybe you could use reflection to construct a map with prettier names

16:21 filter by fields starting with VK_, and turn VK_PAGE_UP into :page-up

16:22 fliebel: raek: Can I use ##(doc bean) for that?

16:22 sexpbot: ⟹ "([x]); Takes a Java object and returns a read-only implementation of the map abstraction based upon its JavaBean properties."

16:23 amalloy: i don't see how

16:23 raek: no, you'd like to iterate over static fields

16:23 fliebel: How do I get these?

16:24 raek: java.lang.reflect

16:24 fliebel: oh, okay :)

16:25 * raek tries to cook something together

16:29 raek: fliebel: (into {} (for [field (filter #(.startsWith (.getName %) "VK_") (.getFields java.awt.event.KeyEvent))] [(.getName field) (.getInt field nil)]))

16:30 fliebel: (inc raek)

16:30 sexpbot: ⟹ 7

16:35 raek: ,(-> "VK_CAPS_LOCK" (.substring 3) (.toLowerCase) (.replace \_ \-) (keyword))

16:35 clojurebot: :caps-lock

16:35 fliebel: neat :)

16:35 raek: clojure is such a wonderful language... :-)

16:56 shellox: hi

16:58 do i need lisp programming experience to learn clojure? I just done a little bit ruby programming before

16:58 pdk: you'll learn the basics of lisp that are applicable to clojure through introductory books

16:58 eg practical clojure, programming clojure etc

16:58 amalloy: shellox: no. it helps, of course

16:59 pdk: a java background is helpful too for understanding performance considerations of code and handling java interop/using java libraries

16:59 amalloy: pascal programming experience helps too :P (because any programming experience helps)

17:00 shellox: ok thanks, I'll read some tutorials

17:53 sritchie: hey all -- quick question on clojure.contrib.monads, if anyone's up for it -- https://gist.github.com/900855

17:54 ((build 1 2 3) (list)) produces [["First return." "Next return."] ("building 3" "a list of 12")], as expected. I had thought that (build-chain (list)) would produce the same result, but that turns out not to be the case

17:54 amalloy: brehaut: aren't you lucky to have been nominated as "that monad guy"?

17:54 sritchie: so, any comments on what I'm doing wrong with m-chain would be great

17:55 brehaut: haha

17:55 sritchie: haha, that's the guy I'm looking for!

17:55 brehaut: sritchie: give me a moment

17:55 sritchie: brehaut: no problem, nothing urgent

17:57 brehaut: sritchie: first up, why have you created phase1 and phase2 as bare functions rather than defining them in terms of the monadic combinators?

17:58 sritchie: I'm very new at this -- I wanted to define a closure that would generate a monadic value

17:59 brehaut: sritchie: sure. lookin at your definitions i think its legit, but its quite an awkward way to write it

17:59 sritchie: brehaut: I definitely agree, and I'm glad to hear that this isn't the way! let me give a quick description of my goal, in exploring this --

18:00 amalloy: oh no. now brehaut's going to see how i helped him make his awful macro awfuler

18:00 sritchie: amalloy: haha, he doesn't get to see the gist, don't worry

18:00 brehaut: amalloy: wait, which awful macro

18:01 amalloy: brehaut: he did this as a macro before trying monads

18:01 sritchie: in https://github.com/pallet/pallet, phases are currently built up by threading a request map through a number of subphases, which modify it and pass it on the next phase

18:02 sritchie: I wrote this macro-writing macro that builds up a phase, inserting a call to a checker-function in between every subphase, to make sure that everything's still well-formed in the request

18:02 amalloy: amalloy: sritchie is talking to himself. looks fun, you wanna give it a go?

18:02 brehaut: ok sure

18:03 haha

18:03 sritchie: sorry, trying to pull up a gist -- probably should have had this ready!

18:03 anyway, it seems that the state monad would be a better way to manage this business of incrementally modifying a request

18:03 amalloy: sritchie: my fork of that gist is at https://gist.github.com/895897/

18:04 marko_: is it possible to create a task containing leiningen commands and shell based mv command all in same?

18:04 brehaut: sritchie: brb

18:04 marko_: i have a shell script for it and possibly could use it on intelliJ when deploying google app for dev server

18:05 sritchie: amalloy: thanks, I was looking for this -- https://github.com/whizbangsystems/pallet/blob/feature%2F0.5.0-develop/src/pallet/phase.clj

18:10 amalloy: the macro definitely feels clunky, but the resulting dsl for composing phases is really clean as a result -- I'm hoping that a clean way of defining phases as monadic values will beat it

18:14 brehaut: sritchie: how familiar are you with monads?

18:14 sritchie: not very, this is my first excursion

18:15 but I've been through this whole thing -- http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/

18:15 brehaut: sritchie: then you are diving into the deep end with state-m :) no problem

18:15 ok sure

18:16 sritchie: (not that that tells you anything about my comfort level, but it's the start of an answer!)

18:16 brehaut: sritchie: so m-bind is a variation of apply; its a function application operator

18:17 in particular it applies the a function that takes a single non-monadic value and returns a new monadic value

18:18 sritchie: that's m-result, right? the function that takes a single non-monadic value?

18:18 brehaut: its a bit clearer in haskell because things like the Maybe type clearly wrap another type and so its easy to see how the two levels work

18:18 m-result is the identity for monads

18:19 (m-bind monadic-val m-result) ;=> monadic-val

18:19 sritchie: got it

18:20 brehaut: sritchie: its important to understand that it unpacks the value from the monad.

18:20 sritchie: this means your computation exists on different levels

18:21 so the monadic type in state-m is a function from a value to a pair of state and value

18:22 the implementation of m-bind is a bit of a trip

18:22 i like to think of it as taking a state machine and function that generates a state machine and the binding is creating a new state machine that connects the two

18:23 sritchie: this is all certainly a bit of a trip -- I'm listening, and scanning the beginning of http://intensivesystems.net/tutorials/monads_101.html

18:24 brehaut: sritchie: the best way to grasp all these things is to implement them yourself

18:24 start with identiy-m, then maybe-m, then list-m and state-m

18:24 sritchie: okay, that makes sense

18:25 brehaut: the other thing is that domonad is really useful but its sugar over m-bind

18:25 and it is going to add to your confusion

18:25 sritchie: yes, I was doing expansions of domonad by hand yesterday

18:25 brehaut: thats good

18:26 sritchie: I think it may have been a mistake to try and go directly from the sugar, domonad, to other sugar, m-chain

18:27 I'll take your advice of implementing these, and working with m-bind

18:27 brehaut: sritchie: your problem is that phase1 in particular is not bindable

18:27 (it takes two arguments!)

18:27 but it does return a valid monadic value for state-m

18:27 amalloy: sritchie: have you watched brian marick's recent series of monad videos?

18:28 sritchie: oh, no, I haven't

18:28 I do remember seeing a comment about those on the clojure list, I'll look those up now

18:28 amalloy: thanks, that'll be really helpful

18:30 brehaut: I had thought that (phase1 1 2) would evaluate to the monadic value, which would be bindable

18:30 brehaut: sritchie: the result of phase1 it is bindable only as value side of the bind, not the function side

18:30 sorry thats imprevise

18:31 (phase1 x y) is only bindable as the value of a bind

18:31 phase1 is not in any way bindable

18:31 sritchie: okay

18:32 what would be the proper way to define a computation, here? for a computation that incremented state by 1

18:32 you had mentioned that I should have used the monadic combinators

18:33 brehaut: here is how i would do it

18:33 (with-monad state-m (defn phase1 [x y] (domonad [_ (update-state (fn [s] (cons (str "a list of " x y) s)))] "First")))

18:34 sritchie: ah, I see

18:35 brehaut: im going to try to desugar that for you too

18:35 sritchie: the expression after the comprehension is implicitly wrapped in m-result btw

18:36 sritchie: okay, sure

18:36 brehaut: heres the desugared form

18:36

18:36 (with-monad state-m

18:36 (defn phase1 [x y] (m-bind (update-state (fn [s] (cons (str "a list of " x y) s))) (fn [_] (m-result "First")))))

18:37 sritchie: that's certainly clearer -- m-result takes a value, and returns the monadic value, then

18:37 and update state takes a monadic value and returns a monadic function?

18:38 and then m-bind applies that function to the value

18:38 brehaut: heres the confusing part

18:38 state-m's monadic values are functions

18:38 update-state takes a state updating function but returns a monad value

18:39 that value _happens to be a function_

18:39 but we are using it here as a value

18:39 note that there is an anon function on the RHS of bind?

18:39 sritchie: so update state is taking a monadic value, which for state-m is a state-updating function

18:39 always a state updating function, right, for state-m?

18:41 brehaut: not quite. update-state's argument is not monadic. jsut a normal function.

18:41 that function is provided the old state and returns a new state

18:41 update state wraps that all up in a state machine function

18:42 sritchie: oh, I see -- so (with-monad state-m (m-result (fn [s] (inc s)))) would convert (fn [s] (inc s)) into a monadic value

18:43 brehaut: yes but not in the way you imagine

18:43 m-result takes a non monadic value and wraps it in the monadic context type needed for the monad

18:44 in state-m that means it returns a function that takes the existing state machine state and returns a new state machine state (thats a pair of value and state) where the state is whatever it always was a the value is (fn [s] (inc s))

18:46 sritchie: one quick question (and really, thanks for taking the time go through this with me) -- in your phase1 example, with m-bind --

18:46 with m-bind, the first parameter is a monadic value, and the second is the function to apply to that value, right?

18:46 brehaut: correct

18:49 sritchie: so our monadic function here -- (fn [_] (m-result "First")) -- returns a monadic value that doesn't modify the state, but returns "First" -- so it's going to be really helpful for me to work out exactly how m-bind applies that function to (update-state .. etc in this case

18:49 brehaut: yeah :D

18:49 thats the head trip ;)

18:50 also, i cant get m-chain to work at all ;)

18:50 sritchie: that's the real head trip

18:51 okay, so, my homework is to go off and implement these

18:51 brehaut: yup

18:51 sritchie: ive got a full expansion of a state-m on my site

18:52 sritchie: simpler question -- in an application like pallet's, where we modify state but don't really care about return values -- that's still a good use for the state monad, right?

18:52 brehaut: sritchie: http://brehaut.net/blog/2010/welcome_to_the_machine

18:52 sritchie: hey, great

18:52 brehaut: if you are just creating a log of events then the writer monad is probably more appropriate, but i dont know if there is an imp in c.c.m

18:53 sritchie: well, eventually the map is converted into a big ssh command for the nodes

18:54 the goal of that macro-writing macro was to allow for the state, the request, to thread through a function that checked whether or not the state was well formed, which would either act as identity or throw an exception

18:54 clojurebot: you're doing it wrong!

18:54 brehaut: haha

18:54 sritchie: haha, what was it responding to?

18:54 brehaut: throw an exception

18:55 sritchie: but it would be very advantageous to, rather than throw an exception, keep passing the request along and add the error as a result

18:55 brehaut: sritchie: i think state is a reasonable tool in this case. in combination with a variation of maybe-m you could get error handling too

18:58 TimMc: clojurebot: throw an exception

18:58 clojurebot: http://paste.lisp.org/display/74305

19:27 hirak8: i'm trying to setup clojure within emacs, and get this error "rlwrap: Oops, crashed (caught SIGFPE)"

19:28 when i run C-c C-z

19:28 on a .clj file

19:28 has anyone seen this before?

19:28 i can't find anything online

19:39 anyone?

19:39 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

19:40 devn: clojurebot: bad form.

19:40 clojurebot: http://clojure.org/java_interop#toc46

19:40 devn: clojurebot just pulled a watson

19:40 hirak8: i have not seen that personally, what platform?

19:41 hirak8: OSX 10.6

19:41 devn: hirak8: let me see if i can reproduce

19:41 hirak8: i'm using a custom script that launches rlwrap to get a nice REPL

19:42 however inferior-mode still doesn't work even when i use the default script that comes with homebrew

19:42 perhaps i should try a straight java command line

19:42 devn: hirak8: whoa whoa -- why not use slime?

19:42 hirak8: i am trying to use slime

19:42 devn: i have rlwrap installed, but that's really not part of my slime setup

19:42 hirak8: i have to set 'inferior-lisp-program' to use slime, no?

19:42 devn: hirak8: ill gist my setup for you

19:42 hirak8: that's where i'm stuck

19:42 ok

19:43 are you on osx?

19:43 devn: hirak8: indeed

19:43 hirak8: k

19:43 are you using emacs starter kit?

19:43 devn: i built my setup out of that sort of, yes

19:44 hirak8: https://gist.github.com/900931

19:44 it's kind of messy because i've been adding to it here and there

19:44 but that should be enough to show you how to get your slime setup working

19:44 Derander: my experience with slime & clojure has been to install lein, type lein swank at the command line and then run m-x slime-connect

19:45 devn: hirak8: I do what Derander is saying

19:45 Derander: I've never heard of rlwrap though

19:45 devn: rlwrap is good if you want a better cmd line repl

19:45 but not necessary for slime

19:46 hirak8: my setup might just confuse you more

19:46 there are much smaller setups out there

19:47 hirak8: http://riddell.us/ClojureSwankLeiningenWithEmacsOnLinux.html

19:47 scroll down to "Configure Emacs"

19:47 that's really all you need

19:48 actually, you dont even need that if you're using elpa

19:49 M-x package-list-packages, get slime, slime-repl, clojure-mode by typing 'i' at the beginning of the lines in the package dialog where you want to install, then type 'x' to execute the installation

19:49 hirak8: why do you say that?

19:49 yes, i've been using ELPA

19:49 i thought i had to configure the 'inferior-lisp-program' variable in order to get it all to work

19:50 without using lein+swank

19:50 devn: you really just need a (require 'slime), (eval-after-load "slime" '(progn (slime-setup '(slime-repl)))), (require 'clojure-mode), and a (slime-setup)

19:51 hirak8: hmm

19:51 this is what i have installed via ELPA:

19:51 let me make a gist

19:52 https://gist.github.com/900937

19:52 alot of that came pre-installed due to emacs starter kit

19:54 was hoping to not have to use lein/swank right away, oh well

19:54 how do you evaluate code that's not part of a lein project?

19:55 TimMc: To get custom printing for my defrecords, all I should have to do is override print-method, yeah?

19:55 not-timmc: To get custom printing for my defrecords, all I should have to do is override print-method, yeah?

19:55 stupid netsplit

19:56 devn: not necessarily in that order

19:56 hirak8: sorry im not as much help as I had anticipated -- i havent mucked with my slime setup in a long time

19:56 d'oh

19:57 hirak8: devn: do you only edit code that lives in a lein project?

19:57 devn: hirak8: uninstall swank-clojure

19:57 that is deprecated IIRC

19:57 hirak8: good to know

19:58 TimMc: devn: I wish they would remove deprecated stuff.

19:58 devn: i use marmalade

19:58 TimMc: Or at least release a modification that warns you.

19:58 devn: it's not in my list anymore

19:58 hirak8: marmalade = different package repo?

19:59 devn: yes

19:59 you need a diff version of package.el

20:04 hirak8: sorry you're having so much trouble

20:04 hirak8: me too!

20:04 even setting inferior-lisp-program to a raw command line instead of a shell script (java -cp /usr/local/Cellar/clojure-contrib/1.2.0/clojure-contrib.jar:/usr/local/Cellar/clojure/1.2.0/clojure.jar clojure.main) didn't cut it

20:04 when i run C-c C-z it loads the repl file

20:05 but when I run C-c C-e on an sexp, i get some error message

20:05 it's bizarre

20:05 i'm just following the instructions on the clojure wiki

20:05 http://dev.clojure.org/display/doc/Getting+Started+with+Emacs

20:07 devn: hirak8: http://marmalade-repo.org

20:07 mreynolds: Newb question : I'm trying to write a server that communicates using DataOutput/InputStream. I got tired of writing (doto OutputStream (.writeInt 1) (....)), so I figured I'd use multimethods. I (defmutli write (fn [stream item] (class item)) and then impl'd the underlying types. Works great till I get to collections, which I tried to switch on "ISeq", but that didn't work. Is this dumb? Are there better ways to do this?

20:07 Otherwise, what class should I use for Seqs so I can (doseq...) them

20:07 http://pastebin.com/wfLD82f2

20:08 hirak8: devn: thanks. so is this for packages that don't exist at all on ELPA?

20:08 devn: hirak8: it's a better maintained package repo

20:08 hirak8: devn: or for updates to existing packages that aren't on ELPA yet

20:08 ok

20:08 devn: both

20:08 hirak8: k

20:09 cool

20:09 well, after reading the help docs again i think i may have figured it out

20:09 devn: hirak8: dont set inferior lisp program -- clojure-mode with slime-repl should be enough

20:09 hirak8: hmm

20:09 devn: hirak8: cool

20:09 hirak8: well, it looks like you have to launch a lisp process with C-c C-z.

20:10 then you can send commands to it using C-x C-e

20:10 but you have to switch to the *inferior-lisp* buffer to see results

20:10 which is kind of odd

20:10 devn: that's kind of a non-standard setup hirak8

20:10 hirak8: it's the setup that's listed here: http://dev.clojure.org/display/doc/Getting+Started+with+Emacs

20:10 which you would think would be *the* standard setup

20:11 i'll setup lein+swank eventually

20:11 if you just use clojure-mode+slime-repl, how does emacs know how to execute clojure?

20:11 like, how does it know what command to run?

20:11 do you need to add the clojure.jar to CLASSPATH and it takes care of everythign else?

20:12 devn: lein swank takes care of the classpath

20:12 you just need to connect to that instance by having [swank-clojure "1.3.0-SNAPSHOT"] in your :dev-dependencies

20:12 hirak8: yes

20:12 devn: lein deps, lein swank

20:12 hirak8: not using lein yet

20:12 will be

20:12 devn: M-x slime-connect

20:34 hirak8: devn: have lein+swank+slime working now tooo

20:36 err, i thought i did

20:36 C-x C-e is broken again :\

20:41 fixed

20:41 god that was a lot of work :)

20:41 but now i can hack clojure!

22:49 MiggyX: hi

22:49 brehaut: MiggyX: hello

22:50 MiggyX: brehaut: do people answer programming related questions here or is it just general clojure discussion? :)

22:50 brehaut: both

22:51 MiggyX: brehaut: Well I've just started using closure, so I'm still getting up to speed. I have a CSV file that I need to process. Each line is self contained and can be processed individually. I'm trying to have each line processed in parallel to make good use of the number of cores on this both (16)

22:52 * amalloy wonders what clojure discussions could possibly be unrelated to programming

22:52 brehaut: MiggyX: clojure or closure?

22:52 MiggyX: but not having a great deal of luck. I've tried a few things with the latest (just seeing if it would work) - (fmap println (read-lines "foo"))

22:53 brehaut: MiggyX: fmap is a bunch slower than map

22:53 MiggyX: brehaut: apologies I meant clojure, hands are on auto pilot :)

22:53 brehaut: no worries, just making sure we are on the same page

22:53 MiggyX: brehaut: I've tried map and pmap - pmap was what I thought i needed

22:54 brehaut: pmap is the obvious first choice, your snippet above has fmap though, which is different again

22:54 the effectiveness of pmap in speeding things up is directly proportional to the cost of each mapping operation though

22:54 MiggyX: this particular file just has two lines of text in it. It prints those out, sits there for a minute and then quits. When I try it on a large file, nothing gets printed, cpu usage is minimal and again after a minute or so it quits

22:54 so I figure I'm doing something obviously wrong

22:55 brehaut: can you paste your program up in a gist or something

22:56 MiggyX: http://www.pastie.org/1752839

22:56 all i wanted it to do was print each line :)

22:56 brehaut: MiggyX: first up, lazy seqs and side effecting code are a fun mix

22:57 you need to force the realization and evaluation of the whole sequence

22:57 (doc doall)

22:57 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

22:57 brehaut: (doc dorun)

22:57 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. dorun can be used to force any effects. Walks through the successive nexts of the seq, does not retain the head and returns nil."

22:58 brehaut: what version of clojure are you using BTW?

22:58 MiggyX: 1.2.0

23:08 hmm, doseq looks more like what I need. The CSV file is massive, I can't load it all into ram at once

23:08 seems processing each line in parallel is a lot harder than I thought it would be

23:09 brehaut: MiggyX: so pmap runs the mapped operation on seperate threads, and by default those threads dont have their std outs bound to the repl console

23:09 MiggyX: i use cljr for my messing about repl and when i pmap println over something it all spews out in the console that i opened cljr from

23:09 MiggyX: but approximately the snippet you provided runs fine for me over /usr/share/dict/words

23:11 malkomalko: anybody know any good clojure/emacs/slime/swank posts? I'm having some problems getting up and running

23:11 keeps complaining about undefined namespace when I try running some code after a slime-connect

23:12 brehaut: malkomalko:have you followed the readme in swank-clojure; most of the blog posts and articles in teh wild are out of date

23:13 * brehaut speaks hypothetically here as he has never used swank

23:14 amalloy: malkomalko: slime-connect doesn't automatically load any code

23:14 malkomalko: I have, but I'm having problems when trying to excecute code

23:14 ahh

23:14 amalloy: the first step after connecting, for me, is usually C-c C-k in the file i want to load

23:14 that spews the whole file and all its dependencies into the repl

23:15 after that, you can use C-x C-e or C-c C-c to load individual forms, or C-c C-k for another wholesale import

23:16 malkomalko: ok cool, that helps a lot

23:16 amalloy: other handy ones to know are C-c M-p (set repl to namespace of active buffer) and C-c C-d C-d (documentation for symbol at point)

23:17 MiggyX: brehaut, hmm that might well be it. I would have still expected to see CPU usage though even if it wasn't printing anything, maybe it's too small to be picked up.

23:17 brehaut, now to find out how to bind stdout for each threa

23:17 thread

23:17 brehaut: MiggyX: until you start doing heavy computation on that, i would expect it to be IO bound

23:18 MiggyX: brehaut: would explain why it justs there for a bit

23:19 malkomalko: thanks amalloy... any other useful emacs plugins or tips/workflows?

23:20 amalloy: malkomalko: emacs in general, or slime/swank in particular?

23:21 malkomalko: just specifically for clojure development with emacs

23:21 been doing a lot of research, but there seems to be a lot of out of date information

23:21 amalloy: malkomalko: install paredit mode if you haven't already, and then learn some of the most-common commands

23:23 my favorites are M-<UP>, C-<RIGHT>, M-(, and occasionally C-}

23:24 malkomalko: are those paredit specific shortcuts?

23:24 amalloy: yes

23:24 malkomalko: alright cool, I'll go dig into that, thanks for the heads up again, been very helpful

23:24 amalloy: enjoy

23:24 malkomalko: and then so after you make changes to a file, you'll want to reload that correct?

23:26 amalloy: yeah

23:33 MiggyX: can anyone provide an example of how to bind *out* in a thread? i.e. each thread needs to be able to write to stdout

23:34 brehaut: MiggyX: i question the sanity of doing that

23:36 MiggyX: brehaut: I agree, I'm just trying to see whether or not the reason the calculation etc aren't taking any cpu time is because I'm not actually doing anything with them

Logging service provided by n01se.net