#clojure log - Nov 13 2011

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

0:00 technomancy: I am probably not going to be measuring perf so much that I'd notice, but I appreciate having it available

0:00 dakrone: cool, well lemme know how it works regardless :)

0:00 and lemme know how I can hely with the JAVA_OPTS lein thing

0:00 *help

0:01 leo2007: technomancy: do you know if fuzzy completion works in slime?

0:02 technomancy: leo2007: people have gotten it working, but I don't know the details

0:04 dakrone: it's just the smarter quote-aware space string split in (System/getenv "JVM_OPTS") on line 94 of compile.clj

0:04 dakrone: technomancy: I'll take a look

0:07 technomancy: sweet

2:26 loz: hi

2:26 it is possible to run clojure programs on android platform?

2:28 zms: loz: if clojure been ported to dalvik as well, i guess.

2:30 loz: zms: any progress in porting?

2:32 zms: loz: this is all i'm aware of http://www.deepbluelambda.org/programming/clojure/clojure-for-android-source-published

2:36 loz: zms: cool, sounds assure)

3:24 mdeboard: Weird question, but is the guy I was bickering with about the functional nature of list comprehensions in python the other day in here?

4:55 _ulises: I know this is awfully specific, but is anybody running emacs inside iTerm2/Terminal.app?

4:55 I'm having trouble mapping C-up/down arrow for history support in slime

7:39 zms: can someone please take a look at http://pastie.org/2856453

8:13 _ulises: zms: what's with it?

8:35 kzar: Oh I see how to do it.. just looked at how with-connection works, ovbious really! Sorry

8:42 zms: _ulises: the dorun part throws a null pointer exception and i've been unable to figure out the source

8:43 _ulises: zms: line 15, you have ((println...))

8:44 zms: println returns nil, if you try to eval that as a fn you're likely to get a NPE

8:44 </wild_guess>

8:44 zms: _ulises: testing..

9:01 _ulises: you're right. the NPE goes away if i remove this statement. but the purpose of the statement was to show if it's actually doing what it should (check if files can fit into available space). that is broken too..

9:02 _ulises: zms: you're trying to modify m with assoc. assoc returns a new map and then it gets discarded :)

9:02 if that's what you mean by "that's broken too"

9:02 zms: _ulises: i'm not sure if the idea of updating the existing list of maps and use that in next iteration sensible at all. coming from imperative mindset i can't seem to think of a way to do it. :-(

9:03 _ulises: ouch. i tried using update-in but that also didn't seem to make sense.

9:03 _ulises: zms: that's because, as you said, you're writing imperative for loops

9:05 zms: _ulises: it's been mind-bending wrapping my head around this. it's fun but frustrating as hell too. :)

9:05 _ulises: zms: let me see if I can cook up something quick that does what you want; then we can walk through it together

9:06 zms: _ulises: i'll be ever grateful.

9:10 Vinzent: anyway, why i can't write something like (def foo) (fact (inc foo) => 2 (provided foo => 1))?

9:11 or maybe (fact .x. => 1 (provided .x. => 1))

9:21 _ulises: zms: nearly there

9:25 zms: _ulises: wonderful!

9:31 _ulises: zms: http://pastie.org/2856836

9:31 zms: there are a few nasty bits such as (comp not (some predicate...)))

9:32 but the general flow of the algorithm is to recurse while trying to fit files into mount points; each recursion loop takes the first file and sees if it fits in any mount point, if so it adds it to the list of files that do fit somewhere, updates the mount point's free space and recurses using the updated list of mount points and files

9:33 I'm sure the code is *not* as clear as it could be

9:33 I also added the option of tagging each file that fits somewhere with the path where you'd have to place it

9:34 Borkdude: _ulises: did you see the thing about the encoding variable yesterday?

9:35 _ulises: it solved my slime error

9:38 zms: _ulises: thanks a lot! it'll take me some time to digest this and get back.

9:41 _ulises: Borkdude: I tried it today and it solved mine too :)

9:41 zms: cool, enjoy :)

10:19 zms: _ulises: there's so many new things (for me) in what you wrote (into, partial, conj, comp, ..) and all introduced in a context/problem space that i understand. :) it'll probably be a while before i can come back to discuss the code. thanks again for your time.

10:20 _ulises: zms: no worries. Please keep in mind that that is definitely not the best code to learn from :)

10:24 zms: _ulises: hehe. still it's an order of magnitude beyond my current level so it's a gift and a lesson to me.

10:24 _ulises: zms: cool then, glad to be of assistance :)

10:42 Vinzent: here is _ulises' code with some minor modifications: http://pastie.org/2857122, wdyt?

11:00 zms: Vinzent: it does produce the same results. i see the differences are in the let bindings. i can't say which one is better or simpler yet. there's more new functions here (group by, concat, ...) and like i said above, i'm still reconfiguring my brain to think in clojure. thank you for the code. i am learning from both of them.

11:21 Vinzent: zms, i've also tried to avoid multiplie passes through the collections (when sorting and around the cons call), although it's not much perfomance boost with collections of such size :) anyway, i think it's interesting to try to find different approaches to the problem

11:21 so _ulises made a good exercise for both of us :)

11:30 jakeskik: hi

11:31 zms: Vinzent: indeed. :)

11:32 Vinzent: hello jakeskik

11:32 jakeskik: is there something like difference for vectors?

11:33 or haskell \\ operator?

11:33 so that (difference [1 1 1 2 3] [1 2]) would result [1 1 3]

11:34 Vinzent: you can convert one vector into the set and then (remove ...)

11:35 but that will return [3] for ypur example

11:36 jakeskik: yap, I need to keep the duplicates (except the one which was processed)

11:38 I'm finding my way around core libraries and trying to craft a decent solution for KataPotter: http://codingdojo.org/cgi-bin/wiki.pl?KataPotter

11:42 Vinzent: then it's possible either to use reduce with accumulator, or partition

11:50 jakeskik: Vinzent: thanks, i'll check patitioning. I played a bit with reduce too, but it seemed to lead quite complex solution. I'd like to do something like this: https://gist.github.com/1362307

11:52 of course, the remove call on the last line doesn't do the trick and I should do the recursion with recur instead of calling the function.

12:05 Vinzent: jakeskik, sorry for the delay. here is a possible implementation: http://pastie.org/2857437 My proposal about partition was wrong, it'd help only if you want to remove the whole second-vector occurences

12:05 let me read your links

12:10 zeek123: Anyone willing to look at three versions of 10 lines of code? I'm loading an file entire into a list and partitioning the list into a list of pairs. Two versions don't work and one works verrrrry slowly. Thanks.

