2011-05-24
| 02: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") |
| 02:44 | brehaut | (defn str-split-retain [s sep] (into #{s} (.split s sep))) ? |
| 02:49 | markoman | works great, thanks |
| 02:50 | brehaut | it has a terrible name though :P |
| 02:51 | no_mind | is it possible to introduce new tags with enlive html ? |
| 02:53 | markoman | name doesnt make man worse, they tell :) |
| 02:53 | thorwil | no_mind: i think it has no idea about specific tags, so i guess yes |
| 05: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? |
| 05:19 | clgv | hm ok, I looked in clojure and contrib - there seems to be nothing. so I just build my own |
| 05:23 | ejackson | look a bit idiosyncratic |
| 05:23 | ejackson | i guess |
| 05:27 | clgv | why do you think? |
| 05:28 | clgv | 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 |
| 06:21 | clgv | Is there a condition checking idiom for macro parameters? |
| 06:23 | clgv | assert-args from core is private unfortunately. |
| 06:31 | cemerick | clgv: if the fn does what you want, there's always the #'clojure.core/assert-args backdoor. |
| 06:32 | clgv | cemerick: so I should do a "with-private" hack with assert-args? |
| 06:32 | cemerick | with-private? |
| 06:33 | cemerick | It's not a hack; you just need to be prepared for potential breakage if assert-args changes |
| 06:34 | clgv | ok :(. Maybe it should be made public in general |
| 06:34 | clgv | wrong smiley... |
| 08:07 | no_mind | in enlive, how do i find the value of an attribute for a given node ? |
| 08:16 | mefesto` | no_mind: (:attrs node) ? |
| 08:16 | mefesto` | or possibly: (get-in node [:attrs :blah]) |
| 08: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 |
| 08:24 | no_mind | the problem is how do I pass the node to get ? |
| 08:24 | clojurebot | People have a problem and think "Hey! I'll use a regular expression!". Now they have two problems.... |
| 08:24 | no_mind | let me paste teh code |
| 08:25 | no_mind | here is the code http://pastebin.com/JsWS7seg . How do I pass the node ? |
| 08:28 | raek | no_mind: is this for transforming a html tree, or extracting data form it? |
| 08:28 | raek | no_mind: a transformation is a function that takes a node and returns a node or a sequence of nodes |
| 08: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. |
| 08: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) |
| 08:32 | raek | the transformation function could look like (fn [node] (let [type (-> node :attrs :type)] (case type "foo" <foo code> "bar" <bar code> <default code>))) |
| 08:34 | raek | (this probably looks prettier if you turn it into a defn) |
| 08: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 |
| 08: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") |
| 08:39 | raek | (html/at tree [(html/id= "username")] (set-attr :value "raek")) |
| 08: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 |
| 08:40 | raek | I see. |
| 08:40 | no_mind | so I was thinking of writingmulti-method for filling value |
| 08:40 | no_mind | butfor multi-method to work, I should be able to identify the type of the node |
| 08:42 | raek | (defn tag-multi [node] (the-multi-method (:tag node) node)) |
| 08:43 | raek | oh, wait. |
| 08:43 | raek | no need for that extra function. |
| 08:43 | no_mind | then |
| 08:43 | no_mind | ? |
| 08:43 | raek | (defmulti your-multi-method (fn [node] (:tag node))) ; this should be enough |
| 08:44 | raek | this will make the multimethod dispatch on the element type |
| 08:44 | no_mind | raek: Icouldfigure that but cannot figureout how to pass the node from enlive selector |
| 08:45 | raek | no_mind: you just do it like this in your at form: (html/at tree ...selector... your-multi-method) |
| 08:45 | raek | no_mind: here, "your-multi-method" will receive the node as its only argument |
| 08:45 | no_mind | oh ok |
| 08:46 | raek | hrm. but you probably want the text value to be passed too... |
| 08:47 | timvisher | morning everyone |
| 08:47 | raek | (defn fill-in [text] (fn [node] (your-multi-method [node text]))) |
| 08:47 | raek | (defmulti your-multi-method (fn [node text] (:tag node))) |
| 08:47 | timvisher | what could cause a binding expression to _not_ rebind the var, other than perhaps a typo? |
| 08:47 | raek | (html/at tree ...selector... (fill-in "value")) |
| 08:48 | raek | timvisher: laziness |
| 08:48 | timvisher | raek: could you explain that a bit further? |
| 08:48 | raek | ,(binding [*out* :foo] (lazy-seq (cons *out* nil))) |
| 08:48 | clojurebot | (#<StringWriter >) |
| 08:49 | timvisher | ahh |
| 08:49 | raek | ,(binding [*out* :foo] (doall (lazy-seq (cons *out* nil)))) |
| 08:49 | clojurebot | (:foo) |
| 08:50 | raek | so the lazy expression does not remember the binding of the var... |
| 08:50 | timvisher | and it turns out that deftest runs lazily, i suppose? |
| 08:50 | timvisher | that explains a lot of what i've been expriencing |
| 08:51 | no_mind | raek: no luck http://pastebin.com/7UF3ZbRw |
| 08:51 | timvisher | i've been assuming that i could wrap all of my deftests in a single binding expression and get a global change |
| 08:51 | timvisher | but i suppose i need to wrap the is expressions instead |
| 08:51 | jjido | shouldn't doall force evaluation before the binding is lost? |
| 08:52 | dnolen | jjido: yes, but beware of nested lazy-seqs. |
| 08:53 | jjido | dnolen: I see... |
| 08: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 |
| 08:55 | no_mind | k |
| 08:55 | raek | no_mind: tag values are keywords, so it should be :input instead of "input" |
| 08:56 | raek | 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" |
| 08:57 | raek | (defn helper-fn [arg1 arg2 arg3] (fn [node] (the-real-function node arg1 arg2 arg3))) |
| 08:57 | raek | (html/at ... ... (helper-fn 1 2 3)) |
| 08:58 | no_mind | aha |
| 08: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 |
| 09:02 | raek | no_mind: https://gist.github.com/988666 |
| 09:03 | raek | also note how set-attr is called due to the "two stage" way of doing things |
| 09:16 | no_mind | raek: thnxs |
| 11:15 | no_mind | 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 | raek | no_mind: will the map have different values at runtime? if so, you can't use the macro approach |
| 11:35 | raek | 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 | raek | 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 | coopernurse | My solution: (fn [xs] (reduce + (for [x xs] (+ 1)))) |
| 11:46 | coopernurse | Site is complaining that I'm using "count", which is prohibited for this problem |
| 11:47 | coopernurse | 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 | manutter | 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 | coopernurse | 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 | coopernurse | a bit humbling |
| 11:52 | manutter | I know what you mean, fp is almost a zen experience |
| 11:52 | manutter | "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 | coopernurse | you think you're good at languages, and then *bam* |
| 11:53 | manutter | indeed |
| 11:55 | manutter | 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 | coopernurse | (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 | raek | coopernurse: ...but it does exactly the same thing as your version |
| 12:47 | raek | 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 | coopernurse | if I'm reading it correctly, we're saying "set x=0 if not provided" |
| 12:48 | coopernurse | or am I reading that incorrect? |
| 12:48 | coopernurse | 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 | coopernurse | so it's faster than my first example that used a nested function |
| 12:50 | coopernurse | 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 | coopernurse | 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 | coopernurse | 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 | amalloy | 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 | coopernurse | 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 | amalloy | some disagree with me, of course |
| 12:58 | ataggart | avoid it if it can be confusing to a reader, otherwise, meh |
| 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 | manutter | 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:28 | defn | good day, gents. |
| 13:30 | defn | 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 | Pisketti | I read Practical clojure and Programming clojure is waiting. I've also thought about ordering The joy of clojure. |
| 13:33 | Pisketti | But other than that, any fundamental must-reads? |
| 13:33 | Pisketti | 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 | amalloy | (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 | amalloy | 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 | qed | amalloy: age has nothing to do with guruship. |
| 13:39 | amalloy | qed: he said "old lisp guru" |
| 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 | qed | 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 | 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 | Pisketti | 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 | Pisketti | 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 | Pisketti | 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 | qed | 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 | amalloy | reminds you lisp is a beautiful language |
| 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 | sexpbot | 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 | imade | (dorun |
| 13:58 | imade | (for [f '(last1, last2, last3, last4)] |
| 13:58 | imade | (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 | raek | 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 | amalloy | and using a list gives a strong hint "these might be used as code, not data" |
| 14:02 | Pisketti | true |
| 14:06 | Pisketti | amalloy: btw, are you (one of) the creator(s) of 4clojure? |
| 14:06 | amalloy | yep |
| 14:06 | amalloy | (one of) |
| 14:07 | Pisketti | Ok. It's probably the best learning tool I've come across. |
| 14:08 | Pisketti | Mostly because it's so much fun. :) |
| 14:08 | coopernurse | Pisketti: I second that |
| 14:08 | coopernurse | 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 | amalloy | 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 | qed | 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 | pdk`` | make 4clojure 2 |
| 14:12 | pdk`` | where we copy paste assignments from our bosses and ask the public at large to solve them |
| 14:13 | qed | (second foreclojure) |
| 14:13 | qed | 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 | qed | it's like rich's talk at the (first clojure-conj): factorial, the problem we need to solve every day at work |
| 14:14 | qed | 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 | qed | 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 | amalloy | 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 | amalloy | 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 | qed | :) |
| 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 | imade | (dorun |
| 14:22 | imade | (for [f [last1, last2, last3, last4]] |
| 14:22 | imade | (are [x coll] (= x (f coll)) |
| 14:22 | imade | 4 '(1 2 3 4) |
| 14:22 | imade | 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 | qed | and usually realize at that point I didn't account for one of the cases appropriately |
| 14:23 | qed | :) |
| 14:25 | imade | thanks, amalloy |
| 14:25 | imade | 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 | imade | 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 | Cozey | or 'where did this exception come from' |
| 14:44 | Cozey | 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 | Cozey | dnolen: do You use some frameworks except for instance jQuery/ Prototype etc? |
| 14:45 | Cozey | 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 | Cozey | 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 | 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 | qed | "Oh, I just add a p and it all happens in parallel!" |
| 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 | dnolen | 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 | technomancy | 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 | dnolen | 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 | coopernurse | so I'm curious how it solves that |
| 14:59 | coopernurse | I'm still reversing a list :P |
| 14:59 | qed | amalloy: heh |
| 14:59 | amalloy | ~source promise |
| 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 | wastrel | 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 | TimMc | 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:11 | dnolen | ah #_ is effed up in SLIME, that's why I avoid it |
| 15:11 | dnolen | 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: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 | timvisher | i'm using clojure.contrib.shell-out to interact with imagemagick |
| 16:04 | timvisher | when I get to an image that has bad data in it, my program just hangs |
| 16:05 | timvisher | 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 | timvisher | 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 | technomancy | 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 | timvisher | 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 | timvisher | 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 | pdk`` | wipe |
| 16:12 | pdk`` | HMMMMMM |
| 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 | timvisher | 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 | timvisher | so far, this is really all I want to do |
| 16:15 | timvisher | if I need more from imagemagick, i might go with im4java |
| 16:15 | timvisher | jmagick seems... poorly documented |
| 16:17 | timvisher | 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 | technomancy | actually ns-unmap may as well |
| 16:21 | technomancy | 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 | timvisher | thanks for the awesome help as always ladies! |
| 16:38 | offby1 | laddies? |
| 16:39 | timvisher | no, i meant ladies |
| 16:39 | timvisher | i was going to say gentlemen |
| 16:39 | timvisher | then i realized there may be ladies present |
| 16:39 | timvisher | then I felt like sticking it the old masculine general pronouns and just call us all ladies |
| 16:39 | timvisher | :) |
| 16:40 | timvisher | 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:43 | offby1 | how dare he |
| 16:43 | offby1 | yeah |
| 16:43 | __name__ | I've been longing for something to feel offended about all day. |
| 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:54 | amalloy | good call there |
| 16:55 | pjstadig | i'm a dog |
| 16:55 | pjstadig | 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 | brian_ | oops, wrong chat! |
| 18:15 | VT_entity | Hey all |
| 18:15 | VT_entity | I've got a question. |
| 18:16 | VT_entity | 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 | VT_entity | (def ringbuffermembers [1 2 3 4 5]) |
| 18:16 | VT_entity | |
| 18:16 | VT_entity | (def ringbuffer (cycle ringbuffermembers)) |
| 18:17 | VT_entity | this works, but if I do |
| 18:17 | VT_entity | (take 20 ringbuffer) |
| 18:17 | VT_entity | it returns a list |
| 18:17 | VT_entity | not a vector |
| 18:17 | amalloy | vectors aren't lazy |
| 18:17 | amalloy | you can't have a lazy vector |
| 18:17 | amalloy | (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 | VT_entity | 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 | amalloy | 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 | raek | ...and not really a data structure, in a sense |
| 18:20 | raek | 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 | amalloy | 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 | VT_entity | 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 | VT_entity | 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 | amalloy | 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 | VT_entity | 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 | raek | 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 | no_mind | 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 | raek | 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 | raek | no_mind: in your case, the outer at should pass the select element subtree to the inner at |
| 18:47 | raek | 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 | raek | (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 | raek | 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 | raek | dnolen: http://technomancy.us/149 |
| 18:56 | raek | 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 | dnolen | so I guess run* is sort of like do in Haskell. |
| 19:09 | raek | no_mind: strange, it works with (content "BOO") instead of xyz... |
| 19:10 | raek | 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 | raek | 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 | raek | no_mind: evaluate (html/at rr [(html/id= "one")] xyz) and then look at the value of a |
| 19:20 | raek | no_mind: the interleaved printing confused the matter |
| 19:22 | raek | no_mind: to answer your original question: (html/at rr [(html/id= "one")] #(html/at % [:option] abc)) |
| 19:22 | raek | 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 | technomancy | adding shutdown-agents fixes it, but that's ridiculous |
| 19:32 | technomancy | 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 | hiredman | 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 | hiredman | waiting to be reused |
| 19:34 | hiredman | (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 | technomancy | that looks like the Right Thing |
| 19:41 | hiredman | they won't run until the threadpool threads stop |
| 19:41 | hiredman | "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 | hiredman | (which it must, come to think of it) |
| 19:43 | hiredman | to return exit codes |
| 19:43 | scgilardi | inc |
| 19:43 | technomancy | it only calls System/exit on failures |
| 19:43 | technomancy | 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 | raek | no_mind: could you explain the surrounding code? |
| 19:48 | no_mind | raek: http://pastebin.com/DLVbMw2F |
| 19:51 | raek | no_mind: first: use = instead of .equals |
| 19:52 | raek | no_mind: second: you are calling set-attr wrong. remember the "two stage" thing? |
| 19:53 | raek | and you are missing the else expression of the if |
| 19:53 | raek | which should return the node unchanges |
| 19:53 | raek | -d |
| 20:01 | raek | 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 | tomoj | so e.g. osc-clj has (ns osc) |
| 20:11 | tomoj | 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 | technomancy | to set your $PATH for GUI apps |
| 20:34 | technomancy | it's ridiculous |
| 20:34 | dnolen | technomancy: got a link? |
| 20:34 | technomancy | dnolen: actually clojure-swank-command would work too |
| 20:35 | technomancy | but you would still have trouble with non-swank commands like with magit |
| 20:35 | technomancy | 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 | technomancy | ooh; a non-xml version. slightly less awful! |
| 20:38 | technomancy | 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 | technomancy | (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 | dnolen | technomancy: I tried jack in from the dired view of my project. |
| 20:42 | technomancy | that oughtta work; is it just stalled? |
| 20:42 | technomancy | 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 | dnolen | 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 | dnolen | lein jack-in 36863: exited abnormally with code 1. |
| 20:47 | dnolen | 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 | dnolen | 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 | technomancy | this is really more of a convenience for people who haven't gone through the setup process yet |
| 20:49 | technomancy | 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 | technomancy | 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 | technomancy | 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 | dsop | 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 | dnolen | 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 | dnolen | hiredman: I ran into some weird errors and did not pursue. There no reason for core.logic to be 1.3 centric. |
| 21:16 | dnolen | 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 | dnolen | 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 | dnolen | 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 | TimMc | 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 | dnolen | attempted duplicate class definition for name |
| 22:22 | hiredman | bleh |
| 22:22 | hiredman | 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 | dnolen | 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 | dnolen | 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 | mefesto` | 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 | KirinDave | 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 | KirinDave | I dunno about it. |
| 23:01 | KirinDave | I see it usually in the context of proxies |
| 23:02 | KirinDave | 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 |