2011-01-26
| 03:06 | TobiasRaeder | morning |
| 03:12 | Scriptor | morning TobiasRaeder |
| 05:28 | edoloughlin | I keep getting a notice from sexpbot saying I have a new message and should 'use the mymail or mail commands without'. Excuse my ignorance, but what on Earth is this? |
| 05:31 | mrBliss` | edoloughlin: have a look at https://github.com/Raynes/sexpbot/blob/master/src/sexpbot/plugins/mail.clj |
| 05:33 | edoloughlin | mrBliss: Sorry, I've been a developer since 1992 but never used IRC for whatever reason until I started using Clojure. How do I send a command to sexpbot? |
| 05:35 | mrBliss` | edoloughlin: I think it is "/query sexpbot", but I'm not sure. |
| 05:35 | edoloughlin | Thanks |
| 06:01 | Leonidas | I have a global configuration (immutable) that I want to read from a JSON file and access in all functions. what is the best way to handle this? global variable? parameter to each function? a dynamically bound variable? |
| 06:09 | ejackson | Leonidas: I think a dynamically bound variable is the accepted answer, but not sure. |
| 06:10 | Leonidas | ejackson: I am thinking about posting it on the mailing list as it is not a technical problem but rather one of various pros and cons. |
| 06:10 | ejackson | I think if you search the IRC logs first, you'll find this discussed before |
| 06:11 | clgv | Leonidas: I made a configuration Object but also played with the thought of dynamically bound variables |
| 06:11 | ejackson | in fact, I'm almost certain of it |
| 06:11 | Leonidas | ejackson: the problem is, I don't know the proper search terms to get any useful results |
| 06:39 | AWizzArd | ~seen rhickey |
| 06:39 | clojurebot | Pardon? |
| 06:39 | AWizzArd | $seen rhickey |
| 06:39 | sexpbot | rhickey was last seen quitting 2 weeks and 1 day ago. |
| 06:43 | ejackson | sexpbot: rhickey is not a quitter - how DARE YOU SIR ! |
| 06:49 | clgv | lol! |
| 07:05 | Leonidas | http://paste.pocoo.org/show/327135/ why does this fail in json-read? I thought json-read returns the value when encountering an EOF? |
| 07:08 | clgv | A tricky question: when I open a repl in code that runs in the java Swing GUI thread I get an exeption that I am not allowed to use (in-ns) - does someone know why? |
| 07:09 | clgv | it's the debug-repl of George Jahad and Alex Osborne |
| 07:09 | raek | are you running a repl session in the swing thread? |
| 07:09 | raek | won't that block all gui events? |
| 07:18 | clgv | yes it will. it is a debug-repl to see why certain GUI code fails ;) |
| 07:19 | Leonidas | fun, I ran into a read-json bug |
| 07:19 | Leonidas | http://dev.clojure.org/jira/browse/CONTRIB-99 |
| 07:19 | clgv | it works in general but I cant change the namespace to the surrounding ns of the macro with (in-ns) |
| 07:25 | clgv | The exceptions says: Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Can't change/establish root binding of: *ns* with set |
| 07:25 | raek | I though that bug had been fixed |
| 07:25 | raek | http://dev.clojure.org/jira/browse/CONTRIB-91 |
| 07:30 | raek | there is a patch for it, but maybe it never got in... |
| 08:26 | Leonidas | get-votes-and-filter (fn [line] (remove (fn [[k v]] false) (get-votes line))) |
| 08:26 | Leonidas | this always fails with clojure.lang.LazySeq cannot be cast to clojure.lang.Associative. Why? |
| 08:26 | Leonidas | the remove-call should be a no-op |
| 08:29 | timvisher | hi all |
| 08:30 | AWizzArd | Hi timvisher. |
| 08:32 | timvisher | is there an easy way to write compound filters? i.e. (filter (and #(.isFile %) (complement #(.isHidden %))) ...) |
| 08:33 | timvisher | possibly even a filter that works on a #{} of predicates? |
| 08:35 | l0st3d | timvisher: as in (filter #(and (.isFile %) (not (.isHidden %))) ...) ? |
| 08:36 | timvisher | l0st3d: you know, I had a tickling feeling at the back of my skull that all I'd have to do was make the whole and a function... |
| 08:37 | timvisher | thanks! |
| 08:37 | timvisher | still new at this. :) |
| 08:37 | Leonidas | (fn [line] (remove (fn [[k v]] false) (get-votes line))) why does calling this result in a clojure.lang.LazySeq cannot be cast to clojure.lang.Associative error? |
| 08:37 | l0st3d | timvisher: me too ;) |
| 08:38 | clgv | timvisher: though a (filter-all #{ .isHidden isFile } ...) would be nice too ;) |
| 08:38 | l0st3d | timvisher: there's something called comp that will compose fns for you |
| 08:38 | clgv | s/#{ .isHidden isFile }/[.isHidden .isFile]/ |
| 08:43 | raek | Leonidas: what happens if you just eval (get-votes line)? |
| 08:44 | Leonidas | raek: {"Foo" {:upvotes 0 :downvotes 1}} |
| 08:45 | Leonidas | strange things happen |
| 08:45 | raek | ,(fn [] (remove (fn [[k v]] false) {"Foo" {:upvotes 0 :downvotes 1}})) |
| 08:45 | clojurebot | #<sandbox$eval628$fn__629 sandbox$eval628$fn__629@e5590e> |
| 08:45 | raek | ,(remove (fn [[k v]] false) {"Foo" {:upvotes 0 :downvotes 1}}) |
| 08:45 | clojurebot | (["Foo" {:upvotes 0, :downvotes 1}]) |
| 08:46 | raek | I think the problem is somewhere else.. |
| 08:46 | Leonidas | yeah, there is a [ ] there |
| 08:46 | Leonidas | where does the vector in the result come from? |
| 08:47 | raek | it's actually a MapEntry |
| 08:47 | raek | they implement IPersistentVector |
| 08:47 | raek | ,(seq {:a 1, :b 2}) |
| 08:47 | clojurebot | ([:a 1] [:b 2]) |
| 08:47 | Leonidas | I wanted to remove items which fail a certain perdicate from a dict, but what remove does is something... else. |
| 08:48 | Leonidas | is there a way how I can get a map out? |
| 08:48 | raek | ,(let [m {:a 1, :b 2}] (into (empty m) (remove (fn [[_ v]] (odd? v)) m))) |
| 08:48 | clojurebot | {:b 2} |
| 08:49 | raek | this will also the preserve the map type (hash-map/sorted-map) |
| 08:50 | Leonidas | what is the point of this strange behaviour? |
| 08:51 | raek | what behaviour? |
| 08:51 | raek | remove operates on sequences. it automatically calls seq on its argument to get a sequence for it. |
| 08:52 | Leonidas | that mapentries get generated? I thought that when I 'remove' on a map I get a map of the same shape out |
| 08:52 | raek | it could be possible that they are the same map enties used internally in the map |
| 08:53 | raek | conj, into, disj, pop, peek are polymorphic and return a datastructure of the same kind |
| 08:53 | raek | the sequence functions are seq-in seq-out |
| 08:54 | Leonidas | ah, hmm, I see. Much I have to learn, still |
| 08:56 | raek | (seq x) for data structure -> sequence and (into (empty x) ...) for sequence -> data structure lets you use the same functions for any type |
| 08:58 | zippy314 | Hi, I'm looking on thoughts on best practices in Clojure for handling inheritance. I've been reading The Joy of Clojure on prototyping and UDP, and I've implemented a few protocols/records. What I think I'd like to do is create a record/type that mixes in new methods, and can itself be inherited from. But I'm wondering if anybody have any pointers to best-practices/idiomatic ways of doing this in clojure? |
| 09:02 | ejackson | zippy314: i don't think it can be done. I tried before and ended up using macros to kludge it. However the more skilled present may know otherwise. |
| 09:03 | clgv | zippy314: afaik there is no such thing as inheritance between types or records in clojure. |
| 09:04 | zippy314 | cigv: ejackson: is that because it shouldn't be done in clojure because there's a better way to accomplish the same functionality, or because it's a limitation of clojure? That's what I'm trying to figure out. |
| 09:05 | ejackson | ah, its not possible in clojure, deliberately I think. |
| 09:06 | zippy314 | I'm reading in the docs this: "Concrete derivation is bad" (http://clojure.org/datatypes) and I'm trying to wrap my head around that. |
| 09:06 | zippy314 | and also this "Tying polymorphism to inheritance is bad" |
| 09:07 | clgv | in general you can use a written function on every data that has the "attributes" that are need by the function |
| 09:08 | timvisher | i'm getting a weird issue when I try to run `lein test`. |
| 09:08 | clgv | you can do dispatch via multimethods |
| 09:08 | timvisher | it's saying that `to-file-name-suffix` cannot be resolved |
| 09:08 | zippy314 | Yah. It looks like since you can simply define a record based on multiple protocols, that you can get the same effect just by mixing in lots of interfaces into one record. |
| 09:08 | timvisher | but `to-file-name-suffix` occurs nowhere in the code |
| 09:09 | timvisher | it used to, but I recently renamed it |
| 09:09 | zippy314 | timvisher: you might need to do 'lein clean' |
| 09:09 | timvisher | zippy314: just had that idea. tried it and it didn't make a difference |
| 09:10 | raek | maybe ~ files lying around |
| 09:10 | zippy314 | timvisher: also, maybe unsaved file so your search works, but on disk it's different |
| 09:11 | timvisher | Ah! |
| 09:11 | timvisher | I'm i'm an idiot as usual |
| 09:11 | timvisher | the core.clj file the error is referring to is my now _stale_ test/core.clj |
| 09:11 | timvisher | :) |
| 09:11 | timvisher | thanks as always, everyone |
| 09:25 | no_mind | which is a good tutorial for starting web development with clojure ? |
| 09:26 | dnolen | no_mind: http://mmcgrana.github.com/2010/03/clojure-web-development-ring.html |
| 09:26 | no_mind | thnxs |
| 09:35 | no_mind | when I run lein deps , it downloads clojure and clojure-contrib forr every new project. is there a way I can avoid this ? |
| 09:36 | jkdufair | I'm a longtime emacs user and have some decent exposure to clojure. I'm on windows and want to set up a production grade development env with Emacs/swank/lein. Recommendations re: native vs. cygwin? |
| 09:36 | ejackson | hmm, I thought it would pull them from your ~/.m2 |
| 09:37 | ejackson | jkdufair: I did this, but was painful. I used the powershell for lein etc, and normal emacs. I think cygwin should work too, but I had COM stuff in the mix that prevented me from doing it. |
| 09:38 | jkdufair | ejackson: thx. i'm leaning toward cygwin and have had some success so far, but just a bit of weirdness with lein |
| 09:39 | ejackson | yes, that's where I spent most of my time gnashing my teeth. There is a port for the script to powershell which worked fine. |
| 09:39 | ejackson | if maven works I'd suggest you just use that |
| 09:40 | jkdufair | you prefer maven over lein? |
| 09:40 | ejackson | yeah |
| 09:40 | jkdufair | pros/cons? |
| 09:40 | ejackson | maven has plugins for a bunch of stuff that i do and integrates nicely with my CI |
| 09:41 | jkdufair | cool. thx |
| 09:41 | ejackson | the XML is a pain intially, but nothing dramatic. |
| 09:50 | shortlord | I have written 2 functions and now want to use them from another namespace. Both functions use a lookup table as an argument, this lookup table is defined in their namespace. What is the most functional way to use these 2 functions now? using both functions + the lookup tables and always passing these tables in other namespaces sounds like a bad idea. Should I make some light wrappers in the original namespaces that supply th |
| 09:50 | shortlord | e lookups automatically? |
| 09:54 | ejackson | shortlord: I dunno why passing the lookup is a bad idea. But, if you arrange your argument order correctly you could partial over the lookup tables perhaps ? |
| 09:54 | ejackson | for you wrapper that is |
| 09:54 | tonyl | can you just require the ns where your fns and lookup tables in the current ns you want to use them? |
| 09:54 | shortlord | ejackson: yep, building the wrapper is easy, the lookup table is the first argument |
| 09:55 | ejackson | well, that seems reasonable, i guess. |
| 09:56 | shortlord | tonyl, ejackson: well, my problem is this: When should I use a wrapper/closure and when should I supply all the arguments every time? I'm pretty sure that the lookup table won't change for the whole application, but just wrapping the function does not seem to be very functional/pure |
| 09:57 | shortlord | I could of course just use the functions without a wrapper, but that would mean that I'd need to pass more arguments every time that I call such a function |
| 09:57 | ejackson | I think a partially applied function is very functional indeed |
| 09:58 | tonyl | then i agree with ejackson, it seems that that would benefit you |
| 09:59 | shortlord | ejackson: so where should I put this partial function? just defn a function in the namespace that uses the original function with the same name and just a (partial lookup-table old-function)? |
| 09:59 | ejackson | yeah |
| 09:59 | shortlord | or should I put this wrapper function in the old namespace, where both lookup tables and functions are contained? |
| 10:00 | ejackson | sorry, the latter. put it in the original namespace |
| 10:00 | shortlord | ejackson: ok. Is there any standard name scheme for simple wrapper functions? like wrapped-<function-name> or something like that? |
| 10:01 | ejackson | no, I'd go with something like standard |
| 10:01 | ejackson | standard-<function> |
| 10:01 | ejackson | of default-<function> |
| 10:01 | ejackson | but there is no reason to suspect that this is in any way more than my own opinion |
| 10:04 | shortlord | ejackson: ok, thx a lot :) |
| 10:14 | shortlord | is it possible to use something like :as in the namespace definition to rename functions in a :use expr? like (:use [clojure.set :only (difference :as diff)])? |
| 10:15 | mattmitchell | anyone know a nice way to convert a hash-map with string values to keyword values? |
| 10:15 | Chousuke | I think you need another vector |
| 10:15 | Chousuke | ie. :only ([difference :as diff]) |
| 10:16 | Chousuke | but I'm not sure, so check the docstring on use |
| 10:17 | Chousuke | mattmitchell: (into {} (map (fn [[k v]] [(keyword k) v]) original-map)) is probably the shortest way without any extra functions. |
| 10:18 | mattmitchell | Chousuke: excellent thanks! |
| 10:18 | Chousuke | note though that that may produce illegal keywords |
| 10:18 | Chousuke | if the strings have spaces in them for example |
| 10:19 | Chousuke | if you have string keys, it's often best to just keep them that way :) |
| 10:20 | mattmitchell | Chousuke: yes ok. the values are coming from a yaml file, so always come in as strings but will only ever be valid keywords |
| 10:26 | momos | Hello. How to check / modify classpath in clojure?I'm trying to write a cake task which uses my project dependent jar's, but my normally working code fails to import java dependencies. How to debug this? |
| 10:28 | mattmitchell | How can I make a "public" defonce or def? I'd like my other namespaces to have access to this value. |
| 10:29 | tonyl | def is public |
| 10:29 | tonyl | just either require the namespace where the binding is |
| 10:30 | tonyl | require or use whichever form fits you best |
| 10:30 | mattmitchell | tonyl: oh i see. so i can't just go into a diff namespace and call the other like (other/some-def) ? |
| 10:31 | mattmitchell | tonyl: ahh ok i got it! it's not a function :) |
| 10:31 | mattmitchell | tonyl: thanks |
| 10:32 | tonyl | yes, and it could be a function or a special case in the ns form whichever you prefer |
| 10:32 | mattmitchell | tonyl: ok i see |
| 10:35 | LauJensen | Chousuke: I prefer reduce ##(reduce #(assoc %1 (keyword (%2 0)) (%2 1)) {} {"string" 5 "str" 10}) |
| 10:35 | sexpbot | ⟹ {:str 10, :string 5} |
| 10:59 | symuyn | Let's say that I have a map: string keys → vectors of string keys. |
| 11:00 | symuyn | So it represents a directed network, and loops are allowed. If a vector contains a string A, the vector’s own key is connected *to* A. |
| 11:00 | symuyn | I want to create another map: string keys → sets of string keys, such that the sets only contain all of the string keys that are directly connected to it (but not from it)…including the key itself. |
| 11:00 | symuyn | (Eventually, I’d like to be able to calculate the keys’ distances too, but that can be later.) |
| 11:00 | symuyn | I can't think of a good way to start, though. Is there a library or simple function that can help me? |
| 11:01 | ejackson | does to-from make any sense in an looping network ? |
| 11:01 | symuyn | I believe so |
| 11:01 | symuyn | Think of recursive functions |
| 11:01 | ejackson | A -> B -> C -> A |
| 11:02 | ejackson | is C connected to or from A ? |
| 11:02 | symuyn | Oh dear, I think I typoed: "If a vector contains a string A, the vector’s own key is connected *from* A." |
| 11:02 | ejackson | well, both |
| 11:02 | symuyn | Hmm |
| 11:02 | symuyn | ejackson: Yes, both. Which it will always be, in a loop |
| 11:03 | hoggarth | symuyn: does this help? http://richhickey.github.com/clojure-contrib/graph-api.html |
| 11:04 | symuyn | hoggarth: Do you know the data format that the library's graphs are supposed to be in? I can't find it. |
| 11:04 | symuyn | How do you make a graph? |
| 11:05 | ejackson | symuyn: this might throw you off course, but I made a little dijstra toy algo last year. https://github.com/ejackson/dijkstra/blob/master/src/main/clojure/net/edmundjackson/astar.clj It makes graph, connects nodes etc, might be helpful. </end blowing own's trumpet> |
| 11:06 | hoggarth | :nodes ; The nodes of the graph, a collection |
| 11:06 | hoggarth | :neighbors) |
| 11:06 | hoggarth | oops |
| 11:06 | hoggarth | symuyn: (defstruct directed-graph |
| 11:06 | hoggarth | :nodes ; The nodes of the graph, a collection |
| 11:06 | hoggarth | :neighbors) |
| 11:06 | symuyn | hoggarth: I see, a struct. |
| 11:06 | symuyn | Pity it doesn't show up on the documentation. |
| 11:06 | symuyn | ejackson: I'll look at that, thanks |
| 11:06 | mec_ | Is there a good way to filter for unique values while keeping the sequence in order? |
| 11:06 | ejackson | of course, cgrand has one too: http://clj-me.cgrand.net/ |
| 11:07 | tonyl | mec_: has it happened to you otherwise? |
| 11:08 | chouser | (doc distinct) |
| 11:08 | clojurebot | "([coll]); Returns a lazy sequence of the elements of coll with duplicates removed" |
| 11:08 | chouser | mec_: ^^^ |
| 11:08 | tonyl | but if you want unique values, maybe hash-set's or sorted-sets' would work for you |
| 11:09 | mec_ | yes but they need to remain the way they are ordered, sets will change order |
| 11:09 | mec_ | chouser: thanks a bunch |
| 11:09 | ejackson | distinct ! cool. |
| 11:10 | symuyn | hoggarth: Yes, this will do; I can't use the library directly, but it shows me how |
| 11:10 | symuyn | Thanks a lot |
| 11:10 | mec_ | i seem to always pick the wrong synonym for what i want |
| 11:11 | chouser | mec_: note that if you walk to the end of the seq returned by distinct, you will end up with the whole (non-dup) collection in memory, even if you aren't holding the head of the seq |
| 11:12 | shortlord | there is no built-in operator that does the opposite of 'frequencies', so (map #(repeat (val %) (key %)) my-map) would be the easiest way, right? |
| 11:12 | shortlord | (+ a flatten in front of it) |
| 11:13 | mec_ | chouser: that should be fine |
| 11:14 | symuyn | What is the hash code of a lazy sequence? What happens when it's used as a hash map's key? |
| 11:16 | tonyl | &(hash (range)) |
| 11:16 | sexpbot | Execution Timed Out! |
| 11:16 | tonyl | mm good quesiton |
| 11:16 | tonyl | *question |
| 11:18 | symuyn | Seems kind of weird |
| 11:19 | tonyl | not necessarily it needs to know the values of the lazy-seq to make a hash of it, so the values are trying to be realized |
| 11:19 | chouser | shortlord: mapcat instead of map |
| 11:20 | symuyn | &(count (assoc {} (range) 1 (range) 2)) |
| 11:20 | sexpbot | Execution Timed Out! |
| 11:20 | symuyn | So it tries to fully evaluate |
| 11:21 | tonyl | yes, that is my understanding of hashcode in java, but it's been a while |
| 11:21 | chouser | a lazy seq hashes to the same as a list or vector with the same contents, so it has to realize the whole thing |
| 11:22 | shortlord | chouser: how would mapcat help there? It is only one map that I want to transform into one seq |
| 11:22 | chouser | shortlord: then you don't need the flatten or a concat |
| 11:25 | shortlord | chouser: you mean like (mapcat repeat (vals foo) (keys foo))? |
| 11:27 | chouser | sure, or (mapcat #(repeat (val %) (key %)) foo) |
| 11:27 | shortlord | chouser: nice solution, thx |
| 11:28 | chouser | I dislike flatten, and (apply concat (map ...)) always suggests (mapcat ...) |
| 11:30 | symuyn | flatten does seem a little inefficient |
| 11:31 | chouser | well, it's a big hammer |
| 11:31 | chouser | ,(mapcat #(repeat (val %) (key %)) {:a 2 :b 2 [:c :d] 3}) |
| 11:31 | clojurebot | (:a :a :b :b [:c :d] [:c :d] [:c :d]) |
| 11:31 | chouser | ,(flatten (map #(repeat (val %) (key %)) {:a 2 :b 2 [:c :d] 3})) |
| 11:31 | clojurebot | (:a :a :b :b :c :d :c :d :c :d) |
| 11:32 | chouser | if it's actually what you want, fine, but in my experience it rarely is. |
| 11:38 | pdk | (doc xor) |
| 11:38 | clojurebot | Gabh mo leithscéal? |
| 11:38 | chouser | (doc bit-xor) |
| 11:38 | clojurebot | "([x y]); Bitwise exclusive or" |
| 11:39 | pdk | i was thinking logical xor to use alongside or/and but hey |
| 11:40 | chouser | yeah, I don't think Clojure's got that |
| 11:40 | pdk | funky |
| 11:41 | chouser | it couldn't short-circuit or do anything useful varargs like or/and |
| 11:51 | zippy314 | is there a way to give defrecord a doc string so that it will show up in autodoc? |
| 11:54 | tonyl | zippy314: AFAIK there isn't |
| 11:54 | zippy314 | hmmm gripe. |
| 11:56 | mec_ | ,(str (doall (range 10))) |
| 11:56 | clojurebot | "clojure.lang.LazySeq@9ebadac6" |
| 11:57 | chouser | zippy314: usually the public face of a defrecord is a factory function, which can of course have a docstring |
| 11:57 | chouser | ,(pr-str (range 10)) |
| 11:57 | clojurebot | "(0 1 2 3 4 5 6 7 8 9)" |
| 11:57 | zippy314 | chouser: right! |
| 11:58 | mec_ | ah that works, but what am i thinking wrong about doall? |
| 11:59 | chouser | str and pr-str do the same thing in a lot of cases. strings and lazy-seqs are a couple of the relatively few exceptions |
| 11:59 | chouser | ,((juxt str pr-str) [1 2 [3 4] '(5 6)]) |
| 11:59 | clojurebot | ["[1 2 [3 4] (5 6)]" "[1 2 [3 4] (5 6)]"] |
| 11:59 | chouser | ,((juxt str pr-str) "hi") |
| 11:59 | clojurebot | ["hi" "\"hi\""] |
| 12:00 | pdk | is there a way to capture a full java stack trace say to a file |
| 12:00 | pdk | vs having it print to the command line and get cut off |
| 12:03 | zakwilson | danlarkin: that NoSQL presentation you posted last night was interesting. When put in the terms the presented used, it seems likely that I do have a single question I usually want to answer and Mongo is probably a good fit for the problem. |
| 12:03 | tonyl | maybe binding *err* to a reify'ed PrintWriter and change the method that outputs to write to a file |
| 12:03 | zakwilson | s/presended/presenter |
| 12:04 | tonyl | pdk: ^^ just the first thought that came to me |
| 12:04 | tonyl | so it might be wrong |
| 12:04 | zippy314 | pdk: (binding [*err* (java.io.PrintWriter. (writer "/your/file"))] |
| 12:05 | danlarkin | zakwilson: cool, I'm glad you found some value from it, and glad you've come to an evidence-based conclusion :) |
| 12:05 | tonyl | simpler zippy314 |
| 12:05 | zippy314 | :pdk, then (.printStackTrace e *err*) |
| 12:06 | zakwilson | And if I'm lucky, scaling will be a concern. |
| 12:06 | symuyn | Another question! Pre- and post-condition are idiomatic, and that Clojure style guides says they're supposed to be ubiquitous. |
| 12:06 | symuyn | Is there any way to turn them off, though? |
| 12:07 | symuyn | (When you're not debugging, for production runs) |
| 12:10 | mattmitchell | is it possible to "use" namespace B in namespace A, then from namespace C, access the B functions "through" A? |
| 12:12 | ohpauleez | mattmitchell: Take a look at potemkin |
| 12:13 | ohpauleez | Typically, what you're asking for you wouldn't do, but potemkin allows you to man-handle the namespaces and imports |
| 12:14 | mattmitchell | ohpauleez: oh cool ok. that's exactly what i'm looking for. |
| 12:14 | ohpauleez | You would normally just use, B and A in C. I personally prefer require, or use-only so that it's clearly documented what I'm using, and where it came from. |
| 12:14 | ohpauleez | mattmitchell: awesome! Glad I could help |
| 12:14 | mattmitchell | ohpauleez: ok so another related question, is it possible to define a function in a different namespace? |
| 12:15 | ohpauleez | mattmitchell: http://clojuredocs.org/clojure_core/clojure.core/in-ns |
| 12:16 | ohpauleez | actually, with-ns is probably what you want |
| 12:16 | ohpauleez | &(doc with-ns) |
| 12:16 | sexpbot | java.lang.Exception: Unable to resolve var: with-ns in this context |
| 12:16 | ohpauleez | it's in contrib |
| 12:17 | ohpauleez | mattmitchell: http://clojuredocs.org/clojure_contrib/clojure.contrib.with-ns/with-ns |
| 12:17 | mattmitchell | ohpauleez: excellent thanks again! |
| 12:17 | ohpauleez | np, glad I could help! |
| 12:42 | momos | Perhaps a lot of you is developing in Clojure at work or for commercial projects. do you publish your code on github etc? if yes, how do you link the commercial and open-source side? under what license do you publish the code? |
| 12:45 | ejackson | momos: a good example of this is Bradford Cross's stuff. Check out https://github.com/getwoven. I guess the license is in there somewhere if you look. |
| 12:45 | momos | hmm I've seen this repo somewhere |
| 12:47 | ejackson | it used to be called clj-sys |
| 12:48 | momos | the license isn't very noticeable.... can't find it |
| 12:48 | momos | maybe there's a default one for clj :P |
| 12:49 | momos | ah.ok. there are a bunch of mit licenses just on some projects |
| 12:51 | ohpauleez | momos: I'm sure you'll see mostly EPL or MIT/BSD licenses for things |
| 12:51 | ohpauleez | you can then take those, and use them in a private, proprietary project |
| 13:26 | amalloy | pdk: if you're looking for logical xor: ##(apply not= (map boolean [:a :b])) |
| 13:26 | sexpbot | ⟹ false |
| 13:27 | pdk | GASP |
| 13:44 | defn | 'lo |
| 13:47 | bobo | if im handed a vector thats realy a map ie [key1 val1 key2 val2] whats the simplest way to turn it into a real map? |
| 13:47 | bobo | cant figure something simple out |
| 13:47 | mefesto | bobo: vec i think |
| 13:48 | mefesto | ,(vec [:a 1 :b 2 :c 3]) |
| 13:48 | clojurebot | [:a 1 :b 2 :c 3] |
| 13:48 | mefesto | oops, what am i thinking :) |
| 13:48 | bobo | :-) |
| 13:48 | mattmitchell | could someone show me how i could "dry" this up? https://gist.github.com/797191 |
| 13:48 | mefesto | ,(apply hash-map [:a 1 :b 2]) |
| 13:48 | clojurebot | {:a 1, :b 2} |
| 13:49 | bobo | mefesto: ofcource! thanks |
| 13:49 | mattmitchell | the only differences between the 2 are the names of the database table and a mapping in "m" |
| 13:50 | chouser | mattmitchell: (db/partners (documentor m/partner)) |
| 13:50 | chouser | then just write your documentor function |
| 13:54 | mattmitchell | chouser: oh right. so pass in the functions, don't immediately execute them |
| 14:03 | KirinDave | It's so cute when someone is like, "Oh dang, macros are pretty weird." for the first time. |
| 14:03 | KirinDave | e.g., http://brandonbyars.com/2008/02/12/understanding-syntactic-macros/ that is making its way around hackernews |
| 14:06 | mattmitchell | how do i get a reference to a function in another namespace and pass it off as a callback to something else? |
| 14:07 | Scorchin | Hey guys, I sent in a pull request a while back to clojure-contrib and it's not been merged. I realise it's probably because it's not considered good enough, but I'd love to know why so I don't make the same mistake again. Pull request here: https://github.com/clojure/clojure-contrib/pull/4 |
| 14:08 | chouser | mattmitchell: just use its name |
| 14:08 | hiredman | Scorchin: you should read the guid for contributing on the clojure website |
| 14:08 | chouser | , clojure.core/filter |
| 14:08 | clojurebot | #<core$filter clojure.core$filter@1c0035b> |
| 14:08 | hiredman | Scorchin: clojure and clojure-contrib don't take pull requests |
| 14:08 | Scorchin | hiredman: Thanks! That makes a lot of sense |
| 14:09 | mattmitchell | chouser: oh that's embarrassing, thanks :) |
| 14:10 | nishant | how can I start swank with a bigger heap? |
| 14:20 | nishant | nevermind |
| 14:52 | pauldoo | how do I zip two sequences together? e.g. turn [[1 2 3] [4 5 6]] into [[1 4] [2 5] [3 6]] |
| 14:52 | chouser | ,(map vector [[1 2 3] [4 5 6]]) |
| 14:52 | amalloy | &(map vector [[1 2 3] [4 5 6]]) |
| 14:52 | clojurebot | ([[1 2 3]] [[4 5 6]]) |
| 14:52 | sexpbot | ⟹ ([[1 2 3]] [[4 5 6]]) |
| 14:52 | chouser | wow |
| 14:52 | amalloy | haha |
| 14:52 | amalloy | &(apply map vector [[1 2 3] [4 5 6]]) |
| 14:52 | sexpbot | ⟹ ([1 4] [2 5] [3 6]) |
| 14:53 | chouser | exactly the same mistake at exactly the same moment |
| 14:53 | amalloy | i was even thinking "do i need apply here? no, not for this instance, because map works on a sequence" |
| 14:53 | chouser | pauldoo: hi, btw. |
| 14:54 | amalloy | pauldoo: there's also ##(apply zipmap [[1 2 3] [4 5 6]]) if you want it as a map instead of an ordered set of pairs |
| 14:54 | sexpbot | ⟹ {3 6, 2 5, 1 4} |
| 14:54 | pauldoo | aha! the vector function is useful! :) |
| 14:54 | pauldoo | cunning! |
| 14:54 | pauldoo | chouser: hello to you to. :) |
| 14:55 | semperos | incanter does something similar |
| 14:57 | __name__ | sexpbot: (contains? '(1 2 3) 1) |
| 14:57 | __name__ | &(contains? '(1 2 3) 1) |
| 14:57 | sexpbot | ⟹ false |
| 14:57 | fogus` | pauldoo: And also ##(apply interleave [[1 2 3] [4 5 6]]) if you don't want them grouped in vectors. ;-) |
| 14:57 | sexpbot | ⟹ (1 4 2 5 3 6) |
| 14:57 | __name__ | why does it just randomly say false instead of failing? |
| 14:58 | pauldoo | fogus`: right-o |
| 14:58 | pauldoo | I'm twatting about reimplemting "separate" so that the filter function is only called once per element |
| 14:58 | chouser | __name__: well, it has no keys at all, so I guess it doesn't have a key of 1 |
| 14:59 | pauldoo | (defn separate [f s] |
| 14:59 | pauldoo | (let [t (map vector (map f s) s)] |
| 14:59 | pauldoo | [ (map second (filter first t)), (map second (filter (complement first) t)) ])) |
| 14:59 | pauldoo | is the best I have so far |
| 14:59 | amalloy | __name__: there is nothing random, and it is not failing |
| 15:00 | amalloy | contains? is for seeing if a map contains a key, not if a list contains a value |
| 15:00 | amalloy | you want ##(doc some) for that |
| 15:00 | sexpbot | ⟹ "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)" |
| 15:00 | __name__ | amalloy: why does it work on a list then? |
| 15:01 | fogus` | __name__: This explains it well. http://en.wikibooks.org/wiki/Clojure_Programming/FAQ#Why_doesn.27t_contains.3F_do_what_I_expect_on_vectors_and_lists |
| 15:01 | amalloy | &(some #{1} '(1 2 3)) |
| 15:01 | sexpbot | ⟹ 1 |
| 15:01 | __name__ | i know that that is how it is done, but why does the compiler not tell? |
| 15:02 | amalloy | $source contains? |
| 15:02 | sexpbot | contains? is http://is.gd/60Qkhn |
| 15:02 | __name__ | ah |
| 15:02 | __name__ | i see |
| 15:02 | __name__ | now it makes sense, thanks |
| 15:02 | amalloy | welcome |
| 15:03 | shortlord | is there some operator like for that travesers multiple bindings parallel? like (for [x [1 2 3 4] y [1 2 3 4]] [x y]) => [[1 1] [2 2] [3 3] [4 4]] |
| 15:03 | chouser | shortlord: map |
| 15:04 | chouser | ,(map vector [1 2 3 4] [1 2 3 4]) |
| 15:04 | clojurebot | ([1 1] [2 2] [3 3] [4 4]) |
| 15:04 | chouser | amalloy: where were you? |
| 15:04 | shortlord | chouser: not as easliy understandable with big expressions as functions, but I guess it has to do |
| 15:05 | amalloy | chouser: jeez sorry, i guess i have to quit my job to keep up with you |
| 15:05 | amalloy | shortlord: you can do this with for also |
| 15:05 | chouser | shortlord: I've thought about how to add that as a feature of 'for' somehow, but I haven't come up with anything that isn't clearly worse. |
| 15:05 | amalloy | or...no, maybe you can't |
| 15:05 | chouser | amalloy: well, it was the same answer as we tied on last time. I assumed I was racing you again. ;-) |
| 15:06 | shortlord | chouser: well, there are already tags like ':let', right? something like ':parallel' would be nice |
| 15:06 | amalloy | &(for [[x y] (interleave [1 2 3 4] [:a :b :c :d])] [x y]) |
| 15:06 | sexpbot | java.lang.UnsupportedOperationException: nth not supported on this type: Integer |
| 15:07 | chouser | shortlord: but how would you use it that doesn't end up looking like just a 'map' inside the 'for'? |
| 15:07 | nickik | first we should get the pmap stuff write (fj) then we can start build parallel everything on top of that. |
| 15:07 | chouser | different kind of parallel |
| 15:08 | amalloy | chouser: but wouldn't it be so much fun to combine them |
| 15:08 | shortlord | chouser: what do you mean? you could just use something like [x y] inside the for, which should be quite nice in cases where you have large expressions that otherwise would have to be defined as functions previously |
| 15:09 | chouser | shortlord: do you have an example in mind of how you could use it? |
| 15:12 | shortlord | chouser: I have an application where I have a vector that holds a lot of similar maps (it's a field made up of fields with quite a few attributes). Now I am using a token that marks one field; this token is a ref that stores the vector index of the field that it references |
| 15:12 | amalloy | shortlord: i think he means, write a for statement using the syntax you wish existed |
| 15:12 | chouser | shortlord: I guess I'm talking about about the syntax than the semantics. Do you have a little code snippet of how you'd use for with :parallel? |
| 15:13 | chouser | :-) |
| 15:15 | shortlord | chouser: I'm not sure whether I understand what you want. The syntax should be as simple as that: https://gist.github.com/797350 If you want a usecase, that's what I've tried to describe |
| 15:16 | chouser | shortlord: so :parallel would group the previous binding (x in your example) with the following (y) |
| 15:17 | chouser | if you had more than two in the group, you would pu :parallel between all of them (like infix notation)? |
| 15:17 | chouser | :when and :while would be illegal inside such groups? |
| 15:19 | tonyl | that is a very big macro |
| 15:19 | tonyl | for |
| 15:19 | chouser | yes. yes it is. |
| 15:20 | shortlord | chouser: ':parallel' would be used equal to :let, so :while and :when should still be allowed. :parallel would just make the bindings after it run at the same index as the main binding in for. But yes, having several bindings in the main for block zould be a problem |
| 15:21 | amalloy | shortlord: there is no "main" binding |
| 15:21 | shortlord | amalloy: I mean the normal binding pair without any tags |
| 15:22 | mefesto | this is to avoid (map vector xs ys zs) ? |
| 15:23 | shortlord | mefesto: in case the function is a simple as vector, map is clearly a good choice. but for with such a tag could be nice for larger expressions |
| 15:23 | chouser | right. (for [[x y] (map vector [1 2 3 4 5] [1 2 3 4 5])] [x y]) would be one way to write that gist currently |
| 15:23 | mefesto | (for [[x y z] (map vector xs ys zs)] [z y x]) |
| 15:25 | chouser | Maybe (for [[x y z] :parallel [xs ys zs]] ...) :-) |
| 15:32 | tonyl | if there are lager expressions, just pull them up as a function |
| 15:37 | shortlord | tonyl: yeah, I guess that should do the job well enough |
| 15:38 | shortlord | what is the recommended way to create a map for a small collection of things? array-map? |
| 15:38 | amalloy | chouser: not sure if you were serious with your last suggestion but that would mess up the binding-partitioning |
| 15:39 | tonyl | hash-map |
| 15:39 | tonyl | &(hash-map 1 2 3 4) |
| 15:39 | sexpbot | ⟹ {1 2, 3 4} |
| 15:39 | __name__ | why can i not add metadata to an integer? |
| 15:39 | amalloy | shortlord: probably (into {}), which will decide for you whether to use an array |
| 15:39 | amalloy | &(instance? IObj 1) |
| 15:39 | sexpbot | java.lang.Exception: Unable to resolve symbol: IObj in this context |
| 15:40 | amalloy | &(instance? clojure.lang.IObj 1) |
| 15:40 | sexpbot | ⟹ false |
| 15:40 | __name__ | or, rather, how can i attach it? |
| 15:41 | chouser | amalloy: yeah, I wasn't very serious |
| 15:43 | amalloy | __name__: put it on something other than an integer :P |
| 15:44 | __name__ | amalloy: I guessed that. |
| 15:44 | amalloy | &(-> 10 vector (with-meta {:name "frank"}) ((juxt first meta))) |
| 15:44 | sexpbot | ⟹ [10 {:name "frank"}] |
| 15:46 | shortlord | how random is clojure's shuffle? it does not seem to shuffle a seq a lot |
| 15:47 | amalloy | shortlord: as random as pseudorandom gets. it calls java.util.Collections.shuffle |
| 15:48 | amalloy | $source shuffle |
| 15:48 | sexpbot | shuffle is http://is.gd/xc6JDT |
| 15:48 | shortlord | amalloy: ok. I guess it just seems not very random at times... normal paranoia ;) |
| 15:49 | amalloy | indeed. humans are terrible at randomness |
| 15:50 | hiredman | I suggest running some stats |
| 15:53 | __name__ | $source with-meta |
| 15:53 | sexpbot | with-meta is http://is.gd/D0GjxE |
| 15:58 | __name__ | &(with-meta 1/1 {:k "v"}) |
| 15:58 | sexpbot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IObj |
| 15:58 | __name__ | &(with-meta 1/2 {:k "v"}) |
| 15:58 | sexpbot | java.lang.ClassCastException: clojure.lang.Ratio cannot be cast to clojure.lang.IObj |
| 16:04 | robonobo | __name__, you can private message sexpbot if you want to use it's services without flooding the channel |
| 16:04 | pdk | (doc repeatedly) |
| 16:04 | clojurebot | "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it" |
| 16:04 | __name__ | i did not flood the channel, did i? |
| 16:04 | pdk | (doc repeat) |
| 16:04 | clojurebot | "([x] [n x]); Returns a lazy (infinite!, or length n if supplied) sequence of xs." |
| 16:04 | robonobo | __name__: no, but you were of risk of doing |
| 16:05 | __name__ | robonobo: why? |
| 16:05 | robonobo | just use sexpbot here if it's pqrtof dicussion |
| 16:06 | __name__ | robonobo: it was, kind of. |
| 16:06 | robonobo | oh, i see, cqrry on, my apologies good sir |
| 16:07 | brehaut | robonobo: you need to get your \a key checked |
| 16:07 | semperos | perhaps he's using a French keyboard |
| 16:08 | thuner | He everyone! |
| 16:08 | thuner | I followed the instuction if https://github.com/richhickey/clojure-contrib/blob/master/README.txt, however the command "mvn package" did not created the target directory. Anyone had the same issue? |
| 16:09 | amalloy | thuner: richhickey's repository is quite out-of-date. i don't know if it will fix your specific problem but you should use the clojure/clojure-contrib repo |
| 16:10 | thuner | thank's I'll give a look at it |
| 16:19 | __name__ | amalloy: is there no way to wrap an integer in something that implements IObj if one wants metadata? |
| 16:19 | amalloy | __name__: what's wrong with the vector-wrapping snippet i gave? |
| 16:20 | __name__ | amalloy: that it returns [int meta] instead of the int with the meta attached? |
| 16:21 | tonyl | __name__: you could reify your own "box" I don't know how that would affect your algorithm |
| 16:21 | amalloy | &(-> 10 vector (with-meta {:name "frank"})) |
| 16:21 | sexpbot | ⟹ [10] |
| 16:21 | amalloy | the ((juxt first meta)) at the end is to unwrap that into the original integer and the meta you attached to the vector |
| 16:22 | chouser | you'd have to decide what operations on the number retain which metadata |
| 16:22 | amalloy | not that this is really a great idea anyway. instead of attaching meta to an integer, why not just use a real datastructure that stores the information you need |
| 16:27 | semperos | learning ring-based web application in Clojure, using enlive and moustache |
| 16:27 | semperos | I define an enlive template (deftemplate) called "index" |
| 16:27 | semperos | deftemplate returns a lazy seq of strings |
| 16:28 | semperos | I then use ring.util.response/response to put that into the :body of a response |
| 16:28 | semperos | (response (index)) |
| 16:28 | __name__ | amalloy: it's more of a principle thing really. |
| 16:28 | __name__ | amalloy: I just wished i could attach metadata without caring what type the data is. |
| 16:28 | semperos | on the repl, the lazy seq is evaluated, and I see what I expect |
| 16:29 | semperos | but when I run it in my web app, I just get a string representation of the lazy seq, "clojure.lang.LazySeq@dd5c324b" |
| 16:29 | brehaut | semperos: i use (defn render [s] (apply str s)) from dnolen's enlive tutorial |
| 16:29 | semperos | yeah |
| 16:29 | semperos | I nkow I can do apply str all over the place :) |
| 16:29 | semperos | but the Ring spec says it takes an ISeq |
| 16:29 | semperos | of strings |
| 16:29 | semperos | in addition to a plain string |
| 16:29 | semperos | was wondering if I was missing something obvious |
| 16:30 | semperos | about the evaluation of a deftemplate's lazy seq of strings |
| 16:34 | brehaut | semperos: ring.uril.servlet/set-body does check for seq's |
| 16:34 | brehaut | semperos: https://github.com/mmcgrana/ring/blob/master/ring-servlet/src/ring/util/servlet.clj#L79-83 |
| 16:35 | semperos | right |
| 16:35 | semperos | it works at the repl, when I give the :body a seq of strings |
| 16:36 | semperos | just not in the app |
| 16:36 | brehaut | does (seq? (index ...)) return trye? |
| 16:36 | semperos | yes |
| 16:37 | semperos | in the app, the :body is actually set to "clojure.lang.LazySeq@xxxxx" |
| 16:38 | brehaut | which is what you would expect if str is called on the lazy-seq directly |
| 16:38 | brehaut | (str (lazy-seq [1 2])) |
| 16:38 | brehaut | bah |
| 16:38 | brehaut | $(str (lazy-seq [1 2])) |
| 16:38 | chouser | use & or , |
| 16:38 | semperos | &(str (lazy-seq [1 2])) |
| 16:38 | sexpbot | ⟹ "clojure.lang.LazySeq@3e2" |
| 16:38 | brehaut | thanks |
| 16:39 | semperos | yep, I get that |
| 16:39 | semperos | I'm sure I'm just missing something very basic |
| 16:40 | semperos | so (response) takes anything that is allowed by the Ring spec as part of the response :body |
| 16:40 | semperos | and sticks it in there |
| 16:40 | semperos | so at the repl, if I do (response (index)), I get everything evaluated correctly |
| 16:40 | semperos | doesn't do the same when I add it to a route with moustache |
| 16:40 | semperos | [""] {:get (fn [req] (response (index)))} |
| 16:41 | semperos | that's my confusion |
| 16:45 | LauJensen | For the Emacsers in here: http://offtopic.bestinclass.dk/post/2942525776/my-emacs-color-theme |
| 16:46 | semperos | nice |
| 16:49 | robonobo | LauJensen: your server seems to be down |
| 16:49 | LauJensen | robonobo: ? |
| 16:49 | LauJensen | robonobo: http://www.downforeveryoneorjustme.com/ |
| 16:50 | neilcj | not down for me ;) |
| 16:50 | __name__ | neither |
| 16:51 | neilcj | LauJensen: pretty theme, thanks for sharing |
| 16:51 | robonobo | it's back after a few tries (it was a maximum bandwith exceededthing, but with nicer layout) |
| 16:52 | pdk | did i ever mention |
| 16:52 | pdk | the parens matching in vimclojure has a really bad case of alzheimer's |
| 16:53 | brehaut | semperos: what middleware are you using (if any) |
| 16:53 | semperos | stacktrace, keyword-params, reload, and a custom one; going to try without the custom one |
| 16:54 | semperos | gah |
| 16:55 | semperos | well, that pinpoints where the error was |
| 16:55 | brehaut | :) |
| 16:55 | semperos | not surprisingly, my own mess |
| 16:55 | LauJensen | neilcj: np :) |
| 16:56 | LauJensen | pdk: Thats fair enough, since you yourself have got to have a pretty bad case of alzheimers to be using Vim in the first place |
| 16:56 | brehaut | LauJensen: theme looks nice |
| 16:56 | LauJensen | brehaut: thanks - notice how the foreground != the background. You could learn a few things :) |
| 16:56 | brehaut | LauJensen: could do with some more eye searing yellow though |
| 16:56 | LauJensen | brehaut: its got plenty yellow - I even got a complaint on twitter about it |
| 16:56 | brehaut | haha |
| 16:56 | brehaut | classic |
| 16:56 | pdk | wellllll |
| 16:56 | pdk | granted! |
| 16:59 | ohpauleez | I use wombat, and still love it: http://dengmao.wordpress.com/2007/01/22/vim-color-scheme-wombat/ |
| 17:00 | ohpauleez | I made a 256 color scheme for it |
| 17:02 | LauJensen | ohpauleez: You can paint Vim... but its still Vim :( |
| 17:03 | ohpauleez | haha you're relentless LauJensen |
| 17:03 | LauJensen | Indeed :) |
| 17:03 | LauJensen | Its called Persistent |
| 17:03 | ohpauleez | paredit.vim + vimclojure + vim + zsh seems to do the trick for me |
| 17:04 | LauJensen | oh, you didn't tell me you were a beginner.. Beginners are allowed to evaluate their tools |
| 17:05 | wolverian | there's a paredit.vim? oh my. |
| 17:05 | wolverian | oh, slimv. |
| 17:06 | wolverian | I never managed to get vimclojure and slimv working together. slimv would force lisp syntax highlighting on my buffers. |
| 17:06 | chouser | experts must accept LauJensen's word without question |
| 17:06 | LauJensen | You can trust chouser, he's been here forever |
| 17:10 | ohpauleez | wolverian: I just yanked paredit.vim out of slimv |
| 17:10 | ohpauleez | haha LauJensen I just caught myself up |
| 17:11 | LauJensen | ohpauleez: So you're using Emacs now? |
| 17:11 | ohpauleez | I always *HAVE* used it. Clojure is the first Lisp I feel comfortable editing in vim, and do most of my day to day edits in vim. But yes, I use both |
| 17:11 | ohpauleez | there, I admitted it :) |
| 17:12 | brehaut | ohpauleez: clojure is the first lisp i have felt comfortable editign in emacs |
| 17:12 | LauJensen | :D |
| 17:13 | LauJensen | I gotta take off gents, but as always, it was fun hanging out with you :) |
| 17:13 | brehaut | gnite lau |
| 17:13 | ohpauleez | later |
| 18:04 | __name__ | http://paste.pocoo.org/show/327503/ |
| 18:05 | __name__ | how do i prevent this from happening? |
| 18:07 | brehaut | __name__: which clojure are you using? |
| 18:07 | brehaut | __name__: 1.3? |
| 18:07 | __name__ | brehaut: 1.2 |
| 18:07 | __name__ | oh, wait |
| 18:07 | __name__ | it's 1.3 |
| 18:08 | brehaut | *clojure-version* |
| 18:08 | brehaut | thats why |
| 18:08 | __name__ | yes, i typed it into the wrong repr. i am deeply sorry. |
| 18:08 | brehaut | no problem |
| 18:09 | __name__ | oh, and of course `map second` |
| 18:10 | __name__ | note to self: do not code in an unfamiliar language when not well-rested, and if you do, do not annoy nice irc people. |
| 18:12 | amalloy | __name__: transitioning from common-lisp, it looks like? or maybe scheme? |
| 18:12 | __name__ | amalloy: python, actually :-) |
| 18:12 | brehaut | that would explain your handle :) |
| 18:13 | __name__ | amalloy: what made you think i am a schemer or clisper? |
| 18:13 | amalloy | __name__: interesting. i know python has [a b c] list literals, so i'm a bit puzzled as to why you're not using clojure's |
| 18:13 | amalloy | (list blah blah) and '(blah blah) are easily replaced by [blah blah] |
| 18:13 | __name__ | amalloy: because they are vectors? |
| 18:13 | __name__ | amalloy: if i am not completely mistaken it's not the same thing |
| 18:14 | amalloy | __name__: vectors are almost always better for handling data |
| 18:14 | __name__ | But in this case a vector is better. |
| 18:14 | amalloy | i mean, it doesn't matter for tiny-little lists |
| 18:14 | __name__ | because i am not doing any stuff that you would use linked lists for. |
| 18:14 | amalloy | but the syntax is more convenient for vectors, and it rarely matters which you use if you're not adding |
| 18:14 | __name__ | Yes, that's what I meant. |
| 18:15 | amalloy | __name__: plus, vectors support fast adding to the end, while lists support fast adding to the front |
| 18:15 | amalloy | so even if you're using it as a linked list you have to choose |
| 18:15 | amalloy | chouser: now's your chance! sell us all on finger trees! |
| 18:16 | __name__ | amalloy: http://paste.pocoo.org/show/327511/ is this better? |
| 18:16 | amalloy | yep |
| 18:17 | __name__ | i'm amazed i've come up with this :) |
| 18:17 | amalloy | depending on how comfortable you are with destructuring, you can make it still-more readable |
| 18:17 | amalloy | &(fn fib [[a b]] [(+ a b) b]) |
| 18:17 | sexpbot | ⟹ #<sandbox11874$eval14090$fib__14091 sandbox11874$eval14090$fib__14091@b94d90> |
| 18:18 | __name__ | amalloy: Thank you. |
| 18:18 | __name__ | amalloy: I just meant to try that myself :) |
| 18:19 | __name__ | i guess defn fibs [] (map second (iterate (fn [[x y]] [(+ x y) x]) [1 1]))) is too much of the good |
| 18:19 | amalloy | __name__: http://rosettacode.org/wiki/Fibonacci_sequence#Clojure |
| 18:19 | amalloy | is in fact what you've just done |
| 18:20 | __name__ | Yep |
| 18:20 | amalloy | (i added the commented version a few months ago) |
| 18:20 | brehaut | ,(let [f (lazy-cat [1 1] (map + ff (rest ff)))] (take 5 ff)) |
| 18:20 | clojurebot | java.lang.Exception: Unable to resolve symbol: ff in this context |
| 18:20 | brehaut | i am a muppet |
| 18:21 | brehaut | ,(let [f (lazy-cat [1 1] (map + f (rest f)))] (take 5 f)) |
| 18:21 | clojurebot | java.lang.Exception: Unable to resolve symbol: f in this context |
| 18:21 | amalloy | anyway nice work __name__. it's impressive to come up with the strategy of using iterate to store temporary data |
| 18:21 | brehaut | unequivocally so apparently |
| 18:21 | __name__ | amalloy: i started with recursion, and saw that it's no use for tail calls … |
| 18:22 | arohner | according to visualvm, it appears my app is spending a significant chunk of time in PersistentHashMap$HashCollisionNode.findIndex(). Are there any clever strategies for reducing the number of hash collisions in my data? |
| 18:22 | arohner | (I assume that hitting a different node type in PHashMap will improve my performance) |
| 18:23 | brehaut | __name__ the nerdy name for the solution you came up with is a hylomorphism |
| 18:24 | brehaut | (roughly) |
| 18:25 | brehaut | ie, converting a recursive algorithm into a stream generator and a stream consumer |
| 18:26 | __name__ | brehaut: thank you for your elaboration. i appreciate it. |
| 18:28 | brehaut | __name__ no problem |
| 18:31 | brehaut | __name__: also, (nth n ...) is (first (drop n...)) |
| 18:32 | brehaut | although i think i have the args backwards |
| 18:32 | __name__ | I ended up with (defn fibs [] (map second (iterate (fn [[x y]] [(+ x y) x]) [1 0]))) by now |
| 18:32 | __name__ | i had forgotten the 0 |
| 18:32 | __name__ | Am I right in believing that at any point in time there's only x and y in memory? |
| 18:33 | brehaut | yup |
| 18:33 | __name__ | yay |
| 18:34 | __name__ | thanks for putting up with my ignorance :) |
| 18:35 | brehaut | nah, ignorance is when you type stupid crap into clojure bot rather than a repl |
| 18:35 | brehaut | and then make the same mistake again |
| 18:35 | brehaut | __name__ how familiar are you with generators, generator expressions and itertools in python? |
| 18:35 | __name__ | brehaut: very |
| 18:36 | amalloy | er, no. only x and y are *required* to be in memory. the gc won't clean them up till it needs to |
| 18:36 | __name__ | amalloy: Oh; Sorry for being vague, I meant that. |
| 18:37 | amalloy | __name__: preface: i don't think the following is actually better than your version |
| 18:38 | amalloy | oh actually i take it back, this version is awesome |
| 18:38 | amalloy | you could implement (fn [[x y]] [(+ x y) x]) as (juxt (partial apply +) first)) |
| 18:39 | __name__ | amalloy: would you mind explaining, i looked at the doc of juxt (and know what partial does), but do not seem to grasp it. |
| 18:40 | brehaut | ,((juxt inc dec) 1) |
| 18:40 | clojurebot | [2 0] |
| 18:40 | amalloy | well, ideally it would be just (juxt + first), which makes more sense |
| 18:41 | amalloy | but because [x y] is a list, you need to ##(apply + [1 2]) |
| 18:41 | sexpbot | ⟹ 3 |
| 18:41 | __name__ | amalloy: are you a haskeller? |
| 18:41 | amalloy | (partial apply +) wraps that up in a new function that will add the list it's passed |
| 18:41 | amalloy | __name__: no, but i keep hearing i should be |
| 18:41 | amalloy | i think point-free is nice |
| 18:41 | brehaut | the haskell solution ported to clojure is |
| 18:42 | brehaut | (def fibs (lazy-cat [1 1] (map + fibs (rest fibs)))) |
| 18:43 | brehaut | turns out i was right previously but i (obviously) need a var in the road, to make it self recursive |
| 18:43 | amalloy | &with-local-vars |
| 18:43 | sexpbot | java.lang.Exception: Can't take value of a macro: #'clojure.core/with-local-vars |
| 18:43 | __name__ | amalloy: I understand |
| 18:44 | brehaut | ,(with-local-vars [fib (lazy-cat [1 1] (map + fibs (rest fibs)))] (take 10 fibs)) |
| 18:44 | clojurebot | java.lang.Exception: Unable to resolve symbol: fibs in this context |
| 18:45 | amalloy | brehaut: the var doesn't exist until its init expr is done |
| 18:46 | brehaut | also i typod |
| 18:46 | amalloy | &(with-local-vars [fibs nil] (var-set fibs (lazy-cat [1 1] (map + (var-get) fibs (rest (var-get fibs))))) (take 10 (var-get fibs))) |
| 18:46 | sexpbot | java.lang.IllegalArgumentException: Wrong number of args (0) passed to: core$var-get |
| 18:46 | amalloy | blah whatever |
| 18:47 | amalloy | &(with-local-vars [fibs nil] (var-set fibs (lazy-cat [1 1] (map + (var-get fibs) (rest (var-get fibs))))) (take 10 (var-get fibs))) |
| 18:47 | sexpbot | java.lang.IllegalStateException: Var null/null is unbound. |
| 18:47 | brehaut | amalloy: im glad its not just me :/ |
| 18:47 | arohner | more info on my hash collision problem. I have a map w/ 33k keys, but 6.7k distinct hash codes (according to (->> my-map keys (map #(.hashCode %)) distinct count |
| 18:47 | amalloy | &(with-local-vars [fibs nil] (var-set fibs (lazy-cat [1 1] (map + (var-get fibs) (rest (var-get fibs))))) (doall (take 10 (var-get fibs)))) |
| 18:47 | sexpbot | ⟹ (1 1 2 3 5 8 13 21 34 55) |
| 18:47 | __name__ | yay |
| 18:47 | amalloy | brehaut: solved! |
| 18:48 | amalloy | vile though it is |
| 18:48 | brehaut | (inc amalloy ) |
| 18:48 | sexpbot | ⟹ 2 |
| 18:48 | brehaut | woo :-) |
| 18:48 | brehaut | yeah remarkably so |
| 18:48 | brehaut | the basic concept is so tidy too |
| 18:49 | Leonidas | __name__: I'm not haskeller either and partial and thread-last are seriously nice ;) |
| 18:49 | amalloy | partial is...really handy, and way too verbose |
| 18:49 | __name__ | Leonidas: oh hey |
| 18:49 | brehaut | amalloy: thats why we have % ;) |
| 18:49 | brehaut | err # |
| 18:50 | Leonidas | __name__: hi :) |
| 18:50 | Leonidas | __name__: I'm currently in clojure-hack mode :D |
| 18:50 | amalloy | one day i'll cross over to the dark side and (def ##(char (rand-int 0xffff)) partial) |
| 18:50 | sexpbot | ⟹ \練 |
| 18:50 | __name__ | Leonidas: i'm in ‘i should go to sleep’ mode. |
| 18:51 | brehaut | amalloy: i apparently dont have that glyph |
| 18:51 | amalloy | brehaut: i don't either, it's too high in the code charts |
| 18:51 | Leonidas | __name__: same here. and "i should learn for exams" mode. this is the one time in the semester when I start to hack productively :) |
| 18:51 | __name__ | Leonidas: :) |
| 18:51 | amalloy | &(char (rand-int 0x8fff)) |
| 18:51 | sexpbot | ⟹ \佗 |
| 18:51 | brehaut | hah awesome |
| 18:52 | amalloy | although FAB0 is the best random character ever |
| 18:52 | amalloy | it's FAB0LOUS! |
| 18:52 | __name__ | &(char 0xdead) |
| 18:52 | sexpbot | ⟹ \? |
| 18:53 | Leonidas | ,(char 0xFAB0) |
| 18:53 | clojurebot | \練 |
| 18:53 | amalloy | that's how haskellers roll, isn't it? define single-unicode-character names for the useful functions? |
| 18:53 | Leonidas | which of these bots is actually to prefer? |
| 18:54 | brehaut | nah, its more like a like a crazy pipe of 2 to 5 punctiation characters as a binary op |
| 18:54 | amalloy | Leonidas: sexpbot imo, but i'm biased as i've been helping write/maintain him for months now |
| 18:55 | Leonidas | amalloy: :) |
| 18:55 | brehaut | amalloy: your homework is to explain the difference between (.) (>>>) and (>=>) |
| 18:57 | brehaut | valid answers do include 'not much' |
| 18:58 | arohner | &(.hashCode {62 0, 75 1720, 73 1}) |
| 18:58 | sexpbot | ⟹ 1913 |
| 18:58 | arohner | &(.hashCode {75 1717, 62 1, 61 1}) |
| 18:58 | sexpbot | ⟹ 1913 |
| 18:59 | amalloy | arohner: (hash x) is the same as (.hashCode x) |
| 18:59 | arohner | amalloy: thanks, but not my issue ATM |
| 18:59 | amalloy | *laugh* i know |
| 18:59 | arohner | &(hash {75 1099}) |
| 18:59 | sexpbot | ⟹ 1024 |
| 19:00 | arohner | &(hash { 69 24 61 1 75 812}) |
| 19:00 | sexpbot | ⟹ 1024 |
| 19:00 | arohner | I can do that 28k more times |
| 19:00 | arohner | out of 33k maps |
| 19:01 | amalloy | have you looked at the source of map.hash? |
| 19:02 | arohner | yeah. it doesn't look very random (though I could have told you that empirically ) |
| 19:02 | amalloy | it looks like it's pretty bad, yeah |
| 19:03 | amalloy | arohner: you could probably make it sufficiently good just by adding hash *= 13 before the += |
| 19:05 | amalloy | perhaps that just slows things down too much for rich |
| 19:08 | arohner | amalloy: if you think computing hashes is expensive, you should try dealing with hash-collisions :-) |
| 19:08 | arohner | amalloy: I'll try out a build with *= 13, and we'll see what happens |
| 19:08 | amalloy | arohner: that's only an issue if maps containing elements with weak hash functions are stored inside of another mapo |
| 19:09 | amalloy | so i doubt it comes up much in practice |
| 19:09 | arohner | &(hash 1238907) |
| 19:09 | sexpbot | ⟹ 1238907 |
| 19:10 | arohner | my data is not distributed randomly. The keys are db ids, and the values are ids of enums that users have selected |
| 19:11 | amalloy | arohner: yes, i understand why it comes up for you |
| 19:12 | amalloy | my point is that it may not come up often enough in general to merit slowing down map hashing; the hit there might be worse than the occasional reduction in collisions |
| 19:16 | __name__ | thanks, especially amalloy and brehaut; good luck with the exam, Leonidas. good night all. |
| 19:17 | Leonidas | __name__: goodnight. |
| 19:22 | symuyn | Is a vector's hash code calculated when the vector is created, or is it lazily calculated when hash or = is called? |
| 19:24 | amalloy | symuyn: on hash |
| 19:24 | symuyn | When hash is called? |
| 19:24 | amalloy | yes |
| 19:24 | symuyn | Good, that makes sense |
| 19:24 | symuyn | By the way, does vector's isEquals use hash codes? |
| 19:24 | symuyn | isEqual, I mean |
| 19:25 | amalloy | symuyn: bizarrely enough, the answer is "sometimes" |
| 19:25 | symuyn | Hmm |
| 19:26 | amalloy | for List and PersistentVector, it checks their hash codes |
| 19:26 | amalloy | for Sequential objects it goes straight to comparing |
| 19:26 | symuyn | Aren't List and PersistentVector inside Sequential? |
| 19:26 | symuyn | Oh wait, they can override |
| 19:27 | symuyn | But what doesn't override Sequential.isEqual? |
| 19:27 | amalloy | &(some #{clojure.lang.Sequential} (supers (class []))) |
| 19:27 | sexpbot | ⟹ clojure.lang.Sequential |
| 19:27 | symuyn | Yeah |
| 19:27 | symuyn | Oh well. Clojure does a good job of hiding this stuff anyway |
| 19:28 | amalloy | symuyn: the persistent data structures have a doEquiv and doEquals |
| 19:28 | symuyn | I forgot: are all Sequential objects persistent? |
| 19:28 | amalloy | equiv is what's called by (= foo bar), and it never checks hash codes b/c it needs [1 2] to equal (1 2) |
| 19:29 | symuyn | I thought that [1 2] and (1 2) had equal hash codes; I was told that yesterday |
| 19:29 | symuyn | @(= (hash [1 2]) (hash '(1 2))) |
| 19:29 | amalloy | they probably do, but that's not really a guarantee |
| 19:30 | symuyn | Ugh |
| 19:30 | symuyn | &(= (hash [1 2]) (hash '(1 2))) |
| 19:30 | sexpbot | ⟹ true |
| 19:30 | amalloy | &(map hash ["" 1] #{"" 1}) |
| 19:30 | sexpbot | java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$hash |
| 19:30 | mefesto | anyone use clojure-rabbitmq in here? |
| 19:30 | amalloy | &(map hash [["" 1] #{"" 1}]) |
| 19:30 | sexpbot | ⟹ (962 1) |
| 19:31 | amalloy | &(apply = [["" 1] #{"" 1}]) |
| 19:31 | sexpbot | ⟹ false |
| 19:31 | amalloy | well, that's good at least |
| 19:31 | amalloy | &(apply = [[1 ""] #{"" 1}]) |
| 19:31 | sexpbot | ⟹ false |
| 19:31 | amalloy | anyway i think it's a complicated issue |
| 19:31 | symuyn | Wait, really? |
| 19:31 | symuyn | &(= #{} []) |
| 19:31 | sexpbot | ⟹ false |
| 19:31 | symuyn | Huh. Sets and vectors aren't equal. |
| 19:32 | symuyn | That might bite me someday |
| 19:32 | symuyn | I wonder what the rationale is |
| 19:32 | brehaut | symuyn: that makes sense though right? vectors have additional information encoded in them than sets |
| 19:32 | symuyn | Ah, right. |
| 19:33 | symuyn | I need to think of collection equality as sequence equality |
| 19:33 | symuyn | Wait, that might not work for sets to sets |
| 19:33 | brehaut | ,[(hash (lazy-seq [1 2 3])), (hash (lazy-seq [3 2 1]))] |
| 19:33 | clojurebot | [30817 32737] |
| 19:34 | brehaut | i dont know why i made those lazy |
| 19:34 | amalloy | brehaut: an extra sprinkling of awesome |
| 19:34 | brehaut | amalloy: i like how you think |
| 19:36 | brehaut | symuyn: i think realistically you need to have much crisper notions of equality |
| 19:38 | symuyn | brehaut: I think that sequentials vs. non-sequentials are fine. "All sequentials are equal if blah, blah, but are never equal to non-sequentials. Non-sequentials are equal if they contain the same elements, but are never equal to sequentials." |
| 19:38 | brehaut | symuyn: what about a sorted set compared to a vector? |
| 19:38 | symuyn | &(= (sorted-set 1 2 3) [1 2 3]) |
| 19:38 | sexpbot | ⟹ false |
| 19:39 | symuyn | Yeah, okay |
| 19:39 | brehaut | yeah, and even worse |
| 19:39 | symuyn | Well, so much for consistency |
| 19:39 | brehaut | is (sorted-set 1 2 3) different to [1 2 2 3]? |
| 19:40 | symuyn | &(= (sorted-set 1 2 3) [1 2 2 3]) |
| 19:40 | sexpbot | ⟹ false |
| 19:41 | brehaut | really, you need to convert one side of your test into the other type |
| 19:41 | brehaut | ,(= (sorted-set 1 2 3) (apply sorted-set [1 2 2 3])) |
| 19:41 | clojurebot | true |
| 19:42 | symuyn | Ugh, apply is so slow; it's been the bottleneck of my programs in the past |
| 19:42 | brehaut | ,(= (vec (sorted-set 1 2 3)) [1 2 2 3]) |
| 19:42 | clojurebot | false |
| 19:42 | symuyn | Thank goodness for vec |
| 19:43 | symuyn | Do you know if there's a way to turn off pre/post-conditions, like tests? |
| 19:43 | brehaut | symuyn: the point being though, depending on how you are viewing _the same data_ equivalence can change dramatically |
| 19:43 | symuyn | Yeah |
| 19:43 | brehaut | (same excluding collection information) |
| 19:43 | amalloy | &(time (apply + (range 1e5))) |
| 19:43 | sexpbot | ⟹ "Elapsed time: 26.930893 msecs" 4999950000 |
| 19:44 | amalloy | symuyn: apply really isn't slow, i don't see what problem you're experiencing |
| 19:44 | amalloy | &(time (reduce + (range 1e5))) |
| 19:44 | sexpbot | ⟹ "Elapsed time: 30.868435 msecs" 4999950000 |
| 19:44 | brehaut | amalloy: i imagine applying a collection constructor to a large collection is going to be a slow operation ;) |
| 19:44 | symuyn | amalloy: It happened twice a year ago. Perhaps I'm wrong, but I'm pretty confident |
| 19:45 | amalloy | brehaut: sure, but not any slower than (doall (map identity coll)) |
| 19:45 | brehaut | amalloy: oh for sure, its not the result of apply that its slow |
| 19:47 | amalloy | symuyn: you found that (foo x y z) was substantially faster than (apply foo [x y z])? i guess i could see that, if foo had a lot of different arities defined |
| 19:47 | symuyn | Why would the number of arities matter? |
| 19:49 | brehaut | symuyn: a function call can choose the implementation at compile time, an apply call has to determine the implementation at runtime |
| 19:50 | symuyn | Yes, but does the search time depend on the number of arities? Maybe it's constant to the number. But the again, I've no idea. |
| 19:52 | brehaut | symuyn: i cant intuit how it could be constant time |
| 19:53 | brehaut | $source apply |
| 19:53 | sexpbot | apply is http://is.gd/AklWob |
| 19:53 | brehaut | i must confess to that not clearing things up for me |
| 19:54 | symuyn | The source there doesn't show the implementation of arity selection. |
| 19:54 | symuyn | It doesn't really matter that much anyway |
| 19:54 | symuyn | I'd think that we'd have to look in clojure.lang.IFn (or .Fn?) but I don't like looking in Clojure's guts |
| 19:55 | brehaut | https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/AFn.java#L154 |
| 19:55 | symuyn | Ah, now that's interesting |
| 19:55 | hiredman | ,((fn [& x] (first x)) (iterate inc 0)) |
| 19:55 | clojurebot | (0 1 2 3 4 5 6 7 8 9 ...) |
| 19:55 | hiredman | erm |
| 19:55 | hiredman | ,(apply (fn [& x] (first x)) (iterate inc 0)) |
| 19:55 | clojurebot | 0 |
| 19:55 | symuyn | Now, doesn't collection counting have near-constant-time? |
| 19:55 | hiredman | apply doesn't count |
| 19:56 | symuyn | Wait, no |
| 19:56 | hiredman | ^- apply to an infinite seq |
| 19:56 | brehaut | apply does magic |
| 19:56 | symuyn | The arglist is an ISeq |
| 19:56 | symuyn | Sequence counting is linear |
| 19:57 | symuyn | hiredman: That's interesting |
| 19:57 | brehaut | https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/RT.java#L1184 |
| 19:57 | symuyn | That kind of boggles my mind, actually |
| 19:57 | symuyn | Yes, and there we have it |
| 20:01 | brehaut | also im presuming that Util.ret1 at https://github.com/clojure/clojure/blob/1.2.x/src/jvm/clojure/lang/AFn.java#L151 is used to let java release the seq? |
| 20:03 | hiredman | yes, java doesn't have a way of clearing the jvms method frame while keeping a reference on the method's stack |
| 20:03 | brehaut | hiredman: cheers |
| 20:22 | brehaut | symuyn: relevant to the discussion http://groups.google.com/group/clojure-dev/browse_thread/thread/c58ec42d78209ee0 |
| 20:24 | symuyn | brehaut: Thanks; that's very interesting |
| 20:24 | symuyn | Oops, wrong punctuation |
| 20:26 | brehaut | symuyn: and by experimention i gather than sorted-sets test equality as sets by default, and seqs if you wrap them seq; YMMV of course, ididnt read the code |
| 20:26 | symuyn | I think you're right in that I should just convert to the same type before comparing |
| 23:09 | pdk | (doc doseq) |
| 23:09 | clojurebot | "([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil." |
| 23:09 | pdk | (doc while) |
| 23:09 | clojurebot | "([test & body]); Repeatedly executes body while test expression is true. Presumes some side-effect will cause test to become false/nil. Returns nil" |
| 23:16 | amalloy | that's a weird docstring for while |
| 23:16 | brehaut | is it weird that i didnt even know there was a while? |
| 23:16 | amalloy | "Presumes some side-effect will cause test to become false/nil" suggests that it is an error to write (while true (...)), because you are violating while's assumption/precondition |
| 23:17 | amalloy | brehaut: yeah, i've never used it either |
| 23:17 | pdk | it's an infinite loop at any rate |
| 23:17 | amalloy | pdk: clearly. but there's nothing wrong with writing an infinite loop if that's what you want |
| 23:18 | technomancy | be honest, who reads the docstring for while? |
| 23:18 | amalloy | technomancy: pdk, it seems |
| 23:18 | amalloy | and now me, to my chagrin |
| 23:19 | brehaut | is there an sexp-grep for clojure? |
| 23:20 | brehaut | (ie, for grepping clojure source) |
| 23:20 | amalloy | brehaut: how would that be different from plain old grep? |
| 23:21 | brehaut | amalloy: knows about trees rather than lines |
| 23:21 | brehaut | grep is probably the wrong term |
| 23:21 | brehaut | xpath is a better one |
| 23:21 | brehaut | sexpath |
| 23:21 | brehaut | probably didnt need to go there |
| 23:21 | amalloy | like...sgrep (if (magic))? it's not clear to me how i'd specify useful sexps for this |
| 23:22 | technomancy | sounds like you want a zipper |
| 23:22 | brehaut | yeah i probably do |