#clojure log - Sep 01 2011

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

0:00 amalloy: gaze__: you don't really need to model state very often. ring, for example, is basically the only webserver anyone uses, and it's side-effect-free unless you introduce your own side effects

0:01 gaze__: so it's probably time to rethink my problem.

0:02 amalloy: gaze__: for example, ftp is a pretty interactive medium, but you can describe what you want to do "all in one go" before you connect

0:03 (-> "myserver.com" (connect) (commands [:cd "/tmp"] [:ls (fn [filenames] (doseq [n filenames] (println n)))])

0:04 solussd: what is the reason (google didn't help me here) that (meta my-macro) doesn't work, but (meta #'my-macro) does?

0:04 ,(meta cond)

0:04 clojurebot: #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/cond, compiling:(NO_SOURCE_PATH:0)>

0:04 solussd: ,(meta #'cond)

0:04 clojurebot: {:macro true, :ns #<Namespace clojure.core>, :name cond, :arglists ([& clauses]), :added "1.0", ...}

0:04 srid: amalloy: this doesn't overflow http://dpaste.com/606448/

0:05 amalloy: &(meta first)

0:05 lazybot: ⇒ {:line 53}

0:05 amalloy: &(meta #'first)

0:05 lazybot: ⇒ {:ns #<Namespace clojure.core>, :name first, :file "clojure/core.clj", :line 48, :arglists ([coll]), :doc "Returns the first item in the collection. Calls seq on its\n argument. If coll is nil, returns nil.", :added "1.0"}

0:06 srid: but that looks ugly; thinking ...

0:06 amalloy: srid: right. now that you've written it in a correct and fast way, consider ##(into () (range 5))

0:06 lazybot: ⇒ (4 3 2 1 0)

0:07 srid: interesting, but doesn't work with vectors ##(into () (vec (range 5)))

0:07 lazybot: ⇒ (4 3 2 1 0)

0:07 srid: what

0:08 amalloy: gaze__: you see what i mean? instead of modeling state at the API level and making the user deal with it, you have them pass "continuation/response" functions for commands that they might need to decide what to do after

0:08 gaze__: yeah, that does make sense.

0:08 srid: ##(into [] (range 5))

0:08 lazybot: ⇒ [0 1 2 3 4]

0:09 srid: amalloy: ok, though I was doing the recursion exercise from http://www.cis.upenn.edu/~matuszek/cis554-2010/Assignments/clojure-01-exercises.html

0:09 amalloy: you're still left with the problem of how to manage state, but it's hidden from the user and you can work it out in whatever ugly way you like

0:09 srid: which is why i made you fix it before i gave you the easy answer :)

0:09 srid: that's good then

0:12 amalloy: now i compresed it down to http://dpaste.com/606454/ and I feel good about myself

0:12 amalloy: srid: now compress it some more, using loop instead of multiple arities

0:13 solussd: amalloy: so what's the {:line 53} output?

0:14 amalloy: solussd: how much do you understand about vars and metadata?

0:15 srid: amalloy: http://dpaste.com/606456/ - i like the multiple arities version, though.

0:16 solussd: vars hold references to objects and metadata is data about a var? I know both clojure books I read gloss over vars as if it isn't an important topic. :/

0:17 amalloy: vars are important, but you're not really wrong about them

0:17 what you're wrong about is metadata: metadata is data about an object

0:17 &(map class [#'first first])

0:17 lazybot: ⇒ (clojure.lang.Var clojure.core$first)

0:17 solussd: attached to the var though, right?

0:18 amalloy: solussd: *shrug* metadata can be attached to anything

0:18 which is why (meta first) returns one thing, and (meta #'first) returns another

0:18 they both have metadata; what you get depends on who you ask

0:19 the data created by defn is attached to the var, not the function

0:19 solussd: ok. so why is there metadata for a var referencing a macro, but not the symbol for the macro itself (I know that is the wrong way to say that)

0:20 amalloy: the macro itself is not a thing. it is not an object; it only exists in the sense that when the compiler sees its name it goes and looks up some code

0:20 solussd: that makes sense- and defmacro adds metadata to the var then?

0:21 so, why does (meta myfunction) work?

0:21 amalloy: because functions *are* things, *are* objects

0:21 &(let [x map] (x inc [1 2 3]))

0:21 lazybot: ⇒ (2 3 4)

0:21 amalloy: &(let [x and] (x inc [1 2 3]))

0:21 lazybot: java.lang.Exception: Can't take value of a macro: #'clojure.core/and

0:22 amalloy: (meta some-fn) only "works" in the sense that there's no error. you still don't get the docstring

0:23 solussd: does fn add metadata to the object it creates?

0:24 amalloy: try it and see

0:24 solussd: yes. :D

0:25 amalloy: not much, though, right? ##(meta (fn []))

0:25 lazybot: ⇒ nil

0:26 solussd: ok. var re-cap. A var can reference an object. A symbol can name a var. When a symbol is resolved you get the value of the var it refers to. #'something returns the var that the symbol something refers to.

0:27 amalloy: sounds good

0:27 solussd: guess you never worry about the distinction between a symbol and a var[iable] in, say, C, because you compile. :D

0:28 amalloy: nothing to do with having to compile

0:29 the reason you don't worry about the distinction is you don't have the power to introspect source code. symbols have no value for C programmers; what could you do with them?

0:30 solussd: that makes sense

0:30 srid: I bet there is no TCO version for flattening a list - http://dpaste.com/606461/

0:31 amalloy: srid: correct, that's impossible

0:31 solussd: I keep getting this feeling that lisp/clojure would have made a lot more sense early on had I never been exposed to C/C++/etc- that it would have been easier to learn too.

0:32 *(than c/c++)

0:32 amalloy: (except by implementing your own version of a stack, stored on the actual heap)

0:36 srid: seq can't be destructured in a loop?

0:36 n/m, i was using loop in place of recur

0:40 i'm close to implementing a TCO version of flatten, debugging a bug ...

0:43 amalloy: the bug that it's impossible? (though of course see my point about reimplementing the stack yourself)

0:45 srid: amalloy: http://dpaste.com/606486/

0:46 amalloy: srid: that's not what's generally meant by "flatten". what do you expect it to return for the input [a [b [c d]]]?

0:47 eg, compare to the flatten in clojure.core: ##(flatten '[a [b [c d]]])

0:47 lazybot: ⇒ (a b c d)

0:47 srid: same

0:48 I used list, instead of vec.

0:48 amalloy: try running it (with lists, not vec), works for me.

0:49 amalloy: hm

0:50 srid: an interesting exercise is to compare this with core.clj's tree-seq based implementation.

0:51 i'm not sure about the algo. complexity of `concat`. it returns a seq, so doesn't construct a new list. but still, wondering how efficient it (and its later lookups) are.

0:52 amalloy: i see. the stack is hidden inside of concat

0:52 srid: ah

0:58 amalloy: i can't figure out an input to break it, though, so i might be wrong

1:06 srid: i really need to understand more of how seq's work under the hood.

1:09 amalloy: srid: http://people.csail.mit.edu/meyer/6001/FT97/psets/ps9/ps9.ps seems to be all about implementing a tail-recursive flatten, and it does so with an explicit stack. i *think* this supports my claim that you need a stack, but i need to think more about it

1:10 either way you would probably find it interesting

1:10 srid: thanks

1:11 that link is down?

1:12 amalloy: it worked two minutes ago

1:12 and works for me now

1:13 srid: times out for me, always. i have access to the google cache, though.

1:13 * srid goes to bed

1:13 amalloy: weird. maybe your client can't...handle postscript files...? this sounds bizarre even as i say it

1:14 srid: connection to people.csail.mit.edu| times out. i'll try from work. ok, really off to bed.

1:16 amalloy: yes, lst is your stack of "items to be processed"

1:17 neat implementation, anyway

2:41 amcnamara: you around?

2:50 amcnamara: amalloy: yep

2:50 amalloy: amcnamara: i was just about to push a new version of 4clojure, and saw you've been making some changes. anything that you want to be pulled in?

2:51 amcnamara: I sent off a pull request ~30 minutes ago, I think you were copied on it... though I'm not too familiar with github's pull system.

2:52 amalloy: oh man, two pull requests in the last hour, apparently

2:52 i was CC'd, but it doesn't forward my notifications to my email. i wonder if i disabled that myself

2:52 amcnamara: ahh

2:52 amalloy: oh never mind. the other pull request was on some other project

2:53 if you're going to do much developing (sounds like you want to), you should join us in #4clojure

2:54 amcnamara: done, didn't know there was a channel

2:54 :)

2:54 yeah, I think 4clojure is great.

3:22 michaelr525: hello!

3:54 http://acooke.org/cute/Optimising1.html

3:54 Interesting stuff..

4:23 roger_: I want to create a string from a list containing two characters. I don't get what's wrong with (apply str (\a \b))

4:25 It gives the same casting error as (str (\a \b))

4:25 dbushenko: (\a \b) -- is a function

4:26 function \a with parameter \b

4:26 you should use (apply str \a \b)

4:27 sorry, (apply str [\a \b]) -- like that

4:28 roger_: OK, or use (apply str '(\a \b))

4:28 dbushenko: yep

4:28 roger_: Thanks!

4:30 dbushenko: np

4:36 amalloy: roger_: make sure you understand the difference between [a b] and '(a b) though

4:36 because it's pretty important

4:37 roger_: but: (= [\a \b] '(\a \b)) gives true?

4:37 amalloy: try it for something that's not a constant

4:37 &(let [a 1, b 2] {:quoted '(a b) :unquoted [a b]})

4:37 lazybot: ⇒ {:quoted (a b), :unquoted [1 2]}

4:40 roger_: amalloy: euh, I'm just reading chapter 2 of 'programming clojure', I'm not yet familiar with let and &.

4:41 amalloy: well, & is just to get lazybot to sit up and take notice

4:41 consider this instead

4:41 ,'((+ 1 2) 3)

4:41 clojurebot: ((+ 1 2) 3)

4:42 amalloy: ,[(+ 1 2) 3]

4:42 clojurebot: [3 3]

4:42 roger_: what's the difference between clojurebot and lazybot?

4:43 &'((+1 2) 3)

4:43 lazybot: ⇒ ((1 2) 3)

4:43 amalloy: not much. i just hoped you'd find , less distracting than &

4:43 roger_: &'((+1 2) 3)

4:43 lazybot: ⇒ ((1 2) 3)

4:44 amalloy: whoa, that doesn't look right at all. is that a bug in lazybot?

4:44 roger_: &[(+ 1 2) 3]

4:44 lazybot: ⇒ [3 3]

4:44 amalloy: &'+1

4:44 lazybot: ⇒ 1

4:45 amalloy: &(read-string "+1")

4:45 lazybot: ⇒ 1

4:45 amalloy: &(read-string "(+1)")

4:45 lazybot: ⇒ (1)

4:45 amalloy: ,(read-string "(+1)")

4:45 clojurebot: (1)

4:45 amalloy: ,+1

4:45 clojurebot: 1

4:45 amalloy: ,'(+1)

4:45 clojurebot: (1)

4:45 amalloy: why on earth isn't +1 a valid symbol?

4:46 at any rate, roger_, you should be putting a space between + and 1

4:46 but i'm surprised it broke in this particular way, instead of a different way

4:48 roger_: oh right, I was trying to type to quickly

4:49 I like the => in lazybot's answer better

4:50 amalloy: $mail Raynes someone likes the arrow!

4:50 lazybot: Message saved.

4:51 amalloy: ,'a1

4:51 clojurebot: a1

4:51 michaelr525: what's the difference between ,( and &(?

4:52 ,1

4:52 clojurebot: 1

4:52 michaelr525: &1

4:52 lazybot: ⇒ 1

4:52 michaelr525: except the arrow :)

4:52 Fossi: it's two bots

4:52 they can do different things

4:52 michaelr525: ah, right

4:52 Fossi: although for & and , they are mostly the same

4:53 michaelr525: ah

4:53 raek: ,(println "&(+ 1 2)")

4:53 clojurebot: &(+ 1 2)

4:53 lazybot: ⇒ 3

4:53 raek: ouch.

4:53 Fossi: don't know if they use the same sandbox though

4:53 michaelr525: hehe

4:53 Fossi: lol

4:53 michaelr525: think of the possibilities

4:54 Fossi: you can't make one of them spam, but both :D

4:54 michaelr525: hmm, maybe someone can add a spell checker to one of the bots?

4:54 raek: $mail Raynes lazybot shoould probablly ignore clojurebot to avoid bot feedback loops

4:54 lazybot: Message saved.

4:54 amalloy: raek: i dare you

4:55 clojurebot can't hear lazybot because of lazybot's ⇒

4:55 (which afaik is the only reason ⇒ is there)

4:55 raek: yup.

4:55 michaelr525: too bad, it could have been funny

4:55 amalloy: raek: mind if i delete your $mail?

4:55 since that is in fact not needed

4:55 raek: amalloy: sure

4:55 amalloy: $login

4:56 lazybot: You've been logged in.

4:56 raek: go ahead

4:56 amalloy: $unmail raek Raynes

4:56 lazybot: Deleted unread messages from raek to Raynes

4:56 amalloy: $logout

4:56 lazybot: You've been logged out.

4:56 amalloy: michaelr525: the person who can add a spell checker is YOU. though tbh i'm not really sure how you would use it?

5:02 michaelr525: https://github.com/flatland/lazybot/wiki/Plugin-quick-start-guide if you're interested in contributing

5:07 michaelr525: sure, I'm interested, I just have to put my work and family adside for a while ;)

5:08 amalloy: okay, i was about to go to bed but i realized "+1" is just the number one with a "positive" sign in front. that's why they're parsing as 1

5:09 so eg ##'-+1 will parse just fine as a symbol

5:09 lazybot: ⇒ -+1

5:09 amalloy: night

5:09 roger_: and dream on!

5:16 michaelr525: It's noon here

5:16 Although a nap would be just fine :)

5:43 wunki: someone willing to help me out with the following compojure route: https://gist.github.com/7a23e06ad21d43710701

5:43 shouldn't in the above code, the `user` parameter get populated with the `user` from the request map?

5:56 rata_: hi

5:56 in enlive, how do you select a td tag that doesn't have a child a tag?

6:15 I did it! =)

6:17 dbushenko: wunki, probably -- no

6:18 you have to add :user to the route

6:21 nizze: Hi!°

6:21 I was reading about defmulti and defmethod and I already know about pattern matching

6:22 What is the real difference between multiple dispatch and pattern matching

6:22 ?

6:26 thorwil: nizze: i guess it's free-form do it all yourself vs having a decision tree written for you

6:27 nizze: So multiple dispatch is superset of pattern matching?

6:28 thorwil: i think they are orthogonal

6:32 nizze: Thanks!!

6:35 thorwil: nizze: looking at the examples at https://github.com/swannodette/match might give you a better idea of what pattern matching is

6:36 (elsewhere you would have to deal with the syntax of languages like erlang or haskell)

6:51 wunki: dbushenko: but I have the signed in user in the request map, I really need it from there.

7:34 khaliG: man Joy of Clojure is one disappointing book so far.. i've halfway through have learnt nothing, except perhaps boredom

7:35 dbushenko: khaliG, You've started with the wrong book

7:35 JoC is an excellent book for advanced clojure programmers

7:35 it's not for beginners

7:35 khaliG: dbushenko, and i've yet to come across anything advanced

7:36 seems a waste of 150 pages when it hasnt got hard yet??

7:36 lazybot: khaliG: Definitely not.

7:36 dbushenko: JoC discovers many subtle thins which you'll not find in any clojure book

7:37 khaliG: dbushenko, hmmm. hopefully the latter half is more interesting :/

7:37 dbushenko: where did you stop?

7:38 khaliG: i'd have to check the bookmark, haven't got it handy

7:40 dbushenko, but to be fair i should finish it first :)

7:40 dbushenko: to my personal mind, Practical Clojure and Clojure in Action -- are the books to start

7:41 Joy of Clojure is good when you want to extend your knowledge on the topics which you already know

8:52 gtrak`: what's the best idiom for mocking stuff with 1.3's dynamic var change? It seems dirty to change the source code for the sake of the tests... akin to having fields/methods be protected when they should really be private

8:53 chouser: gtrak`: with-redefs

8:54 gtrak`: oh, wow

8:54 how's that different from binding?

8:54 in 1.2?

8:55 chouser: with-redefs changes the root binding, so the new value is visible in all threads

8:56 which is (a) better for tests because it worths with things like pmap where binding didn't and (b) doesn't require the var be dynamic.

8:57 gtrak`: well that's better overall, I'm surprised all the places i've read that talk about vars requiring dynamic don't mention it

8:57 chouser: khaliG: Sorry you're disappointed with the book. How long have you been using Clojure? Do you have background in other Lisps or functional languages?

8:58 gtrak`: JoC p. 299 :-)

8:59 gtrak`: oh :-)

8:59 I've read the var chapter, it wasn't in there :-)

9:00 chouser: ah. Actually, with-redefs didn't exist when we were wrote the Var chapter.

9:00 It didn't exist when we wrote the testing chapter either, so we wrote it for the book and then Clojure 1.3 took it as well.

9:02 khaliG: chouser, I spoke too soon, i'll give more useful feedback once i've finished reading. To answer your question, I've got about 2-3 months of experience writing clojure and i'm coming from a CL background

9:03 chouser: khaliG: Hey, if you can't speak your mind on IRC, then what's it good for? :-)

9:05 khaliG: If you haven't dug very deepling into persistent collections yet, I could hope chapters 5 and 6 and perhaps 10 and 11 might have some useful bits for you.

9:05 s/deepling/deeply/

9:09 gtrak`: always impressed by how pliant the core language constructs are, lisp is cool

9:16 khaliG: chouser, excellent :)

10:07 rindolf: Hi all.

10:07 joly: hello

10:08 rindolf: When I run the program in http://clojure.roboloco.net/?p=703 it prints the "Elapsed time" thingy and then takes a lot of time to exit. htop shows that it has several threads running on 0% CPU. I'm on Mageia Linux 2 (CAuldron). Why does it happen?

10:09 joly: hi.

10:09 manutter: rindolf: do you need to call shutdown-agents or something?

10:09 rindolf: manutter: don't know.

10:10 manutter: I remember hearing something about that, but I don't recall the exact details

10:11 rindolf: manutter: yes, now it exits immediately after printing the elapsed time.

10:11 manutter: :)

11:04 tsdh: Can someone explain me this compile error? http://pastebin.com/cKzGwcg5

11:07 The protocol defines exactly those methods, and I've already extended it to some java types before. For that record, I simply want to delegate the resolving stuff to the graph (one of those java types).

11:18 hugod: tsdh: I think you have to specify each overload as a separate sexpr

11:20 tsdh: hugod: Really? It would be strange if the syntax varies between `extend-protocol', `extend-type', and `defrecord', but I'll try it...

11:22 hugod: You are right.

11:24 hugod: tsdh: it is also assymetric with the defprotocol syntax - I always end up getting the syntax wrong for this

11:24 Mike|home: So here's what gets me about Clojure. I still don't get how abstractions are built. Yeah, namespaces are cool, but objects just feel so -right-, you know? Is it normal to think like that or am I just being whiny?

11:25 HET2: Mike|home: objects are not so much about abstraction as they are about encapsulation

11:25 Raynes: It's normal at first. You don't 'get it' immediately.

11:25 At least, not if you're human.

11:26 I got it immediately because I'm a robot.

11:26 Mike|home: I think I disagree HET2. I think they're useful for both.

11:26 tsdh: hugod: Well, once you know it...

11:26 HET2: Mike|home: that's not my opinion, it's Alan Kay's opinion, the guy who invented the OOP paradigm

11:26 Mike|home: Hm.

11:26 HET2: Mike|home: classes are all well and good but OOP is about objects not so much about types

11:27 Mike|home: I guess I disagree with the big man, then.

11:27 That makes sense, yeah.

11:27 HET2: Mike|home: in fact I have been finding that thinking about types when you program is usually less flexible than ignoring them

11:27 Mike|home: So then what's Clojure's take on building abstractions and encapsulating data, HET2?

11:27 chouser: Mike|home: "objects" in OOP are a giant bundle of features that turn out to be essentially unrelated to each other.

11:28 HET2: Mike|home: that said, nothing keeps you from using OO in a lisp

11:28 Mike|home: chouser: That sounds a bit biased. That's bad OOP programming

11:28 chouser: Clojure provides most of those features unbundled from each other so you can take what you need.

11:28 raek: encapsulation can be obtained by functions closing over locals

11:28 Mike|home: I think good objects are clean cut, short sections of the domain languages

11:28 Language, rather*

11:28 HET2: raek: yeah but then you end up with #(lambda) that you know nothing about

11:28 Mike|home: raek: That's really interesting. I never thought of it like that.

11:29 chouser: What are some of those features?

11:29 HET2: Mike|home: thats the whole point of lisp dialects ;)

11:29 Mike|home: Haha, okay.

11:29 Pretty new to Lisp, so yeah excuse the lack of uh.. Lisp culture.

11:29 HET2: hence naming Clojure Clojure I suppose...

11:29 Mike|home: of course my opinion is worth exactly what you pay for it

11:30 chouser: Mike|home: the features are hard to name, but I'll try. again. :-) ...

11:30 raek: (defn make-counter [init] (let [state (atom (dec init))] (fn [] (swap! state inc))))

11:30 gtrak`: Mike|home, http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html

11:31 Mike|home: gtrak: I think I read this a long time ago..

11:31 HET2: raek: eeek ! modifiers

11:31 Mike|home: I think its time to read it again. Haha.

11:31 gtrak`: it's pretty awesome :-)

11:32 HET2: Mike|home: of course when you insist on explicitly modifying state you loose the parallelizability benefits that functional programming gives you

11:32 Mike|home: I don't think that having a nice construct for encapsulation and abstraction implies mutability.

11:32 raek: HET2: a name ending in ! usually means that the function has a side-effect that will not be controlled by the transaction system

11:33 (but not all these functions have a name ending in !)

11:33 coopernurse: hey folks. we've been having a discussion about session implementations on the clj-noir group.

11:33 gtrak`: Mike|home, of course it implies mutability, what else would be encapsulated? if it's not mutable, then a static function is just as good

11:33 chouser: In OOP an object is how you do: a single function, a group of related data (a value), a group of related functions, inheritence, data hiding (encapsulation), an identity (container for mutable data), etc.

11:33 HET2: Mike|home: the very essence of objects as in object orientation is that you encapsulate mutable data

11:33 coopernurse: seems like ring doesn't have a built in session store that uses the HttpSession, which is sort of what you'd want in any sort of clustered environment (e.g. GAE or a cluster of tomcat/weblogic servers)

11:33 so I wrote one here. comments welcome.. I may issue a pull request to the ring project for this. https://github.com/coopernurse/votenoir/blob/master/src/votenoir/httpsession.clj

11:34 chouser: Mike|home: Clojure provides every one of those things, but discretely so that when you see a thing, you can tell what it's being used for.

11:34 Mike|home: chouser: Sounds like you're hinting at language features. Where can I find them?

11:34 chouser: In Clojure a single function is just that, no need for an object instance around it.

11:34 Mike|home: Right.

11:35 chouser: A group of related data can be a map, vector, set, record instance, or type instance.

11:35 Mike|home: gtrak`: Always seemed to me that an object, even if its immutable, is still good because you can package data with its respective functions.

11:35 HET2: Mike|home: not a language feature

11:35 coopernurse: gtrak`: thanks for the link, that Yegge post is interesting

11:35 chouser: a group of related functions can be a namespace or a protocol.

11:35 Mike|home: Hah, HET2, well now I'm very confused. :)

11:35 HET2: Mike|home: the language itself is quite slim in lisp dialects

11:36 Mike|home: because the language is flexible, paradigms are implemented ontop of it

11:36 Mike|home: Makes sense so far, chouser.

11:36 chouser: inheritence can be done with multimethods or protocols

11:36 Mike|home: Are multimethods like multiple arity?

11:36 chouser: data hiding can be done with private vars in a namespace, or closed-over values in a function

11:36 identity is done with refs, atoms, agents, or dynamic vars

11:36 Mike|home: Okay, still sounds pretty sane.

11:37 HET2: Mike|home: maybe you should have a look at SICP and/or brian harvey's CS61A lectures on youtube

11:37 joly: multimethods allow multiple dispatch, and even arbitrary dispatch

11:37 HET2: Mike|home: it's scheme but a lot of what he teaches holds for any lisp

11:37 raek: Mike|home: methods in OOP let you do different things depending on the type of the object, multimethods let you do different things depending on any property (type, value or anything) of any of the parameters

11:37 Mike|home: HET2, obviously I'd get something out of it. But what do you think that I'm just 'not getting'?

11:38 If that made sense, heh

11:38 HET2: Mike|home: closures ;)

11:38 chouser: So for each of these categories, Clojure provides more than one option with various tradeoffs. It provides a vocabulary for thinking about design problems that's not really possible when you lump all of those categories into a single idea of "an object"

11:38 Mike|home: HET2: Got'cha :)

11:38 HET2: Mike|home: in most oop languages they are treated as a bastard child

11:38 Mike|home: I guess I understand what they -are-, but now how they're used in the wild.

11:38 gtrak`: very little of all this stuff is actually a language feature though, it's built on top of functions, macros, etc...

11:39 HET2: Mike|home: the idea is that you treat functions as data and vice versa

11:39 Mike|home: This is all very interesting

11:39 HET2: Yeah, I understand that.

11:39 HET2: Mike|home: well that's the core difference between lisp and c ;)

11:39 gtrak`: functions are just objects after all

11:39 Mike|home: Objects without data?

11:39 gtrak`: they can have data

11:40 think of a beefed up anonymous inner class

11:40 Mike|home: Passed as parameters only though, right? Unless its a closure

11:40 HET2: Mike|home: C++ and java are just not very object oriented. have y ou done any smalltalk?

11:40 gtrak`: yes

11:40 Mike|home: I haven't, HET2.

11:41 HET2: Mike|home: in an OOP language theoretically everything is an object. the number 1, a method and an object which has a state and selectors are all objects

11:41 Mike|home: in c++/java that radicality has been abandoned for performance or so they say

11:41 chouser: the content of this conversation is actually why we wrote JoC -- to comrehensively answer the question "so what?"

11:41 Mike|home: HET2: Yeah, I've heard that too

11:41 HET2: chouser: would you mind expanding JoC

11:41 Mike|home: What's JoC?

11:41 joly: "Actually I made up the term 'object-oriented', and I can tell you I did not have C++ in mind." -- Alan Kay

11:42 HET2: joly: ;)

11:42 gtrak`: smalltalk is about message-passing, which implies late-binding

11:42 HET2: gtrak`: one could argue OOP is about message passing and late-binding

11:42 raek: JoC = Joy of Clojure, chouser's and fogus's book

11:42 joly: The Joy of Clojure, a wonderful book I'd highly recommend

11:43 HET2: joly: thx

11:43 gtrak`: HET2, but also the polymorphism is limited in java/C++

11:43 in clojure you can dispatch based on any function of the arguments, instead of just the type of the first

11:44 HET2: gtrak`: further up in your chat buffer i argued against type systems ;)

11:44 Mike|home: I'll check it out :)

11:44 HET2: gtrak`: or at least ones that are part of the language

11:44 gtrak`: types are just strings, a virtual lookup is just a hash lookup

11:45 HET2: gtrak`: the use for types in java/c++ is to enforce discipline and to allow optimization

11:45 gtrak`: which makes the language less flexible and more verbose imho

11:45 gtrak`: agreed

11:45 I learned C, C++, java, clojure in that order

11:47 HET2, the jit is plenty fast, and you can still get the performance in clojure with records and protocols

11:47 but you don't have to enforce it on people

11:48 zippy314: ,(+ 1 1)

11:48 clojurebot: 2

11:49 gtrak`: in java you'd have to pay for doing something unconventional by writing a lot more code

11:54 zippy31415: ,(+

11:55 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

11:55 zippy31415: ,(+ 2 3)

11:55 clojurebot: 5

12:37 icey: For those of you deploying websites built in Clojure: how do you profile your applications?

12:38 coopernurse: icey: I haven't done any hard core profiling yet. what level of detail are you looking for? like which URLs are slow, or low level profiling metrics about function execution times?

12:39 arohner: icey: I use visualvm

12:39 it's not amazing, but it's free and works well enough

12:39 icey: coopernurse: Right now I'm mostly concerned with the first issue - just knowing what my general execution times for a url look like

12:39 arohner: checking it out now, thanks

12:40 arohner: icey: for URL execution times, I'd just use (time) in a middleware

12:40 icey: arohner: Is it pretty straightforward to translate what visualvm reports to specific locations in your code?

12:40 coopernurse: arohner: that's a good suggestion.

12:41 what I've also done in the past is put my java app server behind nginx, and configured nginx to log request times in the access log (apache can do something similar)

12:41 arohner: icey: yes

12:41 clojurebot: Titim gan éirí ort.

12:41 arohner: I use the sampler, which gives slightly less accurate results, but doesn't take 5 minutes to recompile everything

12:41 Raynes: clojurebot = multilingualbot

12:42 icey: let's say you discover a route that performs strangely; 80% of the time it's fast, but sometimes it really bogs down. What are the troubleshooting / tracing steps you take - attach visualvm to the production JVM you're running and watch for the hiccups?

12:42 (sorry, i'm new to the jvm ecosystem; so i don't have any java background to transfer over :|)

12:43 arohner: I haven't seen much of that (non-determinism), but yeah, I'd start with visualvm

12:43 it has a monitor to tell you how much CPU time is spent, how much time GC'ing

12:44 it's not very good at telling you the individual times for each URL hit

12:44 what kind of performance hit are you seeing?

12:44 icey: arohner: I just picked a random scenario. To be honest, my biggest concern is doing something suboptimal when I write code since I'm new to Clojure, and I'd like to be able to profile everything to make sure I'm not shooting myself in the foot :)

12:45 arohner: the hardest part about profiling is knowing what the results *should* look like

12:46 Is 1M ops/second fast? I don't know, unless I've seen it do 5M ops/second before

12:47 icey: arohner: that's a pretty good point. i have a habit of trying to measure everything to get a feel for how things ought to look. it may not be a good habit, but its' been informative for me in the past

12:47 arohner: icey: it's certainly better to measure than to not measure :-)

12:48 icey: i don't have a formal cs background, so i end up learning things as i need them... but first i have to discover that i need them :)

12:48 coopernurse: icey: if you're using mysql, the slow query log is very useful

13:25 gtrak`: icey, write clean idiomatic code, then measure, then make it faster as neede

13:55 TimMc: Hey, I just thought of a possibly good reason for macros to not be pure functions.

13:56 What if you had a logging or assertion macro that checked a configuration file to see whether it should drop in the relevant calls?

13:57 amalloy: TimMc: that's how clojure.core/assert works

13:57 (it checks a var binding, not a file)

13:57 TimMc: nice

14:08 S11001001: if you make all your functions return sequences and wrap their bodies with lazy-seq, they'll all return really fast :)

14:10 TimMc: S11001001: Look how fast I can create an infinitely long data structure! ##(time (range))

14:10 lazybot: Execution Timed Out!

14:10 TimMc: Oh bother, it's trying to print it.

14:10 ##(= (time (range)))

14:10 lazybot: ⇒ "Elapsed time: 0.489627 msecs" true

14:13 S11001001: impressive speed

14:13 which would put clojure's infinite loop time faster than Linux's

14:14 TimMc: Linux's?

14:14 phenom_: ,(take 10 (range 1 1000))

14:14 clojurebot: (1 2 3 4 5 ...)

14:14 S11001001: (5s, according to Torvalds)

14:15 phenom_: ,(take 2 (range))

14:15 clojurebot: (0 1)

14:15 phenom_: ,(doc time)

14:15 clojurebot: "([expr]); Evaluates expr and prints the time it took. Returns the value of expr."

14:15 phenom_: (time (+ 1 2))

14:15 amalloy: chouser: i read "Clojure provides every one of those things, but discretely" as "discreetly" the first time, and surprisingly it still made sense. "Hey, y'know, if you need X it's over here. Don't get all excited about it, people might be watching."

14:15 phenom_: ,(time (+ 1 2))

14:15 clojurebot: "Elapsed time: 0.085 msecs"

14:15 3

14:34 gtrak`: ,(time (+ 1 2))

14:34 clojurebot: "Elapsed time: 0.084 msecs"

14:34 gtrak`: ,(time (+ 1 2))

14:34 clojurebot: 3

14:34 "Elapsed time: 0.082 msecs"

14:34 3

14:34 gtrak`: keeps getting faster

14:34 manutter: practice makes perfect

14:35 Raynes: raek: That isn't really necessary. If a feedback loop is possible, I generally consider it a bug that needs to be fixed.

14:37 amalloy: damn it, Raynes, i $unmailed that. stupid lazybot, did you not delete it??

14:37 lazybot: amalloy: What are you, crazy? Of course not!

14:38 Raynes: amalloy: It certainly wasnt unmailified.

15:05 turbofail: is there any standard function for merging a set of sorted sequences?

15:06 wabash: A question that probably has been asked before: If I understand FP decently enough, how difficult/impossible is it (and/or is it a bad idea?) to take my codebase in Java, and transform certain parts to clojure?

15:06 already, in java, there are places I use more FP style stuff, like java's pseudo-closures, and recursion.

15:07 technomancy: turbofail: maybe into?

15:07 turbofail: since each sorted thing can have its own sort function you need to specify which to use

15:08 turbofail: they're not mappings, they're just sequences

15:08 amalloy: wabash: there exist libraries for functional programming in java, and you can do functional-oriented stuff without them, as you've noticed

15:08 wabash: Yes indeed.

15:08 amalloy: a lot of the benefits you don't get to keep, though, in a mutable-by-default setting

15:09 turbofail: like the input to the merge function of a merge sort

15:09 nizze: Hi! I'm learning clojure & compojure. My project has these listed as deps: clojure, contrib, compojure, lein-ring. When I do lein deps it's pulling huge amount of stuff.

15:09 amalloy: turbofail: it's pretty rare to want to do that outside of an actual mergesort

15:10 nizze: Most of which seems to be Java. Why?

15:10 amalloy: ring depends on it

15:10 or compojure does

15:10 wabash: amalloy: It's partly this: The codebase I have does stuff that may or may not be amenable to rewrite in clojure from scratch. I simply don't know because I don't know clojure that well. But certain parts of it map very nicely to FP paradigms, and I'm kinda shoehorning them into FP even though they are java.

15:10 technomancy: turbofail: (into (sorted-set-by #(mod % 12) [...]) (sorted-set-by even? [...])) ; is going to be different if you swap the order of the args

15:10 nizze: Yeah, that I inferred. But why do they have such a huge amount of deps?

15:10 wabash: amalloy: Are you saying this: if I mix clojure and java, the immutability of Clojure goes away?

15:11 amalloy: wabash: i think i answered a question you didn't ask

15:11 yes

15:11 wabash: :)

15:11 technomancy: turbofail: oh... never mind; I see what you mean

15:11 amalloy: nizze: 4clojure is a pretty simple website, and its lib/ directory has 50 jar files

15:11 technomancy: the seq has been sorted, not that the seq is inherently sorted

15:12 turbofail: yeah

15:12 coopernurse: nizze: yeah, welcome to java. lots of deps. thankfully we have tools to manage it

15:12 wabash: amalloy: So, if you have a pure clojure app, it's nice with immutable data objects, and everyone is happy. So if you decide then that you are going to use a java lib because it nicely and conveniently does exactly what you need purpose wise, and you add it and make calls, *all* of your clojure immutability goes away?

15:12 technomancy: turbofail: I don't think there's anything built-in for that apart from just (sort (concat a b)), which is not going to be fast

15:12 amalloy: no, it's not the case the the immutability goes away

15:12 nizze: In Ruby we, too, have deps. But not so much of them.

15:13 wabash: amalloy: oh, ok good.

15:13 amalloy: but you lose a lot of the *benefits* of immutability

15:13 like being able to reason about a function in isolation without worrying about some global state

15:13 nizze: Why compojure guys are using Java stuff and not coding those libs in Cojure?

15:13 arohner: turbofail: I don't think there's a built in fn, but it's fairly straightforward to write using loop & recur

15:13 nizze: composure is almost purely clojure, but it uses a java webserver

15:13 wabash: amalloy: So taking a pure clojure app, and adding a small part that uses a java lib, does not mess up the clojure part. However, that java part is suceptible to the typical failings of java?

15:13 amalloy: nizze: complain again when you've written an entire production-ready webserver yourself?

15:14 technomancy: turbofail: you could try (sort (interpose a b)); that'll probably be a bit faster but still naieve

15:14 turbofail: arohner: sure, just wanted to know if i was duplicating work or not

15:14 amalloy: heh, interpose. that would be funny. interleave makes a little more sense

15:14 technomancy: nizze: probably because that's really boring?

15:14 nizze: Okay.

15:14 technomancy: amalloy: hah; interleave is what I meant

15:14 turbofail: the only reason this came up was because of some silly problem that came up on programming praxis

15:15 amalloy: wabash: you can try. some issues will leak through

15:15 coopernurse: nizze: here's one cool thing though. you can do: lein ring war and it will generate a .war file that seals up your app+all deps

15:15 amalloy: but you can carefully wall them off

15:15 coopernurse: that you can deploy to any java servlet container (tomcat, jetty, weblogic, resin, etc). with no external dependencies

15:15 nizze: coopernurse: Oh, nice!

15:15 coopernurse: so that's the rationale behind the madness (in part)

15:15 nizze: Okay.

15:15 wabash: amalloy: Thank you so much.

15:16 nizze: Thanks for help :)

15:16 coopernurse: as opposed to the ruby/python world where you have to manage virtualenvs and make sure everything's installed

15:17 turbofail: 5/6ths of my answer to the problem was implementing the sequence merge

15:18 amalloy: turbofail: really? it's not a very long function, even to merge N sorted seqs

15:18 turbofail: the program was 12 lines of actual code

15:18 so basically there was two lines of other stuff, the rest was just the merge

15:22 nizze: Uhm now I got it. I see it installed Jetty, which in turn pulled in lots of other stuff

15:23 coopernurse: nizze: exactly. and most of that stuff are just dev dependencies.. so if you create a war it won't include them, as the servlet container you deploy to will have them already built in

15:25 nizze: and not to confuse you, but you might take a look at noir, which is a layer on top of compojure that provides a more full featured microframework for clojure. http://webnoir.org/

15:26 amalloy: turbofail: https://gist.github.com/1187034 for your entertainment

15:28 though for reasons i don't understand it looks like github is showing two copies of the file

15:29 hm, the code is also wrong. that 10 snuck in at the wrong end

15:29 oh right. the input seqs weren't sorted, haha

15:38 michaelr525: hello!

16:08 nizze: What is the preferred way to use clojure with vim?

16:09 michaelr525: Edit code..

16:19 coopernurse: question about underscores as input param names - are they special? it seems you can use them more than once

16:19 in the same param list

16:20 hiredman: ,((fn [a a a] a) 1 2 3)

16:20 clojurebot: 3

16:20 coopernurse: I see - so you can use the same name more than once in general

16:20 michaelr`: heyo!

16:21 hiredman: convetion says _ as an argument names you ignore it, but just a convention

16:21 clojurebot: ( is http://xkcd.com/859/

16:21 coopernurse: ok, great. thanks

16:23 TimMc: clojurebot: What triggered you there?

16:23 clojurebot: Excuse me?

16:24 amalloy: TimMc: he likes to jump in at random on occasion

16:24 TimMc: coopernurse: _ is syntactic in some other languages, though

16:24 amalloy: (true; not joke)

16:24 TimMc: amalloy: I know that it will take 1 in n msgs as directly-addressed.

16:25 amalloy: what made him come up with that particular answer is anyone's guess

16:25 clojurebot: ) is http://xkcd.com/224/

16:25 clojurebot: In Ordnung

16:25 ibdknox: lol

16:25 who taught it German?

16:25 ;)

16:26 TimMc: This didn't seem to be a factoid lookup based on anything hired⁠man had said.

16:26 gtrak`: what about http://xkcd.com/297/ ?

16:26 TimMc: amalloy: It usually seems to cue on a single token and use that for a lookup.

16:26 clojurebot: 2 3 4 5

16:26 clojurebot: It's greek to me.

16:26 TimMc: hrmph

16:27 amalloy: clojurebot: 2 3 4 5?

16:27 clojurebot: Pardon?

16:27 TimMc: clojurebot: +

16:27 clojurebot: (+ 2 10) reply 12

16:27 TimMc: clojurebot: +

16:27 clojurebot: (+ 2 10) reply 12

16:27 muke: clojurebot: rand-int

16:27 clojurebot: Gabh mo leithscéal?

16:28 michaelr525: clojurebot: can you teach me clojure?

16:28 clojurebot: Pardon?

16:28 hiredman: 1d12

16:28 clojurebot: 8

16:28 gtrak`: 1d13

16:28 clojurebot: 10

16:28 gtrak`: huh?

16:29 michaelr525: 99999999..999999999999999999999999999999999999

16:29 muke: (rand-int 10)

16:29 michaelr525: clojurebot: 999..99999999999999999999999999999999999999999999999999999999999999999

16:29 clojurebot: Excuse me?

16:29 gtrak`: 1d14

16:29 clojurebot: 6

16:29 gtrak`: 1d1

16:29 clojurebot: 1

16:29 muke: clojurebot: (rand-int 10)

16:29 gtrak`: 1d2

16:29 clojurebot: 1

16:29 Cool story bro.

16:29 gtrak`: 1d3

16:29 clojurebot: 1

16:29 michaelr525: clojurebot: 2^999999999999999999999999999999

16:29 clojurebot: Cool story bro.

16:30 TimMc: clojurebot: Now, why wouldn't you be responding to infix notation?

16:30 clojurebot: infix is not worth the trouble; see http://groups.google.com/group/clojure/browse_thread/thread/319a1c77ed718ba/3e4be7484b7cbe38

16:30 TimMc: clojurebot: botsnack

16:30 clojurebot: Thanks! Can I have chocolate next time

16:31 muke: clojurebot: chocolate

16:31 clojurebot: Gabh mo leithscéal?

16:32 TimMc: My work here is done.

17:22 seancorfield: anyone here going to the Bay Area Clojure Meetup tonight?

17:23 * hiredman is going to the seajure bbq tonight

17:23 * coopernurse is as well

17:25 seancorfield: mm, bbq

17:31 mmarczyk: amalloy: ping?

17:43 mtm: seancorfield: I'll be there

17:47 seancorfield: mtm: cool! amit probably can't make it so he asked me to run things... i'll try to make sure i get there a bit earlier than i normally do...

17:48 pizza is taken care of, so it'll just be facilitation... no fixed topic, so open discussion... we can see what sort of projects folks are working on and maybe get some ad hoc talks :)

17:52 mtm: spiffy

17:53 scottj: seancorfield: can you push an updated congomongo snapshot to clojars?

18:02 amalloy: mmarczyk: hi

18:05 looking at your latest revision now. looks like magic

18:09 mabes_: pprint is truncating my collection with "..." (I'm writing to file, not REPL). What var do I need to set or dynamically bind to avoid this?

18:10 I've tried *print-length* but that didn't help

18:12 jli: mabes_: maybe *print-level* is what you want

18:12 actually, nevermind, I don't think so

18:13 mabes_: jli: yeah, my collection isn't nested.. just long.. prn-str works fine, but I want the formatting pprint provides

18:15 looking at the source *print-length* should do it.. hmm...

18:16 joegallo: print-dup?

18:17 nah, ignore me

18:20 seancorfield: scottj: sure... is it worth doing a non-snapshot release yet?

18:22 scottj: seancorfield: I haven't been following closely I just upgraded from 1.4 and need something from a few days ago. I certainly welcome a non-snapshot release soon

18:24 is there anyway with maven/clojars to depend on a specific snapshot or is that the nature of snapshots?

18:26 technomancy: you can use dated snapshots

18:26 scottj: what's the format on that?

18:26 mmarczyk: amalloy: hi! :-) writing that was *so* much fun, thanks for the idea

18:27 technomancy: scottj: just take the version number from the filename in lib

18:32 scottj: technomancy: so for noir-1.1.1-20110809.143608-35.jar is it [noir "1.1.1-20110809.143608-35"]?

18:33 technomancy: should be

18:40 amalloy: mmarczyk: yeah, it was really interesting. glad you liked it

18:40 jli: amalloy: what is this awesome thing?

18:41 amalloy: http://stackoverflow.com/questions/7240947/is-a-transparent-macrolet-possible/7256432

18:41 mmarczyk: amalloy: I'm writing this up properly now, with some design notes

18:42 anyway, this tool you mentioned :-)

18:42 do you have it ready?

18:42 selective test-running tool, I mean

18:44 hiredman: you know lein has test selectors?

18:44 amalloy: mmarczyk: cake and lein both have something like it already; i was adding a more convenient syntax for tagging tests

18:45 mmarczyk: hm, I vaguely remember that

18:45 though I haven't look at test.clj in lein in ages :-(

18:45 syntactic sugar, then; cool

18:57 dnolen: hmm I'm thinking about using a pre-allocated exception to implement backtracking in match if recur does not appear in any actions - optimization for complex patterns like red-black tree balancing, anyone see a potential problem w/ that?

18:58 seancorfield: scottj: i pushed an updated congomongo-0.1.7-SNAPSHOT.jar to clojars

18:58 scottj: seancorfield: ty

19:41 [swift]: i think i may have found a bug in clojurescript; string? seems to return true for keywords in clojurescript, while it returns false for keywords in clojure

19:43 hiredman: [swift]: someone decided to implement keywords in clojure with strings prefixed by certain characters

19:43 er

19:43 clojurescript

19:45 [swift]: hiredman: googling about i found that this bug has already been reported, and building in production (rather than debug) mode fixes the problem

19:46 it's a bummer, though.. clojurescript takes a long time to build, especially with optimizations on

19:59 dnolen: hmm backtracking via pre-allocated exceptions doesn't look so bad

20:00 chewbranca: dnolen: here's a fun idea, use matching rather than exception handling for control flow ;-)

20:00 could get tricky in a hurry though

20:02 dnolen: chewbranca: not sure I follow. I'm just using exceptions here as a form of jump.

20:03 chewbranca: dnolen: yeah I'm just saying you could theoretically use pattern matching for flow control in your pattern matching lib, so it would look like (match [(some-match-function)] [:success] (proceed) [:error] (backtrack))

20:05 fun idea, would get rough to debug, but I just find it interesting because I'm a big fan of using pattern matching for flow control, and technically you could implement back tracking if your initial match predicate recursively went down the tree

20:06 maybe that's just crazy iono, thought it was interesting and I'm not a huge fan of exception handling for flow control

20:07 dnolen: chewbranca: seems like a bootstrapping problem since match macro comes last. yeah exceptions for flow control, yuck. But here I'm using it to follow the literature.

20:07 so match will be hybrid decision tree / backtracking implementation.

20:08 chewbranca: dnolen: see that's the thing, exceptions just seem odd and out of place, I completey agree that bootstrapping match inside of match most likely would not work and would not be a good idea, but if you've already got your data structure and a decision tree, back tracking just seems like it should be stepping back up the tree and taking previous execution paths

20:10 dnolen: chewbranca: it sounds like it would, but I don't think it will in practice. this optimization is for non overlapping patterns.

20:11 when we backtrack, we already know we don't need to test again because there was a wildcard there in other case.

20:11 chewbranca: dnolen: ahhh ok, yeah I'm not familiar with the implementation, I just figured if backtracking was merely stepping back up the tree and taking a different branch then that would be the way to go

20:12 dnolen: chewbranca: so I think we actually get the benefit of decisions tree and backtracking. test everything once, small code size.

20:12 chewbranca: or is it more backtracking for when you failed to match on a particular column (like x y z columns from your demo) and then you need to move onto another column which is its own tree

20:15 dnolen: alright I gotta run, great job on the matching lib, I'm having a lot of fun with it

20:15 dnolen: chewbranca: on simple values you don't need to backtrack, it matches or it doesn't. however some patterns are deeply nested. then you need to backtrack once you saw that it didn't match, but we only need to move back up to the nearest shared subtree (hopefully I'm making sense), because we're already sharing as much as possible.

20:17 chewbranca: thx!

20:18 chewbranca: dnolen: ahhh ok, yeah that does make more sense, so instead of merely returning to the parent, you can return up an entire path to a much higher point as you know that you took the only possible branches on that subpath

20:18 alright, now I must run, clojure and bbq awaits!!

20:18 dnolen: chewbranca: exactly.

20:27 mmarczyk: amalloy: would you care for a pull request for flatland/useful with the latest revision of w-t-t + tests? (with tweaks to make w-t-t accept a vector of symbols yet still use a set of keywords for tagging)

20:34 amalloy: mmarczyk: yes, please. i like the macrolet version much more than mine

20:36 mmarczyk: amalloy: cool! I'll send it soon then

20:49 amalloy: done

20:52 amalloy: thanks!

21:32 user317: are agents the way to go when dealing with statefull java classes? to interface with the interactive brokers api i need to implement this class which gets called when a bunch of events happen, so i am thinking of using an agent to keep track of state as the events occur, is that the recommended approach?

21:32 i have a haskell background, so in haskell i would have pushed the events into a channel and lazy processed then as they arrive

21:39 scottj: if you're only interested in the latest state of the agent, sure

21:40 and if you need async

21:46 user317: how else would i do this? the agent can be on top of a sequence or some other data structure, so i can keep track of all the events that i get

21:47 i dont see a blocking api, comming from haskell, i thought i could build a blocking generator for a sequence

21:51 scottj: I don't have relevant experience, but there is something called channels not sure if it's related to haskell's https://github.com/ztellman/lamina/wiki/Channels

21:53 user317: cool, thanks

21:55 ah, looks like lazy channel seq does what i was thinking of

21:55 my question is though, is that the right approach?

21:56 scottj: several people have attempted to build IB libs over the years, no one's released one afaik. the old ml thread "design patterns for event driven applications" mentions IB specifically

21:56 hopefully someone with experience in this area will chime in

21:57 user317: i dont really need a lib, i just write one off processes, i have halfassed haskell bindings via their posix api, i just wanted to play around with clojure, its the new cool thing apparently :)

21:59 the "good" part of using a lazy evaluated list for events its that i can write parsers on top of them, so the state machine is captured in the parser

22:00 scottj: did you checkout that thread?

22:01 it's got IB, lazy sequences, and haskell, should be right up your alley

22:01 user317: hehe, i started that thread :)

22:01 scottj: haha, long term project :)

22:01 user317: i ended up not using clojure, i found it easier at the time to write bindings

22:03 cool, well i'll give it another shot :)

22:04 i think this time ill find a silver bullet

22:12 srid: do I really need to have a project.clj for running M-x clojure-jack-in? how else can I get a clojure shell?

22:13 scottj: srid: idk never used clojure-jack-in but you can do lein repl

22:13 srid: i like to have repl in emacs, so that i can send changed buffers to it directly

22:13 scottj: why not create a playground lein app?

22:14 srid: yea, i have one. its annoying to have to open it everytime

22:15 scottj: srid: so write an interactive emacs function to open it for you and run clojure-jack-in

23:23 amalloy: Scriptor: ping

23:23 Scriptor: amalloy: pong

Logging service provided by n01se.net