#clojure log - Aug 17 2011

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

0:17 srid: (def very-lazy (-> (iterate #(do (print \.) (inc %)) 1) rest rest rest))

0:17 I understand what `iterate` does, and even read (doc ->) - but I still cannot understand what the above form does.

0:17 Why is a *function* (rest) in place of *sequences* as (2nd, 3rd, 4th) arguments to `->`?

0:25 ah, the documentation confused me; reading the examples at http://clojuredocs.org/clojure_core/clojure.core/-%3E clarified it better.

0:53 livingston: another library has provided a hook to get a callback for each result it generates. if I just want to count them what's the best way in clojure? in commonlisp I' would just (let [count 0] and the pass the callback function (fn [result] (incf count))

0:54 amalloy: yech, a callback? they can't just provide you with a lazy-seq of results?

0:55 livingston: it's what I've got to work with.

0:55 amalloy: yeah

0:55 i think the best you can do is ape the CL version using an atom

0:55 (let [count (atom 0)] (fn [result] (swap! count inc)))

0:56 livingston: wouldn't it be cheaper to use a var and set! ?

0:57 amalloy: i think the difference would (a) be so small as to be undetectable, (b) i don't know which would be faster

0:57 and actually using set! would be awkward and (not that it matters) not-thread-safe

0:58 livingston: but the var is thread local?

0:59 amalloy: good point. i guess that means that instead it wouldn't work at all, if they called your callback from any thread but the current one

1:01 livingston: ,(doc set!)

1:01 clojurebot: Excuse me?

1:01 livingston: ,(doc 'set!)

1:01 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.Symbol>

1:01 livingston: that was helpful

1:02 amalloy: it has no doc; it's a special form

1:14 anyway, the performance gain from using a var vs atom is known-small, unknown-sign; and using a var instead of an atom will be harder to read, harder to manage, and might have problems in the face of multithreading. i'm not sure why you're worried about performance here to begin with, since this is such a tiny amount of work

1:16 livingston: a tiny amount of work times millions or billions of results is a lot of work. and it's easy with the var, I'll show you ...

1:17 amac: yay, I'm in the top 100 on 4clojure...

1:17 livingston: what's 4clojure?

1:17 amac: If you make the list gigantic I'm on the first page ;)

1:18 its a bunch of interactive clojure problems, worth a look

1:18 I only found out about it yesterday

1:18 amalloy: livingston: if you have billions of results, then for god's sake *benchmark* both approaches instead of debating and speculating about which might be better

1:20 livingston: here's the gist: https://gist.github.com/1150860

1:20 amalloy: &(with-local-vars [v 1] (let [update (fn [] (var-set v (inc (var-get v))))] (time (dotimes [_ 1e7] (update)))))

1:21 lazybot: ⇒ "Elapsed time: 4001.617115 msecs" nil

1:21 amalloy: &(let [a (atom 0) update (fn [] (swap! a inc)] (time (dotimes [_ 1e7] (update))))

1:21 lazybot: java.lang.IllegalArgumentException: let requires an even number of forms in binding vector

1:21 livingston: var has to be faster - no thread locks. also I need the data by yesterday... probably will only get to run this once

1:21 amalloy: &(let [a (atom 0) update (fn [] (swap! a inc))] (time (dotimes [_ 1e7] (update))))

1:21 lazybot: ⇒ "Elapsed time: 2519.085785 msecs" nil

1:21 amalloy: livingston: it looks like you're wrong

1:22 livingston: how is that possible?

1:22 don't atoms have to play with the STM?

1:22 amalloy: *shrug* fewer function calls? don't worry about the internals

1:23 livingston: I'll have to repeat that test a few times though to be sure...

1:29 how do I get the value of an atom?

1:29 tufflax: @the-atom

1:30 livingston: thanks

1:30 thanks for the help ... gotta run.

1:56 srid: caffeine and the-joy-of-clojure to spend the evening. perfect.

1:56 * srid goes to bed

1:57 sshack: Hi. So I'm trying to install leiningen. I've cloned the git repo and tried to run leon self-install, but get a 404 when maven tries to download stuff.

1:57 On first impression, I'm underwhelmed.

1:58 From the documentation this seems to be the correct thing to do. From practice, it isn't. What's the correct way to install leiningen?

2:01 srid: I never had to clone the repo; just downloaded https://github.com/technomancy/leiningen/raw/stable/bin/lein and ran it.

2:02 * srid really goes to bed

2:13 ibdknox_: sshack: yeah, you shouldn't download the repo.

2:13 sshack: ibdknox_: Yeah I got it. Works now.

2:13 Now is there a way to download plugins in advance? (for disconnected work)

2:13 ibdknox_: lein plugin install?

2:13 what do you mean by plugin exactly?

2:13 like project dependencies?

2:17 sshack: Yeah.

2:18 Like ring, or clj-stacktrace or whatever.

2:18 ibdknox_: assuming you always use the same version

2:18 and it's not a snapshot

2:18 it caches the dependencies in ~/.m2/

2:18 so yes

2:18 you would be fine

2:19 though that would only matter if you were creating new projects

2:19 bool_: hello

2:20 sshack: Well, say I want to add a frequently used library to a new project. That's when It'd come in handy.

2:20 But okay, I can live with this for now.

2:20 bool_: if anyone here has a spare minute or two

2:21 mind critiquing my first program? https://github.com/bool-/clojure-irc-bot/tree/master/src/anthony/ircbot

2:22 amalloy: well, your syntax for if/else is broken

2:22 bool_: mind explaining? =O

2:23 ibdknox_: bool_: you use an awful lot of java string functions

2:23 bool_: ibdknox_ are their clojure-alternatives?

2:23 there*

2:23 ibdknox_: clojure.string/split

2:23 bool_: oh alright

2:23 i was unaware

2:23 ibdknox_: ,(doc subs)

2:23 clojurebot: "([s start] [s start end]); Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive."

2:24 amalloy: bool_: the syntax for if is (if test then else)

2:24 ibdknox_: bool_: no worries, it's not wrong, you just asked for critique

2:24 bool_: oh

2:24 okay

2:24 makes more sense

2:24 i was thinking a macro for else was kind of a ridiculous solution

2:25 ibdknox_: bool_: you should use condp instead of cond in your on-connected

2:25 amalloy: (if test (then)) (:else (whatever)) executes (then) if test is true, and then returns the result of looking up :else in the map returned by (whatever)

2:25 bool_: p = predicates?

2:25 ibdknox_: actually, I don'w know what the p is for, do you amalloy?

2:25 amalloy: predicate

2:26 (condp < x 4 "4 is less than x")

2:26 ie, compare x with each clause (here there's only one) using the < predicate

2:26 ibdknox_: though that's not really a long-term solution

2:27 bool_: ibdknox_ i was going to map server to a list of channels

2:27 sshack: ibdknox_: I figured it out. lein plugin install ring 0.3.11 Installed on a per user basis.

2:27 bool_: so the cond there is temp

2:27 sshack: I'm very happy now.

2:27 ibdknox_: sshack: I'm not sure that's doing what you actually want

2:28 sshack: that will only be available to you if you are running leiningen. If you tried jaring that project, it will be missing ring

2:28 amalloy: i'd say it's pretty reasonable bool_. plenty of things to improve, but missing most of the horrendous gaffes you tend to make in your first program

2:28 are you aware that keywords and maps can be called as functions, instead of using get?

2:28 bool_: i've used haskell before so i'm familiar with functional programming (to a certain extend)

2:29 nope, i was unawake of that

2:29 amalloy: &(let [m {:test 1}] (:test m))

2:29 lazybot: ⇒ 1

2:29 bool_: so i can just do (:keyword map) ?

2:29 sshack: ibdknox_: So those jars won't be available if i'm disconnected from the net?

2:29 amalloy: *nod*

2:29 bool_: oh cool

2:30 amalloy: bool_: you can actually do better still in most of your uses of get

2:30 because of the super-duper destructuring feature. a teeny tiny bit like haskell's pattern-matching, but not really

2:30 ibdknox_: sshack: yes, they will. but they are not a part of your project, they are a part of leiningen

2:30 bool_: i see

2:31 ibdknox_: sshack: to have jars downloaded locally all you need to do is add them to your project.clj and call lein deps

2:31 sshack: ibdknox_: Great. so I can pull them into a project at any time? That's what I'm looking for.

2:31 amalloy: &(let [m {:host "irc.freenode.net" :writer "whatever"}] (let [{:keys [host writer]} m] (println host writer)))

2:31 lazybot: ⇒ irc.freenode.net whatever nil

2:31 ibdknox_: sshack: lein deps will then just read from your cache in ~/.m2/ and you'll be fine

2:31 so the right way to do it is add the deps you will need to your project and call lein deps.

2:32 sshack: after that, you're good to go :)

2:32 alex`: hey.. ibdknox.. you wrote socket.io-netty, right?

2:32 ibdknox_: uhoh

2:32 lol

2:32 alex`: yes

2:32 amalloy: bool_: that is, anytime you could (let [var-name value]), you can substitute a destructuring form/pattern for var-name, and it will break apart value in the way that you specify

2:32 alex`: heh.. nice work.. do you know if it works cross domain?

2:32 sshack: ibdknox_: Oh. hrm. So leon will cache everything once I use it?

2:32 ibdknox_: sshack: correct

2:33 bool_: intersting

2:33 ibdknox_: alex`: yep

2:33 amalloy: &(let [[x y z] (range 10000)] (+ x y z))

2:33 lazybot: ⇒ 3

2:33 sshack: That gets the desired behaviour then. Cool.

2:33 alex`: sweet.. good to know.. i might be using it

2:33 ibdknox_: alex`: it's rough around the edges, but it works well enough

2:34 depywork: what's the difference when you do &(expr) or ,(expr) ?

2:34 sshack: ibdknox_: The use case was I'm on an airplane and suddenly think "Shit I forgot to add foobar-clj to my project. But I'm away from internet, so I can't do it"

2:34 amalloy: depywork: a different bot wakes up

2:34 ,1

2:34 &1

2:34 lazybot: ⇒ 1

2:34 clojurebot: 1

2:34 depywork: Oh.. Didn't notice that :)

2:34 ibdknox_: sshack: it'll be fine as long as you've downloaded that version for some other project before

2:35 sshack: That Works for me.

2:50 bool_: is there a clojure-equivalent of indexOf

2:56 amalloy: i mean, maybe, but one generally tries to write clojure so that indexes aren't relevant

2:56 bool_: link me to the line where you want indexOf?

2:57 bool_: https://github.com/bool-/clojure-irc-bot/blob/master/src/anthony/ircbot/irc.clj#L6

2:57 and wow the destructuring makes code a lot cleaner

2:58 amalloy: bool_: probably use re-seq there to pull it apart with a regex

2:58 bool_: regex is hardly an appropriate solution to parsing irc messages imo

2:59 amalloy: bool_: you're using .indexOf, you don't really get moral high ground

2:59 bool_: i suppose

2:59 it seems more appropriate than regex

2:59 jblomo: bool_: you can just use .indexOf. clojure strings are java strings

2:59 bool_: i know jblomo

2:59 jblomo: (.indexOf "string" (int \s))

2:59 bool_: i was just wondering if there was an alternative

3:02 amalloy: $javadoc String split

3:02 lazybot: http://download.oracle.com/javase/6/docs/api/java/lang/String.html#split(java.lang.String,%20int)

3:06 amalloy: &(let [line "foo!bar@baz test", [nick more] (.split line "!" 2), [user host] (.split more "@" 3)] [nick user host])

3:06 lazybot: ⇒ ["foo" "bar" "baz test"]

3:07 amalloy: &(let [line "foo!bar@baz test", [nick more] (.split line "!" 2), [user more] (.split more "@" 2), [host] (.split more " ")] [nick user host]) ;; more like what you want, i guess

3:07 lazybot: ⇒ ["foo" "bar" "baz"]

3:07 amalloy: bool_: ^?

3:07 bool_: hmm

3:07 that is quite a bit better

3:08 jblomo: anyone know if ns-resolve, ns-aliases, *ns* are going to make it into clojurescript?

3:08 amalloy: i'm sure we can do better with something like ##(doc reductions)

3:08 lazybot: ⇒ "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init."

3:13 amalloy: bool_: https://gist.github.com/1151010 is longer but less tedious and micromanaged

3:16 bool_: i ended it just going with the split solution

3:16 UP*

3:16 up*

3:16 amalloy: *laugh*

3:17 well, this is the split solution, but less dense and more extensible. i prefer it, but i can see how you might not

3:17 bool_: i don't see any need to extend it

3:17 lol

3:17 it's not like the rfc is going to change that

3:18 i don't see a new irc standard any time soon breaking that

3:18 amalloy: feh. irc is such a fad

3:18 ibdknox_: amalloy: I didn't know about reductions, that's fun

3:19 bool_: i just pushed an update per (all?) of your suggestions

3:19 amalloy: i'm only here b/c i heard miley cyrus uses irc

3:20 ibdknox_: it's neat, isn't it? i rarely get a chance to use it; reduce is usually enough

3:20 as, indeed, it was here

3:20 ibdknox_: yeah, I'm trying to think of when I would *need* to use it

3:20 bool_: well, it's midnight i'm off to bed

3:20 good night

3:20 thanks for the help

3:21 amalloy: ibdknox_: the classic (if there is one?) is to keep reducing until you hit some cutoff accumulator value, and then stop

3:22 ibdknox_: yeah, there have been a couple of times when I've wanted that

3:22 often when parsing arg collections

3:22 amalloy: like maybe ##(last (take-while #(< (count %) 10) (reductions str ["a" "sfdsa" "bvmez" "sdfewce"])))

3:22 lazybot: ⇒ "asfdsa"

3:22 ibdknox_: though I think dnolen's match will be better for that

3:24 amalloy: parsing arg collections? when is reductions useful for that?

3:24 for that sort of task i'd usually reach for split-with, if i understand what you mean

3:26 ibdknox_: so like in noir you can do (defpage foo [:post "/blah"] [] ...)

3:26 but you can also do

3:26 (defpage "/blah" [] ...)

3:27 I could imagine you could use reductions to homogenize all the different forms of those definitions

3:27 maybe not though

3:27 amalloy: hm

3:28 ibdknox_: it's a great place for match though

3:28 I think that would be the cleanest solution

3:30 my current implementation is essentially like a reduction

3:30 https://github.com/ibdknox/noir/blob/vnext/src/noir/core.clj#L26

3:32 amalloy: ibdknox_: whoa, are you using tabs for indentation or something? the indentation of the last line of parse-fn-name makes it look like part of the let

3:32 ibdknox_: oh weird

3:33 I've been trying this emacs thing you guys keep talking so much about ;) and switching between vim and emacs over and over again hasn't been friendly

3:33 amalloy: *chuckle*

3:33 i went through a period like that with eclipse and emacs

3:34 making me less old-school hard-core, i guess

3:34 ibdknox_: haha

3:37 manuel_: the good thing about emacs is that both eclipse and macosx have the same basic navigation shortcuts

3:37 + killring

3:37 somejan: \

3:37 amalloy: how are emacs, macos, and eclipse related?

3:38 somejan: \join #python

3:38 manuel_: they're all computer programs

3:38 amalloy: come to think of it that sounds like a setup for some weird joke

3:38 ibdknox_: lol

3:38 manuel_: heh

3:39 thorwil: ibdknox: with noir's defpage, how is the order in which routes are matched defined?

3:39 gstamp:    while we're on the topic of emacs… anyone a mac emacs user? I have this slight annoyance that if I move the carot too quickly the screen updates don't keep up so I can't tell where my carot is

3:39 manuel_: gstamp: which emacs variant?

3:39 amalloy: oh, you mean the way that most macos apps support readline-style commands like C-w, in addition to Cmd-x?

3:39 manuel_: i'm using emacs23 in terminal

3:39 ibdknox_: thorwil: it's intentionally not defined

3:40 manuel_: amalloy: i have ctrl-space + ctrl-w yes

3:40 i think i hacked something in a plist somewhere to enable it

3:40 gstamp: the one from here: http://emacsformacosx.com/

3:40 ibdknox_: thorwil: but you have the ability to define pre-routes for filtering and as of last night post-routes for special catch alls, but those should be used sparingly

3:40 amalloy: right. i'm on linux, but during my very brief stint on macos i did find that quite nice

3:40 manuel_: gstamp: i guess it's the cocoa build, right? dunno about that

3:41 i'm using the terminal version with iterm so that i will find the same environment on every machine i possibly can come into contact with

3:41 thorwil: ibdknox: what happens if you use neither pre-routes nor post-routes, but have to deal with a request where more than one defpage matches?

3:42 gstamp: manuel_: I think so. I tried building with brew a weeks back but the compilation was failing.

3:42 manuel_: yeah, i had to fix the emacs.rb

3:42 ibdknox_: thorwil: can you give me an example where that's true?

3:47 thorwil: ibdknox: hmm, for example, if you have a "catch-the-rest" handler to present a 404, after all other routes failed. the way i use that with moustache, this one must be last in the list

3:48 ibdknox_: that already exists :)

3:49 thorwil: there's a route at the end that will return a 404 code, and then a piece of middleware picks that up and gets the right page for that status

3:49 thorwil: to change what that page's content is, you'd used this: https://github.com/ibdknox/noir/blob/master/src/noir/statuses.clj#L15

3:50 thorwil: i admit i have a hard time of thinking of another case where several routes might match

3:50 ibdknox_: :)

3:51 thorwil: I did too

3:51 thorwil: so it seems if you special-case 404, order doesn't matter elsewhere

3:51 ibdknox_: exactly

3:51 and there's power in that

3:51 amalloy: ibdknox_: hrm. i instinctively feel it's evil for you to decree that a 404 has *only one* static output

3:51 ibdknox_: amalloy: it doesn't

3:51 amalloy: I only do that if you haven't given me a body

3:52 amalloy: but i assume you can always return actual content with a code of 404

3:52 ibdknox_: yessir

3:52 amalloy: okay. well, you're off the hook this time

3:52 ibdknox_: :D

3:54 amalloy: i keep forgetting to check whether (defn foo [x] [:bar :baz]) computes the result at compile time or rebuilds it every time the function is called

3:54 if anyone else is excited to know the answer to that question, feel free to check it out and report back to me

3:54 ibdknox_: lol

3:55 * amalloy doesn't really enjoy AOTing clojure code and then running javap on the .class files

3:58 ibdknox_: alright, g'nite #clojure. :)

4:00 pyr: ok i get how easy it is to make DSLs which look like they are providing functions when doing everything inline

4:00 you just have a dispatch match {'fun1 (fn [] ...), 'fun2 (fn [] ...)}

4:00 and apply to these functions

4:01 (map (fn [[fname & fargs]] (apply (dispatch fname) fargs)) some-forms)

4:01 amalloy: whut. i cannot imagine anything that comes after this introduction can be good news

4:02 pyr: that makes macros easy when they're inline

4:02 (i.e: not using `)

4:03 but is it just me or it becomes a world of pain once you want to introduce user supplied symbols in there

4:05 amalloy: pyr: of course it's a pain. you're doing something crazy

4:06 i don't understand even a toy use-case for what you're describing

4:07 pyr: i was starting from the example macro in joy of clojure

4:08 which reduces a DSL to a string (an SQL query)

4:08 amalloy: if anyone's curious: (fn [x] [:foo :bar]) stores :foo and :bar at compile-time, but builds the vector every time

4:09 pyr: amalloy: (SELECT [a b c] (FROM ...))

4:10 which reduces to a vector of query string and arguments

4:10 amalloy: right. that's not a very flexible macro, and iirc they say so

4:11 pyr: yes

4:11 so, just use keywords instead to dispatch

4:12 amalloy: keywords won't make it any easier

4:12 or not much, anyway

4:12 just...if a macro does extensive manipulation/replacement of the form you pass it, don't expect it to handle many corner cases

4:13 instead, write smaller macros or functions that do simple things, and combine them into a bigger thing

4:13 pyr: my reasonning was this

4:13 i have a schema to describe

4:13 my internal storage is a record

4:14 which would be painful to write

4:14 so i provide a macro to reduce forms into this record

4:15 (schema :foo (entity :bar) (entity :baz (unique)))

4:15 for instance

4:16 args are mapped to an entity function, whose args are mapped in this case to unique (which sets a flag to true)

4:16 two levels of reduce are then done to get the final correct representation

4:16 maybe that's completely crazy

4:17 amalloy: the general idea isn't crazy, but the implementation might be

4:17 pyr: :)

4:18 you mean it has to be crazy

4:18 because there's no sane way of doing it

4:18 amalloy: i write such macros as (schema :foo :entities {:bar [], :baz [:unique]}) or some such

4:18 pyr: or

4:18 yeah

4:18 i went that way but thought it wasn't readable

4:18 (or you mean you think i'll do a crazy implementation)

4:20 amalloy: i mean that (a) asking the user to write (entity) over and over is rude, and (b) an implementation that parses this input format is going to have to be more complicated than my map-based approach

4:20 pyr: yes totally agreed

4:20 i initialy went with a map

4:20 maybe i'm overthinking it

4:20 indeed

5:24 fliebel: I found 3 HTTP clients, but I can't decide. http.acync.client, clj-http and Aleph.

5:28 clgv: the name aleph sounds nice. no other opinion here ;)

5:32 fliebel: clgv: Okay, I'll go with aleph :)

5:33 ejackson: aleph has a really nice library behind it

5:33 fliebel: Actually, that's more because I figured I might use the server as well, and I need streaming as well.

5:33 But Aleph looks more complicated than clj-http

5:34 Channels are weird, I wonder where this is leading: http://dev.clojure.org/display/design/Asynchronous+Events

5:37 ejackson: i think they're awesome

5:37 :)

5:37 i use a more basic idea in my own code

5:38 take async thingies and get a seq over em, nice

5:48 fliebel: Huh, the Aleph client *uses* clj-http! https://github.com/ztellman/aleph/blob/master/src/aleph/http/client.clj#L17

5:48 * fliebel is confused

7:33 lnostdal_: hi guys, so theres dynamic variables and then there's with-local-vars .. with-local-vars would be what i'm after, but it's lexical only (hm, right?) .. so not quite .. dynamic vars are not mutable; not even thread-locally, so i got to wrap the value in an atom e.g. to mutate even when there is no concurrency going on .. i'm probably missing something, but what?

7:33 ..with-local-vars would be what i'm after because it has var-set

7:34 leo2007: how large is clojuredocs git repo?

7:35 manutter: lnostdal_: what are you looking for, mutable vars?

7:35 lnostdal_: manutter, something like "mutable dynamic vars"

7:35 i mean since they're dynamic and thread bound; there's no concurrency issues to begin with

7:35 manutter: leo2007: I don't remember how big the clojuredocs repo was, but it was something like a couple meg I think?

7:36 slilo: leo2007: "Receiving objects: 100% (2419/2419), 1.98 MiB | 332 KiB/s, done.

7:36 Resolving deltas: 100% (978/978), done."

7:36 leo2007: for offline usage, do I need mysql?

7:36 manutter: lnostdal_: I'm confused maybe: I thought dynamic vars *were* mutable, using set!

7:36 leo2007: silven and manutter: thanks.

7:37 clgv: lnostdal_: thread local binding with atoms works for that use case

7:38 manutter: leo2007: I forget what db it uses, but I know you need rake to run the search engine

7:39 lnostdal_: manutter, odd, i was attempting to tab-complete "set" , but no result .. but it's really there anyway .. that's what i was looking for

7:39 thank you

7:40 manutter: lnostdal_: I usually use atoms myself, just to keep myself in the "vars == immutable" frame of mind :)

7:41 lnostdal_: reset! || set! ... meh .. :)

7:42 manutter: leo2007: found the docs: clojuredocs uses Ruby 1.8.7, Rails 2.1.5, MySQL 5.1, bundler, Sphinx 0.9.9 and optionally RVM.

7:43 leo2007: yeah, setting that up is a painful process. I love plain html. The common lisp hyperspec works splendidly.

7:43 manutter: I think it's time ClojureDocs was re-written in Clojure ;)

7:46 leo2007: How can I download https://github.com/clojure/clojure/tree/gh-pages using the download button?

7:47 It downloads clojure not the docs.

7:47 vijaykiran: leo2007: just clone the repo ?

7:48 leo2007: vijaykiran: sure. I was just wondering why clojure.org gives that advice.

7:52 vijaykiran: leo2007: I guess the download does contain the docs .. from the gh-pages branch (sorry If I missed context of your question)

7:52 leo2007: vijaykiran: it doesn't.

7:53 slilo: leo2007: https://github.com/clojure/clojure/tarball/gh-pages

7:53 vijaykiran: leo2007: I just clicked on download on https://github.com/clojure/clojure/tree/gh-pages and clocked on Download .zip

7:53 leo2007: the branch in the dialog says Branch:gh-pages

7:54 leo2007: vijaykiran: I see this http://imagebin.org/168351 when clicking on the downloads button on the top-right corner.

7:56 slilo: there are two buttons, for tar.gz and zip archives

7:58 vijaykiran: leo2007: you can try the link slilo posted - should download the tar.gz directly

8:00 leo2007: silven: I see. I was confused by that. the interface at http://repo.or.cz is better.

8:00 slilo: no way )

8:16 leo2007: can special forms contain doc-string?

8:16 (doc def) => Please see http://clojure.org/special_forms#def

8:16 clojurebot: excusez-moi

8:20 clgv: leo2007: why do you ask?

8:20 leo2007: because (doc SPECIAL-FORM) always points to a link

8:20 instead of just show me the doc-string

8:21 clgv: I guess that's because it's described their in more detail than they could within the docstring I guess

8:22 special forms are as well not implemented in clojure but defined by the clojure compiler

8:27 leo2007: Can someone give me an example of making a doc* macro that is the same as doc but eval its arg

8:32 clgv: (defn doc* [arg] (doc arg)) -> argument gets evaluated before the call and doc is called on it afterwards

8:32 slilo: (/ 1 0)

8:32 clojurebot: #<ArithmeticException java.lang.ArithmeticException: Divide by zero>

8:33 clgv: humm doesnt work that well. doc expects a var

8:33 clojurebot: http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png

8:34 clgv: leo2007: try that one (defn doc* [arg] (-> arg meta :doc))

8:34 slilo: (iterate inc 0)

8:34 is there a manual for bot? :)

8:35 clgv: you have to prefix calls to clojurebot via ,

8:35 ,(+ 1 2)

8:35 clojurebot: 3

8:35 slilo: ,(iterate inc 0)

8:35 clojurebot: (0 1 2 3 4 ...)

8:35 clgv: for lazybot it is &

8:35 &(+ 1 2)

8:35 lazybot: ⇒ 3

8:35 slilo: thank you, clgv

8:56 simonj: How can I pass a Seq to a Java method where each item in the seq is a different argument to the method?

8:57 clgv: simonj: I guess you can't.

8:57 leo2007: clgv: but (doc* (symbol "defn")) still fails

8:57 sorry I am not familiar with clojure yet.

8:58 clgv: leo2007: what exactly are you trying to do?

8:59 cemerick: simonj: There's no built-in way to do that. Java methods do not have an equivalent of apply.

8:59 clgv: that works pretty well as it is: ##(doc defn)

8:59 lazybot: ⇒ "Macro ([name doc-string? attr-map? [params*] body] [name doc-string? attr-map? ([params*] body) + attr-map?]); Same as (def name (fn [params* ] exprs*)) or (def name (fn ([params* ] exprs*)+)) with any doc-string or attrs added to the var metadata"

8:59 cemerick: Writing an apply-interop macro wouldn't be tough, tho.

8:59 simonj: cemerick: bother. What about constructors? Same deal I would imagine.

9:00 cemerick: simonj: Indeed; Java has no apply, and everything is positional.

9:00 leo2007: clgv: using your definition of doc*, (doc* (symbol "defn")) returns nil here.

9:01 clgv: leo2007: thats right since the symbol has no metadata

9:02 leo2007: so again, what exactly do you want to do?

9:02 simonj: cemerick: ok, thanks.

9:03 clgv: is there some built-in identity macro? I could use it within a "(->" statement

9:04 leo2007: clgv: I want to see if documentation-symbol in swank-clojure can be more helpful.

9:04 it uses print-doc and seems to return nil for many things

9:05 clgv: e.g.?

9:06 Weisshaupt: Got a quick Leiningen question. I have generated some protocol buffer classes in src/models/Models.java and added :java-source-path "src" to my project.clj.

9:07 However, when doing "lein compile" javac doesn't seem to add the jars in libs to its classpath.

9:07 leo2007: clgv: def

9:07 clgv: ,(doc def)

9:07 clojurebot: excusez-moi

9:07 clgv: &(doc def)

9:07 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

9:07 clgv: I get:

9:07 user=> (doc def)

9:07 -------------------------

9:07 def

9:07 Special Form

9:07 Please see http://clojure.org/special_forms#def

9:08 and thats ok since it's described their in detail ;)

9:10 leo2007: clgv: I am talking about the documentation-symbol in swank-clojure: see basic.clj line 250

9:11 clgv: leo2007: ok. cant help you with that since I do not use it

9:11 leo2007: alright.

9:11 clgv: but I have a feeling that you might waste your time with that "task" ;)

9:11 cemerick: simonj: somethign like this should work: https://gist.github.com/1151504

9:13 simonj: cemerick: awesome! Thank you.

9:14 cemerick: simonj: You're welcome. That is pretty trivially adaptable to do the same sort of thing with ctors as well.

9:14 or maybe a separate apply-new macro would be better *shrug*

9:15 xian: ,`foo

9:15 clojurebot: sandbox/foo

9:15 clgv: cemerick: that won't work for list that are not evaluated until runtime I guess

9:15 xian: is it possible to use the backquote templating syntax (i.e. ` and ~) without symbols expanding to their fully qualified names?

9:16 cemerick: clgv: Right, it's a macro. If you want a runtime apply, then a corollary fn would be required.

9:16 clgv: cemerick: ok, thats what I thought. just wanted confirmation

9:17 dnolen: xian: `(~'foo)

9:17 ,`(~'foo)

9:17 clojurebot: (foo)

9:17 dnolen: ,`(foo)

9:17 clojurebot: (sandbox/foo)

9:18 xian: dnolen: thanks

9:21 cemerick: clgv: Actually, in that case, just a simple eval will do.

9:21 clgv: ,(doc eval)

9:21 clojurebot: "([form]); Evaluates the form data structure (not text!) and returns the result."

9:22 clgv: so building the list of the call and evaling it then

9:22 cemerick: It's simpler than it sounds. :-)

9:22 ,(let [k [0 4] string "foobar"] (eval `(.substring ~string ~@k)))

9:22 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

9:22 cemerick: eh, whatever

9:23 sandboxes aside, if you need to spread args of unknown length at runtime, you're going to either use reflection or eval.

9:24 of course, simonj is gone :-P

9:26 clgv: I don't do that much interop anyway. just curiosity - who knows if it can be useful later ;)

9:37 Weisshaupt: So, leiningen. Trying to compile some java I've got included via :java-source-path. It doesn't seem to add the jars in libs/ to the javac classpath. Anyone familiar with this?

9:38 clgv: Weisshaupt: by default that folder is called "lib" but you may specify a different one in the project.clj

9:39 Weisshaupt: Sorry, it is the default "lib".

9:40 It's a generated file which references classes in "lib/protobuf-java-2.4.1.jar", if I go "javac src/Models.java -cp lib/protobuf-java-2.4.1.jar" it works cleanly.

9:51 clgv: humm strange.

9:52 manutter: Weisshaupt: version of leiningen?

10:10 TimMc: amalloy_: I went through the rest of that paper. It seems to me that one should speak of the *minimum* order of a function, which is defined as 1 + the highest minimum order of any functions in its contract.

10:18 Weisshaupt: manutter: Leiningen version 1.6.1

10:19 I can see, when doing "lein classpath" that the specific jar is in there. I dunno, maybe I screwed up somehow..

10:19 manutter: Weisshaupt: yeah, it should work when used as you describe

10:20 what's the exact symptom that makes you say it's not finding the jar?

10:20 Weisshaupt: Well, doing a "lein cokmp

10:20 flazz: where can i download the vimclojure.jar?

10:20 Weisshaupt: Doing a "lein compile" gives me a bunch of "cannot find symbol: class BuilderParent".

10:21 But when I simply go "javac source -cp libs/protobuf-java-2.4.1.jar" it compiles/

10:24 manutter: Are you pulling in the jars by adding a "protobuf" line to project.clj?

10:25 * raek takes a look at https://github.com/technomancy/leiningen/blob/master/src/leiningen/javac.clj

10:33 raek: Raynes: there seems to be a problem with try-clojure.org. (try to evaluate anything)

11:07 Weisshaupt: manutter: Yeah, the protobuf jars are in project.clj.

11:07 I think I saw an option in project.clj to ignore classes you've built manually, somehow. I guess I can go that route.

11:09 manutter: Yeah, I'm out of clues, best I can do at this point is wish you luck.

11:09 Weisshaupt: :)

11:44 jcromartie: how would I instantiate a java.lang.ProcessBuilder from Clojure?

11:45 clgv: jcromartie: using its constructor like (ProcessBuilder. param1, param2, ...)

11:46 jcromartie: its constructors are: ProcessBuilder(List<String> command) and ProcessBuilder(String... command)

11:46 so it's not that simple

11:49 how do you create a List<string> from Clojure? is that possible?

11:50 dnolen: ,(bases (class '(1 2 3)))

11:50 clojurebot: (clojure.lang.ASeq clojure.lang.IPersistentList clojure.lang.IReduce java.util.List clojure.lang.Counted)

11:51 jcromartie: got it

11:51 I didn't realize that Java generics were purely compile-time, so at runtime it doesn't care what you pass!

11:51 awesome

11:51 manutter: :D

11:51 jcromartie: so (ProcessBuilder. ["foo" "bar"])

11:52 sleepynate: amalloy_: is there a "Run" hotkey on 4clojure?

12:01 anyone know if there's a big speed difference between lambdas partials, and #() ?

12:02 i'm guessing not

12:05 mdeboard: sleepynate: #() == lambda

12:06 sleepynate: (fn) is what then?

12:06 mdeboard: an anonymous function

12:07 sleepynate: fair enuogh... so any major difference between (fn), #(), and partial?

12:07 clgv: #() is a reader macro that is expanded to a fn-form afaik

12:07 sleepynate: clgv: yea, i don't have a repl handy

12:07 mdeboard: Yeah that's what i"m saying

12:08 lucian: &(type #())

12:08 lazybot: ⇒ sandbox7610$eval12974$fn__12975

12:08 mdeboard: a lambda function is an anonymous function is (fn) is #()

12:08 clgv: partial is a function returning a fn

12:08 lucian: &(type (fn []))

12:08 lazybot: ⇒ sandbox7610$eval12983$fn__12984

12:08 sleepynate: ok so they're all pooping out the same thing

12:08 essentially

12:08 lucian: &(partial + 1)

12:08 lazybot: ⇒ #<core$partial$fn__3678 clojure.core$partial$fn__3678@104cfd0>

12:08 lucian: uh, forgot type

12:08 sleepynate: almost

12:09 :/

12:09 lucian: sleepynate: partials are slightly special, but fn and #() are the same

12:09 sleepynate: the question i want to get to the root of "is there one that is preferred speedwise?"

12:09 for example coming feom clisp and haskell, i'm fond of partials, but i know the same pattern in pythong costs

12:10 lucian: sleepynate: python partials are ok

12:10 sleepynate: and premature optimisations are indeed the root of all evil :)

12:11 sleepynate: #() and fn are just java methods. partial, i don't know

12:11 clgv: sleepynate: measure their performance for your usecase.

12:11 lucian: what clgv said

12:11 opqdonut: clojure.contrib.profile is nice

12:12 ( http://richhickey.github.com/clojure-contrib/profile-api.html )

12:12 for simple benchmarks

12:12 sleepynate: ahh the classic stodgy programmer way of saying "i don't know" :)

12:12 opqdonut: I would assume that fn and partial are as fast

12:13 sleepynate: yea. my interest at the moment is purely academic

12:13 mdeboard: sleepynate: Clojure's 4 years old, infancy for a language. If you want to know you'll almost certainly have to benchmark it yourself

12:13 sleepynate: since you have a dynamic language built on top of a static language, how do you rectify not being super slow in creating partials

12:13 mdeboard: sure, and that's fair

12:14 mdeboard: "built on top of a static language" is not right

12:14 lucian: sleepynate: java's object system is totally dynamic

12:14 sleepynate: so all clojure fns implement IFn

12:14 clojure is very "close to the metal"

12:15 sleepynate: IFn is a jvm thing or clojure thing?

12:15 st3fan: put the pedal to the metal

12:15 manutter: IFn is a Java interface

12:15 sleepynate: ok

12:16 so in haskell and i *believe* scala, we know that it's safe to always create a partial because not only everything is a function, but everything is a typed function

12:17 lucian: sleepynate: how would it not be safe to make a partial?

12:17 sleepynate: (str (partial + 10) "derp")

12:18 this would (i'm assuming) raise an exception

12:18 clgv: try it ;) ##(str (partial + 10) "derp")

12:18 lazybot: ⇒ "clojure.core$partial$fn__3678@1ebea8derp"

12:18 dnolen: sleepynate: partials are not slow in Clojure if that's what you're asking.

12:19 sleepynate: dnolen: partially. more asking myself "how would i design this same thing"

12:19 lucian: sleepynate: i don't see how that's less safe than calling a function with the wrong args

12:19 sleepynate: i'm sure many of you wrote lisp interpreters in non-lisps for shits and giggles ;)

12:20 dnolen: sleepynate: never bothered. Clojure fortunately is compiled.

12:23 manutter: I've done lots. Well, actually, I've written buggy and slow implementations of small portions of LISP.

12:23 I call it "PHP code"

12:24 jcromartie: check out my super-slick 100%-true-to-original Markdown lib for Clojure https://gist.github.com/1151940

12:24 sleepynate: lucian: well, in haskell, you can see whether it's going to fit the type where it's applied, and then consider it to be the equivalent of a constant of that type. in clisp using comething like cl-op, you lose a lot of time by essentiall re-expanding a buttload of anonymous functions

12:25 so while they'll both explode eventually, if you can you probably want to explode before you get to the nth level down

12:25 lucian: sleepynate: it still seems pointless to me

12:25 perhaps i like python too much

12:25 sleepynate: ok

12:25 manutter: jcromartie: lol, love it

12:26 jcromartie: (and no it doesn't leave processes hanging around)

12:26 sleepynate: lucian: that said, until i got sucked up as an android developer, i was doing cython on robots :D

12:26 lucian: sleepynate: in a dynamic language, you tend not to care

12:27 jcromartie: sleepynate: that sounds like a fun job

12:27 sleepynate: jcromartie: it was fuckin' sweet

12:28 lucian: awesome indeed

12:28 sleepynate: jcromartie: i got to do a bunch of benchmarking on stuff ported from old LISP ai papers into itertools and then compiled

12:28 lucian: sleepynate: btw, clojure is useless on android atm, sadly

12:28 sleepynate: lucian: yea, i already found out :(

12:29 lucian: maybe an approach similar to clojurescript might work instead

12:29 sleepynate: however... if we can improve the speed by pondering over the type system's effect on the creation of partials...

12:29 ;D

12:29 lucian: sleepynate: then we'd waste time we could better spend on useful things! :P

12:29 sleepynate: that is not a very good hacker attitude

12:30 mdeboard: what.

12:30 lucian: i think it's great. i've always been wrong when i guess what could be slow

12:30 profiling is the only way to know, so caring about the performance of one particular construct seems silly to me

12:31 mdeboard: sleepynate: Is a better hacker attitude to spend half an hour asking about performance instead of just testing it yourself?

12:31 sleepynate: ahh i misunderstood the direction of your "useful things" statement

12:31 dnolen: sleepynate: a type system will not make much Clojure faster, Clojure is designed be as very fast w/o such things.

12:32 sleepynate: the only place where I think it would be interesting is automatically placing type hints for interop calls.

12:32 sleepynate: mdeboard: wel, at the same time i've got the source for cl-op open, i'm looking for the Patrial assembly in scala

12:32 so, from a mental excercise point of view... yes i think so

12:37 dnolen: but there is a type-system pre-existing that it sits on top of, no? as far as i can tell clojure is relying on java most of the time to explode-as-needed

12:37 not that i feel like putting a type system on a standard lisp is a good idea

12:37 lucian: sleepynate: well, clojure does have a type system. a dynamic, strong type system

12:38 it shares bits with java's (also dynamic, mostly strong) type system

12:39 sleepynate: are we talking about through Javarelfector and Coercion protocols? or something i'm not familiar with

12:39 rpg: As a lisper coming to clojure, I'm used to checking what my functions do by using TRACE. Is there something similar for me in Clojure? contrib.trace seems to be a much more cumbersome beast involving recompilation...

12:40 sleepynate: rpg: good question

12:40 dnolen: sleepynate: don't follow. And some people have had succeeded quite well at combining Lisp w/ sophisticated type systems.

12:41 sleepynate: dnolen: for example...

12:41 &(+ 5 "derp")

12:41 lazybot: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number

12:41 dnolen: sleepynate: Typed Racket, Qi/Shen

12:41 sleepynate: ^ not a clojure error

12:42 dnolen: sleepynate: Clojure doesn't mess w/ the JVM exception mechanism for good reason. That *is* a Clojure error.

12:44 rpg: Hm. Looks like maybe dotrace does what I want w/o recompilation.... not sure...

12:46 anyone by any chance using MCLIDE with Clojure? it seems by default not to be configured to find clojure.contrib....

12:51 dnolen: wow Clooj is coming along

12:52 sleepynate: #((format "hi, %s" %))

12:52 why does that raise an exception>?

12:52 &#((format "hi, %s" %))

12:52 lazybot: ⇒ #<sandbox7610$eval13014$fn__13015 sandbox7610$eval13014$fn__13015@64fb8d>

12:52 sleepynate: hm

12:52 i'll wait til i'm at a real repl :)

12:53 dnolen: ,(#((format "hi, %s" %)) "foo")

12:53 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn>

12:53 sleepynate: right.

12:53 dnolen: ,(#(format "hi, %s" %) "foo")

12:53 clojurebot: "hi, foo"

12:54 dnolen: ,((partial format "hi, %s") "foo")

12:54 clojurebot: "hi, foo"

12:54 sleepynate: ahh i see

12:54 the macro expander expects an implicit ()

12:55 dnolen: ,(macroexpand '#())

12:55 clojurebot: (fn* [] ())

12:56 dnolen: ,(macroexpand '#(%1))

12:56 clojurebot: (fn* [p1__3037#] (p1__3037#))

12:56 dnolen: ,(macroexpand '#((f %1)))

12:56 clojurebot: (fn* [p1__3064#] ((f p1__3064#)))

12:56 sleepynate: thanks

12:56 TimMc: ,#()

12:56 clojurebot: #<sandbox$eval3091$fn__3092 sandbox$eval3091$fn__3092@1001b77>

12:56 sleepynate: do either of the bots support the repl's "source" ?

12:56 TimMc: ,(#())

12:56 clojurebot: ()

12:57 dnolen: clojurebot: source vec

12:57 rpg: What does a "no message" error mean? I have a recursive function, and it seems like a recursive call is failing, but I'm not understanding the error...

12:58 dnolen: rpg: the error is at runtime?

12:58 sleepynate: dnolen: nice thanks :)

12:58 rpg: dnolen: yes.

12:58 I'm trying to write my first function that takes a variable number of arguments....

12:58 dnolen: rpg: paste please.

12:59 TimMc: clojurebot: paste?

12:59 clojurebot: http://gist.guthub.com

12:59 TimMc: >_<

12:59 sleepynate: :D

12:59 TimMc: clojurebot: forget paste |is| http://gist.guthub.com

12:59 clojurebot: I forgot that paste is http://gist.guthub.com

13:00 TimMc: clojurebot: paste?

13:00 clojurebot: http://gist.guthub.com

13:00 TimMc: feh

13:02 OK, I think I fixed it (in privmsg).

13:04 rpg: dnolen: https://gist.github.com/1152035 --- I see what I'm doing wrong, but not how to do it right...

13:04 (Fogus & Houser book introduces "&rest" arguments, but w/o (AFAICT) an example of their idiomatic usage...)

13:07 dnolen: rpg: you should add your datatype + the case that fails to yr gist.

13:09 rpg: dnolen: OK, done....

13:10 dnolen: But I think all I need is an example of a function that takes an arbitrary number of arguments through the use of &, and processes them as, e.g., Lisp's +....

13:10 TimMc: rpg: Idiomatically, I'd probably define add to use reduce with a base value. :-)

13:11 rpg: TimMc: I was going to do that, but then I realized "I should understand how to unpack an &rest argument, even if this isn't the best case for it."

13:11 TimMc: *nod*

13:11 dnolen: rpg: consider this

13:12 ,((fn [a b & c]) 1 2 nil)

13:12 clojurebot: nil

13:12 rpg: TimMc: And I want to know what that "no message" means....

13:12 dnolen: ,((fn [a b & c] [a b c]) 1 2 nil)

13:12 clojurebot: [1 2 (nil)]

13:12 TimMc: Oh, I see the problem. But I'll be quiet.

13:12 dnolen: rpg: ^ this is what is happening to you.

13:12 raek: rpg: what is the type of the exception?

13:12 rpg: also: (.printStackTrace *e)

13:12 rpg: raek: Error in Clojure process 1: No message. (maybe this is a SLIME confusion?)

13:13 TimMc: rpg: In REPL I get an NPE.

13:13 raek: hrm. you should get a stack trace in slime

13:13 dnolen: ,(nil? '(nil))

13:13 clojurebot: false

13:13 rpg: dnolen: Right. I need the equivalent of Lisp's APPLY

13:13 raek: rpg: it's called apply in clojure too

13:14 dnolen: rpg: you have apply.

13:15 rpg: dnolen: Thanks! That does it....

13:15 raek: rpg: you also want to check for seq or empty?. (if (empty? x) ... ...)

13:15 TimMc: You've had apply all along, Dorothy.

13:15 raek: ,(empty? ())

13:15 clojurebot: true

13:15 raek: ,(nil? ())

13:15 clojurebot: false

13:15 arohner: anyone here use fnparse?

13:16 rpg: TimMc: Right. I'm trying to use the Fogus and Howard book and having some trouble....

13:16 Possibly it's not a good fit for me...

13:16 TimMc: rpg: Basically, you need apply anytime you write a recursive function with restargs.

13:16 rpg: TimMc: Right. Hence my remark that it would have been appropriate to introduce that topic (or a pointer thereto) when introducing restargs in the book....

13:17 TimMc: Indeed.

13:17 joly: arohner: I did a little with fnparse recently, pretty small though

13:17 arohner: joly: do you understand how followed-by works?

13:17 TimMc: Hmm, I don't see fogus in here...

13:18 chouser: Howard's here though

13:18 rpg: raek: Should I be using empty? in preference to nil?

13:18 dnolen: heh

13:18 chouser: :-)

13:18 dnolen: ,(nil? ())

13:18 chouser: rpg: not everything that is empty? is nil?

13:18 clojurebot: false

13:19 raek: rpg: yes. there are seqable objects that haven't desided if theey're going to be nil

13:19 joly: arohner: haven't used that, but it sounds like it might be the lookahead operator of PEGs

13:20 raek: rpg: http://kotka.de/blog/2011/06/On_types.html

13:20 joly: arohner: I would expect it to match the subrule but not consume it

13:20 arohner: but I'd want it tested before you quote me on that ;)

13:21 rpg: raek: I was confused by being told that the seq API is just first and rest.... In particular, not empty? So what's the API for "there is no rest"?

13:22 (nil? <seq>) right?

13:22 raek: rpg: almost. (nil? (seq x))

13:22 which is what empty? is defined as

13:23 arohner: what about followed-by is confusing?

13:23 arohner: raek: I just don't understand how it works

13:24 joly: arohner: the docstring for followed-by confirms it. It'll match a subrule but not consume it

13:24 arohner: right, so how do I use that?

13:24 (conc (rep* anything) (followed-by "foo") (lit-conc-seq "foo"))?

13:25 or, more concretely, how would I emulate #".*foo"?

13:25 raek: it's lookahead. (def a (lit "x")) (def b (lit "y")) (def c (followed-by a b))

13:26 this matches "x", but only when "y" follows. "y" remains in the remainder

13:26 arohner: raek: your example followed-by takes two arguments. the fn takes one

13:26 so (conc a (followed-by b))?

13:26 rpg: raek, dnolen: thanks.

13:27 raek: hrm, in the api example it takes two... :/

13:27 joly: the code for followed-by has one arg, but for some reason the api mentions 2

13:27 rpg: chouser: In the Joy of Clojure, on p. 27 you introduce &restargs --- in a new edition it might be helpful to point the reader to some treatment of how to manipulate the restarg sequence idiomatically....

13:27 raek: looks like it justs stores the state, matches and then restores the state

13:27 rpg: chouser: Probably just a forward reference....

13:28 raek: so (conc a (followed-by b)) looks like the way to use it, when reading the source

13:29 followed-by seems to behave as if it would be named "match-but-do-not-consume"

13:29 arohner: raek, joly: ok, thanks

13:30 chouser: rpg: good point, thanks.

13:30 In fact, it looks like we never really give apply sufficient direct treatment. The fact that it is lazy for example seems to never be mentioned.

13:30 rpg: BTW, since Clojure is a Lisp-1, it might well be a Bad Thing to call your restarg "rest," right?

13:31 technomancy: rpg: for a small function it's usually not a problem

13:31 chouser: rpg: 'more' is perhaps the most common name. 'rest' works as long as you're careful never to try to then use 'rest' as a function.

13:31 technomancy: the errors you get for accidentally shadowing are pretty obvious

13:32 rpg: technomancy: but in the case of restargs, where you might well be unpacking a sequence.... I just mention it because there was an example on the web where someone (as I, a lisp-2 user, did) made the restarg "rest".

13:33 raek: arohner: have you opened an issue for the doc error?

13:33 technomancy: rpg: it's not very common to explicitly call rest as a function since you usually just destructure those things away

13:33 rpg: That would have worked poorly for this case where the function is processing the restarg seq....

13:33 arohner: raek: no, I don't think fnparse is being actively maintained

13:34 rpg: technomancy: This is making me more and more convinced that I need to find a good example of idiomatic use of a restarg.....

13:34 (or multiple examples...)

13:35 dbushenko: hi all!

13:35 technomancy: we call rest about ten times in a codebase of ~20kloc

13:36 dbushenko: is it possible to make hiccup generate just a part of an html-page, I mean without the headers like "<html><body>"

13:36 pjstadig: it makes much more sense to do something like item & items

13:36 instead of using a generic variable

13:49 thorwil: dbushenko: yes, easily

13:49 dbushenko: thorwil: oh, really? how?

13:50 thorwil: dbushenko: like the very first example on https://github.com/weavejester/hiccup#readme ;)

13:51 dbushenko: OMG... how could I miss that?

13:51 thanks!

13:55 srid: is there one for css representation?

13:56 rpg: technomancy: wrt 'rest', if you don't call it, what's the idiomatic alternative? I think in my case, probably 'reduce'....

13:56 thorwil: srid: see CSS-style sugar at https://github.com/weavejester/hiccup/wiki/Syntax

13:57 srid: or do you mean a way to generate the CSS? there are at least 2 clojure libraries for that (i don't recall the names right now)

14:02 arohner: srid: cssgen

14:09 srid: yes, cssgen fits the description.

14:10 technomancy: ,((juxt (fn [[_ & rest]] rest) (fn [x] (rest x))) (range 10))

14:10 clojurebot: [(1 2 3 4 5 ...) (1 2 3 4 5 ...)]

14:11 technomancy: rpg: ^

14:11 it depends on the context, but you can usually fold it into a destructuring call above

14:19 rpg: technomancy: I guess what I don't get is the way to distinguish the basis case from the recursion. I suppose (def ([x y] ..) ([x y & rest] ...)

14:21 New question: is there some way that I can find out about the math-related protocols? (I'm learning some clojure while relearning some complex algebra...)

14:21 So I know there's a fragmentary complex number library, but I want to avoid it for pedagogical reasons....

14:24 kephale: is there a way to find out the memory footprint of a hash-map? where a hacky approximation would be (count (str my-map))

14:32 cemerick: kephale: In general, no.

14:33 Profiling tools provide some approximation, but they can be off too, especially when things like direct buffers, weak references, etc. are involved.

14:35 symbole: Doesn't PersistentMap contain all its data? So looking at the object size would give an approximation?

14:38 amalloy: no

14:38 not a good one, anyway

14:39 arohner: symbole: you'd have to use a memory profiler to find the real size

14:40 amalloy: most objects have more than one reference to them; how does the memory for them get counted? version X of my 1M-element hash-map gets a new key assoc'ed in, creating version Y

14:40 does version Y take up as much memory as X, plus a little for new items? no, it mostly just takes up a small chunk of what's used by X

14:43 kephale: hrm i see… well, for all intents and purposes it is just a single map (the previous version is discarded as soon as the new one is created)

14:43 rpg: Can someone point me to a discussion of how to take a class of mine (that's mathematical) and extend the = protocol over it?

14:43 kephale: cemerick: i do see what you're saying about the complications though

14:45 technomancy: rpg: = is not currently a protocol

14:45 you'll have to look at how clojure.lang.Util/equiv is implemented

14:45 cemerick: kephale: determining sizeof for simple Java objects is nontrivial; what if your map had a lazy seq in it, etc? It's not a simple question. :-)

14:46 kephale: cemerick: oh, i don't expect it to be trivial, but in this case nothing is actually lazy anymore

14:46 rpg: technomancy: Thanks! Here's a more general question: We see discussions of how to implement protocols in our types and libraries. How do we find protocols in the wild that we should extend? I suppose the clojure-contrib site?

14:47 danlarkin: what.

14:47 kephale: but maybe i just need to poke around the java Object API a bit

14:48 symbole: Can't profilers track down references such that one could find all the references that make up a map? I remember using a profiler that would give me all references from object A and to object A.

14:49 I might be imagining things.

14:50 kephale: symbole: know of anyway to do that dynamically? reference counts might be sufficient

14:50 cemerick: Yes, profilers can provide instance counts as well as an approximation of memory allocation.

14:50 amalloy: so what? how much memory is taken up by a one-element vector that contains a 1MB object in it somewhere?

14:51 a few bytes, or one meg? what if three other people also have a pointer to that object?

14:51 raek: does anyone know of any ClojureScript wrappers for any of the Google Closure libraries?

14:52 amalloy: it's a problem without a well-defined answer, let alone a well-known solution

14:52 ibdknox: raek: I've started on pinot. http://github.com/ibdknox/pinot

14:53 rpg: technomancy: Is this an odd thing to want to do? Define a struct that might be, e.g., equivalent to a number? I was just doing my complex numbers and it seemed like I would want a complex number with no imaginary part to be = to its real number equivalent....

14:54 technomancy: rpg: it's reasonable to want, but I don't know if Clojure's own numerics are open in such a way as to allow that

14:54 static public enum Category {INTEGER, FLOATING, DECIMAL, RATIO}; // <= not terribly promising

14:55 eventually in the promised land of Clojure-in-Clojure everything interesting (except IFn) will be an extensible protocol

14:55 we're still a ways away from that though

14:56 rpg: technomancy: ah. Thanks. that's helpful.... I just assumed that I could extend the equiv protocol by defining the real-part and imag-part accessors on numbers and then it seemed that clojure.lang.Util/equiv was the right way to stitch it all toegether.

14:56 dnolen: rpg: if you want to understand the common protocols you need to look at the Clojure source.

14:57 symbole: kephale: I don't.

14:57 rpg: dnolen: I was just wondering if there was a table of protocols or something. Sounds like "no," is the answer...

14:57 technomancy: there aren't too many protocols in clojure itself yet as the move towards self-hosting has only barely begun

14:57 the last stable release was the first to even have protocol support at all

14:57 dnolen: rpg: I meant Java interfaces. but getting familiar with them via the source is fine.

14:57 rpg: technomancy, dnolen: thanks. That helps me understand a bit....

14:58 technomancy: so naturally it's going to take a few releases before it takes advantage of them internally

14:58 rpg: Can I extend a protocol like my real and imaginary parts to the built in numbers?

14:59 dnolen: rpg: try equiv.

15:00 kephale: cemerick: any tip on which profiler would be efficient for very frequently estimating the memory allocation (possibly at the cost of accuracy)?

15:00 cemerick: kephale: VisualVM is a reasonable first choice. You already have it installed.

15:00 rpg: Thanks, all. I must run out for a moment. You have been very helpful. Cheers!

15:02 kephale: cemerick: ah, yeah I've used that one in GUI mode, but never called it directly from clojure. FYI, by frequent I mean on the order of 1k checks per second

15:03 presumably there will be some slowdown though, it isn't a real-time application

15:03 cemerick: kephale: "calling it directly from clojure" doesn't make any sense; profilers aren't *called*, they receive telemetry from the VM itself.

15:04 kephale: cemerick: ah, then it wont work. i need to get the estimates during run-time

15:05 * cemerick *boggles*

15:05 cemerick: kephale: all profilers operate at runtime.

15:06 kephale: cemerick: you probably know the code I'm working with, Clojush

15:06 cemerick: heh, Lee's GP stuff?

15:06 kephale: <- kyle

15:06 yeah

15:07 so the interpreter is just a map, and thus far we just evaluate them for N instructions

15:07 I'd like to run the Push interpreter forever, but detect if it is going to overflow the heap

15:08 cemerick: I've never looked at Clojush, so I don't know anything about its internals.

15:09 The bottom line with profilers is that you attach one to a JVM process at runtime, and it captures data about its operation — # of allocations, live instances, an approximation of memory allocation, runtime perf, etc.

15:09 You can't control profilers from "userland" code (at least, I'm not aware of any method of doing so).

15:11 kephale: hrm… i'll have to poke around at calling visualvm from within clojure, i don't see why one couldn't do it from userland

15:12 cemerick: kephale: Seriously, you can't "call" a profiler. It provides no library, no API.

15:13 kephale: cemerick: worst case : P http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Robot.html

15:14 cemerick: kephale: sorry, you have me baffled. :-)

15:15 kephale: cemerick: thanks though, i think i'm on the right track now, i'll keep you posted… visualvm does seem to have an api though (designed for plugins)

15:16 cemerick: oh, sure, but that plugin code will be running in a different JVM than the one you're profiling

15:16 Anyway…good luck. Say hi to Lee for me. :-)

15:16 kephale: mmm will do

15:20 TimMc: kephale: When the JVM runs out of heap, does it throw an Error of some sort?

15:21 amalloy: anyone know of a library that will analyze a clojure expr and determine which variables are "free" in the closure sense? i'm playing with the idea of turning (fn [x] (conj [:foo :bar] x)) into (let [v [:foo :bar]] (fn [x] (conj v x)))

15:22 kephale: TimMc: yes, i guess catching the heap exception might work. i haven't tested that yet, but the concern is that there are a bunch of agents possibly overflowing the heap. i think your instinct is right, that should be the first thing to test

15:24 amalloy: (and i speculate that knowing what variables are free would help me do that, by pulling expressions about them up as high as possible)

15:25 cemerick: amalloy: A Clojure analyzer will do. :-P

15:25 amalloy: cemerick: i don't think i follow

15:30 dnolen: amalloy: hmm seems like you write a fairly simple core.logic program to do something like that ;)

15:36 PPPaul: can 'join' do something similar as 'index' if i join a table on itself on 1 key?

15:41 amalloy: dnolen: aha, interesting point. damn it, now i have a reason to learn core.logic instead of just letting all the news blow by

15:50 gridaphobe: does anyone know what's happening to clojure.contrib.http.agent in 1.3?

15:51 dnolen: amalloy: would be fun to figure out, thinking something along these lines, https://gist.github.com/1152441

15:52 amalloy: since running backwards isn't so important here, could probably use conda/u and it would be pretty efficient.

15:53 amalloy: dnolen: i'm afraid i'm a fish getting tips about space exploration, here. none of that means anything yet. i've got a lot of basics to catch up on first

16:05 fwiw though i think you'd have to operate on let*/fn*, since you want to look at the macroexpanded tree

16:06 dnolen: amalloy: you'd probably want to handle all cases since I don't think you'd want to depend on where in the macroexpansion you are.

16:07 amalloy: dnolen: you don't have to; (defmacro fold-constants [form] (let [expanded (macroexpand-all form)] ...))

16:08 dnolen: amalloy: macroexpand-all is the devil

16:08 amalloy: aw, i thought flatten was the devil. but i can see how they might be related

16:08 dnolen: unless it's just for analysis.

16:08 any macroexpansion inside of a macro forces users of your macro to consider macroexpansion order. ARGH

16:11 amalloy: i'm not sure i get it. as long as i'm not doing something weird like expanding just parts of the expression, isn't it the same as what the compiler would do later anyway? then i work with the post-expanded form and do semantic-preserving operations like constant folding; so it should be equivalent to having no macroexpand at all

16:11 ibdknox: does anyone know where (show) ended up from repl.utils?

16:14 dnolen: amalloy: heh, it's usually not a big deal :) however things get tricky in my experience when the macro involves code-walking.

16:15 amalloy: well, yes. i suspect any macro that involves code-walking (as this one would have to) will get complex no matter what else you do

16:18 PPPaul: how do i limit what fields are used when doing a clojure.set/join ???

16:23 TimMc: PPPaul: Take a look at the last example of http://clojuredocs.org/clojure_core/clojure.set/join

16:23 upwardindex: In common lisp when I wanted recompile my project and have a fresh start i would restart-inferior-lisp and (require 'project). What is the equivalent in clojure? (restart-inferior-lisp says No inferior lisp)

16:23 TimMc: THat might do the trick.

16:25 technomancy: upwardindex: how did you start swank?

16:25 upwardindex: technomancy: M-x clojure-jack-in

16:26 technomancy: Is that the preferred way?

16:26 technomancy: upwardindex: that's fine. you can kill the *swank* buffer and re-run clojure-jack-in.

16:26 upwardindex: technomancy: ah so simple, thank you!

16:26 symbole: Will Clojure be at JavaOne?

16:27 technomancy: upwardindex: you should be able to just re-run clojure-jack-in, but there's a bug in some versions of emacs that makes it more reliable if you just kill *swank* first

16:28 next version of clojure-mode will fix that

16:29 TimMc: PPPaul: Pass a keymap in with identical keys and values.

16:33 upwardindex: technomancy: yes I believe I ended up with 2 swanks when just rerunning clojure jack-in

16:33 technomancy: it's on the hit list.

16:34 * amalloy lives in fear of technomancy's hit list

16:36 ibdknox: amalloy: one of us are gonna end up on it one day...

16:37 technomancy: pew pew pew: http://fuckyeahfingerguns.tumblr.com/

16:37 ibdknox: lol

16:49 aaelony: I have a silly question. How can I issue a unix system call from clojure? I am trying the following but still not quite there....

16:49 (reader (BufferedInputStream. (.getInputStream (.exec (Runtime/getRuntime) "ls -l" ) )))

16:51 technomancy: aaelony: it's impossible afaict to stream input to a subprocess on the JVM

16:51 aaelony: without crazy JNI stuff anyway; JRuby manages it somehow

16:51 amalloy: technomancy: whattttt, i don't think that's true at all

16:51 technomancy: oh nm; you are talking about getting output from the process

16:52 amalloy: all the APIs I've seen only let you use a byte array or a stream as stdin

16:52 *or a string

16:52 aaelony: just a simple "ls -l" given that we are on a *nix box

16:52 technomancy: (doc clojure.java.shell/sh)

16:52 clojurebot: I don't understand.

16:52 technomancy: wat

16:52 ,(doc clojure.java.shell/sh)

16:52 clojurebot: Cool story bro.

16:52 aaelony: where "ls -l" could be any valid command

16:52 technomancy: clojurebot: botsmack

16:52 clojurebot: Owww!

16:53 * technomancy gloats

16:53 amalloy: $javadoc Process getOutputStream

16:53 lazybot: http://download.oracle.com/javase/6/docs/api/java/lang/Process.html#getOutputStream()

16:53 Scriptor: http://clojuredocs.org/clojure_core/clojure.java.shell/sh

16:53 Raynes: &(doc clojure.java.shell/sh)

16:53 lazybot: ⇒ "([& args]); Passes the given strings to Runtime.exec() to launch a sub-process. Options are :in may be given followed by a String or byte array specifying input to be fed to the sub-process's stdin. :in-enc option may be given followed by a String, used as a charac... http://gist.github.com/1152603

16:53 * Raynes files his nails arrogantly.

16:54 aaelony: looks cool.. will try it out :)

16:54 amalloy: technomancy: short version: Runtime/exec returns a Process; a Process has an outputstream you can send bytes to

16:54 technomancy: amalloy: hum... interesting.

16:55 I believe I had problems when I tried that

16:55 but I don't remember the details

16:57 aaelony: hmmm... so how would I actually see output from an "ls -l" ?

16:57 this doesn't do it: (clojure.java.shell/sh :in "/bin/ls -l")

16:58 amalloy: (:out (clojure.java.shell/sh "/bin/ls" "-l")) iirc

16:58 yeah

16:59 aaelony: cool, also found this http://clojuredocs.org/clojure_core/clojure.java.shell/sh

16:59 amalloy: although, wait, what? you want to use ls to look at a directory? please tell me this is just a contrived example and not your actual use case

17:00 aaelony: contrived example

17:00 technomancy: don't go judging now

17:00 aaelony: haha

17:00 ibdknox: amalloy: the shell is the only thing you can trust...

17:01 amalloy: I try to do everything relating to IO that way ;)

17:03 aaelony: btw, this is awesome. works really well.

17:04 amalloy: ibdknox: great, now you've created a shell addict

17:04 ibdknox: BWAHAHAH

17:04 I will burn this world to the ground ;)

17:05 one ridiculous shell invoking program at a time

17:05 aaelony: beats head-scratching over archaic java deprecated library classes... nice executable, very nice...

17:06 Hodapp: 9_9

17:07 ibdknox: aaelony: what are you actually trying to do?

17:11 aaelony: ibdknox: just need a simple way of querying an S3 bucket. Also pulling files down, and pushing files back up.

17:11 was using org.jets3t.service but its turning out to be a huge pain

17:12 rest calls reply that buckets are empty when I know they are not, etc..

17:13 ibdknox: aaelony: I have something in Noir that does some basic S3 stuff

17:13 and I know it works

17:14 it also uses jets3t though

17:14 aaelony: cool, pls pass it on

17:14 ibdknox: https://github.com/ibdknox/noir/blob/master/src/noir/util/s3.clj

17:14 not much there lol

17:15 it was just whatever I needed for image uploading on typewire

17:15 aaelony: basically the listObjects method is too opaque for me (http://jets3t.s3.amazonaws.com/api/org/jets3t/service/S3Service.html#listObjects%28org.jets3t.service.model.S3Bucket,%20java.lang.String,%20java.lang.String%29)

17:15 cool thanks, will take a look

17:16 looks nice. I admit I haven't used noir yet

17:16 ibdknox: aaelony: it's awesome ;)

17:16 haha

17:17 aaelony: looks nice

17:17 amalloy: never admit that you don't use noir. the cool kids will never let you live it down

17:17 i'm a broken shell of a man after my confession

17:17 * ibdknox shuns amalloy

17:17 aaelony: haha, will be trying it shortly

17:19 what is the most lightweight way to get the s3 functionality?

17:19 ibdknox: copy that file

17:19 lol

17:20 I didn't separate it out

17:20 that one is probably one that should be though

17:20 aaelony: haha... hell I'll try the whole kit...

17:20 ibdknox: since it's not noir specfic

17:25 aaelony: ibdknox: so to list files in a bucket, I wrap list somehow? I likely need an idiot proof example...

17:27 rpg: Is there a way (akin to instance? ) to check if an object participates in a protocol?

17:27 ibdknox: ,(doc satisfies)

17:27 clojurebot: It's greek to me.

17:27 ibdknox: ,(doc satisfies?)

17:27 clojurebot: "([protocol x]); Returns true if x satisfies the protocol"

17:28 ibdknox: aaelony: I'm looking

17:28 aaelony: ibdknox: cool

17:30 ibdknox: (with-s3 {:secret-key "blah" :access-key "blah"} (list "somebucket"))

17:30 should work

17:30 basically just wrap all of your calls in that with-s3 macro

17:31 aaelony: cool

17:36 rpg: ibdknox: thanks!

17:40 can defrecord take a docstring? The clojure.org doc suggests not...

17:41 amalloy: i don't think so. where would it go? classes don't have metadata

17:56 TimMc: And I guess defrecord doesn't introduce a var.

17:58 ,(macroexpand-1 '(defn foo "hello" [n] n))

17:58 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

17:58 TimMc: aw

17:58 scottj: anyone setup their emacs to use inferior-lisp for cljs files but slime for .clj files?

18:01 TimMc: Anyway, that expands to (def foo (.withMeta (clojure.core/fn foo ([n] n)) (.meta (var foo))))

18:02 ...which confuses the hell out of me. The initialization expression apparently use the var it is initializing?

18:02 amalloy: TimMc: i agree, it's madness

18:03 TimMc: I suppose that means that the compiler handles the var itself and then goes back and initializes it.

18:03 amalloy: not afaict. this causes behavior that seems to me like a bug

18:04 a couple months ago seancorfield (i think) had an issue where when he redef'd a var with new meta, the meta didn't "stick" until the second time

18:05 TimMc: Anyhow, the :doc sticks to the var, not the fn -- that's what I was originally investigating.

18:05 amalloy: because (.meta (var foo)) was sneaking the old meta back onto it or something

18:05 TimMc: yuck

18:06 Anyway, hometimes.

18:06 I'll check backlog for any rebuttals, etc. :-)

19:06 upwardindex: Elementary question here, I get the dreaded "Can only recur from tail" on this but I don't understand this seems to me to be ok: http://pastebin.com/PjNgbYs2

19:09 amalloy: you're not returning the result of recur

19:09 you're returning one plus that result

19:10 thus, the recur is not in tail position

19:10 upwardindex: ahhh ok thank you!

19:10 amalloy: once you fix that you'll want to fix the infinite loop

19:11 ibdknox: lol

19:11 amalloy: upwardindex: you come from common lisp, right?

19:11 ibdknox: ,(doc next)

19:11 clojurebot: "([coll]); Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil."

19:11 upwardindex: amalloy: yes

19:12 ibdknox: empty list is false in CL, right?

19:12 amalloy: the short answer is to use next instead of rest (in this case; not in all cases), because an empty list is not the same as nil

19:12 upwardindex: ibdknox: that is right

19:12 amalloy: and next implicitly calls seq on its argument, which converts empty seqs to nil

19:12 upwardindex: amalloy: ah ok rest will return an empty list at the end and next will return nil

19:13 ibdknox: yep

19:13 amalloy: &((juxt rest next) [1])

19:13 lazybot: ⇒ [() nil]

19:30 upwardindex: amalloy: Are you the one who created 4clojure?

19:30 amalloy: kinda

19:30 i'm the current maintainer, and was contributing about 50/50 as it was being built

19:30 upwardindex: amalloy: Should there be a restriction on apply for number 24?

19:31 amalloy: i don't see why. learning that you can use apply is good for you

19:32 "ohhhh, *that's* why clojure doesn't have a built-in `sum` operator"

19:32 ibdknox: amalloy: who built the other half?

19:32 amalloy: dbyrne

19:32 upwardindex: amalloy: I guess, just depends on the objective of the exercise. Most previous numbers put restrictions on functions that are good to learn.

20:10 amalloy: upwardindex: i have to wonder about the person who found a 120-character solution to "sum it all up"

20:11 upwardindex: amalloy: very descriptive variable names perhaps ;)

20:15 amalloy: or if spaces are counted, maybe its a matter of placing parenthesis on their own line (like you would do in java for example)

20:15 amalloy: nah, we only count real characters

20:16 and whoever it was, they did it before we started saving solutions; i just checked and nobody's solution is that long

20:16 so i guess we'll never know

20:49 tufflax: what a shame, we probably could have learned a lot from it

21:18 ndimiduk: i have a question about extending protocols

21:19 i'd like to augment the clojure.java.io/IOFactory for String

21:19 adding support for a new URI scheme

21:20 which mean, in effect, i want to call (extend String io/IOFactory ...) such that i can locally bind the existing implementation of :make-input-stream so that i can call it in the negative case

21:21 it looks like i can use find-protocol-method to do this

21:21 but i'm troubled because, after (require 'clojure.java.io)

21:21 err

21:21 (require '[clojure.java.io)

21:21 :as io])

21:22 (= (find-protocol-method io/IOFactory :make-input-stream String) (find-protocol-method io/IOFactory :make-input-stream Object)) => true

21:23 i can invoke (io/make-input-stream "path/to/file") and that works

21:24 but invoking ((find-protocol-method io/IOFactory :make-input-stream String) "path/to/file" {}) falls back on the Object impl

21:24 what gives?

22:00 rpg: I am having a problem with the use of defprotocol and defrecord as illustrated in https://gist.github.com/1153123 A call to (modulus (complex. 1 1)) there bombs, but what seems like the exact same code as (mod2 (complex. 1 1)) works fine.

22:01 For some reason, when I use the defrecord + defprotocol I end up trying to interpret an integer as a function (as far as I can tell from the error message). Can anyone see my mistake?

22:02 I'm completely stumped by this, and my attempts to trace do me no good.

22:12 amalloy: rpg: shadowed symbols

22:13 rpg: amalloy: oh, dear. Is my lisp-2 heritage showing?

22:13 amalloy: nah, it's a clojure-specific thing

22:13 rpg: what's shadowed?

22:13 amalloy: inside the body of (defrecord Foo [value]), the symbol 'value maps to the value field of the record

22:13 so (real c) is calling the real-part field of the record

22:14 rather than the protocol-function real

22:14 rpg: amalloy: Ah. So I had better rename the real and imag fields, so that they don't collide with the accessor names, right?

22:14 amalloy: right

22:15 this also implies that you can implement the accessor as just (real [c] real)

22:16 rpg: But if I do that, I can't reference the accessor in the body, right?

22:17 amalloy: yeah, don't use the same name. i was just pointing out that you don't need to call (:real c)

22:17 rpg: so I'm better off with something like (defrecord complex [real-part imag-part] CPARTS (real [c] real-part))

22:17 amalloy: right

22:18 is just what i'd write

22:18 rpg: I NEVER would have figured that out. Thanks a million!

22:18 amalloy: i usually forget about that feature of records too

22:18 but once the stacktrace appears...

22:22 mjonsson: rpg: btw, you may want to use Math.atan2 instead of Math.atan

22:24 rpg: mjonsson: Thanks! I hadn't known about this (I'm not much of a hand with Java).

22:24 amalloy: Math also has Math.sqrt

22:27 srid: what is the most interesting use of lazy seq in clojure?

22:34 amalloy: uh. i think the answer to that is "clojure"

22:38 amac: srid: I would say the idea of being able to process infinite sets of data without having to manage how/when the data is created or consumed.

22:39 a good example that's used in sicp is the sieve of eratosthenes

22:39 srid: ah ok, an example is what I was looking for.

22:40 amac: basically its a function that conceptualizes every prime number (infinetly many) but only produces the next result when its needed to be consumed

22:41 ps -- sicp is a good book if you want to understand why functional languages (lisp in particular) are designed the way they are

22:44 srid: i read 3.5 chapters of sicp a few years ago, actually. that's when I got a feel for lisp.

23:19 * srid didn't fully understand the quicksort example in TJoC, but skips over it to complete the book sooner than later (so he gets to write code!).

23:26 srid: interesting. noir is not listed in http://disclojure.org/projects/

23:27 scottj: noir is newish

23:27 tbatchelli: srid, that page need a serious, serious update

23:27 :(

23:27 srid: so, what is the currently popular web framework for clojure?

23:28 scottj: noir and compojure or just plain ring

23:28 kephale: moustache is another

23:28 pcavs: srid: messing around with noir, and I find it alright

23:28 tomoj: routing looks funky

23:28 pcavs: in noir?

23:28 srid: tbatchelli - i wonder why http://clojars.org/ doesn't have categorization of popular libraries.

23:29 tomoj: yeah

23:29 pcavs: tomoj: or in ring in general?

23:29 tomoj: noir

23:29 there is no routing in ring, is there?

23:29 scottj: srid: http://www.clojure-toolbox.com/

23:29 tbatchelli: right, http://www.clojure-toolbox.com/

23:29 srid: ah nice.

23:29 scottj: of course noir isn't on there either :)

23:29 tomoj: I guess it is supposed to be for simple stuff anyway so strings are OK?

23:29 srid: wait, is this manually maintained or auto updated from clojars?

23:30 tbatchelli: well, people keep putting awesome libraries out every week, it's hard to keep up with that!

23:30 pcavs: tomoj: noir routing is okay for basic stuff, haven't really pushed it around much yet

23:30 srid: tbatchelli - heh, neither does that site have noir.

23:30 tbatchelli: srid, noir is very new

23:31 noir is nice, but it pays to know compojure and ring

23:31 srid: https://github.com/hlship/cascade is advertised as webframework for "idiomatic" clojure

23:32 tomoj: "Cascade templates are an embedded DSL directly in the Clojure code"

23:32 is this really idiomatic clojure? seems like _popular_ clojure

23:32 is the popular idiomatic?

23:33 pcavs: srid: interesting, uses buildr too it looks like

23:34 buildr=gradle, wow how did I screw that one up

23:34 tbatchelli: srid, although this article doesn't include noir, it is a very good survey of what's popular and available http://brehaut.net/blog/2011/ring_introduction

23:35 scottj: the only problem with it being it leaves off slice :)

23:35 tomoj: I guess you can write idiomatic clojure even when it is a bad idea (not that it necessarily is in that particular case..)

23:36 scottj: there used to be a graphic that showed the different layers and options for web dev

23:36 srid: tbatchelli - excellent, thanks!

23:47 scottj: is there a standard clj->js function? (cljs)

Logging service provided by n01se.net