12:16 fliebel: zeek123: You did not actually post the 10 lines.

12:16 zeek123: Indeed. I wanted to make sure it was appropriate to do so.

12:16 Here they come...

12:17 TimMc: zeek123: pastebin, of course

12:17 zeek123: that was my next q, thanks

12:18 TimMc: ~paste

12:18 clojurebot: paste is http://gist.github.com/

12:19 zeek123: https://gist.github.com/1362348

12:19 fliebel: Do files and sockets actually override Object.finalize?

12:21 zeek123: TimMc: I'm getting OutOfMemoryErrors if I remove the doalls. But with the doalls, it doesn't seem to terminate, but it might eventually. If I use my group-by-twos instead of partition, then back to OutOfMemoryErrors. I want to make sure I understand what lazy sequences do before I actually try to do something real.

12:21 TimMc: Do you really need the whole file in memory at once?

12:22 Can you process it as a stream instead?

12:22 zeek123: Ideally I want to do numerical processing on ~1.5GB files with Incanter, so I guess ultimately I won't be able to keep everything in mem at once.

12:23 My ultimate goal is an n^2 algorithm. I will need to keep scanning back to the beginning of the file... Are streams still a good fit?

12:26 TimMc: zeek123: The thing about lazy seqs is this: Although they delay computation of the seq until it is needed, they keep the results around as long as you hold onto the head of the seq.

12:26 zeek123: I was formulating a question about that... is there a way to do this that generates what I need from a function? I know there's a classic newbie mistake in here somewhere.

12:27 TimMc: It really depends on what you want to do.

12:27 zeek123: hmm

12:28 I found a bunch of blog posts about this topic, but nothing that was immediately enlightening. Any general principles or reading, or should I go back to my original problem and do some more thinking?

12:28 TimMc: seqs wrapped around file streams are great if you are doing stream processing -- as you keep calling (next) on the seq, the lines or chars that you have read into the seq (lazily) are garbage-collected.

12:29 zeek123: TimMc: That makes sense. You keep rebinding to a new head, right?

12:29 TimMc: yeah

12:29 In the general case, seqs are just linked lists with some potentially clever stuff in the tail.

12:30 zeek123: Because they're lazy they're faster but they take up more mem, right?

12:30 Or at least they accumulate a lot of not-yet-run code.

12:30 TimMc: I don't know how much more memory they take up. Less, if you don't realize the entire tail while holding onto the head.

12:31 zeek123: Makes sense; especially if the seq is infinite.

12:31 TimMc: right

12:31 zeek123: So maybe I should be thinking harder about what I can throw away and when. And how to get it back on-the-fly if I need it again.

12:31 TimMc: You can keep walking (range) as long as you like as long as you don't keep a reference to the head.

12:31 duck1123: was there a clojure library wrapping java.security.* I remember seeing something, but I can't find it again

12:32 TimMc: zeek123: Yep. What are you writing?

12:32 duck1123: trying to avoid re-inventing the cryptographic wheel

12:33 TimMc: duck1123: java.security is just easy enough to use that I haven't bothered looking for a wrapper.

12:33 duck1123: zeek123: as long as you make sure not to hold the head of any long lazy seqs, the JVM should be pretty good at GC-ing those discarded objects

12:33 zeek123: TimMc: It's a compression algorithm from a 2011 paper that uses previous "contexts." You need to be able to search through everything causal to the symbol you're trying to encode. I have it mostly working in Matlab, but I'm trying to break my dependence on Matlab, etc.

12:33 TimMc: duck1123: The problem here is a quadratic algorithm that maybe requires all the data at once.

12:33 leo2007: how to get java doc in clojure repl?

12:33 duck1123: TimMc: not sure if that was sarcastic or not...

12:33 zeek123: (Thanks, duck1123.)

12:34 leo2007: duck1123: do you use ac-slime?

12:35 TimMc: duck1123: j.s.MessageDigest isn't so bad!

12:35 zeek123: TimMc: I've never had to do this before, but maybe I should leave the file I'm encoding on disk and do random access as needed.

12:35 duck1123: leo2007: No, I only use the default of what is loaded with the emacs starter kit

12:36 TimMc: zeek123: Is there any way you can build up a table of extracted data?

12:36 duck1123: TimMc: I'm doing RSA encrytion and verification. (implementing the salmon protocol) and it's a bit of a pain

12:37 TimMc: hrm

12:37 duck1123: So, not just running some bytes through MD5?

12:37 duck1123: no, a bit more complicated than that

12:39 TimMc: zeek123: "symbols" are any byte sequence?

12:39 zeek123: TimMc: The "contexts" heavily overlap, like a sliding window, and they can't really be boiled down into a table. I think what I'll do is have one stream of the file for encoding, and I'll have to restream the entire file for each symbol that I want to encode.

12:40 TimMc: eep

12:40 zeek123: TimMc: Symbols are 16 bits of any arbitrary byte sequence.

12:40 I don't see another way to do it. :)

12:41 In matlab I can get the entire file into memory and then have multiple iterators off of it.

12:41 fliebel: Has anyone written something to access fields and enums nicely in Clojure? bean coms close, but that's not "it"

12:41 zeek123: but I am still making many, many passes over the file.

12:42 TimMc: zeek123: I'm sure there's a way to load the whole file into memory in Clojure, too -- you'd just want to use something other than a lazy seq to iterate over it.

12:43 There's probably an existing seq impl that will do what you want here/

12:43 zeek123: TimMc: re loading whole file into memory; yes! that would be fantastic. seq implementation: what should i be googling?

12:44 how can i not fill up the JVM heap? how do i know how much it's giving me?

12:45 TimMc: Well, you may need to tell the JVM to use a big heap. There are some switches like -Xmx2G you can pass it for various aspects of its memory footprint.

12:46 zeek123: TimMc: got it

12:47 TimMc: zeek123: What sort of access do you need to the data? Aligned words?

12:47 zeek123: TimMc: yes, the file will always be an even number of bytes

12:47 and my "symbols" are 16 bits

12:49 TimMc: So some kind of random-access collection of ints

12:49 or bytes, I guess

12:49 zeek123: TimMc: makes sense. ideas for idiomatic clojure?

12:50 TimMc: Not sure yet.

12:50 If you read the whole thing in, the JVM might not be happy with the size of the byte[] required.

12:51 duck1123: Okay, the good news is I can sign and verify with freshly generated keys, so this hasn't been a complete loss. Now to just figure out where the example sig I have fails.

12:52 TimMc: There are utilities around that can manage large buffers of (primitive) bytes; that's what you'd want to use. You can probably roll a quick function to slurp a file into one of these.

