#clojure log - May 24 2011

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

2:41 markoman: I want to split string and include original value on set, what is an easy way to do this? (split #" " "some phrase") -> ("some" "phrase" "some phrase")

2:44 brehaut: (defn str-split-retain [s sep] (into #{s} (.split s sep))) ?

2:49 markoman: works great, thanks

2:50 brehaut: it has a terrible name though :P

2:51 no_mind: is it possible to introduce new tags with enlive html ?

2:53 markoman: name doesnt make man worse, they tell :)

2:53 thorwil: no_mind: i think it has no idea about specific tags, so i guess yes

5:07 clgv: is there something similar to juxt that allows me easily to combine funtions which create a map where every function provides a key and a value?

5:19 hm ok, I looked in clojure and contrib - there seems to be nothing. so I just build my own

5:23 ejackson: look a bit idiosyncratic

5:23 i guess

5:27 clgv: why do you think?

5:28 my use case is (juxt-map :key1 func1 :key2 func2) that generates a function f that returns a map instead of a vector like juxt does

6:21 Is there a condition checking idiom for macro parameters?

6:23 assert-args from core is private unfortunately.

6:31 cemerick: clgv: if the fn does what you want, there's always the #'clojure.core/assert-args backdoor.

6:32 clgv: cemerick: so I should do a "with-private" hack with assert-args?

6:32 cemerick: with-private?

6:33 It's not a hack; you just need to be prepared for potential breakage if assert-args changes

6:34 clgv: ok :(. Maybe it should be made public in general

6:34 wrong smiley...

8:07 no_mind: in enlive, how do i find the value of an attribute for a given node ?

8:16 mefesto`: no_mind: (:attrs node) ?

8:16 or possibly: (get-in node [:attrs :blah])

8:21 raek: no_mind: you can use select to extract the node in question (which is represented as a map with keys :tag, :attrs and :content) and then do as mefesto` said

8:24 no_mind: the problem is how do I pass the node to get ?

8:24 clojurebot: People have a problem and think "Hey! I'll use a regular expression!". Now they have two problems....

8:24 no_mind: let me paste teh code

8:25 here is the code http://pastebin.com/JsWS7seg . How do I pass the node ?

8:28 raek: no_mind: is this for transforming a html tree, or extracting data form it?

8:28 no_mind: a transformation is a function that takes a node and returns a node or a sequence of nodes

8:30 no_mind: raek: actually transformation. I need to apply a transformation function based on the type of form element. For which I need to first extract the "type" attribute.

8:30 raek: no_mind: to just get the value: (let [tree (html/html-resource "something.html") node (select tree [(html/id= "entity_label")]) attr (get-in node [:attr :foo])] attr)

8:32 the transformation function could look like (fn [node] (let [type (-> node :attrs :type)] (case type "foo" <foo code> "bar" <bar code> <default code>)))

8:34 (this probably looks prettier if you turn it into a defn)

8:34 no_mind: raek: Let me detail teh problem. I have a html file which has a form. I need to serve this html file by filling the values in form elements. The values of form elements is available as a map containing the elementid as key and corresponding value as the value to be set

8:38 raek: no_mind: but then you don't need to look at the type attribute, right? I think you just need to make one rule for each entry in the map, where the selector is as in your existing code and where the transformation is (set-attr :value "element value")

8:39 (html/at tree [(html/id= "username")] (set-attr :value "raek"))

8:39 no_mind: I need to lookup :tag not :type . The (set-attr :value "value") will work for input type elements butfor checkboxes, select, multi-select we need more work

8:40 raek: I see.

8:40 no_mind: so I was thinking of writingmulti-method for filling value

8:40 butfor multi-method to work, I should be able to identify the type of the node

8:42 raek: (defn tag-multi [node] (the-multi-method (:tag node) node))

8:43 oh, wait.

8:43 no need for that extra function.

8:43 no_mind: then

8:43 ?

8:43 raek: (defmulti your-multi-method (fn [node] (:tag node))) ; this should be enough

8:44 this will make the multimethod dispatch on the element type

8:44 no_mind: raek: Icouldfigure that but cannot figureout how to pass the node from enlive selector

8:45 raek: no_mind: you just do it like this in your at form: (html/at tree ...selector... your-multi-method)

8:45 no_mind: here, "your-multi-method" will receive the node as its only argument

8:45 no_mind: oh ok

8:46 raek: hrm. but you probably want the text value to be passed too...

8:47 timvisher: morning everyone

8:47 raek: (defn fill-in [text] (fn [node] (your-multi-method [node text])))

8:47 (defmulti your-multi-method (fn [node text] (:tag node)))

8:47 timvisher: what could cause a binding expression to _not_ rebind the var, other than perhaps a typo?

8:47 raek: (html/at tree ...selector... (fill-in "value"))

8:48 timvisher: laziness

8:48 timvisher: raek: could you explain that a bit further?

8:48 raek: ,(binding [*out* :foo] (lazy-seq (cons *out* nil)))

8:48 clojurebot: (#<StringWriter >)

8:49 timvisher: ahh

8:49 raek: ,(binding [*out* :foo] (doall (lazy-seq (cons *out* nil))))

8:49 clojurebot: (:foo)

8:50 raek: so the lazy expression does not remember the binding of the var...

8:50 timvisher: and it turns out that deftest runs lazily, i suppose?

8:50 that explains a lot of what i've been expriencing

8:51 no_mind: raek: no luck http://pastebin.com/7UF3ZbRw

8:51 timvisher: i've been assuming that i could wrap all of my deftests in a single binding expression and get a global change

8:51 but i suppose i need to wrap the is expressions instead

8:51 jjido: shouldn't doall force evaluation before the binding is lost?

8:52 dnolen: jjido: yes, but beware of nested lazy-seqs.

8:53 jjido: dnolen: I see...

8:55 raek: no_mind: remove the parentheses around (abc) since you don't want to pass the return value of the function, but the function itself to envlive

8:55 no_mind: k

8:55 raek: no_mind: tag values are keywords, so it should be :input instead of "input"

8:56 no_mind: enlive will only pass one argument to the supplied function (the node), so it is common to make a closure that remembers "extra arguments"

8:57 (defn helper-fn [arg1 arg2 arg3] (fn [node] (the-real-function node arg1 arg2 arg3)))

8:57 (html/at ... ... (helper-fn 1 2 3))

8:58 no_mind: aha

8:58 raek: here, the call to helper-fn will return a function that takes a node, but when that function is invoked, it also knows ablut arg1 arg2 and arg3

9:02 no_mind: https://gist.github.com/988666

9:03 also note how set-attr is called due to the "two stage" way of doing things

9:16 no_mind: raek: thnxs

11:15 raek: around ?

11:15 raek: no_mind: yes

11:17 no_mind: raek: how can one iterateover nodes in enlive. I have a list of nodes in a map with map keys being id of the nodes

11:25 raek: no_mind: you want to transform each entry in the map to one selector-transformation pair?

11:26 no_mind: yes, each node matching the id key in the map

11:30 raek: no_mind: since at is a macro, you can either write a macro that expands into the desired at form, or use loop/recur or reduce and in each iteration make a call to at with only one selector-transformation pair

11:31 no_mind: will the map have different values at runtime? if so, you can't use the macro approach

11:35 no_mind: the second way could look like this: (defn foo [tree form-map] (if (empty? form-map) tree (let [[id value] (first form-map)] (recur (at tree [(id= id)] (abc value)) (rest form-map)))))

11:35 where "abc" is the function from my last gist

11:39 no_mind: ok

11:46 coopernurse: I'm doing this "count a sequence" problem here: http://4clojure.com/problem/22

11:46 My solution: (fn [xs] (reduce + (for [x xs] (+ 1))))

11:46 Site is complaining that I'm using "count", which is prohibited for this problem

11:47 Is there something about for / reduce that I'm not understanding? Or is 4clojure just returning a misleading error message? From what I can tell I'm not using count

11:49 manutter: hmm, for might use count internally

11:50 coopernurse: manutter: I see. maybe they're using trickery to detect that function anywhere in the eval loop?

11:50 manutter: well, I'm just guessing

11:50 could just as easily be a bug at 4clojure too

11:50 coopernurse: ok, well 200+ people figured it out, so there's clearly another right way to do it

11:51 great site btw

11:51 manutter: It sounds good, I haven't gotten around to visiting it yet

11:51 coopernurse: yeah, I'm new to FP, so I'm really getting a workout

11:51 a bit humbling

11:52 manutter: I know what you mean, fp is almost a zen experience

11:52 "And then the Master hit him over the head with an 800 page COBOL listing, and he was enlightened."

11:53 coopernurse: yeah, I told my girlfriend it was like learning mandarin after learning 3-4 romance languages

11:53 you think you're good at languages, and then *bam*

11:53 manutter: indeed

11:55 If I were going to count a sequence without using count, I'd use a map/reduce, but that's just because map/reduce is also blowing my mind ever since I went to the NoSQL track at the last O'Reilly conf.

11:56 coopernurse: good hint. I'll play with that

11:59 jean-philippe: coopernurse: you might want to read on the reduce function, as it already iterates over the whole sequence, no for needed

11:59 coopernurse: jean-philippe: ok thanks

12:03 jean-philippe: coopernurse: or start from the beginning: knowing that a sequence can be expressed as a box containing a single element (the (first seq) function) and and and pointer to the sequence of the remaining elements (the (rest seq) function), and that the empty list can be checked using (empty? seq), how can you recursively count the number of elements?

12:05 coopernurse: can anonymous functions be recursive?

12:05 wastrel: use recur should work

12:05 coopernurse: thanks

12:05 wastrel: your super welcome :]

12:39 coopernurse: I suspect this is not what you guys had in mind earlier.. but it works

12:39 (fn [xs] ((fn [x xs] (if (empty? xs) x (recur (+ 1 x) (rest xs)))) 0 xs))

12:43 jean-philippe: that's quite right, although it could be a bit cleaner using (loop)

12:43 manutter: I think you were closer to a nice solution with your original snippet tho

12:44 coopernurse: manutter: yes, I think they wanted to force you to learn some other bits of clojure.. or it's a bug in the test :-)

12:44 jean-philippe: the reduce function is just an abstraction of that construct

12:45 raek: coopernurse: instead of nesting functions like this, you can use 'loop'

12:45 coopernurse: raek: thanks. reading docs

12:45 raek: coopernurse: (fn [xs] (loop [x 0, xs xs] (if (empty? xs) x (recur (+ 1 x) (rest xs)))))

12:46 coopernurse: ...but it does exactly the same thing as your version

12:47 I would use inc instead of (+ 1 ...), but other than that, this is what I would have written

12:47 coopernurse: raek: thanks. is the default variable binding in: (loop [x 0, xs xs]) a general thing you can do in functions? or is that a loop specific bit of syntax?

12:48 if I'm reading it correctly, we're saying "set x=0 if not provided"

12:48 or am I reading that incorrect?

12:48 incorrectly

12:48 raek: coopernurse: it is only for loop. think of it as ((fn [x xs] ...) 0 xs), but with a different look

12:49 jean-philippe: it's rather, bind x to 0 in the first iteration of the loop, recur will rebind it according to the parameters

12:49 raek: coopernurse: you must always provide a value

12:49 coopernurse: I see

12:50 raek: it has the same syntax as let, but works as fn/recur

12:50 coopernurse: from the docs it sounds like loop avoids recursion under the hood

12:50 so it's faster than my first example that used a nested function

12:50 and won't blow up the stack if xs has lots of elements

12:50 raek: actually, in this case there is no big difference, since you use recur in the other case too

12:51 jean-philippe: for completion's sake, here's the reduce version (fn [xs] (reduce (fn [acc x] (inc acc)) 0 xs))

12:51 raek: i.e. the avoiding-stack-overflow-magic lies in 'recur'

12:51 manutter: you're on the right track with your description of loop/recur

12:51 coopernurse: raek: oh, I see. thanks

12:51 manutter: right, what he said :)

12:53 coopernurse: wild stuff. very terse. curious how long it will take my brain to read these types of constructs

12:54 but I understand why people find lisp elegant. there really isn't much syntax

12:54 amalloy: coopernurse: we macroexpand the form before checking it

12:54 coopernurse: the hard part is learning the vocabulary of all the abstractions built on it

12:56 jean-philippe: the reduce version reads much more cleanly imho.

12:56 amalloy: the solution i find most elegant, though it's not shortest, is (fn [coll] (reduce + (map (constantly 1) coll)))

12:57 which is more or less what you were doing, coopernurse, but with map/constantly intead of for

12:57 coopernurse: amalloy: that is nice.

12:57 btw, what's the party line for making sure your arguments don't name collide with functions?

12:58 amalloy: coopernurse: who cares? shadowing is fine

12:58 some disagree with me, of course

12:58 ataggart: avoid it if it can be confusing to a reader, otherwise, meh

12:58 * technomancy has only seen collisions with arg names like "name" and "map"

12:58 manutter: amalloy: So, if that's not the shortest, what is?

12:58 amalloy: but (fn [list] (map inc list)) is pretty clear if the input is a list

12:58 technomancy: which aren't very descriptive args to begin with

12:59 coopernurse: amalloy: I see.

12:59 ataggart: I think there's a list of idiomatic arg names somewhere

12:59 amalloy: #(.size (vec %)) is probably shortest, but it's surely cheating

13:00 coopernurse: yes, one of the clojure books I'm reading (not sure if it's Joy of Clojure or the pragmatic prog's book) has a list

13:01 amalloy: btw coopernurse, if you want to talk to the devs we generally hang out in #4clojure when we're around

13:01 coopernurse: amalloy: ah, great

13:04 manutter: heh, short == true, cheating == true, check check. :)

13:05 kinda like it tho

13:10 amalloy: &(.size (vec '(1 2 3 1 2 3)))

13:10 sexpbot: ⟹ 6

13:10 amalloy: whew. (true? working) also

13:24 dnolen: interesting core.logic can solve the Einstein constraint problem in < 2ms now, making it nearly 40 times faster at that particular problem than the Prolog implementation in Qi.

13:25 ataggart: dnolen: what reading material do you suggest for someone to be able to grok core.logic?

13:26 dnolen: ataggart: The Reasoned Schemer, William Byrd miniKanren dissertation, Bratko's Prolog for Artificial Intelligence Programming

13:26 ataggart: thx

13:27 * hiredman got bratko's book from goodwill for $2

13:28 defn: good day, gents.

13:30 back in a moment...

13:32 Pisketti: Speaking of books (for noobs), any suggestion for someone who wrote his first line of clojure a few months ago?

13:33 I read Practical clojure and Programming clojure is waiting. I've also thought about ordering The joy of clojure.

13:33 But other than that, any fundamental must-reads?

13:33 SICP maybe? Little schemer?

13:33 nishant: Hey everyone, I'm using the extend construct to make some java classes conform to a clojure Protocol. I am then loading these classes using load, however when I am calling a function on one of these classes, the same function from a different class is invoked, which leads to a "java.lang.IllegalArgumentException: No matching method found" exception. help!

13:34 chojeen: just bought "the joy of clojure", it's pretty nice for a beginner (read: me)

13:34 technomancy: hiredman: I bought that book from zed shaw.

13:35 Pisketti: chojeen: really? I thought it was the first not-the-first-to-read-on-clojure ever written ;)

13:35 hiredman: mine has a "USED" sticker on it, so I think it was a textbook

13:36 amalloy: Pisketti: it was my first clojure book

13:36 (and only, thus far)

13:36 Pisketti: amalloy: but you were not a beginner

13:36 amalloy: when i read it back in july i was

13:37 chojeen: pisketti: sure, but I felt like a challenge, and coming from a decent functional background helps

13:37 amalloy: only had a few weeks' self-taught common lisp under my belt

13:37 Pisketti: I thought you were an old lisp guru :D

13:38 amalloy: JoC is good. it's a little less spoon-fed than the others (i'm told), but if you expend some effort you will learn lots from it whether you know clojure or not

13:38 Pisketti: Goes to show you can learn it pretty fast

13:38 amalloy: indeed

13:38 i'm not old enough to be an old lisp guru :P

13:38 chojeen: I've never found "beginners" books all that helpful, anyway

13:39 qed: JoC is great.

13:39 amalloy: age has nothing to do with guruship.

13:39 amalloy: qed: he said "old lisp guru"

13:39 * qed nods

13:39 Pisketti: chojeen: Yeah, they tend to be geared towards beginner programmers (of any language) which isn't necessarily the case

13:40 amalloy: but yes, i'm aware. i've taken on the mantle of git guru in an organization or two

13:40 coopernurse: I'm 4 days into Clojure. reading JoC and Programming Clojure - both are good. JoC is more complete.

13:40 amalloy: SICP starts by introducing what programming is, but then it gets heavy fast. what a book

13:41 dnolen: nishant: do you have a simple paste of your problem?

13:42 chojeen: JoC appealed to me because it claims to teach "the clojure way", i.e. idiomatic clojure

13:42 Pisketti: http://sicpinclojure.com/ <-- This is extremely interesting. Does the person behind this happen to be on this channel?

13:42 qed: Pisketti: I think he used to be, not sure if he's around anymore.

13:42 It's too bad it hasn't continued. I'm floating the idea to a few people to pick up where he left off.

13:44 Pisketti: qed: Do it! Seriously, that would be a great service to the community. :)

