#clojure log - Feb 03 2011

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

2:23 amalloy: brehaut: (defn pivot-with [pred seq] (let [seq (drop-while pred seq)] (take-nth 2 (partition-by (comp boolean pred) seq)))) maybe?

2:26 would be my take on bartj's problem. i haven't read your version, since it sounds like you'd be sad if i did

2:30 apparently all that was four hours ago

3:15 brehaut: amalloy: oh yeah that looks a little less 'raw'

3:15 and you're welcome to look at my mess ;)

3:16 clever use of take-nth

3:18 amalloy: brehaut: yeah, it seemed like partition-by had to be the starting point, and from there take-nth is the only thing that made sense

3:19 brehaut: amalloy: i think there is an argument for a loop recur version. it's kind of a `primative' operation

3:20 amalloy: brehaut: disagree. you can't be lazy that way

3:21 &(take 10 ((fn [pred seq] (let [seq (drop-while pred seq)] (take-nth 2 (partition-by (comp boolean pred) seq))) even? (range))

3:21 sexpbot: java.lang.Exception: EOF while reading

3:22 amalloy: &(take 10 ((fn [pred seq] (let [seq (drop-while pred seq)] (take-nth 2 (partition-by (comp boolean pred) seq)))) even? (range))

3:22 sexpbot: java.lang.Exception: EOF while reading

3:22 amalloy: blah whatever

3:22 brehaut: :)

3:22 amalloy: brehaut: i like your docstring for pivot-on, anyway. the user knows what they're getting themselves into

3:22 brehaut: :)

3:23 i figure it pays to be clear

3:25 i added your version to the gist

3:31 amalloy: $mail bartj brehaut's gist at https://gist.github.com/808961 has been updated with a nicer version of pivot-on

3:31 sexpbot: Message saved.

3:43 Dranik: hello all!

3:43 brehaut: morning Dranik

3:44 Dranik: did you use defsymbol from clojure.contrib?

3:44 *defsymbolmacro

3:44 brehaut: i havent

3:44 Dranik: ((

3:45 yayitswei: morning Dranik

3:45 Dranik: yayitswei, morning!))

3:52 how is clojure 1.3.0-alpha4? is it stable enough for non-production code?

4:17 ejackson: Good Morning Fine and Noble People

4:18 oh, and you too LauJensen :)

4:19 Dranik: ejackson, :-)

4:55 shtutgart: Hi, I have a trouble with appengine-magic. When saving new entity, I'm passing nil as a value of the key, and all save! and retrieve works fine, but key of retrieved entities still contains nil. Am I doing something wrong?

5:00 There is an example: http://paste.lisp.org/+2K2Q

5:44 Dranik: is Konrad Hinsen around here?

6:55 lpetit: hello

7:12 babilen: Hi all! (If this is in some FAQ/document i did not find, just tell me) -- How do I install clojure system-wide on linux? With scripts (wrapper like "clojure") manpages and everything.

7:15 raek: babilen: you usually install some build tool like leiningen or cake system-wide. they do what typical launcher scripts do in other languages.

7:16 babilen: raek: technomancy/leiningen?

7:16 raek: yep

7:16 babilen: raek: Ok. (I just hope that my next question is not: "How to install leiningen?" ;)

7:16 raek: babilen: see instructions here: https://github.com/technomancy/leiningen

7:17 babilen: yeah, i found that. :)

7:17 raek: there will be a deb package for leiningen eventually (dunno if it's done yet)

7:17 babilen: cake is even simpler to install: gem install cake

7:21 babilen: ok, and now? "Modify the dependencies and repositories sections of your Leiningen project.clj" seems to assume that I already have a leiningen project file, for a project I don't have.

7:27 raek: babilen: ah. run "lein new <project-name>" to create a project directory

7:28 the default project.clj file will include clojure and contrib version 1.2

7:28 start a clojure repl with "lein repl" and let the hacking start :)

7:30 lein will make the src/ directory, as well as your jar depencencies (including clojure itself), will be on the classpath, so that clojure can find them

7:32 * babilen runs "lein new hello-world" -- there has to be a better way. Any comments on "cljr" (https://github.com/liebke/cljr) ? -- Sorry for asking such basic questions, but the tool-infrastructure of clojure (and in JVM in general) is quite new to me.

7:33 raek: cljr is similar tool, but lets you have one system-wide installation of clojure libs. maybe I whould have mentioned that too...

7:34 Raynes has written an introduction to these build tools: http://blog.raynes.me/?p=48

7:35 cljr works as long as you stick to compatible versions of every lib you have installed

7:36 cake and lein let the projects have the versions they need without interfering with each other

7:36 like virtual_env in python

7:36 babilen: raek: Ok. Just to clarify this. Leiningen is a tool to setup self-contained projects and building them on a project-by-project basis. cljr uses a central installation, but does not necessarily install all dependencies of a project into the "project" directory and does not even necessitate that you have a "project"

7:36 raek: exactly.

7:36 babilen: ok -- me thinks lein == python virtualenv and cljr == python system install now :)

7:37 Ok, given that I'll just play with Clojure without having a project cljr might just suffice. Thanks for the pointer so far.

7:37 raek: as soon as you need to split your code into multiple source files, I recommend cake/lein

7:38 but until you need that, cljr should be fine

7:38 babilen: Ok. Wonderful, that blog post seems to be exactly what I need/want to read right now. Thank you raek!

7:38 raek: np.

7:57 babilen: raek: I went with cake -- Easy, elegant and nice. /me would be happy if instructions like this had been on the clojure homepage. :)

7:57 fliebel: raek: I think cake's global project does that better.

7:58 uh, sorry, need to scroll down :P

7:58 my comment was re cjlr

7:58 babilen: fliebel: yes, exactly my impression.

7:59 fliebel: no problem, i would have been happy to read it if I haven't arrived at the same conclusion earlier.

8:00 fliebel: babilen: what is your os?

8:00 babilen: debian linux

8:01 fliebel: okay. macports seems to install Clojure "system wide", meaning it places a shell script with the correct java command on your path.

8:02 raek: fliebel: noted.

8:03 babilen: yeah, i thought about working on incorporating the new upstream release into the existing debian package. but after asking in here, it is my impression that this is not really necessary and also not the preferred way in the community.

8:03 khaliG: Hi. I'm writing my first clojure app and a bit stuck atm. I have designed my GUI using Matisse in Netbeans. Now i'm struggling with how to pass my clojure models through to the (Java) Swing code. Can anyone share some tips on this matter?

8:04 fliebel: khaliG: 'clojure models'? Well, if you need to extend java classes, look at gen-class and proxy.

8:04 Chousuke: khaliG: I don't know anything specific but you should be able to use swing directly. What have you tried to do and how is it failing?

8:04 khaliG: khaliG, the models which the GUI widgets will manipulate

8:05 Chousuke: I think generally such models would have to be contained in a ref or an atom, then.

8:06 khaliG: Chousuke, Well i started with my models being Java classes but I'd rather have them be clojure code

8:06 Chousuke: and if you need to implement some interfaces for the java code to work with them, you can use reify and close over a ref, for example.

8:06 if you need concrete classes, then gen-class or proxy, but that's more work :/

