#clojure log - Dec 10 2011

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

0:15 lnostdal_: there's something i don't understand .. why does lein deps "sometimes" seem to just go on even though project.clj refers to something it can't find? i mean, it can't find a clojure 1.4 snapshot here now, so instead it seems to add clojure 1.2.0 to lib/ here then just silently continues

0:43 seems the problem is something in enlive .. [org.clojure/clojure "[1.2.0,)"] looks weird

1:01 ambrosebs: where can I find the definitions of clojure.core/gen-interface and clojure.core/gen-class?

1:09 jodaro: Source clojure/genclass.clj:492

1:10 according to clojuredocs.org

1:10 http://clojuredocs.org/clojure_core/clojure.core/gen-class

1:10 Source clojure/genclass.clj:669 for gen-interface

1:22 ambrosebs: jodaro: cheers :)

1:23 amalloy: lnostdal_: "[1.2.0,)" is: "any version at least as high as 1.2.0"

1:24 which is effectively promising it will work with clojure 5.7 - a dubious claim, but one i made myself back before i knew better

1:28 lnostdal_: amalloy, hm, ok .. perhaps it doesn't "understand" 1.4.0-master-SNAPSHOT or something

1:28 amalloy: i don't really know the rules of maven dependency version selection

1:29 lnostdal_: if i change enlive to depend on "1.2.0" .. my project gets the right clojure jar in its lib/ folder

1:29 me neither

1:30 sometimes there's too much java

1:30 ..involved

1:40 skeeterbug: can someone help me out with clojureql?

1:40 i am a bit of a clojure noobie

1:41 Raynes: amalloy, lnostdal: The thing about it is, version ranges are kind of useless. It doesn't matter what you specify, whatever version of Clojure the project depending on you depends on wins.

1:42 Closed version ranges can be useful to document the specific versions that you're capable of working with, but open ended version ranges are just silly.

1:53 notostraca: &(print (apply str (flatten (repeatedly 1 (fn [] (conj (shuffle (concat (repeat 40 "/") (repeat 40 "\\"))) "\n"))))))

1:53 lazybot: ⇒ ////\\//\\//\\\//\\///\\\\\\//\\\\///\//\/\\\\///////\///\//\/\\\/\\\\///\\\\/\/ nil

1:53 notostraca: god I love clojure

2:58 amalloy: notostraca: btw, since you seem to be shuffling stuff: would a lazy shuffle be of any utility to you?

2:59 notostraca: amalloy, I don't know what I would use it for yet, but maybe someday :-)

3:00 mostly I am trying to figure out how to "rotate" a 2D array of slashes and backslashes to become horizontal and vertical lines

3:03 amalloy: you probably want to (a) figure out what that actually means, and (b) come up with an algorithm, before you write any clojure

4:11 notostraca: hmm

4:11 ,doc take

4:11 clojurebot: #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/doc, compiling:(NO_SOURCE_PATH:0)>

4:12 notostraca: ,(doc take)

4:12 clojurebot: "([n coll]); Returns a lazy sequence of the first n items in coll, or all items if there are fewer than n."

4:12 notostraca: so how do I evaluate the lazy sequence? I just don't seem to understand how laziness works in clojure

4:12 ,(doc do)

4:12 clojurebot: No entiendo

4:18 notostraca: amalloy, still around?

4:18 amalloy: indeed

4:18 the point is mostly you shouldn't need to worry about when they get evaluated, of course

4:19 if you care about that, it implies side effects in your code

4:28 notostraca: amalloy, actually I do have side effects, I want to generate some strings randomly, and printing the sequences just gives me LazySeq@abcd78 or some other ID

4:29 I want to only use the first 10 or so strings I generate in the sequence

4:29 amalloy: do you want to generate some strings, or print them? i suspect you don't have any need to print the actual sequence of strings to the console at once

4:30 notostraca: well it is kinda complicated, but I am generating the strings so I can copy them into a text editor and regex them into java code

4:31 anyway, i solved it by only printing at the very end

4:31 and not str'ing a lazy sequence, just conj'ing what I need onto the end of it

4:32 amalloy: notostraca: a good rule of thumb is not to give lazy sequences to side-effecty things. instead, use some side-effect-oriented operation, like doseq, to extract non-lazy values out of the sequence

4:32 notostraca: ah ok

4:32 amalloy: eg, print is side-effecty, and it doesn't like lazy sequences very much. but (doseq [s strings] (print s)) would work

4:33 or, you could use (pr strings)

4:50 notostraca: ok, now I have a list of 2d vectors, each 2d vector a 3x3 box of tile names. I need to concatenate the rows of all the boxes into 3 long rows instead of 10 boxes with 3 rows each

4:51 * notostraca hurt his head thinking

5:37 lnostdal: Raynes, yes, that what i've generally seen; the "end project" gets the vote for what clojure version stuff will actually run under .. but in this particular case, that doesn't happen

6:33 Borkdude: &findfn

6:33 lazybot: java.lang.RuntimeException: Unable to resolve symbol: findfn in this context

6:33 Borkdude: what is the syntax again?

6:33 lazybot: findfn