12:53 duck-streams did this kind of thing, but it no longer quite exists.

12:53 duck1123: Would a simple byte array input stream work for you? It's easy enough to get that from a file

12:53 TimMc: duck1123: For a 1+ GB file?

12:53 duck1123: most went to c.java.io

12:54 TimMc: there are limits to the *length* of arrays in Java

12:54 zeek123: Oh! Could you maybe memory-map a file?

12:54 zeek123: TimMc: duck1123: It's not even so much the size of the file, it's any time i start doing interesting things with it that the memory usage explodes.

12:55 TimMc: that's a great idea. more transparent to me.

12:55 TimMc: java.nio I think has utils for that

12:55 duck1123: isn't there a lazy input stream for stuff like that? I don't know as much about java io as I should

12:56 zeek123: TimMc: I will have a look at that, and I will make sure to lose my head, as it were. That will hopefully get me a lot farther.

12:56 TimMc: duck1123: I really don't think that will work here -- this algorithm needs random access.

12:57 duck1123: nvm then

12:57 zeek123: TimMc: In any case, you don't think I'll be adding epicycles on top of epicycles? Clojure is a reasonable language for this? It's been a real pleasure to work with so far. I'm hoping to stick with it.

12:58 TimMc: zeek123: Nothing wrong with using Java libs. That's why Clojure targets the JVm, after all.

12:59 I think Clojure is a fine language for this. You'll just need to be careful about which tools you use, just as in Java.