8:07 khaliG: ok so if i'm reading you correctly, i should write my models as java interfaces, then implement them on the clojure side? That sounds good

8:07 Chousuke: interfaces are the easiest to deal with from the clojure side

8:07 so if you can use them, do so

8:08 khaliG: seen, thanks!

8:08 chouser: can you not use clojure's existing interfaces -- IPersistentMap, Ref, etc.?

8:08 khaliG: i dont mind, i look forward to using as much clojure code as possible, but the swing classes ive generated using netbeans will need to interact with that code somewhere -- and that's where i was stuck

8:09 fliebel: khaliG: I assume you read this page? http://clojure.org/java_interop

8:09 Chousuke: you might also be able to generate a "generic" model class in Java and pass refs or clojure functions to it to customise its behaviour

8:10 but since I don't know much of the actual API I'm just throwing out ideas :P

8:12 khaliG: fliebel, i've come across it before, let me re-read it now to see if i missed something crucial

8:42 pppaul: anyone use fixtures here?

8:43 i'm having problems with my fixtures, they run, and then my tests throw null pointer exceptions

8:43 i'm using a fixture that does nothing, just calls the function it is given

9:30 zippy314: Hi. Is (use 'clojure.contrib.duck-streams) still the preferred way to use files in clojure or do folks prefer other options?

9:31 chouser: zippy314: recent clojure 1.3 alphas have simiplar functionality in clojure.java.io

9:32 zippy314: I'm still at 1.2, so I guess I'll stick with duck-streams for slurp and spit.

9:33 raek: but c.j.io has been there since 1.2, right?

9:33 slurp and spit has been in clojure.core since 1.2

9:35 chouser: has there been additions to c.j.io in 1.3?

9:35 zippy314: hmm. I get so confused about this because when I google stuff, it's hard to tell.

9:35 but yah, I just found it in core. Duh.

9:36 raek: clojuredocs.org is very good

9:37 zippy314: But it doesn't look like there is anything directly in core to get a list of files of the current directory for example.

9:37 chouser: raek: sorry, could be. I get fuzzy on what happened in which version. :-/

9:38 Raynes: babilen: Cake can do the majority of the things that cake *and* Leiningen can do. It has a 'global project' where you can specify dependencies and such, and those dependencies are used for things like 'cake repl' when it's ran outside of a project.

9:38 Er, "cljr and leiningen"

9:38 Dranik: how is clojure 1.3.0-alpha4? is it stable enough for non-production code?

9:39 Raynes: Forgive me, I wont up a total of 30 seconds ago.

9:39 chouser: Dranik: sure

9:39 Dranik: chouser, thanks!

9:40 raek: zippy314: you can call the .list method on a file to do that: (-> "path" io/file .list seq)

9:40 chouser: zippy314: raek is right -- Clojure 1.2 has clojure.java.io

9:40 Dranik: about clojure.contrib: will it be included into clojure-contrib?

9:41 raek: zippy314: in general, clojure does not add a function when there is a method doing exactly the same thing (the problem is of course to find that method instead...)

9:41 zippy314: raek: yah! that is the problem... :-)

9:42 raek: zippy314: there's also file-seq in core...

9:42 Raynes: raek: Doesn't file-seq also work?

9:42 raek: :)

9:43 Bow to me.

9:43 raek: it recursively traverses subdirs too, though...

9:44 Raynes: raek: At least it doesn't overuse ellipses...

9:44 raek: Raynes: :)

9:56 zippy314: why is there not-any? but not any? Seems weird.

9:57 Raynes: Because some is more flexible.

9:57 &(some #{'c} ['a 'b 'c 'd 'e])

9:57 sexpbot: ⟹ c

9:58 Vinzent: There is should be bot for answering this question

9:59 Raynes: Just pretend I'm automated and it'll all work out.

10:00 zippy314: (blush) again the newbie here...

11:41 gilecham: anyone got slime-call-defun working properly? C-c C-y to insert a call to this function in the REPL?

11:55 anna198: Hi, I'm using lein init-script, but even using the github example I'm getting an NullPointerException

11:56 suggestions?

12:01 mefesto: anna198: are you using :repl-init-script or just :init-script ?

12:01 edw: I'm looking at some source and constants are surrounded by plus signs. This seems crazy. Is there some established naming convention that this is mimicing, or is it just plain evil?

12:02 sritchie: edw: I think the established convention is to use *constant*

12:02 edw: sritchie: I thought *earmuffs* are for things whose value is subject to dynamic rebinding.

12:03 anna198: init-script

12:03 sritchie: edw: oh, you're right, from the wiki: Use *earmuffs* only for things intended for rebinding. Don't use a special notation for constants; everything is assumed a constant unless specified otherwise.

12:03 anna198: that's the project https://github.com/zkim/leiningen-init-script

12:03 mefesto: oh i see

12:03 edw: sritchie: Where's that wiki you;re referring to?

12:04 sritchie: http://www.assembla.com/wiki/show/clojure/Clojure_Library_Coding_Standards

12:04 edw: sritchie: Thanks!

12:04 anna198: mefesto: any suggestion?

12:05 sritchie: edw: no problem! I guess the simple answer is "plain, unadulterated evil"

12:05 edw: I'm thinking of forking the clojure-zmq module to fix this.

12:05 sritchie: edw: I've got to go replace some earmuffs in my code

12:05 mefesto: anna198: sorry i misunderstood you and thought you were talking about lein's repl-init-script ... im not familiar with this project

12:06 sritchie: here's an odd one -- does anyone here have any experience with GZIPInputStream?

12:06 I'm comparing a stream with GZIP to a normal input stream, and they match exactly, except for the first two bytes

12:06 anna198: mefesto: that's ok... I'm trying to make an wrapper to my project do you know other project to do that?

12:11 hiredman: edw: the plus sign thing is some kind of common lisp convention a few refugees refuse to give up

12:14 sritchie: so the clojure standard is -- for constants like (def map-dimensions [180 360]), no special notation

12:15 hiredman: defs should be considered constants be default

12:31 shortlord: what is the idiomatic way to pick the longest collection from a collection that holds these collections? putting all the collections in a sorted map and then pick the first?

12:35 arohner: I would do something like (apply max-key :count (map (fn [coll] {:coll coll :count (count coll}) mega-coll))

12:40 amalloy: shortlord, arohner (apply max-key count mega-coll)?

12:41 arohner: amalloy: even better

12:41 I'd gotten in the habit of building the map, because I commonly need to pass those values around

12:41 shortlord: oh god, somehow totally missed max-key

12:41 thx a lot

12:42 amalloy: arohner: as in, keep the count for every coll as well as the longest?

12:43 arohner: amalloy: in my app it's not count, it's probabilities, but yeah

12:43 raek: also (map (fn [x] ...) coll) --> (for [x coll] ...)

12:43 amalloy: (apply max-key second (map (juxt identity count) mega-coll)) is an option that avoids writing an explicit (fn)

12:51 __name__: amalloy: you seem to like juxt :)

12:51 amalloy: <== official member of the juxt fan club

12:52 __name__: where can i apply?

12:52 sritchie: hey all, quizzical issue here -- take a look at this gist: https://gist.github.com/941f9523212137c3a0ed

12:52 amalloy: __name__: i think technomancy was the first to call it a fan club :P

12:52 sritchie: the first defn works great, whereas the second pads two bytes onto the front of the input stream

12:53 GZIPInputStream is doing some sort of mutation, I'm just not sure why

12:54 amalloy: sritchie: well, that's as far as i'd gotten :)