13:45 amalloy: Pisketti, qed: https://github.com/vu3rdd/sicp seems to exist

13:45 Pisketti: Mmm, interesting

13:45 amalloy: might be an easier starting point

13:47 Pisketti: Thanks, I'll check it out.

13:47 * dnolen thinks that SICP is less far useful than a Standard ML text and CTMCP for grokking Clojure.

13:47 Pisketti: How about Little schemer?

13:48 dnolen: Pisketti: Little Schemer is good for picking up the basics of idiomatic Lisp style.

13:48 Pisketti: Or even Land of Lisp. I bought that to a friend, and once he has finished it, I'll read it too.

13:49 dnolen: that's exactly what I'm looking for

13:49 dnolen: Land of Lisp also good but too broad in scope to spend much time on Clojure's unique strengths

13:50 Pisketti: I'm thinking a healthy dose of basics of functional programming would do me good

13:52 There's also Let Over Lambda. I just somehow get the feeling that it might be too hardcore for me at this point

13:52 Not sure though

13:53 amalloy: On Lisp is probably not a good clojure book, but it's a good lisp-in-general book

13:53 qed: Little Schemer is a fun read.

13:54 amalloy: and it has the advantage of beeing free

13:54 qed: The curriculum for learning a lisp is kind of a big mixture IMO.