12:59 (e.g. for this project you wouldn't use an ArrayList<Byte>.)

13:00 zeek123: TimMc: right, thanks. i think I'm spoiled by matlab, but half the point of this is to get out of the matlab ghetto.

13:00 TimMc: haha

13:00 zeek123: matlab is, after all, dedicated to this kind of problem

13:00 TimMc: yup

13:01 zeek123: and i want to be working with a general language so while i'm doing this stuff i'll be building skills that i can use for my own projects.

13:01 anyway, thanks for much for kicking this around with me. i'll have a look at what we've chatted about.

13:01 thanks for the ideas duck1123.

13:01 afk for now

13:02 TimMc: zeek123: I'll leave you a link as soon as I can find it.

13:03 zeek123: TimMc: i'll keep an eye on the log

13:04 TimMc: zeek123: Here is a post by dnolen with an example of high-efficiency Clojure: http://dosync.posterous.com/lispers-know-the-value-of-everything-and-the

13:06 zeek123: TimMc: link is excellent. much food for thought. afk for real this time.

13:55 fliebel: drewr: Why is javax.activation excluded?

14:05 Can we have clojure in clojure already? If java.lang where all protocols, life would be easy, in certain areas.

14:05 dbushenko: how to override JFrame.paint() with clojure?

14:09 TimMc: dbushenko: proxy

14:09 dbushenko: TimMc, have a look: (proxy [JFrame] [] (paint [graphics] (println "Hello, World!")))

14:10 it doesn't work. could you tell my why?

14:10 fliebel: &(source into)

14:10 lazybot: java.lang.RuntimeException: Unable to resolve symbol: source in this context

14:10 TimMc: dbushenko: $source into

14:10 ack

14:10 $source into

14:10 lazybot: into is http://is.gd/7toqQd

14:10 TimMc: fliebel: ^

14:10 fliebel: (use 'clojure.repl)

14:11 &(use 'clojure.repl)

14:11 lazybot: ⇒ nil

14:11 fliebel: &(source into)

14:11 lazybot: ⇒ Source not found nil

14:11 TimMc: dbushenko: I've done it here: https://github.com/timmc/CS4300-hw6/blob/master/src/hw6/core.clj#L25

14:11 fliebel: ok, what I wanted to say, is that it does some weird stuff for transients.

14:11 dbushenko: TimMc, thanks!

14:12 fliebel: if it is a transient, convert it to a transient, conj, and return a persustent.

14:12 TimMc: dbushenko: Mine is doing some other stuff, but the basic are there.

14:13 dbushenko: Looks like your code is similar to mine..

14:15 TimMc: dbushenko: Does the window at least come up?

14:15 ,(ancestors (class (transient [])))

14:15 dbushenko: yeah, but the paint function isn't called

14:15 clojurebot: #{clojure.lang.ILookup clojure.lang.ITransientCollection java.util.concurrent.Callable clojure.lang.AFn java.lang.Runnable ...}

14:15 gfredericks: ,(.run (transient []))

14:15 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: TransientVector>

14:16 TimMc: &(instance? clojure.lang.IEditableCollection (transient []))

14:16 lazybot: ⇒ false

14:16 TimMc: &(instance? clojure.lang.IEditableCollection [])

14:16 lazybot: ⇒ true

14:16 TimMc: fliebel: That's neat.

14:16 gfredericks: O_o

14:16 TimMc: what does it mean?

14:16 TimMc: gfredericks: Take a look at into's source.

14:17 gfredericks: so "Editable" means "transientable"?

14:17 TimMc: Apparently.

14:17 fliebel: TimMc: wait, what... a persistent collection extends clojure.lang.IEditableCollection?

14:17 TimMc: Yeah. :-)

14:17 It's not a great name.

14:18 fliebel: ah, I though all transients where editable, which is why I was confused.

14:18 gfredericks: ,(transient (transient []))

14:18 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector$TransientVector cannot be cast to clojure.lang.IEditableCollection>

14:18 TimMc: fliebel: It's more that they are Editablable :-P

14:18 And I wonder... ##(into (transient []) [1 2 3])

14:18 lazybot: java.lang.ClassCastException: clojure.lang.PersistentVector$TransientVector cannot be cast to clojure.lang.IPersistentCollection

14:18 TimMc: And I wonder... ##(class (into (transient []) [1 2 3]))

14:18 lazybot: java.lang.ClassCastException: clojure.lang.PersistentVector$TransientVector cannot be cast to clojure.lang.IPersistentCollection

14:19 TimMc: OK, so you can't use into with transients. Not a big surprise, you have a limited set of operators.

14:20 Question for the channel: Is it proper to say that "seqs are collections", or is it more correct to say that "seqs happen to be implemented using a collection (list)"?

14:21 dbushenko: TimMc, I've found what was wrong. I should have invoke that with SwingUtilities/invokeLater

14:21 gfredericks: TimMc: I would question the second part, if I didn't think you knew more than me.

14:21 TimMc: dbushenko: Aha! Which should you have run with that?

14:22 the launch of the JFrame?

14:22 dbushenko: Time: (proxy [JFrame] [] (paint [graphics] (SwingUtilities/invokeLater (proxy [Runnable] [] (run [] (draw-graph @win))))))

14:22 that code works for me

14:22 TimMc: hmmm

14:22 I don't know if that's correct.

14:23 dbushenko: why? did I have to run the JFrame with invokeLater?

14:23 TimMc: I think the Graphics object may only be safely used in the dynamic scope of paint().

14:23 I think so. Look at the last line of my example.

14:23 Swing is weird about threads.

14:24 dbushenko: TimMc, hopefully I don't use it in this function.

14:24 TimMc: gfredericks: Lazy seqs use Cons cells, which is what lists are, so coll? and seq? both return true for (range).

14:24 dbushenko: draw-graph fetches the graphics object and then draws on it

14:25 TimMc: dbushenko: I believe that Swing paints on the event loop thread.

14:25 dbushenko: TimMc, how to call on the event loop?

14:25 TimMc: By the way, (proxy [Runnable] [] (run [] ...)) is just #(...)

14:26 dbushenko: really?????

14:26 :-D

14:26 great!

14:26 TimMc: Yeah, check this out:

14:26 &(ancestors (class #(* % %)))

14:26 lazybot: ⇒ #{clojure.lang.AFunction clojure.lang.Fn clojure.lang.IMeta clojure.lang.IObj clojure.lang.IFn java.util.concurrent.Callable java.lang.Object java.lang.Runnable java.util.Comparator clojure.lang.AFn java.io.Serializable}

14:26 TimMc: See the Callable and Runnable in there? :-)

14:27 and Comparator as well

14:27 dbushenko: super!

14:27 TimMc: So, back to Swing -- I think you want to launch the JFrame using invokeLater, and not use invokeLater in the paint method.

14:27 dbushenko: yeah, that really works

14:28 hmm... let me try

14:28 TimMc: I could be wrong, but that's what I seem to recall.

14:28 dbushenko: TimMc, you were right, it works

14:29 TimMc: yay!

14:30 I recommend reading up briefly on Swing threading. I think there are some other weird things to be aware of, but I havne't used it in a bit.

14:30 fliebel: What would be the best way to convert a Clojure map to any subclass of java.util.Map? Now I just reduce the one into the other.

14:30 dbushenko: yeah, swing and threading is a weird thing

14:31 TimMc: &(java.util.HashMap. {:a 1, :b 2})

14:31 lazybot: ⇒ #<HashMap {:b=2, :a=1}>

14:31 TimMc: &(.get (java.util.HashMap. {:a 1, :b 2}) :a)

14:31 lazybot: ⇒ 1

14:32 TimMc: fliebel: ^ The Java Collection classes usually have a (Collection) constructor.

14:32 fliebel: TimMc: Not this one (Properties)

14:32 TimMc: Ah.

14:32 *any* subclass?

14:33 fliebel: oh, I can call putAll

14:33 TimMc: nice!

14:44 Borkdude: Hmm, I'm puzzled by an enlive example. I get lazyseqs instead of

14:44 strings in my output.

14:46 fliebel: user=> (field-map javax.mail.Folder) {:holds_messages 1, :holds_folders 2, :read_only 1, :read_write 2}

14:49 raek: Borkdude: ring accepts lazy seqs of strings as response bodies

14:50 using a lazy seq allows the body to be generated lazilly

14:50 TimMc: That's great!

14:50 Borkdude: raek: I got this now https://gist.github.com/1362567

14:50 raek: I was trying to imitate and example from enlive on github

14:51 raek: I expected the tablebody to be filled by

14:51 *** <tr><td>names</td></tr> things

14:51 raek: is username a node tree?

14:52 Borkdude: raek: they are just strings.. not good?

14:52 raek: clojure.lang.LazySeq@... means that you gave something that expected a string something else (a seq)

14:52 brehaut: Borkdude: transformations are functions from node to node; you are returning a seq rather than a node (map with :tag :attrs :contents)

14:53 raek: sorry, my first comment does not apply in this case

14:53 (thought you mean something else)

14:53 "A transformation is a function that returns either a node or collection of node."

14:53 Borkdude: raek: I checked with (swank.core/break) that username in the for

14:53 loop is a string

14:54 brehaut: aha...

14:54 raek: Borkdude: also, have you considered clone-for

14:54 brehaut: Borkdude: you might want to look at clone-for in enlive

14:54 raek: ?

14:54 Borkdude: just trying to imitate this one: https://github.com/cgrand/enlive/blob/master/examples/net/cgrand/enlive_html/examples.clj

14:55 TimMc: I have found the enlive tutorials difficult to read and apply to my work.

14:55 I just wnat to shove some data into some HTML, dammit! :-)

14:55 Borkdude: haha

14:55 I am touching it for the very first time now

14:56 brehaut: TimMc: my problem was that they cover all the conceptual stuff pretty quickly, and then dive into examples. i never grasped the conceptual stuff to i had bet my head against my own problems

14:56 TimMc: Borkdude: I'm working with it right now, let me show you my code so far.

14:56 Borkdude: brehaut: why clone-for if the example should work with for?

14:56 and why the heck is my table body disappearing

14:57 brehaut: Borkdude: im curious about that too; i wonder how old that example is; enlive changed dramatically over its life

14:57 TimMc: Borkdude: Here's where the pertinent stuff is in my case: https://github.com/timmc/seqs-and-colls/blob/master/src/seqs/core.clj#L40

14:57 Borkdude: brehaut: I am using version 1.0.0 from clojars!

14:57 brehaut: Borkdude: but what version is that example using! ;)

14:58 raek: my guess is that something adds one extra layer of seqs

14:59 Borkdude: brehaut: good question. let me just explain what I'm trying to

14:59 do => insert <tr><td> ... </td></tr> 's with names filled in on the dots

14:59 raek: and maybe enlive checks whether each element of the outer seq is a map (a node), and if it isn't calls 'str' on it

14:59 Borkdude: now show me the most appropriate way in enlive ;)

15:00 raek: Borkdude: clone-for

15:00 Borkdude: raek: I guess that one is not in 1.0.0

15:00 TimMc: Borkdude: I run clone-for over the :tr in here and then clone-for over the :td 's: https://github.com/timmc/seqs-and-colls/blob/master/src/seqs/html/table.html

15:00 brehaut: Borkdude: as raek suggests, thats the usecase for clone-for

15:01 raek: Borkdude: example: https://github.com/raek/lcug-guestbook/blob/master/src/se/raek/lcug/guestbook/view.clj

15:01 TimMc: brehaut: I often prefer to have a working example first, and then drill down into how it actually works.

15:03 brehaut: TimMc: likewise

