#clojure log - Feb 26 2012

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

0:12 lynaghk: Does anyone have a suggestion for how to map with an accumulator

0:12 value? I have a collection of maps and want to return new ones that

0:12 contain an offset field based on all of the maps before it.

0:12 ugggg emacs, sorry about that folks.

0:14 The only thing I can think of is to calculate the values of the accumulator in advance using 'reductions, then mapping over both sequences at the same time, but it'd be nice to be able to walk the collection just once

0:14 juhu_chapa: it may sounds strange but when I execute in the REPL: (.split "key=value" "=") it works as expected, but when I execute the whole program where it is found that method does not work.

0:14 any clue?

0:14 lynaghk: juhu_chapa, can't say without more code.

0:15 juhu_chapa: I tried changing the delimiter to ":" and that behavior does not appear anymore

0:15 ibdknox: so after watching the bret victor video

0:15 I decided to try and create a real-time editing experience for CLJS

0:15 amalloy: lynaghk: isn't that just reductions?

0:16 lynaghk: amalloy: reductions just returns the value of the accumulator. I want those values to be within maps

0:17 juhu_chapa: lynaghk: this is the whole code: (do

0:17 (println (.split "key=value" "=")))

0:18 if you run just the split method it works

0:18 but inside in this case of another form it DOES NOT WORK

0:18 lynaghk: amalloy: I'm looking for [{:val 1} {:val 2} {:val 3}] => [{:val 1 :offset 0} {:val 2 :offset 1} {:val 3 :offset 3}]

0:19 amalloy: lynaghk: yeah, it's not really that pretty with reductions. i'd just bash together a quick recursive lazy-seq for it

0:21 you sorta need two functions, yeah? one for computing a new accumulator, and one for computing a value for the sequence based on an accumulator and an input item

0:22 lynaghk: Yeah, that sounds right

0:22 amalloy: it's *almost* like an unfold, but i don't think it would be that convenient to write as one

0:23 lynaghk: I'm not that familiar with functional idioms beyond map, to be completely honest.

0:24 I mean, I started to write it as a loop/recur, but I thought I'd check and see if there was a nice way to do that built into the std lib.

0:24 amalloy: loop/recur won't be lazy. i don't think that would make you happy

0:25 lynaghk: So you think recursive lazy-seq would be the way to go?

0:25 amalloy: the skeleton will be like (defn map-accumulating [next-item next-acc init-acc coll] ((fn step [acc xs] (lazy-seq (when-let [[x & xs] (seq xs)] ...))) init-acc coll))

0:26 i tried to write out more detail but i don't actually know what you're doing, so i gave up

0:26 lynaghk: Just doing a rolling sum

0:26 amalloy: well, i was writing the more general case, i think

0:27 lynaghk: Okay, I'll dig into that and see how it checks out. I might also do the double map for clarity.

0:28 juhu_chapa: I tried your code and it worked fine inside the do.

0:29 amalloy: for what it's worth, reductions followed by map really only goes over the sequence once anyway, because of laziness

0:31 muhoo: well my first semi-useful set of little functions in clojure: https://refheap.com/paste/860

0:31 feel free to tell my why that sucks balls.

0:31 lynaghk: amalloy: good point.

0:32 sritchie: hey all -- have you guys experienced leiningen running really, really slowly?

0:32 I have a few projects that take minutes and minutes to run deps

0:32 tomoj: yes, clean as well

0:32 sritchie: is there something I can do to diagnose this, or fix it?

0:33 juhu_chapa: lynaghk: you are right I am going to public the "erroneous" code in pastebin

0:33 ibdknox: sritchie: happens to me too :(

0:33 sritchie: it started with 1.6.2, I think

0:33 ibdknox: sritchie: the workaround seems to be that if you do rm -rf classes/ every time it would do a clean, it "fixes" it

0:33 tomoj: it's intermittent, right?

0:34 sritchie: oh, that's interesting

0:34 ibdknox: any idea what it's doing with that classes dir?

0:34 ibdknox: no clue, I've been annoyed by it, but haven't actually taken the time figure out what's going on

0:36 muhoo: doh! ##2r101101

0:36 &2r101101

0:36 lazybot: ⇒ 45

0:36 sritchie: ibdknox: I hadn't found a reference anywhere, it almost feels taboo

0:36 espringe: How do I get mildly readable errors out of clojure? Like here's an example one i get:

0:36 "Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol (main.clj:0) "

0:36 muhoo: &16r3e0F9

0:36 lazybot: ⇒ 254201

0:37 espringe: It doesn't tell me the line at all

0:37 the backtrace is all in Compiler.eval

0:37 The only thing it tells me is the file

0:37 ibdknox: espringe: sounds like an ns error :(

0:37 those are notoriously difficult to deal with

0:37 amalloy: yes, quite likely. but also the backtrace isn't *all* in compiler.eval

0:38 espringe: Well *none* of it is in my code

0:38 amalloy: like, main.clj:0 is probably saying the issue is at the beginning of your main.clj file, i think?

0:38 espringe: nah, it's definitely not

0:38 tomoj: sritchie: I was going to ask about it the other day, also couldn't find any other mentions

0:38 espringe: Cause since it was last working, i've only modified like 10 lines -- none near the top of the file

0:38 sritchie: technomancy, any ideas?

0:39 ibdknox: espringe: can you put up a paste of the file?

0:39 espringe: ibdknox: sure

0:40 ibdknox: http://pastebin.com/4MbCNYA6

0:41 Also if anyone doesn't mind, can they tell me how bad my code is. I haven't done a dynamically typed language in over 10 years, and i feel like i'm defeating its entire purpose

0:41 tomoj: I think delete-file-recursively is the culprit

0:41 espringe: the protocol/record thing i'm using, seems to be a crap approach?

0:43 ibdknox: espringe: multi-methods are a better solution for this kind of stuff

0:43 espringe: ibdknox: multi-methods that dispatch based on value, rather than type?

0:43 is that how to do it?

0:44 ibdknox: espringe: the cljs compiler is a really good example of the multi-method approach to emitting code, basically build up an ast and then just walk the tree calling emit based on the node type

0:44 muhoo: ast?

0:45 tomoj: sritchie: interesting you say 1.6>2

0:45 ibdknox: Abstract Syntax Tree

0:45 espringe: abstract-syntax-tree

0:45 * muhoo goes diving for wikipedia

0:45 sritchie: that's speculation, I had a buddy upgrade to 1.6.2 and start exclaiming about how slow things were

0:45 tomoj: https://github.com/technomancy/leiningen/commit/32ebf41f23b0fdc5b35991ab3f04a506ac0934c5

0:45 espringe: ibdknox: I'll look into doing that, but i'll need to figure out why it's not compiling now before i start refactoring

0:45 tomoj: this System/gc is in the hotspot that showed up in my profiler run

0:46 ibdknox: sritchie: does it eat your CPU too? for me it pegs a core

0:46 espringe: yeah I'm looking at your file

0:46 tomoj: how much time and money has this commit cost? :)

0:46 ibdknox: nothing obvious is jumping out

0:47 sritchie: ibdknox: I don't know that I'm able to have children anymore from the heat my laptop puts out when I run lein deps

0:47 ibdknox: sritchie: hah! finally someone else has the same thing

0:47 espringe: Are there plans on fixing the clojure errors/stacktraces? Other than my occasional "found X expected X" in scala, this has got to be the least helpful compile error i've seen :(

0:48 tomoj: hmm

0:48 the System/gc shouldn't be the problem, though

0:49 oh, maybe

0:49 xeqi: tomoj: it causes FullGCs on my system, so I could see it being the culprit

0:50 ibdknox: espringe: line 101 is your problem

0:50 espringe: what version of clojure are you using?

0:50 espringe: 1.2.0

0:50 ibdknox: ah nice, thank you

0:50 how did you find it?

0:50 ibdknox: espringe: 1.3.0 will give you *much* better error messages

0:51 ran it in a 1.3 repl :) and saw where it blew up

0:51 espringe: ibdknox: oh sweet, i'll give that a go. That's been my #1 pain point so far

0:51 in 1.2 the _only_ useful information is the filename

0:51 ibdknox: espringe: yeah 1.2's error messages were rough. 1.3's are a lot better, but there still tons of room for improvement. I think there were a couple patches in Jira somewhere for better defn error messages

0:51 * espringe goes to install 1.3

0:52 ibdknox: they might've gone into the 1.4alphas

0:52 espringe: ibdknox: You know of a simple example of someone using multimethods to decompose a dynamically-typed AST? (I'm looking at cljs atm, but it's a bit overwhelming)

0:52 technomancy: sritchie: never heard of that myself. I assume it's not snapshots?

0:53 ibdknox: technomancy: it's the same thing happening to me. I've ruled out plugins and it happens on 1.7

0:53 technomancy: sritchie: would be interested in seeing if you can repro on lein 2 from git master

0:54 tomoj: how do you test a source checkout?

0:54 (of lein)

0:54 technomancy: espringe: try clj-stacktrace; it gives way more helpful messages

0:54 tomoj: see "building" in the readme on master; you need 1.x to bootstrap it right now

0:54 ibdknox: espringe: korma sort of does it (http://github.com/ibdknox/korma). Ambrose's DSL article does too: http://pragprog.com/magazines/2011-07/growing-a-dsl-with-clojure

0:54 muhoo: ibdknox: sritchie: os specific?

0:55 ibdknox: sritchie: you on OS X?

0:55 espringe: ibdknox: thanks

0:55 sritchie: yup, OS X Lion

0:55 ibdknox: same

0:55 sritchie: technomancy: I can try that out tomorrow

0:55 espringe: technomancy: is that for just pretty-printing stack traces, or it gives better ones as well?

0:55 technomancy: espringe: it colorizes frames from clojure internals and java differently

0:56 sritchie: would be interested in hearing how lein2 works for you since it sounds like you have a pretty big codebase

0:56 it should be usable at this stage but hasn't been widely tested

0:56 muhoo: that'd explain why you're getting "wfm"'s from the linux users :-

0:56 sritchie: technomancy: I've got a number of plugins, so it's time for me to try it out

0:56 I love checkout deps, btw

0:56 technomancy: sweet

0:57 sritchie: plugins are going to be the biggest sticking point for upgrading, but I'm trying to help out with upgrading the most commonly-used ones

0:57 ibdknox: I'm going to have a really cool demo for you guys tomorrow I think :D

0:57 sritchie: nice

0:57 muhoo: so the lein-deps-melts-the-cpu problem seems isolated to osx lion?

0:57 sritchie: interesting, it seems like that might be the case

0:57 technomancy: the top 10 plugins are lein2 compatible

0:58 sritchie: gotta run for now, guys, but ibdknox, I'm glad we spoke up on this :)

0:58 technomancy: according to a mostly unscientific ranking somewhat based on clojuresphere data

0:58 tomoj: hmm, I get https://gist.github.com/197712ab7da69da50931 trying to run lein2

0:58 ibdknox: sritchie: indeed! Ttyl sir

0:58 technomancy: yeah I need to head off too

0:58 espringe: technomancy: another stupid question, does lein support scala (as in, an all-scala project)?

0:58 sritchie: espringe: that's a good question, actually, I'm interesting in creating jars from scala projects

0:59 lein-scalac is quite nice

0:59 technomancy: tomoj: that indicates you're using clojure 1.2

0:59 tomoj: oh, maybe clear out lib/ in the lein checkout?

0:59 espringe: theoretically it should work, but I have no idea if it's practical

1:00 tomoj: yeah, deleted and recloned lein checkout, and it's fine

1:00 technomancy: great; would love to hear feedback

1:01 tomoj: found the erronous lib/ inclusion in bin/lein; will get rid of that

1:01 muhoo: technomancy: sounds like you have an os-specific bug in lein.

1:01 technomancy: muhoo: oh, I have plenty

1:01 tomoj: muhoo: I'm on ubuntu

1:01 technomancy: most of them are for winders, but it's no surprise that mackosecks has a few too

1:02 xeqi: I think its more dep file size related

1:02 muhoo: why would that be? different jvm versions?

1:02 ibdknox: woah now. Them be fightin' words.

1:02 xeqi: I can see a >2 sec change on a ubuntu vm from to 1.6.2

1:04 technomancy: the first thing to ask is whether you are running deps because you have to or because you think you have to.

1:04 muhoo: or because you're on the bleediing edge doing cljs and al the deps are snapshots?

1:04 tomoj: does deps call clean?

1:05 amalloy: with checksum-deps, is there ever a time when you have to?

1:06 technomancy: amalloy: only to pull in new snapshots if you're not using checkout deps

1:06 otherwise it's a bug in lein

1:07 tomoj: `lein clean` on this project took 1m42s, `lein2 clean` took 2.2s

1:07 espringe: ibdknox: Thanks for those earlier links, they're kick ass and helping immensely

1:07 technomancy: holy smokes

1:07 ibdknox: espringe: np :)