13:55 It's hard to say there's one approach that everyone should use.

13:55 amalloy: qed: i mostly just loved the gorgeous writing in On Lisp

13:55 reminds you lisp is a beautiful language

13:56 * qed nods

13:56 qed: I'm going to pick up another copy, on that note.

13:56 imade: hello, how's the easiest way to make a list of functions, let's say I have functions last1, last2, last3, last4

13:57 amalloy: [last1 last2 last3 last4]: a list! probably not what you're looking for, though; what do you want to *do* with that list

13:57 qed: &[(fn [x] (+ x 1)) (fn [x2] (+ x2 1))]

13:57 ataggart: xy?

13:57 sexpbot: ⟹ [#<sandbox11964$eval14849$fn__14850 sandbox11964$eval14849$fn__14850@2100f3> #<sandbox11964$eval14849$fn__14852 sandbox11964$eval14849$fn__14852@1541c3f>]

13:57 clojurebot: xy is http://mywiki.wooledge.org/XyProblem

13:57 imade: right now I am trying to do (for [f '(last1, last2, last3, last4)] (f '(1, 2, 3, 4))), but it returns (nil nil nil nil)

13:58 qed: you don't need for

13:58 amalloy: $google clojure list vector difference quote

13:58 sexpbot: First out of 433 results is: Clojure - cheatsheet

13:58 http://clojure.org/cheatsheet

13:58 amalloy: bah

13:58 imade: I am trying to simplyfy my unit testing

13:58 qed: imade: which version of clojure

13:58 amalloy: qed: for is a fine solution. it's the ' that's a problem

13:58 imade: (deftest test-last

13:58 (dorun

13:58 (for [f '(last1, last2, last3, last4)]

13:58 (is (= 4 (f '(1 2 3 4)))))))

13:58 raek: imade: what you wrote is a list of symbols, not a list of functions

13:58 ataggart: ,(doc clojure.test/are)

13:58 clojurebot: "([argv expr & args]); Checks multiple assertions with a template expression. See clojure.template/do-template for an explanation of templates. Example: (are [x y] (= x y) 2 (+ 1 1) 4 (* 2 2)) Expands to: (do (is (= 2 (+ 1 1))) (is (= 4 (* 2 2)))) Note: This breaks some reporting features, such as line numbers."

13:59 imade: but currently it's failing

13:59 amalloy: &((juxt inc dec) 1)

13:59 sexpbot: ⟹ [2 0]

13:59 ataggart: imade: use clojure.test/are

13:59 technomancy: amalloy: was wondering how long it would take before you pulled out el juxt

13:59 raek: imade: you probably want [last1 last2 last3 last4] (as amalloy suggested) or (list last1 last2 last3 last4)

13:59 the first is more ideomatic, though

13:59 imade: k, thanks, will try them out

14:00 amalloy: technomancy: i wanted to point out the problem with the current approach first. i hope that doesn't make me a bad person

14:00 raek: but in the case of clojure.test, 'are' already solves this problem as ataggart pointed out

14:01 Pisketti: Is there any other reason for choosing a vector over a list other than "adding" to the end is faster?

14:01 amalloy: writing them in source code is easier

14:02 and using a list gives a strong hint "these might be used as code, not data"

14:02 Pisketti: true

14:06 amalloy: btw, are you (one of) the creator(s) of 4clojure?

14:06 amalloy: yep

14:06 (one of)

14:07 Pisketti: Ok. It's probably the best learning tool I've come across.

14:08 Mostly because it's so much fun. :)

14:08 coopernurse: Pisketti: I second that

14:08 although it is destroying my work productivity :-)

14:08 amalloy: the site's only been around for a little over a month. we're very pleased with the reception it's gotten

14:09 dnolen: interesting Clojure protocols have the same limitation as Haskell typeclasses (as opposed to Standard ML functors) - you should really only extend a type to a protocol *once*.

14:09 Pisketti: coopernurse: I've fought hard not to open the page at work.

14:10 amalloy: hah

14:10 coopernurse: Pisketti: I lack the willpower

14:10 Pisketti: :)

14:10 amalloy: worse when you can *work* on it at work

14:10 qed: yeah 4clojure is awesome.

14:10 Pisketti: amalloy: What I really miss, is a feature that would allow the users to compare solutions

14:10 qed: It's like an interactive Project Euler, which I found equally addictive.

14:10 Pisketti: Exactly

14:11 coopernurse: another site to never go to: http://www.coderloop.com/

14:11 amalloy: Pisketti: #4clojure on twitter

14:11 and under Account Settings you can join the competition for finding the shortest solution

14:11 qed: Pisketti: we've been discussing that, but IMO it's a good idea to divorce solutions from the site to stop people from peeking too much.

14:12 As it stands right now you can go out to Twitter and do a bit of searching to reveal a solution, which is bit bigger barrier than say, a button that says "CHEAT!" on each problem page. :)

14:12 pdk``: there's no real purpose to a "project euler for clojure" sort of site if people can copy paste crap :p

14:12 Pisketti: amalloy: sure twitter helps and that's what I've been doing but I'm thinking something like a forum.

14:12 pdk``: or better yet

14:12 make 4clojure 2

14:12 where we copy paste assignments from our bosses and ask the public at large to solve them

14:13 qed: (second foreclojure)

14:13 pdk``: i don't that's the logical next step ;)

14:13 amalloy: pdk``: that's already where all the problems i pose come from. my boss is always asking me whether this object i can't see is a vector or a list or what

14:13 qed: bahahaha

14:14 it's like rich's talk at the (first clojure-conj): factorial, the problem we need to solve every day at work

14:14 something along those lines anyway, not a direct quote, but funny either way

14:14 Pisketti: I don't care about solving the problems per se. I just would like to see what kind of approaches other people have used once I get my own initial or second or third solution working for any particular problem

14:15 qed: Pisketti: sure, but then what incentive do you have to think about making your solution smaller?

14:15 amalloy: qed: so what? not everyone wants to optimize their own solution in isolation

14:16 qed: amalloy: yeah I don't either really

14:16 I guess I'm just saying having a barrier to peeking is nice, even if its superficial

14:16 Pisketti: But that's point. I spend a lot of time optimizing each problem and write several versions. When I'm "done", I'd like to see how other people dit it to _learn_.

14:16 qed: s/its/it's/

14:16 sexpbot: <qed> I guess I'm just saying having a barrier to peeking is nice, even if it's superficial

14:17 qed: Pisketti: *nod*

14:17 amalloy: Pisketti: at some point i'd like to add *some* kind of feature for seeing other user's solutions

14:17 but how to make it usable is unclear

14:17 Pisketti: I's like you can only learn so much by writing your own code (= keep making the same mistakes). Seeing other people's code can be an eye opening experience

14:18 amalloy: if you want to submit an issue at https://github.com/dbyrne/4clojure/issues, having a user request will help

14:18 qed: Pisketti: but then it sort of cheapens the idea of having the smallest solution -- what incentive do most users have to slim down their solutions if they can just peek at the smallest solution and paste it in

14:19 Pisketti: qed: personally I don't care about the copy-pasters. I just want to learn.

14:19 qed: Pisketti: *nod* -- I guess part of what I've learned as a result of not seeing solutions is that I've been getting better and better at being clever about slimming down my solutions

14:19 amalloy: Pisketti: yes; i was the one to implement the "shortest solution" feature, but i think qed is a little too focused on it, when it's one of many good ways to learn and have fun

14:20 we absolutely want to cater to you too, but catering to both is tricky. like i said, an issue request will help

14:20 qed: amalloy: id agree with you i am too focused on it

14:20 :)

14:20 coopernurse: qed: agreed. I'm enjoying the fact that I can't see other answers

14:20 qed: that being said, the focus on that aspect has been really fun and interesting

14:21 coopernurse: I know that I would have cheated. I honestly don't want to tell you guys how long I'm spending on some of these problems. It's embarrassing

14:21 qed: ive been keeping a log of my solutions -- i do a "most readable" solution, followed by a smallest solution possible

14:21 amalloy: qed: that sounds fun

14:22 qed: that combination is really great -- you get your head around the problem, see the "shape" of the solution, and then find out how to condense that "shape"

14:22 amalloy: back when we weren't storing solutions for you, i stored them manually, but keeping multiple copies is too much work for me :P

14:22 qed: amalloy is in the server room manually typing your solutions into a 286

14:22 imade: k, so the updated version of my unit test is like this, is it idiomatic now or could I improve it further somehow (deftest test-last

14:22 (dorun

14:22 (for [f [last1, last2, last3, last4]]

14:22 (are [x coll] (= x (f coll))

14:22 4 '(1 2 3 4)

14:22 nil '()

14:22 amalloy: hahaha

14:22 imade: 1 '(1)))))

14:22 amalloy: i meant store *my* solutions manually

14:22 qed: :D

14:23 amalloy: imade: https://gist.github.com next time you paste something long, please

14:23 imade: aa, k, will do

14:23 amalloy: dorun/for is evil. just use doseq instead, which is like for with a dorun baked in

14:23 qed: I do a split window: 4clojure.clj and a REPL -- bounce back and forth, then paste my solutions into 4clojure

14:23 and usually realize at that point I didn't account for one of the cases appropriately

14:23 :)

14:25 imade: thanks, amalloy

14:25 here's the gist also https://gist.github.com/989314

14:26 amalloy: i don't know how `are` works, but i'd replace '(1 2 3 4) with [1 2 3 4], and similarly elsewhere

14:27 imade: k vector, cause it indicates it's a data

14:28 amalloy: *nod* i mean, lists can be data too, and vectors can be code - it's lisp - but vectors are much more convenient when you want data

14:29 imade: yep

14:29 wow, it's awesome how short this form of testing can be

14:32 qed: imade: not to mention how much less you /need/ to test in general :)

14:33 imade: yeah

14:33 amalloy: yes. it's very hard to get (map #(* 2 %) some-list) wrong

14:34 Cozey: OT: Do You develop javascript / css on web apps? What is the Lisper's favourite developing pattern for these? CoffeeScript? SCSS? QUnit for testing? or is it something on node.js - or - plain old code-'reload'-check in firebug pattern?

14:35 ataggart: imade: see the comment I added to that gist

14:36 imade: thank you ataggart, I edited the gist according to the recommendation

14:37 amalloy: ataggart: i love that you can fork gists. seems more intuitive to me than writing code in the comments

14:38 gfrlog: I love that you can gork fists

14:43 dnolen: Cozey: I just write regular JS / CSS + Webkit Inspector + reload.

14:43 technomancy: Cozey: if I were doing web work I'd use coffeescript

14:43 Cozey: i wonder if with all what is happening now in node.js environment (NPM packages etc), the way we code js for the browser will improve

14:44 technomancy: I just get so sick of playing the "where did I forget to put the explicit return" game

14:44 Cozey: personally i hate coding js in the browser because it takes so much time to find and fix bugs

14:44 or 'where did this exception come from'

14:44 or even better 'why my browser swollowed an exception'

14:45 dnolen: Cozey: WebKit debugger is quite good, but then again I have 7 years experience w/ client-side JS

14:45 Cozey: also i don't feel like clojure-script comming to the rescue very soon

14:45 dnolen: do You use some frameworks except for instance jQuery/ Prototype etc?

14:45 some object oriented thingy or functional one ?

14:46 dnolen: Cozey: currently using mixture of Underscore, jQuery, and some hand-rolled OO-like thing sans inheritance.

14:46 gfrlog: there's no way to destructure sets is there? :(

14:46 Cozey: and what do you thing bout node.js popularity? is it so super fast and cool 'older' languages: java/python/ruby - or clojure can't beat them?

14:46 is js faster then clojure btw?

14:47 edw: JavaScript would be significantly less painful if it simply adopted some sort of shorthand anonymous function syntactic sugar.

14:47 dnolen: Cozey: no

14:47 * technomancy is baffled by the node.js hype

14:47 coopernurse: Cozey: there was a benchmark someone did of a node.js vs Compojure site. Perf was about the same

14:47 dnolen: Cozey: I've used node.js for file-streaming, it's good for that. I've use for rapidly prototype network stuff good for that as well.

14:48 qed: (inc rapid-prototyping-with-node)

14:48 sexpbot: ⟹ 1

14:48 ataggart: gfrlog: (seq a-set)

14:48 qed: (inc dnolen)

14:48 sexpbot: ⟹ 3

14:48 gfrlog: ataggart: yeah, that's what I've been doing. Takes a whole nother (let) expression.

14:48 coopernurse: Cozey: the GC in V8 (node) isn't as advanced as the JVM from what I've read. I believe it's stop-the-world.. so you get some spikes in response time periodically

14:49 dnolen: Cozey: at the same time node.js can't fix a broken language. So I'm not really interested in node.js for anything but small projects w/ very limited goals.

14:49 qed: what's up with disclojure.org? No update since May 11th?

14:49 edw: technomancy: I think it has something to do with the fact that there are a lot of domains that no longer need big-ass web app frameworks e.g. RoR and Django and Node.js is the easiest way to write non-bloated web services.

14:49 coopernurse: dnolen: agreed. I'm actually porting a hobby site off of node.js

14:49 dnolen: Cozey: I also find the idea that code can easily be shared between server and client w/ Node.js absurd. Client code is filled with client crap. Server code filled w/ server crap.

14:50 coopernurse: dnolen: this was exactly what I wanted to explore. I found no shared code opportunities of any importance. client was all jQuery - very little html templating on the server

14:50 qed: dnolen: SoC

14:51 edw: technomancy: It's the triumph of XHR & Ajax: Node.js programs are basically adpters between NoSQL databases and JavaScript code on a client. Of course, it's like putting a loaded gun in the hand of a child in that it "empowers" every copy-and-paste JS monkey to start writing server-side stuff.

14:51 qed: sometimes things are too powerful, even for us...

14:51 technomancy: edw: sorry, still baffled. =)

14:52 coopernurse: edw: very good observation. but the avg node.js developer I've encountered is pretty skilled

14:52 qed: (see my first experience with pmap)

14:52 "Oh, I just add a p and it all happens in parallel!"

14:52 * qed facepalm

14:52 edw: coopernurse: Yeah, I'm more bracing for the inevitable impact.

14:52 Cozey: edw: do you predict the age of node.js security horrors? ;-)

14:52 technomancy: http://p.hagelb.org/async.jpg

14:52 coopernurse: edw: heh.. yes. they'll need to dumb down the installation process first, although homebrew supports it now

14:52 dnolen: SpiderNode is also interesting, but the Node.js community seems filled with adolescent coders who can't really see what that project is trying to do - which is makes JS on the server not suck.

14:53 I got mad respect for Brendan Eich and David Herman and the Mozilla Team, they're trying hard to make JS compete w/ programming languages circa 2000.

14:53 technomancy: you can't library your way out of the statement/expression distinction.

14:54 amalloy: technomancy: clojure is a pretty good library for java

14:54 technomancy: probably a lost cause

14:54 amalloy: sure, the runtime is not a lost cause =)

14:54 coopernurse: technomancy: agreed. JS is a bizarre language. but there's a ton of client side developers who have gotten good at it, and want to use those skills on the server

14:55 Cozey: Uff. this means we'll not all be forced to leave lisp and code JS .... :P Thanks for the opinions, gotta go. good night!

14:56 qed: JavaScript in general is like Ke$ha barfing glitter.

14:56 manutter: ew

14:56 qed: :D$&#^&^$#&^$# <--example

14:56 dnolen: qed: problem is that JS neighter as bad as people say (Java people who don't know anything) nor as good (JS koolaid drinkers)

14:56 s/neighter/neither

14:56 sexpbot: <dnolen> qed: problem is that JS neither as bad as people say (Java people who don't know anything) nor as good (JS koolaid drinkers)

14:56 edw: technomancy: That most languages insist on that statement/expression distinction is baffling to me.

14:57 qed: dnolen: agreed.

14:57 coopernurse: it has some serious issues for anyone writing anything nontrivial

14:57 Pisketti: Coming from a Java background, having everything as expressions is wonderful

14:57 coopernurse: error propegation in async code, for example

14:58 amalloy: qed: i saw a good tweet on that topic: "I think the most common complain about javascript is 'Help, this language is bullshit!'"

14:58 coopernurse: I haven't explored Clojure's promise implemenation yet

14:58 so I'm curious how it solves that

14:59 I'm still reversing a list :P

14:59 qed: amalloy: heh

14:59 amalloy: ~source promise

15:00 * edw is saddened that Chicken of the VNC does't support the clipboard, as he would like to copy that. Or click on it...

15:00 pjstadig: http://twitter.com/#!/fogus/status/57082438286979072

15:01 coopernurse: great quote

15:01 edw: Is there an X analog to VNC?

15:01 coopernurse: edw: X itself is a network protocol

15:01 imade: why (comment ...) cannot contain : character? https://gist.github.com/989395

15:01 edw: Er, an X analog to screen?

15:02 coopernurse: edw: hmm.. that I don't know

15:02 wastrel: xdmcp

15:02 screen?

15:02 amalloy: (comment) is misleading and evil

15:02 wastrel: iono

15:02 clojurebot: paredit screencast is http://p.hagelb.org/paredit-screencast.html

15:02 ataggart: imade: because the comment form is still read by the reader.

15:02 gfrlog: amalloy: why?

15:03 technomancy: clojurebot: what are you insinuating there

15:03 clojurebot: Titim gan éirí ort.

15:03 ataggart: imade: if you want the reader to ignore the form, use the #_ reader macro

15:03 amalloy: &(comment TODO: do some stuff)

15:03 sexpbot: java.lang.Exception: Invalid token: TODO:

15:04 amalloy: &(inc (comment make one bigger) 1)

15:04 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$inc

15:04 edw: coopernurse: I want to be able to keep an X client going forever and simply re-connect my server to it.

15:04 imade: I see, ok, I will investigate this #_ macro then

15:04 edw: There must be some sort of X proxying app.

15:04 amalloy: gfrlog: ^

15:04 dnolen: &(comment ; foobar)

15:04 sexpbot: java.lang.Exception: EOF while reading

15:05 coopernurse: edw: gotcha. I don't know how to do that

15:05 ataggart: ,#_(does not get read)

15:05 clojurebot: EOF while reading

15:05 gfrlog: amalloy: (comment) is misleading and evil

15:05 dnolen: imade: comment is fine, but you can't just have random text lying around in it, you need to to preface non sexpr lines with ;. It's still the most convenient way to block out code you don't want to get recompiled when developing, at least for me.

15:06 gfrlog: dnolen: what about #_?

15:06 ataggart: dnolen: can you think of a reason to use comment over #_ ?

15:06 TimMc: comment can take multiple forms

15:06 So use #_(comment ....) :-)

15:07 gfrlog: TimMc: or just #_(....)

15:07 TimMc: gfrlog: Erk, yes,

15:07 dnolen: just personal preference, I use #_ to remove single exprs wedged in code, (comment ...) for blocks of various code I'm playing around with.

15:09 gfrlog: I agree that the name is misleading. Maybe (ignore) would be better. "comment" already means something specific that (comment) isn't

15:10 * ataggart waits for someone to ask about contains?

15:11 dnolen: ah #_ is effed up in SLIME, that's why I avoid it

15:11 both for formatting and evaluation

15:12 edw: dnolen: I do the same (or similar): COMMENT for things like test or exercise code, #_ for individual expressions I don't want to be eval'd.

15:12 * gfrlog tests his clients "/me" detection

15:14 amalloy: dnolen: really? how do you find it messed up for evaluation?

15:14 ataggart: speaking of contains?, if I could go back in time, I'd have sets act as predicate fns, create a new fn called get? which behaves like current contain?, and change contains? to do what most people think it should do.

15:14 dnolen: #_(+ 4 5)^ C-x C-e -> 9

15:14 amalloy: sure. i would be astonished if it traveled back *past* that sexp to the first one that's not commented

15:14 TimMc: dnolen: Ah, it doesn't go back far enough?

15:15 amalloy: that is, i think the existing behavior is useful for "does this code i've commented out still work", and some other behavior would be useful for "oh shit i wanted to test this commented-out code, not that delete-the-db function before it"

15:17 dnolen: amalloy: not disagreeing I use #_ when I want to test multiple possible values for an expr in an existing expr, I put snippets of test code in (comment ...)

15:19 amalloy: incidentally i don't think it would be possible to make slime understand #_ without a huge effort

15:22 edw: I use #_ extensively and I've never been bitten by this. Do you really see "(foo) #_ (apocalypse)|", type C-x C-e and expect the foo combination to be evaled? That's crazy.

15:23 dnolen: edw: I did say personal pref :) it affects movement and paredit as well

16:04 timvisher: hey all

16:04 i'm using clojure.contrib.shell-out to interact with imagemagick

16:04 when I get to an image that has bad data in it, my program just hangs

16:05 i remember from my groovy days that if you don't properly consume output, you can get into this situation, but i can't find anything in the docs indicating how to consume the error stream

16:05 thoughts?

16:06 ataggart: try clojure.java.shell

16:10 technomancy: dnolen: harder than you think as it would probably involve forking slime

16:10 since I don't think upstream would be too keen on the feature

16:11 timvisher: ataggart: whoo! that seems to have done it. thanks!

16:12 btw, when programming in slime, i find myself wanting to get a clean version of my namespace, i.e. wipe out all references and definitions and then reload them

16:12 the way i do this is to kill the swank server and then restart it

16:12 pdk``: slime

16:12 timvisher: is there a better way to do that?

16:12 pdk``: clean

16:12 wipe


16:12 clojurebot: Cool story bro.

16:13 technomancy: timvisher: you can do ns-unmap or remove-ns, but there's nothing exposed from elisp. there should be though.

16:13 TimMc: clojurebot: botsnack

16:13 clojurebot: thanks; that was delicious. (nom nom nom)

16:13 pdk``: have you considered using im4java through clojure

16:14 timvisher: pdk``: i was looking into JMagick but they don't appear to be available through maven/clojars

16:15 i then figured that if I was going to bother shelling out through im4java, i want to do something so simple that there has to be an easy way to simply shell out

16:15 so far, this is really all I want to do

16:15 if I need more from imagemagick, i might go with im4java

16:15 jmagick seems... poorly documented

16:17 technomancy: I suppose I could effectively switch to the user namespace, (remove-ns whatever-ns) at the repl, and then switch back to the buffer and C-c C-k again.

16:21 technomancy: beware that remove-ns can screw up downstream consumers though

16:21 actually ns-unmap may as well

16:21 one way to find out

16:32 amalloy: timvisher: you could bind that sequence of commands to a key and just use that

16:36 timvisher: amalloy: indeed I could. 'nother day though. I can now generate thumbnails for my image seq. hooray! :)

16:36 thanks for the awesome help as always ladies!

16:38 offby1: laddies?

16:39 timvisher: no, i meant ladies

16:39 i was going to say gentlemen

16:39 then i realized there may be ladies present

16:39 then I felt like sticking it the old masculine general pronouns and just call us all ladies

16:39 :)

16:40 hopefully no one's offended, as I don't think i'd make much progress with clojure if I had to stop coming here

16:42 * amalloy is unlikely to be featured in a Ladies of Clojure calendar

16:43 * offby1 is offended

16:43 offby1: how dare he

16:43 * __name__ is offended

16:43 offby1: yeah

16:43 * offby1 hands out torches and pitchforks

16:43 __name__: I've been longing for something to feel offended about all day.

16:43 * timvisher would pay at least... $10 for a calendar featuring amalloy

16:43 * __name__ burns the pitchfork.

16:44 __name__: Oh. Wait. That's not how it works, is it?

16:44 amalloy: offby1: i admire the way you immediately turned a vicious personal attack into an opportunity to profit through merchandising

16:45 timvisher: offby1's got class

16:52 Pisketti: I wonder if there are any _real_ ladies here.

16:53 * technomancy suspects that if there are they would probably appreciate not being singled out

16:54 amalloy: good call there

16:55 pjstadig: i'm a dog

16:55 http://www.unc.edu/depts/jomc/academics/dri/idog.jpg

18:05 brian_: FYI - I created an s4code git repo that contains all the other repos as submodules for easy cloning/updating/etc

18:06 oops, wrong chat!

18:15 VT_entity: Hey all

18:15 I've got a question.

18:16 I'm trying to use cycle to produce an infinitely repeating collection. I want to use vectors because I think they will be faster

18:16 (def ringbuffermembers [1 2 3 4 5])


18:16 (def ringbuffer (cycle ringbuffermembers))

18:17 this works, but if I do

18:17 (take 20 ringbuffer)

18:17 it returns a list

18:17 not a vector

18:17 amalloy: vectors aren't lazy

18:17 you can't have a lazy vector

18:17 (also, it returns a seq, not a list; the repl renders them both as (a b c))

18:17 VT_entity: so... duck typing is turning my vector into a list because I'm treating it lazily?

18:18 ooooh

18:18 amalloy: &(class (take 1 (cycle [1])))

18:18 sexpbot: ⟹ clojure.lang.LazySeq

18:18 amalloy: you can use a vector if you want, but cycle will take a sequence view on it anyway

18:18 and return a sequence

18:19 VT_entity: yeah, I couldn't figure out why

18:19 no_mind: using enlive, I have selected a node of tag type :select . Now I want to iterateover all teh optin tags under selected select node and set one of the option nodes as selected. How do I do this ?

18:19 amalloy: &(seq [1 2 3])

18:19 sexpbot: ⟹ (1 2 3)

18:19 raek: a seq is just a sequential view of some abstract collection, which can be infinite

18:19 ...and not really a data structure, in a sense

18:20 no_mind: at?

18:20 VT_entity: I'm trying to figure out whether its faster to do this with lists or vectors

18:20 amalloy: neither, really

18:21 i mean, you might notice a slight difference

18:22 VT_entity: I'm still learning the language. I figured vectors might be faster because I might eventually be creating a lot of these ringbuffers

18:22 amalloy: and if you did, lists would probably be the winner in this particular contest, but i'm just guessing

18:23 VT_entity: maybe do it with pvec

18:23 ah, thanks

18:23 amalloy: &(doc pvec)

18:23 sexpbot: java.lang.Exception: Unable to resolve var: pvec in this context

18:23 VT_entity: ah, I guess I forgot the mnemonic for parallel vector

18:24 amalloy: VT_entity: i don't understand what you're talking about. parallel vector?

18:24 raek: VT_entity: are you concerned about whether (cycle [1 2 3]) or (cycle (list 1 2 3)) is the most efficient?

18:24 VT_entity: lol, yes

18:24 I am an utter noob, sorry

18:25 amalloy: VT_entity: there are 10,000 more important things to worry about when you're learning a language. ask this question again once you've covered them all :)

18:25 VT_entity: I am going to be invoking a whole bunch of these ringbuffers and popping functions off of them

18:25 raek: if so, it must be hard for you to get anything done if you spend your time doing these (premature) micro-optimizations all the time

18:26 VT_entity: it's going to be pretty intense

18:26 amalloy: VT_entity: madness

18:26 stop worrying about it

18:26 VT_entity: I'm building an artificial life game

18:26 raek: VT_entity: if a queue is what you need, there is a data structure in Clojure for that too

18:26 amalloy: so what? if you find out this is the bottleneck, you can change it later

18:27 VT_entity: ah, that's a smarter way to go about it.

18:27 amalloy: (cycle foo) will return a lazy-seq no matter what foo is, so the consumer won't care

18:27 no_mind: raek: no luck http://pastebin.com/KZ1jHJV1

18:27 VT_entity: &(doc queue)

18:27 sexpbot: java.lang.Exception: Unable to resolve var: queue in this context

18:28 amalloy: &(doc seque) i think?

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

18:28 amalloy: clojure's seq isn't very well polished afaik though

18:28 VT_entity: aaah

18:28 thanks

18:30 raek: no_mind: the problem with your code is that in the "transformation slot" of the outer html/at form, you don't put a transformation function

18:37 no_mind: you need to turn (html/at <some node> [:option] abc) into a function that takes a node and returns the changed node

18:41 no_mind: k

18:41 raek: we need a short book to explain the concepts of enlive :)