15:04 Borkdude: ok, clone-for... what enlive version should I use from clojars then?

15:04 TimMc: I'm using 1.0.0.

15:05 [enlive "1.0.0"]

15:05 Borkdude: hmm ok, lemme see

15:05 oopz, forgot to prefix it

15:08 tensorpudding: i genuinely ignored the docs for enlive, they just confused me

15:08 and just looked at the code of the example in the wiki that has a form that they clone

15:09 Borkdude: hmm, I now get two tablebodies with tr/td/name in it

15:09 with the two names I listed though

15:12 ah, got it

15:15 works: https://gist.github.com/1362567

15:15 tnx guys!

15:23 TimMc: yay

15:29 Borkdude: which transformation to use to remove smth from the html?

15:29 substitute?

15:29 brehaut: Borkdude: substitute with a nil result

15:29 s/result/value/

15:30 or perhaps content with nil depending what your selector is

15:30 TimMc: Borkdude: (fn [nodes] (when-not (hungry?) nodes))

15:30 something like that

15:31 Borkdude: timmc: I have added an id to the table

15:31 and when the user first comes to the page, I don't want to show

15:31 the table

15:33 TimMc: so smth like this: (deftemplate welcome-page "index.html"

15:33 [] [:table#names] ...)

15:34 I'm trying to understand how it works by looking at the tests...

15:34 https://github.com/cgrand/enlive/blob/master/test/net/cgrand/enlive_html/test.clj

15:34 but that doesn't help me very much with substitute

15:34 TimMc: That [] can take a boolean called first-view? and then you can have [table#stuff] (fn [tbl] (when (not first-view?) tbl))

15:35 tensorpudding: yes, templates are functions

15:35 you can specify them with arguments that you pass

15:36 Borkdude: eh, how many lines of code can I paste without being kicked out?

15:36 4 too much?

15:36 brehaut: you wont get kicked, but its not good form

15:36 tensorpudding: just use a pastebin, or gist, or ideone

15:36 gfredericks: everybody will glare at you

15:36 using the unicode glare character

15:36 TimMc: ಠ_ಠ

15:37 Borkdude: ok, like this? https://gist.github.com/1362634

15:37 gfredericks: that is a very cool character

15:37 TimMc: It is U+0CA0

15:37 brehaut: 💩

15:37 TimMc: twice, with an underscore

15:38 tensorpudding: nice astral plane characters

15:38 gfredericks: ironically, it takes four lines to print it

15:38 Borkdude: tnxs a lot, these characters will come in handy

15:38 TimMc: brehaut: All I got from you was U+FFFD

15:38 brehaut: TimMc: huh. it was supposed to be the unicode pile of poo

15:38 Borkdude: btw, my example doesn't work. why not?

15:38 brehaut: i blame colloquay

15:39 TimMc: I blame my fucked-up server.

15:39 brehaut: Borkdude: you dont need to pass a fun to substitute; just pass nil

15:39 TimMc: Borkdude: Did you see my example at :29? I didn't use substitute.

15:40 brehaut: alternatively instead of subsitute you oculd use (constantly nil)

15:40 Borkdude: brehaut: ah that works

15:40 TimMc: Borkdude: Whatever expression you put in has to evaluate to a function. That function will be called with the matched list of nodes.

15:41 The result of the function should be a string or a seq.

15:46 Borkdude: my emacs crashed...

15:46 TimMc: what did you say? I missed it

15:47 TimMc: Borkdude: Whatever expression you put in has to evaluate to a function. That function will be called with the matched list of nodes. / The result of the function should be a string or a seq.

15:47 Borkdude: so putting in nil... why does it work?

15:48 TimMc: Borkdude: You're not putting in nil, you're putting in a function that, when called, gives nil.

15:49 Borkdude: TimMc: I mean this: [:table#names]

15:49 (enlive/substitute nil)

15:49 like brehaut suggested, it works

15:49 brehaut: Borkdude: do you understand that all the core transformations (eg, content, substitute etc) are actually returning functions ?

15:49 TimMc: Borkdude: enlive/substitute returns a function

15:49 brehaut: That was the key to my understanding what enlive was doing.

15:50 brehaut: Borkdude: content frinstance is approximately (fn [new-content] (fn [node] (assoc node :content new-content)))

15:51 Borkdude: substitute is probably (fn [new-nodes] (fn [_] new-nodes))

15:51 TimMc: it actually uses constantly :-)

15:51 Borkdude: so, substitute something returns (fn [new-content] (fn [matched-node] ...replace something in the matched-node])?

15:51 TimMc: (constantly (flatten-nodes-coll values))

15:51 brehaut: TimMc: i figured ;) but for the purposes of simplifying whats happening

15:51 Borkdude: TimMc: I saw that, but I still don't understand it quite

15:52 TimMc: ((enlive/substitute "hello")) => '("hello")

15:52 brehaut: ,(map (constantly :foo) (range 1 10))

15:52 clojurebot: (:foo :foo :foo :foo :foo ...)

15:52 Borkdude: ah wait, I thought substitute would substitute something inside the matched node

15:52 TimMc: Borkdude: A template is not an html tree -- it is a tree of *functions* for transforming an html tree.

15:52 brehaut: Borkdude: thats content

15:53 Borkdude: but it substitutes the entire node

15:53 * brehaut thinks enlive beginners shouldnt be taught about deftemplate till after they know about snippets (and emit*)

15:54 TimMc: brehaut: I think they should deftemplate first, but not be released from class until they see snippets, etc.

15:54 Borkdude: ok, so substitute returns a function that always evaluates to the substitution

15:54 TimMc: yup

15:54 Borkdude: and what is that function applied to, the matched node?

15:54 TimMc: Yes, but it ignores the node.

15:55 (nodes)

15:55 Borkdude: so each function is applied to the matched node

15:55 brehaut: Borkdude: yes exactly.

15:55 Borkdude: and that series of applications results in new html

15:55 TimMc: brehaut: This is something I am not clear on, actually -- does [:table :tr]'s matcher get all the :tr's, or just the first, or is it called once for each?

15:55 Borkdude: so why do I need snippets?

15:56 brehaut: TimMc: it should match all the :trs inside :tables inside the current context node

15:56 TimMc: So the function gets a collection.

15:57 brehaut: Borkdude: snippets are like templates that return nodes instead of a seq of strings

15:57 churib: is there an "unintern" in clojure?

15:58 brehaut: TimMc: i think it depends _where_ that selector is used; if you use it with select then i think it gets a collection; if you use it with at (which is implicit in templates and snippets) then you get single node

15:58 TimMc: OK.

15:58 raek: churib: ns-unmap?

15:58 churib: raek: sounds good - thanks!

15:59 Borkdude: brehaut: why was content a nested function?

15:59 brehaut: like (fn [new-content] (fn [node] ...))

15:59 what is new-content?

15:59 brehaut: Borkdude: all the standard transforms are nested function

16:00 Borkdude: the transformations are only ever passed a node (or node set for a selection range)

16:00 churib: raek: how do i get the current namespace?

16:01 brehaut: Borkdude: but you probably want additional data in that transformation (such as the new content to insert); the inner function closes over outer functions locals. new-content is whatever the new content of the node is (ie, it replaces :content in the node map)

16:01 TimMc: ,*ns*

16:01 clojurebot: #<Namespace sandbox>

16:01 churib: TimMc: thanks :)

16:02 TimMc: churib: There might be a better way...

16:02 brehaut: Borkdude: constantly returns a function too - a function that ignores its arguments and returns the same thing constantly

16:02 Borkdude: brehaut: er, the outer function gets "usernames" in my example then?

16:02 sritchie: hey all -- is the clojure 1.4 snapshot available on maven?

16:03 for dev

16:03 Borkdude: brehaut: I know that, but constantly doesn't return a nested function

16:03 churib: TimMc: I used it only in the repl to get rid of an typo

16:03 (symbol)

16:03 brehaut: (source constantly)

16:03 TimMc: Ah, OK.

16:03 brehaut: Borkdude: i need a link to the code you are talking about

16:03 Borkdude: brehaut: ok, wait

16:04 brehaut: https://gist.github.com/1362567

16:04 brehaut: if clone-for returns a nested function

16:04 brehaut: Borkdude: so are you refering to the argument to content ?

16:05 Borkdude: brehaut: then what would an application to it look like?

16:05 brehaut: Borkdude: https://github.com/cgrand/enlive/blob/master/src/net/cgrand/enlive_html.clj#L658-661

16:06 Borkdude: clone-for is a special case here; it uses a macro to generate the function rather than creating it through closuring

16:06 Borkdude: but it still creates a function from node -> nodes

16:06 Borkdude: brehaut: ah, that's why I was confused

16:07 brehaut: but also constantly isn't nested right? I get node -> nodes, but not new-content -> node -> nodes like you suggested (I think)

16:07 new-content -> (node -> nodes) I mean

16:08 brb

16:09 brehaut: Borkdude: i dont understand what you mean about constantly not being nested

16:10 constantly is defined as (defn constantly [x] (fn [& args] x))

16:21 Borkdude: brehaut: yes, so constantly doesn't return a nested function, but just a function that returns x

16:22 brehaut: Borkdude: i think we may have different notions of what a 'nested function' is

16:22 Borkdude: brehaut: my notion is: a function that returns a function

16:23 brehaut: Borkdude: thats _exactly_ what constantly is

16:23 Borkdude: brehaut: yes, but it doesn't _return_ a nested function

16:23 TimMc: uh...

16:24 ,(let [return-value (constantly 17)] (fn? return-value))

16:24 clojurebot: true

16:24 brehaut: Borkdude: lets use more precise terminology then. constantly returns an anonymous function that is within the lexical scope of the invocation constantly that returned, closing over constantly's argument

16:24 Borkdude: thats the same as enlive's content and substitute

16:25 also i fail at english

16:25 Borkdude: TimMc: you are just checking if the return-value is a function, not if it is a function that will return a function

16:25 brehaut: I'm just trying to understand

16:26 TimMc: Oh, it most certainly isn't. That's true.

16:26 brehaut: Borkdude: lets start with the basics. do you know what lexical scope is?

16:26 Borkdude: brehaut: yes

16:26 brehaut: Borkdude: and you understand that the inner function is closing over the containing functions lexical variables ?

16:27 Borkdude: brehaut: (constantly 3) returns a function of varargs that closes over the value 3

16:27 brehaut: right?

16:27 brehaut: right

16:28 now; can you tell me why you think thathttps://github.com/cgrand/enlive/blob/master/src/net/cgrand/enlive_html.clj#L598-601 is a different construction to constantly?

16:30 Borkdude: brehaut: I think we can agree on "a transformation _is_ a function of --args-- that _returns_ a function of a node that closes over the --args--", right?

16:30 brehaut: yes

16:30 Borkdude: brehaut: ok

16:31 brehaut: then I think I'm starting to understand it ;-)

16:31 brehaut: Borkdude: phew :)

