2011-09-01
| 00: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 |
| 00:01 | gaze__ | so it's probably time to rethink my problem. |
| 00: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 |
| 00:03 | amalloy | (-> "myserver.com" (connect) (commands [:cd "/tmp"] [:ls (fn [filenames] (doseq [n filenames] (println n)))]) |
| 00:04 | solussd | what is the reason (google didn't help me here) that (meta my-macro) doesn't work, but (meta #'my-macro) does? |
| 00:04 | solussd | ,(meta cond) |
| 00:04 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/cond, compiling:(NO_SOURCE_PATH:0)> |
| 00:04 | solussd | ,(meta #'cond) |
| 00:04 | clojurebot | {:macro true, :ns #<Namespace clojure.core>, :name cond, :arglists ([& clauses]), :added "1.0", ...} |
| 00:04 | srid | amalloy: this doesn't overflow http://dpaste.com/606448/ |
| 00:05 | amalloy | &(meta first) |
| 00:05 | lazybot | ⇒ {:line 53} |
| 00:05 | amalloy | &(meta #'first) |
| 00: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"} |
| 00:06 | srid | but that looks ugly; thinking ... |
| 00:06 | amalloy | srid: right. now that you've written it in a correct and fast way, consider ##(into () (range 5)) |
| 00:06 | lazybot | ⇒ (4 3 2 1 0) |
| 00:07 | srid | interesting, but doesn't work with vectors ##(into () (vec (range 5))) |
| 00:07 | lazybot | ⇒ (4 3 2 1 0) |
| 00:07 | srid | what |
| 00: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 |
| 00:08 | gaze__ | yeah, that does make sense. |
| 00:08 | srid | ##(into [] (range 5)) |
| 00:08 | lazybot | ⇒ [0 1 2 3 4] |
| 00: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 |
| 00: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 |
| 00:09 | amalloy | srid: which is why i made you fix it before i gave you the easy answer :) |
| 00:09 | srid | that's good then |
| 00:12 | srid | amalloy: now i compresed it down to http://dpaste.com/606454/ and I feel good about myself |
| 00:12 | amalloy | srid: now compress it some more, using loop instead of multiple arities |
| 00:13 | solussd | amalloy: so what's the {:line 53} output? |
| 00:14 | amalloy | solussd: how much do you understand about vars and metadata? |
| 00:15 | srid | amalloy: http://dpaste.com/606456/ - i like the multiple arities version, though. |
| 00: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. :/ |
| 00:17 | amalloy | vars are important, but you're not really wrong about them |
| 00:17 | amalloy | what you're wrong about is metadata: metadata is data about an object |
| 00:17 | amalloy | &(map class [#'first first]) |
| 00:17 | lazybot | ⇒ (clojure.lang.Var clojure.core$first) |
| 00:17 | solussd | attached to the var though, right? |
| 00:18 | amalloy | solussd: *shrug* metadata can be attached to anything |
| 00:18 | amalloy | which is why (meta first) returns one thing, and (meta #'first) returns another |
| 00:18 | amalloy | they both have metadata; what you get depends on who you ask |
| 00:19 | amalloy | the data created by defn is attached to the var, not the function |
| 00: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) |
| 00: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 |
| 00:20 | solussd | that makes sense- and defmacro adds metadata to the var then? |
| 00:21 | solussd | so, why does (meta myfunction) work? |
| 00:21 | amalloy | because functions *are* things, *are* objects |
| 00:21 | amalloy | &(let [x map] (x inc [1 2 3])) |
| 00:21 | lazybot | ⇒ (2 3 4) |
| 00:21 | amalloy | &(let [x and] (x inc [1 2 3])) |
| 00:21 | lazybot | java.lang.Exception: Can't take value of a macro: #'clojure.core/and |
| 00:22 | amalloy | (meta some-fn) only "works" in the sense that there's no error. you still don't get the docstring |
| 00:23 | solussd | does fn add metadata to the object it creates? |
| 00:24 | amalloy | try it and see |
| 00:24 | solussd | yes. :D |
| 00:25 | amalloy | not much, though, right? ##(meta (fn [])) |
| 00:25 | lazybot | ⇒ nil |
| 00: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. |
| 00:27 | amalloy | sounds good |
| 00:27 | solussd | guess you never worry about the distinction between a symbol and a var[iable] in, say, C, because you compile. :D |
| 00:28 | amalloy | nothing to do with having to compile |
| 00:29 | amalloy | 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? |
| 00:30 | solussd | that makes sense |
| 00:30 | srid | I bet there is no TCO version for flattening a list - http://dpaste.com/606461/ |
| 00:31 | amalloy | srid: correct, that's impossible |
| 00: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. |
| 00:32 | solussd | *(than c/c++) |
| 00:32 | amalloy | (except by implementing your own version of a stack, stored on the actual heap) |
| 00:36 | srid | seq can't be destructured in a loop? |
| 00:36 | srid | n/m, i was using loop in place of recur |
| 00:40 | srid | i'm close to implementing a TCO version of flatten, debugging a bug ... |
| 00:43 | amalloy | the bug that it's impossible? (though of course see my point about reimplementing the stack yourself) |
| 00:45 | srid | amalloy: http://dpaste.com/606486/ |
| 00: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]]]? |
| 00:47 | amalloy | eg, compare to the flatten in clojure.core: ##(flatten '[a [b [c d]]]) |
| 00:47 | lazybot | ⇒ (a b c d) |
| 00:47 | srid | same |
| 00:48 | srid | I used list, instead of vec. |
| 00:48 | srid | amalloy: try running it (with lists, not vec), works for me. |
| 00:49 | amalloy | hm |
| 00:50 | srid | an interesting exercise is to compare this with core.clj's tree-seq based implementation. |
| 00:51 | srid | 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. |
| 00:52 | amalloy | i see. the stack is hidden inside of concat |
| 00:52 | srid | ah |
| 00:58 | amalloy | i can't figure out an input to break it, though, so i might be wrong |
| 01:06 | srid | i really need to understand more of how seq's work under the hood. |
| 01: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 |
| 01:10 | amalloy | either way you would probably find it interesting |
| 01:10 | srid | thanks |
| 01:11 | srid | that link is down? |
| 01:12 | amalloy | it worked two minutes ago |
| 01:12 | amalloy | and works for me now |
| 01:13 | srid | times out for me, always. i have access to the google cache, though. |
| 01:13 | amalloy | weird. maybe your client can't...handle postscript files...? this sounds bizarre even as i say it |
| 01:14 | srid | connection to people.csail.mit.edu|128.30.2.148 times out. i'll try from work. ok, really off to bed. |
| 01:16 | amalloy | yes, lst is your stack of "items to be processed" |
| 01:17 | amalloy | neat implementation, anyway |
| 02:41 | amalloy | amcnamara: you around? |
| 02:50 | amcnamara | amalloy: yep |
| 02: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? |
| 02: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. |
| 02:52 | amalloy | oh man, two pull requests in the last hour, apparently |
| 02:52 | amalloy | i was CC'd, but it doesn't forward my notifications to my email. i wonder if i disabled that myself |
| 02:52 | amcnamara | ahh |
| 02:52 | amalloy | oh never mind. the other pull request was on some other project |
| 02:53 | amalloy | if you're going to do much developing (sounds like you want to), you should join us in #4clojure |
| 02:54 | amcnamara | done, didn't know there was a channel |
| 02:54 | amcnamara | :) |
| 02:54 | amcnamara | yeah, I think 4clojure is great. |
| 03:22 | michaelr525 | hello! |
| 03:54 | michaelr525 | http://acooke.org/cute/Optimising1.html |
| 03:54 | michaelr525 | Interesting stuff.. |
| 04: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)) |
| 04:25 | roger_ | It gives the same casting error as (str (\a \b)) |
| 04:25 | dbushenko | (\a \b) -- is a function |
| 04:26 | dbushenko | function \a with parameter \b |
| 04:26 | dbushenko | you should use (apply str \a \b) |
| 04:27 | dbushenko | sorry, (apply str [\a \b]) -- like that |
| 04:28 | roger_ | OK, or use (apply str '(\a \b)) |
| 04:28 | dbushenko | yep |
| 04:28 | roger_ | Thanks! |
| 04:30 | dbushenko | np |
| 04:36 | amalloy | roger_: make sure you understand the difference between [a b] and '(a b) though |
| 04:36 | amalloy | because it's pretty important |
| 04:37 | roger_ | but: (= [\a \b] '(\a \b)) gives true? |
| 04:37 | amalloy | try it for something that's not a constant |
| 04:37 | amalloy | &(let [a 1, b 2] {:quoted '(a b) :unquoted [a b]}) |
| 04:37 | lazybot | ⇒ {:quoted (a b), :unquoted [1 2]} |
| 04:40 | roger_ | amalloy: euh, I'm just reading chapter 2 of 'programming clojure', I'm not yet familiar with let and &. |
| 04:41 | amalloy | well, & is just to get lazybot to sit up and take notice |
| 04:41 | amalloy | consider this instead |
| 04:41 | amalloy | ,'((+ 1 2) 3) |
| 04:41 | clojurebot | ((+ 1 2) 3) |
| 04:42 | amalloy | ,[(+ 1 2) 3] |
| 04:42 | clojurebot | [3 3] |
| 04:42 | roger_ | what's the difference between clojurebot and lazybot? |
| 04:43 | roger_ | &'((+1 2) 3) |
| 04:43 | lazybot | ⇒ ((1 2) 3) |
| 04:43 | amalloy | not much. i just hoped you'd find , less distracting than & |
| 04:43 | roger_ | &'((+1 2) 3) |
| 04:43 | lazybot | ⇒ ((1 2) 3) |
| 04:44 | amalloy | whoa, that doesn't look right at all. is that a bug in lazybot? |
| 04:44 | roger_ | &[(+ 1 2) 3] |
| 04:44 | lazybot | ⇒ [3 3] |
| 04:44 | amalloy | &'+1 |
| 04:44 | lazybot | ⇒ 1 |
| 04:45 | amalloy | &(read-string "+1") |
| 04:45 | lazybot | ⇒ 1 |
| 04:45 | amalloy | &(read-string "(+1)") |
| 04:45 | lazybot | ⇒ (1) |
| 04:45 | amalloy | ,(read-string "(+1)") |
| 04:45 | clojurebot | (1) |
| 04:45 | amalloy | ,+1 |
| 04:45 | clojurebot | 1 |
| 04:45 | amalloy | ,'(+1) |
| 04:45 | clojurebot | (1) |
| 04:45 | amalloy | why on earth isn't +1 a valid symbol? |
| 04:46 | amalloy | at any rate, roger_, you should be putting a space between + and 1 |
| 04:46 | amalloy | but i'm surprised it broke in this particular way, instead of a different way |
| 04:48 | roger_ | oh right, I was trying to type to quickly |
| 04:49 | roger_ | I like the => in lazybot's answer better |
| 04:50 | amalloy | $mail Raynes someone likes the arrow! |
| 04:50 | lazybot | Message saved. |
| 04:51 | amalloy | ,'a1 |
| 04:51 | clojurebot | a1 |
| 04:51 | michaelr525 | what's the difference between ,( and &(? |
| 04:52 | michaelr525 | ,1 |
| 04:52 | clojurebot | 1 |
| 04:52 | michaelr525 | &1 |
| 04:52 | lazybot | ⇒ 1 |
| 04:52 | michaelr525 | except the arrow :) |
| 04:52 | Fossi | it's two bots |
| 04:52 | Fossi | they can do different things |
| 04:52 | michaelr525 | ah, right |
| 04:52 | Fossi | although for & and , they are mostly the same |
| 04:53 | michaelr525 | ah |
| 04:53 | raek | ,(println "&(+ 1 2)") |
| 04:53 | clojurebot | &(+ 1 2) |
| 04:53 | lazybot | ⇒ 3 |
| 04:53 | raek | ouch. |
| 04:53 | Fossi | don't know if they use the same sandbox though |
| 04:53 | michaelr525 | hehe |
| 04:53 | Fossi | lol |
| 04:53 | michaelr525 | think of the possibilities |
| 04:54 | Fossi | you can't make one of them spam, but both :D |
| 04:54 | michaelr525 | hmm, maybe someone can add a spell checker to one of the bots? |
| 04:54 | raek | $mail Raynes lazybot shoould probablly ignore clojurebot to avoid bot feedback loops |
| 04:54 | lazybot | Message saved. |
| 04:54 | amalloy | raek: i dare you |
| 04:55 | amalloy | clojurebot can't hear lazybot because of lazybot's ⇒ |
| 04:55 | amalloy | (which afaik is the only reason ⇒ is there) |
| 04:55 | raek | yup. |
| 04:55 | michaelr525 | too bad, it could have been funny |
| 04:55 | amalloy | raek: mind if i delete your $mail? |
| 04:55 | amalloy | since that is in fact not needed |
| 04:55 | raek | amalloy: sure |
| 04:55 | amalloy | $login |
| 04:56 | lazybot | You've been logged in. |
| 04:56 | raek | go ahead |
| 04:56 | amalloy | $unmail raek Raynes |
| 04:56 | lazybot | Deleted unread messages from raek to Raynes |
| 04:56 | amalloy | $logout |
| 04:56 | lazybot | You've been logged out. |
| 04: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? |
| 05:02 | amalloy | michaelr525: https://github.com/flatland/lazybot/wiki/Plugin-quick-start-guide if you're interested in contributing |
| 05:07 | michaelr525 | sure, I'm interested, I just have to put my work and family adside for a while ;) |
| 05: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 |
| 05:09 | amalloy | so eg ##'-+1 will parse just fine as a symbol |
| 05:09 | lazybot | ⇒ -+1 |
| 05:09 | amalloy | night |
| 05:09 | roger_ | and dream on! |
| 05:16 | michaelr525 | It's noon here |
| 05:16 | michaelr525 | Although a nap would be just fine :) |
| 05:43 | wunki | someone willing to help me out with the following compojure route: https://gist.github.com/7a23e06ad21d43710701 |
| 05:43 | wunki | shouldn't in the above code, the `user` parameter get populated with the `user` from the request map? |
| 05:56 | rata_ | hi |
| 05:56 | rata_ | in enlive, how do you select a td tag that doesn't have a child a tag? |
| 06:15 | rata_ | I did it! =) |
| 06:17 | dbushenko | wunki, probably -- no |
| 06:18 | dbushenko | you have to add :user to the route |
| 06:21 | nizze | Hi!° |
| 06:21 | nizze | I was reading about defmulti and defmethod and I already know about pattern matching |
| 06:22 | nizze | What is the real difference between multiple dispatch and pattern matching |
| 06:22 | nizze | ? |
| 06:26 | thorwil | nizze: i guess it's free-form do it all yourself vs having a decision tree written for you |
| 06:27 | nizze | So multiple dispatch is superset of pattern matching? |
| 06:28 | thorwil | i think they are orthogonal |
| 06:32 | nizze | Thanks!! |
| 06:35 | thorwil | nizze: looking at the examples at https://github.com/swannodette/match might give you a better idea of what pattern matching is |
| 06:36 | thorwil | (elsewhere you would have to deal with the syntax of languages like erlang or haskell) |
| 06:51 | wunki | dbushenko: but I have the signed in user in the request map, I really need it from there. |
| 07:34 | khaliG | man Joy of Clojure is one disappointing book so far.. i've halfway through have learnt nothing, except perhaps boredom |
| 07:35 | dbushenko | khaliG, You've started with the wrong book |
| 07:35 | dbushenko | JoC is an excellent book for advanced clojure programmers |
| 07:35 | dbushenko | it's not for beginners |
| 07:35 | khaliG | dbushenko, and i've yet to come across anything advanced |
| 07:36 | khaliG | seems a waste of 150 pages when it hasnt got hard yet?? |
| 07:36 | lazybot | khaliG: Definitely not. |
| 07:36 | dbushenko | JoC discovers many subtle thins which you'll not find in any clojure book |
| 07:37 | khaliG | dbushenko, hmmm. hopefully the latter half is more interesting :/ |
| 07:37 | dbushenko | where did you stop? |
| 07:38 | khaliG | i'd have to check the bookmark, haven't got it handy |
| 07:40 | khaliG | dbushenko, but to be fair i should finish it first :) |
| 07:40 | dbushenko | to my personal mind, Practical Clojure and Clojure in Action -- are the books to start |
| 07:41 | dbushenko | Joy of Clojure is good when you want to extend your knowledge on the topics which you already know |
| 08: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 |
| 08:53 | chouser | gtrak`: with-redefs |
| 08:54 | gtrak` | oh, wow |
| 08:54 | gtrak` | how's that different from binding? |
| 08:54 | gtrak` | in 1.2? |
| 08:55 | chouser | with-redefs changes the root binding, so the new value is visible in all threads |
| 08:56 | chouser | 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. |
| 08: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 |
| 08: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? |
| 08:58 | chouser | gtrak`: JoC p. 299 :-) |
| 08:59 | gtrak` | oh :-) |
| 08:59 | gtrak` | I've read the var chapter, it wasn't in there :-) |
| 09:00 | chouser | ah. Actually, with-redefs didn't exist when we were wrote the Var chapter. |
| 09:00 | chouser | 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. |
| 09: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 |
| 09:03 | chouser | khaliG: Hey, if you can't speak your mind on IRC, then what's it good for? :-) |
| 09:05 | chouser | 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. |
| 09:05 | chouser | s/deepling/deeply/ |
| 09:09 | gtrak` | always impressed by how pliant the core language constructs are, lisp is cool |
| 09: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 | rindolf | 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 | tsdh | 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 | tsdh | 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 | Raynes | At least, not if you're human. |
| 11:26 | Raynes | 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 | Mike|home | 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 | Mike|home | 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 | Mike|home | 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 | Mike|home | Pretty new to Lisp, so yeah excuse the lack of uh.. Lisp culture. |
| 11:29 | HET2 | hence naming Clojure Clojure I suppose... |
| 11:29 | HET2 | 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 | raek | (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 | coopernurse | 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 | HET2 | 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 | chouser | 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 | Mike|home | 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 | Mike|home | 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 | gtrak` | 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 | HET2 | 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 | gtrak` | 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 | HET2 | gtrak`: which makes the language less flexible and more verbose imho |
| 11:45 | gtrak` | agreed |
| 11:45 | gtrak` | I learned C, C++, java, clojure in that order |
| 11:47 | gtrak` | HET2, the jit is plenty fast, and you can still get the performance in clojure with records and protocols |
| 11:47 | gtrak` | 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 | arohner | 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 | icey | 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 | coopernurse | 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 | icey | (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 | arohner | it has a monitor to tell you how much CPU time is spent, how much time GC'ing |
| 12:44 | arohner | it's not very good at telling you the individual times for each URL hit |
| 12:44 | arohner | 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 | arohner | 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 | TimMc | 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 | amalloy | (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 | TimMc | ##(= (time (range))) |
| 14:10 | lazybot | ⇒ "Elapsed time: 0.489627 msecs" true |
| 14:13 | S11001001 | impressive speed |
| 14:13 | S11001001 | 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 | clojurebot | 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 | clojurebot | "Elapsed time: 0.082 msecs" |
| 14:34 | clojurebot | 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 | wabash | 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 | technomancy | 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 | amalloy | 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 | amalloy | 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 | amalloy | 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 | arohner | 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 | turbofail | 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 | coopernurse | 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 | amalloy | though for reasons i don't understand it looks like github is showing two copies of the file |
| 15:29 | amalloy | hm, the code is also wrong. that 10 snuck in at the wrong end |
| 15:29 | amalloy | 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 | coopernurse | 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 | amalloy | clojurebot: ) is http://xkcd.com/224/ |
| 16:25 | clojurebot | In Ordnung |
| 16:25 | ibdknox | lol |
| 16:25 | ibdknox | who taught it German? |
| 16:25 | ibdknox | ;) |
| 16:26 | TimMc | This didn't seem to be a factoid lookup based on anything hiredman 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 | TimMc | 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 | clojurebot | 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: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 | seancorfield | 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 | amalloy | 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 | mabes_ | I've tried *print-length* but that didn't help |
| 18:12 | jli | mabes_: maybe *print-level* is what you want |
| 18:12 | jli | 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 | mabes_ | looking at the source *print-length* should do it.. hmm... |
| 18:16 | joegallo | print-dup? |
| 18:17 | joegallo | 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 | scottj | 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 | mmarczyk | anyway, this tool you mentioned :-) |
| 18:42 | mmarczyk | do you have it ready? |
| 18:42 | mmarczyk | 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 | mmarczyk | though I haven't look at test.clj in lein in ages :-( |
| 18:45 | mmarczyk | 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 | hiredman | er |
| 19:43 | hiredman | 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 | [swift] | 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 | chewbranca | 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 | chewbranca | 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 | chewbranca | 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 | dnolen | 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 | dnolen | 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 | chewbranca | 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 | dnolen | 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 | chewbranca | 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 | mmarczyk | 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 | user317 | 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 | scottj | 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 | user317 | 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 | user317 | ah, looks like lazy channel seq does what i was thinking of |
| 21:55 | user317 | 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 | scottj | 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 | user317 | 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 | scottj | 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 | user317 | cool, well i'll give it another shot :) |
| 22:04 | user317 | 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 |