18:42 raek: no_mind: most of enlive is actually ordinary clojure

18:42 no_mind: wellclojure is not ordinary :)

18:42 raek: no_mind: what you put in the "transformation slot" of an 'at' form is just an ordinary clojure expression, and follows ordinary evaluation rules

18:44 no_mind: I assume you come from a programming language where functions are not values?

18:45 no_mind: raek: but that still leaves the original problem unsolved. How to iterate over each option tag and set a tag value as selected ? From what I see, 'at' will select all the option tags

18:45 raek: no_mind: at will only operate on the tree that you give it

18:46 no_mind: in your case, the outer at should pass the select element subtree to the inner at

18:47 I assume you want to iterate over all the option elements of that select element

18:48 no_mind: raek: yes iterate over al elements and set one option as selected

18:51 raek: at works by matching nodes with selectors. on a match, it will pass the matched node (and its subnodes) to the corresponding transformation function.

18:52 (at (html-snippet "<p><b>foo</b></p>") [:b] (fn [node] (prn node) {:tag :i, :content ["bar"]}))

18:52 dnolen: is it not possible to install swank-clojure via marmalade?

18:53 raek: dnolen: swank-clojure or swank-clojure.el?

18:53 dnolen: raek: used to install swank-clojure via ELPA, wondering if marmalade is the new way to go, has more packages, and seems more up-to-date.