16:37 Borkdude: brehaut: some Haskell-ish notation would be helpful here maybe

16:37 brehaut: in the code itself

16:37 brehaut: Borkdude: it wouldnt hurt.

16:39 data HTMLNode = Nil | HTMLText String | HTMLNode String (Map String String) [HTMLNode]

16:39 content :: HTMLNode -> HTMLNode -> HTMLNode

16:39 ;)

16:40 substitute :: HTMLNode -> HTMLNode -> HTMLNode

16:40 not really all that clarifying is it ;P

16:41 churib: is there a way to get all symbols of an namespace?

16:43 brehaut: &(keys (ns-map 'clojure.core)) ;; churib

16:43 lazybot: java.lang.SecurityException: You tripped the alarm! ns-map is bad!

16:43 brehaut: hah. well, try that in your own repl churib

16:43 Borkdude: brehaut: hmm... that brings us to, what would it look like for clone-for? ;)

16:43 brehaut: Borkdude: my template haskell is weak ;)

16:44 churib: brehaut: thanks!

16:45 djanatyn: how feasible would it be to write a game in 48 hours, and then distribute it publically with clojure?

16:46 I'm thinking of entering a 48 hour game-making competition - I did it last time with python and pygame

16:46 brehaut: djanatyn: distribution would be trivial; lein uberjar would create a self contained jar file that you could run

16:46 djanatyn: the competition is in 33 days - would it be possible?

16:46 yeah, I saw lein had some really cool distribution things when I was playing with it.

16:46 but how is the library situation for making games?

16:47 I'm not really interested in learning clojure to make games, but I think this might be a cool opportunity to force myself to write some real clojure code

16:47 brehaut: djanatyn: i dont know if there is anything that is analogous to pygame

16:47 partly because pygame is all over the place wrt what it provides

16:47 djanatyn: my friend tomoj linked me this: https://github.com/jvillste/clojure-lwjgl

16:48 i've never used lwjgl before, not really sure what it is

16:48 I've used SDL with perl and python with pygame

16:48 tomoj: https://github.com/ztellman/penumbra

16:48 then wrap whatever else from lwjgl you want

16:50 maybe that clojure-lwjgl library is good, no docs it seems. at least inspiration