12:54 sritchie: amalloy: haha, just wanted to grab the obvious points

12:55 amalloy: sritchie: you're sure it's *adding* bytes, not removing them?

12:55 you can see http://kickjava.com/src/java/util/zip/GZIPInputStream.java.htm has it read two bytes in readHeader()

12:55 sritchie: amalloy: it would make sense if I mixed that up -- it's probably reading the first few bytes

12:55 amalloy: yup, that's gotta be it

12:56 the adding certainly would be curious! crowded REPL syndrome

12:56 amalloy: heh

12:58 sritchie: you could wrap the input stream in a PushbackInputStream to avoid having to recreate the original stream if something goes wrong

12:59 but i guess that will end up being more complicated, not less

12:59 sritchie: amalloy: what I'm missing in this body of functions is a proper understanding of with-open

13:00 amalloy: sritchie: with-open simply ensures that as soon as you leave the lexical scope of with-open, the resource is closed. nothing fancier than that

13:00 sritchie: amalloy: I open up this stream on a byte array in one function, and create a lazy seq of pretty large blocks of bytes -- then I have to open up another stream on each of these blocks, to read floats in little endian format

13:01 amalloy: so is it sufficient to call with-open every time I open a stream?

13:01 amalloy: this leads to problems if you lazily consume data from that stream, because by the time the seq is realized, the stream has been closed

13:01 sritchie: amalloy: I've been setting a call to close at the termination of each lazy seq

13:01 __name__: isn't lazy io generally a bad idea?

13:02 amalloy: __name__: you have a better way to process a 1GB file? :P

13:02 __name__: because you can end up with a lot of open fd

13:02 fair enough

13:03 sritchie: __name__: yeah, this is for a cascalog function that cuts a byte array into chunks, converts bytes to floats and streams it all back out --

13:03 so, lazy seqs prevents the need to load everything into memory, as I don't need to actually hold on to any of this data during processing

13:04 raek: when using with-open, you are supposed to do all things that need the file inside the with-open form.

13:04 amalloy: sritchie: how's cascalog treating you? it looked pretty interesting to me when i was starting some hadoop work, but i wound up not trying it out

13:05 __name__: ok

13:05 okay, this was not supposed to go here

13:05 sritchie: amalloy: it's been fantastic so far, mature enough for this project. I'm performing manipulations on NASA MODIS tiles, and generating time series from lots of smaller data chunks

13:06 amalloy: cascalog let me get around this issue in hadoop of these big compound keys, with (dataset, tile, chunk, time period)

13:07 amalloy: the community's not that big, as of yet, but nathan (the creator) is extremely helpful, and chris wensel of cascading is fairly active

13:07 amalloy: that's convenient

13:39 mefesto: anna198: sorry was afk. could you explain to me what you mean by wrapper project?

13:40 anna198: mefesto: a daemon or a init.d script sorry for my bad explanation

13:41 mefesto: anna198: I'm not familiar with any Clojure specific tools for that but there is this java one: http://commons.apache.org/daemon/

13:41 anna198: that might help, i've never actually used it though :)

13:42 anna198: mefesto: I'll read about it thanks anyway =)