18:54 raek: dnolen: the swank-clojure you probably want to use is not an emacs library

18:55 there is an old lib called swank-clojure.el from the times before Leiningen, but it was hard to use since you needed to configure the classpath (so switching betsween projects was a pain)

18:56 dnolen: http://technomancy.us/149

18:56 dnolen: either add [swank-clojure "1.3.1"] to your project.clj or run "lein plugin install swank-clojure 1.3.1"

18:57 hiredman: dnolen: does core.logic provide a cond like macro for conditional execution based on matching?

18:58 raek: no_mind: in that example, the transformation function receives {:tag :b, :content ("foo")} and returns another tree ("<i>bar</i>"). it also prints the original tree

18:58 no_mind: raek: http://pastebin.com/CFZ1LAuk it prints the whole node including the html. Whereas what I want in function xyz is bunch of :option tags only

18:58 raek: no_mind: in your case, you probably want to write something like (fn [node] (at node ...selector... ...transformation))

18:59 dnolen: hiredman: yes, conde is the primitive form, defne gives you pattern matching sugar. It's a bit different from Prolog tho since in Prolog different clauses can be defined top-level, in core.logic matching is local to fns (goals) - kinda like Clojure multi-arity fns. Hope that makes some sense. I need to document more.

19:01 hiredman: and you wrap it in the whole run* thing?

