2012-02-01
| 00:53 | aphyr | Out of curiosity, how expensive is deref in clojure? |
| 00:53 | aphyr | Safe to call, say, 250K/sec? |
| 00:54 | G0SUB | aphyr, vars are getting deref-ed all the time. |
| 00:54 | G0SUB | aphyr, in 1.2 all vars are dynamic, for example. so I guess it should be pretty fast. |
| 00:55 | ibdknox | it depends entirely on what you're derefing |
| 00:56 | aphyr | ibdknox: (ref (NonBlockingHashMap.)) in this case. |
| 00:57 | aphyr | I've been using it to allow an aleph server to change its underlying configuration after being started |
| 00:57 | aphyr | But now I'm wondering if I should build some kind of reload functionality instead |
| 00:57 | ibdknox | ,(time (loop [i 0] (when (< i 250000) @x (recur (inc i))))) |
| 00:57 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0)> |
| 00:57 | ibdknox | ,(let [x (atom 1)] (time (loop [i 0] (when (< i 250000) @x (recur (inc i)))))) |
| 00:57 | clojurebot | "Elapsed time: 75.945 msecs" |
| 00:57 | ibdknox | ,(let [x (ref 1)] (time (loop [i 0] (when (< i 250000) @x (recur (inc i)))))) |
| 00:57 | clojurebot | "Elapsed time: 100.592 msecs" |
| 00:58 | ibdknox | it appears that will not be an issue |
| 00:58 | ibdknox | :) |
| 00:58 | G0SUB | ibdknox, :-) |
| 00:58 | aphyr | Haha, apparently not. :) |
| 00:59 | aphyr | ,(time (loop [i 0] (when (< i 250000) (recur (inc i))))) |
| 00:59 | clojurebot | "Elapsed time: 21.745 msecs" |
| 00:59 | aphyr | ,(time (loop [i 0] (when (< i 250000) (recur (inc i))))) |
| 00:59 | clojurebot | "Elapsed time: 20.966 msecs" |
| 00:59 | aphyr | So ~80ms for the var deref |
| 01:00 | aphyr | out of a 1-second timeslice, 8%... hmm. Might be worth investigating actually. |
| 02:33 | pyr | hi |
| 02:33 | G0SUB | pyr |
| 02:34 | pyr | does read-string "intern" strings on the jvm, thus making use of permgen space |
| 02:34 | G0SUB | pyr, literal strings are interned. |
| 02:35 | pyr | as well as keywords |
| 02:35 | pyr | i have a permanent process that reads of a queue |
| 02:36 | pyr | and does read-string on the input |
| 02:36 | pyr | i see constant permgen space growth |
| 02:36 | pyr | which i don't understand |
| 02:42 | G0SUB | pyr, -XX:MaxPermSize=128m -XX:PermSize=128m might be the only option. |
| 02:43 | aphyr | Wait, so any string created with read-string is on permgen? |
| 02:43 | raek | keywords are always interned (by Clojure), but strings are not always |
| 02:43 | G0SUB | pyr, apparently interned strings are GCs as expected - http://stackoverflow.com/questions/1091045/is-it-good-practice-to-use-java-lang-string-intern/2012661#2012661 |
| 02:44 | raek | string literals in function bodies tend to be identical |
| 02:45 | raek | anyway, the Clojure reader does not call .intern on the strings, IIRC |
| 02:45 | raek | ,(identical? (read-string "\"foo\"") (read-string "\"foo\"")) |
| 02:45 | clojurebot | false |
| 02:46 | raek | ,(identical? (name (read-string "foo")) (name (read-string "foo"))) |
| 02:46 | clojurebot | true |
| 02:47 | raek | the names of keywords and symbols are, though |
| 02:47 | aphyr | ,(.get (System/getenv) "PWD") |
| 02:47 | clojurebot | #<AccessControlException java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.*)> |
| 02:47 | aphyr | ha |
| 02:48 | aphyr | I actually could use some sandbox code right now... good to know |
| 02:48 | pyr | raek: yup, but i clearly don't have enough keyword read in |
| 02:48 | pyr | raek: to justify the growth i'm seeing |
| 02:58 | Jachy | Is there a way I can do (def (symbol ...) val) outside a macro? |
| 03:15 | raek | Jachy: not with 'def', no. |
| 03:16 | raek | there is intern though |
| 03:18 | Jachy | raek: That looks useful, thanks. |
| 04:04 | clj_newb | is it possible to ahve two separate instances of clojure share the same jvm? |
| 04:04 | clj_newb | for example, I have a simle digital led clock writen in clojure -- I think ti's a bit overkill to have it have its own jvm instance |
| 04:05 | simonj | Hi all. Confused as to the non-laziness of the returned Seq from this function. https://gist.github.com/1716056 |
| 04:22 | pyr | alright, so given a huge list of strings containing pr-str'd maps |
| 04:22 | pyr | if i do: (let [m (doall (map read-string huge-list)] (Thread/sleep 10000) (println "saw: " (count m))) |
| 04:23 | pyr | i see a permgen increase which doesn't get freed up |
| 04:23 | pyr | using CMSClassUnloadingEnabled and UseConcMarkSweepGC |
| 04:23 | pyr | doesn't change a thing |
| 05:33 | yawNO | i often see in clojure libs (defn ^ |
| 05:33 | yawNO | what is that? |
| 05:33 | yawNO | *def ^ |
| 05:35 | ivan | yawNO: are you asking about metadata? |
| 05:35 | yawNO | i dont know asd |
| 05:35 | yawNO | i've been clojuring for like |
| 05:35 | yawNO | 3days? |
| 05:35 | yawNO | so im really kinda noob right now :P |
| 05:36 | ivan | ^{:a 1} (fn) attaches {:a 1} as metadata to (fn) |
| 05:36 | ivan | see also with-meta and meta |
| 05:36 | yawNO | okay got it |
| 05:36 | yawNO | thx :D |
| 05:37 | yawNO | yeah i know with-meta and meta :D |
| 05:37 | Martijn2 | I just installed lein and made anew project based on clojure 1.2.0 and clojure-contrib 1.2.0 When I do (require 'clojure.contrib.str-utils) I get this error: |
| 05:37 | Martijn2 | java.lang.NoClassDefFoundError: clojure/lang/RT (NO_SOURCE_FILE:0) |
| 05:37 | Martijn2 | what is going on? |
| 05:39 | Martijn2 | sorry, problem solved |
| 06:40 | cemerick | totally OT, but: does anyone else find it totally bizarre that the 13" Macbook Pro has a lower screen resolution than the 13" Macbook Air? |
| 06:42 | ordnungswidrig | cemerick: yes, me. now as I know the fact. |
| 06:46 | Borkdude | I installed rlwrap on my mac. how is "lein repl" supposed to use it for completion? |
| 06:48 | lucian | Borkdude: rlwrap lein repl |
| 06:48 | lucian | it literally wraps your commands |
| 06:48 | Borkdude | lucian: how does it do autocompletion then? |
| 06:48 | jondot | my first hit at useful clojure code - a ring middleware: https://github.com/jondot/ring-ping/blob/master/src/ring/middleware/ping.clj ==> anyone care to take a look and point some aweful newbie pitfalls to me? |
| 06:48 | lucian | Borkdude: oh, completion? sorry |
| 06:48 | lucian | Borkdude: for that you'd need some machinery in lein i think |
| 06:48 | cemerick | Borkdude: I can't see how rlwrap would help with completion. |
| 06:49 | lucian | cemerick: it can, actually. there was a small hack i saw for the regular clj |
| 06:49 | cemerick | command history and editing, yes. |
| 06:49 | lucian | cemerick: rlwrap can search a file of completions when you press tab |
| 06:49 | Borkdude | cemerick: command history also worked without rlwrap on my mac |
| 06:49 | lucian | Borkdude: you could generate such a file with (find-doc) or something |
| 06:49 | cemerick | lucian: oh; that's not really completion tho. :-) |
| 06:50 | Borkdude | not very intelligent completion anyway ;) |
| 06:50 | lucian | https://github.com/technomancy/leiningen/pull/381 |
| 06:50 | lucian | it's terrible, really |
| 06:50 | lucian | don't bother |
| 06:50 | cemerick | Borkdude: lein will be getting some baked-in completion shortly. |
| 06:51 | Borkdude | I have some students who are trying out clojure, they used a console for it, so I thought it could be handy for them |
| 06:52 | cemerick | Borkdude: this is likely to be the new frontend for lein's repl: https://github.com/trptcolin/reply/ |
| 06:56 | lucian | cemerick: that reply thing is awesome |
| 06:56 | lucian | it has precisely the features i want, and nothing else |
| 06:57 | Borkdude_ | cemerick: totally cool, autocompletion works |
| 06:58 | cemerick | lucian: you want more, you just don't know it yet ;-) |
| 06:58 | lucian | cemerick: heh |
| 07:06 | cemerick | G0SUB: you have a MBA, right? |
| 07:18 | G0SUB | cemerick, lol! |
| 07:18 | G0SUB | cemerick, not at all. I have a BS in CS, that's all. |
| 07:18 | cemerick | Macbook Air :-P |
| 07:18 | G0SUB | cemerick, haha |
| 07:18 | G0SUB | cemerick, yeah, 11" MBA :-) |
| 07:19 | G0SUB | cemerick, the same as cgrand |
| 07:19 | cemerick | G0SUB: I take it the SSD makes up for anything the CPU is lacking, then? |
| 07:19 | Fossi | lol |
| 07:19 | Fossi | best ever |
| 07:19 | Fossi | you should put that on your business card XD |
| 07:20 | G0SUB | Fossi, ;-) |
| 07:20 | G0SUB | cemerick, I agree. and the CPU isn't that bad either. |
| 07:31 | G0SUB | cemerick, cgrand, ninjudd & I have the same MBA. |
| 08:01 | shales | Hi, does anyone know what version of mongodb 4clojure requires? |
| 08:06 | romain_p | Hi everyone, what is the best way of turning {:a #{:foo :bar}, :b #{:baz}} into [[:a :foo] [:a :bar] [:b :baz]] ? |
| 08:07 | lucian | maybe something like (map vec your-hash) |
| 08:08 | romain_p | ,(map vec {:a #{:foo :bar}, :b #{:baz}} |
| 08:08 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading> |
| 08:08 | romain_p | ) |
| 08:08 | romain_p | ,(map vec {:a #{:foo :bar}, :b #{:baz}}) |
| 08:08 | clojurebot | ([:a #{:foo :bar}] [:b #{:baz}]) |
| 08:08 | romain_p | hmmm no |
| 08:09 | lucian | close, just vec again on the set |
| 08:13 | lucian | ,(map (fn [item] [(first item) (vec (second item))]) {:a #{:foo :bar}, :b #{:baz}}) |
| 08:13 | clojurebot | ([:a [:foo :bar]] [:b [:baz]]) |
| 08:14 | lucian | nvm, i must've misread |
| 08:23 | romain_p | lucian: thanks! |
| 08:24 | romain_p | oops no |
| 08:24 | lucian | romain_p: it's not what you asked |
| 08:24 | shales | ,(mapcat (fn [[k v]] (map vector (repeat k) v)) {:a #{:foo :bar}, :b #{:baz}}) |
| 08:24 | clojurebot | ([:a :foo] [:a :bar] [:b :baz]) |
| 08:24 | shales | that work? |
| 08:24 | romain_p | shales: yup that does it, cheers |
| 08:25 | babilen | How can I influence the sort order of records? I essentially want them sorted by field1 first, then field2, … What would be a good approach? |
| 08:32 | llasram | babilen: Have the records implement Comparable? |
| 08:32 | babilen | llasram: Not yet - I figured that something like this would be the best approach, but wanted to ask first. |
| 08:35 | llasram | Ok. I'm pretty sure that's the best/only way to do it |
| 08:36 | babilen | llasram: Can you, by chance, provide pointers to documentation on how to achieve this (easily)? |
| 08:40 | llasram | babilen: Just the normal way you implement interfaces for defrecords/types. Some general examples at: http://clojuredocs.org/clojure_core/clojure.core/defrecord |
| 08:40 | babilen | I am not sure how to achieve this, but figure that implementing a comparator (for e.g. sorted-set-by) is another option. (which is as far as my knowledge is concerned easier) |
| 08:42 | llasram | babilen: Here's a specific simple example: https://refheap.com/paste/527 |
| 08:43 | llasram | You can also just pass a comparator (just a function returning {-1,0,1} for any argument pair) whenever you need to sort |
| 08:43 | babilen | llasram: Thanks -- Is it important that I implement in a way that allows comparison between different types or is that checked earlier? |
| 08:44 | llasram | Normal rules apply: only if you care about inter-type sorting. |
| 08:44 | babilen | llasram: I don't (at least not right now) |
| 08:46 | llasram | Ah, and the `sort' default behavior just throws an exception anyway with different types intermixed. You'll definitely need to pass in a comparator if you ever do want anything sane to happen in those cases :-) |
| 08:50 | raek | babilen: one way is to implement Comparable, and one way is to implement Comparator. one thing that's convenient is that functions of two arguments implement Comparator |
| 08:50 | babilen | llasram: Ok, that makes sense and is good news. Thanks for your kind and great help. Have a nice day! |
| 08:52 | raek | ,(sort #(> (.length %1) (.length %2)) ["a" "aaa" "aa"]) |
| 08:52 | clojurebot | ("aaa" "aa" "a") |
| 08:52 | babilen | raek: Ok, great. Well -- I have collections of records and want them sorted by field1, field2 and don't really care about additional fields. (still need to be part of the comparison as sorted-set-by would, for example, remove all elements that differ only in additional fields) |
| 08:53 | raek | babilen: you can also use sort-by. it accepts a function that gives another value which is used for te comparisons |
| 08:54 | raek | ,(sort-by (juxt length last) [[1 2 3] [1 2] [0 0 10]]) |
| 08:54 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: length in this context, compiling:(NO_SOURCE_PATH:0)> |
| 08:54 | raek | ,(sort-by (juxt count last) [[1 2 3] [1 2] [0 0 10]]) |
| 08:54 | clojurebot | ([1 2] [1 2 3] [0 0 10]) |
| 08:54 | raek | vectors and sequences are compared element wise |
| 08:55 | babilen | yeah -- I will try to implement a compare-by-field([:field1 :field2]) → comparator -- that will take additional (i.e. other not listed fields) into account, but sorts by field1 first, then field2, then the rest in no specific order. (alphabetically maybe) |
| 08:55 | raek | you can use (juxt :field1 :field2) as the key-fn |
| 08:56 | babilen | raek: Indeed - I am just not sure how to deal with the other fields that might be present in the record (yet). |
| 08:56 | raek | the ones with the same :field1 and :field2 value will be sorted next to each other in some order |
| 09:00 | babilen | raek: Shouldn't be hard though (use (keys rec) to get keys, remove given ones, ...) -- Thanks for your comments as well. |
| 09:05 | Kototama | hi, is there a way in SLIME to have slime-repl-previous-matching-input behavior more like the one from term-send-reverse-search-history (like C-r in the console) ? |
| 09:24 | noidi | is it not possible to implement two protocols (defined in different namespaces) with the same method name? |
| 09:26 | noidi | I get "Duplicate method name&signature" when I try to implement foo/Foo with foo/get-xyzzy, and bar/Bar with bar/get-xyzzy in the same reified protocol implementation |
| 09:26 | noidi | luckily I'm just playing around with this, so it's not a real problem that I'm facing |
| 09:27 | noidi | this kind of makes namespaces useless when using protocols |
| 09:29 | gfredericks | noidi: I don't know the reasoning behind it, but I think each method that you implement gets added as an actual java method on the type, without the namespace, so I'm not sure how that could be resolved |
| 09:31 | noidi | yeah, some sort of a name mangling scheme would be needed |
| 09:32 | gfredericks | which would be gross for anybody who intended to actually use the methods |
| 09:33 | noidi | well, now you need to do the name mangling manually to avoid this problem |
| 09:34 | gfredericks | true; I am not equipped to argue about the design choices. |
| 09:34 | noidi | or to avoid causing problems for the people who have to implement your protocol, possibly along with other protocols also out of their control |
| 09:34 | gfredericks | but hode up |
| 09:34 | gfredericks | the exact same problem exists with java interfaces doesn't it? |
| 09:35 | noidi | probably. I'm not that familiar with Java. |
| 09:35 | gfredericks | yeah, now that I think about it I expect this is a very general problem |
| 09:35 | cemerick | noidi: you can implement two protocols with the same signature, etc. without a problem *unless you're doing so inline* |
| 09:36 | cemerick | use extend-type, extend-protocol, or extend to provide protocol impls. |
| 09:36 | gfredericks | cemerick: how does it map to method names? |
| 09:36 | noidi | cemerick, thanks, I was hoping that it could be possible via extending! |
| 09:36 | noidi | I'll give that a go |
| 09:37 | cemerick | gfredericks: extend* doesn't map to method names. |
| 09:37 | cemerick | That's why it works. :-) |
| 09:37 | gfredericks | Indeed! |
| 09:51 | noidi | cemerick, brilliant, that works! |
| 09:51 | cemerick | :-) |
| 09:52 | cemerick | noidi: inline implementations are really only needed for maximum perf and Java interop. |
| 09:55 | noidi | I hope that the times I'll have to implement two Java interfaces with colliding method names will be few and far between |
| 10:08 | noidi | now if only there was a way to specify contracts directly on the protocol instead of the contract block of each method implementation... |
| 10:09 | noidi | it seems that trammel doesn't do that (yet) |
| 10:19 | cmajor7 | is there a "mental rule" on where to use map/reduce/filter vs. list comprehensions? |
| 10:20 | gtrak | less/clearer code wins? |
| 10:21 | raek | cmajor7: whatever shows the intent of the code the best... :-) |
| 10:23 | cmajor7 | gtrak, raek: but from a "problem solution" side. besides constantly mentally substituting both approaches ( map/reduce/filter & list compr ), is there certain indicators? |
| 10:24 | cmajor7 | e.g. list comprehensions would probably make more sense when iterating over multiple seqs where each element in one seq needs to visit each element in the other… |
| 10:24 | TimMc | cmajor7: Sure. If you want to walk through a collection one at a time and use the values to hammer on some other value, 'reduce is your friend. |
| 10:25 | TimMc | especially if you are trying to maintain some invariant on that value |
| 10:25 | gtrak | reduce is aggregation |
| 10:25 | TimMc | reduce is folding |
| 10:25 | TimMc | You're folding values in, one at a time. |
| 10:26 | noidi | my own mental rule is that when I use map with a lambda, it probably reads better as a list comprehension |
| 10:26 | TimMc | list comprehensions are a Swiss Army knife |
| 10:26 | TimMc | gtrak: Challenge: Implement 'reduce using 'for. |
| 10:27 | gtrak | hmm :-) |
| 10:27 | TimMc | My gut says you can't. |
| 10:27 | gtrak | i can find a way |
| 10:29 | TimMc | cmajor7: Given a collection, 'map gives you 1-for-1 collection answer, 'filter gives you a subset, and 'reduce gives you a single value for the whole thing. |
| 10:30 | TimMc | cmajor7: So first, ask yourself which of those results is what you want! |
| 10:31 | cmajor7 | TimMc: thank you. interesting.. I do understand map vs reduce vs filter. I am on list comprehensions vs map/filter/reduce… is there a difference in performace? e.g. reduce only walks once over all the seqs given and grows the accumulator, where if multiple seqs are given to "for" e.g. for [s1 (range 1 10) s2 (range 1 10)], it will walk seq2 completely for each element in seq1… |
| 10:31 | noidi | with my rule: (map #(* 2 %) (filter #(> % 5) (range 10))) --> (for [x (rang 10) :when (> x 5)] (* 2 x)) |
| 10:32 | babilen | noidi++ |
| 10:32 | TimMc | cmajor7: I can't imagine the performance would be different enough to care about. |
| 10:34 | cmajor7 | TimMc: { btw, I also find that in several cases reduce gives you a subset => similar to a filter. the true difference between "reduce" and "filter" in my understanding, is that "reduce" would have an accumulator, which allows a _new_ seq, rather than just a subset of the existing seq that "filter" does } |
| 10:34 | TimMc | Yes, you can certainly implement filter and reverse and so forth using reduce. |
| 10:34 | TimMc | and map, for that matter |
| 10:35 | TimMc | &(reduce #(conj %1 (* 3 %2)) [] (range 10)) |
| 10:35 | lazybot | ⇒ [0 3 6 9 12 15 18 21 24 27] |
| 10:36 | TimMc | &(reduce #(cons %2 %1) () (range 10)) ; reverse |
| 10:36 | lazybot | ⇒ (9 8 7 6 5 4 3 2 1 0) |
| 10:38 | TimMc | gtrak: I think 'for can produce a collection with at minimum the number of elements that :when and :while let through. |
| 10:39 | TimMc | Oh, and it always produces a collection, so you *can't* do it without at least some post-processing. |
| 10:39 | gtrak | I think there's no reason for not being able to reduce with a for, but i can't make my code work at the moment, I'm rusty :-), my basic idea is for x in the range of the length, swap an accumulator atom |
| 10:39 | TimMc | Ugh, that's terrible! |
| 10:39 | gtrak | reduce isn't lazy either |
| 10:40 | TimMc | Yeah, that's the kicker, I think. |
| 10:41 | cmajor7 | seems that 'list comprehensions in fact is somewhat close to a noidi's idea of "map + filter" application to seq(s). :while is an interesting one.. would 'list compr actually stop a seq walk on the first "while false"? |
| 10:41 | TimMc | &(for [a [(atom 0)] x (range 6)] (swap! a (partial + x))) ;; reductions |
| 10:41 | lazybot | ⇒ (0 1 3 6 10 15) |
| 10:43 | TimMc | cmajor7: :while will stop the current iteration only, and only at that level. |
| 10:45 | shales | does anyone know what version of mongodb 4clojure requires? |
| 10:45 | cmajor7 | &(dorun (for [col "ABCD" :when (not= col \B) row (range 1 4) :while (< row 3)] (println (str col row)))) |
| 10:45 | lazybot | ⇒ A1 A2 C1 C2 D1 D2 nil |
| 10:45 | TimMc | &(for [l0 '[a b c], l1 '[1 2 3] :while (< l1 3), l2 '[d e f]] (str l0 l1 l2)) |
| 10:45 | lazybot | ⇒ ("a1d" "a1e" "a1f" "a2d" "a2e" "a2f" "b1d" "b1e" "b1f" "b2d" "b2e" "b2f" "c1d" "c1e" "c1f" "c2d" "c2e" "c2f") |
| 10:46 | cmajor7 | TimMc: so the iteration actually stopped when a row became 3? |
| 10:46 | TimMc | cmajor7: Correct. |
| 10:47 | cmajor7 | cool. so it is quite "controllable".. nice |
| 10:47 | TimMc | and :let makes it even better |
| 10:49 | noidi | just think of `for` as a fancy `map` :) |
| 10:50 | cmajor7 | I still feel I would need to right many more maps/reduces/filters & listcomps to get the true feeling on when the one is more applicable.. but appreciate all the thoughts.. very cool. |
| 10:51 | cmajor7 | noidi: 'map can't really iterate over multiple collection matching each element of one collection to all elements of another ( unless there is an internal map/reduce ). while 'listcomp can and does that. or am I missing something? |
| 10:51 | cmajor7 | *over multiple collections |
| 10:52 | noidi | it can't. you'll need something like (map (fn [x] (map f x)) xs) |
| 10:52 | TimMc | cmajor7: It can, the result is just a collection of collections. |
| 10:52 | gtrak | you can do it with map, but it'd be really awkward? |
| 10:52 | TimMc | mapcat takes care of that. |
| 10:53 | gfredericks | you could do X with just a bunch of lambdas also |
| 10:53 | TimMc | cmajor7: 'for is great for unrolling nested collections, by the way. |
| 10:53 | cmajor7 | doesn't mapcat just flatten the result of mapping? |
| 10:53 | TimMc | Yeah, but it does the mapping too. |
| 10:54 | cmajor7 | but not on nested collections.. |
| 10:54 | cmajor7 | e.g how would you do this |
| 10:54 | cmajor7 | &(dorun (for [col "ABCD" :when (not= col \B) row (range 1 4) :while (< row 3)] (println (str col row)))) |
| 10:54 | lazybot | ⇒ A1 A2 C1 C2 D1 D2 nil |
| 10:54 | cmajor7 | with a single map/mapcat? |
| 10:54 | TimMc | without the :when and :while, of course |
| 10:56 | TimMc | &(mapcat (fn [c] (map (fn [r] (str c r)) (range 1 3))) "ABC") |
| 10:56 | lazybot | ⇒ ("A1" "A2" "B1" "B2" "C1" "C2") |
| 10:56 | cmajor7 | right => 2 maps |
| 10:56 | TimMc | sure |
| 10:56 | TimMc | which is equivalent to a 2-level 'for |
| 10:57 | cmajor7 | yep.. so another mental rule would be.. "think about 2> maps? try 'it' with for" |
| 10:57 | cmajor7 | (thinking out loud) |
| 10:57 | TimMc | yeah, cartesian joins |
| 10:58 | cmajor7 | is there an appealing case to use 'for vs 'map on a single seq? |
| 10:59 | cmajor7 | ( I meant 'for vs. 'map/'filter/'reduce ) |
| 10:59 | gfredericks | cmajor7: I like map with named functions and for with inline functions |
| 10:59 | TimMc | Sure, when the lambda is of moderate complexity and depends on a bunch of local s |
| 10:59 | cmajor7 | besides the laziness of the result of course |
| 10:59 | TimMc | cmajor7: 'for is lazy |
| 11:01 | cmajor7 | TimMc: "when the lambda is of moderate complexity and depends on a bunch of local s" => this would be strictly a readability advantage, right? [not saying it is not enough of an advantage though] |
| 11:12 | TimMc | cmajor7: A lamba of moderate to high complexity should generally be extracted as a separate named function, but if you'd have to pass it a crapload of locals, it *might* be better to keep it inline in a 'for. |
| 11:13 | cmajor7 | TimMc: yep, makes sense. thank you. |
| 11:13 | gfredericks | (> (count locals) crapload) |
| 13:04 | muhoo | these instructions assume i have a pom.xml file. i don't. this is lein, i have a project.clj and it looks like the dependencies are there instead. http://devcenter.heroku.com/articles/local-maven-dependencies |
| 13:05 | muhoo | how woudl i translate those instructions from maven into lein? |
| 13:05 | technomancy | muhoo: I recommend using this instead: https://github.com/technomancy/s3-wagon-private |
| 13:05 | technomancy | should see about getting that devcenter article to mention it |
| 13:06 | TimMc | technomancy: But otherwise, you would just add a file: repo to your project.clj, right? |
| 13:06 | muhoo | technomancy: very cool, thanks! |
| 13:08 | technomancy | TimMc: yeah, but ... binaries in git; yuck. |
| 13:08 | muhoo | i don't mind having it on s3. and yes, binaries in git makes my skin crawl |
| 13:09 | muhoo | in fact, i don't even need credentials, i expect i could do this over http too |
| 13:09 | muhoo | this stuff isn't private or confidential, it's just not in anyone's maven repo |
| 13:09 | technomancy | oh yeah, in that case you can use http |
| 13:18 | gtrak | ha, rich hickey calls { a curly in his vid, I'm vindicated |
| 13:31 | maio | which version of Clojure is prefered for newbies? |
| 13:32 | sritchie | do you guys any recommendations on how to check equality of two regexes? |
| 13:32 | sritchie | ,(= #"string" #"string") |
| 13:32 | clojurebot | false |
| 13:32 | sritchie | I guess this works: |
| 13:32 | sritchie | ,(= (.pattern #"string") (.pattern #"string")) |
| 13:32 | clojurebot | true |
| 13:32 | technomancy | sritchie: yeah, that kills me |
| 13:32 | gtrak | maio: check out https://github.com/arthuredelstein/clooj |
| 13:34 | sritchie | technomancy: I wonder why implementation isn't value-based |
| 13:34 | gtrak | i don't use it, i recommend it for people to play around with? remind me of drscheme |
| 13:35 | gtrak | except, now that I try it, it doesn't work at all :-) |
| 13:35 | cemerick | maio: just grab leiningen, and you can get started in the REPL in a snap |
| 13:36 | cemerick | alternatively, there are plugins for all the major Java IDEs and emacs |
| 13:36 | faust45 | what is the best way to dispatch method for empty list and not empty list? |
| 13:36 | cemerick | maio: http://dev.clojure.org/display/doc/Clojure+Tools |
| 13:37 | faust45 | so i have two cases for empty list return '() and for not empty return lazy-seq |
| 13:37 | faust45 | but i wish to avoid (if code |
| 13:37 | Raynes | gtrak: I mean, clooj would be a good way to get started if it even supported syntax highlighting. |
| 13:37 | gtrak | Raynes: yea, I thought it was further along than it is |
| 13:38 | Raynes | There are Clojure plugins for generally every popular editor/IDE and it is almost certain that any given person coming to Clojure is already familiar with one of them. I just don't know where clooj fits in. |
| 13:38 | maio | <- Vim guy :) I'm asking because I every now and then I end with "Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite" errors |
| 13:38 | Raynes | Not to dismiss the fellow's work. It is quite admirable. |
| 13:39 | Raynes | maio: I use Vim too (these days, anyways). :> |
| 13:39 | Raynes | It is an excellent environment for Clojure. |
| 13:40 | raek | maio: try creating a new temp project, change the clojure version to "1.2.1", run lein deps, delete the temp project |
| 13:41 | technomancy | you're pulling in a broken plugin that declares its own version of Clojure |
| 13:43 | maio | yes. (this time) It started when I installed nailgun plugin |
| 13:43 | rlb | faust45: multiple function bodies, perhaps? (defn foo ([] 42) ([&x] 13)) |
| 13:44 | maio | is there something I can do about it? |
| 13:44 | faust45 | rlb: (defn foo []) not work for me if call (foo '()) |
| 13:47 | cemerick | faust45: An empty seq can be a number of different concrete types. Just use a conditional. (if (seq x) y z) |
| 13:48 | faust45 | cemerick: LazySeq never become EmptyList |
| 13:49 | faust45 | type |
| 13:49 | faust45 | cemerick: so its impossible dispatch on type |
| 13:50 | cemerick | faust45: of course it can. &(class (rest (lazy-seq [1]))) |
| 13:50 | cemerick | uh, lazybot? |
| 13:50 | cemerick | ,(class (rest (lazy-seq [1]))) |
| 13:50 | clojurebot | clojure.lang.PersistentList$EmptyList |
| 13:51 | cemerick | faust45: you can dispatch on type, it's just hardly ever a good idea. What are you actually trying to accomplish? |
| 13:51 | faust45 | clojurebot: great ) |
| 13:51 | clojurebot | Titim gan éirí ort. |
| 13:51 | Raynes | cemerick: ##(class (rest (lazy-seq [1]))) |
| 13:51 | lazybot | ⇒ clojure.lang.PersistentList$EmptyList |
| 13:51 | Raynes | cemerick: Don't blame lazybot for your inability to understand him. He is a complex being. |
| 13:52 | cemerick | The beatings will continue until lazybot can read my mind. |
| 13:52 | Raynes | cemerick: We'd just go with &&(), but that'd blow up in our face for channels where people use languages like Ruby. |
| 13:52 | Raynes | Same with &() |
| 13:52 | faust45 | cemerick: thanks will try |
| 13:53 | faust45 | Raynes: why you confused about ruby use case ? |
| 13:53 | cemerick | Raynes: I figured you'd set up per-channel characters. |
| 13:54 | Raynes | cemerick: Man, we've set up so much per-channel crap that our config file is like 100 line long and it's all one big map. I'm to the point where anything that requires me to have per-channel configuration, I just disable entirely and forget exists. |
| 13:55 | Raynes | cemerick: I originally planned for lazybot to be an end-user bot, but I don't think any non-programmer in the world could figure it out at this point. |
| 13:59 | cemerick | Raynes: are there end user bots? |
| 14:06 | amalloy | lazybot ends users |
| 14:08 | jsabeaudry | Recommandations regarding a lein clojurescript plugin? lein-cljsbuild looks like it has a lot of features |
| 14:11 | jkdufair | i've been using clojure-mode and the swank-clojure lein plugin. What do i need to use my local emacs to control swank running on a remote server? an explicit slime install? will it conflict with the slime embedded in clojure-mode? |
| 14:12 | technomancy | jkdufair: yeah, manual slime install; you can use marmalade |
| 14:12 | jkdufair | super. thx. |
| 14:12 | technomancy | or if you use an emacs instance that has already jacked in, it'll already have it. |
| 14:12 | technomancy | might be nicer not to rely on that leftover copy though |
| 14:12 | jkdufair | how does that work? |
| 14:13 | technomancy | how does which work? |
| 14:14 | jkdufair | using an instance that is already jacked in? in other words, where is slime in clojure-mode? didn't see it in the sources |
| 14:14 | jsabeaudry | emezeske, Out of curiosity, why arent hooks and :jar true the default values in lein-cljsbuild? |
| 14:14 | technomancy | it's a "payload" that comes from the swank-clojure jar |
| 14:14 | jkdufair | oh fascinating. thx. |
| 14:15 | jkdufair | clever idea. |
| 14:16 | technomancy | it's insane. =) |
| 14:23 | emezeske | jsabeaudry: I don't think there's any way to enable the hooks by default |
| 14:23 | emezeske | jsabeaudry: And the plugin began life without :jar support, so when it was added, we made it default to off for backwards compat. |
| 14:40 | jsabeaudry | Ok I got hiccup and clojurescript but what about css? |
| 14:42 | fliebel | jsabeaudry: There where some DSLs, but nothing really useful afaik. |
| 14:47 | jkdufair | how do i get swank-clojure to listen on an external interface? |
| 14:49 | pjstadig | jkdufair: according to `lein help swank` it accepts port and host arguments |
| 14:49 | pjstadig | so you should be able to do something like `lein swank 6666 123.123.123.123` |
| 14:49 | jkdufair | pjstadig: thank you. wasn't aware of lein help :-O |
| 14:49 | pjstadig | :) |
| 14:56 | tscheibl | jsabeaudry: cssgen from paraseba (it's on github) is quite useful |
| 14:57 | jsabeaudry | tscheibl, Thanks I'll take a look |
| 14:59 | tscheibl | jsabeaudry: i've been using it for quite some time know... for generating css on the fly in compojure routes |
| 15:00 | tscheibl | jsabeaudry: it's better than writing css directly because it's composable and supports inline hierarchies |
| 15:00 | jsabeaudry | tscheibl, Is that so the users can modify the "skin" of the site? |
| 15:01 | tscheibl | jsabeaudry: it renders to pure css .. |
| 15:02 | tscheibl | jsabeaudry: I usually create compojure routes which set the Content-Type to "text/css" and return on the fly generated css |
| 15:03 | amro | http://hastebin.com/qihujumime.lisp I get java.lang.NullPointerException after the ex[ected pit[it |
| 15:03 | amro | expected output* |
| 15:04 | jsabeaudry | tscheibl, Yes I was curious to know in which context you would like to generate css on the fly? |
| 15:05 | tscheibl | jsabeaudry: you could parameterize it that way |
| 15:05 | tscheibl | jsabeaudry: using get query paramters |
| 15:07 | tscheibl | jsabeaudry: e.g. using hiccup: (include-css "/main.css?background=green") |
| 15:08 | tscheibl | jsabeaudry: in that case you would probably have to add nocache headers to the response |
| 15:10 | tscheibl | jsabeaudry: you could also use it to compile static css from clojure files and include these in your html |
| 15:10 | rsenior | anyone around that can talk about the build.clojure.org setup? |
| 15:13 | tscheibl | jsabeaudry: where maybe cookies would be the best way to make the skin user configurable |
| 15:26 | aphyr | tw |
| 16:30 | the-kenny | Is there a swank server for clojurescript? |
| 16:33 | technomancy | the-kenny: there's one for Javascript, but I've never used it |
| 16:35 | technomancy | the swank-clojure codebase is extremely intertwingled with Java though |
| 16:40 | the-kenny | understandable. One would most likely have to write a "real" swank server in clojurescript. |
| 16:40 | the-kenny | Also, there's the problem of compilation |
| 16:41 | clj_newb | is it possible to define defrecords Foo, Bar, s.t. (.open foo) -> returns a Bar, (.close bar) -> returns a Foo ? |
| 16:44 | TimMc | Ah, a circular dependency? |
| 16:44 | TimMc | If you use protocols... maybe? |
| 16:44 | clj_newb | yes |
| 16:44 | clj_newb | ah, so (.open foo) returns a BarInterface object, and (.close bar) returns a Foo interface object? |
| 16:45 | TimMc | Yes, although that might just net you a new circular dep. :-) |
| 16:45 | clj_newb | at the interface level ; hmm |
| 16:46 | TimMc | Is this part of your scheme to create TYped Clojure? |
| 16:46 | clj_newb | sssssh, that could get me lynched |
| 16:46 | tjgillies | how do i access functions is projectname.core namespace from lein repl? |
| 16:46 | clj_newb | This is part of building my WYSIWYG editor, I'm implementing functional zippers on my own |
| 16:47 | tjgillies | s/is/in/ |
| 16:47 | clj_newb | so there are "closed/open" nodes |
| 16:47 | gtrak | tjgillies: use or require |
| 16:47 | the-kenny | Let's track clj_newb down and lock him behind 10^100 layers of parenthesis. |
| 16:47 | xian | Hi, just a quick question: When I create an uberjar with leiningen, how do I ensure that additional jars specified in :extra-classpath-dirs are available/included in the resulting uberjar? |
| 16:47 | clj_newb | and they need to return each other based on open/close |
| 16:47 | tjgillies | gtrak: thnx |
| 16:47 | brehaut | clj_newb: https://github.com/frenchy64/typed-clojure |
| 16:47 | technomancy | xian: only dependencies go into the uberjar |
| 16:47 | gtrak | tjgillies: and you can in-ns to switch to your desired namespace, but it won't be compiled until it's require'd i think |
| 16:48 | xian | technomancy: Okay, is there an easy way to add arbitrary jar files as dependency? |
| 16:48 | clj_newb | brehaut: certain looks interesting thanks |
| 16:48 | TimMc | Upload them to clojars |
| 16:48 | technomancy | xian: yes, you can publish them to s3, either in a public or private bucket |
| 16:48 | technomancy | clojurebot: repeatability is crucial for builds, see https://github.com/technomancy/leiningen/wiki/Repeatability |
| 16:48 | tjgillies | whats the syntax? i keep getting errors |
| 16:48 | brehaut | clj_newb: im pretty sure its just experiemental |
| 16:49 | tjgillies | (require 'project/core) ? |
| 16:49 | TimMc | clojurebot is pondering your request |
| 16:49 | gtrak | something like that |
| 16:49 | TimMc | tjgillies: got, not slash |
| 16:49 | TimMc | *dot |
| 16:50 | clj_newb | brehaut: yeah; but it has interesting links to read |
| 16:50 | clojurebot | Ack. Ack. |
| 16:50 | TimMc | haha |
| 16:50 | tjgillies | TimMc: thnx |
| 16:50 | TimMc | ~repeatability |
| 16:50 | clojurebot | repeatability is crucial for builds, see https://github.com/technomancy/leiningen/wiki/Repeatability |
| 16:50 | clj_newb | on a complete unrelated note, is it just me; or does anyone else have an intense urge to write cocoa apps (osx, ipad) in clojure? |
| 16:50 | technomancy | ugh; no |
| 16:51 | xian | technomancy: Hmm, I would prefer another way, actually. Uploading them to s3 requires too much work just to get some external jars included in my clojure project. |
| 16:51 | technomancy | xian: have you tried it? it's much easier than the alternatives. |
| 16:51 | technomancy | unless you're ok with "works on my machine; good enough" |
| 16:52 | TimMc | xian: Do you plan on having other people use your code? |
| 16:52 | clj_newb | ah ha |
| 16:52 | clj_newb | I think what I need is extend-typ |
| 16:52 | clj_newb | e |
| 16:53 | xian | technomancy, TimMc: I just put my jars in the lib directory and building the uberjar worked fine. |
| 16:53 | xian | TimMc: Not directly. Other people will interact with the uberjar. |
| 16:53 | TimMc | clj_newb: Yep, you'll use that after the protocols and records are defined. Have you succeeded in getting both protocols defined? |
| 16:54 | clj_newb | TimMc: yeah; there's no circular dependency at the protocal level since there arne't return-type signatures in protocols |
| 16:54 | TimMc | Ah, nice. |
| 16:55 | clj_newb | is there a book that coers all this stuff? |
| 16:55 | clj_newb | I don't see it in programing clojure |
| 16:55 | TimMc | clojurebot: private jars is <reply> To depend on private jars, use https://github.com/technomancy/s3-wagon-private |
| 16:55 | technomancy | xian: if you don't care about making it work on other machines you can use lein-localrepo to turn standalone jars into real dependencies |
| 16:55 | TimMc | clj_newb: It's new in 1.3, how old is the book? |
| 16:55 | clj_newb | TimMc: says copyright 2009 |
| 16:56 | TimMc | Not recent enough. |
| 16:56 | clj_newb | is any book recent enough? |
| 16:56 | xian | technomancy: Ah, I see. And yes, I only want to build the uberjar on my machine. Others won't interact with the code. Thanks for your help. |
| 16:56 | clojurebot | Ik begrijp |
| 16:56 | TimMc | I don't know. |
| 16:57 | clj_newb | ah, according to amazon, there's a new edition in april 2012 |
| 16:57 | TimMc | xian: Well, just make sure you leave sufficient breadcrumbs so that you or someone else can figure out how to build it in the future. |
| 16:57 | technomancy | cool |
| 16:58 | TimMc | clj_newb: Read through the sidebar links on http://clojure.org/, you'll pick up some new stuff. |
| 17:00 | tcrawley | technomancy: in lein 2.0, are you doing away with the ability to override :library-path, :resources-path, etc? The lack of defaults in leiningen.core.project leads me to believe that |
| 17:02 | technomancy | tcrawley: you can override :resources-path and :source-path and friends |
| 17:02 | technomancy | :library-path is gone altogether; classpaths are constructed directly out of ~/.m2; so there's no more need to gratuitously copy dependencies around. |
| 17:03 | TimMc | No more ./lib? |
| 17:03 | tcrawley | technomancy: ah, cool - I see :resources-path now, thanks |
| 17:04 | gfredericks | how will negligent coworkers accidentally and irrevokably add 30mb of jars to the git repo? |
| 17:04 | technomancy | the lib/ directory was more of a historical accident from the days of M-x swank-clojure-project than something actually useful |
| 17:04 | technomancy | gfredericks: I have no doubt their ingenuity will find a way! |
| 17:04 | gfredericks | I guess there's still the build outputs |
| 17:04 | tcrawley | technomancy: right now, in Immutant we assume lib/, and add the contents to the module class path for the app. if lib/ no longer exists, we'll need to suss the classpath from lein, but I suspect that won't be difficult |
| 17:05 | TimMc | tjgillies: `lein classpath` |
| 17:05 | TimMc | tjgillies: Sorry, that was meant for tcrawley |
| 17:05 | technomancy | yup |
| 17:05 | tcrawley | TimMc: well, it will be a bit more involved that that, but I can find it from there. thanks! |
| 17:06 | technomancy | it would be easy to write a copy-deps plugin, but there's just no need to have it built-in |
| 17:06 | TimMc | whoa |
| 17:06 | TimMc | I just realized that a meter is basically a baker's yard |
| 17:07 | brehaut | welcome to the future TimMc |
| 17:07 | TimMc | high on the metric system |
| 17:08 | TimMc | Sorry. ANYWAY. |
| 17:08 | brehaut | the initial euphoria should pass fairly quickly. it'll seem very ordinary in no time |
| 17:09 | gfredericks | ha: TIME. When are we switching from years to kilodays? |
| 17:09 | TimMc | technomancy: I assume lein2 will be able to use the vast majority of project.clj files out of the box? |
| 17:10 | AimHere | Then it stops being fun. You're just thinking in metres, kilometres, kilogrammes, just in order to feel normal each day. |
| 17:10 | TimMc | gfredericks: I already say things like "I'll be back in about a metric hour" just to mess with people. |
| 17:10 | clj_newb | should I prefix protocols with I or P, i.e. IFoo or PFoo? |
| 17:11 | TimMc | clj_newb: From the Java side, they just look like regular interfaces, right? |
| 17:11 | TimMc | I haven't worked with protocols yet. |
| 17:12 | clj_newb | I do not know enough about clojure to know. |
| 17:17 | lucian | clj_newb: i've seen them prefixed with P. i wouldn't prefix them with anything, though |
| 17:19 | jcrossley3 | clj_newb: i think the context in which a protocol is used makes the prefixes superfluous. i don't even like using 'em in java, myself. |
| 17:19 | hiredman | my irc client only shows me timestamps in kiloseconds since midnight |
| 17:20 | TimMc | Which midnight, O /ignore'ant one? |
| 17:20 | TimMc | (UTC would be best.) |
| 17:21 | jsabeaudry | Anyone knows how to tell cljsbuild to look into lib so it can find cljs libraries such as pinot? |
| 17:22 | clj_newb | hmm; I like my hungarian notation. |
| 17:22 | TimMc | clj_newb: As long as it's Apps Hungarian. |
| 17:28 | emezeske | jsabeaudry: The missing support for that is a bug (that I plan to fix this evening) |
| 17:28 | jsabeaudry | emezeske, Sweet! I'll use cljs-watch for the time being |
| 17:30 | technomancy | TimMc: yep, the main blocker will be plugins that use Leiningen functions that have moved. |
| 17:32 | jcrossley3 | clj_newb: TimMc: i don't even think Simonyi uses hungarian notation any more. :) |
| 17:59 | the-kenny | emezeske: Nice to hear this. I wated to report this bug today :) |
| 17:59 | the-kenny | s/wated/planned/ |
| 18:44 | emezeske | jsabeaudry, the-kenny: I'm trying to decide how best to fix the lib/ problem. I wonder if everything in :dependencies should be accessible to the cljs project, or if maybe I should add a new :dependencies option to the :cljsbuild config |
| 18:44 | Raynes | emezeske: http://blog.raynes.me/blog/2012/02/01/i-code-with-things-and-stuff/ I gibs vim love (and link to your copy of paredit.vim). |
| 18:46 | jsabeaudry | emezeske, I would tend to make everything in :dependencies and :dev-dependencies available |
| 18:46 | the-kenny | Yup, me too. |
| 18:46 | the-kenny | cljsbuilds own :dependencies would lead to a problem with hybrid jars which contain .clj and .cljs (like cljs-uuid) |
| 18:48 | emezeske | I guess my only worry is that cljsbuild depends on clojure 1.3.0 |
| 18:48 | emezeske | What would happen if the project used 1.2.x? |
| 18:48 | emezeske | Right now, the plugin uses leiningen's eval-in-project to always use 1.3.0 |
| 18:49 | emezeske | I'm not a jar expert, but it seems like conflicts could arise (?) |
| 18:49 | emezeske | Raynes: Awesome, I'll have to give that a read-through! |
| 18:50 | technomancy | emezeske: yeah, declaring a direct dependency on a project that requires 1.3 will cause issues. you would have to run cljsbuild code inside eval-in-project as well |
| 18:51 | emezeske | technomancy: That makes sense. I'm trying to figure out how to allow the cljs code to have jar dependencies |
| 18:52 | emezeske | technomancy: right now it uses eval-in-project and does not assoc in anything from the parent |
| 18:53 | technomancy | emezeske: wouldn't it make sense to just say that projects that have clojurescript components can't use 1.2? |
| 18:53 | emezeske | technomancy: Hmm, that seems fair. I doubt anyone that uses cljs is not up to 1.3 by this point |
| 18:54 | emezeske | the-kenny, jsabeaudry: Informal survey: are your projects using clojure 1.3? |
| 18:54 | TimMc | I'd liek to maintain import-static from old contrib. Any thoughts on how to do this? |
| 18:55 | TimMc | (Should I just fork and delete everything else?) |
| 18:57 | the-kenny | emezeske: Yup |
| 18:59 | emezeske | the-kenny: Okay, thanks |
| 19:04 | cmajor7 | what space does "loop/recur" consume? heap? |
| 19:05 | TimMc | cmajor7: constant space |
| 19:05 | TimMc | Oh, you mean where does it allocate locals? |
| 19:05 | cmajor7 | yep. where does it keep the "memories" |
| 19:05 | TimMc | ? |
| 19:06 | TimMc | As I understand it, the JVM basically puts everything in the heap. |
| 19:06 | cmajor7 | well… recursion (unless it is "tail") keeps them on the stack |
| 19:07 | cmajor7 | ok.. so loop/recur saves the "recursion" point in heap |
| 19:07 | cmajor7 | right? |
| 19:08 | hiredman | it doesn't consume space, that is the point |
| 19:10 | cmajor7 | hiredman: I see, so it is in a way tailed.. |
| 19:10 | cmajor7 | like: |
| 19:10 | cmajor7 | fac( N ) -> |
| 19:10 | cmajor7 | fac ( N, 1 ). |
| 19:10 | cmajor7 | fac ( 0, Holder ) -> |
| 19:10 | cmajor7 | Holder; |
| 19:10 | cmajor7 | fac ( N, Holder ) -> |
| 19:10 | gfredericks | cmajor7: that's why loop/recur exists |
| 19:10 | cmajor7 | fac( N - 1, N * Holder ). |
| 19:10 | cmajor7 | (erlang) |
| 19:10 | hiredman | ~pastebin |
| 19:10 | clojurebot | Excuse me? |
| 19:11 | hiredman | clojurebot: paste you jerk |
| 19:11 | clojurebot | No entiendo |
| 19:11 | hiredman | ~paste |
| 19:11 | clojurebot | paste is gist |
| 19:11 | gfredericks | cmajor7: because the native JVM functions won't do tail recursion |
| 19:11 | hiredman | ~gist |
| 19:11 | clojurebot | gist is forget paste |
| 19:11 | amalloy | hiredman: he can't remember "paste is gist.github.com" because the . ends the factoid |
| 19:11 | gfredericks | clojurebot: paste is gist,github,com |
| 19:11 | clojurebot | 'Sea, mhuise. |
| 19:12 | hiredman | amalloy: that is not true |
| 19:12 | hiredman | ~forget paste |is| gist,github,com |
| 19:12 | clojurebot | I forgot that paste is gist,github,com |
| 19:13 | amalloy | hiredman: okay. i'd be delighted to learn the right way to teach him, then, becase at least three times i've seen someone teach him gist.github.com and he parrots back just gist |
| 19:13 | cmajor7 | gfredericks: right. so loop/recur pair takes an existing state, creates a new [single] stack frame, passes the state to that stack frame, and leaves the past to GC? |
| 19:13 | hiredman | amalloy: most likely because some taught it 'paste is gist' |
| 19:13 | hiredman | ~gist |
| 19:13 | clojurebot | gist is https://refheap.com/ |
| 19:13 | hiredman | ~paste |
| 19:13 | clojurebot | paste is http://gist.github.com/ |
| 19:13 | hiredman | ~paste |
| 19:13 | clojurebot | paste is gist |
| 19:13 | hiredman | ~paste |
| 19:13 | clojurebot | paste is gist.github.com |
| 19:13 | hiredman | ~paste |
| 19:13 | clojurebot | paste is http://gist.github.com/ |
| 19:14 | hiredman | etc |
| 19:14 | amro | any idea why I'm getting a NullPointerException with this macro? http://hastebin.com/qihujumime.lisp |
| 19:14 | hiredman | amro: to start with docstrings go before arg lists |
| 19:15 | hiredman | to end with, look at the macroexpansion |
| 19:15 | gfredericks | cmajor7: I don't know the GC details but it certainly doesn't accumulate space like explicit recursion does |
| 19:16 | amro | hiredman: yes, there's an extra pair of () around it |
| 19:16 | amro | I don't know how to get rid of it |
| 19:16 | hiredman | extra how? |
| 19:16 | hiredman | you have a for |
| 19:16 | amro | ((print "a")) instead of (print "a") for instance |
| 19:16 | hiredman | for is list/seq comprehension, so the result is a seq |
| 19:17 | cmajor7 | gfredericks: that I see from the documentation. I was wondering the under the hood state of things.. it seems that it only keeps a single stack frame at a time.. |
| 19:17 | amro | how do I flatten just the topmost seq then? and have it return (print "a") (print "b") etc |
| 19:18 | weavejester | You probably want a (do ~@(for ...)) |
| 19:18 | weavejester | But using a macro to do this is pretty strange |
| 19:18 | weavejester | Is it just for practise? |
| 19:19 | amro | weavejester: that doesn't work, I tried it. I get Var clojure.core/unquote-splicing is unbound. |
| 19:19 | amalloy | also, drop the # in b#. it will just confuse people (mostly you) |
| 19:19 | amro | I dumbed down the macro so I can figure out what's wrong |
| 19:19 | weavejester | You probably forgot the beginning backtick |
| 19:19 | weavejester | In total it should be `(do ~@(for ...)) |
| 19:19 | amalloy | &(let [body '(a b)] `(do ~@(for [b body] `(print ~b)))) |
| 19:19 | lazybot | ⇒ (do (clojure.core/print a) (clojure.core/print b)) |
| 19:20 | amro | that's it, thanks |
| 19:20 | amro | I wasn't sure how to combine ` with ~@ |
| 19:20 | weavejester | ~ and ~@ go inside `() |
| 19:20 | clojurebot | Gabh mo leithscéal? |
| 19:21 | weavejester | It's like string interpolation in Ruby, Bash or Perl |
| 19:21 | weavejester | "hello $foo" is kinda equivalent to `(hello ~foo) |
| 19:21 | amro | amalloy: b# was part of the expanded macro when I first wrote it |
| 19:21 | weavejester | Except you're using data structures instead of strings |
| 19:22 | amalloy | personally i slightly prefer (cons `do (for ...)) to `(do ~@(for ...)), but i don't have a compelling argument |
| 19:23 | amalloy | i guess it forces me to keep in mind that really macros are functions for building lists, not "magic templates" |
| 19:23 | weavejester | Not just lists in Clojure ;) |
| 19:23 | gfredericks | the magic rose ~@ |
| 19:25 | amalloy | weavejester: yeah, i know. having a macro expand to just an integer or a string is pure magic |
| 19:26 | weavejester | amalloy: Hiccup makes does a lot with strings :) |
| 19:27 | amalloy | i feel like there must be very few cases where (html ...) expands to a string, though |
| 19:27 | weavejester | Yeah, it only expands to a string if there are no variables in the mix |
| 19:27 | weavejester | Does anyone else find that search engines are surprisingly good nowadays? |
| 19:27 | weavejester | I mean, I take them for granted |
| 19:28 | amalloy | i guess that's only half-true, because (html [:div foo bar]) expands recursively to something like (str "<div>" (html foo) (html bar)], and then foo and bar might be literal strings |
| 19:28 | weavejester | But even using them everyday sometimes they manage to match queries to the right page with very little info |
| 20:05 | amalloy | technomancy: make is pretty good. i'd definitely prefer it to ant, for example |
| 20:06 | technomancy | high praise |
| 20:07 | amalloy | yeah yeah |
| 20:07 | technomancy | I guess in my mind make is tainted by autotools |
| 20:07 | technomancy | guilt by assosiation |
| 20:07 | amalloy | yeah, autotools are something i cannot fathom at all. maybe it's great, but it is so bewildering |
| 20:07 | brehaut | i can only presume that once upon a time, it didnt seem like a bad idea |
| 20:08 | brehaut | and then it metastasized |
| 20:08 | technomancy | the fact that people who seem otherwise intelligent put up with them makes me think that the alternative of doing that kind of stuff by hand is just too horrible to comprehend? |
| 20:08 | technomancy | it is beyond my feeble imagination |
| 20:36 | TimMc | Any tips on testing namespace-manipulating functions? |
| 20:37 | TimMc | I don't want to contaminate my test namespace. Currently trying to write a macro that will evaluate its contents inside a temporary namespace. |
| 20:39 | technomancy | TimMc: copy what slamhound does |
| 20:39 | technomancy | each run generates a throwaway ns named after a gensym |
| 20:41 | TimMc | I think I finally have it, thanks. |
| 20:41 | TimMc | But I'll look at slamhound for sure. |
| 20:42 | TimMc | I ran a test in my REPL that worked differently line-by-line vs. as a single 'let form. |
| 20:59 | jcromartie | so I'm digging the REST vibe right now |
| 20:59 | jcromartie | and I am getting this idea that you could actually build a perfectly RESTful API without actually setting up routes for resources |
| 21:00 | jcromartie | i.e. by leveraging hypermedia and continuation-style callbacks of some sort |
| 21:01 | jcromartie | like, in your server-side API, you return a resource where the actions called by verbs are just closures tied to unique URLs |
| 21:01 | jcromartie | I hope that's not too ASP.NET |
| 21:09 | seancorfield | jcromartie: do you have example code somewhere? how do you map the urls to actions? |
| 21:10 | jcromartie | I'm working on it :P |
| 21:10 | jcromartie | let me whip up an example |
| 21:10 | brehaut | jcromartie: i dont see any reason why that couldnt be restful; nothing about rest requires you to have stable URLs |
| 21:11 | brehaut | (stable in terms of the app configutarion) |
| 21:11 | jcromartie | brehaut: yes, that's the point |
| 21:11 | jcromartie | well there do need to be stable entry points |
| 21:11 | brehaut | sure |
| 21:11 | jcromartie | I think I basically just came up with Seaside for APIs |
| 21:11 | jcromartie | but not so fancy in the use of continuations |
| 21:12 | brehaut | jcromartie: yeah |
| 21:13 | brehaut | jcromartie: as long as you keep the old URL callbacks around in case the client passes you an older version of the state, then it should be fine |
| 21:14 | jcromartie | but deleting the non-idempotent verbs when they are executed |
| 21:14 | jcromartie | that has the added benefit of not eve being able to accidentally DELETE something twice |
| 21:17 | martinklepsch | what is the reason behind "acc" as loop binding name? |
| 21:17 | brehaut | accumulator |
| 21:19 | brehaut | which i guess is following on from the registers of the same name |
| 21:19 | martinklepsch | ok |
| 21:22 | martinklepsch | I don't get how acc is being bound to the new value in the (recur) example here http://clojure.org/special_forms |
| 21:22 | martinklepsch | could anyone explain me that? |
| 21:23 | gfredericks | martinklepsch: the loop contains two bindings, so in the call to recur the second argument gets bound to acc |
| 21:24 | martinklepsch | okay so when i have 3 bindings I'd have 3 arguments to recur etc? |
| 21:24 | brehaut | yes |
| 21:24 | gfredericks | exactly |
| 21:25 | martinklepsch | makes sense... |
| 21:42 | wiseen | is there a library for serializing things to clojure Data that's more flexible than (prn-str x) ... eg. I would like java.util.Date to be serialized and some other primitives (URI) |
| 21:43 | gfredericks | wiseen: print-dup might be what you want? |
| 21:46 | wiseen | clojurebot ,(doc print-dup) |
| 21:47 | ibdknox | hola |
| 21:48 | Raynes | ibdknox: stfugoaway |
| 21:48 | ibdknox | Raynes: h8. |
| 21:51 | TimMc | wiseen: print-dup is a multimethod you extend. |
| 21:57 | blakesmith | Can anyone recommend a good clojure memcache library? |
| 22:05 | jcromartie | why did I just write a JSON library |
| 22:05 | gfredericks | there's nothing funner |
| 22:05 | jcromartie | this sort of thing happens |
| 22:06 | TimMc | It really does. |
| 22:06 | jcromartie | https://gist.github.com/3872b7bfd382ef706bd9 |
| 22:07 | jcromartie | I think it was because I didn't feel like opening project.clj |
| 22:07 | jcromartie | and adding the dependency |
| 22:07 | ibdknox | that's so much slower :p |
| 22:08 | jcromartie | nerds will go to great lengths to be lazy |
| 22:08 | brehaut | that sums up haskell |
| 22:11 | TimMc | pffft |
| 22:12 | TimMc | I can't remember why I ended up dropping clj-json in favor of cheshire... |
| 22:15 | ibdknox | TimMc: everyone's doing it :p Raynes made me change it in Noir |
| 22:15 | ibdknox | something to do with "more features" and "just as fast" |
| 22:21 | TimMc | Oh! clj-json gave me string keys, I wanted keyword keys |
| 22:23 | TimMc | No, it was *coercions* not being marked :dynamic, that was it. |
| 22:23 | TimMc | Looks like that one is fixed. |
| 22:55 | Raynes | ibdknox: The bad part is that a coworker seems to be the maintainer now. |
| 22:55 | ibdknox | Raynes: of clj-json? |
| 22:55 | Raynes | Making everybody switch to cheshire is probably not a good career move. |
| 22:55 | ibdknox | lol |
| 23:00 | seancorfield | how many json libraries do we have? and what's wrong with clojure.data.json? |
| 23:00 | TimMc | seancorfield: What's wrong with it is that I didn't know it existed. :-P |
| 23:04 | seancorfield | formerly clojure.contrib.json |
| 23:05 | ibdknox | seancorfield: it's not very fast I thought |
| 23:05 | ibdknox | at least not compared to something using jackson |
| 23:06 | seancorfield | i guess it depends whether it's "fast enough" |
| 23:07 | ibdknox | format conversions are one of those things that should just be as fast as possible |
| 23:07 | seancorfield | but i'd prefer we all worked to improve the standard clojure.* whatever libraries than proliferate incompatible alternatives :) |
| 23:07 | brehaut | ibdknox: unless its xml-rpc |
| 23:07 | brehaut | ibdknox: that might encourage someone to want to use it |
| 23:07 | ibdknox | lol |
| 23:09 | TimMc | seancorfield: Speaking of which, I'm trying to adopt import-static right now. |
| 23:10 | TimMc | It currently works by making macros, so you can't do (import-static '(java.lang.Math sqrt)) (map sqrt (range 10)) |
| 23:10 | TimMc | ...but I don't know what my chances are of getting my version blessed. |
| 23:11 | seancorfield | :) |
| 23:11 | seancorfield | well, after that drive-by pot-stirring, i'm off to watch TV and drink wine... or whisky perhaps? |
| 23:12 | TimMc | heh |
| 23:12 | TimMc | What is the beverage of choice of trolls? :-P |
| 23:14 | Raynes | seancorfield: I see no real point in improving clojure.* if a non-contrib library is better and significantly faster. You can't clean shit. |
| 23:15 | Raynes | And that came out a lot more rude to whoever the original author of that library is than I meant it to be. |
| 23:15 | brehaut | Raynes: but you can dunk it in varnish |
| 23:15 | Raynes | My point is, if the library can't be fast, why support it in the first place? |
| 23:15 | Raynes | The only reason cheshire can't be a contrib library (or clj-json for that matter) is because it relies on a fast Java library. |
| 23:16 | TimMc | The official libs also have the stigma (deserved or not) of not being able to move quickly. |
| 23:16 | Raynes | But really, I hate the distinction between 'contrib' libraries and libraries that people make. |
| 23:16 | seancorfield | the guys on mythbusters proved that you _can_ polish a turd, btw |
| 23:16 | TimMc | Raynes: The contribs are just the officially blessed libs, yeah? |
| 23:17 | Raynes | It seems to me that contrib is only useful for political purposes and for people who really like XML and terrible JIRA issue managers. |
| 23:17 | brehaut | Raynes: i dunno, i think contrib as a 'this project has proven to be great, lets promote it into a more visible tier' is valuable; eg core.logic |
| 23:17 | Raynes | That's kind of my point. |
| 23:17 | Raynes | The JSON lib *isn't* great. It's slower than ever other library. |
| 23:18 | Raynes | But we should work on it because… it's officially sanctioned and written in pure Clojure? |
| 23:18 | Raynes | inb4 itisn'tpureclojurebecauseitcallsouttojava |
| 23:19 | jeremyheiler | If a project is blessed, doesn't that immediately raise the barrier of entry to support it, as opposed to just being a popular project that doesn't have the same contributor rules as clojure porper? |
| 23:19 | seancorf | there are discussions around using external dependences in some contrib libs... it might happen... |
| 23:19 | jeremyheiler | proper* |
| 23:19 | seancorf | and the new process is meant to be a lot more streamlined and faster to evolve code |
| 23:20 | Raynes | No, because being officially blessed means you have to go through hell to actually contribute. |
| 23:20 | Raynes | Not that they don't have excellent reasons for the hellish procedure. |
| 23:20 | seancorf | but the important distinction is a legal one: contrib libraries are protected under the same license / IP as clojure itself - which is of concerns to a lot of companies |
| 23:20 | Raynes | Some of them, anyways. |
| 23:20 | Raynes | Yeah yeah yeah, I know. |
| 23:21 | Raynes | Not a lawyer. |
| 23:21 | Raynes | Thankfully. |
| 23:21 | seancorf | and to be honest Raynes the process really isn't hellish :) |
| 23:21 | Raynes | If we're talking about barrier to entry, I'd be happy to hear of a single point in the favor of non-hellish. |
| 23:21 | seancorf | i ended up maintaining java.jdbc without much fuss, because i needed contrib.sql running on 1.3 |
| 23:23 | seancorf | there are a LOT of people with signed CA's on file which means a large pool of people who can submit patches |
| 23:24 | Raynes | But we were talking about barrier to entry, right? |
| 23:24 | seancorf | all the open source projects i know have a similar barrier to entry |
| 23:24 | seancorf | you have to sign a CA and follow the patch process |
| 23:24 | cmajor7 | "recur special form can also be used as the last call in a function to return to the beginning of that function with new arguments" => would this be a common use? or the one to avoid? ##(defn recursive ([number] (recursive number 1)) ([number factorial] (if (zero? number) factorial (recur (- number 1) (* factorial number))))) |
| 23:24 | lazybot | java.lang.SecurityException: You tripped the alarm! def is bad! |
| 23:24 | Raynes | I sure don't know of a lot of them. |
| 23:25 | Raynes | But I wasn't arguing against the CA. |
| 23:25 | Raynes | Like I said, I'm not a lawyer. |
| 23:25 | jeremyheiler | seancorf: Is a maintianer of a contrib allowed to process patches at their own pace? So, for example if a popular library with an active community is blessed, that shouldn't hurt the project in anway, right? |
| 23:25 | jeremyheiler | If* |
| 23:25 | jeremyheiler | sorry, Is* |
| 23:25 | Raynes | seancorf: As a lib maintainer, are you allowed to accept patches and issues on Github? |
| 23:25 | jeremyheiler | (sans a CA agreement form all) |
| 23:26 | seancorf | no pull requests allowed |
| 23:26 | Raynes | I consider JIRA a massive barrier to entry, dismissing all the CA stuff. |
| 23:26 | jeremyheiler | ^agreed. |
| 23:26 | TimMc | seancorf: Ouch. |
| 23:26 | Raynes | I consider JIRA a massive barrier to *anything*. |
| 23:26 | seancorf | patches via JIRA are the acceptable way |
| 23:26 | seancorf | it's because of legal traceability of copyright |
| 23:26 | TimMc | I'm not going to even bother trying to get this contrib I'm maintaining blessed. |
| 23:26 | Raynes | Well, at least they've got their asses covered. *shrug* |
| 23:27 | Raynes | Really, really well. |
| 23:27 | seancorf | like i say, just like all the other open source projects that corporations feel comfortable using |
| 23:28 | jeremyheiler | For core, I think the CA and legal stuff works really well. That's important. But I think it really makes it undesirable to have a library blessed into contrib if it wasn't specificlly written to be there in the first place. |
| 23:28 | seancorf | when i worked at macromedia / adobe i had the "pleasure" of going thru a license audit on a large project |
| 23:28 | TimMc | seancorf: Ah, you're saying that this is effectively due to pressure from corp.s that want to use these projects? |
| 23:28 | Raynes | I'm fine with companies not using my projects if I get to maintain them in a sane was a resut. |
| 23:28 | Raynes | result* |
| 23:28 | seancorf | yeah, without that stuff, many corporations cannot use an open source project |
| 23:28 | seancorf | i want clojure to be usable by such companies so i'm happy to comply with the process |
| 23:29 | Raynes | The way I feel at this point is that I just hope nobody puts any libraries I like into contrib so that, if I ever have to contribute to them, I don't have to go through all the nutty crap involved. That's just me though. |
| 23:29 | TimMc | seancorf: I don't see why you can't get the same traceability via Github permissions. |
| 23:29 | nuclearsandwich | Raynes: agreed |
| 23:29 | Raynes | TimMc: Apparently if you delete your account, your name disappears. |
| 23:30 | TimMc | >_< |
| 23:30 | seancorf | TimMc: because you have to go back thru the entire repo history and ensure that all committers have signed CAs on file |
| 23:30 | TimMc | But the commits are still there! |
| 23:30 | TimMc | seancorf: Not hard. There is rarely a ton of committers. |
| 23:30 | Raynes | It's probably only a matter of time before they have the code in git repos hosted on their server, just in case. :p |
| 23:31 | TimMc | seancorf: Although I guess someone could lie and submit under someone else's name? |
| 23:31 | Raynes | You could probably send in a fake CA and submit a patch under that. Not sure what would happen. Damn not-being-a-lawyerness. |
| 23:32 | Tcepsa | cmajor7: I believe that is a common use |
| 23:32 | seancorf | the CA is a legally binding document - so it protects the project |
| 23:32 | jeremyheiler | I don't see why accepting a pull request can't involve a core committer checking the user for a CA first. I Imagine that is done in JIRA anyway? |
| 23:32 | Raynes | You can only get a Jira account if you've been sanctioned by a team member. |
| 23:32 | seancorf | jeremyheiler: because then the burden is on core which isn't fair to the project |
| 23:32 | Raynes | It's admittedly different. |
| 23:32 | jeremyheiler | Ah, ok. |
| 23:32 | Raynes | But... |
| 23:33 | seancorf | having been thru the other side of this at a corporation, i can only say that this is necessary for corporation adoption of clojure and its set of sanctioned contrib libraries |
| 23:33 | arohner | seancorf: "this" being CAs. JIRA + patches seems to be more of an implementation detail, IMO |
| 23:34 | arohner | I can imagine Github having a permissions model that would make this painless |
| 23:34 | Raynes | Let the record stand that it is not the CA that I have a problem with. |
| 23:34 | seancorf | yeah, we know you don't like JIRA :) |
| 23:34 | Raynes | It is the fact that we're only allowed to use a small subset of what Github offers. |
| 23:34 | Raynes | You might as well host these repositories with gitweb. |
| 23:35 | TimMc | Oh, fun with macros: actual: (not (number? (. java.lang.Math (sqrt 3.141592653589793)))) |
| 23:35 | cmajor7 | Tcepsa: thank you. you mean it is used commonly even though it can be accomplished with "loop/recur"? |
| 23:36 | seancorf | *you* can use the full range of github - you can fork clojure, work on it any way you want... |
| 23:36 | emezeske | jsabeaudry: I just released lein-cljsbuild 0.0.10, which pulls in the host project's :dependencies and :dev-dependencies. Let me know if it works for you! |
| 23:36 | Raynes | seancorf: I'm making sure I'm clear on this. You know I don't like Jira, right? |
| 23:36 | seancorf | but if you want a patch accepted, you have to put it in a JIRA ticket as a patch :) |
| 23:36 | Raynes | You can pull from a gitweb repository and work on it anyway you want. |
| 23:36 | Raynes | And it is the exact same thing. |
| 23:36 | TimMc | It's not JIRA that bothers me, it's patch-formatted contributions. |
| 23:37 | seancorf | i agree github's "free-for-all" workflow is more convenient |
| 23:37 | Raynes | seancorf: All a Github fork is is a copy of a repo under your name. It isn't anything special that you need Github for. If that was the full range of Github, I'd probably just use bitbucket and hg. |
| 23:37 | seancorf | but i also understand that corporate concerns mean a tighter control on IP and contributions |
| 23:37 | Raynes | ;) |
| 23:38 | Raynes | Yeah, we know you're worried about corporate concerns. :) |
| 23:38 | seancorf | i maintain clj-time and work on congomongo too and it's nice to be able to accept random pull requests but that also means those libraries can't be used by corporations that have license audits :) |
| 23:39 | jeremyheiler | All I'm saying is that "the process" might just make it less desirable to want a useful lib be blessed into contrib. Wether tha tis important or not, i don't know. |
| 23:39 | jeremyheiler | (from a maintainer's and community perspective) |
| 23:40 | Raynes | That's where I'm at right now. |
| 23:40 | seancorf | jeremyheiler: understood - and several folks have raised that issue on clojure and clojure-dev MLs over the last year or so (i'm sure it came up before then too but i wasn't around then :) |
| 23:40 | Raynes | But like I said, that's just how I feel. I understand the justifications and I know that my bitching wont change anything. Doesn't mean I have to like it. |
| 23:40 | seancorf | it's ok, we don't mind being a "shoulder to cry on" about it :) |
| 23:41 | Raynes | You mean you. :p |
| 23:41 | seancorf | and, yeah, for the record, i wish we could accept pull requests but it is what it is |
| 23:42 | Tcepsa | cmajor7: Yes; I believe that's the intent of providing a mechanism to return to the beginning of the current function; it prevents you from having to put in a redundant loop statement if you're essentially doing a tail-call. |
| 23:42 | Raynes | The important thing is that we're all free to do whatever we want because Clojure *is* open source. If we don't want to put our libraries in contrib then we certainly don't have to. Don't have to use the ones that are there either, but the contrib process wouldn't stop me from using a good contrib library. clojure.data.json doesn't seem to be one of them though. |
| 23:42 | jeremyheiler | I should probably cancel mine then. (I submitted a patch as well, though) |
| 23:42 | TimMc | jeremyheiler: Cancel which? |
| 23:42 | jeremyheiler | the pull request. |
| 23:42 | TimMc | heh |
| 23:43 | jeremyheiler | yeah |
| 23:43 | Tcepsa | cmajor7: Put another way, that's how you can approximate tail-call optimization even though the JVM doesn't support it directly. |
| 23:43 | jeremyheiler | Raynes: compeletely agree. And it's simple to fork a contrib lib and modify it for your own needs until a patch is approved. |
| 23:44 | Tcepsa | cmajor7: Instead of calling your function again and pass it the new arguments, you call recur and pass IT the new arguments. |
| 23:44 | kilborn | Hi, new to clojure, I'm trying to figure out an idiomatic way to do the equivalent of mutating a closure bound variable? I have a function which recurs, and I need it's behavior to be controllable from outside it's scope. Global variables are not the right way... Suggestions? |
| 23:44 | Raynes | That's generally what I've been doing. |
| 23:44 | Raynes | Except the sending a patch part. I have to really care to do that. |
| 23:45 | Raynes | But that's pretty selfish and a habit I intend to break. |
| 23:45 | jeremyheiler | haha |
| 23:46 | cmajor7 | Tcepsa: I see.. so the "loop/recur" actually equals "defn/recur"? |
| 23:46 | Tcepsa | kilborn: This is a shot in the dark, but have you looked at using an "agent"? |
| 23:48 | kilborn | Tcepsa: I thuought about it (message-passing seems to suggest itself), but I hoped there's a simpler way then going all erlang and stuff... |
| 23:49 | kilborn | I'm pretty close to constructing the function by passing an atom map into it, then pinning the atom symbol on the function's metadata, but that feels too complicated as well. |
| 23:50 | dnolen | kilborn: what you're trying to do doesn't sound all that idiomatic. but you can do it. |
| 23:50 | Tcepsa | cmajor7: I am not certain what's actually happening under the hood (I wouldn't be at all surprised if there was some subtle-but-important difference between the two) but that understanding will probably serve you pretty well. I think of them as being two separate things, but as far as how you go about using them, they are very similar. (In other words, it looks like it but I'm not familiar enough with the details to say "Yes |
| 23:50 | Tcepsa | absolutely" ~wry grin~) |
| 23:50 | dnolen | kilborn: (let [x (atom nil)] (defn foo [] ...)) |
| 23:51 | flazz | i'm doing bit operations on an integer, is there a way to not have it convert to a long? |
| 23:52 | kilborn | dnolen: hey, you're the core.logic guy! *tips hat*. But then I keep everything in outer namespace, and it *feels* like it should be encapsulated inside the function... |
| 23:52 | dnolen | kilborn: it's not visible, you've create a lexical scope |
| 23:53 | dnolen | created |
| 23:53 | Tcepsa | kilborn: Also, at the hazard of looking like a complete idiot, I ask "Could you use a namespaced variable?" |
| 23:53 | Tcepsa | Nevermind, you just answered |
| 23:53 | kilborn | dnolen: well, if I do it exactly like you suggest yeah, but then how to I modify the atom from say the REPL? i need a symbol in my hand |
| 23:53 | kilborn | s/todo/ |
| 23:54 | arohner | cmajor7, Tcepsa : recur goes "up" to the nearest recursion point, which is either a loop, or the defn |
| 23:54 | cmajor7 | Tcepsa: thanks. in clojure core source I see "loop/recur", hence I suspect it outperform "defn/recur"… the thinking is "loop" just creates a "point/address" of recursion, while "defn" might be a bit more expensive. especially a arrity matching. e.g. (defn fn ([n] (fn n 1)) ([n accum] (…))) |
| 23:54 | Tcepsa | kilborn: If you have a "starter function" (no idea what it'd really be called) that creates an atom and passes it to your recurring function and also returns the atom, then you could catch the return value and modify it in your REPL. |
| 23:56 | dnolen | kilborn: it sounds like you're doing something strange :) probably need more context |
| 23:56 | kilborn | Tcepsa: True, and that's where I was leaning, but then if my function has 2 lines in it, It feels like i'm balancing dolphins on my nose while simultaneously practicing my limbo skills |
| 23:56 | Tcepsa | kilborn: (assuming that it starts the recursive function in a separate thread, but the way you've been talking about it strongly implies that it is in a separate thread from e.g. the REPL) |
| 23:56 | kilborn | Dnolen: gladly. you've heard of overtone? |
| 23:56 | dnolen | kilborn: yep |
| 23:57 | kilborn | dnolen: great. really basic use case. I have a function which takes in a list of chords, chooses one randomly, and then reschedueles itself to play the next one in say 1000 ms |
| 23:58 | kilborn | dnolen: it's all working nicely, but now I want to change the chord choices (say I move to the chorus in a piece, whatever). with closures and set! , or objects and setters, this would be very natural, but with immutable data I can't find the idiom |
| 23:59 | dnolen | kilborn: not sure why an atom at the top level your ns doesn't perfectly solve the problem. |
| 23:59 | Tcepsa | cmajor7: I'm not sure, but based on what arohner said I'm guessing that when it enters a function it also places a point/address of recursion. Arity isn't a problem--just think of functions defined with different arities as different functions. Whichever one the recur is in is the one that will be recurred to. (i.e. you can't recur from inside a function that takes two arguments to the inside of a function of the same name that |
| 23:59 | Tcepsa | takes one argument; you'd have to use trampoline for that) |