16:53 https://github.com/ztellman/penumbra/blob/master/test/example/game/asteroids.clj

16:59 Borkdude: brehaut: how would you go about removing all things from the html that have class="welcome"

16:59 brehaut: I have [:.welcome] (enlive/substitute nil)

16:59 brehaut: but it only removes one

17:00 brehaut: Borkdude: (enlive/transform doc [:.welcome] (enlive/subsitute nil))

17:01 Borkdude: i probably wouldnt use an at form to do it (or a snippet or template which have implicit ats)

17:05 Borkdude: brehaut: how would I use this inside a deftemplate?

17:06 brehaut: Borkdude: i dont think you would

17:06 Borkdude: brehaut: so deftemplate kind of presumes that every selector,transform pair is only applied once?

17:07 brehaut: i think so?

17:07 ive never tried to do anything super fancy with deftemplates

17:08 Borkdude: brehaut: maybe I should just make a second html file... but I'm too lazy ;-)

17:08 brehaut: lol

17:08 how about you just use a html-resource, an at, a transform and an emit*

17:08 rather than the special case that template wraps up for you

17:10 Borkdude: brehaut: ok, let me check that out, tnx

17:10 brehaut: (deftemplate name "my.html" [args] atstuff…) is roughly (defn name [args] (at (html-resource "my.html") atstuff…))

17:10 Borkdude: Perfect!

17:10 brehaut: Borkdude: although it caches the html-resource

17:19 daaku: what's the right way to deal with destructuring in macros defining functions? let should do the trick, but i'm wondering if that's the idiomatic way. this gist should explain better: https://gist.github.com/f2e1c00a93826b40dd34

17:19 Borkdude: brehaut: ah wait, deftemplate worked ok, but I just made a mistake in the html

17:19 brehaut: two class attributes... oopz

17:20 brehaut: ah lol :)

17:32 ohpauleez: finally home after the conj- I can feel my brain coming back together

17:32 Borkdude: I guess this is working then finally with some Enlive templates :) http://whosnotfollowingme.herokuapp.com/

17:34 dnolen: ohpauleez: was lots of fun.

17:34 Borkdude: brehaut, TimMc : tnx for helping, learned a lot today

17:34 brehaut: Borkdude: no problem

17:36 jimduey: ohpauleez: me too. It was a blast.

17:37 ohpauleez: dnolen: jimduey: Totally. One of the most fun, educational, and inspiring trips I've had in awhile. I'm reading through a new stack of papers as we speak

17:48 djanatyn: penumbra is pretty great

17:54 ohpauleez: djanatyn: What are you using it for? Or just playing around with it

17:54 djanatyn: ohpauleez: Well, I haven't used it yet at all. I cloned the git repo, not really sure how to work with it.

17:55 I've been learning common lisp, and I really like lisp and want to start using it. There's a 48 hour game-making competition coming up in a little bit over a month, and I figured that maybe the library situation would be better with clojure.

17:55 I'm not really sure how to do distribution with common lisp, either.

17:56 It seems like most people advocate bundling a common lisp interpreter *with* your program, but I'm not sure how to do that either

17:56 a quicklisp is a little intimidating for me, at least.

17:56 s/a/and

17:58 ohpauleez: ahh, gotcha - well, welcome to Clojure! There's been some great success making games in Clojure

17:58 djanatyn: awesome :)

17:59 i'm really interesting in functional programming, too

17:59 however, the only thing i've ever written in a vaguely functional style was a little haskell script

18:00 I can grok lisp a lot easier than haskell, and it looks like clojure's distribution is super easy with lein (I've had distribution issues in the past), so I'm excited

18:05 zerokarmaleft: when using cljs-watch, is bootstrap.js the only thing that needs to be pulled in?

18:06 dnolen: zerokarmaleft: what do you mean?

18:07 zerokarmaleft: dnolen: from within an html file

18:08 djanatyn: does clojure sepreate pure and non-pure functions in the same way as haskell?

18:08 brehaut: djanatyn: no

18:08 djanatyn: if by 'the same way' you mean via the type system

18:08 dnolen: zerokarmaleft: you don't need to include bootstrap.js, just whatever output file you specified.