19:03 raek: no_mind: it doesn't print the whole tree, it prints nil. the at expression returns the whole tree, though

19:03 carllerche: Is there a way to determine the arity of an arbitrary (anonymous?) function?

19:05 dnolen: hiredman: yup, run* is basically a sort of monadic thing, it threads an environment through your logic statements, it return a lazy-seq of answers.

19:06 raek: no_mind: sorry, actually it doesn't print anything at all. the selector does not match, somehow

19:06 dnolen: goals are really just closures that take an environment manipulate it (possibly replicate it) and pass it on to the next goal.

19:06 no_mind: raek: how come ?

19:06 dnolen: (== q true) -> (fn [a] (unify a q true))

19:07 so I guess run* is sort of like do in Haskell.

19:08 * dnolen is probably gonna lose an hour tonight trying to figure what the new way to Clojure and Emacs is ...

19:09 raek: no_mind: strange, it works with (content "BOO") instead of xyz...

19:10 dnolen: technomancy's recent blog post is the way to go. the previous approach (pre "clojure-jack-in") is here: http://dev.clojure.org/display/doc/Getting+Started+with+Emacs

19:11 no_mind: (defn xyz [node] (prn node) node) works as expected...

19:12 no_mind: raek: the selctor for select tag is working, i checked by doing a set-attr instead of xyz and it works

