#clojure log - Nov 23 2011

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

0:00 alexbaranosky: amalloy: any interest in working on Midje? we could use your skills :)

0:00 amalloy: alexbaranosky: the case i'm concerned about is (.foo IBar b) => 10 (.bar IBar b) => 9

0:01 alexbaranosky: amalloy: I wonder what Midje does now for the fn analog of that? Probably just uses the last defined provided

0:02 devn: midje is great.

0:02 alexbaranosky: amalloy: oop misread

0:02 hey devn

0:02 * devn waves

0:03 alexbaranosky: devn: I'm the dude you were talking about pair programming and philosophy with first day of the Conj

0:03 devn: oh, right! how's it going?

0:03 alexbaranosky: amalloy: I see your point now and will add it to the notes I'm accruing on the Github Issue

0:03 devn: good!

0:04 devn: alexbaranosky: working on midje, eh?

0:05 alexbaranosky: dev: yeah, I've got three features on my list of things that seem most useful:

0:06 devn: colorized console, auto/lazy-test powers, mocking java methods (including static ones)

0:06 if you've got the burning urge to do any, that could be arranged :)

0:07 devn: If I commit to anything else I think I might implode

0:07 I absolutely want to, but wanting does give me extra hours :(

0:07 alexbaranosky: me too, he

0:07 reiddraper: anyone know if there's a quickcheck for clojure that's actively maintained?

0:07 i've found a couple but they seem abandoned

0:08 alexbaranosky: well, you can always give more feedback on GitHub issues, or to me; that stuff is really useful

0:08 devn: reiddraper: how abandoned is abandoned in your estimation?

0:08 reiddraper: devn: no commits in 2011

0:08 amalloy: reiddraper: halloway has test.generative, which i think is similar

0:08 devn: alexbaranosky: yeah, I will definitely do that. I haven't used midje a *ton*, but when I have used it I've really enjoyed it.

0:08 reiddraper: so clojurecheck is out of the picture, yes?

0:09 amalloy: and i think he's working on it

0:09 alexbaranosky: devn: we don't get enough people adding their two cents to issues imho

0:09 reiddraper: devn: that's the one i was looking at, perhaps it's great and just hasn't needed anything since 2010

0:10 devn: alexbaranosky: i have spent a fair amount of time on the wiki for midje. next time I'll peek at issues. :)

0:10 reiddraper: amalloy: I'll look more at test.generative. It wasn't well documented and I didn't dig further than that

0:11 devn: reiddraper: haskell ports seem to have the property of standing the test of time

0:11 reiddraper: but they require some care and feeding

0:11 reiddraper: have you looked at test.generative?

0:12 reiddraper: devn: just enough to see there weren't many docs. should look more.

0:12 devn: reiddraper: I think you're right -- there aren't many docs, but I believe there are examples under src/

0:12 reiddraper: devn: i coudldn't tell if it indented to be like quickcheck, or just a random input testing facility

0:12 devn: reiddraper: also, fogus' libraries clache and unk use test.generative, so that might be helpful

0:13 reiddraper: honestly I don't know, but if you check out fogus' projects that might give you the answer you're looking for

0:13 reiddraper: devn: ok, will take a look at those as well. I'm particularly interested in the "simplification" of failing cases that haskell/erlang QC provide

0:14 I suppose there's always the possibility of using a Java lib too :)

0:14 bartj: I thought re-seq returned a sequence of matches

0:15 brehaut: ,(re-seq #"a+" "aababaabaababbbba")

0:15 clojurebot: ("aa" "a" "aa" "aa" "a" ...)

0:15 bartj: , (re-seq #"(?i)\b(Mission Road|Bangalore)\b" "45, Mission Road, Bangalore")

0:15 clojurebot: (["Mission Road" "Mission Road"] ["Bangalore" "Bangalore"])

0:15 bartj: but, it seems to return a sequence of matches

0:15 where the matches seem to be vectors!

0:16 brehaut, ?

0:16 brehaut: bartj: its because you have capture groups

0:16 devn: ,(doc re-groups)

0:16 clojurebot: "([m]); Returns the groups from the most recent match/find. If there are no nested groups, returns a string of the entire match. If there are nested groups, returns a vector of the groups, the first element being the entire match."

0:17 devn: ,(doc re-seq)

0:17 clojurebot: "([re s]); Returns a lazy sequence of successive matches of pattern in string, using java.util.regex.Matcher.find(), each such match processed with re-groups."

0:17 devn: "each element is processed with re-groups"

0:17 brehaut: ,(map first (re-seq #"(a+)" "abaabaaa"))

0:17 clojurebot: ("a" "aa" "aaa")

0:23 bartj: brehaut, devn cool, thanks

0:27 amalloy: can i just say, this kind of "you can't predict the return type" seems pretty evil to me?

0:32 tensorpudding: how does clojure do error handling?

0:32 can you specify your own errors?

0:32 amalloy: &(/ 1 0)

0:32 lazybot: java.lang.ArithmeticException: Divide by zero

0:32 amalloy: i created an error right there. awesome

0:32 tensorpudding: okay, so it uses java's exceptions

0:32 how do i throw an exception

0:32 how do i create new exceptions

0:33 amalloy: tensorpudding: i seem to recall you hate reading docs, right?

0:33 tensorpudding: is the only facility in java?

0:34 i skimmed the clojure docs but couldn't find anything talking about exceptions

0:36 alexbaranosky: &(throw (RuntimeException. "boom"))

0:36 lazybot: java.lang.RuntimeException: boom

0:37 alexbaranosky: tensorpudding: also checkout slingshot on github

0:37 tensorpudding: where is throw defined?

0:37 choffstein: If I am trying to upgrade a project to 1.3 and have a dependency that is still on 1.2, is there anything I can do to stop some conflicts?

0:37 tensorpudding: i didn't see it in the api docs

0:38 alexbaranosky: clojure.core??

0:38 lazybot: alexbaranosky: What are you, crazy? Of course not!

0:38 clojurebot: this is not IRC, this is #clojure. We aspire to better than that.

0:38 alexbaranosky: (doc throw)

0:38 clojurebot: It's greek to me.

0:38 amalloy: tensorpudding: the compiler

0:38 tensorpudding: sorry

0:38 i meant to say, which module is it in

0:39 alexbaranosky: clojurebot is pissed man

0:39 brehaut: tensorpudding: amalloy already told you: the compiler; its a special form

0:39 tensorpudding: oh

0:39 brehaut: http://clojure.org/special_forms#Special%20Forms--(throw%20expr)

0:40 choffstein: anyone use weavejester's hiccup library?

0:40 alexbaranosky: tensorpudding: http://clojuredocs.org/clojure_core/clojure.core/throw

0:40 amalloy: choffstein: most webapps use hiccup, though not all

0:41 tensorpudding: dang

0:41 choffstein: amalloy: yeah, I realized after typing it that it was a pretty stupid question

0:41 tensorpudding: i forgot

0:41 to check the clojuredocs instead of the api page on clojure.org

0:41 choffstein: I'm trying to figure out if its dependence on 1.2.0 is breaking my 1.3.0 move

0:42 amalloy: choffstein: probably not. if you have the latest hiccup you're fine

0:42 choffstein: I can't find which dependency is breaking. I'm getting a strange error: java.lang.IllegalStateException: Can't dynamically bind non-dynamic var: clojure.contrib.pprint/*format-str*

0:42 amalloy: even if it depends on 1.2, so long as it doesn't use contrib

0:44 that's pretty much what happens to everyone who tries to upgrade (including me).

0:44 tensorpudding: why does the api page on clojure.github.com not cover throw

0:44 amalloy: some dependency uses contrib, and old-style contrib isn't 1.3 compatible

0:45 brehaut: tensorpudding: because its not part of the api, its part of the compiler?

0:45 tensorpudding: hmm

0:45 i had assumed let was a special form

0:45 but it's a macro?

0:45 amalloy: so you have to track down who's using contrib, and update those

0:46 tensorpudding: brehaut, except clojuredocs has it

0:46 brehaut: let is a macro that wraps let* which is a special form

0:46 amalloy: try: $ lein pom && mvn dependency:tree

0:46 this will at least tell you about *one* of your deps that uses contrib

0:46 brehaut: tensorpudding: clojuredocs is not an autogenerated project, its a curated by humans

0:48 tensorpudding: well

0:48 it'd be more helpful if the info on clojuredocs were front-and-center on the clojure.org page

0:49 choffstein: amalloy: so does that mean I either need to a) fork the dep with the contrib dependency and try to move it to 1.3, b) not use the dep, or c) something else?

0:49 devn: tensorpudding: not always.

0:49 brehaut: tensorpudding: everything that makes clojuredocs great in some areas means its very weak in others

0:49 devn: tensorpudding: i agree, but it is not always the case that I want to see potentially mediocre example code. the clojure.org docs are very clear.

0:49 they describe intent, philosophy, etc.

0:49 clojuredocs is icing

0:49 amalloy: choffstein: often you can (c) use a more recent version of the dep that's already updated

0:50 tensorpudding: that's a reasonable point, that clojuredocs has possibly mediocre content, but it seems clearer and more helpful

0:50 devn: tensorpudding: yes, but now you probably see the issue: not everyone is looking for API docs

0:50 choffstein: I'm confused because none of my deps seem to depend on clojure-contrib :-\

0:51 devn: they could make relatively short documentation pages long and difficult

0:51 tensorpudding: you could always create a greasemonkey script or something that adds them to the page

0:51 tensorpudding: api docs are the main thing that i want when i go there now

0:51 i read the reference

0:52 devn: tensorpudding: why not just use clojure.repl?

0:52 ,(doc +)

0:52 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0. Does not auto-promote longs, will throw on overflow. See also: +'"

0:52 tensorpudding: i use doc 99% of the time

0:52 but it doesn't help if i don't know what i'm looking for

0:52 devn: tensorpudding: do you have an example? not trying to grill you, just trying to understand

0:52 tensorpudding: browsing vs. querying

0:52 well, i wanted to know how to throw an exception

0:53 turns out that you use throw, a special form

0:53 it wasn't in the api docs, i missed it

0:54 devn: tensorpudding: so you went to clojure.org and you weren't satisfied with the documentation there, so you went to clojuredocs?

0:54 tensorpudding: is that correct?

0:54 tensorpudding: well, clojuredocs was pointed out to me

0:55 for the second time

0:55 i had heard of it before

0:56 devn: tensorpudding: so you think clojure.org should prominently display clojuredocs.org for the purposes of additional information?

0:56 tensorpudding: no

0:56 devn: tensorpudding: sorry, I'm just trying to understand what might have made your life easier.

0:57 tensorpudding: i just really wanted throw to have appeared in the place i expected to find it, the docs

0:57 devn: tensorpudding: 1.4.0 looks like it's going to get some documentation love FWIW

0:58 tensorpudding: http://dev.clojure.org/display/design/Clojure+1.4+docstrings

0:58 tensorpudding: better docstrings would be nice

0:59 helpful exceptions would be a lot nicer

0:59 devn: tensorpudding: you're in luck! http://dev.clojure.org/display/design/Clojure+1.4+error+messages :)

0:59 tensorpudding: well, that's good news

1:00 devn: nothing is done yet, but those concerns have definitely been heard before and there is an effort to make people's lives a bit easier in clojure land

1:01 amalloy: we should elect devn as Chief Finder-of-Things From dev.clojure.org

1:01 devn: amalloy: I am sort of a librarian

1:03 amalloy: along those lines, I have a friend who thinks the idea of "architects" as they have been traditionally defined in large software development companies is wrong, but that what a lot of projects need is someone who knows the terrain, the papers to read, etc.

1:04 amalloy: it's an interesting thought. "team librarian" -- the guy who knows which library you should use because he's reviewed its code and kicked its tires.

1:06 tensorpudding: in the meantime, if i could suggest to you another tool you might use to avoid a trip to clojure.org: clojuredocs-client @ http://dev.clojure.org/display/design/Clojure+1.4+error+messages

1:06 woops: https://github.com/dakrone/clojuredocs-client

1:06 tensorpudding: i'll check it out

1:06 devn: you can include that in your project and query clojuredocs' api from the REPL

1:08 Raynes: $examples clojure.core/defmulti

1:08 lazybot: https://gist.github.com/1387995

1:08 clojurebot: eg, https://github.com/clojure/tools.logging is the new version of clojure.contrib.logging

1:08 Raynes: $cd defmulti

1:08 lazybot: clojure.core/defmulti: http://clojuredocs.org/v/1989

1:08 clojure.core/defmulti: http://clojuredocs.org/v/5452

1:08 Raynes: Or you can just use lazybot. ;)

1:10 amalloy: Raynes: seems like you could put those on one line

1:10 Raynes: amalloy: You proposed that before and I told you no then as well.

1:10 amalloy: well, i'll get back to you in a month when you've forgotten

1:37 ~logs

1:37 clojurebot: logs is http://clojure-log.n01se.net/

2:40 tuubow: in clojure if (= '(1) (quote (1))) is true then why (= '(1) (first '('(1) '(2)))) is false..is this a bug or i am doing something wrong..

2:41 hiredman: what do you think is more likely?

2:42 tuubow: i am doing something wrong i guess

2:42 hiredman: and what do you think the best way to figure out what you are doing wrong is?

2:42 tuubow: but (first '('(1) '(2))) is (quote (1))

2:43 so it should be true.

2:43 hiredman: tuubow: is it?

2:43 and what is '(1)?

2:43 ,'(1)

2:43 clojurebot: (1)

2:44 tuubow: same thing isn't '(1) is same as (quote (1))

2:44 hiredman: thats not (quote (1))

2:44 yes '(1) is the same as (quote (1)), but (list 'quote (list 1)) is not the same

2:44 neither is ''(1)

2:45 or (first '('(1)))

2:45 Raynes: &(first '('(1)))

2:45 lazybot: ⇒ (quote (1))

2:46 hiredman: http://en.wikipedia.org/wiki/Lisp_%28programming_language%29#Self-evaluating_forms_and_quoting

2:46 tuubow: but how come then (= '(1) (quote (1))) is true

2:46 hiredman: be cause they are equal

2:47 look, you need to spend sometime learning about quoting and how it works, sit down with a repl somewhere

2:48 tuubow: in repl when i type this (first '('(1) '(2))) it gives (quote (1))

2:48 hiredman: sure

2:48 ,(= (+ 1 2) 3)

2:48 clojurebot: true

2:48 hiredman: ,(= '(+ 1 2) 3)

2:48 clojurebot: false

2:48 hiredman: ,(= '3 3)

2:48 clojurebot: true

2:48 hiredman: ,(= ''3 3)

2:48 clojurebot: false

2:49 hiredman: ,''3

2:49 clojurebot: (quote 3)

2:49 hiredman: ,3

2:49 clojurebot: 3

2:49 hiredman: ,'3

2:49 clojurebot: 3

2:49 tuubow: (= '(1) (first '('(1) '(2)))) so if replace (first '('(1) '(2))) with (quote (1)) it should be true

2:49 hiredman: like I said, sit down with repl and figure it out, a solid understanding of quoting will serve you well

2:49 tuubow: as (= '(1) (quote (1))) is true

2:50 hiredman: ,'(1)

2:50 clojurebot: (1)

2:50 hiredman: ,(quote (1))

2:50 clojurebot: (1)

2:50 hiredman: ,(quote '(1))

2:50 clojurebot: (quote (1))

2:51 hiredman: anyway, I am going to put you on ignore now

2:51 tuubow: sorry i will look at it thanks.

2:59 raek: tuubow: '<foo> is just a shorthand for (quote <foo>). quote is also a special form

2:59 when you evaluate a quote expression, the value is the "content" of the quote

3:00 (quote x) evaluates to the symbol x. (quote (quote x)) evaluates to (quote x), i.e. a sequence of length two where the first element is the symbol quote and the second element is the symbol x

3:02 so to evaluate (= '(1) (first '('(1) '(2)))) you first eval the arguments to =, namely '(1) and '('(1) '(2))

3:02 (quote 1) evaluates to 1

3:02 sorry

3:03 '(1) is (quote (1)), which evaluates to (1)

3:03 '('(1) '(2)) is the same as (quote ((quote (1)) (quote (2)))), which evaluates to ((quote (1)) (quote (2))))

3:04 (1) and ((quote (1)) (quote (2))) are not the same data, so (= ...) returns false

3:08 tuubow: thanks raek

3:18 jidotnet: Hi! Anybody knows if/when the videos of the Conj will be available?

3:18 amalloy: jidotnet: they will be available, supposedly sooner than last year's were, but i don't know details

3:19 G0SUB: amalloy

3:20 jidotnet: amalloy: thanks, is there a way to get an alert when that happens?

3:21 raek: tuubow: btw, you usually use vectors as sequence literals

3:21 ,(= 1 (first [1 2 3]))

3:21 clojurebot: true

3:21 amalloy: jidotnet: probably if you follow @clojure_conj and #clojure_conj on twitter you'll find out

3:22 tuubow: well i am trying to implement set with this although clojure already has it.I would have gone to scheme for doing that but preferring clojure

3:23 so was trying to implement a member function as there is one scheme

3:24 Raynes: jidotnet: @confreaks is supposed to tweet when videos are ready.

3:24 tuubow: and as scheme doesn't have vectors so can't use it

3:25 it is a part of the assignment i am doing

3:26 * amalloy starts following @confreaks

3:27 raek: tuubow: in Clojure lists and quote work the same as in Scheme, except that you cannot have "dotted pairs"

3:27 amalloy: wait, they tweet all kinds of stuff i don't care about. i'll just assume someone i follow retweets

3:29 raek: (in Clojure-land you will hear about sequences which is a generalization of lists)

3:29 tuubow: raek, cons is there so i don't think i will need dotted pair,but i would have loved to have the member function on lists but i have implemented it now.I am loving clojure

3:30 raek: tuubow: yes, but you cannot have a non-sequence as the cdr

3:30 ,(cons 1 1)

3:30 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

3:31 amalloy: clojure makes it so easy to get a generalized version of member, so you don't really need member

3:31 &(some #{5} (range 10))

3:31 lazybot: ⇒ 5

3:31 amalloy: &(some #{50} (range 10))

3:31 lazybot: ⇒ nil

3:31 amalloy: &(some #{1 5} (range 10))

3:31 lazybot: ⇒ 1

3:33 tuubow: &(cons 1 '(1))

3:33 lazybot: ⇒ (1 1)

3:35 tuubow: &(defn member "Looks for the member in the lists return false if not found else return part of the list" [key list] (if (nil? (first(seq list))) false (if (= key (first list)) list (member key (rest list)))))

3:35 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

3:36 amalloy: tuubow: (member nil '(1 nil 2))

3:36 tuubow: sorry i didn't know the lazybot don't expect functions

3:36 G0SUB: amalloy: isn't it possible to play with lazybot in a PM window?

3:36 amalloy: G0SUB: yes?

3:37 G0SUB: amalloy: I was thinking if people could just use the bot in a private window the channel noise could be reduced

3:38 tuubow: amalloy: yeah that is the corner case.

3:38 amalloy: indeed you can do that, and if people are being super-noisy i encourage it. but it's not like we're trying to have a philosophical conversation and being drowned out by lazybot

3:38 G0SUB: amalloy: not really, was curious about the possibility. thanks.

5:19 cataska: any one has "Practical Clojure" book ? I have a question on page 160

5:21 G0SUB: cataska: I can try. have the book.

5:22 cataska: last sentence on page 160, "..., and because the update-average involves just processing and waiting for IO"

5:23 but update-averate is only processing with no IO, right ?

5:23 update-average

5:23 G0SUB: cataska: should read "and no waiting for IO..."

5:24 cataska: G0SUB: ok, thanks

5:24 it seems not in official errata

5:25 G0SUB: cataska: if IO in involved, you're better off using send-off

5:25 &(doc send-off)

5:25 lazybot: java.lang.SecurityException: You tripped the alarm! send-off is bad!

5:25 G0SUB: &(doc 'send-off)

5:25 lazybot: java.lang.SecurityException: You tripped the alarm! send-off is bad!

5:25 G0SUB: :(

5:26 cataska: G0SUB: :)

5:26 G0SUB: &doc

5:26 lazybot: java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/doc

5:27 G0SUB: hmm, this thing is broken.

5:28 &(:doc (meta #'clojure.core/send-off))

5:28 lazybot: java.lang.SecurityException: You tripped the alarm! send-off is bad!

5:28 G0SUB: amalloy: are you guys using regex on the command as well?

5:28 it seems the var itself is blocked somehow.

5:29 amalloy: yes, it is. not using regexes, though; i don't see why that would be relevant

5:29 G0SUB: amalloy: can't I even see the docs of all the core fns?

5:30 amalloy: evidently not. it would be nice if we could tell you're using doc, and take out the blocks in that case; patches welcome

5:30 G0SUB: &(keys (ns-publics (:ns (meta #'clojure.core/first))))

5:30 lazybot: java.lang.SecurityException: You tripped the alarm! ns-publics is bad!

5:31 G0SUB: :-)

5:31 amalloy: cool

5:34 amalloy: what about a doc plugin? won't that be easier?

5:37 Fossi: ,(doc 'send-off)

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

5:38 Fossi: ,(doc send-off)

5:38 clojurebot: "([a f & args]); Dispatch a potentially blocking action to an agent. Returns the agent immediately. Subsequently, in a separate thread, the state of the agent will be set to the value of: (apply action-fn state-of-agent args)"

5:39 amalloy: G0SUB: sure

5:55 fliebel: I forked and basically rewrote a small utility. Not likely to get merged back, but I'm using it in a project. How should I distribute it?

5:56 Actually, I did this twice.

5:57 For now I just did lein install, but one way or another, I need to get it on Clojars or something.

5:59 fbru02: hey guys how do i make the repl/swank overshadow some function when i evaluate it ? i think it's 1.2.1 onwards that the overshadowing doesn't occur automatically

6:18 tsdh: fbru02: What do you mean with overshadowing? Can you given an example?

6:18 fbru02: tsdh: sorry, i just meant re-writing when re-evaluating

6:21 tsdh: fbru02: I still don't get it... You want to redefine some clojure functions when you do "lein repl" or M-x clojure-jack-in?

6:22 fbru02: what i'm doing now : i load a bunch of functions using "(use 'ns1)" one of the fns is called foo. I want now to load foo from my souce code so i step on another function called foo and evaluate it, that doesn't work i get an exception

6:22 is there a way no to get an exception ?

6:23 fliebel: drewr: https://github.com/drewr/postal/issues/13

6:29 Hm, how do I push a project to org.clojars.pepijndevos/whatever?

6:30 clgv: fliebel: create an account. add an ssh public key of your computer and copy it per scp there.

6:30 it = jar

6:30 fliebel: clgv: Yes, but the namespace.

6:31 clgv: oh right. I have no idea about that. I would have liked a description on my jar as well - but no idea ho to get it there

6:31 fliebel: clgv: Another project I pushed just ended up under foo:foo

6:31 clgv: yeah, my only project also landed there under its plain name

6:32 I miss some editing/managing functionality on clojars when you are logged in

6:32 fliebel: clgv: just, maybe puting the namespace in the project.clj or editing the po file might do the trick. let me see.

6:33 clgv: fliebel: there is a chance that you can provide metadata via project.clj, but the question is how^^

6:34 fliebel: clgv: I'm pretty sure that if I change groupid in the pom, it'll work.

6:34 clgv: oh, I never touched the pom^^

6:35 fliebel: clgv: ah, if I change project.clj to (defproject org.clojars.pepijndevos/ring-http-basic-auth, the pom changes its groupid to that.

6:35 clgv: ah, interesting

6:37 fliebel: clgv: What is your one project on clojars?

6:37 clgv: a leiningen plugin: lein-checkouts

6:37 clojurebot: leiningen is a build tool designed not to set your hair on fire (http://github.com/technomancy/leiningen)

6:39 clgv: fliebel: changing the project name to contain the group-id is also suggested in some tutorial I found

6:39 fliebel: clgv: As well as in my Java book :P

6:40 clgv: Doesn't lein already do checkouts?

6:40 clgv: fliebel: I wanted to build all "checkouts" projects from the project that is using them.

6:41 like "lein checkouts uberjar" will "install" all "checkouts" and then build an uberjar of the current project

6:41 fliebel: oh, nice

6:42 clgv: yeah. that was a missing piece since I structured my main project in several libraries that I might share with students

7:01 Blkt: good day everyone

7:36 clgv: fliebel did it ;)

7:36 fliebel: clgv: ?

7:36 clgv: pushing to clojars ;)

7:37 fliebel: ,botsnack

7:37 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: botsnack in this context, compiling:(NO_SOURCE_PATH:0)>

7:37 fliebel: hm

7:37 clgv: clojurebot: botsnack

7:37 clojurebot: thanks; that was delicious. (nom nom nom)

7:41 * clgv finally wrote a pmap version that is "lazy" only in respect to memory consumption provided that the function is a kind of projection

7:50 fliebel: clgv: ?

7:51 clgv: fliebel: the pmap implementation is a nightmare briefly said - if you want to apply a function on a sequence.

7:53 I turned it into a producer-consumer scenario with a bounded queue which fits better for most parallelization purposes on sequences.

7:53 fliebel: clgv: ok, that is briefly, what is the full store? (maybe you could write it down in a Jira issue?)

7:54 clgv: Talking about producer-consumer, seque is just as much of a nightmare.

7:54 clgv: fliebel: a jira issue does not fit. it has no bug - but is inappropriate in all cases I wanted to parallelize something.

7:54 &(doc seque)

7:54 lazybot: ⇒ ------------------------- clojure.core/seque ([s] [n-or-q s]) Creates a queued seq on another (presumably lazy) seq s. The queued seq will produce a concrete seq in the background, and can get up to n items ahead of the consumer. n-or-q can be an integer n bu... https://gist.github.com/1388585

7:55 fliebel: Try running that with a priority queue. It makes invalid assumptions about what a que is.

7:55 clgv: &(source seque)

7:55 lazybot: ⇒ Source not found nil

7:55 fliebel: $source seque

7:55 lazybot: seque is http://is.gd/aZK2oD

7:56 clgv: I hate the slow github highlighting :(

7:56 humm lazybot linked another defn

7:58 fliebel: clgv: This is my implementation: https://gist.github.com/934781

7:59 clgv: its hard to diff between two tabs ;)

8:01 fliebel: clgv: Basically the core version just puts and takes until it encounters itself. My version uses a second FIFO queue, to send to the other end what to do next.

8:02 clgv: ah ok

8:03 fliebel: my implementation definitely applies f to all items of the passed sequence but has a bounded queue size so that it wont run out of memory (I'll process big files with it)

8:04 fliebel: clgv: So it is basically like (pmap f (seque s limited-queue))?

8:04 $source pmap

8:04 lazybot: pmap is http://is.gd/zPdiIH

8:04 clgv: fliebel: no pmap only processes a sliding window on consumption

8:05 fliebel: clgv: I don't get it. source?

8:07 clgv: fliebel: (lazy-)seq -> producer takes elements puts them into bounded queue -> queue -> consumer threads process items from queue and put the results in a result queue -> result queue -> returned lazy-seq reads from result queue

8:07 the producer will block when the bounded queue is full

8:08 so the entire calculation is async but you can acces already computed elements via the lazyseq as soon as they are calculated

8:08 fliebel: clgv: in order? Or just asap?

8:08 clgv: at the moment order is preserved but I also want a version where first calculated is first in result seq

8:09 I use it like (pprocess f coll :thread-count 4 :queue-size 8)

8:11 fliebel: clgv: I don't see why you have a queue for the producer. Presumably, f takes long, so the queue is just a buffer of realized items?

8:12 clgv: fliebel: to bound the items that are in memory the producer reads only as much as allowed

8:12 *many

8:13 fliebel: clgv: But if the input is a lazy seq, why realize even a buffer full of them?

8:14 clgv: fliebel: I dont understand your question

8:15 one problem there is that I cant let multiple threads access one lazy-seq like a queue

8:16 fliebel: clgv: Well, you have a lazy seq of unrealized items. You realize 8 ahead of time. Why not realize none at all?

8:16 hmm, is that true? hm, I guess

8:16 clgv: fliebel: and how can the 4 consumer threads access the sequence like a queue?

8:17 fliebel: clgv: Not, unless you put it in an atom or something.

8:18 ref, even

8:18 clgv: fliebel: extracting something from the lazy-seq means calculating it anyways

8:18 so I have to realize an item to pass it into a thread

8:18 fliebel: clgv: Yea, so you just go ahead and put it in a queue, I get it.

8:20 clgv: fliebel: indeed you have to be aware to put all of the expensive computation in the function and not some of it in the lazyseq

8:26 fliebel: one could think of a concurrent lazy-seq that acts like a queue by passing elements out as futures one-by one

8:26 notostraca: How do I pass the contents of a seq as arguments to a constructor that takes lots of arguments?

8:26 Like apply, but for a constructor

8:27 clgv: notostraca: if you cant write a function for it in advance (manually or as part of a macro) you probably have to fall back to reflection

8:27 fliebel: notostraca: (apply new object seq)?

8:27 notostraca: clgv, I never quite figured out macros

8:27 fliebel, I will try it

8:27 clgv: fliebel: that works?

8:28 fliebel: clgv: No idea...

8:28 clgv: ,(apply new java.util.Date [])

8:28 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: new in this context, compiling:(NO_SOURCE_PATH:0)>

8:28 fliebel: no, new is a special form :(

8:29 clgv: I dont think it is possible. but for a defrecord you can enhance the defrecordmacro to create a factory function in 1.2 or use the automatically generated one in 1.3

8:30 notostraca: clgv, I am using defrecord...

8:30 clgv: clojure 1.3?

8:30 notostraca: no, not yet

8:30 I am using CCW in Eclipse, which hasn't updated yet

8:31 is there a better way, I wonder...

8:31 clgv: notostraca: thats not an issue simply delete the clojure jars and replace them with 1.3 ones if nothing else helds you back

8:31 notostraca: so what would I use in 1.3?

8:31 for this particular problem

8:32 I will switch now if it fixes it...

8:32 cemerick: notostraca: you can use 1.3 in your projects with ccw without a problem

8:32 clgv: (->Rec 1 2 3) for (defrecord Rec [a b c])

8:32 in your case: (apply ->Rec [1 2 3])

8:33 notostraca: clgv, great

8:33 clgv: CCW: just installs default clojure 1.2 in your new project but that doesnt prevent you from switching to 1.3

8:34 maybe it should have an option for selecting 1.2.1 or 1.3.0

8:35 fliebel: Would it be possible to somehow proxy an instance of a class? I want to extend it, but it doesn't have a public constructor.

8:35 omg, I can of course just define a protocol and extand that to it.

8:35 clgv: fliebel: you can call the constructor via reflection anyway and use it as aggregate

8:36 protocol approach is much better if possible ^^

8:37 pyr: i supposed core.incubator is meant to get into core eventually

8:37 fliebel: clgv: Yea, I'll do that. I'm trying to handle java.xmail.* objects nicely, so i converted them to maps, but now I can't use the methods of the objects anymore of course.

8:38 clgv: fliebel: writing the next spambot? ;)

8:39 fliebel: clgv: Almost... more like a... web mail rss twitter client... I need to work on my elevator pitch.

8:39 clgv: "elevator pitch"?

8:40 fliebel: clgv: short introduction, like you stand in the elevator with an investor, and you have 10 seconds to explain your product.

8:41 clgv: fliebel: ah. you got a startup?

8:41 fliebel: clgv: hmmm, dunno, I guess you could call it that. A serious project at least.

8:43 clgv: fliebel: so you are still hanging out in elevators waiting for the investors? ;)

8:43 fliebel: clgv: nope, I just started building, and i want to take it to WebFWD.

8:44 clgv: didnt know about that program, yet

8:45 fliebel: clgv: Random question: where are you from?

8:45 clgv: fliebel: seems not that random. germany.

8:47 and you?

8:47 fliebel: clgv: How is it not random? Netherlands.

8:49 clgv: fliebel: scientifically speaking "cant judge since we didnt tie the model". personally, it just doesnt seem random like 11111 doesnt seem ;)

8:50 fliebel: clgv: Well, yea, it's a perfectly normal question, but one moment we're talking about clojure, the next I ask where you are from.

8:51 notostraca: OK, I'm debugging now, it is getting the wrong number of arguments somehow

8:51 fliebel: (tbh, I mostly assume everyone who speaks reasonable english is an american)

8:51 notostraca: It might be that I defined the record with 1 field?

8:52 fliebel: notostraca: paste?

8:53 notostraca: sure, it's kinda a mess and it is meant to read in a TSV table

8:54 http://pastebin.com/AwbSxKdu

8:55 the TSV file is pasted directly from a spreadsheet

8:55 the column names are the first row, everything after that is data

8:56 clgv: notostraca: I have the feeling you are using defrecord strangely

8:56 notostraca: clgv, yeah

8:56 clgv: notostraca: the defrecord contains the header and the map part of the defrecord the values?

8:56 notostraca: I need to define it at runtime

8:56 clgv: notostraca: defining at runtime is not a problem

8:57 notostraca: clgv, I am calling defrecord with a vector drawn from parsing the file

8:57 I don't know if that works

8:57 clgv: notostraca: did you have a look at incanter and how they manage their datasets?

8:57 notostraca: I don't know what incanter is

8:57 clgv: $google incanter

8:57 lazybot: [Incanter: Statistical Computing and Graphics Environment for Clojure] http://incanter.org/

8:57 clgv: thats it^^

8:58 if you need any visualization for your data you should consider it

8:59 notostraca: clgv, no I don't think I need that

8:59 clgv: ok, you might have a look at their dataset implementation - they have a defrecord for it as well

8:59 notostraca: I just need to get this in a hashmap of things, so I can persist it as clojure code with prn

8:59 it doesn't need to be records

9:00 clgv: afaik they divided it into a headerfield and a rows field

9:00 notostraca: there's some old code in that paste that gets the TSV into a sorted-map of hash-maps of strings

9:01 clgv: the header contains the keywords for the columns and the rows field contains the row data with each row beaing a hashmap from column name (keyword) to value

9:01 notostraca: but ideally it would be able to take integer fields in the TSV and convert them to ints instead of strings

9:01 pyr: is there a cleaner (simpler) way to sanitize a map

9:01 clgv: that layout could work for you as well

9:01 pyr: than this:

9:02 notostraca: pyr: pastebin

9:02 pyr: (->> {:a nil, :b :foo} (filter #(val %)) (reduce merge {}))

9:02 notostraca: clgv, it doesn't seem like it needs a lib dependency honestly

9:03 clgv: yes. you can easily build it like that as well.

9:03 pyr: notostraca: i don't think it's warranted

9:03 clgv: notostraca: ^^

9:05 pyr: you could do a reduce + dissoc approach to keep sharing structure

9:06 pyr: reduce dissoc on keys ?

9:08 clgv: pyr: (let [m {:a nil, :b :foo}] (reduce #(dissoc % %2) m (filter nil? (keys m))))

9:08 &(let [m {:a nil, :b :foo}] (reduce #(dissoc % %2) m (filter nil? (keys m))))

9:08 lazybot: ⇒ {:a nil, :b :foo}

9:09 fliebel: clgv: filter is wrong

9:09 clgv: damn... somehting missing. #(let [m {:a nil, :b :foo}] (reduce #(dissoc % %2) m (filter #(nil? (m %)) (keys m))))

9:09 &(let [m {:a nil, :b :foo}] (reduce #(dissoc % %2) m (filter #(nil? (m %)) (keys m))))

9:09 lazybot: ⇒ {:b :foo}

9:10 fliebel: clgv: ##(+ 1 1)

9:10 lazybot: ⇒ 2

9:10 clgv: yeah. typo^^

9:10 pyr: actually, mine should read (->> {:a nil, :b :foo} (filter val) (reduce merge {}))

9:10 ,(->> {:a nil, :b :foo} (filter val) (reduce merge {}))

9:10 clojurebot: {:b :foo}

9:10 pyr: &(->> {:a nil, :b :foo} (filter val) (reduce merge {}))

9:10 lazybot: ⇒ {:b :foo}

9:11 clgv: pyr: yours doesnt share structure with the old map. thats only not that optimal if the map is large and there are few "nil keys"

9:12 pyr: clgv: agreed

9:14 fliebel: I really wish clojure used protocols, so I could extend java.foo.Bar to clojure.lang.IBaz

9:16 notostraca: what is the equivalent of (last) that drops the last element instead of the first?

9:17 like first, but all of the entries but the last

9:17 joegallo: butlast, drop-last

9:17 notostraca: thanks

9:18 joegallo: http://clojure.github.com/clojure/ (Ctrl+F, "last" and looked around)

9:18 ;)

9:18 notostraca: butlast doesn't show up?

9:19 in clojure.core

9:19 huh, nvm

9:21 clgv: you can use lazybot as well

9:21 $findfn [1 2 3 4] [1 2 3]

9:21 lazybot: [clojure.core/butlast clojure.core/drop-last clojure.core/pop]

9:22 bendlas: wut?

9:22 that's advanced

9:25 pyr: $findfn {:a nil :b :foo} {:b :foo}

9:25 lazybot: []

9:28 clgv: it cant build functions compositions although that should be doable as well until the timeout strikes ;)

9:29 marchdown: hello

9:31 notostraca: hmm, maybe that's it

9:32 can you create records with string keys?

9:32 or do they have to be symbols?

9:32 clgv: defrecord will always have keywords of the symbols you provide

9:32 notostraca: ah

9:33 clgv: but you can easily create a keyword via ##(keyword "bla")

9:33 lazybot: ⇒ :bla

9:33 notostraca: so there's the problem

9:33 and if there's a space in "some random phrase" ?

9:33 ,(keyword "something happy...")

9:34 clojurebot: :something happy...

9:34 notostraca: woah what

9:34 clgv: thats probably a bad idea since it works but is not supposed to, i.e. you cant read it back

9:34 ,(read-string (with-out-str (pr (keyword "something happy..."))))

9:34 clojurebot: :something

9:35 notostraca: is there a way to format a string nicely as a symbol?

9:35 clgv: there is also ##(symbol "bla")

9:35 lazybot: ⇒ bla

9:35 clgv: &(class (symbol "bla"))

9:35 lazybot: ⇒ clojure.lang.Symbol

9:35 notostraca: (symbol "oh yeah")

9:35 ,(symbol "oh yeah")

9:35 clojurebot: oh yeah

9:36 notostraca: ah

9:36 joegallo: ,(name 'foo)

9:36 clojurebot: "foo"

9:36 joegallo: oh, that's backwards from what you want. :)

9:36 marchdown: I'm struggling to install clojure. $ java -cp clojure.jar works, but lein barfs out an error.

9:36 notostraca: marchdown, lein should grab its own clojure

9:36 i think it needs maven

9:37 maybe you need to run "lein self-install"

9:37 joegallo: mmm.... i'm not sure about that. marchdown, can you gist the error you're getting?

9:37 notostraca: maybe you need to run "lein selfinstall" instead, not sure what the word is

9:37 duck1123: lein uses maven stuff, but it doesn't actually need maven installed

9:38 marchdown: I don't know the first thing about maven, but I've run 'mvn install' in clojure repo as per instructions, and it did something. I'm on a mac with system-provided java.

9:39 joegallo: yeah, i don't think that does what you'd like it to do

9:39 that's "install this jar into my local .m2 directory"

9:39 which isn't quite as awesome as it sounds... :)

9:39 notostraca: marchdown, have you run lein just as "lein" ?

9:39 duck1123: Some clojure projects use maven, also as part of lein install, a basic pom file is created

9:40 marchdown: https://gist.github.com/1388808

9:40 joegallo: don't try to install leiningen 2.0.0

9:40 it's a highly experimental in-development version -- i think

9:41 notostraca: use stable -- https://raw.github.com/technomancy/leiningen/stable/bin/lein

9:42 you can probably just wget that

9:43 download that into somewhere on your PATH, like /usr/bin , "chmod 755 lein", "./lein"

9:44 you may need to run the last two as sudo if you put it somewhere where you need root permission to write

9:45 duck1123: I prefer to put mine in ~/bin or similar, that way I can upgrade without sudo

9:45 marchdown: cool, thanks. I'm feeling so stupid now for not noticing it was a plain old 404. The reason is, this is the second box I'm installing clojure on, and the first time I had an error at the same stage, but it was far more cryptic.

9:45 duck1123: just have to make sure that dir is on PATH

9:46 marchdown: Okay. So, how'd I hook it up with emacs now?

9:46 I need a clojure-runner script, right?

9:46 joegallo: no

9:47 notostraca: marchdown, are you familiar with emacs? Because I'm not, and there are good IDE plugins too

9:47 and the IDE plugins probably have better support for Java, though I can't be certain

9:47 marchdown: I am.

9:47 notostraca: ok

9:48 joegallo: you need clojure-mode

9:48 marchdown: Got that.

9:48 joegallo: you need lein-swank-[latest stable version].jar in you ~/.lein/plugins/ directory.

9:48 notostraca: in that case, I imagine you will be sticking with mostly- or pure-clojure projects, which will be pleasant compared to switching your mindset from one to the other

9:55 dabl: hi all, /quit

10:06 notostraca: is there a good way to get an Integer or int or some number from a String in clojure?

10:07 kephale: ,(read-string "1")

10:07 clojurebot: 1

10:07 notostraca: huh good to know

10:07 ,(read-string "1 2 3 4"

10:07 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

10:07 notostraca: ,(read-string "[1 2 3 4]")

10:07 clojurebot: [1 2 3 4]

10:07 notostraca: ,(read-string "1 2 3 4")

10:07 clojurebot: 1

10:08 joegallo: ,(doc read-string)

10:08 clojurebot: "([s]); Reads one object from the string s"

10:09 notostraca: ,(/ (read-string "1") 3)

10:09 clojurebot: 1/3

10:10 Wild_Cat: ,(Integer. "2")

10:10 clojurebot: 2

10:12 clgv: notostraca: there is also Integer/parseInt

10:13 notostraca: I'm going to read-string on every value, individually -- it handles string data so I don't need to have types as part of the data

10:16 fliebel: notostraca: read-string is a bit of a security issue, I think. I don't know if that matters to you.

10:18 jcromartie: So I was playing with this on the train this morning: https://gist.github.com/1388915

10:18 creating a temporary memoization context for certain functions... is there any chance that this is already idiomatic?

10:18 notostraca: fliebel, I am making the data in a spreadsheet, so it will be fine

10:18 jcromartie: it makes writing this kind of math code very nice

10:19 fliebel: notostraca: I just saw you already evaluated a list.

10:19 clgv: ,(read-string "(System/exit 0)")

10:19 clojurebot: (System/exit 0)

10:20 clgv: ,(read-string "(eval (System/exit 0))")

10:20 clojurebot: (eval (System/exit 0))

10:20 clgv: lol

10:20 ,(eval (read-string "(System/exit 0)"))

10:20 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

10:20 clgv: hehe ok^^

10:20 so read-string cant do any harm I guess, since it is not evaling

10:21 ,(read-string "#=(System/exit 0)")

10:21 clojurebot: #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.>

10:21 clgv: ,(binding [*read-eval* true] (read-string "#=(System/exit 0)"))

10:21 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.ClassNotFoundException: System>

10:21 floatboth: clgv: sandbox won't let you eval anyway

10:21 fliebel: jcromartie: You should talk to fogus, he's putting a memoization lib in contrib.

10:22 jcromartie: I got my math wrong :P

10:26 fliebel: Do there exist functions for translating and selecting keys from a map? {:foo 1 :bar 2} -> {:baz 2}

10:28 wee, armagedom :)

10:28 clojurebot: botsnack

10:28 clojurebot: Thanks! Can I have chocolate next time

10:28 fliebel: I'll see...

10:29 clgv: fliebel: select-keys, rename-keys

10:30 $findfn {:bar 2}{:baz 2}

10:30 lazybot: []

10:30 clgv: $findfn {:bar :baz} {:bar 2}{:baz 2}

10:30 lazybot: []

10:30 clgv: $findfn {:bar 2} {:bar :baz} {:baz 2}

10:30 lazybot: [clojure.set/rename-keys]

10:31 fliebel: ah, it's hiding in set...

10:31 clgv: yep, they always do ;)

10:33 fliebel: clgv: Maybe it should be named clojure.map then...

10:33 I should revive clojure-quiz

10:34 clgv: &(keys #{1 2 3})

10:34 lazybot: java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.Map$Entry

10:34 clgv: &(rename-keys #{:a :b :c} {:a :z})

10:34 lazybot: java.lang.RuntimeException: Unable to resolve symbol: rename-keys in this context

10:34 clgv: &(use 'clojure.set)

10:34 lazybot: ⇒ nil

10:35 clgv: &(rename-keys #{:a :b :c} {:a :z})

10:35 lazybot: java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Associative

10:35 clgv: fliebel: yes it should be renamed indeed ^^

10:35 fliebel: hm, what about rename-keys-in? [:foo bar] [:baz] :D

10:36 apgwoz: has anyone used the ring-netty-adapter ?

10:37 clgv: no I meant clojure.set -> clojure.map

10:43 fliebel: apgwoz: *netty*? Interesting. No, but I've used Aleph, which uses Netty.

10:43 .. and provides a ring wrapper.

10:44 apgwoz: fliebel: might be worth finally jumping into aleph if that's the case. cool, i'll have a look

10:45 is there a specific ring-aleph-adapter? or were you just doing (respond! (ring-handler whateer)) like i saw in an old clojure list thread?

10:46 fliebel: nevermind. gonna research aleph. the answers probably sitting there waiting for me to read it

10:46 :)

10:47 fliebel: apgwoz: I can't remember either.

10:48 apgwoz: fliebel: looks like aleph.http has (wrap-ring-handler ...) that is the magic button

10:50 clgv: $inc aleph

10:50 lazybot: ⇒ 2

10:51 * clgv gotta research aleph as well

10:57 cemerick: huh, didn't realize you didn't need a handle for that

10:57 $inc kittens

10:57 lazybot: ⇒ 1

10:59 jidotnet: cemerick: just had a look at your conj slides

11:00 cemerick: any idea when the code will be available?

11:02 cemerick: jidotnet: should have been out already. I'm running behind on about 83 different things. :-|

11:02 I'll definitely make some noise when it's up :-)

11:04 jidotnet: cemerick: cool thanks; i'll keep whatching ;)

11:16 jweiss: can someone recommend a way to have metadata added to an object (eg, with ^{:my :meta} that doesn't overwrite the meta that is already there?

11:17 or can i not use ^ at all, must i do (with-meta obj (merge (meta obj) newmeta))

11:25 clgv: jweiss: there is vary-meta - see ##(doc vary-meta)

11:25 lazybot: ⇒ ------------------------- clojure.core/vary-meta ([obj f & args]) Returns an object of the same type and value as obj, with (apply f (meta obj) args) as its metadata. nil

11:26 jweiss: clgv: thanks, was hoping to be able to use ^ but that does not appear possible. i'll just make a function with a short name to make it convenient for my users :)

12:02 fliebel: Where and how do you usually store configuration?

12:03 for a web app

12:05 duck1123: I have a library that allows you to store config maps in the root of the project and then query them like (config :foo :bar :baz)

12:05 It'll merge the default environment with the specified environment

12:06 It works well enough for my needs

12:11 fliebel: duck1123: Nice idea.

12:13 duck1123: fliebel: If you're interested https://github.com/duck1123/ciste/blob/master/src/ciste/config.clj

12:16 reiddraper: I'm trying to understand the difference between clojure.lang.Seqable and clojure.lang.ISeq, could just be that my java-reading skills are rubbish

12:17 cemerick: Seqables can provide an ISeq

12:18 reiddraper: cemerick: If I'm making a new type with deftype, which should I be looking to implement, both then?

12:18 cemerick: The tricky part is that `seq` provides polymorphism that isn't entirely captured by Seqable.

12:18 joegallo: sounds like iterables which can return an iterator, from java collections

12:18 cemerick: That's the right corollary.

12:19 reiddraper: if your type *is* a seq, then implement ISeq (or some derivative). If it can provide a seq, Seqable.

12:19 'course, the former extends the latter

12:20 reiddraper: cemerick: ok that makes sense. I'm making a Set, so it sounds like I want to provide a seq

12:20 on second that, i suppose a set *is* a seq

12:20 s/that/thought

12:21 cemerick: how is a set a seq?

12:21 hiredman: no

12:21 reiddraper: maybe i have a poor seq definition

12:21 Chousuke: most things aren't seqs

12:21 but lots of things are seqable

12:22 in core only lists are true seqs (and lazy seqs of course)

12:22 cemerick: The only built-in that are their own seqs are lists

12:22 hah

12:22 oh, Cons too :-P

12:24 reiddraper: i remember coming across definitions for these before... so are all things that *are* seqs, sequential?

12:28 cemerick: for want of a reasonable class hierarchy viewer online

12:28 oh, hah

12:29 reiddraper: http://www.clojureatlas.com/org.clojure:clojure:1.2.0?guest=t#clojure.lang.Sequential — click on the 'i' or roll over 'Sequential' while holding down Ctrl.

12:29 reiddraper: cemerick: cool, thanks

12:52 shequo: I'm interested in learning about how clojure implements efficient creation of modified datastructures via structural sharing etc...can anyone point me in a good direction to research this?

12:52 fliebel: What kind of magic could be going on here? I have a ring handler, if I call it on the repl, I get a result, if I launch jetty with it, a weird NullPointerException.

12:53 shequo: You could try the research papers for them.

12:53 dnolen: shequo: Okasaki - Purely Functional Data Structures

13:00 fliebel: Magic: The handler has no default route, returns nil, end of story.

13:12 antares_: hey. I have a question: where do I need to sign up to publish jars to oss.sonatype.org? Looks like clojars.org is having some issues, my freshly published jars cannot be accessed even though project page loads fine and displays the version I pushed.

13:44 gfredericks: anybody know what's messed up if my `lein repl` goes nuts whenever I backspace?

13:45 by "goes nuts" I mean continues functioning properly, but deletes a bunch of characters so I can't tell what's going on

13:48 duck1123: gfredericks: does it do this even if you open a new terminal?

13:49 gfredericks: hmm, no

13:49 it's been happening for a day or two now, across different terminal instances. I'm not sure what the common thread is

13:50 oh let me try it with this particular project...

13:50 duck1123: are you printing out "odd" values?

13:50 gfredericks: nope

13:51 okay, it does do it for this project

13:52 * gfredericks looks at his project.clj

13:52 gfredericks: maybe it's this dependency on jruby

13:53 yep, remove jruby dep and it's better

13:53 well if there's one thing you can count on ruby to do, it's magical crap in the background that you have no hope of ascertaining.

13:54 duck1123: don't forget screwing up your UTF-8

13:55 gfredericks: duck1123: thanks for rationally talking me through it. Being punished for backspacing can make you go batty.

13:56 duck1123: bah! real programmers don't need backspace. Everything is perfect the first time.

13:57 gfredericks: That'd be a funny feature for an elite keyboard

13:57 moogatronic: or a mode for emacs.

13:57 amalloy: gfredericks: but ^H would still work

13:58 gfredericks: if jruby was a problem, i bet it's because it pulls in a ruby version of readline, conflicting with the one your system wants to use

13:58 gfredericks: amalloy: holy crap this might drastically improve my life

13:59 by which I mean my finger pain

13:59 does ^H work everywhere?

13:59 amalloy: anywhere that expects emacs/readline-style stuff

13:59 on a mac, i think that's pretty much anywhere

13:59 duck1123: most of the emacs commands work in terminals

13:59 gfredericks: I'm on ubuntu

14:00 it works on irssi and in the bash terminal at least

14:00 duck1123: I always feel so awesome when I make use of C-t correctly

14:00 moogatronic: i'd be surprised if it didn't do the same everywhere in ubuntu

14:00 amalloy: gfredericks: like i said, anyplace that uses readline

14:00 gfredericks: I bet it doesn't work in vim, but I'm sure that can be changed

14:00 amalloy: moogatronic: prepare to be surprised, bro

14:00 duck1123: it's an option

14:00 gfredericks: is there a key shortcut for enter as well

14:00 amalloy: gfredericks: ^J

14:01 gfredericks: omg.

14:01 amalloy: *now* will you learn emacs?

14:01 gfredericks: no.

14:01 amalloy: gfredericks: you can also configure readline to use vim bindings instead of emacs bindings

14:01 in your .inputrc i think

14:02 duck1123: gfredericks: https://help.ubuntu.com/community/AdvancedCommandlineHowto

14:02 gfredericks: oh ^H and ^J both work in vim

14:02 duck1123: that looks like a good link

14:02 amalloy: it seems weird to me that you'd want to use them in vim, though. doesn't vim encourage you to go into edit-mode and then type d<something>?

14:03 duck1123: actually, not as good as I'd hoped for the key shortcuts

14:03 amalloy: dh, i guess

14:03 gfredericks: amalloy: true, I probably don't really use backspace and enter in vim. I just expected I could get annoyed if I got used to ^H/J and then vim didn't support them

14:03 but you're right, probably wouldn't have mattered

14:04 I'll think about emacs.

14:05 I don't remember what my objections were.

14:05 moogatronic: also ^? .. (http://en.wikipedia.org/wiki/ASCII_code#ASCII_control_characters)

14:06 gfredericks: moogatronic: oh. that helps explain it better.

14:09 amalloy: haha that dang ^S. i've accidentally frozen a few consoles with that. i guess this was back when i had readline set up in vim mode, though, because ^S does something different normally

14:22 R4p70r: Let’s try this again. Is anyone in Canada looking for an entry-level Clojure dev? I’m in Montreal but willing to relocate.

14:34 amalloy: duck1123: thanks for that ascii link, btw. i knew most of that already, but noticing that escape characters get sent as ESC [ helped me figure out a problem i've been having, actually

14:41 gfredericks: Look maybe I'll think about emacs but not for another couple weeks. Gotta graduate first.

14:44 moogatronic: gfredericks: yeah, graduation > emacs. =)

14:44 gfredericks: huh. I just realized that ^J and ^H mirror the functionality of vim's 'j' and 'h'

14:46 At least in not-insert-mode

14:50 kephale: are you sure emacs doesn't have a key bind for degree completion?

14:52 gfredericks: even if it does I'm sure I'd forget it when I actually needed it

15:11 amalloy: like C-t

15:13 fliebel: amalloy: ?

15:13 kephale: never used that one

15:14 amalloy: fliebel: an emacs command you forget whenever you acutally need it (see what i did there?

15:14 kij: hey guys. Is there an form that would let me do a (dissoc { :a 1 :b 2 :c 3 } (unlist '(:b :c)) ) ... unlist would just return :b :c

15:14 amalloy: &(doc apply)

15:14 lazybot: ⇒ ------------------------- clojure.core/apply ([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args]) Applies fn f to the argument list formed by prepending intervening arguments to args. nil

15:14 amalloy: &(apply dissoc {:a 1 :b 2 :c 3} [:b :c])

15:14 lazybot: ⇒ {:a 1}

15:17 gfredericks: works because ##(dissoc {:a 1 :b 2 :c 3} :b :c)

15:17 lazybot: ⇒ {:a 1}

15:18 fliebel: amalloy: You wrote {:keys [tag attr content]}, do you mean that every node is actually a map?

15:18 amalloy: yes

15:18 kij: thanks!

15:19 '(:a :b) -> :a :b, is not possible ? what should i read to understand why ?

15:20 amalloy: kij: because one thing is not two things

15:20 fliebel: amalloy: oh, ok. I'm just using sequences.

15:20 gfredericks: kij: you're saying you want dissoc to return the keys that you removed?

15:21 kij: if so, then it doesn't do that because you want it to return the map instead. Clojure maps are immutable, so dissoc creates a new map that doesn't have the keys. If it returned the keys, you wouldn't have the new map, so nothing would have happened.

15:21 amalloy: fliebel: hiccup uses vectors: [tag attrs & content]

15:21 kij: gfredericks: no, i would like to remove the list and get the single values.

15:21 amalloy: kij: it is not possible to return two values from a function

15:21 fliebel: amalloy: I do the same, without the attrs, which is really convenient, because of the first/rest concept in Clojure.

15:22 amalloy: just like it is not possible to do that in c, or python, or...

15:22 gfredericks: kij: I'm not sure what that means

15:22 amalloy: gfredericks: he wants (unlist [1 2]) to return both 1 and 2, but not as a list

15:22 so that he can splice it into some function call

15:22 gfredericks: amalloy: ah, that makes some sense of it

15:23 kij: gfredericks: what amalloy says :)

15:23 Raynes: So, he wants apply?

15:23 gfredericks: kij: then amalloy's original recommendation of using 'apply' is what you want

15:23 fliebel: kij: You can use destructuring: ##(let [[a b] '(1 2)] b)

15:23 lazybot: ⇒ 2

15:23 Raynes: But doesnt know it?

15:23 (apply + [1 2 3])

15:23 amalloy: Raynes: arguably he should know it, because i said that already

15:23 Raynes: &(apply + [1 2 3])

15:23 lazybot: ⇒ 6

15:24 kij: i understand now. Thanks!

15:25 fliebel: How can I setup, run and test a Maven Clojure project, such as data.xml?

15:25 gfredericks: mvn clojure:[compile|test]?

15:26 fliebel: gfredericks: uhm, okay. Let me try...

15:26 duck1123: mvn test and mvn compile work as well

15:26 amalloy: fliebel: just $ mvn test

15:26 duck1123: or mvn clojure:swank or mvn clojure:repl

15:27 amalloy: duck1123: oh, good to know. i just added a project.clj locally to get swank

15:27 duck1123: amalloy: be careful. lein install will clobber your pom.xml (but that's what git is for)

15:36 fliebel: amalloy: Huh, weird output... It sets the namespace as an attribute? Did you setNamespaceAware, as the ticket suggested?

15:37 amalloy: fliebel: that's actually a perfectly valid way to set the xmlns of a node

15:37 fliebel: amalloy: Okay, so the test is incorrect?

15:37 amalloy: by declaring "everything from here (inclusive) on down, is implicitly in the api namespace"

15:37 fliebel: i think the test is *probably* over-specific, but like i said i don't know a ton about namespaces

15:38 last time i had to know anything at all about them was five years ago

15:39 fliebel: amalloy: You are using SAX for everything, right?

15:39 amalloy: fliebel: no idea

15:39 that stuff is all chouser's - mostly i just wrote the converter from hiccup-style to enlive-style

15:40 fliebel: amalloy: Which is which?

15:40 amalloy: hiccup: [tag {attrs} & content]

15:40 enlive: {:keys [tag attrs content]}

15:41 fliebel: ArmageDOM: ^{attrs} [tag & content]

15:41 amalloy: MADNESS

15:41 brehaut: what

15:41 amalloy: i know, right? someone tell fliebel that attrs are not metadata

15:42 fliebel: in fairness though i can see how that would be handy, and i can't immediately think of any ways it would cause a problem or be hard

15:43 fliebel: meta = about itself, data about the data: <link rel="base">http://example.com</link>

15:43 brehaut: ,(= ^{:href "http://example.com"} ["a" "a link"] ^{:href "http://google.com"} ["a" "a link"])

15:43 clojurebot: true

15:43 brehaut: thats why its bad

15:44 amalloy: hah

15:44 yes, wow that's bad. thanks, brehaut

15:44 brehaut: no problem

15:45 amalloy: brehaut: if you care to follow along, the discussion started at http://groups.google.com/group/clojure-dev/browse_thread/thread/dff8e406b7502a0b/0997aaf57a2d4c75?show_docid=0997aaf57a2d4c75 when fliebel kindly volunteered to help with data.xml

15:45 fliebel: hmm, good point.

15:45 brehaut: amalloy: ah right. /me catches up

15:45 amalloy: the metadata discussion isn't really germane, i was just astonished by his choice

15:46 dnolen: fliebel: attributes are not definitely not metadata

15:46 metadata is not just data about data, it's data about data that should never be considered under equality

15:46 amalloy: btw fliebel: "at frist glance, mine doesn't have 20-line functions." i didn't get your point here

15:48 fliebel: amalloy: I mean to say the emit code is rather ugly, if you ask me: https://github.com/clojure/data.xml/blob/master/modules/xml/src/main/clojure/clojure/data/xml.clj#L285

15:49 dnolen: That is indeed a detail of clojure meta data I had not considered.

15:49 brehaut: wait. core.xml is seperate to clojure.xml ?

15:50 fliebel: brehaut: According to the readme, it might become clojure.xml later.

15:51 amalloy: i'm in favor of pulling the configuration out into a separate function, fliebel, but i suspect there's a good reason the code exists (ie, you couldn't just throw half of it away)

15:51 brehaut: fliebel: thanks; ive had to hack about with clojure.xml's emit for necessary-evil (thanks python xmlrpc imp); core.xml looks like it might fix the issue for me

15:51 (https://github.com/brehaut/necessary-evil/blob/master/src/necessary_evil/xml_utils.clj#L30-53)

15:52 fliebel: amalloy: My initial iteration of ArmageDOM looked like that, but now it's broken into small bits.

15:53 amalloy: brehaut: so is python's impl incorrect and you need to cover for it, or clojure's is incorrect and you need to send python something more-correct

15:53 brehaut: amalloy: its python's thats dodge; new lines throw it out, which i dont believe should be a problem

15:54 amalloy: and 1.2's emit-elements hardcoded emitting new lines (with println)

15:54 amalloy: i see. so you copied the code but changed println to print. very funny

15:55 brehaut: indeed; i couldnt think of a better way to do it :P

15:55 amalloy: wow clojure.xml is *really* old

15:55 brehaut: oh! https://github.com/brehaut/necessary-evil/blob/master/src/necessary_evil/xml_utils.clj#L42 that line is important

15:56 im not sure if i was using the xml tools wrong, or if its an actual bug

15:56 fliebel: yea, structs and all

15:56 amalloy: check out the last three lines:

15:56 ;(export '(tag attrs content parse element emit emit-element))

15:56 ;(load-file "/Users/rich/dev/clojure/src/xml.clj")

15:56 ;(def x (xml/parse "http://arstechnica.com/journals.rssx"))

15:56 brehaut: but that version of emit wasnt escaping < > and &

15:56 * brehaut wonders why he never raised these as issues in the past. sorry!

16:22 fliebel: amalloy: I think setting http://xml.org/sax/features/namespace-prefixes to true, would fix the test, but I can;t figure out how to do it.

16:24 call setFeature on *something*

16:25 amalloy: fliebel: indeed, that is the crux of most of the data.xml problems. "how do we set a damn feature"

16:25 fliebel: "Turn features on or off using setFeature."

16:25 amalloy: right, but features aren't standardized

16:25 across the various impls

16:26 fliebel: amalloy: but, but... these are "SAX2 Standard Feature Flags"

16:26 amalloy: there are *some*. did you find one for indentation/pretty-print?

16:26 fliebel: amalloy: scroll down here: http://www.saxproject.org/apidoc/org/xml/sax/package-summary.html

16:29 amalloy: fliebel: i see the one for namespaces, but not for whitespace

16:29 fliebel: amalloy: me neither....

16:32 amalloy: http://apache.org/xml/features/dom/include-ignorable-whitespace ?

16:33 amalloy: fliebel: that's for parsing, not output. but not relevant anyway because it's apache-specific. we already set the apache indent-amount, but not every transformer is an apache transformer

16:33 which is why this whole thing is a mess

16:34 fliebel: amalloy: so the project is waiting for a minor whitespace issue?

16:34 amalloy: yes, absurd as i personally think that is

16:34 that's why a number of forks have sprung up on clojars

16:36 technomancy: we should have clojars alert a library maintainer once a threshhold of forks have been created

16:36 "hey dude, I don't know if you've been paying attention, but you might want to do something about this..."

16:38 brehaut: technomancy: thats a great idea

16:42 fliebel: meta data counter-argument: href/src is so far the only one that would matter for equality. counter-example: <content type="xhtml">foo</content> <content type="html">foo</content> <content type="text">foo</content>

16:43 amalloy: fliebel: that is so, so wrong. what about ant build files?

16:43 fliebel: amalloy: What does an ant buidl file look like... googles.

16:43 amalloy: shield your eyes

16:44 i'm just saying, attributes are an integral, important part of an xml element

16:44 pretending they're metadata is bizarre

16:45 in html, if you prefer: <input type="button" name="submit" /> vs <input type="text" name="name" value="your name here" />

16:47 brehaut: fliebel: i think what you are confusing is that in most xml applications, the attributes are treated as a kind of meta data, but in a tool that is handling xml data, then that isnt meta data, its straight data

16:47 fliebel: amalloy: well, they are metadata, only not of the same kind as clojure meta data.

16:50 brehaut: that is true.

16:52 tolstoy: Is there a handy clojure lib to deal with uint type of issues?

16:52 brehaut: tolstoy: most people just use one size larger primatives

16:53 fliebel: Now I have a problem, because I like neither the enlive or the hiccup syntax. The one is verbose, the other ambiguous.

16:53 tolstoy: brehaut: Okay. I've done all that before. I was hoping someone had a handy lib that could read byte-buffers and Do The Right Thing. ;)

16:53 brehaut: tolstoy: i dunno sorry

16:54 amalloy: fliebel: hiccup isn't ambiguous at all, it's just a teeny bit non-trivial to parse

16:54 tolstoy: brehaut: No prob! Just curious.

16:55 brehaut: fliebel: enlive is verbose because xml is verbose :P

16:56 fliebel: brehaut: I thought the point of a DSL was to... nvm, I'll just use (format "<xml>" foo bar) ;)

16:57 brehaut: fliebel: but you almost never need to reference the node enlive structure directly in either enlive or the older clojure.xml stuff

17:00 fliebel: amalloy: [:tag {:foo 1} "bar"], now did I make an attribute, or added a map as a child?

17:00 amalloy: you can't add a map as a child, because children are always vectors

17:01 you can't have attrs free-floating in an xml document: they're attached to a tag

17:01 you're right that it's awkward to add an attribute to a node that might or might not have an attr-map already; you can avoid this by creating nodes that have empty attr-maps instead of no map at all

17:02 i guess you're saying that hiccup isn't a format that's easy to modify programmatically once it's been written - i agree with that

17:04 fliebel: amalloy: What I'm saying is that tag and content map nicely to key/value or first/rest, attr is why we can't have nice things.

17:05 Chousuke: that's a fault in XML :p

17:05 at least regarding a Clojure DSL design

17:06 fliebel: Chousuke: true

17:10 * kephale shakes fist at amalloy. I keep pressing C-t now

17:10 amalloy: kephale: i rebound C-t to transpose-sexps, which is something i use a lot more often

17:10 kephale: amalloy: ooo good tip

17:14 fliebel: amalloy: What is C-t? I don't have emacs.

17:15 btw, solution: (defn =m [& args] (and (apply = (map meta args)) (apply = args))) :P

17:15 amalloy: fliebel: transpose-characters

17:16 fliebel: amalloy: like.. rot-n?

17:16 amalloy: turns e|t into te|

17:16 (where | is point)

17:17 transpose-sexps turns (map (some-seq) | f) into (map f (some-seq)|)

17:17 fliebel: nice

17:17 Raynes: That makes me happy.

17:20 schaefer: hi. anyone here familiar with the insides of core.logic? i'm interested in implementing the IUnify* protocols and would like a little direction

17:20 clojurebot: http://clojure-log.n01se.net/date/2009-10-13.html#12:02

17:21 Raynes: ambrosebs is totally not familiar with core.logic.

17:21 amalloy: well, clojurebot, i guess maybe he wanted to know about protocols in general. good try

17:21 schaefer: heh

17:22 ambrosebs: well i didn't write them :P

17:22 schaefer: ah.. i missed your nick on the list :)

17:22 ambrosebs: but I can open the source and make some sense of it

17:22 what are you try ing to do?

17:22 schaefer: so, i'm looking to incorporate a database as a source of facts

17:23 i just started looking at the code about an hour ago and it looks like i need to implement the IUnify* protocols but i'm a lost on what each one of them does

17:25 klutometis: What do you call the property of `defn' such that I can do: (let [] (def x 2)) x => 2. Doesn't that break lexical scoping in the sense that `x' shouldn't be visible outside the `let'?

17:25 Doing e.g. `(let () (define x 2)) x' in Scheme gives me ``Error: unbound variable: x'', which is lexically consistent.

17:25 s/defn/def/

17:26 schaefer: i don't know if you're familiar with mandarax (a java backwards reasoning system). it defines an interface which supplies a set of constraints and return a resultset-like lthing. an RDBMS implementation simply converts the constraint parameters into SQL and returns a wrapped JDBC result set

17:26 fliebel: klutometis: clo*s*ures

17:27 oh, no

17:27 klutometis: fliebel: That's my point, dude: x shouldn't be visible outside of that closure. Clojure is breaking lexical scoping.

17:28 fliebel: klutometis: yes, in Clojure def just defines a var outside of the let scope. Going to bed now...

17:28 technomancy: klutometis: vars are totally different things from locals; you seem to be confusing the two

17:28 klutometis: fliebel: Thanks.

17:28 aperiodic: klutometis: def doesn't create a closure, it defines a var in the namespace

17:30 klutometis: aperiodic: Oh, ok; I'm used to Scheme, where even `define' won't break lexical scoping.

17:30 * klutometis must erase the def-define analogy from his neurons.

17:31 amalloy: "break" is a strong word

17:31 technomancy: def doesn't create locals; it has nothing to do with lexical scope.

17:31 klutometis: technomancy: This whole locals/vars dichotomy is another way of saying: "we don't respect lexical scope."

17:32 amalloy: scheme just guarantees that if the first "chunk" of expressions in a define are themselves defined, they get given lexical scope

17:32 klutometis: amalloy: Good point.

17:32 technomancy: klutometis: lexical scope is for locals

17:32 it's totally unrelated

17:32 gfredericks: dangit ^J won't work in the browser.

17:32 amalloy: define normally creates dynamically-scoped variables, even in scheme

17:32 klutometis: technomancy: Right; circular argument, though.

17:32 amalloy: there's just this crazy exception for if it's at the beginning of another define

17:32 gfredericks: i think most browsers do have a shortcut for that though

17:32 klutometis: amalloy: Really? I'm trying to conjure up an example.

17:33 amalloy: in the url bar, anyway

17:33 * brehaut restrains himself from a web framework pun

17:33 klutometis: amalloy: Oh, in the sense that `let' reduces to `define'.

17:33 amalloy: klutometis: well, i'm not a scheme expert at all. but (define (foo x) (...blah...) (define (bar y) 10)) is undefined, i believe

17:34 i read that in sicp, so it must be true

17:35 technomancy: that's like saying set! "breaks" variables because it changes their value. it's what it's there for.

17:35 klutometis: amalloy: Hmm; I mean, `bar' is visible within `foo' but not outside of `foo'. Is that what you mean?

17:35 The actual return value of `define' is the value `#<unspecified>'.

17:36 amalloy: no, i mean, it's not defined by the scheme standard. your scheme implementation can do whatever it wants

17:36 klutometis: Oh, right; `unspecified'.

17:36 Thanks, guys.

17:40 amalloy: technomancy: heh. set! *does* break variables, which is what it's there for

17:40 technomancy: amalloy: the horror

17:46 aperiodic: is there a handy way to handle posix signals in java/clojure?

17:47 Raynes: aperiodic: http://stackoverflow.com/questions/40376/handle-signals-in-the-java-virtual-machine

17:49 klutometis: technomancy: Heh, missed that the first time around.

17:50 aperiodic: Raynes: so not within the context of my application?

17:52 kd4joa: Anyone here know the Midje testing package well and could help with a question?

17:54 I want to test a function that returns a list of hash maps but only care that the maps have a particular key. I don't care about the rest of the map.

17:54 hiredman: contains?

17:54 clojurebot: contains? is for checking whether a collection has a value for a given key. If you want to find out whether a value exists in a Collection (in linear time!), use the java method .contains

17:54 kd4joa: In other words the function returns [{:id 1 :score 1.5} {:id 2 :score 0.5}] and I only care that the maps have :id 1 and :id 2

17:55 I tried contains but it didn't seem to work right. I tried [{:id 1 :score 1.5} {:id 2 :score 0.5}] => (contains [ { :id 1} {:id 2} ])

17:55 and a couple other permutations of that

17:56 hiredman: well, uh, that is plainly wrong, so I suggest you read some docs

17:58 kd4joa: thanks. that's very helpful.

18:00 aperiodic: ,(contains? {:id 1} :id)

18:00 clojurebot: true

18:00 aperiodic: ,(contains? [{:id 1}] :id)

18:00 clojurebot: false

18:01 carllerche: I'm trying to write some documentation for a async / future library I'm working on. If anybody has some time, i would appreciate feedback: https://github.com/carllerche/momentum/blob/master/src/clj/momentum/core/async.clj

18:06 moogatronic: kd4joa: are you just wanting know know whether every map in your list contains :id ?

18:08 kd4joa: no, I want the maps to have the pair :id 1 and :id 2

18:08 I thought the Midje contains function was for that but can't get the syntax for it right I guess

18:09 I don't care about what the rest of the keys and values in the maps are

18:09 alexbaranosky: k4djoa: I think you're right

18:09 what do you need to test exactly?

18:09 that a certain map contains some key-val pairs?

18:10 moogatronic: looks like he wants to test if a list of maps collectively contain given key-value pairs.

18:11 kd4joa: yes. moogatronic has it right

18:11 alexbaranosky: don't think midje has a built-in checker for that

18:11 kd4joa: ok. thanks. I thought the contains checker might work for it, but I haven't been able to get it to work so it must not

18:11 alexbaranosky: kd4joa: let me investigate further

18:12 you can just write function for it

18:12 kd4joa: yeah that's what I'll have to do then. I just thought I was being dense about the contains checker

18:12 alexbaranosky: then say: (fact (my-function-call) => (partial maps-contain { ......}))

18:13 kd4joa: thanks for the help! much better than "go read some docs" answer I got a little bit ago

18:13 alexbaranosky: kd4joa: though don't quote me on the syntax, I haven't needed to test that kind of thing

18:13 I've used aMidje a lot

18:14 kd4joa: le t me know how it goes, and if you have any more questions

18:14 moogatronic: At first i thought you were asking this:

18:14 (reduce #(and %1 (contains? %2 :id)) true [{:id 1 :score 1.5} {:id 2 :score 0.5}])

18:15 but i think just need a function to or some internal may k/v checks

18:17 Raynes: kd4joa: Don't mind him. He means well.

18:18 You can't have an apple tree without a few rotten apples at some point.

18:18 moogatronic: hard cider!

18:18 technomancy: moogatronic: not for Raynes; he's underaged.

18:18 (at least in the US)

18:19 Raynes: ;)

18:19 moogatronic: I think "hard cider" is a US'ism anyway -- cider means fermented apple juice everywhere else I think.

18:19 alexbaranosky: technomancy: but there's a blue hair law - if your hair's blue you can drink at 16

18:19 moogatronic: alexbaronsky: ONLY when operating a vehicle though, i'm pretty sure.

18:20 Raynes: I only drink when I need to drive long distances. It helps me stay focused.

18:20 kd4joa: Thanks all. I've found the clojure community very welcoming to newcomers. I know there are exceptions in every group

18:21 alexbaranosky: Raynes: but yeah totally legal in 49 states -- if your hair is blue

18:21 Raynes: I'm golden then.

18:21 alexbaranosky: ok, I'll stop polluting the airwaves with bad humor ;)

18:23 moogatronic: the uc davis cop may provide you with some sriracha to the face if you don't stop. =)

18:33 gfredericks: java interop in jruby never ceases to aggravate.

18:33 $inc clojure

18:33 lazybot: ⇒ 4

19:10 yaron2343: Anyone been playing with defrecord? I'm tearing my hear out on an issue and was hoping for some help.

19:11 brehaut: yaron2343: just ask your question, if someone can help they will

19:12 yaron2343: I am using a trivial defrecord (defrecord connection-record [next-state conf-func]) in my clj file. I then C-c C-l the whole clj file into my repl (e.g. via swank). Any attempt to reference the record fails. I try import (e.g. (import lib-phl.core connection-record)) and that fails to.

19:12 I just get class errors.

19:15 tolstoy: Is your repl in the same namespace as the file? (I got nothin.)

19:16 yaron2343: No, it's not. That's why when I try to reference the record I use a fully qualified name (e.g. lib-phl.core/connection-record

19:16 I also tried lib-phl.core.connection-record out of desperation

19:16 brehaut: yaron2343: but if you are sending the record to a different name space then its going to be created there

19:18 yaron2343: I tried connection-record by itself and it doesn't work. Where as other functions I defined in the clj file show up just fine so long as I prefix them with lib-phl.core. For example lib-phl.core/is-connection-record? Shows up just fine.

19:18 It's only the class defined with defrecord that doesn't show up.

19:18 brehaut: oh, dashes in record names is a bad idea

19:18 try ConnectionRecord

19:18 to avoid having name munging

19:19 i would guess that connection-record is being name munged to connection_record for the classname

19:19 yaron2343: I actually figured that as well and tried _ but it didn't make any difference.

19:20 I also tried that with my namespace that also has a dash in it (e.g. typing in lib_phl.core instead of lib-phl.core)

19:20 What's weird is that functions defined in my clj file that use the record work just fine!

19:21 brehaut: yaron2343: records are much more complex than functions

19:21 yaron2343: Indeed, I'm seriously considering just moving all my code back to structs. At least those worked easily. :(

19:21 brehaut: try running your defrecord directly in your repl, rather than sending it to the repl from the editor

19:21 jeez, not structs. just use maps

19:22 yaron2343: Oh if I define the record in the REPL directly then everything works just fine.

19:22 brehaut: ok so its not a defrecord problem, its someting to do with your slime usage

19:22 yaron2343: It's only if I try to load the file C-c C-L or the buffer segment C-c C-R that I'm in trouble.

19:23 Yeah it smells strongly like a class path resolution issue

19:23 It's not finding the class.

19:23 For example, when I try to C-c C-l my test file I get the error lib-phl.core.connection-record ClassNotFoundException

19:24 And yes, I tried changing it to (:import [lib-phl.core ConnectionRecord]) and sure enough I get lib-phl.core.ConnectionRecord ClassNotFoundException

19:24 alexbaranosky: yaron2343: you could always just use maps

19:24 yaron2343: Yup, that's sounding like the right answer. (Just using maps)

19:24 alexbaranosky: yaron2343: does the namespace also have a dash? That becomes part of the class name I think

19:25 yaron2343: Yes, the namespace does have a dash.

19:25 alexbaranosky: that is getting underscorified too

19:25 yaron2343: (ns lib-phl.test.core

19:25 (:use [lib-phl.core])

19:25 (:import [lib-phl.core ConnectionRecord])

19:25 (:use [clojure.test]))

19:25 alexbaranosky: but really maps are the 90+% tool

19:26 yaron2343: I ran into similar problems as you, and was told to just NOT put -'s in namespaces that contain records... It may be your problem. I just decided to screw it and use maps instead for my use case

19:27 yaron2343: Yeah, I think you're right. Records hurt too much and don't give me enough value. I mostly wanted them because they were easier than duck typing and could catch some errors.

19:28 Although before I finally throw in the towel I will recreate my project without any -s. Won't take long and I hate to give up because I'm confused as opposed to understanding the feature and deciding it doesn't work.

19:29 alexbaranosky: yaron2343: let me know how it goes, I would like to know if that fixes the issue or not

19:29 yaron2343: Will do, am trying to throw it together now.

19:34 amalloy: (inc maps)

19:34 lazybot: ⇒ 1

19:34 mindbender1: I hope it's not a stupid question.. but what are the uses of closures in any language?

19:36 alexbaranosky: mindbender1: they have LOTS of uses

19:37 amalloy: consider a simple example: (let [x 10] (filter #(< % x) some-sequence))

19:38 yaron2343: O.k. so the good news is that removing the - did resolve the problems I was having in the main file. But not in my test file I'm getting a new error "libphl/core__init.class or libphl/core.clj on class path FileNotFoundException.

19:38 I'm guessing this is because of my import

19:38 mindbender1: alexbaranosky: please some education

19:38 yaron2343: I have no clue if lein sets up the class path correctly so that the test files see the src files

19:39 alexbaranosky: mindbender1: use closures anytime you want to tell another function HOW - anytime you might use a Strategy pattern for example

19:39 so higher order functions need to be configured with another function -- so you might want to use a closure

19:40 (defn do-something-to-each-twice [f coll] (map f (map f coll)))

19:41 ;; better: (defn do-something-to-each-twice [f coll] (map (comp f f) coll))

19:41 then call it with a given function aor closure

19:42 (do-something-to-each-twice inc [1 2 3]) ;=> (3 4 5)

19:42 mindbender1: how does f tell do-something-to-each-twice HOW

19:42 alexbaranosky: mindbender1: you could replace 'inc' here with any closure

19:43 can you ask a more elaborate question? I don't know what you need to know

19:44 mindbender1: alexbaranosky: from my understanding closures hold a kind of state right?

19:45 alexbaranosky: ahhhh, sometimes

19:45 aperiodic: they're often used that way in javascript

19:46 alexbaranosky: it just means I can create a closure, that references a local var in one context, then pass that closure to another context

19:49 amalloy: one usage of closures is to let you, basically use a variable that "belongs" to one function inside a completely unrelated function

19:49 eg in my example, (let [x 10] (filter (fn [item] (< item 10)) (range 30)))

19:49 how can filter, which knows nothing about x, manage to use that variable? it's because we've packaged x up inside of the function we give it

19:50 gfredericks: amalloy: you left x out there?

19:50 amalloy: hah, yes

19:51 though it still applies equally well. how does filter, in clojure.core, know about the value 10? i didn't pass it 10

19:51 i passed it this function, which knows about 10

19:53 yaron2343: O.k. defrecord really is painful. So with a map both (:a b) and (b :a) work just fine. But with defrecord only (:a b) works.

19:56 TimMc: yaron2343: and (.a b)

19:57 gfredericks: hmmm...what's the reasoning for that?

19:57 yaron2343: Yeah, that makes sense. Although it also argues against using defrecord. I want Clojure to get away from Oop.

19:57 Because the keyword is effectively an accessor and a record is a class.

19:58 So you are asking for property "a" on the record

19:59 gfredericks: but records deliberately have the map interface, so it's strange they wouldn't implement the IFn side of maps as well

19:59 brehaut: yaron2343: why have you decided to use a record over a map?

19:59 gfredericks: I guess records might want to provide their own IFn :/

19:59 yaron2343: The reason for going to a record was that I wanted to do type checking and equality checking and records make that much easier.

20:00 amalloy: gfredericks: more importantly calling records wouldn't be nearly as fast as caling keywords

20:00 yaron2343: I'm also hoping that eventually clojure will make type hints enforceable

20:00 Yes, I'm a typist. :) But Scala hurt too much so I'm sticking with Clojure

20:00 gfredericks: amalloy: I would think uniformity of interface would trump that consideration

20:01 yaron2343: (F# was actually fun, much easier for me than Scala but I there isn't good IDE support on my mac)

20:01 amalloy: gfredericks: if uniformity of interface were all that mattered, we wouldn't have records or structs at all

20:01 brehaut: its fairly idiomatic in clojure maps that are used objectfully to have (:keyword map) access and maps that are used mapfully to have (map index) lookup, and records are specifically an optimized objectful map, so it makes sense that only the former is supported

20:02 yaron2343: brehaut - How do you tell the difference between an objecfull map and a manful map?

20:02 er manful I meant :)

20:02 mapful

20:02 (Damn you autocorrect!)

20:03 brehaut: well to start an objectful map will have all keyword keys

20:03 quite possibly will have heterogenous values

20:03 and as a whole represents one 'object' in the system

20:03 where as a mapful map may have any kind of key, often has homogenous values and represents an aggregation in the system

20:05 gfredericks: amalloy: that second one is harder to imagine

20:05 why homogenous values?

20:05 amalloy: brehaut: sorry, meant to brehaut

20:06 yaron2343: Then I'm fully guilty of being objectful

20:06 brehaut: yaron2343: objectful maps are idiomatic clojure

20:06 gfredericks: because thats often how they are used? perhaps homogenous value _types_ would be clearer?

20:06 yaron2343: Now if I can just figure out why C-c C-l on my core.clj file in my test directory is producing a "Could not locate libphl/core__init.class or libphl/core.clj on class path: [Thrown class java.io.FileNotFoundException]

20:07 Note btw that "lein test" from the command line works just fine.

20:07 gfredericks: brehaut: do you have an example?

20:07 brehaut: gfredericks: im sure i must

20:07 yaron2343: brehaut - Then I suppose using records makes sense for me.

20:07 So whatever my issue is, it's some swank related thing

20:07 brehaut: yaron2343: but its idiomatic to use maps _until_ records are shown to be needed (for protocols, or performance)

20:08 ,(frequencies "aababc")

20:08 clojurebot: {\a 3, \b 2, \c 1}

20:08 brehaut: gfredericks: ^ a really trivial example

20:09 yaron2343: brehaut - What's the flag that should trip one to think about records? My use of maps is to pass around a state object. The only reason I used records at all is that it made it easy to see if someone submitted the right 'type' of map and to do automatically equality testing when I needed to compare states.

20:09 gfredericks: hmm

20:09 brehaut: yaron2343: well, typically clojure programmers dont 'check type'

20:09 gfredericks: yaron2343: why don't maps give you equality testing?

20:10 brehaut: yaron2343: if you profile your code and find map access is slow, then a record may be an option. alternatively if you need to implement a protocol, a map is probably a good choice

20:10 yaron2343: records are surprisingly rare in clojure code

20:10 yaron2343: brehaut - Indeed, I did actually know that. But I'm writing a distributed system where debugging is a nightmare so I need the system to be as helpful as possible in telling me where things went wrong. Checking types helps out a lot with that.

20:10 amalloy: yaron2343: just put another key in your map

20:10 brehaut: yaron2343: pre and post conditions may also help you

20:10 amalloy: {:what-kind-of-thing :my-awesome-state-type ...more keys...}

20:11 using records has way more pitfalls than maps, and taking all of that on just so you can call .getClass for debugging is asking for pain

20:11 yaron2343: gfredericks - Because I'm an idiot. I just realized that works. :( Thanks for pointing this out. At least now I know.

20:12 gfredericks: yaron2343: now all you need to do is loosen up about checking types and you're golden :)

20:12 yaron2343: brehaut - Actually pre and post conditions is where I do the type checking. I use instance?

20:12 gfredericks: yaron2343: why not write a function that checks if the maps has the expected keys and such?

20:13 yaron2343: gfredericks - That's what I originally did but records gave me that for free

20:13 gfredericks: that tells you more than calling instance? on a record, since a record could be initialized with nulls and all that

20:13 tells you more if you examine the values as well I mean

20:13 yaron2343: gfredericks - Which is why the calls after instance walked through the various keys and checked if they were right. And yes, the more I type the more I realize that records were the wrong choice. Just too much overhead for very little benefit.

20:14 Thankfully Clojure produces such awesomely tight code that changing everything from records to maps will be easy.

20:19 BTW is something like this idiomatic? (defn

20:19 create-state [state-function connections]

20:19 (hash-map :state-function state-function :connections connection))

20:19 The goal is to make it easy to remember what a state is supposed to have

20:19 gfredericks: a shallow answer is you could use a map literal instead of the hash-map function

20:20 yaron2343: Yeah, I know. But I find the short syntax makes it harder for me to read the code. That's just a personal thing for me.

20:20 Does it really make any functional difference?

20:20 gfredericks: not that I know of

20:20 I'm like that too with new

20:21 so you're asking about having a map-assembler function instead of creating the maps inline everywhere

20:21 yaron2343: Yup. Just to prevent typos and such.

20:22 gfredericks: I personally like it, but I tend to be on the type-checking-lover side of things, so I expect people around here to disagree with me

20:23 yaron2343: gfredericks - I love type checking. The only reason I'm not using Scala is that it's type inference logic was painfully bad and the community is about as friendly as a bear trap. But that could just be me. :)

20:23 gfredericks: yaron2343: I suspect that testing instead of doing static types is probably more fruitful

20:24 yaron2343: BTW, what is the difference between FN and IFN?

20:24 amalloy: instead, abstract it a level: (defn make-state-object [a b] (...)) (defn is-state-object? [x] (...))

20:24 yaron2343: I did try looking this up but I couldn't find a good answer

20:24 gfredericks: then you're reasonably sure you have your types right, but also reasonably sure the program works right, which static compilers can't tell you

20:24 yaron2343: am alloy - That's exactly what I'm doing. I have a create-state and is-state?

20:24 gfredericks: yaron2343: FN is a class, IFN is an interface

20:25 yaron2343: gfredericks - Bingo! Thank you!

20:25 So if I want to check if a value is a callable function will IFN? give me wider coverage?

20:25 gfredericks: most of the interface names start with I, though for some reason not all of them

20:26 yaron2343: I notice that just about everything in clojure seems to have interfaces on it

20:26 I just want to check if a value is a callable function

20:26 gfredericks: &(instance? clojure.lang.IFn [])

20:26 lazybot: ⇒ true

20:26 gfredericks: depends on if you want vectors, maps, and sets to return true :)

20:26 amalloy: then you can use maps, and later use records if you truly find yourself needing them

20:26 yaron2343: gfredericks - That's actually o.k., if it walks like a duck…. :)

20:27 gfredericks: then yep

20:27 amalloy: (hint, though: you won't find yourself needing records)

20:28 yaron2343: :) Makes sense. Gotta run! Thanks everyone for your help! You helped move my clojure project forward. I appreciate it!

20:29 brehaut: ,@#'clojure.core/global-hierarchy

20:29 clojurebot: {:parents {}, :descendants {}, :ancestors {}}

20:29 brehaut: ,(derive ::a ::b)

20:29 clojurebot: nil

20:29 brehaut: ,(derive ::c ::a)

20:29 clojurebot: nil

20:29 brehaut: ,@#'clojure.core/global-hierarchy

20:29 clojurebot: {:parents {:sandbox/c #{:sandbox/a}, :sandbox/a #{:sandbox/b}}, :ancestors {:sandbox/c #{:sandbox/a :sandbox/b}, :sandbox/a #{:sandbox/b}}, :descendants {:sandbox/a #{:sandbox/c}, :sandbox/b #{:sandbox/a :sandbox/c}}}

20:29 brehaut: gfredericks: ^ global-hierarchy is an objectful map, but its 3 fields are mapful

20:29 gfredericks: also, the homogenous type might be an implicit union type

20:29 gfredericks: for instance the maps in the fields of the hierarchy have a sets of an implicit union of class and clojure.lang.Named

20:29 aperiodic: brehaut: what is the @#' prefix doing there?

20:29 brehaut: its private, so #' is avar quote to access it, and then @ to deref the var to get the actual value

20:29 ,clojure.core/global-hierarchy

20:29 clojurebot: #<CompilerException java.lang.IllegalStateException: var: clojure.core/global-hierarchy is not public, compiling:(NO_SOURCE_PATH:0)>

20:29 brehaut: ,#'clojure.core/global-hierarchy

20:29 clojurebot: #'clojure.core/global-hierarchy

20:29 brehaut: ,(class #'clojure.core/global-hierarchy)

20:29 clojurebot: clojure.lang.Var

20:29 brehaut: aperiodic: make sense?

20:29 aperiodic: huh, i didn't know you could do that

20:29 brehaut: yeah, thanks!

20:29 brehaut: aperiodic: extremely useful for testing things

20:29 aperiodic: i'm still not entirely clear on how vars, environments, and namespaces interact during evaluation

20:29 brehaut: aperiodic: with a sprinkling of magic ;)

20:29 moogatronic: how much documentation does anyone reading this and wanting to reply usually put in their docstrings?

20:29 brehaut: moogatronic: err… not sure i understand what you are asking

20:29 yaron2343: just dont ;)

20:29 but yes

20:29 moogatronic: (defn function "docstring" [] body) how much do you write in the doc string?

20:29 brehaut: moogatronic: as much as is required to describe the intent and contract of the function

20:29 moogatronic: as much as say, a javadoc?

20:29 brehaut: moogatronic: if you use marginalia you may also write more to add to the overall narrative

20:29 * brehaut hasnt written javadoc in years

20:29 moogatronic: brehaut: marginalia is on my list of things to invetigate.

20:29 brehaut: id say its similar to whats normal for python functions, thoguh not classes

20:29 moogatronic: its extremely straight forward.

20:29 moogatronic: I just like the formalism of javadoc... Defined spot for @param @return etc..

20:29 brehaut: moogatronic: none of that nonsense, we have metadata for that

20:29 moogatronic: docstrings are for prose (and perhaps example usage)

20:30 amalloy: yaron2343: "free" is a huge overstatement

20:30 gfredericks: I think my IRC client just went bonkers

20:30 brehaut: gfredericks: i think you mean ifn?

20:31 ,(ifn? [])

20:31 clojurebot: true

20:31 moogatronic: brehaut: do you have a small example demonstrating metadata as a replacement for some of the 'javadoc' ish crap?

20:31 amalloy: gfredericks: no, network issue of some kind

20:31 moogatronic: gfredericks: mine too.

20:31 gfredericks: now I'm doubting everything that happened in the last 10 minutes

20:31 brehaut: moogatronic: i have a large example? https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj

20:32 moogatronic: haha large or small, i was trying to minimize imposed burdon.

20:32 brehaut: moogatronic: be aware that :tag is the not just documentation, its used by the compiler so dont go adding it wildly

20:33 moogatronic: overall, there is much less of that stuff than javadoc though

20:34 gfredericks: brehaut: half of the stuff you said about mapful maps came in in a lump just then

20:35 brehaut: gfredericks: huh. sorry about that

20:35 gfredericks: i assume my internet is lagging to crap again

20:35 amalloy: brehaut: gfredericks is accusing you of causing the network issue that all of freenode just felt

20:35 gfredericks: brehaut: I doubt it's your fault :) I was just explaining any apparent lack of ACK

20:35 amalloy: no apologizing

20:35 brehaut: oh! haha

20:36 gfredericks: me and amalloy: ignorant cop, explanatory cop

20:36 amalloy: although... relevant: http://xkcd.com/945/

20:39 gfredericks: oh there goes google wave

20:41 brehaut: gfredericks: it was still around?

20:42 gfredericks: apparently

20:49 amalloy: haha google knol too

20:51 brehaut: are they sending the old dogs to the farm?

20:52 gfredericks: dog foo is expensive

20:53 as is dog bar

20:56 moogatronic: .. i finally discovered what laziness is for. I feel like the world played the "you just discovered a secret room" song from "the legend of zelda"... code I wrote earlier today is now comical.

20:57 amalloy: moogatronic: well then, what is laziness for? you don't really know until you can explain it :)

20:58 moogatronic: amalloy: true enough. In my case it was that I just realized how I could utilize the lazy-sequence to accomplish some list generation tasks that I was using loop/recur for...

20:59 but everyone knows the answer to everything is 42.

20:59 brehaut: nah, the answer to everything is "No"

20:59 gfredericks: brehaut: is it really?

20:59 brehaut: No

21:00 gfredericks: well that explains it then, thanks!

21:00 brehaut: gfredericks: if that seems inconsistent to you, you dont know prolog ;)

21:00 gfredericks: Do I know prolog??

21:00 lazybot: gfredericks: Definitely not.

21:00 brehaut: No

21:01 gfredericks: ~prolog

21:01 clojurebot: Pardon?

21:02 moogatronic: Are we doing the "This statement is false." thing? =)

21:02 brehaut: No

21:02 moogatronic: 42

21:02 amalloy: moogatronic: gfredericks seems to be. near as i can tell, brehaut is enjoying saying "your statement is false, or your question has no correct answers"

21:03 brehaut: amalloy: theres also the 'none of the facts i know imply this'

21:03 amalloy: No further universes exist which satisfy all of your constraints

21:03 brehaut: exactly

21:03 its the extent of my prolog based humour

21:04 i guess i should at least port the joke to core.logic

21:04 amalloy: you've got em rolling in the aisles

21:06 brehaut: sorry #clojure

21:07 aperiodic: got any erlang jokes?

21:08 brehaut: i do not

21:08 gfredericks: there cannot be any erlang jokes because it has no flaws

21:08 aperiodic: that's a pretty big flaw right there

21:09 gfredericks: is nil the only argument for which type returns nil?

21:09 amalloy: uhhhh, i think that's true, yes

21:09 TimMc: ,(doc type)

21:09 clojurebot: "([x]); Returns the :type metadata of x, or its Class if none"

21:10 TimMc: ,(type ^{:type nil} [1 2 3])

21:10 clojurebot: clojure.lang.PersistentVector

21:10 gfredericks: I've a multimethod that dispatches on type and was just curious if (defmethod nil) knew for sure the argument was nil

21:10 TimMc: ಠ_ಠ

21:10 gfredericks: ,(binding [type (constantly nil)] (type []))

21:10 clojurebot: #<IllegalStateException java.lang.IllegalStateException: Can't dynamically bind non-dynamic var: clojure.core/type>

21:10 amalloy: TimMc: i know, i thought of that too. but i remember reading that it does (or (:type (meta x)) (class x))

21:11 as opposed to (:type (meta x) (class x))

21:11 TimMc: "or its Class if none", right

21:11 gfredericks: ,(with-redefs [type (constantly nil)] (type []))

21:11 clojurebot: nil

21:11 TimMc: hrmf

21:12 amalloy: fwiw, putting reader metadata on stuff when you want it to have metadata at runtime makes me super-nervous, TimMc

21:12 (with-meta [1 2 3] {:type nil}) seems a lot safer to me

21:13 gfredericks: that's an interesting distinction

21:13 untrustworthy macros?

21:13 TimMc: I will admit to knowing basically nothing about metadata. :-)

21:14 ,(:type ^{:type 'foo} [])

21:14 clojurebot: nil

21:14 TimMc: ,(:type (with-meta [] {:type 'foo}))

21:14 clojurebot: nil

21:14 TimMc: ugh

21:15 amalloy: gfredericks: not untrustworthy, it's just...reader metadata is for the compiler. in most cases it will leak over into your program and you can use it as runtime metadata

21:15 but depending on that doesn't seem good

21:16 TimMc: &(meta ^{:type 'foo} [])

21:16 lazybot: ⇒ nil

21:17 TimMc: right

21:18 aperiodic: there are two kinds of metadata?

21:19 amalloy: no

21:19 there are two times at which you could attach metadata

21:19 (more than two, really)

21:19 aperiodic: read-time and eval-time?

21:20 amalloy: yeah, that's the distinction i was drawing

21:20 but there's also macroexpansion time

21:21 aperiodic: you say that in most cases metadata attached during read-time exists in runtime, but could you provide an example where that doesn't happen?

21:22 amalloy: &(meta ^{:type 'foo} [])

21:22 lazybot: ⇒ nil

21:22 TimMc: ^

21:22 aperiodic: huh

21:23 TimMc: But a macro would see it, yeah?

21:23 amalloy: yes

21:23 &(meta ^{:type foo} [1])

21:23 lazybot: ⇒ nil

21:23 amalloy: at the moment i can't even find an example where it *does* leak over to runtime

21:24 &(meta ' ^{:type foo} 1)

21:24 lazybot: java.lang.IllegalArgumentException: Metadata can only be applied to IMetas

21:24 amalloy: &(meta ' ^{:type foo} (1))

21:24 lazybot: ⇒ {:type foo, :line 1}

21:25 aperiodic: why does the metadata disappear?

21:25 amalloy: it doesn't. it was never there

21:25 you pass the compiler an object, x, with metadata on it. it emits the bytecode necessary to reproduce x

21:26 aperiodic: up to equality?

21:26 amalloy: at runtime, that bytecode is executed to create a brand-new x

21:26 but the metadata was for the compiler, not for you

21:26 aperiodic: ah, got it

21:27 amalloy: well, that makes one of us

21:27 it's a confusing issue either way

21:30 aperiodic: so if i want to attach metadata visible at runtime, i should use with-meta, rather than the reader macro, because metadata attached at read-time (usually) gets eaten by the compiler?

21:35 brehaut: i pressed some magical emacs chord by accident: all my html got stripped out and left only the text

21:36 moogatronic: brehaut: -x u!

21:36 aperiodic: the compilation process for clojure is way harder for me to wrap my head around than any other language i've used

21:37 hiredman: aperiodic: do go on

21:37 brehaut: aperiodic: and yet its probably much simplier than most of them

21:39 aperiodic: hiredman: well, it seems to start with the reader, which is what takes string data and turns it into clojure forms

21:39 brehaut: aperiodic: so far so good

21:40 aperiodic: but i've seen some references to reader macros that cause evaluation (i think #=?)

21:40 hiredman: oh, well, if that is complicated then you've never used a lisp

21:40 aperiodic: how can you be doing evaluation at read-time? what's the environment?

21:40 i haven't

21:41 brehaut: aperiodic: question: what do you think the compilation unit of clojure is?

21:41 aperiodic: that's undoubtedly part of my woes

21:41 hiredman: which means you don't have a basis for comparison

21:41 I suggest you go write a lisp, even a simple one

21:43 * brehaut seconds

21:43 aperiodic: brehaut: unit ~ atomic to compilation?

21:43 brehaut: aperiodic: so in java the compilation unit is the class (i believe), it might be the package

21:43 in C its the source file

21:43 aperiodic: brehaut: the first thing that popped into my head was namespace

21:44 brehaut: aperiodic: its a single form

21:44 amalloy: man, i don't even know what clojure's compilation unit is

21:44 i'd guess top-level form

21:44 brehaut: amalloy: toplevel or eval expression i think

21:44 which is why we have declare for forward declarations

21:44 amalloy: suuuure, but those are just top-level in a different context

21:46 brehaut: i guess you could think of it that way, but its slightly circular

21:46 aperiodic: the key difference between macros and normal functions is when they run

21:47 aperiodic: brehaut: macros run between read and evaluation, right?

21:47 which is why the arguments are unevaluated forms

21:48 brehaut: aperiodic: macroexpansion is part of the evaluation or compilation process

21:48 its not really 'between'

21:48 gfredericks: where's there a function for transforming keys of a map?

21:48 hiredman: well, it runs ahead of the first pass of the compiler

21:49 brehaut: hiredman: its more clearly seperated with a compiler than a traditional lisp evaluator though right?

21:50 hiredman: yes

21:51 aperiodic: brehaut: well, if it runs after its arguments have been read but before they've been evaluated, i'd call that between the two

21:52 brehaut: gfredericks: theres rename-keys ? but thats not an general transform, just a mapping

21:53 gfredericks: ah

21:53 aperiodic: brehaut: but i see your objection (there's evaluation happening in the macro, so they're not distinct phases)

21:53 gfredericks: well zipmap is pretty easy

21:55 alexbaranosky: gfredericks, there's a function `map-keys` in useful

21:56 gfredericks: I need to start using useful

21:56 but only with :only

21:59 amalloy: i kinda frown on the map-keys/values functions in useful, personally

21:59 alexbaranosky: amalloy, do you think that they're a code smell?

22:00 amalloy, I havent needed them ..... yet

22:00 amalloy: i don't have a very good reason. i just wish people would stop going map->seq->map, which gets you the worst of both worlds performance-wise

22:52 fbru02: ehi guys i have a macro question anybody up to help?

22:53 amalloy: ~anyone

22:53 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

22:54 fbru02: :)

22:56 so i want to check on one of the arguments and recursive call the macro if one of the arguments is not of the specified type (defmacro my-macro [arg1 arg2 & rest] (if-not (map? arg2) `(mymacro arg1 {} ~@rest)))

22:56 so the thing is that i do a macroexpand with this and i never seem to get {} in arg2

22:57 i'm confused

22:58 amalloy: well, there are a couple issues. one is you don't have an else clause for your if; it's unclear whether that's a bad copy/paste or what

22:59 the other is, are you looking at a macroexpand-1 or what? because if you (macroexpand-1 '(my-macro foo bar baz)) from this definition, it should result in '(my-macro foo {} baz)

23:01 fbru02: amalloy: let me try again and if not paste real code

23:01 thanks :)

23:10 callen: okay, you have my attention

23:10 why does the current version of lein not have a "jack-in" verb?

23:10 because that's what my clojure-mode.el is looking for.

23:11 I need to install swank, don't I?

23:11 sigh.

23:11 I forget these things every time.

23:12 * callen kills self

23:16 Raynes: callen: You don't need to install swank.

23:16 And jack-in is definitely in the latest lein.

23:33 callen: Raynes: not by default, had to install swank-clojure plugin.

23:33 Raynes: I just fetched the lein earlier from the repo.

23:33 Raynes: Oh, I thought you meant in Emacs.

23:40 callen: in Emacs?

23:40 clojure-mode just invokes lein.

23:40 there's little that Emacs has to do with it.

23:55 georgek: hi, I have 'clojure-mode-font-lock-setup added to 'slime-repl-mode-hook in my .emacs, but when I connect to a remote swank with slime-connect, I get error in process filter: run-hooks: Symbol's function definition is void: clojure-mode-font-lock-setup

23:55 if I just reconnect, I get the remote repl, but no highlighting

23:55 anyone come across this already?

23:59 spoon16: technomancy around?

Logging service provided by n01se.net