1:08 amalloy: the only time i've had lein take a long time is when it's transitively AOT-compiling a bunch of stuff i don't want. perhaps it accidentally does that pre-clean?

1:08 technomancy: clean has no eval-in-project

1:08 * technomancy has to go; feel free to follow up on the mailing list

1:08 amalloy: i'm going to pretend you said "nope, that's not it"

1:09 xeqi: tomoj: can you do LEIN_JVM_OPTS=-verbose-gc for those?

1:09 err

1:09 LEIN_JVM_OPTS=-verbose:gc

1:11 daaku: i'm trying to get ac-slime working (have clojure-mode, auto-complete and ac-slime installed via el-get and swank-clojure 1.4.0 globally installed) and i'm getting a java.lang.ClassNotFoundException when auto completing in the repl -- here's a screenshot of the state: http://postimage.org/image/o1ds4gejr/

1:11 tomoj: xeqi: https://gist.github.com/ec7e2d7114d0014d8d74

1:11 lots more like that

1:11 daaku: seems similar to the issue described to be fixed in this: https://github.com/purcell/swank-clojure/commit/7172c275f390c59d0b532ec3dc2994b2b9f72167 -- but seems like maybe-resolve-sym should be handling it in the 1.4.0 branch

1:13 tomoj: bisecting..

1:16 hmm

1:17 git-bisect doesn't seem to want to help find out where the bug was fixed

1:17 oh well

1:20 xeqi: is there a public project that you guys have the slowdown on?

1:31 muhoo: what does a double-colon mean? i.e. ::foo ?

1:38 juhu_chapa: what is @def?

1:40 espringe: I have this as a multi-method dispatch. This works great, except I want it to match any integer, not just 34. What's the way to doing it?

1:40 (defmethod emit-llvm-type

1:40 [:int 34] [_] (str 'i 34))

1:40 Like how do i make the condition a function or something?

1:42 muhoo: espringe: (class foo?)

1:43 espringe: muhoo: There's no better way? That really sucks, as I'll now need to nest multimethods inside each other :/

1:44 Surely there's a way to not specify a dispatch value, but a dispatch-function ?

1:44 muhoo: look at the source of defmethod?

1:47 jedahu: macro problem

1:48 (defmacro foo [& body] `(let [a# 9] (macrolet [(~'bar [] `(+ 1 ~a#))] ~@body)))

1:48 (foo (bar))

1:48 => Compiler exception

1:48 java.lang.InstantiationException

1:49 any ideas?

1:51 muhoo: jedahu: wfm

1:51 jedahu: muhoo: ?

1:52 muhoo: works for me. i ran your defmacro in clj 1.3.0 and it gave no error

1:52 i've no idea what it's supposed to DO, but it didn't error

1:53 jedahu: muhoo: did you run (foo (bar)) ?

1:53 the defmacro works fine for me too

2:07 duck1123: Is there something written already for parsing http link headers? "<http://example.com>; rel=\"alternate\"; type=\"application/atom+xml\""

2:08 If not, is there a better way than trying to write a regexp to parse that?

2:20 muhoo: duck1123: enlive? but there may be something less heavyweight

2:21 jedahu: i tried (foo "bar"), but there's no macrolet definition

2:21 maybe macrolet is where the problem is?

2:21 jedahu: muhoo: you will need to :use clojure.tools.macro

2:22 which is here: https://github.com/clojure/tools.macro

2:29 callen: (split-at (/ (count (into (first (split-at (/ (count (vec poss)) 2) (vec poss))) (reverse (flatten (cons (last (first (split-at (/ (count (vec poss)) 2) (vec poss)))) (rest (split-at (/ (count (vec poss)) 2) (vec poss)))))))) 2) (count (into (first (split-at (/ (count (vec poss)) 2) (vec poss))) (reverse (flatten (cons (last (first (split-at (/ (count (vec poss)) 2) (vec poss)))) (rest (split-at (/ (count (vec poss)) 2) (vec poss)))))))))

2:29 I do believe this code has gotten out of hand.

2:31 * espringe feels embarrassed at finding my code with 3 levels of nesting unreadable

2:31 callen: espringe: this is some of the worst code I've ever written

2:32 espringe: I am enjoying this more than I can express.

2:32 espringe: if you're wondering how one reaches this point, the answer is over-reliance on REPL-driven-development over Hammock-D-D.

2:33 espringe: callen: rofl, i was thinking it was machine generated ;D

2:33 or at least, macro generated

2:34 Search my code for the largest amount of sequential closing braces, i have found:

2:34 ]]]]]))

2:35 muhoo: callen: looks like the throw-arity stuff in potempkin

2:35 callen: espringe: no that's home-grown insanity.

2:35 muhoo: just seeing if I can out-do Tellman on the depths of madness.

2:35 muhoo: I felt like impressing a Perlist I guess.

2:35 muhoo: so far the ugliest thing i've seen today has to be the regexp from youtube-dl

2:36 though, that's not a clojure thing

2:36 callen: muhoo: Clojure isn't idiomatic to my brain yet, I'm still trying to crack it like I have Python.

2:36 muhoo: doing 4clojure to fix my brain.

2:36 I'm still getting used to the "transformation" style.

2:36 I need to use more let bindings.

2:37 muhoo: funny, i'm reading docs and code for mundane stuff, and finally almost understandnig the functional way to wrap stuff, i.e. ring middleware

2:38 callen: i have to wonder what that vec-poss business would look like indented

2:38 espringe: When i get more time, i'll write a utility to search through a project and find the deepest nested s-expr. I wonder what major clojure project will win

2:39 callen: muhoo: well. I could just screenshare and you could watch this madness take form.

2:39 muhoo: it's already cleaned up a lot because I added a particularly choice let binding or two.

2:39 muhoo: I've got an emacs split between repl and the indented form.

2:42 muhoo: go ahead, refheap it

2:43 espringe: i did a quick search in emacs, and found some files with 20 closing parentheses

2:43 and a huge number with >10 closing parentheses

2:43 in a row

2:44 that's in EMACS, not in clojure

2:44 espringe: That makes my 6-in-a-row seem very unimpressive

2:44 In your emacs code, or in emacs itself?

2:44 muhoo: i do believe rhickey explicitly set out to make such insanity unnecessary, even difficult

2:44 no, this was in emacs source code

2:44 //usr/lib/emacs

2:45 because someone on #emacs was chiding me, telling me that if i had more than 5 levels of nesting then may code was broken

2:45 callen: tbqh, I write cleaner elisp than Clojure right now.

2:45 and cleaner clisp

2:45 I'm not used to clj yet.

2:45 refheap forthcoming.

2:46 muhoo: so i said, "oh yeah?" and pasted a list off file sin emacs itself that had like 10 or more closing parens in a row

2:46 amalloy: 5 is an absurd limit

2:46 callen: muhoo: https://refheap.com/paste/861 scroll to see the madness grow.

2:46 amalloy: you can start to worry at 14 or something

2:46 callen: well with indentation, it scarcely matters.

2:47 amalloy: what does indentation have to do with this?

2:47 callen: amalloy: check out that refheap paste, you may enjoy that.

2:47 amalloy: my ugly code led to this conversation.

2:48 muhoo: lol Evaluation aborted

2:49 callen: muhoo: don't make fun of me :(

2:50 muhoo: not at all

2:51 callen: I have a working example now.

2:51 muhoo: so you're writing a function to reverse the characters?

2:52 callen: muhoo: https://refheap.com/paste/862

2:52 muhoo: no, palindrome predicate

2:52 muhoo: anyway, seems to work for odds-n-evens now.

2:52 going to test it @ 4clojure.

2:52 muhoo: istr there's some kind of pop/push business which works in opposite directions on vectors vs lists

2:53 for reverseing thins

2:53 callen: reversing isn't really the tricky part

2:53 I'm just calling reverse.

2:57 muhoo: pretty awful eh? :P

2:58 the code works locally, but 4clojure seems to be failing.

2:58 amalloy: You failed the unit tests

2:58 wait.

2:58 I might be an idiot.

2:58 jfsdnerg

3:18 muhoo: oh cagwd

3:18 there is some function in clojure that will return true if ALL of the elements in the collection are true

3:18 it had a nice name like "all", but there doesn't appear to be an "all" function

3:18 callen: muhoo: whatsit?

3:19 muhoo: i read it in the "joy of clojure" book or in one of the dozens of blogs i've read. i have no idea.

3:19 alzheimer's has struck me early.

3:20 callen: muhoo: every?

3:21 muhoo: http://clojuredocs.org/clojure_core/clojure.core/every_q

3:21 muhoo: ya

3:21 every

3:21 callen: muhoo: you're welcome.

3:23 muhoo: thanks

3:33 amalloy: so callen, are you an idiot?

3:33 or was 4clojure broken?

3:34 callen: amalloy: I'm an idiot.

3:34 amalloy: fixing my code.

3:36 to my credit, I did make a function that passes the test

3:37 it's lunacy. Really fat series of sequential let bindings

3:38 https://refheap.com/paste/863 worst. code. ever.

3:38 amalloy: callen: are you aware you can follow people on 4clojure and see their solutions once you've solved a problem? it would help you see less-awful-mess sorts of answers

3:39 callen: amalloy: sure, most of my answers are as short as yours.

3:39 Raynes: What does that function do?

3:39 callen: amalloy: I followed that madness to its conclusion even though I knew to compare the reverse to itself after being seq'd

3:39 amalloy: I just wanted to force myself to learn how to abuse the shit out of it.

3:39 Raynes: palindrone predicate.

3:39 Raynes: Holy shit.

3:39 callen: Raynes: I'm aware of #(= (reverse %) (seq %))

3:40 Raynes: but I wanted to try madness.

3:40 muhoo: callen: i got a surprise for you

3:40 hang on

3:40 aperiodic: that's kind of awesome

3:40 amalloy: (comp (partial apply =) (juxt reverse seq)) ;; who needs variable names

3:40 callen: aperiodic: I'm glad you appreciate my objective here.

3:40 amalloy: points-free?

3:41 amalloy: usually just point-free

3:41 aperiodic: one of my recent objectives has been to try to be more point free

3:41 callen: I really enjoy writing horrible code too much.

3:41 I should stop that, haha. :)

3:41 aperiodic: mainly because i remember seeing some nice point-free haskell

3:41 callen: you should see what I've made in Python.

3:41 muhoo: ah crap, man you guys totally toasted me.

3:41 aperiodic: as long as you can keep it under control

3:42 callen: I've done some absurd one-liners with list comprehensions, map, filter, and reduce.

3:42 muhoo: i'd got it down to 3 lines and thought i'd accomplished something.

3:42 callen: aperiodic: well it's not something I put in production, I just indulge this source of amusement when I'm futzing around.

3:42 amalloy: aperiodic: point-free clojure can be nice, but haskell really does take the cake; our syntax frequently leads to fairly bad point-free code

3:42 muhoo: and it looks like you can do it in like one line, 3 functions. faaaack.

3:43 tjgillies: what version of node is clojurescript developed against?

3:43 Raynes: I'm not convinced they actually test that things work with node.

3:44 amalloy: Raynes: the cljs devs, or the node devs?

3:44 Raynes: ~rimshot

3:44 clojurebot: Badum, *tish*

3:44 aperiodic: amalloy: it may be amatuerish, but i do feel burdened by the parens sometimes

3:44 tjgillies: lol

3:44 aperiodic: amalloy: whereas $ and . are very succinct

3:44 amalloy: yep

3:44 muhoo: i thought they developed against rhino

3:44 callen: tjgillies: hey I have some code to show you.

3:45 tjgillies: callen: yay

3:45 * muhoo gets popcorn

3:45 amalloy: $google clojure github hiredman functional

3:45 lazybot: [hiredman/clojurebot - GitHub] https://github.com/hiredman/clojurebot

3:45 callen: tjgillies: https://refheap.com/paste/864 When you understand the zen of Clojure, you'll be able to write stuff like that!

3:45 amalloy: hmph

3:46 muhoo: i think it's the same kind of zen that, back in the 90s, causd my friends and i to voluntarily watch a marathon of "styx kilroy was here" and "kiss vs the phantom of the park"

3:46 tjgillies: callen: when i understand the zen of clojure im going to take over the world

3:46 callen: muhoo: similar, yes!