19:12 amalloy: carllerche: no

19:13 raek: the printing seems to mess it up...

19:14 amalloy: mainly because functions can have multiple arities, and that information only really exists in the var's metadata (which anonymous function don't have) once the compiler's read it in

19:15 no_mind: raek: no luck here.. I am still getting the same result

19:15 carllerche: amalloy: there seems to be getRequiredArity it seems

19:16 amalloy: &(-> + var meta :arglists)

19:16 sexpbot: ⟹ ([] [x] [x y] [x y & more])

19:16 amalloy: if you have an actual var object, you can work with that to see what it accepts

19:16 carllerche: that doesn't really help though

19:16 raek: no_mind: oh, now I get it! it actually works, but prn is called in the middle of the printing of the result!

19:16 amalloy: no

19:16 carllerche: amalloy: yeah, i'm working with anonymous functions :(

19:16 raek: try this: (html/at rr [(html/id= "one")] (fn [node] (prn "BEGIN") (prn node) (prn "END")))

19:16 amalloy: whose arities you don't know, but need to know? that seems like a bad design choice

19:17 carllerche: amalloy: it's mostly for convenience helpers during testing

19:17 amalloy: i don't think that message has much information in it :P

19:18 carllerche: it's not a big deal, it's mostly so that I can write tests w/o _ everywhere, but whatever.. worth a shot

19:18 raek: no_mind: due to laziness, the transformation won't be call until needed, which happens to be in the middle of the printing of the expression

19:18 no_mind: raek: ok butI am still receiving the complete html in prn whereas I want only option tags

19:19 raek: no_mind: take a look at this: (def a (atom nil)) (defn xyz [node] (reset! a node))

19:19 no_mind: evaluate (html/at rr [(html/id= "one")] xyz) and then look at the value of a

19:20 no_mind: the interleaved printing confused the matter