18:10 bhenry: i want the overtone presentation video asap! (i never use "asap," but this time it's deserving)

18:11 djanatyn: hmm, weird.

18:11 so clojure doesn't have, like, an IO type?

18:11 dnolen: djanatyn: no, it has reference types. we have statement management, we just don't rely a type system for such things.

18:11 er state management

18:14 zerokarmaleft: dnolen: i'm just running cljs-watch with no args, so the default output is bootstrap.js

18:15 TimMc: djanatyn: This is a good read: http://www.clojure.org/state

18:15 dnolen: zerokarmaleft: ok, then yes that should work.

18:15 zerokarmaleft: i'm able to get an inferior-lisp repl connected to the browser fine that way, i just seem to be missing dom functions

18:15 dnolen: zerokarmaleft: did you switch into your namespace? you need to eval your ns form to do that.

18:15 zerokarmaleft: yes

18:16 dnolen: zerokarmaleft: so dom/getElement is not working?

18:16 zerokarmaleft: for instance, append and get-element work, but not much else

18:16 dnolen: zerokarmaleft: oh are you trying to use cljs dom namespace? not the google one?

18:17 I wouldn't do that. I think cljs dom is half-baked at this point.

18:19 zerokarmaleft: dnolen: ah ok, that's it then!

19:30 gfredericks: I just used the {:strs ...} destructuring form for the first time.

19:30 in case any of you were wondering.

19:33 klauern: gfredericks: I'm new to clojure, what is that?

19:33 I know sort of what destructuring is, but only on a var-args defn kind of way

19:33 Raynes: gfredericks: Not sure I'm familiar with that there non-existent form.

19:34 gfredericks: ,(let [{:strs [foo bar]} {"foo" 734, "bar" [1 2 3]}] [foo bar])

19:34 clojurebot: [734 [1 2 3]]

19:34 gfredericks: Raynes: did I misdescribe something?

19:34 Raynes: Oh, cool!

19:34 * Raynes hugs gfredericks.

19:35 gfredericks: Raynes: also :syms

19:35 Raynes: You have to write blog posts about this.

19:35 gfredericks: one for :strs and one for :syms?

19:35 klauern: these kinds of things seem kind of magical to me

19:36 Where do you pull up the docs for that kind of thing?

19:36 gfredericks: klauern: :keys is the one most people are familiar with, and it seems a bit cryptic until you've written (let [{foo :foo, bar :bar} m] ...) a million times

19:37 klauern: Yeah, part of it is that is seems fairly non-obvious that you'll get some sort of modified result because of a :symbol being there

19:37 gfredericks: klauern: http://clojure.org/special_forms#Special Forms--(let [bindings* ] exprs*)

19:38 klauern: ah, got it

19:38 well, I'm off to read something for a bit ;)

19:38 gfredericks: klauern: have fun

19:39 klauern: I was trying to link to the section on let, in case the whitespace in that link mucked things up

19:39 klauern: ah, yeah, %20 would work to hack around those spaces

19:39 gfredericks: should be easy enough to find it manually

19:40 klauern: http://clojure.org/special_forms#Special Forms--(let%20[bindings*%20]%20exprs*)

19:40 http://clojure.org/special_forms#Special%20Forms--(let%20[bindings*%20]%20exprs*)

19:40 whoops

19:42 Something that I was confused for a while in Clojure was that the terminology used seemed academic. For instance, alot of the time I was thinking "why aren't they just calling that a method", but then I realized that Clojure (and I suppose Lisps in general) have alot of nuance in behavior, so method wouldn't work in some cases, etc.

19:42 Now I'm starting to get a handle on the language a bit better, but it's tricky trying to learn something that has such depth to it compared to OO/Imperative languages

19:44 gfredericks: klauern: my impression is that "method" is an OO word referring specifically to a "function on an object"

19:44 probably it's used more loosely than that most of the time though :/

19:45 klauern: Well, in general I see things like 'lexical binding' and then get confused for a second since it's not easily transferrable to other languages I work with.

19:45 binding in particular

19:45 destructuring is neat and something that opens up a nice world of flexibility

19:45 I'm not even up to learning protocols and multimethods, so it's still a fun ride ahead for me

19:46 pnicholson: Hey, I'm trying to play with overtone and am getting "CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: File"

19:46 gfredericks: do you need to import it?

19:47 klauern: it is fun stuff.

19:47 pnicholson: I don't think so… https://github.com/overtone/overtone/blob/master/src/overtone/helpers/file.clj#L151 is the line is failing on

19:48 klauern: I like the organic nature to it. "Growing a language" and all that

19:49 gfredericks: pnicholson: I don't see File imported at the top, so I'm not sure why that would be expected to work. Does the library have tests you can run?

19:49 klauern: have you seen rich's Simple Made Easy talk?

19:50 pnicholson: gfredericks: file is part of the io package right?

19:50 gfredericks: pnicholson: java.io.File is a java class, and those have to be imported separately from clojure namespaces

19:51 I would expect adding an (:import java.io.File) to the ns declaration at the top of that file would make the error go away

19:51 klauern: gfredericks: That is a good video. He mentions that one slide should be used as a reference for something, but that slide is full of concepts that I'm not even familiar with to know what they are, so I'm trudging along with a book or two and some minor pet projects to get a feel for the language

19:52 pnicholson: gfredericks: hmm….this stuff was demoed at the conj yesterday

19:52 zerokarmaleft: dnolen: have you posted your slides anywhere yet?

19:52 gfredericks: pnicholson: yeah, it sounds like a popular lib, so I'm weirded out a bit

19:52 dnolen: zerokarmaleft: not yet, I'll try to get them added to the conj slide repo soon.

19:53 zerokarmaleft: cool

21:01 alexbaranosky: I'm far enough into installing emacs to realize I suck at it

21:01 I've clone Sam Aaron's emacs files

21:02 I stuck them in the .emacs.d folder

21:03 I couldn't tell for sure if I had done it right so I tried to do something simple (to my mind) which was install a color theme

21:04 I put the color theme .el file into .emacs.d/config/ and tried to do M-x color-theme-tango, to which Emacs replied [No match]... What does no match mean exactly, and have I done something utterly wrong?

21:05 is Emacs somehow not finding the file?

21:08 brehaut: alexbaranosky: im not an expert or anything, but have you done a (require …) for the theme.el?

21:21 alexbaranosky: brehaut: in the color-theme-tango.el file?

21:22 brehaut: in your init.el ?

21:22 alexbaranosky: I'm still learning the whole Emacs ecosystems, so I'm probably missing something obvious

21:22 let me check

21:31 brehaut: seems to be working if I add: (require 'color-theme)

21:31 (color-theme-initialize)

21:31 (color-theme-robin-hood) to the .emacs file

21:31 however, the theme doesn't look like I thought it was supposed to

21:31 I think I hear themes work differently between GUI emacs and terminal Emacs

21:35 duck1123: alexbaranosky: they do look a little different depending on the settings of your terminal

21:36 usually you just have to try them all till you find one that works for you

21:37 alexbaranosky: do most folks use the GUI Emacs or the terminal version?

21:37 amalloy: or modify one you almost-like

21:37 alexbaranosky: I'm fond of that ;)

21:38 duck1123: I'd say that most use the gui if they have it available

21:38 alexbaranosky: amalloy: I used 'macro-do` yesterday

21:38 amalloy: and `juxt`. Thought you'd be proud

21:39 amalloy: *chuckle*

21:40 macro-do is one i try to avoid using - it's tempting to use macros when in fact functions are sufficient

21:41 alexbaranosky: I almost never write macros

21:43 amalloy: alexbaranosky: out of curiosity do you have a link handy for your use of macro-do?

21:45 alexbaranosky: yes. I was cleaning up some Midje code, replacing a few (map (fn []...)) spots with (for [] and ran into a spot where we're generating 10 checkers, let me show you the link

21:46 Last lines of: https://github.com/marick/Midje/blob/master/src/midje/checkers/collection.clj

21:49 amalloy: i see. yes, it's hard to avoid when the underlying form you want to generate is a macro

21:49 btw, you can link to a specific line on github by clicking the line number in the left margin

21:50 alexbaranosky: thx

21:51 hmmm, my dark background theme (tango) comes out with a white background... weird

21:52 amalloy: alexbaranosky: i use tty-dark, if you want to give that a try

21:55 alexbaranosky: let me show you my `juxt`spot: https://github.com/marick/Midje/blob/master/src/midje/ideas/metaconstants.clj#L23

21:58 amalloy: (I'm clearly failing badly at the color theme setup... I have to go back to square one. Don't think it was really working when I thought it was)

22:26 daaku: any vim users know if there's a way do something along the lines of set lispwords+=def* (which doesnt work) to make anything starting with def a lispword?

23:15 i remember running into some debugging macro that logged a form and returned it, anyone know what its called?

23:16 found it: spy

23:57 klauern: When documenting a (defn), is there a preferred format, much like Ruby's RDoc, or Java's Javadoc format?

Logging service provided by n01se.net