3:46 aperiodic: so, somehow, i'm having trouble finding lein2

3:47 amalloy: aperiodic: https://github.com/hiredman/odds-and-ends/blob/master/functional.clj is not something i'd really recommend, but it's a good example of what you can do with lisp to mimic haskell

3:48 (scroll to the bottom to see what he's getting at)

3:50 aperiodic: amalloy: ooh, i really like the flip operator

3:50 * aperiodic has a flip in his useful

3:50 muhoo: god damn i suck

3:51 aperiodic: so, is uncurry needed to get haskell-style function chaining to work with variadic clojure fns?

3:52 muhoo: callen: you with this palindrome thing.... i've spent a half hour on it now

3:52 aperiodic: i'm not familiar with that operator

3:52 muhoo: and it'll take me another 2 to understand how the correct solution, this partial apply juxt reverse seq business, actually works

3:53 aperiodic: muhoo: the partial apply juxt reverse seq is really quite simple

3:54 i mean, you're just asserting that the seq (phrase) is equal to its reverse

3:54 muhoo: suuuuure it is :-)

3:54 aperiodic: which is remarkably like the definition of a palindrome

3:55 muhoo: i should show you the lameness i came up with. once i finish it.

3:55 aperiodic: don't mean to come of harsh or condescending :)

3:55 muhoo: that's ok, i don't mean to sound clueless and stupid either :-)

3:58 amalloy: aperiodic: you can't get haskell's currying with varargs

3:59 you have to be very clear about how many args every function takes, in an expression, in order to have the automated curry/partialing