19:22 no_mind: to answer your original question: (html/at rr [(html/id= "one")] #(html/at % [:option] abc))

19:22 no_mind: do you see why this works?

19:24 no_mind: yaa

19:30 technomancy: what could cause a simple (clojure.java.shell/sh "ls") call to cause the JVM to never exit?

19:31 adding shutdown-agents fixes it, but that's ridiculous

19:32 there are a few futures in clojure.java.shell/sh, but they're all deref'd by the time the function returns

19:33 hiredman: technomancy: sh uses futures, which spins up the agent threadpool, etc

19:33 the jvm waits for live threads to exit before exiting

19:33 technomancy: even with no active futures?

19:33 hiredman: after the futures finish they are returned to the threadpool, and are still "live"

19:33 waiting to be reused

19:34 (kind of what a threadpool is for)

19:34 technomancy: makes sense if the process isn't trying to exit

19:34 hiredman: which is why shutdown-agents was added

19:35 technomancy: shutdown-agents is permanent though

19:35 hiredman: the other option is to make the threadpool threads daemon threads

19:35 technomancy: useless for writing composable code without a corresponding startup-agents

19:35 hiredman: correct

19:36 technomancy: the JVM is getting revenge on me for having ported a 75-line clojure file to a 30-line shell script

19:36 hiredman: http://tech.puredanger.com/2010/06/08/clojure-agent-thread-pools/

19:37 technomancy: "If you really loved me, you wouldn't want to shell out! I've got everything you need right here. Come baaaaaaack..."

19:37 hiredman: I kind of agree with the blog post, not making the threadpool threads daemon threads by default is kind of a drag

19:37 technomancy: I wouldn't mind one bit if I could reset the thread pool

19:38 no_mind: raek: calling set-attr in xyz is throwing error

19:39 scgilardi: given that you can't recover from shutdown-agents, I wonder if arranging for a call to shutdown-agents in a shutdownhook would be appropriate. (Runtime.addShutdownHook)

19:40 raek: no_mind: what error?

19:40 technomancy: scgilardi: whoa; shutdown hooks.

19:40 that looks like the Right Thing

19:41 hiredman: they won't run until the threadpool threads stop

19:41 "The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or "

19:41 technomancy: ಠ_ಠ

19:41 scgilardi: Isn't a successful System/exit what we're after?

19:42 technomancy: in this case System/exit would break composability as well

19:42 hiredman: unless lein did some kind of "run these tasks then call System/exit"

19:43 (which it must, come to think of it)

19:43 to return exit codes

19:43 scgilardi: inc

19:43 technomancy: it only calls System/exit on failures

19:43 but it probably should either way

19:45 no_mind: raek: java.lang.IllegalArgumentException: Don't know how to create ISeq from: net.cgrand.enlive_html$set_attr$fn__696

19:46 raek: no_mind: all I can tell from that is that you have put the (set-attr ...) call in the wrong place...

19:47 no_mind: could you explain the surrounding code?

19:48 no_mind: raek: http://pastebin.com/DLVbMw2F

19:49 * no_mind is wondering if writing a new html templating engine would have finished work faster than using enlive

19:51 raek: no_mind: first: use = instead of .equals

19:52 no_mind: second: you are calling set-attr wrong. remember the "two stage" thing?

19:53 and you are missing the else expression of the if

19:53 which should return the node unchanges

19:53 -d

20:01 no_mind: anyway, here's my approach: https://gist.github.com/990033

20:03 no_mind: raek: thnxs, i fixed that

20:07 tomoj: clojurebot: single segment namespaces?

20:07 clojurebot: single-segment namespaces is unsupported. (foo instead of foo.core) they may work in a few circumstances, but you shouldn't rely on them.

20:07 tomoj: but why, clojurebot?

20:09 amalloy: tomoj: default package

20:10 tomoj: ah

20:10 so e.g. osc-clj has (ns osc)

20:11 that means if there is a java lib out there with an "osc" class in the default package, they clobber?

20:12 amalloy: i don't think that's the *only* issue

20:30 dnolen: when I try clojure-jack-in it says it can't find lein, how can I set the path to lein?

20:33 technomancy: dnolen: gui-launched emacs on OS X?

20:33 dnolen: technomancy: yeah

20:33 technomancy: yeah, your .profile is being ignored =\

20:33 dnolen: do I just (setq clojure-swank-command ...) ?

20:33 technomancy: there's some XML plist you have to edit

20:34 to set your $PATH for GUI apps

20:34 it's ridiculous

20:34 dnolen: technomancy: got a link?

20:34 technomancy: dnolen: actually clojure-swank-command would work too

20:35 but you would still have trouble with non-swank commands like with magit

20:35 maybe this? http://www.emacswiki.org/emacs/MacOSTweaks#toc11

20:36 scgilardi: http://developer.apple.com/library/mac/#qa/qa1067/_index.html

20:36 technomancy: that's specific to emacs rather than all gui-launched programs; maybe it's good enough

20:38 ooh; a non-xml version. slightly less awful!

20:38 that is probably the #1 most common problem people have with Emacs on any platform. probably should mention it in the swank readme.

20:39 (apart from "zomg the parens" of course)

20:39 scgilardi: well, it's a gui on the xml. and comes with apple's developer tools.

20:39 jedi: ah that would explain my problem with it too

20:40 dnolen: technomancy: how long should jack in take? I see that it's pasting slime.el into *swank* buffer...

20:41 technomancy: dnolen: maybe 5-10 seconds on the server JVM?

20:41 dnolen: technomancy: hmm I should get a REPL ?

20:41 technomancy: I tried jack in from the dired view of my project.

20:42 technomancy: that oughtta work; is it just stalled?

20:42 what's at the end of the *swank* buffer?

20:43 scgilardi: example environment.plist: https://gist.github.com/990084

20:44 dnolen: technomancy: *swank* looks stalled on line 10000 something.

20:45 technomancy: I used: lein install plugin swank-clojure 1.4.0-SNAPSHOT, and trying to jack into a 1.3.0-alpha7 project.

20:46 technomancy: dnolen: I haven't used it with clojure 1.3 but have seen reports of it working. what's the content at the end of the buffer?

20:46 dnolen: technomancy: it just keeps freezing around line 10937: it's in the middle of pasting "slime-repl-current-input"

20:47 lein jack-in 36863: exited abnormally with code 1.

20:47 in *Messages*

20:47 technomancy: freezing mid-function? that's odd; I haven't heard of anyone else getting that.

20:48 dnolen: I will say the slime.el paste it very slow, I see it scroll by

20:48 s/it/is

20:48 sexpbot: <dnolen> I will say the slime.el paste is very slow, I see is scroll by

20:48 technomancy: if you already have slime installed, you can stick with lein swank + m-x slime-connect

20:48 this is really more of a convenience for people who haven't gone through the setup process yet

20:49 I am curious what's going on though

20:49 dnolen: technomancy: can you grab files from marmalade and ELPA ?

20:50 technomancy: yeah, you should be able to use curl or whatever

20:50 they're also inside the swank-clojure jar

20:51 dnolen: technomancy: won't installing package.el from ELPA override marmalade package.el?

20:52 technomancy: you mean using package.el to upgrade itself?

20:52 I'm not sure; I don't think the elpa version has a higher version number

20:55 dsop: is it true that I cannot access the cached collection inside a lazy-seq body?

20:55 so something like (lazy-seq (let [x (seq coll)] ... (count x)...)

21:03 dnolen: technomancy: so swank-clojure is not something I should install from ELPA right?

21:10 Emacs is not for the faint of heart ...

21:10 hiredman: dnolen: core.logic run on 1.2?

21:11 dnolen: hiredman: I'd like it to but I haven't had time to sort out what needs to be fixed.

21:11 hiredman: I ran into some weird errors and did not pursue. There no reason for core.logic to be 1.3 centric.

21:16 after much teeth gnashing, animal sacrificing, I have a working Clojure Emacs setup again and I can get packages from Marmalade and ELPA.

22:03 hiredman: OK looked at it a little, here's a real bug in 1.2.1 that prevents core.logic from working https://gist.github.com/990176

22:07 if anyone knows how to work around this one, I'll be happy to fix core.logic to work w/ 1.2 now.

22:17 hiredman: dnolen: https://gist.github.com/990194

22:18 dnolen: hiredman: will that be slow? core.logic really relies on very fast map lookups.

22:19 hiredman: the other option is make Foo the full package qualified name

22:20 TimMc: arglbalrlgrl

22:20 hiredman: basically Foo is resolved to the wrong classname at compile time (it is resolved to the stub the compiler generates)

22:20 TimMc: I did my first serious Java coding today since... about a year ago.

22:20 I REALLY want macros.

22:20 amalloy: haha TimMc i was gonna ask if it was java-related

22:20 TimMc: of course

22:21 amalloy: TimMc: well, it could be php-related

22:21 dnolen: hiredman: yeah tried fully qualified name, got classloader error.

22:21 attempted duplicate class definition for name

22:22 hiredman: bleh

22:22 stupid deftype bugs in 1.2

22:27 dnolen: hiredman: difference is pretty dismal, w/ resolve in 1.2 you're looking at 600ms for 1e7 iterations, 1.3 7-9ms if I can do the real instance check.

22:28 core.logic is constantly reaching into the map to check vars, add vars, etc. so equal needs to really cost near nothing.

22:29 hiredman: I may noodle on it

22:30 dnolen: hiredman: if you come w/ something let me know, I think this is the weird issue I saw, probably the only real bug, but of course it breaks everything.

22:31 amalloy: dnolen: (let [this-class (atom nil)] (deftype Foo [] (equals [this other] (instance? this-class other))) (reset! this-class Foo)) perhaps?

22:31 dnolen: amalloy: not really willing to do something like that.

22:31 I'll mention this on the dev ML

22:39 mefesto`: dnolen: this works for me on clojure 1.2.0: https://gist.github.com/990219

22:40 not sure if it meets your performance requirements but atleast it returns true :)

22:42 dnolen: mefesto`: huzzah! and it's even faster it seems!, k will see if that fixes core.logic in a few, gotta run for a bit.

22:59 amalloy: KirinDave: i found an entry in the #clojure logs where you talk about http if-modified-since. is there a compojure wrapper that handles that already (for static file-based routes), or would i have to write it myself? so far i can't even figure out how to convince the client to send an If-Modified-Since header

23:00 KirinDave: amalloy: I dunno if there is a compojure wrapper. I doubt it?

23:00 amalloy: Which client?

23:01 amalloy: KirinDave: neither chrome nor firefox seem to be sending that header afaict

23:01 KirinDave: amalloy: Oh

23:01 I dunno about it.

23:01 I see it usually in the context of proxies

23:02 I don't know how you'd provoke Chrome or Firefox.

23:03 amalloy: KirinDave: i thought most clients were keeping a local cache and would involve the server in a decision whether or not updating was needed

23:04 KirinDave: amalloy: Offhand I'm not sure what they do.

23:04 amalloy: KirinDave: looking at the headers when i request google.com a few times, it looks like mostly google says "this data is good for N seconds, don't even ask me if it's changed". but for at least one resource, they convince chrome to include If-Modified-Since

23:55 dnolen: core.logic is now compat w/ 1.2

23:56 mefesto`: very cool. now i just need to learn about this thing they call "logic"

23:58 technomancy: Licenser: ping

Logging service provided by n01se.net