6:34 lazybot: [clojure.core/cond clojure.core/dosync clojure.core/import clojure.core/prn clojure.core/refer-clojure clojure.core/print clojure.core/with-loading-context clojure.core/newline clojure.core/comment clojure.core/or clojure.core/load clojure.core/shutdown-agents cloj... https://gist.github.com/1454963

6:34 raek: $findfn

6:34 lazybot: [clojure.core/cond clojure.core/dosync clojure.core/import clojure.core/prn clojure.core/refer-clojure clojure.core/print clojure.core/with-loading-context clojure.core/newline clojure.core/comment clojure.core/or clojure.core/load clojure.core/shutdown-agents cloj... https://gist.github.com/1454964

6:34 Borkdude: $findfn 'a 'b 'b

6:34 lazybot: [clojure.core/max-key clojure.core/char-escape-string clojure.core/*clojure-version* clojure.core/min-key clojure.core/char-name-string clojure.core/primitives-classnames clojure.core/merge-with]

6:34 Borkdude: Is there a function in clojure that does this: (fn [a b] b) ?

6:35 I want to use it to swap an atom value to a new value regardless of the old one

6:35 maybe there is an easier way (probably)

6:35 raek: Borkdude: yes: 'reset!'

6:36 cemerick: reset!

6:36 Borkdude: ah

6:37 raek: there's also constantly: (def constantly [x] (fn [& args] x))

6:37 which is kinda like a two-step version of your fn

6:37 *defn

6:38 Borkdude: hmhm, ok

6:39 why do I get a nullpointerexception: (def cmp-prev (let [prv (atom nil)] (fn [nxt] (let [retval (< @prv nxt)] (reset! prv nxt) retval))))

6:39 if I call it like (cmp-prev 1)

6:41 I guess < can't handle nil?

6:48 cemerick: what would it possibly return for (< 6 nil)?

6:48 raek: Borkdude: you should only use reset! when you don't care about the previous value of the atom

6:49 Borkdude: raek: yes, ok

6:49 raek: otherwise you will have a race condition due to the different point of read and write

6:49 Borkdude: cemerick: right

6:49 raek: Borkdude: just make a fn that you pass to swap!

6:49 Borkdude: raek: I don't care about the previous value

6:50 lnostdal_: lein stuck doing apparently nothing again .. gah .. and no output; nothing

6:50 raek: Borkdude: but you use it to compute the return value of the fn

6:50 Borkdude: raek: I can't be sure that this will happen before the reset?

6:51 raek: Borkdude: but what if another thread runs the same code?

6:52 then you can get an interleaving where this happens: thread 1 derefs, thread 2 derefs, thread 1 reset!s, thread 2 reset!s

6:53 and if you want to maintain state within *one* thread you shouldn't use a (global) atom at all

6:53 you can use loop variables in loop/recur

6:53 Borkdude: raek: I just want to build a function with some memory

6:53 raek: (computational state, that is)

6:53 Borkdude: so I can use partition-by over a sequence with this function

6:54 raek: Borkdude: you could also use a thread local var in this case

6:54 Borkdude: can I do a closure over a var?

6:55 raek: well, in that case you would just use binding to get your own var, and then set! and deref to access it

6:55 Borkdude: there is probably a purely functional way of solving the problem

6:56 Borkdude: raek: I am realizing this

6:56 raek: Just experimenting, I don't use atoms often

6:57 raek: if the standard library fuctions don't allow you to "get the right values to the right places", you should probably fall back to a simple loop/recur

6:58 atoms are made for dealing with concurrency and not really for maintaining values in stateless computations

6:59 Borkdude: raek: so this is actually not a good solution: http://stackoverflow.com/questions/8442524/writing-an-accumulator-function-in-clojure

6:59 ?

7:09 not a thread-safe solution anyway then

7:23 is there a function that does this? (select max count [[1 1] [1 1 1] [1]]) => [1 1 1]) ?

7:25 like this: (reduce (fn [a b] (if (> (count a) (count b)) a b)) [[1 1] [1 1 1] [1]])

7:28 cemerick: ,(max-key count [1 1] [1 1 1] [1])

7:28 clojurebot: [1 1 1]

7:28 Borkdude: great

7:28 ,(doc max-key)

7:28 clojurebot: "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest."

7:29 Borkdude: why is this called max-"key"?

7:30 cemerick: can't say

7:49 raek: Borkdude: yes. that was not intended as an example of how you should do it.

7:50 hrm. I misread the example. it is not intended as an example of how to have an accumulator in a computation

7:50 _ulises: ahoy!

7:51 raek: but it is how you would make a function that modifies a globally accessible atom

7:52 which you don't need when you just want to remember a previous value

7:52 (in a computation)

7:53 Borkdude: finally solved this 4clojure problem 53, fully functional ;)

8:24 _ulises: anybody here interested in advising me on literate programming?

8:38 Somelauw: ,(apply max-key count [(([1 0]) ([0 1] [1 2] [2 3]) ([3 0]) ([0 4] [4 5] [5 6])))

8:39 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Unmatched delimiter: )>

8:39 Somelauw: ,(apply max-key count [(([1 0]) ([0 1] [1 2] [2 3]) ([3 0]) ([0 4] [4 5] [5 6]))])

8:39 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector>

8:42 Somelauw: ,(apply max-key count ['(([1 0]) ([0 1] [1 2] [2 3]) ([3 0]) ([0 4] [4 5] [5 6]))])

8:42 clojurebot: (([1 0]) ([0 1] [1 2] [2 3]) ([3 0]) ([0 4] [4 5] [5 6]))

8:44 Somelauw: Sorry, I wanted to paste a problem that I have, but that appears harder than I thought. I will post the problem later.

8:44 Okay I figured it out. Here is the problem:

8:47 Okay, I think I figured it out myself. Nested lists can be tricky sometimes.

9:20 Wild_Cat: hmm. webnoir.org is down.

9:56 Borkdude: Is it possible to just run one test you defined with deftest?

9:59 Somelauw: I know how to find the longest increasing subseq in a list.

9:59 Borkdude: Somelauw: I solved that one as well

10:06 How do you do this with paredit: (| (expr1) (expr2)) => (expr1) (expr2)

10:06 I keep running into this one

10:07 _ulises: Borkdude: I do it with M-up arrow

10:08 but the cursor must be exactly where you put it, otherwise hilarity ensues

10:08 Borkdude: _ulises: tnx

10:08 _ulises: np

10:36 Borkdude: Is there also a transpose like ("a"| "b") => ("b" a")?

11:29 ambrosebs: which Java classes are implicitly imported in a Clojure namespace?

11:30 jodaro: i think it might be just java.lang

11:30 but i have no proff

11:30 or proo

11:30 f

11:30 crap

11:30 more coffee needed, apparently

11:30 ambrosebs: ,Character

11:30 clojurebot: java.lang.Character

11:30 gtrak`: i think for java it's just java.lang

11:31 ambrosebs: any idea where this happens?

11:31 the imports?

11:31 gtrak`: well, for java source it's a compiler thing

11:32 if you got the clojure source, do a grep java.lang :-)

11:32 ambrosebs: sure

11:34 jodaro: there are a bunch in clojure/lang/LispReader.java

11:34 but i'm not sure if thats what makes them available directly in clojure

11:34 gtrak`: yea, those are imports fot the actual java

11:35 how about the asm commons Method.java?

11:35 ambrosebs: right, that makes sense

11:36 gtrak`: ah, no, that's not it

11:37 ah yea, check it out, sb.append("java/lang"), I'm guessing that's related

11:37 jodaro: could it be that they don't have to be explicitly imported by clojure?

11:38 gtrak`: take a look at Method.java https://github.com/clojure/clojure/blob/master/src/jvm/clojure/asm/commons/Method.java specifically the 'map' function

11:40 I'm guessing that both the reflection api and the ASM lib use that as a default, it doesn't look like clojure's doing anything special itself

11:40 ambrosebs: excellent :) now I just need a seq with all java.lang.* class names ...

11:47 jodaro: http://snippets.dzone.com/posts/show/4831

11:47 not sure if thats what you want

11:47 ambrosebs: jodaro: :) will try

11:47 jodaro: you want to find it dynamically?

11:48 or just have a static sequence of them

11:48 ambrosebs: the latter will do fine.. how volatile is java.lang?

11:48 I'm guessing not very

11:48 jodaro: heh probably not

11:49 ambrosebs: I'll just do it statically, seems less error prone

12:01 TimMc: WTF, is enlive removing my doctype?

12:02 gtrak`: ambrosebs, even if it changes, they'll only add stuff

12:06 ambrosebs: grak`: yea, it's part of the language now

12:06 duck1123: yeah, java seems to keep depreciated methods around for quite a while

12:06 gtrak`: duck1123, it'll never go away

12:07 nothing can get removed or even changed, maybe code relies on the broken semantics

12:08 but it seems with clojure we have a way out :-)

12:09 duck1123: that's really a shame though. You would think that after a few years and several versions of having things deprecated, it would be safe to remove them. That's one of Microsoft's biggest problems

12:10 gtrak`: it helps the platform at the expense of the language

12:11 I think it's the right thing to do

12:11 java was started as a high-level lang, but now it's relatively low-level compared to the other stuff

12:16 TimMc: duck1123: Having the @Deprecated annotation helps.

12:16 You don't get that in C++, I think.

12:17 Deprecating *language* features, on the other hand -- that's tricky.

12:18 gtrak`: C++ is really really weird :-)

12:25 ambrosebs: is there a version of resolve that doesn't throw an exception if a class cannot be found?

12:30 ssideris: hello

12:30 does anyone use lein-multi?

12:31 I'm running "lein multi test" and apart from the dependency sets that I have defined, it does run the tests against the "base" set of dependencies

12:32 is that because I have a dev-dependencies as well?

12:45 ambrosebs: dnolen: https://gist.github.com/1455735 :)

13:32 seertaak: hi everyone. really stupid question: how can I make functions defined in a file (with a (ns ...) clause at the top) available to a REPL which loads the package?

13:32 Loads the package via (import my-package) , by the way

13:38 chewbran`: sweet

13:39 seertaak: Please ignore my question, I've worked it out myself.

14:19 alexbaranosky: amalloy_, you there? I'm curious about possibile the midje git repo trimming

14:32 daniel__: im trying to use korma but is there not a way of defining a database schema? should i look to the jdbc driver docs for doing this? i need some way of defining the tables, otherwise ill forget what i need

14:40 alexbaranosky: daniel__, there's a library whose name escapes me that is good for setting up the schema

14:40 don't think you need to use jdbc driver

14:43 daniel__: alexbaranosky: ok, let me know if you remember

14:43 i'll have a search

14:46 alexbaranosky: lobos? https://github.com/technomancy/lobos

14:47 alexbaranosky: daniel__, lobos sounds like it

14:47 daniel__: ok :)

14:48 alexbaranosky: good luck

14:48 gtrak`: ambrosebs, is that what I think it is?

14:49 TimMc: alexbaranosky: What I meant about licensing was, can I get your OK on using the EPL for the seqs repo?

14:51 You're a slippery one to pin down!

14:51 alexbaranosky: TimMc: sounds good to me

14:52 is there something I need to do?

14:52 TimMc: I'm using emacs over here... it is truly painful

14:53 TimMc: haha, OK

14:53 gtrak`: TimMc, consider printing out the cheat sheets

14:53 i mean alexbaranosky

14:53 TimMc: alexbaranosky: Nah, just wanted your permission.

14:54 alexbaranosky: gtrak`, I've got them up in my browser, but printing is a good idea

14:54 gtrak`: alexbaranosky, circling the ones I look for often helped me a lot

14:54 devn: hello all

14:54 alexbaranosky: hi devn

14:54 devn: how goes the clojuring?

14:55 gtrak`: alexbaranosky, though I had to do some image processing on the paredit cheat sheet to get it to look good

14:55 alexbaranosky: I recently made it so that Midje tabular doesn't require ?'s which I think is pretty sweet

14:56 daniel__: does anyone know if i can use the connection that korma makes instead of also connecting via lobos?

14:57 Raynes: alexbaranosky: https://skitch.com/discipleraynes/gxj72/clojure don't diss the Emacsen.

14:58 gtrak`: Raynes, is that ubuntu mono? <3

14:59 Raynes: gtrak`: Certainly not

14:59 gtrak`: ah, what font is it then?

14:59 Raynes: DejaVu.

14:59 gtrak`: ah

15:00 alexbaranosky: Raynes, no dissing here, just painful switching from Intellij where I'm really comfortable. -- I want to see what Emacs can do that isn't possible in Intellij, but so far the paradigm shift is heavy duty

15:00 Raynes: alexbaranosky: I understand.

15:00 alexbaranosky: do any of you all use stuff like ECB for Emacs?

15:01 Raynes: Emacs is an acquired taste. If you give up before you acquire it, you may never understand why it is so amazing.

15:01 clojurebot: 'Sea, mhuise.

15:01 alexbaranosky: one major thing I miss when in Emacs or Vim is the ability to have a bird's eye view of all the files in a project

15:02 kumarshantanu: daniel__: it seems both of them use the same map structure

15:02 probably they get passed to clojure.java.jdbc

15:02 Tharem: Hi there. I'm trying to require a namespace in the slime REPL, but it's giving me an error: nth not supported on this type: Class. When invoking the program using lein run, it doesn't give a problem. What could be wrong?

15:03 gtrak`: alexbaranosky, you can just use M-x grep to look for stuff or C-x C-f to navigate, it gives you lists

15:03 it might be rgrep

15:04 Raynes: alexbaranosky: Chances are, there is elisp to do what you want.

15:04 Tharem: There is also a package that shows the possible completions in the minibuffer (I pulled it in via emacs starter kit). That's quite usefull when switching between buffers

15:04 alexbaranosky: Tharem, the completions thing is nice, I have it too

15:04 dnolen: Tharem: how are you trying to require it?

15:04 alexbaranosky: but so far.... none of this is better than Intellij

15:05 Raynes: alexbaranosky: Does it give a tree view of the entire project?

15:05 alexbaranosky: I want to know the stuff that is actually an improvement over it, not just a different approach to mostly the same thing

15:06 Raynes: Well, the defining feature of Emacs is really how extensible it is. If it doesn't do exactly what you want, you can write Elisp code to make it do exactly what you want. Doesn't matter if what you want is genius or insane, you can do it with a little elispfu.

15:06 Tharem: Alexbaranosky, I use (require RogueLike.core). RogueLike.core is also the namespace defined at the top of my file

15:06 alexbaranosky: Raynes, Intellij? yeah. 'project view', just like a little tree-style file browser on the side of the screen... Emacs can have it too, but most don't use it

15:07 Raynes: As such, people have written insane things in Elisp that run in Emacs. ERC is an example. A full-on IRC client in Emacs that is a joy to use and navigate even with several networks and over a dozen channels.

15:07 None of it slows Emacs down either.

15:07 devn: could someone please use my nick in here?

15:07 Raynes: I've got a twitter client in a buffer two clicks left of here.

15:07 alexbaranosky: Raynes, speed is nice, IDEs can bog down sometimes

15:07 Raynes: devn: Hi.

15:07 Tharem: devn: sure, but why?

15:07 devn: perfect. thanks.

15:07 TimMc: Tharem: Sounds like there's a compile error in whatever you're require'ing.

15:07 devn: i lost my hilight window and needed to create a new one and wanted to make sure i had set it up correctly

15:08 Tharem: Then why does it run through leiningen?

15:08 Raynes: alexbaranosky: Now, none of the last two things I've mentioned have anything at all to do with editing, but my point is to demonstrate the power and flexibility of having an editor configured in a Lisp.

15:08 Tharem: Any errors that don't show up when running through leiningen?

15:08 TimMc: hmm

15:08 alexbaranosky: Tharem, what were you talking about regarding RogueLink? I didn't understand that.

15:08 Raynes: A great thing, for example, is that if I didn't have ERC loaded when I started Emacs up, I could always load/reload it later. Emacs is a big Lisp box. A giant sophisticated repl.

15:09 Tharem: Nothing special, that's just the name of the namespace

15:09 I've defined it using (ns RogueLike.core (:import [imports ommitted]))

15:10 alexbaranosky: Tharem, so its a macro for that for you?

15:11 TimMc: Tharem: quote the namespace: (require 'RogueLike.core)

15:11 and don't do :require, use require

15:12 Tharem: XD Yeah now it returns nil. I'm assuming that's ok?

15:12 TimMc: yep!

15:12 Tharem: Also, why shouldn't I be sing :require in the ns macro?

15:12 alexbaranosky: Raynes, thanks for your thoughts on Emacs

15:12 TimMc: (:require foo) in ns, (require 'foo) from REPL. :-/

15:12 Tharem: using*

15:13 Oh ok. Thanks a lot guys

15:13 TimMc: It's inconsistent, but there it is.

15:14 Tharem: I don't think it's inconsistent. (require foo) is a function call, :require is an argument to the ns macro

15:14 TimMc: Yeah, but it trips a *lot* of people up.

15:14 Anyone who has written a Lein plugin: How hard do you suppose it would be to create a "n00b" plugin for Leiningen that catches common errors?

15:15 Raynes: Tharem: The fact that you're not screaming "What? That's bullshit!!!" right now means you have an excellent future with Clojure. Welcome to the team.

15:15 alexbaranosky: TimMc, such as?

15:15 Raynes: TimMc: You're looking for a lint.

15:15 TimMc: alexbaranosky: Like `(:require SomeSymbol) => nth not supported by Class

15:15 Raynes: http://community.haskell.org/~ndm/hlint/

15:16 alexbaranosky: yeah, sounds like there are two pieces: a Clojure lint, and a lein plugin that just runs the lint on the project

15:16 Tharem: Raynes: Thanks. I actually have some experience with common lisp (in b4 HERETIC :P ). I'm still smacking my forehead for not thinking of using a few quotes XD

15:17 TimMc: alexbaranosky: A REPL-oriented lint, specifically.

15:18 Tharem: TimMc, what you're actually suggesting is to improve the error handling. I seem to recall that Java puts some limits on how error handling goes

15:19 TimMc: Tharem: Better error handling would be nice (although calling (pst) after an error on the REPL is not so bad), but this would specifically look for common mistakes and suggest tips to the user.

15:19 A REPL Clippy, if you will.

15:19 * TimMc ducks

15:22 Tharem: One way would be to have function and macro calls routed through a function that checks for common mistakes and tosses a readable error message if it detects a common mistake

15:22 That wouldn't immediately dump you into the Java debugger

15:23 TimMc: Well, I wouldn't want to prevent normal execution.

15:23 For one thing, this would *not* be a conservative checker, so it might get some stuff wrong.

15:24 Tharem: You don't need to prevent normal execution. What you could do is check the input to detect a possible error, run it, then catch any errors and give hints

15:24 TimMc: (:require foo) is a valid statement if (def foo {:require true})

15:24 I think after execution is the time to do it, since then you can see whether it produced an exception.

15:26 Tharem: Yes but after execution the input is gone, so you have to cache the input to detect possible errors. You can't tell the difference between "nth not supported by class" caused by a wrong load or by calling nth on something that isn't a sequence

15:26 alexbaranosky: hey Raynes, what is the one thing you wish Midje had when you use it?

15:26 duck1123: focus

15:26 Raynes: alexbaranosky: Less, so that I wouldn't feel bad when I inevitably end up using only a subset of what I actually should be using because I'm too lazy to learn the whole API.

15:27 alexbaranosky: duck1123, was that directed at me? Could you elaborate?

15:27 Raynes: duck1123: Did we just say the same thing?

15:27 alexbaranosky: I think so!

15:27 TimMc: Tharem: I guess it depends on how the REPL works.

15:27 alexbaranosky: interesting. I wonder how we could make less?

15:28 Raynes: I was actually just kidding.

15:28 I don't have anything in particular that I'd like right now.

15:28 alexbaranosky: are there features that could be collapsed into one?

15:28 duck1123: alexbaranosky: I know the question wasn't directed at me, but I wish there was an easy way to restrict down to only some test. Like RSpec's focus

15:28 Raynes: Right, I was wondering about ways to run only specific tests myself.

15:28 alexbaranosky: so you want a way to run just on etest?

15:28 TimMc: OK, I have come to a conclusion about seqs and colls: They are abstractions, and it is not possible to determine which abstraction a particular value "belongs" to.

15:29 alexbaranosky: is that what you meant by focus?

15:29 duck1123: alexbaranosky: yes

15:29 TimMc: You can only coerce a value into the abstraction you want, you can't inspect it to see what it already is.

15:29 alexbaranosky: duck1123, yeah, I want that too :)

15:29 Raynes: Since tests aren't named, we don't have a way to refer to them.

15:29 alexbaranosky: do you know you can run just a single ns?

15:30 Raynes, we could conceivably do something with metadata... there's an idea floating around around the idea of tagging groups of facts, then being able to run that tagged group

15:30 lein midje org.alexbaranosky.justthisonens

15:31 Raynes: alexbaranosky: Can you give me input on how I did these tests here: https://github.com/Raynes/tentacles/blob/master/test/tentacles/users_test.clj

15:32 alexbaranosky: Raynes, sure thing

15:32 Raynes: alexbaranosky: In particular, I'm not sure if my grouping of assertions is nice or not.

15:32 duck1123: the namespace reduction helps, but sometimes you want to just focus on a specific test, and don't feel like autotesting or testing in a repl

15:32 Raynes: alexbaranosky: I grouped assertions about certain 'types' of API calls. Felt good, but I'm not sure if I've done something terrible.

15:33 alexbaranosky: funny enough, I've never seen `has` :D

15:34 Raynes, I don't think anything there is terrible. I have a different style when I test, but I think it is mainly a stylistic thing, where I would be more explanation of what each fact is confirmig in the doc strings... let me show you a project of mine with a lot of midje facts .........

15:35 Raynes: The users and keys facts there are what I was unsure about. I primary started grouping these things because I needed to wrap several assertions in the same let so that I could let an API call and then test that result and use it in the other assertions as well. I wasn't sure what would happen if I, for example, wrapped several facts in a let and an exception occurred outside of the let itself.

15:35 duck1123: so are you guys using lein-midje to run your tests, or lein test? I had some issues with lein midje and am still wrapping all of my facts in deftests

15:35 Raynes: Er, outside of a fact itself.

15:36 alexbaranosky: Raynes, example of more my style https://github.com/AlexBaranosky/EmailClojMatic/blob/master/src/ecm/fact/reminder_parsing_facts.clj

15:36 Raynes: duck1123: I'm using lein test. No particular reason. I'll probably use lein midje later.

15:36 alexbaranosky: Raynes, grouping facts is good

15:37 duck1123, I use lein midje -- what were your issues?

15:38 duck1123: alexbaranosky: IIRC, it was mostly because I was using 1.3 before it supported 1.3, and had to patch my own version of midje

15:39 Here's an example of how I structure some of my tests: https://github.com/duck1123/jiksnu/blob/master/test/jiksnu/actions/activity_actions_test.clj (not as much 'provided' as there should be yet)

15:39 daniel__: does anyone use lobos? i cant understand why i need to define a schema and migrations... cant i just use migrations? is there an alternative to lobos that people use?

15:40 alexbaranosky: duck1123, is `testing` a clojure.test thing?

15:41 duck1123: yes. I'm using it as a poor man's "context" in the BDD sense

15:42 Raynes: alexbaranosky: For example, in my keys fact, I wrap my assertions in a let that binds 'ks' to an API call that returns the ssh keys a user has, and then that data is used in the following assertions. If I made each of those assertions (which are assertions about entirely different API calls) individual facts, I'd have to wrap them in a let like so: (let [l (Integer. "a")] (fact l => 3)). Now, the previous code will fail, but not in a

15:42 pretty way. The error happens outside of a fact so I just get an ugly exception slathered on my terminal. And that is the extremely long explanation about why I grounded those assertions under one fact.

15:42 alexbaranosky: duck1123, gotcha... you can just use raw strings and Midje will ignore them

15:42 gtrak`: daniel__, you could probably do it yourself, I've written one in java in a couple hours. all you need is a db table to keep track of changes, and a migrate-up sql runner thingy

15:42 Raynes: s/grounded/grouped/

15:43 duck1123: I've been thinking I want to write an actual "context" macro for midje that will define the grouping like that but also allow me to attach backgrounds to that block in a nice way. Just haven't done it yet

15:43 alexbaranosky: Raynes, let me think about that

15:44 daniel__: gtrak`: i could probably do it myself but im sure someone's already done it

15:45 gtrak`: yea

15:45 duck1123: Raynes: what if you puth that let in a around background?

15:45 gtrak`: lots of wheels reinvented all the time :-)

15:46 duck1123: Raynes: ie. https://github.com/duck1123/jiksnu/blob/master/test/jiksnu/model/webfinger_test.clj#L16

15:47 alexbaranosky: Raynes, I've thought about it and I think what you're doing is fine. If I think of a cleaner way, I'll let you know

15:47 mindbender: (fact (let [l (Integer. "a"] l) => 3)

15:48 gtrak`: daniel__, http://budu.github.com/lobos/doc/uberdoc.migration.html

15:49 alexbaranosky: duck1123, Raynes yeah there might be something there with background or around... I'd dig in the docs in the wiki

15:49 Raynes: Digging.

15:51 alexbaranosky: Raynes, looks like `around` is what you want: https://github.com/marick/Midje/wiki/Setup%2C-Teardown%2C-and-State

15:51 Raynes: alexbaranosky: Yeah!

15:51 duck1123: Thanks! :)

15:51 Now I can FACTor this stuff out. ;)

15:54 duck1123: One gotcha, multiple (background (arounds)) will overwrite each other. I have a global around that I keep in a test helper macro, that means that if I then want a per-namespace around, I need to use against-background, which indents all my tests

15:55 daniel__: thanks gtrak`

16:05 Raynes: duck1123: This is working brilliantly. Thanks for pointing that out.

16:06 kumarshantanu: daniel__: https://bitbucket.org/kumarshantanu/lein-lb/overview

16:06 duck1123: Raynes: no problem

16:06 Raynes: kumarshantanu: Do you use bitbucket to prove you're a rebel?

16:07 kumarshantanu: Raynes: I used to maintain my own mercurial repo once upon a while, then bitbucket was my consequential refuge

16:17 duck1123: I have to say, I'm enjoying the little bit of color in my midje test results now.

16:17 alexbaranosky: duck1123, awesome :)

16:19 is there a way to set the REPL to pretty-print all output?

16:38 TimMc: alexbaranosky: Maybe a set! on one of those print vars?

16:40 Hmm, I'm thinking of clojure.pprint

16:40 Raynes: alexbaranosky, duck1123: https://github.com/Raynes/tentacles/blob/master/test/tentacles/users_test.clj

16:42 daniel__: thanks kumarshantanu

16:45 TimMc: alexbaranosky: You could have your REPL always pull in clojure.pprint/pp. Then you can write (pp) any time you want to pretty-print the last result.

16:46 Magnars: I just watched Rich doing his Simple made Easy talk. It was amazing. Anyone link to more videos/posts in that vein?

16:48 TimMc: Magnars: "Are We There Yet?" is a pretty good one.

16:49 Magnars: TimMc: Excellent, thanks. Loading it up right now. :-)

16:50 TimMc: Magnars: It is more foundational -- pre-Clojure stuff.

16:51 Magnars: TimMc: Sounds good. I'm very intrigued by his thoughts on state, time and complexity.

16:53 djhworld: does the clojure standard library function for flipping the arguments to a function? (like 'flip' in haskell)

16:53 I've only managed to come up with this

16:53 (defn flip [f & args]

16:53 (apply f (reverse args)))

16:54 but I was just wondering if there's one already out there

16:55 alexbaranosky: djanatyn, not in the standard library

17:03 duck1123: I use a macro that log the pprinted result of the wrapped code. That handles all my desires to see stuff pprinted

17:09 Tharem: I've got a question about building trees in clojure. I've got a record that keeps some data around and can either point to nothing, one element or two other nodes. Now I want to code a function to add nodes to the tree, but of course assoc returns a new node instead of altering an existing one. Does that mean I have to use assoc to rebuild the entire tree or am I missing a shortcut?

17:15 duck1123: Tharem: you would either want to return a new tree, or update an external ref. (prefer the first)

17:15 Clojure's data structures to make it way more efficient to return a whole new value than in other languages

17:15 Tharem: Yeah I get that. What I'm wondering about is building the new tree. Do I to use assoc on every element of the tree or is there a shortcut.

17:16 wiseen: Tharem, update-in ?

17:16 duck1123: check out assoc-in and update-in

17:17 Tharem: Thanks. Looks like those where the functions I was looking for. Will they return a new tree?

17:17 duck1123: yes

17:17 Tharem: OK nice

17:18 duck1123: by "tree" are you talking maps of maps, or is this some other data structure

17:18 TimMc: &(update-in {:a [0 1 2] :b 6} [:a 1] * 30)

17:18 lazybot: ⇒ {:a [0 30 2], :b 6}

17:19 Tharem: It's essentially a map of maps. I've got a record that can point to two other records of the same type

17:19 TimMc: Any `associative?` data structure will do.

17:19 accel: Clojure likes immutable data right. Suppose I am writing a WYSIWYG editor; with nested components. How do I do updates to the document without recreating the entire document?

17:19 Tharem: The exact definition is (defrecord node [x-min y-min x-max y-max content split]). Content can either contain an element or a set of two nodes

17:20 TimMc: Tharem: You can access record fields using keywords.

17:21 accel: It's a tree of maps and records and other associative data structures. Refer to the conversation Tharem is in right now. :-)

17:21 accel: so when I update a piece

17:22 wiseen: accel, you use one of "update" functions on the object and clojure returns a "new" object that *shares* all unmodified data with previous object

17:22 accel: is it O(n) time, or O(log n) time?

17:23 wiseen: ah, so clojure does all this under the scene for me

17:23 TimMc: accel: Bonus: The old versions can be safely stored in an undo buffer.

17:23 and they'll share structure, to keep memory down.

17:23 accel: x.update(k, y) = "create new x', with x'[k] = y" ?

17:24 TimMc: something like that

17:26 alexbaranosky: 32-bit vector trie rings a bell

17:26 wiseen: accel, http://www.innoq.com/blog/st/2010/04/clojure_performance_guarantees.html

17:27 TimMc: accel: This app I wrote <https://github.com/timmc/CS4300-HW3/&gt; stores the entire program state as an associative data structure (maps, vectors, and records) and keeps undo and redo buffers of those values.

17:27 I could also have stored the GUI state in there, which would have an interesting (probably unwanted) effect.

17:28 tmciver: TimMc: using slime/swank yet?

17:28 TimMc: haha, nope

17:28 accel: wiseen: are the columns off by 1 (i.e. should e shifted to the right by 1)

17:28 tmciver: TimMc: I just discovered that the slime-interrupt we talked about is bound to C-c C-c. Awesome.

17:28 TimMc: Haven't been doing algorithmic stuff, though.

17:28 nice

17:28 wiseen: accel, yeah :)

17:29 tmciver: TimMc: Do you ever take a break from irc? Jeesh!

17:29 wiseen: it's not my site I just found that recently - I think it answers your questions

17:30 tmciver: TimMc: how am I supposed to keep up when you're here all the time?

17:30 Tharem: Hmm, so if I want to use update-in or assoc-in, I need to know the keys needed to get to the right node beforehand right? Or can I use a function that traverses the tree in some way, for example via a lazy sequence?

17:31 TimMc: tmciver: I keep my IRC window on all workspaces, so I chime in when there's something interesting.

17:31 Tharem: That's right, you need to know the nature of the data structure.

17:31 alexbaranosky: TimMc, and there's almost always something interesting

17:31 TimMc: yup

17:31 tmciver: TimMc: I got my recursive hex-printing function working but I'm having a lot of trouble doing it non-recursively.

17:32 alexbaranosky: tmciver, use a loop

17:32 TimMc: Tharem: Wouldn't be hard to write something that recurses in a more complicated way.

17:32 Tharem: Yeah, I'm thinking of that too

17:32 tmciver: TimMc: the non-recursive way seems like it should have an elegant functional solution but I can't get my head around it yet.

17:33 TimMc: tmciver: What's wrong with loops? :-)

17:33 alexbaranosky: is it online where I could see it?

17:33 tmciver: alexbaranosky: hold on

17:33 TimMc: gist that sucker

17:34 accel: wiseen: it's very helpful; thanks!

17:34 I have a structure that is equivalent to a HTML DOM tree. It's being constantly updated. What is the right clojure way to store it?

17:35 alexbaranosky: accel, a map most likely

17:35 Tharem: how is it being updated?

17:35 TimMc: accel: Store the top-level value in a ref.

17:35 accel: dom elements change

17:35 wiseen: accel, can you be a little more vague please, I can still get a hint of your problem :)

17:36 tmciver: TimMc: alexbaranosky: https://gist.github.com/1456800

17:36 alexbaranosky: wiseen, good one, you made me laugh there

17:36 Tharem: No, I mean are you calling an update function every time, does it watch some value, is a thread sending it updates?

17:36 kumarshantanu: accel: perhaps either a transient vector or atom/ref of a vector, depending on where you want to use

17:36 tmciver: I started a looping version but it's a mess.

17:37 alexbaranosky: tmciver, I thought you said it was recursive?

17:37 that version is looping

17:37 tmciver: alexbaranosky: isn't it? It uses loop/recur

17:37 alexbaranosky: <<<loop>>> :)

17:38 loop/recur is the only way to loop in clojure

17:38 Tharem: You could use trampoline

17:38 That can also be used for loops

17:38 alexbaranosky: well I guess maybe like doall or something

17:38 tmciver: alexbaranosky: I wanted to come up with an equivalent version that uses some combination of map/apply or some sort.

17:38 TimMc: tmciver: You want to print ab cd ef gh\nij kl mn...

17:39 tmciver: Yes. 16 bytes per line, with a space between pairs of bytes.

17:40 Tharem: hmm, doesn't clojure have a return keyword? I'm writing a function that's basically a long cond and it first needs to check a condition and return nil if the condition fails. Do I need to wrap the whole cond in an if-clause?

17:40 accel: wiseen: I have this idea in mind; I think it's turing complete, and thus can be written up in Clojure. However, I'm not sure where to start.

17:40 tmciver: TimMc: (with 2 spaces after 4 byte pairs.

17:40 TimMc: that's what that version does.

17:40 accel: Let me rephrase my question. Suppose you're trying to write something like MS Word in Clojure, i.e. a WYSIWYG editor; what would be the right way to store the state of the documnet (i.e. the text, the nested structure of the text, etc ...)

17:40 wiseen: ^is that better?

17:43 TimMc: accel: I also recommend using a data structure called a "rope" for any long strings of text.

17:43 Tharem: I'm not exactly sure of what you'd have to store but I'd go with nested maps. You can use watches to keep the GUI up-to-date and use normal map operations to update the maps.

17:43 TimMc: tmciver: Yeah, it can probably be done as a one-liner.

17:43 accel: There's a Java library for it. Ropes are persistent data structures, by the way.

17:44 kumarshantanu: map entries are not ordered I think(?)

17:44 Tharem: They are if you use an ordered map ;)

17:44 TimMc: vectors are ordered, and can contain maps

17:45 Tharem: But if you need your stuff ordered and have no need to access them via keywords, vectors or lists would also work

17:57 kumarshantanu: tmciver: are you still looking for a non-loop solution for the snippet you gist'ed?

17:57 TimMc: Tharem: Regarding `return`, no, I don't know of a bail-out mechanism.

17:58 Tharem: Oh, I've found a way around it already, but thanks anyway.

17:58 TimMc: I've seen one written in Scheme with call/cc. :-P

17:58 tmciver: Can you provide an example output?

18:00 tmciver: kumarshantanu: yeah, I'm working on it but if you want to take a crack feel free.

18:00 TimMc: yep, hold on.

18:02 TimMc: tmciver: Data generator: (byte-array (take 20 (repeatedly #(byte (- (rand-int 256) 128)))))

18:03 tmciver: TimMc: updated gist: https://gist.github.com/1456800

18:03 TimMc: Yeah, that's going to require 3 partition or partition-all calls.

18:04 tmciver: TimMc: for generating random binary data? Nice.

18:06 Gotta go for a few minutes. Be back soon.

18:08 kumarshantanu: tmciver: I posted a comment with a snippet

18:09 TimMc: nice

18:11 It does use flatten though, which is slightly squicky.

18:12 I also prefer \space -- it is less visually magical.

18:13 kumarshantanu: TimMc: +1 @ \space

18:13 TimMc: I guess there's no harm in flatten when you *know* your data.

18:13 Tharem: Anyone got a good resource to learn about macros in clojure? I'm only familiar with Common Lisp macros and I have a hard time finding out how and where they differ

18:14 TimMc: Tharem: Some of that knowledge lives in http://clojure.org/reader

18:17 Tharem: If you find a good post on the read vs. compile vs. eval stages of Clojure, I'd love to see it.

18:17 kumarshantanu: Tharem: TimMc: `The Joy of Clojure` describe macros and quoting quite nicely

18:17 TimMc: and of course http://clojure.org/lisps is good to review periodically.

18:18 kumarshantanu: I guess some other books do a good job too, but I don't remember

18:18 TimMc: kumarshantanu: Ah, I think I bought that. I should read it. >_<

18:18 Tharem: That's probably a bit deeper than I'm looking for right now, all I'm trying to do is write a let-variant of cond XD

18:19 TimMc: Tharem: ` is syntax-quote, ~ is unquote, ~@ is splicing-unquote, foo# is a gensym. :-)

18:19 kumarshantanu: Tharem: This might help -- http://java.ociweb.com/mark/clojure/article.html#Macros

18:19 Tharem: Kurman, yeah I'm looking at that right now

18:19 Also screw me, there's a clojure "port" of practical common lisp. If there's one book that's a good introduction it's that

18:20 TimMc: kumarshantanu: After trying to write something without flatten, I think you were right to use it.

18:20 too many (map (partial apply str) ...)

18:22 kumarshantanu: TimMc: A clever way to avoid flatten is to convert to string at every step, so as to give up laziness

18:22 TimMc: I tried that, it was ugly. Maybe I need to try harder.

18:23 Tharem: Oh joy, looks like I'm going to have to write a recursive macro :)

18:26 TimMc: Tharem: Want to gist the surface and expanded forms?

18:34 tmciver: kumarshantanu: Very good. Thanks!

18:35 kumarshantanu: interpose, I forgot about that one. Makes things much easier, I think.

18:36 TimMc: tmciver: A close cousin of interleave.

18:37 devn: anyone here use clojurecheck?

18:38 http://kotka.de/blog/2010/06/ClojureCheck_is_back.html

18:38 tmciver: TimMc: yes, another good one. This is why I come here, to be reminded of gems like those.

18:38 Tharem: Hmm, what's wrong with the following macro? http://pastebin.com/GJNvdash. It's giving me the following error: if-let requires a vector for its binding

18:38 TimMc: tmciver: Look at the source on http://clojuredocs.org/clojure_core/clojure.core/interpose

18:39 Tharem: Have you tried macroexpanding it?

18:39 kumarshantanu: Tharem: the form is not quoted!

18:39 alexbaranosky: I'd love it if GitHub allowed people to upvote issues

18:39 Tharem: It won't even accept the definition. And before you ask, I see I forgot to add a # to the first rest. That doesn't affect the result

18:40 Hmm, the form isn't quoted? which one?

18:40 alexbaranosky: I never know which feature to work on next... Sometimes it is hard to tell which features people care most about

18:40 TimMc: Tharem: gensyms are only valid inside syntax-quote

18:40 Tharem: oh... Good point

18:40 Let me test it without that

18:40 TimMc: I think they are, at least!

18:40 Tharem: Hmm, removing the #'s doesn't change a thing

18:41 tmciver: TimMc: I didn't get the (drop 1 . . . part but it's to get rid of the first separator.

18:41 TimMc: tmciver: Correct. I tried making my own interpose, but I couldn't figure out how to get rid of the last separator -- the answer was to start with the separator!

18:42 tmciver: TimMc: couldn't you use drop-last?

18:42 TimMc: tmciver: Not as fun.

18:43 (Probably less efficient.)

18:43 Tharem: You are unquoting before getting to the gensym. Can you give an example of the desired input/output?

18:44 Tharem: Sure, here it is: http://pastebin.com/ydc1YLuZ. It also contains the newest macro definition with the gensyms stripped

18:46 alexbaranosky: Tharem, my version: (defmacro cond-let [cond fun & more]

18:46 `(if-let ~cond ~fun (cond-let ~more)))

18:48 TimMc: Racket's cond already has this, I think.

18:50 georgek: does anyone know of another location for the Noir docs, webnoir.org seems to be down

18:50 Tharem: Alexbaranosky: Almost works. First I had to splice the more. Now it's giving me errors because I'm calling cond-let with 0 input args, which can be fixed by adding a 0-element clause to cond-let

18:50 Thanks

18:50 TimMc: alexbaranosky, Tharem: http://clojuredocs.org/clojure_contrib/clojure.contrib.cond/cond-let

18:51 Tharem: Ok I'm getting too tired for this XD

18:52 Anyway, the macro is running now and it was good practice

18:54 TimMc: Tharem: Did you see macroexpand-1? It's a great debugging tool.

18:54 You can also put printlns in your macro. :-P

18:54 Tharem: Yeah I know it. It doesn't help if the macro itself isn't a valid expression :P

18:54 georgek: nm, looking at the repository on github

18:57 TimMc: OK, time to switch my brain to Python for a bit.

19:04 jodaro: bleh. trying to get from a shitty java while loop with a bunch of "breaks" to a reasonably idiomatic clojure version

19:05 if anyone has any general advice, i'd appreciate it

19:05 amalloy: TimMc: you can use foo# symbols outside of syntax-quote (since they're valid symbols, you can let them, etc), but it will just confuse people (usually the author)

19:05 jodaro: loop/recur gets me a lot of the way there i think

19:05 kumarshantanu: jodaro: can you gist it?

19:06 jodaro: https://github.com/imatix/zguide/blob/master/examples/Java/mdcliapi.java

19:06 its the send method of that

19:07 right now i'm loop/recurring on retries

19:08 and the first thing i do is if-not interrrupted and retries

19:08 kumarshantanu: jodaro: consider this -- https://bitbucket.org/kumarshantanu/clj-miscutil/src/acfb97c662d9/src/main/clj/org/bituf/clj_miscutil.clj#cl-502

19:08 jodaro: that actually gets me a decent amount of the way but i'm trying to figure out what to do on like line 106

19:09 looking

19:10 ok yeah

19:10 wow lots of great stuff here

19:11 thanks

19:22 TimMc: amalloy: Ah, you're right -- I made a mistake when testing if it was allowed!

19:23 jcrossley3: anyone know of a simple webdav library for clojure?

19:24 TimMc: You'll probably want to broaden your search to include Java libs.

19:25 jcrossley3: yeah, figured, but wondered if anyone here might've used one they liked.

20:16 duck1123: How do you point to a pom as a dependency in leiningen? ie. I want the transitive dependencies to be included

20:20 travisjeffery: Is there an easy way to get the value of a hash map for a key that may be either a string or keyword, e.g. if given {:my-keyword "my value"}, I could access "my value" with "my-keyword" hopefully without having to result to using a control structure.

20:22 cemerick: duck1123: lein does not support parent poms

20:28 TimMc: &(map keyword ["foo" 'foo :foo]) ; travisjeffery

20:28 lazybot: ⇒ (:foo :foo :foo)

20:29 tomoj: aren't parent poms a separate issue?

20:31 you can point to a pom with :type "pom", but you just get the pom, not its deps.. due to the way the maven ant task works?

20:33 TimMc: &(symbol :foo) :-(

20:33 lazybot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String

20:34 mrb_bk: does anyone have much experience with clojure.java.io ?

20:34 I'm trying to read in a byte stream and I'm wondering what the idiomatic clojure way of handling this is

20:36 cemerick: tomoj: poms don't have dependencies, they declare dependencies. Poms can have parents, but leiningen's model doesn't opt into that inheritance mechanism. It could, but there are actually far more powerful dependency/project composition options that have yet to be explored.

20:37 This is part of what I'm driving at w/ my point #2 here. http://groups.google.com/group/leiningen/msg/cef32b294960b678

20:38 Lein v2 will make a lot of that sort of stuff feasible.

20:40 TimMc: mrb_bk: Depends on what you want to do with it, I think.

20:41 A generic approach would use FileInputStream's .read into a byte-array.

20:41 mrb_bk: TimMc: actually that's what I'm tryign to do!

20:41 TimMc: I'm sure someone has created a lazy byte-seq thingy.

20:42 mrb_bk: I'm a total noob and am figuring out how to call the read(byte[] b, int off, int len) form of .read

20:43 weavejester: mrb_bk: What do you want to do with the ByteStream?

20:43 mrb_bk: weavejester: read it in x bytes at a time, compare it to some tokens, etc.

20:44 so regular (.read (input-stream file)) works for me but I don't know the right way to call the above form

20:45 weavejester: Why not just read it into a byte array?

20:45 TimMc: mrb_bk: What specifically are you having trouble with? Creating a byte array?

20:45 weavejester: (let [b (byte-array 10)] (.read stream b) b)

20:46 Although you probably want to reuse the array

20:46 mrb_bk: ah

20:46 yes

20:47 TimMc: yeah that's what was tripping me up

20:48 TimMc: mrb_bk: Example: (with-open [r (java.io.FileInputStream. "project.clj")] (let [bs (byte-array 20)] (.read r bs) (seq bs)))

20:48 The (seq bs) is just to get you something printable.

20:50 mrb_bk: TimMc: beautiful

20:50 thank you

20:50 weavejester: thanks!

20:51 weavejester: np

20:51 mrb_bk: how about using a function like the above to scan through the file

20:51 i have to take 5 bytes, and then 2 bytes, and then 6 bytes, and then 8 bytes, etc.

20:52 weavejester: I almost wonder whether chunked arrays might be a good choice to do that...

20:52 Or chunked seqs, I mean

20:53 mrb_bk: this is close to clicking with me but i get confused about the correct way to hold on to the "index" of the stream being seq'd

20:53 like for the above i want to .read 5, and then another number after

20:53 not read the first 5 and then the first 2 again, etc.

20:54 weavejester: Well, I'm not sure how efficient it would be, but you could turn the whole stream into a lazy seq of bytes

20:54 Well... maybe that would be inefficient...

20:54 TimMc: weavejester: tmciver has been playing with byte stuff too. Can you think of an efficient way to make aand use a byte-seq?

20:55 perhaps a hinted seq class

20:55 weavejester: TimMc: Hmm... I haven't really given it much thought...

20:56 I doubt a standard lazy seq of bytes would be hugely memory-efficient :)

20:56 But maybe something that implements the ISeq interface?

21:00 mrb_bk: What are you going to do with the bytes when they have been read?

21:00 It kinda sounds like you're implementing some sort of binary protocol?

21:07 TimMc: weavejester: Shouldn't be too hard to write one. How can I tell if it is employing boxing, by the way?

21:08 weavejester: TimMc: You mean boxing a byte into a Byte?

21:08 TimMc: right

21:09 I can throw hints at it all I like, but how can I tell if they are working? :-P

21:09 weavejester: Not sure why it would be, but maybe I'm thinking of a different sort of implementation.

21:09 mrb_bk: weavejester: yep, binary protocol

21:09 so it has a small "magic number" header, a version number, and then data

21:10 amalloy: binary protocol: probably worth learning gloss

21:10 mrb_bk: a lazy seq of bytes is what i was hoping i could get

21:10 weavejester: You could probably make a function like:

21:10 mrb_bk: amalloy: oh cool, gloss looks like it could help

21:11 weavejester: (defn read-bytes [s n] (let [bs (byte-array n)] (.read s bs) (seq bs)))

21:12 mrb_bk: weavejester: it should return the "rest" of the file, right?

21:12 weavejester: mrb_bk: What returns the rest of the file?

21:14 mrb_bk: weavejester: sorry, i just mean the function should read n bytes from the stream, do some evaluation of the bytes which have been put into a byte array, and then should either have the opportunity to exit or read the next n bytes

21:17 weavejester: mrb_bk: Yeah, so .read is a side-effectful operation, right?

21:18 mrb_bk: So you can just do something like (read-bytes stream 4) to read the next 4 bytes

21:20 TimMc: It would be better to have the mutation contained.

21:21 weavejester: Yeah... Gloss sounds nice in that regard.

21:22 TimMc: Does Gloss expose some of the lower-level aspects, and not just a fancy DSL?

21:22 weavejester: But I'm not sure how tricky the protocol is...

21:22 No idea, honestly. I haven't looked into Gloss.

21:25 TimMc: Oh, it looks pretty nice, actually.

21:26 mrb_bk: Yeah, just use Gloss, it looks fantastic.

21:26 weavejester: ztellman usually does good work.

21:26 All of his libraries tend to be well-thought-out

21:31 TimMc: Huh, has a pretty good blog too.

21:32 tomoj: I haven't been able to figure out how to do magic numbers in gloss

21:33 I mean, if you know the length of the thing it's easy to parse successfully, but it seems ideally it'd be a constant in the frame definition and would be left out of the result

21:35 I guess your decoder function can just throw it out?

21:47 TimMc: tomoj: Call it _, I guess. :-)

21:47 I think you can say to expect a literal.

21:48 amalloy: tomoj: it looks like you can use a header

21:50 (header :int32 {0xDEADBEEF body-codec} (constantly 0xDEADBEEF))

21:51 and use an error-detecting-function instead of just a plain map if you want something nicer than NPE when the magic number is wrong

22:14 tomoj: yeah, that looks good, thanks

22:35 ambrosebs: gtrak`: my gist before was the ClojureScript analyzer being used on clojure code

22:40 misfo: Did the anonymous function literal work differently in clojure 1.2?

22:41 TimMc: misfo: Not that I know of, why?

22:42 misfo: I'm using compojure for a web app (which uses Clojure 1.2) and for some reason I can't get map to work with an anonymous function literal

22:42 It works just fine with (fn [thing] ...)

22:59 TimMc: misfo: Here's a debugging tip: Enter the literal in a REPL, preceded by `

23:00 &`#(+ % 4) ; for example

23:00 lazybot: ⇒ (fn* [p1__25495__25496__auto__] (clojure.core/+ p1__25495__25496__auto__ 4))

23:02 TimMc: then compare that to your explicit version

23:02 misfo: Tim: that's a good tip

23:02 TimMc: amalloy taught me that one

23:03 misfo: I figured out that I my code was trying to execute a map

23:03 woops

23:03 (map #({:a (:b %)}) other-map)

23:04 TimMc: Well, that *can* work... if you pass it an argument. :-)

23:04 misfo: works fine as (map (fn [m] {:a (:b m)}) other-map)

23:05 TimMc: Probably best to use the fn version.

23:05 misfo: which leads me to another question: is there a better way to "rename" a key in every map in a collection?

23:06 sorry, "other-map" in my example is actually a sequence of maps

23:06 cgray: misfo: you could use (map #(hash-map :a (:b %)) other-map) if you wanted

23:06 TimMc: Well, that reduces to how to rename a key in a single map.

23:07 misfo: cgray: thanks, that's what i was *trying* to do with the function literal

23:09 TimMc: makes sense. so is there a better way to do that than the fn i was passing to map?

23:09 TimMc: misfo: It's probably time for a helper function. I don't know of a core fn.

23:09 I know there's a fn to map over the keys of a fn, but that's not what you want.

23:10 cgray: misfo: store the value of :b somewhere, then dissoc :b and assoc :a

23:10 tomoj: wouldn't the (:b %) always return nil?

23:10 oh

23:11 missed that bit :)

23:11 TimMc: There's probably some nasty trick with replace.

23:12 misfo: cgray: that would work, but wouldn't be any shorter. i was just wondering if there was a function for doing that in core

23:12 (map %(rename-key :old :new) maps)

23:12 something like that

23:12 no big deal if there isn't

23:13 TimMc: I don't think it's really common.

23:13 misfo: errr.... (map #(rename-key % :old :new) maps)

23:13 cgray: misfo: well just write rename-key yourself :)

23:13 tomoj: there is clojure.set/rename-keys

23:13 but that doesn't do what you wrote

23:14 TimMc: that renames all of them, right?

23:14 misfo: cgray: point taken

23:14 tomoj: it renames whichever you want, but it keeps the rest of the kvs too

23:14 instead of just returning a map with one pair

23:14 TimMc: that's fine, right?

23:15 Oh hey, that's perfect.

23:15 ,(require 'clojure.set)

23:15 clojurebot: nil

23:16 TimMc: ,(clojure.set/rename-keys {:a 1, :b 2} {:a :c})

23:16 clojurebot: {:c 1, :b 2}

23:16 TimMc: welp

23:16 tomoj: I am slightly curious why it's in clojure.set..

23:16 TimMc: misfo: ^

23:17 misfo: yeah, that's exactly what i need

23:17 thanks

23:17 !

23:17 yeah, why is that in clojure.set?

23:17 TimMc: &(inc tomoj)

23:17 lazybot: java.lang.RuntimeException: Unable to resolve symbol: tomoj in this context

23:17 TimMc: haha

23:17 tomoj: wtf is a rel anyway?

23:17 TimMc: &inc tomoj

23:17 lazybot: ⇒ #<core$inc clojure.core$inc@d47af3>

23:17 TimMc: -.-

23:18 cgray: tomoj: see line 1 of the example in map-invert on clojuredocs

23:20 tomoj: hmm.. is a rel a seq of associatives?

23:21 as in.. _rel_ational maybe?

23:21 TimMc: where do you see "rel"?

23:22 tomoj: docs for many functions in clojure.set

23:22 looks like it is canonically a set of associatives, though any seqs work too, at least in some places?

23:23 TimMc: Oh, makes sense, I think.

23:23 It's a set of named tuples.

23:24 clojure.set seems to be centered around relational algebra.

23:26 tomoj: and a rel is a set, so clojure.set makes perfect sense for a name. </sarcasm>

23:26 TimMc: Probably named that way for hysterical raisins.

23:28 Like, someone was doing some database stuff, and created that lib for sets, then expanded it sideways. :-)

23:29 tomoj: index: "Returns a map of the distinct values of ks in the xrel mapped to a set of the maps in xrel with the corresponding values of ks."

23:30 jeebus

23:30 clojuredocs to the rescue :D

23:38 TimMc: I want the author of ClojureDocs to send a pull request to the Clojure/Core team. -.-

23:55 apetrescu: I think Marginalia might be the prettiest documentation generator I've ever seen

23:55 I would start using Clojure just for that

Logging service provided by n01se.net