3:59 muhoo: i ended up with this: (every? identity (map #(= %1 %2) (seq p) (reverse p)))

4:00 amalloy: (every? true? (map = p (reverse p))) is a less verbose way to write the same idea

4:00 nybbles: hm could someone familiar with aleph please tell me why for some urls, the :body in @(http-request {:method :get :url some-url }) is a channel and for other urls, it's a TruncatedChannelBuffer?

4:03 aperiodic: amalloy: yeah, i knew that was too good to be true. found the hoogle definition

4:03 amalloy: aperiodic: of what?

4:03 aperiodic: amalloy: the uncurry thing

4:05 muhoo: maybe what rhickey is going to announce at clj west is a haskell that runs on the jvm

4:10 callen: muhoo: you're still trying to unroll my palindrone predicate?

4:12 muhoo: you have no idea how much it pleases me to know I've nerd-sniped you into grotesque horror.

4:15 muhoo: callen: worse than that. it took that long for me to produce my own one-liner, which i shared above

4:16 and now i'm trying to understand the other one-liners, the ones with juxt/partial/comp

4:21 callen: muhoo: have you unrolled mine yet?

4:34 muhoo: gad no

4:34 i did come up with a very tight oneliner though

4:34 taking the one someone posted above, and shaving it down a bit

4:35 removed the partial and the comp

4:35 (defn palindrome? [p] (apply = ((juxt reverse seq) p)))

4:35 callen: muhoo: no no, it's not fun if you don't trace the horror.

4:36 muhoo: seriously dude? i have deal with php and java for a living

4:36 i have MORE than enough horror, thank you

4:36 tracing the horror is what i have to do to survive. when i'm not being paid, no horror if i can avoid it.

4:38 callen: muhoo: d'aww. Just having some fun.

4:38 muhoo: I still say #(= (reverse %) (seq %)) is the most elegant.

4:38 muhoo: yeah, i'm going to try that one next

4:39 yep, it is, i agree.

4:40 tightest yet

4:41 callen: muhoo: that's the initial answer I came up with, but I decided I want to see how far I could go with a rube goldbergian answer.

4:41 with a bunch of unnecessary transforms.

4:42 muhoo: where i went wrong was in not remembering that you can check equality of a sequence without iterating over it

4:42 so i was doing stupid stuff with list comprehensions and doseq and that lot

4:42 callen: muhoo: ouch.

4:42 AimHere: What's the idiomatic clojure way of applying 'and' or 'or' to the contents of a collection? 'apply' and 'every?' and 'reduce' don't like taking on macros, and something like (reduce #(and %1 %2) ...) looks awful to me

4:43 callen: muhoo: you could use (every? ...) but there's not much point.

4:43 muhoo: finally narrowed it down to that map business, then i got schooled about the juxt thing

4:43 yeah, i ended up with every which is as far as i got on my own. the conceptual error was iterating

4:43 (= (reverse p) (seq p)) states it so much more clearly

4:43 callen: AimHere: I don't know what you mean by 'and' and 'or', but if you want to apply a given operation to all the contents of a collection, you're usually thinking of a map or an apply.

4:44 muhoo: I don't mind %()

4:44 muhoo: it's composable.

4:44 AimHere: I mean the logic operations 'and' or 'or'. Which aren't functions, they're macros, so apply and map won't take them

4:44 callen: AimHere: I need a concrete example of what you're trying to accomplish.

4:44 AimHere: what you're saying doesn't make sense man.

4:44 AimHere: can you paste it at refheap.com?

4:45 AimHere: Well I'd like something like (foo and [true true true false ...]) to return the logical and of all the stuff in the vector

4:45 muhoo: AimHere: ahaa! every?

4:45 AimHere: Ordinarily 'apply' would do the job just fine

4:46 Every? doesn't work

4:46 I've taken to something like "(fn [p v] (eval (list* 'a v))" at the moment only macroified,

4:47 muhoo: &(every? identity [ true true true false])

4:47 lazybot: ⇒ false

4:48 muhoo: &(every? identity [ true true true true])

4:48 lazybot: ⇒ true

4:49 AimHere: Heh, well that's and. Now I'll have to find 'any?' or a synonym for or

4:49 callen: clojure.contrib could use some expansion on the text-processing front.

4:49 I may come up with something to contribute.

4:49 muhoo: AimHere: http://clojure.org/cheatsheet

4:50 AimHere: Saved me hunting for the bookmark

4:50 muhoo: &(some identity [ true true true true])

4:50 lazybot: ⇒ true

4:50 AimHere: &(some identity [true false false false])

4:50 lazybot: ⇒ true

4:50 muhoo: &(some identity [ false false false])

4:50 lazybot: ⇒ nil

4:51 muhoo: &(some identity [ false false false])

4:51 lazybot: ⇒ nil

4:51 muhoo: yyeah, like that

4:51 callen: you know that clojure.contrib is depreciated, right?

4:52 callen: muhoo: I heard something to that effect, what's going on exactly?

4:52 AimHere: Of course, this doesn't work for writing my own boolean logical predicate macros, but I'm sure I'll work that out if I need to

4:52 callen: AimHere: I bet there's a macro (app) for that.

4:53 muhoo: callen: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

4:53 ~contrib

4:53 clojurebot: Monolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

4:53 AimHere: For passing generic boolean pred macros into the contents of a list? I don't think so

4:54 muhoo: i'm new, but i can't see a reason to make it a macro. why not a function?

4:55 AimHere: Because you want it to stop evaluating the arguments once it's decided it knows what the answer is

4:55 Lajla: Greetings my brethren

4:55 I am the best programmer in the world second only to the Microsoft Chief Software Architect

4:55 AimHere: &(or true (println "This never happens))

4:55 lazybot: java.lang.RuntimeException: EOF while reading string

4:56 AimHere: &(or true (println "This doesn't happen even if I stringify it properly"))

4:56 lazybot: ⇒ true

4:56 muhoo: side effects of or, eh?

4:56 callen: hrm.

4:56 AimHere: Not really, it's working as intended.

4:56 callen: muhoo: how open are they to ruby-esque shortcut functions in clojure.string?

4:56 clojurebot: Huh?

4:57 callen: muhoo: I'm wondering if there's a demand for predicates like upper-case? and lower-case?

4:57 muhoo: callen: i haven't a clue. ask on mailing list?

4:57 wait

4:57 callen: muhoo: the objective being to avoid duplication of effort.

4:57 muhoo: what?

4:57 muhoo: &(.toUpperCase "fuu")

4:57 lazybot: ⇒ "FUU"

4:57 muhoo: like that?

4:57 callen: no, predicate.

4:58 the ? means predicate.

4:58 upper-case already exists.

4:58 muhoo: ah, yes. i dunno then.

4:58 callen: (upper-case? \A) => true

4:58 (upper-case? \a) => false

4:58 (filter upper-case? "HeLlO") => "HLO"

4:58 muhoo: see nao?

4:59 muhoo: i'd say, why not write a library that does that stuff, put it up on github, ???? .. profit!

4:59 callen: muhoo: these are things that need to be in core to be useful.

4:59 muhoo: elimination of duplication of effort.

4:59 muhoo: i dunno. sounds like a mailing list questino to me

5:00 if yoou want duplicatino of effort, how many oauth libraries are there for clojure now

5:00 callen: er. I'm just trying to build simple foundational stuff for core

5:00 Not boil the ocean and lob it into core

5:00 oauth stuff would be *completely* inappropriate.

5:01 muhoo: i have no authority, so i can't even guess. but the core people do read the mailing list

5:01 i doubt any are here

5:01 * callen shrugs

5:02 callen: I'll formulate some type-hinted functions that I think would be handy and see what they say. I doubt they want to waste any time discussing hypotheticals.

5:03 muhoo: good point.

5:05 callen: I already have the lower? and upper? ones written, I'll peruse the ruby-docs and see what other ideas I can steal for Clojure.

5:11 stevelknievel: Hi all. Trying to build tools.nrepl and mvn can't find "clojure:jar:1.4.0-master-SNAPSHOT". Which repository am I missing?

5:11 Raynes: muhoo: As far as I know there is only one oauth library...

5:17 callen: Raynes: how much do you know behind the culture for contributing to core?

5:17 Raynes: Not much.

5:18 callen: Raynes: could you take a guess at how warm they'd be to the idea of more common-case helper functions/predicates/transforms in String.clj?

5:18 stuff like you get with Ruby/Python/etc

5:19 Raynes: If the things are useful and not already in java.lang.String, then you've got a shot. You'd really have to start a mailing list thread about it. This involves sending Rich Hickey a signed CA and then asking for membership to the clojure-dev group.

5:20 callen: Raynes: I'm okay with that. I'll check for duplication in Java-land and proceed from there. Thanks.

5:21 yeah, my ideas aren't in java.lang.String

5:25 Raynes: $max

5:25 $load max

5:25 lazybot: Loaded.

5:25 Raynes: $max

5:25 lazybot: The most users ever in #clojure is 376

5:30 callen: wait, I'm retarded, it exists in Character

5:30 fml.

6:52 jamii: Who are the moderators for the clojure google group?

6:55 callen: jamii: soup?

6:56 jamii: callen: is that a name?

6:57 callen: jamii: no, wondering what's up.

6:58 jamii: callen: oh, my post seems to have been deleted. I wondered if I did something wrong

6:58 callen: jamii: are you positive that's the case? Google Groups is known for being a bit off. What was the post about?

6:59 jamii: callen: subject was "Crowdfunding an open-source clojure library for p2p NAT traversal, dynamic addressing and pubsub"

7:00 callen: yeah. no.

7:00 that sounds like advertisement/bullshit to me.

7:00 either make it or don't.

7:00 don't try to busk for "crowdfunds"

7:00 no wonder they deleted it, haha.

7:01 jamii: Fair enough

7:02 callen: jamii: I would advise not simply rewording it and reposting

7:02 jamii: either make it or not, if you do make it, post about it and ask if anybody wants to contribute. Fin.

7:02 jamii: callen: I wasn't intending to repost

7:03 callen: jus' sayin'

7:07 jamii: callen: The content of the post was that I'm planning to post this as a small project on indiegogo and I was asking for feedback on the protocol. At the moment I work on this sort of stuff anyway and fund it with freelance work. I'm just wondering if funding it more directly is feasible.

7:08 callen: jamii: don't ever ask for money on the mailing list.

7:08 jamii: it's never appropriate to do that.

7:09 jamii: callen: sure

7:15 lnostdal_: deftype redefinitions and isa? https://refheap.com/paste/865 .. how do you guys deal with this? .. i like doing some run-time type checking, but...

7:16 callen: lnostdal_: you redfined it

7:16 redefined*

7:16 wiseen: is there any particular reason why core.match doesn't have something like (fnmatch [case-a] (exp) ...) where fnmatch would be a macro that generates a function that pattern matches arguments ?

7:16 or am I missing that macro ?

7:16 lnostdal_: yeah, i can see how that would be ok in some sense .. but other times some "slack" right there is needed

7:19 (= (str (class -blah-)) (str Blah)) => true ;; though .. but, hm, not exactly the same as isa? with regards to subtypes

7:31 __deo`: I want to make a async request for each item in a list and wait until a callback is called for the current req until making the next.

7:32 cant figure it out

8:07 callen: No matching field found: indexOf for class java.lang.String

8:07 caused by user> (.indexOf "Leroy")

8:07 which is pure lunacy.

8:08 how can't it find the method indexOf for the string?

8:12 dedeibel: Any ideas? http://stackoverflow.com/questions/9453117/has-anyone-a-case-implementation-for-clojurescript

8:14 callen: dedeibel: would it kill you to implement it yourself?

8:14 I guess I don't see what the problem is :\

8:15 bsteuber: (defmacro case [& args] `(condp = ~@args))

8:15 morphling: callen: indexOf takes two arguments

8:16 bsteuber: dedeibel: or just use condp for now

8:16 I'm sure it will be added to cljs

8:16 callen: morphling: hrm. Staying up all night appears to have driven me mad. Good clal.

8:16 Good call*

8:17 dedeibel: bsteuber: thx

8:18 Well there is an easy olution and one that is fast and everyone could benefit from

8:18 *solution

8:23 LauJensen: So, everybody going to the EuroClojure event?

8:27 bsteuber: LauJensen: maybe..

9:59 gtrak: what's the best way to run arbitrary clojure code remotely these days? possibly secure?

10:00 I'm thinking of creating a http-client that registers itself with a server, then the server calls stuff on it

10:04 the idea being that the server has all the code, but no state, the client is a dumb stateful thing

10:08 trptcolin: so the server remotely executes code on the clients?

10:08 gtrak: yea

10:08 the client keeps a persistent connection

10:08 one use-case, I want to put up source code to the site on github, but keep sensitive configuration locally, or run a db locally

10:10 trptcolin: not sure i follow how that use case motivates that execution context, but maybe the "client" could run an nrepl server.

10:11 gtrak: well, the server has a public IP, my local box doesn't :-)

10:12 trptcolin: oh, ok, so this isn't about remote-executing on *many* clients, it's more of a work-delegation thing?

10:12 gtrak: yea

10:12 though I suppose there are use cases I haven't thought of that make sense for multiple clients

10:13 like a distributed computing grid

10:18 I found this: https://github.com/nakkaya/net-eval/blob/master/src/net_eval.clj maybe I can adapt it

10:25 actually, I can get rid of one use case, is there a safe clj reader that just allows literals?

10:27 found it, clj-config

11:11 miner49r: ,(doc sequence)

11:12 clojurebot: Execution Timed Out

11:45 twhume: Anyone up for answering a newbie-q?

11:46 AimHere: That's not how IRC works. Just blurt the question out into the ether, and ghostly voices may, or may not reply

11:47 Asking to ask is considered silly

11:48 twhume: OK… I'm trying to rewrite this to use a short-form anonymous function passed to map:

11:48 (defn digest [input]

11:48 "Parses an input block of text and returns a sequence of name/number pairs, each of which indicates a word from the input and the confidence of its importance"

11:48 (let [words (str/split input #"\s") ]

11:48 (into {} (map (fn[key] [key (count (filter #{key} words))] ) words))

11:48 ))

11:49 I thought it'd be (into {} (map #([% (count (filter #{%} words))]) words)) … but no.

11:49 AimHere: Well for future reference, I suggest pastebinning anything that's more than one line of code

11:49 * twhume goes to look up pastebin

11:50 stuartsierra: #([ is wrong. It's like trying to invoke the vector.

11:50 See http://dev.clojure.org/display/doc/FAQ under "Syntax"

11:51 twhume: Thanks stuart :)

11:51 stuartsierra: twhume: 'welcome

12:07 TimMc: technomancy: Huh, I wonder why the nix package manager isn't in the Ubuntu repos.

12:29 dnolen: Started a Clojure GSoC 2012 project ideas page - http://dev.clojure.org/display/community/Google+Summer+of+Code+2012

13:05 cran1988: hi!!! how to run a thread with time limit ?

13:05 for example to run a thread for 5 sec only

13:06 lucian: cran1988: it's not possible to stop a thread from another thread reliably, in general

13:08 cran1988: lucian: so i can not say (thread (run-something) 5000) where 5000 is 5 seconds

13:09 lucian: cran1988: as i said, not reliably. there's thread interruption APIs, but they don't always work

13:09 raek: cran1988: it is possible to force a thread to stop, but there are issues: http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

13:09 lucian: that's generally something only possible with processes

13:10 cran1988: (thank-you!)

13:10 lucian: although if what you're trying is a time-limited sandbox, you could conceivably have the sandbox make sure it would be relatively safe for it to be killed

13:11 cran1988: sandbox sounds good

13:12 lucian: what are you trying to build?

13:15 cran1988: i try to run jetty-server only in a specific time

13:15 ibdknox: jetty has a shutdown functio

13:15 n

13:15 just call that from another thread after n-seconds

13:17 cran1988: yes you are right ... now i am imagine it using Thread/sleep

13:17 ibdknox: no

13:17 just use a Timer

13:17 cran1988: Timer ?

13:18 ibdknox: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html

13:19 cran1988: it looks great thanks!!

13:26 clj_newb: Hi can I obtain an InputStream out of a String?

13:27 I'm trying to parse xml, but I have a String (as I can see in (class var)) but xml/parse keeps looking for a File called like the content of the xml string

13:28 rlb: clj_newb: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/with-in-str

13:28 perhaps?

13:28 raek: clj_newb: if the API you are using acceps Readers (text streams), you can use a StringReader

13:29 if you really need an InputStream (binary data stream), convert the String into a byte array and create a ByteArrayInputStream

13:29 (StringReader. "foo bar")

13:29 clj_newb: I tried (parse (with-in-str var)) but does not work and also the (input-stream var)

13:30 gtrak: is there a way to treat environment variables as a map?

13:30 raek: (ByteArrayInputStream. (.getBytes "foo bar" "UTF-8"))

13:31 rlb: ahh, right.

13:32 clj_newb: thanks raek

13:33 gtrak: oh yea, system.getenv() returns a map

13:34 vijaykiran: (into {} (System/getenv))

13:34 gtrak: yup, just found it :-), beautiful

13:35 ,(into {} (System/getenv))

13:35 clojurebot: #<AccessControlException java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.*)>

13:35 gtrak: &(into {} (System/getenv))

13:35 lazybot: java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.*)

13:35 vijaykiran: the bot java.policy is different, I guess :)

13:36 cran1988: are there any good examples for scaling clojure ?

13:36 sritchie: cran1988: scaling in what sense?

13:36 vijaykiran: what you mean by scaling ?

13:36 cran1988: the same way the web administrators do

13:37 vijaykiran: scaling clojure web applications ?

13:37 cran1988: yes

13:37 vijaykiran: depends on type of app you build - I guess.

13:38 sritchie: cran1988: yeah, people toss around the term "scale" a lot --

13:38 better to talk about # of machines, or requests per second, or something that can be benchmarked

13:39 here's a nice post by dnolen on benchmarking aleph: http://dosync.posterous.com/22516635

13:39 gtrak: infinite requests/(machine*seconds)

13:40 cran1988: thanks , i am checking it now ...

13:40 lucian: web requests are an embarrassingly parallel problem. the only hard bit is the data store

13:41 clj_newb: raek: it worked, thank you! But is there any clojure-only way to do it ? wondering

13:42 cran1988: so i should use a NoSQL server ?

13:43 lucian: that benchmark is stupid

13:43 just don't worry about it for now, make your app first

13:43 vijaykiran: cran1988: there's no one single answer - as I said, it always depends on what kind of application you are trying to build

13:43 lucian: and use postgres if sql fits

13:44 cran1988: yes postgres i am using ... ok thanks , i understand

13:58 can i ask something ? every object that i create in repl , stay alives for how long ? can i destroy an object in the repl ?

13:59 i think i ask to much

13:59 lucian: cran1988: why would you care?

13:59 it stays alive as long as there's a reference to it

13:59 cran1988: for fun

14:00 i thought lisp is just an OS :D and objects are programs

14:03 lucian: some early lisps were similar to what one might call an OS nowadays

14:03 clojure objects are at some point jvm objects

14:04 scriptor: cran1988: but otherwise, clojure and most other modern lisps are just regular programming languages, objects you create in the repl reside in the memory given to that repl

14:04 cran1988: yeah , jvm does not give control over objects

14:05 scriptor: cran1988: what do you mean?

14:06 cran1988: the Object Class does not have a method to destroy itself

14:06 lucian: why would it?

14:06 just don't reference it, the gc will clean it up

14:06 scriptor: that method is only needed when something *extra* needs to be done when the jvm destroys it

14:07 lucian: and there are finalizers, but they're rarely useful (and the way they're implemented in the jvm makes them problematic)

14:08 ferd: What's more idiomatic?: (:key mymap) or: (mymap :key)

14:08 cran1988: hm... its ok ... clojure is great , i was just checking how far it can go.

14:08 lucian: ferd: from what i've seen, neither. whichever feels better

14:09 dnolen: ferd: (:key map)

14:09 rlb: (and in many cases, relying on a destructor can be "wrong" (in any language) -- i.e. closing files, for example)

14:09 scriptor: cran1988: how far did you want it to go? A repl is basically like python's interactive prompt or ruby's irb

14:10 ferd: thanks

14:10 cran1988: i want clojure repl goes even far than python and ruby. In my mind , I have SBCL and Factor

14:10 dnolen: ferd: field/property access is generally of that form - (.field object) and (.-property object) in CLJS

14:11 scriptor: cran1988: what can SBCL's repl do that clojure's can't? I'm curious about this

14:12 I know factor's repl has some neat tricks related to reloading code

14:13 ferd: dnolen: I "feel" more confortable with (:key map)... But (map :key) makes more sense if I have to explain why it works :-)

14:13 pipeline: i was honestly unaware until now that clojure didn't support reloading running code

14:13 dnolen: ,(nil :key)

14:13 ,(:key nil)

14:13 clojurebot: nil

14:13 #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0)>

14:14 dnolen: ,(nil :key)

14:14 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0)>

14:14 dnolen: ferd: also you should consider this ^

14:14 cran1988: scriptor: not only that , in Lisp you control the gc for real

14:14 lucian: pipeline: it kinda does

14:15 ferd: dnolen: good point

14:15 lucian: pipeline: the same way java supports it

14:15 pipeline: http://travis-whitton.blogspot.com/2009/09/hot-code-swapping-with-clojure.html

14:19 callen: Serious question, is it normal for 4Clojure to make you feel stupid/frustrated? I feel like I could come up with the answer an order of magnitude faster in a different language sometimes.

14:19 I don't think my brain has fully enveloped immutable FP yet.

14:20 lucian: callen: i feel the same, often

14:20 callen: well my concern is that I'll never shake the feeling

14:20 lucian: i doubt it, there was a time when i had trouble with while loops

14:20 callen: if I can't shake that feeling and inability to avoid getting stuck like that, it's difficult for me to justify using the language.

14:20 dnolen: callen: I now feel the opposite

14:21 callen: I don't think I want the opposite either, I have to interact with code I haven't written on a regular basis. I guess I'm wondering if there's a way to fix my brain, and if the way of fixing it is to keep going with 4Clojure.

14:21 lucian: i've sometimes written it in python iteratively, then rewritten in python functionally, then clojure/scheme

14:22 callen: I have 44 problems solved on 4Clojure and I still feel like a fricking idiot.

14:22 lucian: callen: SICP appears to help me, give it a try

14:22 callen: nono, I've done SICP Scheme before

14:22 lucian: then?

14:22 callen: you tell me chief. I'm having the same friction with Clojure that I had with haskell.

14:22 I didn't have this with CLisp or Scheme.

14:23 dnolen: callen: I don't personally find working on 4Clojure a useful way to understand the ins/outs the language

14:23 lucian: clisp i can see, but scheme? it doesn't exactly encourage mutability

14:23 dnolen: I'd rather see how Clojure applies to common problems.

14:24 * lucian couldn't even write mergesort in clojure yesterday

14:24 callen: lucian: admittedly, and I was more adept at CLisp than Scheme.

14:24 lucian: terrible stack traces and debuggers sucks too

14:25 callen: dnolen: well, I know I can play database fire brigade (my common day-to-day) with Clojure, but I want to try to push myself so that I know my limits.

14:25 I'm wondering if I shouldn't go ahead and proceed with my idea for a side project (which is something that scratches an itch of technomancy's) and see how it goes.

14:25 scriptor: callen: what's the main issue you have, translating what you want into a functional style?

14:26 dnolen: callen: I'm not talking about talking to databases - commons tasks like manipulating data, modeling solutions

14:26 callen: scriptor: somewhat. It's worth remembering that my Python is functional as it is, but I fall back to mutation/reassignment from time to time and the inability to do so in Clojure is *BORKING* my head.

14:27 scriptor: I've 44 questions done on 4Clojure, still feel like a moron.

14:27 gtrak: playing around with moustache, why does the ring map after having been routed not have a :url relative to root, and how would I get that?

14:27 scriptor: callen: hmm, I guess you could try redoing some of those questions and seeing if it's any easier this time around

14:28 callen: scriptor: well, I either come up with the answer in a few seconds

14:28 scriptor: or I spend an inordinate amount of time on it.

14:28 oftentimes because I don't know stuff like complement or tree-seq exists.

14:29 dnolen: callen: how long have you been writing Clojure? (also a well placed atom is a lovely thing)

14:29 callen: scriptor: the problem is that it feels "tricky" to me, like the questions on 4Clojure are impossible-feeling until I know some sort of trick/fold to it.

14:29 dnolen: off-and-on for like a year.

14:30 the problems on 4Clj feel brittle is the word I would use. They don't gradually unravel or break-apart like the things I do in Python.

14:30 scriptor: do many of the 4clojure problems need mutation? I thought most of them were doable without

14:30 callen: all of the ones I've done so far are doable without.

14:31 I've not used a single mutable datatype so far.

14:31 I think that's sorta the point, to understand how to do things immutably.

14:31 the problem is that I find the process disheartening/discouraging and it's making me feel like I'm too stupid for the language/paradigm.

14:31 dnolen: callen: I find it strange that people rely on online resources for learning something the new - why not learn Clojure w/ a really good book on FP, rhickey's list of resources on Amazon is incredible

14:32 scriptor: I had the same issue with haskell in the beginning, the idea of declarative programming helped a lot

14:32 callen: dnolen: I purchased Fogus and Halloways books IIRC

14:32 scriptor: I understand the concept.

14:32 scriptor: if I didn't, I wouldn't have gotten 44 problems done.

14:33 tmciver: callen: FWIW, I feel similarly. I think a lot of the problems of 4clojure marked easy are not that easy. I'm not looking forward to the hard ones.

14:33 callen: scriptor: it's that the process of coming to an answer is too binary and makes me feel stupid until it suddenly unravels.

14:33 tmciver: that's encouraging, thank you.

14:33 sort of.

14:33 tmciver: dnolen: cool. I'll have to look into those resources myself.

14:33 callen: except for the part where I wonder where amalloy_'s head is.

14:33 dnolen: btw, loved your talk on predicate dispatch if you're who I think you are.

14:34 dnolen: callen: I think 4Clojure is about puzzles not problems - I've also found that a good book on Haskell or Standard ML is a killer way to focus on functional thinking.

14:34 callen: thx!

14:34 callen: dnolen: the problem is that I found OCaml and Haskell *agonizing*

14:35 I own Programming in Haskell on Amazon, *shudders*

14:35 dnolen: callen: did you read a good book? (I think Real World Haskell stinks)

14:35 callen: The Craft of Functional Programming (Haskell) is very good

14:35 callen: dnolen: supposedly PiH is the foremost book for plain ole programmers wanting to learn Haskell.

14:35 dnolen: I find the *semantics* agonizing.

14:36 scriptor: lyah does a decent job at at least introducing FP's concepts and how to work with it

14:36 dnolen: callen: doesn't mean it doesn't stink, I hate books that don't start with programming.

14:36 right away

14:36 tmciver: dnolen: I'd assume that it would be difficult to learn clojure with a book on ML or Haskell.

14:36 callen: I'm not new to FP, I'm new to trying to get things done with FP without having mutability available.

14:36 I like the concept of transformation and threading immutable data through composed functions.

14:36 you guys have to understand, I've been writing CLisp for literally half my life, as long as I have C.

14:36 lucian: i'm rewriting my first 4clojure solutions, they're tons shorter now :)

14:36 callen: it's not the FP, it's the immutability.

14:37 dnolen: tmciver: not really, a lot more of Clojure makes sense if you've read a book on Haskell/SML

14:37 callen: my default code doesn't mutate.

14:37 dnolen: and I have, and I ran for the hills screaming :(

14:37 scriptor: tmciver: not really, once I learned enough of haskell learning clojure's syntax got me pretty far

14:37 tmciver: dnolen: Hmm, that's interesting. I've been thinking of learing Haskell anyway.

14:37 lucian: learn you a haskell for great good is interesting

14:37 dnolen: callen: find a better book

14:37 callen: I desperately want to use Clojure more regularly and I'm struggling.

14:37 tmciver: lucian: yeah, I've heard a lot of good about that book.

14:37 dnolen: if you having a hard time - often the teacher stinks

14:38 4Clojure is not a teacher, it's just disconnected puzzles

14:38 callen: it's helped me to learn a lot of core though.

14:38 like tree-seq, mapcat, etc.

14:38 scriptor: lyah is pretty good, especially if you get to the part where it introduces how map/fold/filter/etc are implemented

14:38 and instead of reading the implementations you try to write them yourself first

14:38 callen: I understand things like map, foldl, foldr, reduce, and filter just fine.

14:39 scriptor: callen: can you give a specific example where it's the immutability you had a problem with?

14:39 ferd: Exercise: Cleanest way to know of "map-y" is fully contained on "map-x"? My naive take: (every? #(= (get map-x %) (get map-y %)) (keys map-y) )

14:39 callen: Most of the problems on 4Clj are trivial for me, but will totally gork me. Let me link an example.

14:39 scriptor: I think I have an approach for this, but it took me far too long to come up with: http://www.4clojure.com/problem/30

14:40 my approach involves abusing .indexOf

14:40 but I'm having a problem modeling the iteration in my head.

14:40 dnolen: callen: knowing about the various fns is less useful than understanding how to write useful programs w/o mutations - even better when you understand where mutation *simplifies* the problem.

14:40 callen: as well as the aggregation.

14:41 dnolen: when/where is it appropriate to use mutation in Clojure? I felt like it was supposed to be avoided at almost all costs.

14:41 dnolen: callen: nope

14:41 callen: how does one do mutations if it's simply a mechanism for an algorithm or approach? var?

14:42 dnolen: callen: clojure.xml uses mutation, ClojureScript compiler uses mutation to simplify identifying loop/recur expressions

14:42 * callen digs up the code in his copy of the repo

14:42 dnolen: when it makes sense to use state - use it.

14:43 callen: dnolen: since you're a contributor I thought I'd ask, how open are they to Ruby-esque helper-functions for strings that eliminate duplication of effort?

14:43 dnolen: I wasn't certain how austere they wanted String.clj to be.

14:44 in core that is.

14:44 Vinzent: callen, why do you need .indexOf? You can use e.g. (reduce (fn [[acc prev] new] ...))

14:44 dnolen: callen: I think simple helper functions will have a hard time making it in. but you can try!

14:44 callen: best to bring it up on the dev ML first

14:44 callen: of course.

14:44 dnolen: is there a guiding document or something that describes what they prefer to see?

14:45 I take it they don't want anything that they think most people can come up with themselves or isn't somehow foundational?

14:45 Vinzent: callen, also, if you really need mutation, you can use java arrays (see to-array, aset, etc)

14:45 dnolen: callen: pretty much.

14:45 callen: I'd rather not, I think my brain is just broken.

14:45 Vinzent: I'm not totally sure where you're doing with that reduction :(

14:46 I mean, I figured it was a reduction, (the answer to #30), but the devil is in the details.

14:46 let me see what I can come up with.

14:48 dnolen: ferd: (every? #(= (% map-x) (% map-y)) (keys map-y))

14:49 callen: Vinzent: can you tell me where you were going with that? :(

14:50 Vinzent: callen, yeah of coursr here is the code: https://gist.github.com/1918617 It's pretty common pattern to use reduce with accumulator instead of explicit loop\recur

14:51 hm, actually I don't need prev at all

14:51 callen: I find loop/recur awkward still, so I was trying to avoid it

14:52 It may be that part of my problem is that I haven't developed this repertoire of methods like reduction with an accumulator and a threading macro.

14:53 Vinzent: how'd you eliminate prev?

14:53 Vinzent: callen, I've gisted updated code

14:54 callen: Vinzent: thank you!

14:55 Vinzent: callen, yeah, it quickly becomes your second nature and you're starting using such things without even thinking about them

14:55 np, glad to help

14:56 callen: Vinzent: the problem is that my faculties for modeling the problems are limited because the way one generally uses FP in say, Python, is purely for simple one-dimensional threading/transformation of data.

14:57 if you get my meaning.

14:58 scriptor: callen: since lacking the repertoire of knowing all the idioms is an issue, I think picking up a good book and start a decent-sized project might be the way to go

14:58 callen: scriptor: I agree on picking up a good book. the current project I have in mind might too easily allow me to dodge my limitations though.

14:59 scriptor: what's it involve?

14:59 callen: scriptor: I have Programming in Clojure 1st Ed and Joy of Clojure

14:59 scriptor: it's conceptually just an IRC bouncer, but I want to build an IRC framework around it so that people can easily make things like IRC bots, clients, etc.

15:00 scriptor: technomancy wanted one awhile back and I haven't delivered yet :(

15:01 scriptor: sounds like a good project, you might be putting too much emphasis on 4clojure itself

15:01 callen: I feel like I shouldn't by stymied so easily by 4Clojure.

15:01 be*

15:02 well. "easily", it's an 80/20 thing. 80% of the time, I breeeeze right through it, 20% of the time, I get stuck really badly.

15:03 sramsay: Question: Is there a way to take a system path string (e.g. /home/rhickie/foo/bar.txt) and turn it into a URL (file:///home/rhickie/foo/bar.txt)?

15:03 ferd: dnolen: Thanks. That's almost exactly like the my first take (except I used "get" hoping to make it clearer)

15:03 Vinzent: callen, yeah, it requires some time to get used to. You may want to try to translate some of your python code to clojure - i think it's a good exercise

15:04 callen: Vinzent: most of my Python code is pretty damn FP already, I'd just be rewriting the syntax. I have to find those painful edge cases to really bump into this. That's the usefulness of 4Clojure.

15:05 scriptor: callen: hmm, for both the irc project and translating python you've said that it'd be pretty easy, why not go ahead any see if it is ;)

15:05 callen: the tricky part of the IRC project isn't the lang or the immutability

15:05 it's modeling the hand-offs

15:05 that'd be a PITA in any language.

15:05 it's basically a dispatch problem.

15:06 I could model each client as an agent.

15:09 thanks everyone for your advice and help. I'll start on my project and start working through another book.

15:11 jaley: I'm playing with writing a connect 4 AI in Clojure. Any recommendations on how to represent the board states? I was planning to just use a vector of vectors. Is there a better way?

15:20 gfredericks: jaley: that sounds decent

15:20 empty row == empty vector or vector with blank entries?

15:21 scriptor: probably blank entries

15:21 gfredericks: I like empty vector better, since in connect 4 you can only add to the end (top?) of a column

15:21 jaley: gfredericks: yeah - thinking blank enteries, so I can drop-while == :_

15:21 gfredericks: so you have conj/pop, rather than assoc

15:22 I guess I shoulda said "column" instead of "row"

15:22 but I think it's all personal preference at this point

15:23 jaley: also, I don't think any choice of data structure here will make detecting wins simpler :/

15:23 diagonals!

15:23 gfredericks: sure it will, if you use the data structure {:winning-moves [...], :losing-moves [...]}, then it's quite easy

15:24 jaley: oh... I was thinking of writing something like, (defn win? [board] ...)

15:25 gfredericks: yeah that works too

15:25 doesn't tell you what to do to win though

15:25 jaley: :-)

15:25 i'm sure the dots will work...

15:26 solutions are always sparse in clojure

15:26 gfredericks: I guess the most information is win/lose/draw and a move-count

15:26 or something like http://www.shredderchess.com/online-chess/online-databases/endgame-database.html

15:37 Bronsa: isn't there a way to have varargs using deftype?

15:37 gtrak: seriously contemplating writing yet another url parser/micro-router

15:37 moustache is like 80% what I want but not quite

15:39 brehaut: gtrak: if you do, reversible routes would be my number one feature ontop of what moustache offers

15:39 gtrak: what's a reversible route?

15:40 brehaut: it lets you referenate a url from a route and a list of arguments

15:40 gfredericks: functions -> URLs?

15:40 gtrak: ah, interesting idea

15:41 brehaut: ive thought about adding it to moustache myself, but that code is quite complex ;)

15:41 gtrak: brehaut, yea, that's kind of the issue I'm having now, it expects the url path segments in a format that won't let me specify it just once

15:41 so when I generate the links in my templates, there's no simple way to correlate it to the route

15:41 brehaut: ah sure

15:41 yeah, i maintain some multimethods to reverse stuff in my code

15:42 (but thats relatively easy because im using big blobs of couchdb data with :type tags)

15:42 gtrak: oh, I'm just tooling around on basic web stuff, writing my own framework, considering it as an opportunity for playing with core.match, though?

15:43 brehaut: i no idea sorry ;)

15:44 if you could use core.match to make static routes that'd be pretty cool though

15:44 gtrak: it seems like it

15:44 brehaut: both moustache and compojure allow fall throughs, so theres an opening for something different

15:45 Raynes: cgrand doesn't write anything that human beings can comprehend.

15:46 gtrak: yea, that's nasty stuff

15:46 I want something much simpler

15:48 and core.match gives bindings already

15:58 brehaut, for reversible routes, you'd need to define mappings that are truly invertible, is there any way to tell that an arbitrary mapping is equivalent to another?

15:59 brehaut: not in an arbitrary way i dont think?

16:00 gtrak: I think you can't do much better at the end of the day than passing a seq of the original url into the handler?

16:01 and maybe provide some functions, like generate a url like the one I have, except change the third-from last path segment?

16:02 brehaut: if i were to write it ontop of what moustache provides

16:02 id want a way to name routes, possibly as meta data? and a Reversible protocol

16:03 gtrak: I still don't quite get it, the point is to simplify route generation within the handler or downstream, yes?

16:03 brehaut: yeah

16:04 django's got a reasonable implementation

16:04 gtrak: hmm

16:04 brehaut: but it leverages the fact that you can compare functions in python

16:05 gtrak: do you have a link?

16:05 brehaut: trying to find it

16:05 djangos docs are comprehensive, but a bit of a pain to navigate

16:06 https://docs.djangoproject.com/en/1.3/ref/templates/builtins/#url is probably the most useful examples of it in use (in the template language)

16:06 gtrak: wait... so is the generated url actually meaningful?

16:07 brehaut: yes

16:08 gtrak: ah, I see

16:08 how does it know?

16:08 brehaut: https://docs.djangoproject.com/en/1.3/topics/http/urls/

16:08 thats the general url config docs; but i cant point you to a single useful point

16:08 gtrak: i did a little bit of django once, it was way too magical for me

16:08 brehaut: https://docs.djangoproject.com/en/1.3/topics/http/urls/#reverse just tells you the same stuff as url does

16:09 i have many grumbles about django ;)

16:09 urls are the part that i would complain about the least

16:09 ibdknox: have you guys heard of Noir? I hear it's less a lot more straightforward than django ;)

16:09 confusion abounds

16:09 brehaut: ibdknox: too much ceremony! raw ring for life

16:10 gtrak: ibdknox, do you use it? ;-)

16:10 ibdknox: gtrak: I've been experimenting with it. Still reserving my judgement until I really dig in

16:10 gtrak: i hope the vim's not slowing you down too much

16:10 ibdknox: I'm very close to a killer CLJS demo

16:11 I have Bret Victor's modify a game while it's running thing basically done

16:11 in cljs :D

16:11 gtrak: awesome

16:11 ibdknox: getting the cljs compiler to play nicely in real-time was interesting

16:12 dnolen: ibdknox: always working on the cool stuff

16:13 ibdknox: dnolen: well.. I've been working from sun up to sun down the past couple weeks, I needed to do something fun :)

16:14 the whole thing ended up being surprisingly simple

16:15 I think even the projecting time into space thing is pretty easy. haven't done that part yet

16:15 bbloom: Just yesterday I came up with something that seems to work for cljs & vim relatively nicely

16:15 dnolen: ibdknox: you going to demo this @ ClojureWest?

16:16 ibdknox: bbloom: oh?

16:16 bbloom: here's what i do:

16:16 https://github.com/franks42/lein-repls

16:16 ibdknox: dnolen: I was going to write a blog post about it tonight :)

16:16 bbloom: run two terminals

16:16 both in tmux

16:16 in one, i run lien repls

16:16 in the other i run cljsh

16:17 so they share an environment

16:17 then i open two macvims

16:17 one in my clj directory

16:17 and one in the cljs directory

16:17 src/clj and src/cljs that is

16:17 then i use vim-tslime

16:17 one per vim for each of the tmux sessions

16:17 dnolen: ibdknox: sweet

16:18 ibdknox: dnolen: with a little video and the code so people can mess around with it, or at the very least see it

16:18 dnolen: bbloom: also probably worth a blog post, not enuf CLJS workflow info out there.

16:18 ibdknox: !

16:18 bbloom: this results in a 4-way split screen with a server/macro terminal & vim; and a terminal/vim client side terminal

16:18 ibdknox: since it's CLJS, which has to compile putting it on a website probably won't work.. the latency would kill the changes as you type bit of it

16:19 bbloom: dnolen: ok,maybe I'll write it up later — where is best to help people find such an article? post it on mailing list?

16:20 ibdknox: dnolen: I will say though, it is ridiculous amounts of fun. He was right about this being a much better experience

16:20 dnolen: bbloom: yes, also perhaps worth linking to from the ClojureScript wiki

16:21 bbloom: good call

16:21 would really like to see more work done on networked repls in the core clojure stuff

16:21 ability to fork repls

16:21 multiplex them

16:21 etc

16:22 i'd love to send a form from vim to multiple simultaneous browsers

16:22 stuff like that

16:22 dnolen: bbloom: brenton ashworth is working on that feature for CLJS

16:22 bbloom: awesome.

16:22 link?

16:23 dnolen: bbloom: I'm sure he could use help, https://github.com/clojure/clojurescript/tree/multi-browser-repl

16:23 bbloom: if you haven't sent in your CA, you should, and then pitch in :)

16:24 bbloom: dnolen: I'm a registered contributor now :-)

16:24 still need to push harder on the Var work for cljs I did…. I'm finding them useful, but I don't have a demo ready yet...

16:24 octagon: hello clojure! i'm new, and trying to figure out some of the basics of functional programming. i feel like i should be able to define this function, (defn collect [f] (comp f vector)), without using defn, and only by composition of higher order functions. example usage ((collect (partial reduce +)) 1 1 1) => 3

16:24 bbloom: brb

16:27 gfredericks: octagon: is there a more motivating use case for this? your thing there is can obviously just be (reduce + [1 1 1]), since the arguments are given explicitly...

16:28 or are you just trying to play around with point-free expressions?

16:28 octagon: gfredericks: yes, i feel like i'm missing some important concept here

16:29 gfredericks: what makes you think that? what made you think of this "collect" function?

16:29 octagon: gfredericks: well i'm trying to understand which of the higher order functions are the real fundamentals

16:30 gfredericks: and which ones can be built just by composing those fundamentals

16:30 gfredericks: oh man; that sounds messy

16:31 octagon: gfredericks: so collect is just an example of binding stuff out of order

16:31 gfredericks: like a reversed partial?

16:32 * gfredericks likes the name "rartial"

16:32 octagon: gfredericks: i considered this (defn applyto [args f] (apply f args))

16:32 gfredericks: but it didn't turn out to be completely useful in this case

16:32 gfredericks: you know using (partial applyto ...)

16:33 gfredericks: i have a "partiar" btw

16:33 gfredericks: I guess I still don't quite understand the way you're approaching it, but I'm sure we could change your original defn to be point-free just for the fun of it...

16:34 octagon: gfredericks: point-free, i didn't know that term

16:35 gfredericks: (def collect (comp (partial apply comp) reverse (partial list vector)))

16:35 * jkkramer shields his eyes

16:35 gfredericks: octagon: point-free means not using function literals, I believe

16:35 or locals in general

16:36 octagon: gfredericks: yes, and google comes up with all kinds of interesting things that refrerence the term

16:36 gfredericks: I think.

16:36 octagon: it seems to be what you're trying to play around with

16:36 octagon: gfredericks: totally, thanks for that

16:37 gfredericks: sure

16:39 octagon: is there any discussion of the design tradeoffs involved with using varargs like clojure does?

16:50 mdeboard: So I'm using type dispatch in a multimethod (https://github.com/mattdeboard/clj-solr/blob/master/src/clj_solr/core.clj#L6) because I don't know how to dispatch based on arity, and haven't been able to find any examples of arity dispatch. How would I go about doing this?

16:50 gfredericks: you can't (defmulti foo (fn [& args] (count args)))?

16:50 mdeboard: gfredericks: Oh.

16:50 gfredericks: (defmulti foo (comp count list)) also

16:51 brehaut: i wonder if theres much difference between list and (fn [& args] args)

16:51 gfredericks: mdeboard: so you want it extensible? just providing different function definitions doesn't work?

16:51 mdeboard: gfredericks: My objective is to capture arity cases `[foo & kwargs]` and `[& kwargs]`

16:52 gfredericks: mdeboard: how do you recognize a foo?

16:52 mdeboard: which I can't do with e.g. `(defn foo ([foo & kwargs] stuff) ([& kwargs] stuff))`

16:52 brehaut: ,(first (apply (fn [& args] args) (range)))

16:52 clojurebot: 0

16:52 brehaut: ,(first (apply list (range)))

16:52 clojurebot: Execution Timed Out

16:54 gfredericks: mdeboard: so all you want is an optional first argument?

16:54 mdeboard: gfredericks: Well, to be specific about my example, the signature for the (filter) function would be either `[my-node :param1 val :param2 :val]` or just `[:param1 val :param2 val]`

16:54 right

16:54 gfredericks: mdeboard: you have a default value for when it's missing?

16:56 mdeboard: gfredericks: If it's missing, it just returns a hash-map of the args. If the optional first argument is missing, it inserts a node as a sibling to the optional first argument.

16:56 "...inserts a node composed of a hash-map of the args as a..."

16:58 That sounds kind of dumb now that I've typed it out.

16:58 gfredericks: yeah I don't think there would be built in support for this kind of thing because there's no default way to tell if the first arg is there; but if you supply a first-arg-recognizer you could make a simple enough HOF for this...

16:58 mdeboard: HOF?

16:58 clojurebot: HOF is Higher-Order Function

16:58 mdeboard: ah

16:58 gotcha

16:59 type dispatch it is.

16:59 gfredericks: :/

16:59 mdeboard: :P

16:59 I think I'm just going about this dumb.

16:59 technomancy: callen: I think 4clojure is designed to be frustrating in a way

17:00 callen: technomancy: you're telling me, I spent last night pissing blood until I passed out at 6 am.

17:00 gfredericks: is it unidiomatic to use multimethods that aren't intended to be extended?

17:00 technomancy: it's trying to tie your hands behind your back and force you into a corner so you have to learn something new to break through

17:00 mdeboard: callen: I... I don't think that was 4clojure.

17:00 technomancy: hah

17:00 callen: anyway, I wouldn't beat your head against it; it's probably healthy to vary between that and something more practical

17:01 gfredericks: I wouldn't say that

17:01 callen: technomancy: my ulcer thanks you. I'm getting back on that IRC bouncer.

17:01 technomancy: callen: no pressure though!

17:01 callen: technomancy: startup life hijacked my soul.

17:01 gfredericks: technomancy: doesn't it unnecessarily break up a function's definition?

17:01 callen: technomancy: sure, but I want to make something that is of use to you, you've made a kajillion things that the community depends on.

17:02 gfredericks: seems kind of messy :/

17:02 at least wrt code structure

17:03 technomancy: gfredericks: you mean it's not intended to be extended outside your own code base or it's not intended to be extended beyond a single dispatch value?

17:04 mdeboard: gfredericks: Well, my foray into multimethods was just to do *something* with them since I'd not used them before. I wrote one that works but I don't like how the methods return different types of things.

17:04 s/works/does what I wanted

17:06 gfredericks: technomancy: a small fixed set of dispatch values. So no reason for anyone else or even myself to extend it

17:06 technomancy: sounds like simple polymorphism to me

17:06 gfredericks: :/

17:07 maybe I don't mean anything

17:11 pipeline: whover pointed out 4clojure is a pretty awesome dude

17:11 gfredericks: only one-third as awesome as whoever made 4clojure

17:11 callen: pipeline: you're welcome?

17:12 pipeline: thank amalloy

17:12 mdeboard: pipeline: Warning, 4clojure will apparently make you piss blood

17:12 * callen whimpers

17:12 bbloom: dnolen: https://github.com/clojure/clojurescript/wiki/Vim

17:12 Raynes: amalloy didn't start 4Clojure.

17:12 mdeboard: callen: What problem exsanguinated you

17:12 Raynes: That would be dbyrne, wherever he is.

17:12 mdeboard: He's in my basement

17:12 callen: Raynes: I saw his commit. name names if you like.

17:12 bbloom: ibdknox: youu too

17:13 hopefully that will help cljs vim users out :-)

17:13 cemerick: mdeboard: thank you for 'exsanguinated' :-)

17:13 amalloy: yeah, that's today's word of the day

17:13 mdeboard: cemerick: Triple word score

17:13 callen: mdeboard: I'm 44 problems in. I've breezed through 80% of the problems, and gotten rather stuck on 20%. A recent sticker is: http://www.4clojure.com/problem/30 but someone showed me how to do with a reduce + accumulator pattern.

17:13 mdeboard: oh yeah

17:13 callen: mdeboard: it doesn't help that I'm not awful comfortable with loop/recur yet.

17:20 mdeboard: callen: Something that helped me when I was on a 4clojure marathon last weekend was learning about `partition-by`, `group-by` and `mapcat` . I used some formulation of those three (with `apply` and `reduce` sprinkled in here and there) for several solutions.

17:22 callen: mdeboard: tree-seq and complement saved my arse last night too.

17:22 I'll add those to my "contemplate deeply" list.

17:22 mdeboard: thank you.

17:22 mdeboard: for the flatten re-implementation?

17:22 technomancy: tree-seq is sublime

17:22 callen: mdeboard: yes.

17:22 mdeboard: I cheated and looked at the flatten source for that problem :P

17:22 Raynes: technomancy: text 2

17:22 callen: I accidentally re-implemented, then re-discovered tree-seq.

17:27 ivan: this may interest anyone backing up blip.tv https://github.com/ivankozik/youtube-dl/commit/801531e66a4a47d1c739ee93c77c1e6a73f6bacb

17:27 funny how the source videos are sometimes 3x smaller than the default .flv

17:28 mdeboard: technomancy: Why sublime? What about it blows you away?

17:30 technomancy: mdeboard: it's just such a high level of abstraction just sitting there

17:30 I think everyone coming to Clojure would expect to have to write it themselves

17:31 octagon: gfredericks: hey, thanks again. i found this excellent paper that describes exactly the thing i was trying to understand http://www.stanford.edu/class/cs242/readings/backus.pdf

17:36 amalloy: my most recent use of tree-seq was to find the largest number in a structure like {:a {:p [1 9 10] :q 4} :b [6]} with arbitrary nesting. tree-seq is so great for that

17:36 ivan: does this work for traversing directory trees?

17:36 amalloy: it works for anything you want. all the interesting bits are pluggable with functions

17:37 ivan: heh, I should have read one defn below and seen file-seq

17:37 nybbles: hey I'm reading through some lamina code - what does "^{:pipeline pipeline}" mean? seems like a general clojure thingie, it's in the body of a let

17:37 i mean.. syntactically

17:37 ivan: nybbles: metadata

17:38 callen: nybbles: it's short for (meta ...)

17:38 nybbles: they're tagging it.

17:39 nybbles: ivan, callen: ah ok cool thanks, didn't expect it in the middle of a function

17:39 amalloy: "it's short for (meta ...)" is totally wrong, though

17:39 mheld: hey y'all

17:40 callen: amalloy: well fuck. correct me. :(

17:40 nybbles: don't listen to me.

17:40 dnolen: callen: with-meta

17:41 amalloy: it's *close* to being shorthand for with-meta

17:41 nybbles: haha, ok, i figured as much :)

17:41 amalloy: but it's really read-time metadata, which is not the same thing as runtime metadata

17:41 callen: I was basing it on what I saw on the cheatsheet.

17:41 it said ^form is (meta form)

17:41 so that's why I misunderstood.

17:42 nybbles: amalloy: so the stuff in "^{}" will not show up in a function call to (meta.. ) with the tagged thing?

17:42 amalloy: that was probably true in clojure 1.0 or 1.1 or something, but it isn't anymore

17:42 nybbles: try it

17:42 nybbles: ok :P

17:43 amalloy: &(meta ^{:x 1} (map inc []))

17:43 lazybot: ⇒ nil

17:43 callen: now I am seriously worried I've missed something critical. :|

17:43 amalloy: naw. it's just that clojure.org never updates :P

17:44 callen: amalloy: is the site on github?

17:44 amalloy: if so, one could make a pull request or something.

17:44 amalloy: don't we all wish

17:45 callen: amalloy: is it worth proposing on the mailing list?>

17:47 technomancy: might as well mention it; just don't expect a response

17:47 amalloy: i suppose it's possible rich would let the website have a looser rein than the language

17:47 nybbles: hm

17:48 &(meta (with-meta {} {:x 1}))

17:48 lazybot: ⇒ {:x 1}

17:48 nybbles: ok that makes sense

17:48 &(meta ^{:x 1} {})

17:48 lazybot: ⇒ nil

17:48 nybbles: whaat

17:48 dnolen: callen: yes

17:49 nybbles: my clojure repl gives me: "{:x 1}"

17:49 weird

17:49 technomancy: nybbles: smells like a lazybot bug

17:50 nybbles: technomancy: ok so the problem is with lazybot, so why is it that with (meta ^{:x 1} {}) i should expect {:x 1}, but..

17:50 &(meta ^{:x 1} (into {} []))

17:50 lazybot: ⇒ nil

17:51 tjgillies: whats with symbols with asterisk, like *this* ?

17:51 dnolen: tjgillies: to denote vars that might be dynamically rebound

17:51 technomancy: nybbles: I think you're placing metadata on the into call

17:51 amalloy: IMO it's more of a bug in clojure that read-time metadata ever leaks out to runtime

17:52 technomancy: nybbles: that is, the metadata application happens in the reader before into is ever called

17:53 tjgillies: dnolen: by dynamically you mean by user or by program?

17:53 nybbles: technomancy: so why would the read-time metadata application be different for {} versus (into {} [])?

17:53 technomancy: nybbles: because {} evaluates to itself

17:53 since it's a literal

17:54 (into {} []) evaluates into a function call

17:54 and you're placing metadata on the source code, not on the result

17:56 nybbles: technomancy: so does it fail to attach read-time metadata to the literal and then fallback to run-time metadata, and that's why the (meta..) call returns non-nil?

17:56 amalloy: no. it attaches read-time metadata to the source code, and then just returns the source code at runtime

17:59 nybbles: ok i understand that for the (meta ^{:x 1} (into {} [])) situation, but how does that work for the (meta ^{:x 1} {}) situation? why would i get back {:x 1}?

17:59 amalloy: that's what i just explained

17:59 a literal evaluates to itself, so it just evaluates to the source code

17:59 the source code is: {}, with metadata of {:x 1}

18:00 tjgillies: can i tap a repl into an already running environment? like in erlang, or do i need to start the repl first always?

18:02 weavejester: tjgillies: repl first, as far as I'm aware, though in theory it should be possible to make a library to inject a repl

18:03 nybbles: amalloy: oh i get it now, ok thanks

18:04 theres a little section in Practical Clojure that's useful..

18:04 to understanding it

18:04 tmciver: amalloy: I'm confused by this meta stuff as well. For (meta ^{:x 1} (into {} [])), if metadata is being attached to the function call as technomancy says, why does that meta call return nil?

18:04 amalloy: it's not

18:04 it's being attached to the source code for that function call

18:04 nybbles: i wasn't realizing that the form gets evaluated and goes away, and then the result does not have the source code

18:05 arch i mean "the result does not have the metadata attached to it"

18:05 amalloy: the compiler has no use for that metadata, so it compiles a regular function call

18:05 nybbles: tmciver: it's being attached for the source code "(into {} [])"

18:05 tmciver: amalloy: it has no use for it so it removes it?

18:06 nybbles: with-meta is the call to attach it to the actual result of (into {} [])

18:07 tmciver: http://t.co/xNQI5YPP

18:07 tmciver: nybbles: thanks. Looking.

18:08 nybbles: that's one Clojure book I don't have. Do you like it?

18:08 nybbles: i don't have it either, but i like it now :)

18:11 tjgillies: hrm why doesn't leiningen create a default :main entry in project file? the majority of the time in my use cases it project_name.core

18:11 it's

18:11 amalloy: that assumes you want a :main at all. most of my clojure projects i don't bother

18:11 tjgillies: amalloy: how do you run them?

18:12 amalloy: repl, swank

18:12 tjgillies: ah, i thought that was just for debugging and exploratory didn't know people actually ran them that way

18:13 amalloy: when you're deploying into a production environment, sure, it's good to have a :main

18:13 but almost all the time you spend with a project is exploring and debugging

18:14 gtrak: hmm, why wouldn't I be able to instantiate a record from another ns? I've :use'd the ns

18:15 ibdknox: gtrak: gotta import it

18:15 gtrak: ah

18:15 ferd: &(and (resolve 'IamUndefined) (var? #'IamUndefined))

18:15 lazybot: java.lang.SecurityException: You tripped the alarm! resolve is bad!

18:15 dnolen: gtrak: IMO, better to use the provided ctor fns, or write your own.

18:16 gtrak: what's a provided one?

18:16 amalloy: only provided in 1.3+

18:17 but i agree that's true

18:17 ferd: i suspect #'IamUndefined get looked up at compile-time, so the short-circuiting and won't protect you

18:18 gtrak: ah, I see there's a factory function

18:18 ferd: amalloy: thanks... What's a clean way to check if a var is defined and bound ?

18:18 tjgillies: im calling (clojure.main/repl) in a function and it outputs a repl prompt, but when i type a command it doesn't "do" anything

18:18 amalloy: well resolve gives you the var back

18:18 just call bound? on that

18:18 tjgillies: using "lein run" to invoke

18:18 ferd: ahh... idiot

18:19 amalloy: but...this is a very questionable thing to be doing. why are you wondering whether a particular var is defined

18:19 ferd: I have a unit test that depends on some vars so me set (to load some fixture data)

18:20 if they are not set, I want to def them to some special values

18:20 the vars are normally set by the build environemnt... but when developing interactively, I want them to be automatically set to some values

18:20 am I clean ?

18:20 clear ?

18:21 amalloy: so why not just def them to the default values in source code, and then let the build env redefine them

18:21 rather than not defining them at all

18:22 ferd: hmmm but if I def them in the test (with a value) it will overwrite whatever value the env defined :-\

18:24 tjgillies: is there a convention for capitalizing hashmap keys? like :Foo vs :foo ?

18:24 ferd: amalloy: may be I can do something like: (do (def xxx) (if-not (bound? #'xxx) (def xxx "my-value")))

18:25 amalloy: there's gotta be a cleaner way... Learning here.

18:26 choffstein: Hey all. I have a system design question with clojure. I am trying to provide an API for data and proprietary algorithm access. I am using aleph as my HTTP server, with redis and resque-clojure to fire off background jobs. My issue is, I don't know the right way to get the jobs BACK to the HTTP server, or how to keep the HTTP server from just sitting in a holding pattern (and possibly blocking, or worse, timing out?) on long

18:26 tasks. My only thought was to theoretically associate a job UUID with each resque-clojure task, and just have my HTTP server poll redis over and over until the job is marked complete -- but that seems like overkill. My only other thought was maybe some sort of callback system using channels -- but I don't know if passing the channels over redis could even possibly work. Any ideas?

18:26 pipeline: mdeboard: I'm only on problem 24, so that's not really ar isk yet.

18:26 dnolen: tjgillies: Clojure doesn't generally capitalize anything - deftype/record/protocols are an exception in Clojure

18:27 ferd: just provide default values - if you're going to rebind something, perhaps you want dynamic vars. if not then you have with-redefs.

18:28 tjgillies: dnolen: i ask because in http://clojure.org/runtime_polymorphism there is a lot of captialized keys

18:28 are a lot*

18:29 dnolen: tjgillies: that's an old and somewhat intentionally contrived example

18:30 tjgillies: Clojurians don't usually capitalize their keywords

18:30 ferd: dnolen: ... hmm no... I have code that needs the value of a global var... but if this global var is not defined (and bound), then I what to define it with a default value.

18:30 So, I think I will def it (which is a noop if it's already defined) then check if it's bound?

18:32 tjgillies: dnolen: thnx

18:35 Raynes: http://en.wikipedia.org/wiki/Dead_Space_Extraction

18:35 Eh, wrong channel.

18:36 tmciver: Raynes: is that game any good?

18:36 Raynes: tmciver: It's pretty intense.

18:37 Not as much horror as I had hoped.

18:37 But plenty of action.

18:37 tmciver: Raynes: I'm surprised you have time for games.

18:37 Raynes: I really don't.

18:37 I hardly ever play games.

18:37 tmciver: I used to play some call of duty but ever since I found Clojure, not so much.

18:38 It's probably for the best; I was sick of getting my ass handed to me by 15-year-olds that play all day and night.

18:41 scriptor: this is probably far-fetched, but is there any way to destructure the metadata of an object?

18:42 tmciver: Raynes: I remember hearing that you tried working with enlive and then abandoned it. I'm trying to use enlive to do a html->xml tranformation; do youkonw if it's the right tool? It looks like it's good for filling in template files which is not what I'm doing?

18:43 Raynes: Well, I didn't really try and give up on it. A found a bug which was promptly fixed, but the reason I didn't use it after that was because mustache was a better fit for what I was doing.

18:43 I don't know how well Enlive would do in that situation.

18:44 tmciver: Raynes: OK, thanks.

18:46 amro: scriptor: same way you'd destructure anything, (let [... (meta foo)] bar) where ... is your destructuring

18:48 gtrak: what causes No single method: handle of interface ... on a record call?

18:48 some of the protocol methods work, others don't

18:48 scriptor: amro: right, but if you were to use this technique in the parameters you'd have to make every call to the function be something like (f foo (meta foo))

18:49 gtrak: oh shit, protocols don't do varargs

18:50 that's a little weird

18:51 amro: scriptor: then don't do it in the parameters. use a let inside your fn

18:51 scriptor: it'd be neat to be able to do something like (fn foo [{:value val :meta {:keys [meta-key1 meta-key2]}}] ...)

18:52 of course, that might conflict when you pass it a hash like {:value "bla"}

19:27 choffstein: Anyone here have experiene with Avout? I'm trying to figure out why Zookeeper is still needed for mongo-refs...

19:34 jweiss: any slingshot users here? Trying to figure out how to catch a java exception and throw+ a clojure object, with the java exception as the initCause.

20:08 BostX: hi guys

20:08 I have a definition: (defn foo [func x y] (func x y))

20:09 and I'd like to do a call: (foo java.net.URLEncoder/encode "bar & baz" "UTF-8")

20:09 but I get #<CompilerException java.lang.Exception: Unable to find static field: encode in class java.net.URLEncoder (NO_SOURCE_FILE:1)>

20:09 does anyone know how is the proper syntax?

20:09 scriptor: if I remember correctly, you can't pass java methods as you would clojure functions

20:10 brehaut: scriptor is right. you'll probably want #(…) or memfn

20:11 BostX: scriptor, yea I read about that: http://stackoverflow.com/questions/2208865/how-do-i-pass-a-static-method-to-comp-in-clojure

20:11 but if I do:

20:11 (map #(java.net.URLEncoder/encode %1 %2) ["bar & baz"] ["UTF-8"])

20:11 then it works!

20:12 brehaut: ,(map #(java.net.URLEncoder/encode %1 %2) [["bar & baz", "UTF-8"]])

20:12 alexbaranosky: BostX, are you located in beantown?

20:12 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox$eval29$fn>

20:12 BostX: no... Im in germany

20:12 scriptor: need to pass it two lists

20:13 BostX: scriptor, ???

20:13 lazybot: BostX: Yes, 100% for sure.

20:13 brehaut: BostX: in that variation you'll want a long winded anon fn

20:13 scriptor: er, vectors

20:13 alexbaranosky: BostX, well you're still invited to this Wednesdays BAZNEX gathering if you can make it ;)

20:13 scriptor: BostX: sorry, that was aimed at brehaut

20:13 brehaut: ,(map (fn [[s e]] (java.net.URLEncoder/encode s e)) [["bar & baz", "UTF-8"]])

20:13 clojurebot: ("bar+%26+baz")

20:14 brehaut: scriptor: yeah sorry, i forgot to add the descriptive comment at the end

20:14 BostX: brehaut, hmmm... l'll try it out

20:15 brehaut: ,'#(inc %)

20:15 clojurebot: (fn* [p1__89#] (inc p1__89#))

20:16 brehaut: BostX: the full fn form lets you use destructuring in the argument vector to unpack the incoming sequence

20:16 scriptor: how do you comment out entire sexps in emacs?

20:17 ah, found it

20:17 M-;

20:17 once you select the sexpr first

20:19 BostX: brehaut, uff... destructuring of the argument vector and unpacking the incoming sequence... oh je!

20:19 scriptor: on another note, why is my multimethod still working even when I comment it out

20:19 BostX: brehaut, java sounds simpler :)

20:19 brehaut: scriptor: the defmulti services reloads;

20:20 BostX: its not honest

20:20 err

20:20 scriptor: the defmulti survives reloads. it is effectively defonced

20:20 ,(apropos 'unmap)

20:20 clojurebot: (ns-unmap)

20:20 brehaut: scriptor: use ns-unmap to remove it

20:21 scriptor: you can also get caught there if you redefine the defmulti's dispatch function, and have it not get pickedup on reload

20:21 gfredericks: is there something about using clojure.java.shell that would cause the jvm to hang for ~30sec before exiting?

20:21 scriptor: brehaut: the same seems to happen with my defns

20:21 brehaut: scriptor: then i have no idea

20:22 although i suspect they might hang around too actually

20:22 you'd need to ask someone with better understanding of the ns and reload machinary

20:23 BostX: Ok, guys thanks a lot... it's 2:21 a.m. now i gotta got to bed

20:24 scriptor: hmm, the repl's not loading new functions either

20:25 brehaut: weird

20:25 you are saving the file in the right place?

20:26 scriptor: yep

20:26 I'll try restarting the repl

20:31 gfredericks: all I have to do is (clojure.java.shell "ls" "-l") and the jvm will hang for 30 seconds

20:31 scriptor: both tried reconnecting slime and restarting the swank server and it's still not working, hmm

20:32 brehaut: scriptor: you arent by chance running your repl inside a vbox vm with a shared folder are you?

20:33 scriptor: brehaut: nope

20:53 wait, I messed something up, restarting swank *did* fix it

22:30 callen: is Aleph ninja-rockstar tech?

22:34 mdeboard: Is `|` not allowed in macro names

22:57 arohner: mdeboard: technically: yes. though I find emac's clojure-mode gets very bitchy if I have | in the file

22:57 mdeboard: Yeah ditto

22:58 callen: is | actually legal?

22:59 if so, I'm going to have some macros named lo||apalooza

22:59 arohner: callen: it's not explicitly disallowed, so it currently works

22:59 * callen laughs maniacally.

22:59 callen: I now know a new way to torment people with my code, thanks.

23:00 arohner: you mean aside from ə?

23:01 callen: the drunk pacman letter!

23:06 TimMc: callen: Use fullwidth latin characters, cyrillic lookalikes for latin script, accented chars...

23:06 callen: TimMc: if Hickey had left reader macros in, I'd have made an APL dialect.

23:07 TimMc: concatenative mindfuck.

23:07 TimMc: callen: Oh, and make sure to take full advantage of the 4 normalization formats of UTF-8.

23:07 err, of Unicode

23:07 callen: TimMc: why are you helping me be evil?

23:08 TimMc: Unicode awareness.

23:08 callen: TimMc: it'll just make people hate unicode.

23:10 ibdknox: bwahahahah

23:10 mission accomplished

23:10 dnolen: ibdknox: ?

23:11 ibdknox: I got his mapping time to space stuff to work

23:11 it's ridiculous neat to play with

23:11 dnolen: ibdknox: uh ... where's the video dude!?

23:11 ibdknox: hopefully within the hour :)

23:15 jessetrimble: sorry to drop such a trivial question here, but I'm having some problems figuring out some regexp stuff.

23:15 I want to split a string on whitespace-only lines, but the following doesn't seem to be working for me:

23:15 (re-split #"^[ ]*\n" "stuff\nand\n \njunk")

23:16 any thoughts?

23:16 TimMc: multiline mode, I think?

23:16 Well, maybe not.

23:17 jessetrimble: maybe something with the beginning of line match? this works:

23:17 (re-split #"\n" "stuff\nand\njunk")

23:18 arohner: &(re-split irc://irc.freenode.net:6667/#"^[ ]*\n" "stuff\nand\n  \njunk")

23:18 lazybot: java.lang.RuntimeException: Unable to resolve symbol: re-split in this context

23:22 arohner: &(clojure.string/split "stuff\nand\n \njunk" #"[ ]+\n")

23:22 lazybot: ⇒ ["stuff\nand\n" "junk"]

23:22 mdeboard: TimMc: What was that pastebin you linked yesterday? refpaste?

23:22 arohner: &(clojure.string/split "stuff\nand\n \njunk" #"[ ]*\n")

23:22 lazybot: ⇒ ["stuff" "and" "" "junk"]

23:23 jessetrimble: oh, interesting. thanks arohner!

23:23 any idea what the underlying difference between 're-split and plain 'split is?

23:24 mdeboard: One uses regex, one doesn't?

23:24 &(doc re-split)

23:24 lazybot: java.lang.RuntimeException: Unable to resolve var: re-split in this context

23:24 dnolen: jessetrimble: isn't re-split a clojure.contrib thing?

23:24 jessetrimble: yeah

23:24 arohner: jessetrimble: no, but re-split came from contrib, while clojure.string is more tested

23:24 dnolen: jessetrimble: if so it's deprecated

23:24 TimMc: mdeboard: refheap.com

23:24 mdeboard: Ah, blast

23:24 callen: didn't Raynes make refheap?

23:25 or did I fuck up attribution of authorship a second time today?

23:25 TimMc: yep

23:25 mdeboard: https://gist.github.com/1921384 This sort of repetitive code is the right place for a macro, right?

23:25 jessetrimble: dnolen: ok, good to know. thanks

23:25 * TimMc leaves that agreement ambiguous in case he is wrong

23:26 TimMc: mdeboard: Or a higher-order function.

23:27 (def -& (make-foo :and))

23:29 callen: &(def -& (make-foo :and))

23:29 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

23:29 callen: hrm. okay then.

23:30 amalloy: mdeboard: i prefer HOFs here, like TimMc says

23:31 your macro would probably be written *only* to defn functions, whereas a HOF is way more flexible - you can create a function inline, for example, or create them all at once with a for-comprehension

23:35 mdeboard: amalloy, TimMc: I see. I guess I'm confused by how I do this in this instance.

23:36 Like I'm familiar with (partial) and #(foo-fn %&) but having trouble putting it together here.

23:36 amalloy: (defn wrapper [connector] (fn [coll] (paren-wrap (clojure.string/join (connector connectors) (map build-querystring coll))))) (def -& (wrapper :and))?

23:37 mdeboard: Not what you had in mind then? https://gist.github.com/1921435

23:37 That's very python-y

23:37 (my gist)

23:38 gross python-y

23:38 amalloy: meh. that's okay

23:38 but you're not taking advantage of the ability to easily construct functions

23:38 mdeboard: Yeah I guess that's what I mean by python-y

23:38 amalloy: (also, every time i see apply-str/interpose i cry. i used clojure.string/join as a hint, there)

23:39 mdeboard: Oh, right.

23:39 TimMc: Don't make amalloy cry.

23:39 dnolen: mdeboard: personally I don't think there was much worth fixing in the first gist, unless you are going to have a lot of functions that look like that.

23:40 mdeboard: dnolen: Just the two. Repetitive code makes me gag, changing/fixing identical code blocks in more than one place is gross.

23:40 dnolen: mdeboard: solving problems not worth solving makes me gag more ;)

23:42 mdeboard: I'm a newb though, I need to learn from these small examples. I don't have the experience/understanding to know what is/isn't worth fixing, so for now I'm idiom-seeking.

23:42 dnolen: mdeboard: Clojure has made me comfortable /w redundancy.

23:42 the lack of inheritance - redundancy is better than spaghetti

23:43 mdeboard: dnolen: Yeah I understand what you're saying. "Foolish consistency is the hobgoblin of little minds"

23:44 TimMc: Localized redundancy is not so bad.

23:45 Everyone has a different threshold for what is acceptable, though.

23:46 mdeboard: It's a personal pet peeve, is all.

23:46 FOolish consistency :)

23:48 On the plus side that puts my Solr API into I guess alpha.

23:50 I mean, after I fix the apply str interpose.

23:51 callen: you know, mutable languages are capable of being as powerful/concise as Clojure, but they don't spend enough time thinking about data transformation.

23:51 I mean, what's reasonably popular that has an equivalent to tree-seq? itertools in Python looks lame by comparison. :(

Logging service provided by n01se.net