13:50 mefesto: does anyone know of a blog post or could explain how one properly performs a release with leiningen and clojars? (i.e. no libname-1.0.0-SNAPSHOT's)

13:51 do you edit the project.clj's version then perform a jar build and upload that to clojars? plus any vc tagging necessary

13:51 sritchie: hey all -- if I have a string like this, "2006-09-28T21:44:50.000Z", is there an easy way to define a format for that string, and destructure it based on that format?

13:51 sort of the opposite of the usual use fo format

13:51 of*

13:51 mefesto: sritchie: would a regex work for you?

13:53 ,(let [[_ year month day] (re-find #"(\d{4})-(\d{2})-(\d{2})" "2011-02-03")] [year month day])

13:53 clojurebot: ["2011" "02" "03"]

13:53 amalloy: sritchie: yeah, your choices are regex or java.text.SimpleDateFormat

13:53 sritchie: regex it is, i think

13:54 thanks, guys, that's just what I was looking for

13:54 raek: sritchie: Joda Time, or the clj-time wrapper could be worth checking out

13:56 sritchie: clj-time definitely looks like a cleaner way to go

14:11 dakrone: clj-time is pretty nice, been using it lately

14:31 mjg123: Hi folks. Whats the best way to find the first occurence of something in a vector? i.e. to implement (first-occurrence [4 6 2 0 5] 0) would give 3

14:32 is there a core function that can do that?

14:34 amalloy: mjg123: usually you "shouldn't" want to do this. scanning a vector to find an index is not a good way to get things done - what's the problem you're trying to solve?

14:34 $findfn 0 [4 6 2 0 5] 3

14:34 sexpbot: []

14:34 lazy1: mjg123: You can use keep-indexed

14:34 ,(first (keep-indexed #(when (= %2 2) %1) [1 2 3]))

14:34 clojurebot: 1

14:34 amalloy: &(.indexOf [4 6 2 0 5] 3)

14:35 sexpbot: ⟹ -1

14:35 amalloy: &(.indexOf [4 6 2 0 5] 0)

14:35 sexpbot: ⟹ 3

14:35 amalloy: so .indexOf is how to do what you want, but i recommend reevaluating whether you actually want it

14:35 mjg123: cool

14:35 I'm happy to do that, definitely.

14:36 kencausey: the reason not to do that of course is that it involves a linear search, dead slow

14:36 mjg123: The problem I am trying to solve is the 8 queens problem. I had modelled the positions of the queens as a length-8 vector, so [1 2 3 4 5 6 7 8] would represent all the queens along a diagonal.

14:37 I would start with [nil nil nil nil nil nil nil nil].

14:37 shortlord: is it possible to pass a form as an argument to a function without evaluating it or is that something that only macros support?

14:37 brehaut: shortlord: you can quote it

14:37 mjg123: then, proceed to find the first "nil" in that vector (my original question here), then calculate possible places for the queen in that rank, and recurse from there.

14:38 brehaut: ,(type '(fn [] 1))

14:38 clojurebot: clojure.lang.PersistentList

14:38 shortlord: brehaut: but I'd have to quote it in the caller, right?

14:38 brehaut: shortlord yes

14:39 shortlord: I'd like the caller to be able to pass something without having to quote it every time (because the caller could forget to do it)

14:39 so that leaves only macros and doing it like apply and passing the function and arguments seperately, right?

14:40 mjg123: I guess my algorithm is OK, but if you can suggest a better way to keep the data structured then that'd be great

14:40 brehaut: shortlord: macros are the only way to capture a form without the caller explicitly quoting it.

14:40 lazy1: mjg123: You can think of a queen location as number 0-7 on a column. Then the possible locations are permutations on the vector 0-7

14:41 (which you can use clojure.contrib.combinatorics for)

14:42 brehaut: shortlord: why do you want this?

14:42 amalloy: mjg123: instead of starting with [nil nil ...], why not just start with [], and fill it as you go?

14:42 mjg123: :)

14:43 amalloy: brehaut: i've found reasons to want a "function" whose arguments are automatically quoted, which is basically what shortlord seems to want

14:44 brehaut: really? aside from lists i'm struggling to imagine what it would be

14:44 mjg123: lazy1: That's a good idea, only 8! to check

14:45 amalloy: that is almost worth kicking myself for

14:45 shortlord: brehaut: I need a function that only executes the passed functions, if a certain condition is met

14:45 mjg123: I had got stuck on the idea that the vector would *always* have 8 elements

14:46 lazy1: clojurebot: solve 8 queens

14:46 (was worth the try)

14:46 mjg123: I'm using this as a kata/clojure-practise, so I'll try both ways

14:46 brehaut: shortlord: by 'functions' you mean expressions?

14:46 shortlord: brehaut: yes

14:47 amalloy: brehaut: DSL-y shorthand stuff. eg, the "natural" way for me to specify a player's hand for a card game is (hand aqt42 kj8 k74 3) (with an implied ordering of the suits)

14:47 having to quote all of those, or wrap them in a string, is unnatural

14:47 raek: shortlord: you can let the caller send the expression wrapped in a 'delay' or 'fn'

14:48 amalloy: as it happens it's convenient to have that happen at compile time, but i wouldn't mind if (hand foo) expanded to (hand* 'foo)

14:48 but now, afk for lunch!

14:49 shortlord: raek: but that would mean that the caller always has to delay manually. It could be quite tedious to find a bug caused by a call that has the delay omitted

14:49 raek: but if you quote the expression, you don't capture the context of the call

14:49 shortlord: looks like you need a macro, then

14:50 like the implementation of 'future' and 'future-call'

14:50 (future foo bar baz) macro-expands into (future-call (fn [] foo bar baz))

14:51 the point is, if your function is inconvenient to call, you can make a macro make it look prettier

14:52 bdesham: is the following considered idiomatic? (-> {:a {:b {:c 5}}} :a :b :c)

14:52 raek: as long as the keys are keywords (i.e. work as functions), I don't see why not

14:52 brehaut: bdesham: use get-in

14:53 ,(get-in {:a {:b {:c 3}}} [:a :b :c])

14:53 bdesham: brehaut: oh, nice... I think that's more what I was looking for

14:53 raek: get-in basically does the same thing in this case, but you can use any type for the keys

14:53 brehaut: bdesham: it has a related function assoc-in

14:53 bdesham: the -> form certainly works, but I wanted to know what the "preferred" method was to access nested maps

14:54 yeah, I just found out about assoc-in yesterday and was amazed

14:54 brehaut: bdesham: personally i prefer get-in because its explicit about the intent

14:54 bdesham: brehaut: yeah, that makes sense

14:54 thanks raek & brehaut!

15:47 * hv pokes technomancy

15:48 * hv presents Clove https://github.com/honr/clove, and crawls back to his cave ...

15:51 brehaut: hv clove looks interesting

15:51 hv: been using it for a while ;)

15:53 odyssomay: What is the best way to find and replace each " ... " (block of quotes) in a string?

15:54 brehaut: odyssomay: what do you mean by 'block of quotes'

15:54 odyssomay: ehm

15:54 " blablabla "hello\" blablabl"

15:54 oops

15:54 " blablabla \"hello\" blablabl"

15:54 brehaut: can your quotes contain quotes?

15:54 odyssomay: I want to replace \"hello\"

15:55 yes

15:55 hiredman: ,(doc split-with)

15:55 hmmm

15:55 ping?

15:56 brehaut: clojurebot has been a bit laggy this morning

15:56 odyssomay: I can look it up in the repl anyway

15:56 hiredman: ping?

15:56 clojurebot: PONG!

15:56 hiredman: ,(doc split-with)

15:56 clojurebot: "([pred coll]); Returns a vector of [(take-while pred coll) (drop-while pred coll)]"

15:57 hiredman: not the fastest thing in the world

15:57 if you want spead you'll want to get the byte array, scan, and bash in place

15:57 speed

16:02 odyssomay: hiredman: any example of split-with? I don't really get it...

16:03 hiredman: ,(split-with (partial = \") "hello \"world\" hello")

16:04 clojurebot: [() (\h \e \l \l \o \space \" \w \o \r ...)]

16:04 hiredman: hmmm

16:04 odyssomay: I got something similar, yeah

16:04 hiredman: ,(take-while (partial not= \") "hello \"world\" hello")

16:04 odyssomay: it splits the whole thing

16:04 clojurebot: (\h \e \l \l \o \space)

16:04 amalloy: hiredman: ##(split-with (complement #{\"}) "hello \"world\" hello")

16:04 sexpbot: ⟹ [(\h \e \l \l \o \space) (\" \w \o \r \l \d \" \space \h \e \l \l \o)]

16:05 amalloy: or partition-by

16:05 hiredman: I don't think you want partition-by

16:05 I mean, I guess you could just say every other list is something that was quoted

16:05 amalloy: hiredman: i suppose you're right, that would mess up ""

16:05 hiredman: oh, yeah

16:06 brehaut: ,(re-seq #"\"[^\"]*\"|[^\"]*" "hello \"world\" test")

16:06 clojurebot: ("hello " "\"world\"" " test" "")

16:06 * hiredman was actually just replace partition-by in some code at work this morning for a similar reason

16:06 hiredman: :/

16:06 brehaut: ,(take-nth 2 (re-seq #"\"[^\"]*\"|[^\"]*" "hello \"world\" test"))

16:06 clojurebot: ("hello " " test")

16:06 amalloy: brehaut: idea stealer!

16:06 brehaut: hehe

16:07 sorry

16:07 monkey see monkey do

16:07 thats an orrible regexp though

16:07 amalloy: brehaut: it's nice to have someone who abuses regexes more than i do though

16:12 brehaut: amalloy: i try to avoid it, but yes :P

16:13 i do try to stick to fishbowl's law though

16:14 "Every regexp that you apply to a particular block of text reduces the applicability of regular expressions by an order of magnitude." – http://fishbowl.pastiche.org/2003/08/18/beware_regular_expressions/

16:14 ohpauleez: brehaut: haha

16:14 I have never seen that before

16:16 brehaut: got it

16:16 ,(apply str (take-nth 2 (map first (re-seq #"\"(\\\"|[^\"])*\"|[^\"]*" "hello \"wo\\\"rld\" test"))))

16:16 clojurebot: "hello test"

16:16 brehaut: odyssomay: does that make sense?

16:17 amalloy: brehaut: i am concerned you may be involved in devil worship

16:19 brehaut: Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn

16:21 LauJensen: brehaut: Are you guys trying to do something like ##(.replaceAll "Hello \"World\" - testing" "\".*\"" "")

16:21 sexpbot: ⟹ "Hello - testing"

16:21 brehaut: LauJensen: sssh

16:21 amalloy: LauJensen: brehaut has taken it on himself to handle every corner case

16:21 for no particular reason :P

16:22 LauJensen: amalloy: excellent :)

16:22 brehaut: amalloy: i fear regexps and i havent learn't fnparse yet ;)

16:22 amalloy: LauJensen: your version will, eg, not work if there are more than two quotes in a string, and brehaut seems to even want it to understand \\\"

16:25 brehaut: the \\\" is so that escaped quotes in a quoted block are captured

16:26 amalloy: brehaut: yeah, i'm aware of *why* :)

16:26 brehaut: (as per odyssomay's requirments)

16:26 odyssomay: (seq (.split "hello \"world\" test" "\"")) works

16:26 brehaut: amalloy: oh right, sorry :)

16:28 amalloy: brehaut: now make it realize that "\\\\" is *not* an escaped quote :)

16:28 brehaut: amalloy: it does

16:28 oh

16:28 hmm

16:29 odyssomay: LauJensen: yes actually that's what I'm trying to do, thank you

16:29 LauJensen: odyssomay: np

16:30 sritchie: hey guys, quick question -- for a multimethod that dispatches based on type, how could I specify variadic arguments?

16:32 brehaut: amalloy: that case also shows that i havea sublte infinite loop in my version

16:32 sritchie: it feels cluttered, the way I have it, but here's the gist -- https://gist.github.com/9363935ac77cc8ef2f5a

16:32 the line with the comment is where I'm not sure

16:33 raek: I guess the dispatch function needs to be variadic too

16:33 amalloy: sritchie: (defmulti name (fn [& args] (type (first args))))

16:33 sritchie: which reminds me of one more -- is it idiomatic to have a multimethod call itself?

16:33 raek: (defmulti julian->period (fn [x & _] (type x)))

16:34 sritchie: let me take a peek at those, one sec

16:34 raek: I don't see why not

16:34 amalloy: raek's is better

16:35 sritchie: hey, haven't seen the underscore before,I like that

16:35 rata_: hi

16:35 sritchie: presumably that's for an ignored symbol, right?

16:35 raek: yes.

16:35 ,((fn [x] (type x)) 1 2 3)

16:35 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (3) passed to: sandbox$eval47$fn

16:35 raek: ,((fn [x & _] (type x)) 123 :foo "bar")

16:35 clojurebot: java.lang.Integer

16:40 sritchie: had to restart swank to get rid of the old defmulti, but it works

16:40 thanks a lot

16:41 solussd: a73p

16:41 raek: sritchie: yes, they behave as defonce

16:42 sritchie: you can "reset" it by running (def julian->period nil) or (ns-unmap 'your-namespace 'julian->period)

16:42 sritchie: raek: good to know, wasn't sure how to undo things at the repl

16:43 raek: previously, when you reevaluated a namespace containing a defmulti, you'd lose all the method implementations

16:46 mefesto: any recommendations on how to perform a release with leiningen/git/clojars? i'm probably making it more compliccated then it needs to be but i was thinking: git branch release; update project.clj with version (w/out SNAPSHOT); git commit; git tag; lein jar && lein pom; upload to clojars ... ?

16:47 raek: this is basically how I have done it

16:48 except that I didn't make a dedicated branch for it

16:49 mefesto: raek: sounds good. just wanted to make sure i wasn't leaving something obvious out. thanks

16:50 amalloy: mefesto: cake release pushes to clojars for you

16:51 mefesto: i guess my thoughts behind the dedicated branch was to keep from having these small release edits from polluting up my git log ...

16:52 raek: fair enough

16:54 amalloy: mefesto: i think it's good to have a branch for a release, though i don't do it myself

16:56 best of all is to have a "release" branch that stays alive between releases, and just merge into it, rather than a new branch every time

16:57 some people like to use master for that purpose, and have "dev" or something for non-release commits. that idea appeals to me but i don't have the discipline to do it for small projects

16:57 Chousuke: git has a nice model

16:57 master is the always-stable branch

16:58 mefesto: im the same. i'll try to be disciplined ... let's see how long it lasts :)

16:58 amalloy: Chousuke: that is *one* model you can use

16:58 git doesn't have any such model inherently

16:58 Chousuke: releases are tagged from it. maintenance fixes to to maint, then there's "next" for development. merging goes maint -> master -> next

16:58 I meant git.git :)

16:58 it's like a model project for others to imitate

16:59 it's fun reading just the logs too, there's a lot of information

16:59 technomancy: hv: looks interesting; I'll take a look

16:59 amalloy: Chousuke: git flow is another

16:59 technomancy: does it cover some of the same ground as nailgun?

16:59 Chousuke: not just "fix bug" or "fix breakage"

17:00 edw: Is there a difference between seq? and sequential? Should I care?

17:00 Chousuke: though maintaining such a repository takes some skill :/

17:00 edw: Ah. I see.

17:00 technomancy: mefesto: if you anticipate keeping two versions active at once then a branch is important, otherwise a tag might suffice

17:00 Chousuke: you can always branch from a tag if you need to

17:00 technomancy: and you can go back and branch once you discover you need to update an old release (like clojure 1.2.1)

17:01 raek: ,(map (juxt seq? sequential?) [[1 2 3] {:a 1, :b 2} '(1 2 3) (seq [1 2 3]) (lazy-seq [1 2 3])])

17:02 clojurebot: ([false true] [false false] [true true] [true true] [true true])

17:05 mefesto: well i just pushed to github. would be interested in some feedback if anyone has a few mins: https://github.com/mefesto/wabbitmq

17:05 it's a simple clojure wrapper for rabbitmq 2.2.0

17:58 mattmitchell: not sure what i'm doing wrong here... when i run this code:

17:58 (defrecord Page [filename])

17:58 (Page. "site/www/index.html")

17:58 I get: java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol (models.clj:3)

18:00 brehaut: mattmitchell: i dont know what you are doing wrong either; that works fine for me

18:01 mattmitchell: can you eval *clojure-version*

18:01 odyssomay: How can I take every second element in a list?

18:01 brehaut: odyssomay: (drop 1 (take-nth 2 my-list))

18:01 odyssomay: Ex In '(1 2 3 4) I want '(1 3)

18:01 brehaut: oh

18:01 thats even easier

18:01 odyssomay: hmm?

18:02 brehaut: ,(take-nth [1 2 3 4])

18:02 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$take-nth

18:02 brehaut: whoops

18:02 odyssomay: oops

18:02 brehaut: ,(take-nth 2 [1 2 3 4])

18:02 clojurebot: (1 3)

18:02 odyssomay: nice, thanks

18:07 this is how I tried doing it: http://pastebin.com/Gv1mm092 :D

18:09 brehaut: odyssomay: just for the sake of; (defn take-nth-ish [n s] (map first (partition n s)))

18:10 or, the amalloy way: (def take-nth-pf (comp (partial map first) partition))

18:13 amalloy: brehaut: cute

18:13 brehaut: :)

18:14 odyssomay: hehe

18:14 amalloy: odyssomay: your recur form is indented weird; it's hard to read. usually all the arguments should line up with the first argument

18:15 odyssomay: amalloy: sorry, I agree. It's enclojure style ;)

18:15 amalloy: blugh

18:15 odyssomay: hah

18:17 mattmitchell: brehaut: *clojure-version*

18:17 {:major 1, :minor 2, :incremental 0, :qualifier ""}

18:18 brehaut: mattmitchell: likewise. i copied your code and ran it in my repl and it ran exactly as expected

18:18 mattmitchell: weird

18:18 amalloy: mattmitchell: my guess would be that you are getting the exception somewhere else

18:18 mattmitchell: ok, i'll try a fresh repl env instead of my project

18:18 amalloy: what is on line 3 of models.clj?

18:18 mattmitchell: brehaut: yeah probably

18:19 amalloy: (defprotocol Fileable

18:19 "A simple protocol for a static resource (file/image etc.)"

18:19 (load-from-file [self] "Loads the resource at :path"))

18:22 amalloy: mattmitchell: weird

18:22 rata_: mattmitchell: that misses the [field ...] part I think

18:22 mmm... no... it's a protocol

18:22 confused by the prior defrecord

18:28 joshua__: Nobody?

18:30 ohpauleez: joshua__: What was your question?

18:30 amalloy: joshua__: so far you haven't said anything

18:30 joshua__: Oh.

18:31 I asked if there was a standardized way to deal with users in compojure.

18:31 Well, I thought I asked that at least.

18:31 amalloy: joshua__: with distaste. users are so yucky

18:33 ohpauleez: haha

18:34 joshua__: amalloy, scary

18:34 amalloy, so should I add a record to mongodb with user name and password with like a 'logged in as this user' variable added to the session of someone who logs in?

18:36 amalloy: well, whatever you do don't store a password in plain text

18:37 joshua__: I have to hash it right? and than I hash it again when I also hash when a user tries to log on.

18:38 Sorry, I'll start reading what I type before sending it.

18:38 Oh, by the way, college started again!

18:38 ohpauleez: joshua__: I'm pretty neurotic, I so I do a user, and email, and password collections/tables

18:38 and normalize

18:38 all passwords SHA-256 or stronger

18:38 password links to email, email links to user

18:38 user never links directly to password

18:40 joshua__: Why can't user link to password?

18:40 ohpauleez: joshua__: The idea is that if you lose or compromise any single collection, you don't give up all Personal Identifying Information

18:40 and you can mostly recover from it

18:42 Again, most people don't roll systems this way, but I think it's pretty smart, and it makes dealing with the lawyers easy (if you're a data driven startup or a data driven app_

18:42 )

18:42 Derander: seems to me that the odds of breaching a single collection and not breaching anything else are astronomically low

18:42 joshua__: Could you do the same thing by having a :passwords collection with user/password and than having a :users collection that has everything else for the user?

18:43 Oh, this isn't standard practice?

18:44 ohpauleez: Derander: Really?

18:44 Derander: that's how it seems to me. I can envision circumstances where it happens

18:44 ohpauleez: Using frameworks and smart access to the DB, I think that Injection attacks are hard enough, and when security holes do slip it, it usually only exposes a table or two

18:44 or a collection or two

18:45 hv: technomancy: yes it is similar to nailgun to some extent, except I used AF_UNIX instead of TCP sockets to make it fast and secure. also there is FD passing which let's you give the terminal's stdin, stdout, stderr to the service (e.g. to clojure). I cannot remember if nailgun passed env vars to the service, but clove does (clove-clojure even binds it to clojure.core/*env*, so you can just do things like (*env* "PATH"), *pwd*, etc.)

18:45 ohpauleez: Mongo is a little harder because you can execute mostly arbitrary js in some circumstances

18:45 Derander: I'm having trouble envisioning an injection that would only work on a single collection, but I'm sure it exists

18:47 on the other hand, how far do you want to go?

18:47 why not keep the passwords on another server or something?

18:47 hv: ohpauleez: who do you handle lost/"forgotten" passwords?

18:48 ohpauleez: hv: the password links to the email

18:48 so you can still reset

18:48 without knowing the actual user

18:49 hv: cool. that's smart.

18:49 Derander: why not store half of the password hashed in one collection?

18:49 and half in another

18:50 ohpauleez: Derander: Now you're making me look soft. or foolish. :)

18:50 Derander: well, there is a line somewhere

18:50 I see your argument

18:50 joshua__: why are they in the same database?

18:50 hv: joshua__: they don't need to

18:50 ohpauleez: Derander: My point is, if you have startup, and you have PII, it's the first thing you need to square away with lawyers

18:51 the setup I described is a little overkill, but it also keeps everyone happy

18:51 and doesn't suffer too much performance

18:51 Derander: not familiar with the laws

18:51 joshua__: ohpauleez, I don't need any personally identifiable information, does that mean this is overkill for me?

18:52 Derander: ohpauleez: my perspective is that a certain point you're fucked. I tend to draw that line at "executing code"

18:52 ohpauleez: if you're building a little hobby site or the service isn't indexing data on a particular user, you can do whatever you want, just hash the passwords

19:01 technomancy: you want bcrypt

19:01 http://codahale.com/how-to-safely-store-a-password/

19:16 brehaut: (inc technomancy)

19:16 sexpbot: ⟹ 7

19:17 brehaut: many minutes late, but thats a great reference

20:23 how frequently is the clj-dev ml request for member ship queue cleaned out?

20:26 _user_: She was right. The women who’d been naturally well-endowed before were

20:26 notoriously reluctant to get the shot. The world had changed, for sure.

20:26 A woman with a double D chest, or even a double E could blend in easily

20:26 at this point. The ones who started out with nothing for the most part

20:26 found the extra breast growth a wonderful life enhancement and boost to

20:26 their self-esteem. A fun adventure. But a woman who grew up

20:27 self-conscious of her large bosom—as was common with many women a D cup

20:27 or larger—always worried about attracting the wrong kind of attention,

20:27 or being thought of as a bimbo; the fact that the world had changed

20:27 around them did nothing to remove their ingrained trepidations and

20:27 ‘body issues’.

20:27 And Kelly’s sunny testimonial to the contrary, larger-busted women were

20:27 by no means immune to Efema’s effects. One cup size or less was

20:27 definitely the exception to the rule. Two to three cup sizes of growth

20:27 was considered the norm. And while no one was at risk of the seven cup

20:27 sizes of growth that Sarah had been made to endure, some women

20:27 experienced four or more jumps in size, even on the new accelerated

20:27 eight week formula.

20:27 clojurebot: Cool story bro.

20:27 _user_: Tracy and her kind needed to be vaccinated against breast cancer. That

20:27 was the bottom line. But she had good reason to doubt she’d be as

20:27 ‘lucky’ as her friend Kelly.

20:27 “A natural-born double D will probably wind up an F or a G cup. Or

20:27 larger. But so what?!” Sarah asked hypothetically. “Tracy’s a big

20:27 crybaby if you ask me. So what if she winds up a G cup. Or an H cup for

20:27 that matter? Walk a mile in my K cups, honey. Then lets talk.”

20:27 A car pulled up outside and two car doors slammed shut. Dean jumped up

20:27 and peeked out the closed curtains. “It’s my mom and dad.” They were

20:27 making one of their notorious unannounced pop-in visits.

20:27 Sarah got up and padded into the back bedroom to get a clean shirt. She

20:27 could hear John and Brenda at the front door while she was still

20:28 standing there in her bra staring at her closet. She grabbed a button

20:28 up top, snaked her arms into its short sleeves and made quick work of

20:28 the buttons, though pulling a shirt together across the apex of her

20:28 bust was always a careful consideration. Her buttons were always coming

20:28 loose and needed to be sewn back on all the time. She checked herself

20:28 in the full length mirror, applying a quick dash of lipstick to help

20:28 distract from dark circles under her eyes.

20:28 “Where’s that Sarah?” she could hear Brenda asking loudly from the

20:28 living room.

20:28 “Right here.” Sarah said as she emerged from the bedroom looking more

20:28 put-together than Dean could remember seeing her in almost a week.

20:28 Brenda extended her arms to her daughter in law and embraced her and

20:28 kissed her on the mouth. Sarah suppressed a tiny orgasm, tensing her

20:28 loins. John and Dean looked on dumbly as their wives pressed their

20:28 boobs into each other and held the embrace.

20:28 “How’ve you been? We haven’t seen you in weeks.” Brenda asked

20:28 cheerfully, aware probably of the little thrill she’d just given Sarah.

20:28 She held her daughter-in-law at arms length but grasped her hands,

20:28 interlocking fingers with hers, not letting go. As always, Mrs. Sutton

20:28 helped herself to a lingering apprising view of her Sarah’s incredible

20:28 34 Ks.

20:28 “I’m good. We’re good.” Sarah said with a weak smile.

20:28 “You look tired dear.” Brenda responded with a concerned scowl.

20:28 “Brenda!” John Sutton shouted, admonishing his characteristically rude

20:29 wife.

20:29 “Mom…” Dean echoed his dad’s sentiments.

20:29 “I know! I know!” Sarah admitted she did look tired. She confessed

20:29 she’d been sleeping terribly lately.

20:29 “You look beautiful as ever.” Mrs. Sutton reassured her.

20:29 “Oh, I don’t know about that. I could use a good night’s sleep.” Sarah

20:29 blushed, ashamed slightly at being forced to talk about her sex life in

20:29 front of Dean’s parents.

20:29 The Sutton’s knew full well what she meant by that comment. They could

20:29 all see the bags under Sarah’s eyes, and the general fatigue that

20:29 hiredman: huh

20:29 _user_: seemed to settle around her narrow shoulders.

20:29 “You look like you’ve lost weight. Have you lost weight?” Brenda asked.

20:29 Sarah sighed.

20:29 “Mom, come on.”

20:29 She did look like she’d lost weight, mainly in her face. Her once plump

20:29 cheeks and soft chin looked harder these days. Were it not for the

20:29 enormous tits bursting the seams of her tiny top one would say she

20:29 looked malnourished. To make matters worse her hair was dirty and

20:29 getting longer and at the moment was not particularly fetching.

20:29 “I don’t think so. I haven’t weighed myself recently.”

20:29 “Well you look beautiful” Brenda concluded, shaking Sarah’s hand in

20:29 hers until her thin arms bounced against the sides of her boobs.

20:29 “So what brings you guys by?”

20:29 “Oh, we were just in the neighborhood and thought we’d stop by. After

20:30 we missed out on lunch this morning.” Brenda gave a sideways glance at

20:30 technomancy: ~botsnack

20:30 _user_: John and elbowed Dean as she passed by and walked toward the kitchen.

20:30 She knew about Dean and Sarah’s frequent mid-day trists. It was Sarah

20:30 that had told her about them.

20:30 “They don’t mind you taking off early of a morning?” John asked, taking

20:30 a seat on the couch.

20:30 Dean sat back in his chair and grabbed the TV remote, turning the

20:30 volume down.

20:30 Sarah overhead John’s comment as she helped Dean’s mother find

20:30 something to drink. Brenda spied the food-stained tee shirt in the sink

20:30 but said nothing.

20:30 “So yeah, what ever happened with Olivia today? You never told me.”

20:30 hiredman: sorry, when I saw the flooding my first instinct was to kill the bot incase it was somehow related

20:30 _user_: Sarah voice rang out from the kitchen.

20:30 It occurred to Dean just now that his mom and dad would be coming in to

20:30 hiredman: ~botsnack

20:30 _user_: the gym for their regular workouts. They’d wonder what was up when he

20:30 clojurebot: thanks; that was delicious. (nom nom nom)

20:30 _user_: wasn’t there. He’d have to tell them eventually. But he wasn’t ready to

20:30 tell the family he’d lost his job.

20:30 “Oh, yeah. She wanted to straighten some stuff out with the schedule.

20:30 We’re overstaffed. Not enough hours for all these new trainers.”

20:30 “Overstaffed?” John asked.

20:30 “Oh you know the usual. Everyone wants more hours. Most of these

20:30 technomancy: the botsnacks must flow</blue-eyes>

20:31 brehaut: what does the botsnack do?

20:31 technomancy: it's like a scooby snack

20:32 hiredman: it makes you anthropomorphize to the bot

20:32 ~clojurebot

20:32 clojurebot: clojurebot is a multimap

20:32 hiredman: ~clojurebot

20:32 clojurebot: clojurebot is amazing

20:32 hiredman: bleh

20:32 technomancy: clojurebot: would you do it for ... three botsnacks?

20:32 clojurebot: Cool story bro.

20:32 technomancy: ...

20:32 hiredman: ~botsnack

20:32 clojurebot: thanks; that was delicious. (nom nom nom)

20:58 mattmitchell: i'm following this article: http://debasishg.blogspot.com/2010/09/domain-models-thinking-differently-in.html

20:59 and tried the macro he posted, which uses redef. But redef doesn't exist.

20:59 Anyone know where redef is?

20:59 hiredman: I recommend against ever doing anything you see in a blog post

21:00 redef sounds horrid

21:00 hv: hiredman: not even http://bc.tech.coop/blog/ ?

21:00 mattmitchell: hiredman: ?

21:00 hiredman: yes

21:01 brehaut: mattmitchell: the implication that people who blog about clojure generaelly dont know what they are talking about and are advocating crazy

21:01 hiredman: mattmitchell: top level defs are best thought of as single assignment constants

21:01 mattmitchell: hiredman: i see

21:02 technomancy: bc.tech.coop has some particularly bad advice about setting up slime

21:02 mattmitchell: hiredman: "redef" does sound bad you're right. i'm just trying things out though.

21:03 sritchie: right before he introduces redef: "Weeee .. it's a macro :)"

21:04 hiredman: a. there is no reason for it to be a macro b. the idea of "re-defining" something is flawed

21:04 c. you read about it in a blog post

21:04 the damning evidence mounts

21:05 technomancy: yeah, get it right the first time; honestly.

21:05 mattmitchell: ok let me ask you all... i'm in the process of setting up "models" for my application. what's the best way to design models in clojure? I have a basic page model i'm starting with.

21:06 a page pulls in content from a file. i need to be able to save, update and delete these "pages".

21:06 hv: umm, what is a "model"? as in model/view/controller ?

21:07 hiredman: I think you are better off with a set of limited protocols you can extend to the objects you have holding your data

21:07 mattmitchell: hiredman: ok yeah i started looking at protocols tonight.

21:08 brehaut: mattmitchell: think more like you would design an SQL schema than an OO network

21:08 dnolen: mattmitchell: start with maps (models/data/whatever) and regular functions. then maybe you'll decide you need multimethods for polymorphism.

21:09 mattmitchell: I'd recommend against protocols when you're modeling.

21:09 lots of limitations, and it's much more tedious.

21:09 hiredman: tedious in what way?

21:09 dnolen: I'd reach for them when a) you have a real design, b) if you actually need the performance.

21:09 mattmitchell: dnolen: that's how i began, until i googled, and found that awesome article :)

21:09 dnolen: hiredman: more code, more design.

21:10 technomancy: yeah, nothing you've said so far hints towards needing polymorphism

21:11 mattmitchell: nothing complex at this point. a "page" accepts a filename, loads the content, knows how to save/update/delete etc.. that's about it.

21:11 brehaut: a lot of the polymorphism you'll end up using is through parametric polymorphism and hofs rather than switch-on-type, which is different enoguh from what people with a lot of OO experience may not even recognise as polymorphic

21:12 hiredman: I find multimethods much more tedious

21:12 mattmitchell: brehaut: sorry, what is hofs?

21:12 brehaut: higher order functions

21:12 hiredman: you can't deal with a set of multimethods as a single unit

21:12 mattmitchell: brehaut: ahh ok

21:12 dnolen: mattmitchell: doesn't even sound like you need a model. just some functions. your.ns.page/load, your.ns.page/update, etc.

21:12 technomancy: namespaces can bundle units of multimethods

21:13 mattmitchell: dnolen: true, seems like the simplest too

21:13 technomancy: even better: namespaces can bundle units of functionality; whether they are all multimethods or some are regular fns is an implementation detail

21:13 hiredman: technomancy: right, but that hardler ever makes a nice clean interface

21:13 hardly

21:13 technomancy: the only strike against multimethods is they got a lot less convenient when defonce semantics were introduced to them

21:14 hiredman: technomancy: I could come argue this at your table

21:14 technomancy: hiredman: yeah, why don't you say that to my face?

21:14 brehaut: mattmitchell: this is a long paper but its chock full of insights http://web.mac.com/ben_moseley/frp/paper-v1_01.pdf

21:14 hiredman: technomancy: if I did then who would make emacs work when I break it?

21:15 technomancy: hiredman: talk to the M-x butterfly

21:16 mattmitchell: brehaut: wow that's some serious readin'. thank you, i'll dig in.

21:17 brehaut: technomancy: rofl

21:19 hiredman: http://groups.google.com/group/clojure/browse_thread/thread/83ad2eed5a68f108?hl=en

21:20 it amazes me how convoluted people can make things

21:20 brehaut: hiredman: at least he recognises it

21:20 dnolen: mattmitchell: word of advice, just do the simplest thing. OO brainwashes people into over-engineering, wasting time generalizing. Prolly cause OO code is painful to refactor, FP code less so.

21:21 hiredman: brehaut: he parrots "eval is evil" but then does this whole crazy concat thing which has nothing to do with anything

21:22 brehaut: oh sure, hes neck deep in crazy

21:22 mattmitchell: dnolen: excellent thanks for the advice

21:22 hiredman: '(Person. "Peter" 18) vs. (concat [(symbol "Person.")] ["Peter"] [18])

21:23 I dunno why he just doesn't create a factory function

21:24 brehaut: if he's a noob maybe he thinks he is supposed to mash a bunch of lists together and then do some metaprogramming ?

21:24 out of fear that anything else isnt lisp?

21:24 hiredman: I don't know

21:24 it's just bleh

21:25 like, you want to build a record from names that resolve to values, but you want to delay the binding of the names to values till runtime

21:26 anyway, I will stop raving

21:47 mattmitchell: would anyone recommend using clojure as a yaml config alternative? i have a yaml file that defines db connection info etc.

21:47 brehaut: mattmitchell: does it only need to be used by clojure?

21:47 mattmitchell: brehaut: actually yes

21:48 brehaut: then yes

21:48 mattmitchell: brehaut: i mean, a developer will edit etc.. but the only the *using* it is clojure

21:48 brehaut: i have a project.settings clj namespace i use. but you could easily use read to load a file

21:49 id lean toward a namespace until you know you need a more dynamic config system

21:49 mattmitchell: brehaut: cool. i'll give it a try.

21:49 brehaut: as its trivial to reload in the repl and you probably wont need to reload it in production. remember: simple is good

21:51 mattmitchell: brehaut: simple is good. reading that paper now :)

21:51 pdk: wait what

21:51 brehaut: mattmitchell: i would encourage you to wathc mark mcgranaghan's "one ring to bind them" presentation btw. its a exemplifies how using clojure core datatypes and functions makes life easier

21:51 pdk: this guy is blabbering making dynamic records

21:51 and he doesn't know about apply

21:51 brehaut: pdk easy on the noobs; crazy or not they are still noobs

21:52 hiredman: at work we have a config system build on reading config.clj files from the classpath and merging together the clojure maps they contain

21:56 pdk: oh shi

21:56 brehaut: hiredman: do you use the reader explicity or just require it?

21:59 hiredman: brehaut: hmmm?

21:59 the clojure reader?

21:59 brehaut: yeah

22:00 hiredman: we use the reader explicitly, it's not meant to be a namespace, there are no defs, the file just contains { … }

22:00 brehaut: ah sure that makes sense

22:03 mattmitchell: hiredman: so i'm doing just a (def settings (load "myconfig.clj")) -- myconfig.clj contains a simple hash-map. Is that about it?

22:04 hiredman: if that works for you, keep in mind load will eval code, not just read datastructures

22:04 mattmitchell: hiredman: ok thanks

22:07 technomancy: hiredman: pretty sure that's what we do

22:07 since we need config files to be able to uniquify tmp dirs and such

22:08 hiredman: I know

22:08 and I think it's kind of nuts to do that in a config (but kind of handy)

22:09 technomancy: nuts and handy often go together

22:09 brehaut: mattmitchell: http://clojuredocs.org/clojure_core/clojure.core/read

22:10 hiredman: load happens to resolve the classname via the classpath, which read doesn't, and is handy

22:11 well, classname, filename whatever

22:12 mattmitchell: so read, just reads data structures without evaluating the code (possibly function calls) etc.?

22:13 well, returns the "next" data structure in the stream. ok i see.

22:13 hiredman: there is this eval reader form, the existence of which is not really advertised

22:13 which causes some evaluation to happen at read time

23:01 zakwilson: I am trying to decide between using Rails for a new website, or Clojure and an ad-hoc collection of libraries. Rails would be easy, but I like Clojure better than Ruby and ClojureQL looks ilke like it might be a really nice way to interact with a database

23:05 gfrlog: zakwilson: I have found clojureql to be exactly as much fun as you are expecting it to be

23:08 zakwilson: gfrlog: I'm watching the screencast now and it's looking very appealing. I've done web stuff in Clojure before, but never with a database. My new project is going to involve a bunch of joins, and this looks like a nicer way to do it than the Rails OO way.

23:15 gfrlog: yeah. I did a bunch of complex joiny things with it. It worked pretty well. I love the clojure-style immutability much better than active record

23:16 and it's not terrible like cc.sql

23:16 I had a hitch or two, but Lau was quite helpful

23:17 zakwilson: I think I'll go the Clojure route then. Rails might be easier short-term, but I don't like OO.

Logging service provided by n01se.net