#clojure log - Jul 17 2012

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

0:00 dsrguru: so lets walk through evaluating this

0:00 oh btw

0:00 you should set acc to 1

0:00 not 0

0:00 since 0! = 1

0:01 otherwise each time you multiply by n

0:01 you're still at 0 :)

0:01 so acc just means

0:01 iDesperadO: acc is accumulation of the current factorial..

0:01 dsrguru: this is the ultimate return value

0:01 but what we've accumulated so far

0:01 yes

0:01 so

0:01 dsrguru: good

0:01 and trace it out

0:02 you'll see that (fact 2) -> (recur (dec 2) (* 2 1))

0:02 -> (recur 1 (* 2 1)) -> (recur 0 (* 1 (* 2 1)))

0:02 and now that (= n 0)

0:03 (recur 0 (* 1 (* 2 1))) just equals (* 1 (* 2 1))

0:03 dsrguru: which evaluates to 2

0:03 so to make something tail recursive

0:03 or the clojure equivalent at least

0:03 iDesperadO: (defn rrgcd [a b] (loop [a a b b] (if (= a 0) b (recur (rrgcd (rem b a) a)))))

0:03 dsrguru: what you want to do is have all the operations

0:03 that get you closer to the base case

0:03 take place inside the recursive call

0:03 not outside

0:04 i.e. (recur (bla...) (bla...)) not (bla (recur 2)...

0:04 if you look at a few examples online

0:05 dsrguru: the pattern will be very clear

0:09 iDesperadO: (defn rrgcd [a b] (loop [a a b b] (if (= a 0) b (recur (rrgcd (rem b a) a)))))

0:09 this definition is still not right

0:09 Mismatched argument count to recur, expected: 2 args, got: 1

0:10 oh nvm

0:10 iDesperadO: i'm afraid the parens are right...

0:11 dsrguru: you don't also include rrgcd

0:11 it should be (defn rrgcd [a b] (loop [a a b b] (if (= a 0) b (recur (rem b a) a))))

0:11 why there's no rrgcd there?

0:11 dsrguru: loop and recur work together

0:11 loop isn't just a let statement

0:11 it also sets the boundary of a new function

0:12 that can be recursively called

0:12 with TCO

0:12 (tail call optimization)

0:12 when you call recur

0:12 so recur says

0:12 call the function I just defined by loop

0:12 it happens to have the same parameters as the outer function rrgcd

0:13 but that's unusual

0:13 that's why I showed you the factorial case first

0:13 where it was clear

0:13 that the loop expression was autonymous

0:13 so in this case (loop [a a b b] (if (= a 0) b (recur (rem b a) a)))

0:13 iDesperadO: so (loop [a a b b] ...) is a function?

0:13 dsrguru: defines an anonymous function

0:13 yes

0:13 exactly

0:13 except

0:14 it doesn't define it

0:14 it calls it in place

0:14 it's like ((fn [a b] ...) a b)

0:14 dsrguru: sorry I should have explained that at the beginning!

0:15 iDesperadO: if the loop part is an anonymous function then this function body is just [a a b b] ???

0:15 dsrguru: do triple question marks trigger lazybot ???

0:15 lazybot: dsrguru: Oh, absolutely.

0:16 so..?

0:16 dsrguru: sorry had to test that

0:16 I'm not sure I get your question

0:16 let me give you two examples

0:17 one with loop/recur

0:17 one with a named fn

0:17 so you can see how they map up

0:17 iDesperadO: if the loop is a anonymous function, then it must have a function body, which i guess is [a a b b]

0:17 dsrguru: although remember that loop/recur will run faster

0:17 or at least conserve space in the call stack

0:17 btw a named fn is the same as a regular anonymous fn except it temporarily has a name for purposes of recursion

0:17 so:

0:18 (fn rgcd [a b] (if (= a 0) b (rgcd (rem b a) a)))

0:18 is the same as:

0:18 wait

0:19 ((fn rgcd [a b] (if (= a 0) b (rgcd (rem b a) a))) 3 4)

0:19 is the same as:

0:19 (loop [a 3 b 4] (if (= a 0) b (recur (rem b a) a)))

0:19 except for efficiency

0:19 dsrguru: does that help?

0:20 wingy: finally

0:20 cljs worked!

0:20 iDesperadO: helps a lot !

0:20 wingy: https://github.com/emezeske/lein-cljsbuild was really great

0:20 much better than clojurescriptone if you wanna get started

0:21 iDesperadO: loop defines a function, binds the parameters and then call the function...

0:21 dsrguru: iDesperadO: or at least I'm assuming that's true because that's how the equivalent works in Scheme!

0:21 yes

0:21 and it does one more thing

0:22 iDesperadO: for recur to rebind the parameters

0:22 dsrguru: yes

0:24 dsrguru: iDesperadO: np I've been pestering the good people on this channel enough in the last couple days as I too am starting to use clojure, so I'm only happy to help

0:26 iDesperadO: i'm a c++ programming by profession, but now I'm amazed by clojure...

0:26 programmer

0:27 a clojure's function can do so much more than a c++'s class...haha~~~

0:28 dsrguru: haha yup LISPs are so expressive

0:48 wingy: one thing bad though is the jvm startup time in lein

0:48 i wish they can move to node.js instead for lein .. isn't cljs designed for running cli tools

0:48 technomancy: ^ :)

0:52 yonatane: Hi wingy, do you ever sleep? ;)

0:52 wingy: yonatane: couldn't sleep since i couldn't get cljs working

0:52 but now its fixed

0:52 so now i have to play with it some more before i sleep

0:53 yonatane: have you been stalking me?

0:53 ivan: technomancy might think about it after you port 20MB of Java to CLJS

0:54 wingy: ivan: :/

0:55 it's using a lot of java libs?

0:55 ivan: take a look inside leiningen's jar

0:55 it's got all that maven stuff

0:55 wkelly: and ant stuff

0:56 wingy: plan b … let's just kill the startup time

2:42 iDesperadO: hi, `lein search` always returns with exception with clj-http: status-404

3:00 wingy: how do i add a css file in hiccup?

3:01 the api doesnt mention css files http://weavejester.github.com/hiccup/hiccup.element.html

3:08 ro_st: what do you think of hiccup so far, wingy?

3:11 akhudek: I greatly prefer enlive

3:11 ro_st: they do different things, don't they? enlive is more for parsing/scraping?

3:11 akhudek: ro_st: not really, enlive is great for templating

3:12 ro_st: i'm planning on using enlive/enfocus with a common set of templates

3:12 akhudek: the big deal with enlive is that a designer can give you pure html and you don't need to modify it directly

3:12 ro_st: allow the server to render pages, but also allow the client to re-render them or parts of them

3:12 akhudek: that's a good idea

3:12 was thinking of something similar myself

3:13 we use a lot of enlive at my work

3:13 ro_st: part of my app is a store, i'm planning to do what the new basecamp does

3:13 with pjax

3:13 where it only loads the 'center' on page nav

3:14 makes it really fast

3:14 akhudek: I'm not very familiar with basecamp sadly, but enlive on both server + ajax client seems pretty natural

3:14 ro_st: what i like about the enlive/enfocus strategy is i don't need to decide where things get rendered

3:14 and i can change my mind easily once i do

3:14 akhudek: I've found cljs to be very undocumented this point overall

3:14 ro_st: makes things a lot more manageable

3:14 yeah

3:15 cljsbuild's crossover feature is great

3:15 akhudek: there are a number of places where I could also see cljs and clj sharing code directly

3:16 ro_st: i'm doing all my 'model' code in clj and testing with midje and midje-mode

3:16 akhudek: enfocuse/enlive templates and snippets, and also validation/state control code

3:16 ro_st: and it's auto compiling all those ns's to js as well

3:16 akhudek: huh, so you do share code between client and server?

3:16 ro_st: so hopefully i'll only need to actually develop the glue and service layer code in cljs directly

3:17 i'll be able to build all my templates in the repl with enlive

3:17 yes

3:17 it's very easy to configure

3:17 akhudek: nice, I was hoping that it was possible. Our project hasn't incorporated any cljs yet, but I've been starting to look into it

3:18 ro_st: i'm re-doing a google closure javascript codebase as cljs

3:18 i'm coming out at less than a 1/6th of the code, including tests :-)

3:18 akhudek: our client code is jquery, which makes it a bit more painful to move over… maybe

3:19 ro_st: my advantage is that i'm already familiar with the closure compiler and library

3:19 our CI et al already has all that set up

3:20 akhudek: nice, that seems like it would make it a bit easier

3:20 ro_st: definitely

3:20 akhudek: do you know if closure provides multiple file upload in IE8?

3:20 ro_st: i don't, sorry

3:21 akhudek: darn, no worries. IE8 is very annoying.

3:21 ro_st: indeed

3:21 unfortunately it accounts for close to a third of our userbase

3:21 thankfully ie6/7 are less than 1% combined

3:21 akhudek: same or worse here :-(

3:22 we don't support 6/7

3:22 although I think 7 still mostly works last I checked

3:24 ro_st: what's the simplest way to find the index of an item in a set?

3:24 akhudek: set's have no numerical index

3:24 or any index really

3:24 they compare on the items they contain directly

3:25 ro_st: oh, my mistake. index of an item in a vector

3:25 in this case, i know for sure the vector only contains one copy of each item in it

3:26 malcolmsparks: (just a test)

3:26 akhudek: I can't think of any easy way outside of combining map and some

3:27 ro_st: i'm using seq-utils' positions fn now

3:27 but i'm using it in a crossover (clj + cljs) ns. so i guess i'll have to yank it out into a util.clj in my own crossover folder

3:29 akhudek: isn't seq-utils deprecated?

3:30 easiest direct way I can see right now is

3:30 ,(let [items (map vector (iterate inc 0) [:a :b :c :d])] (some (fn [[i v]] (if (= v :c) i)) items))

3:30 clojurebot: 2

3:30 akhudek: could make it into a function easily enough

3:31 or just copy the seq-util function if it works for you

3:31 ro_st: i guess it takes that much code because of the lazy nature?

3:31 yeah i copied it

3:31 it's not much: https://www.refheap.com/paste/3638

3:32 hiredman: ,(doc keep-indexed)

3:32 clojurebot: "([f coll]); Returns a lazy sequence of the non-nil results of (f index item). Note, this means false return values will be included. f must be free of side-effects."

3:32 amalloy: you want ##(doc keep-indexed), but really if your code needs the index of something you're usually doing something wrong

3:32 lazybot: ⇒ ------------------------- clojure.core/keep-indexed ([f coll]) Returns a lazy sequence of the non-nil results of (f index item). Note, this means false return values will be included. f must be free of side-effects. nil

3:33 ro_st: well, i have a ref to a unique element, and i want to get the very next element in the vector after this element i have a reference to

3:33 and so i'm using positions to get the index of the element i have, adding 1, and checking bounds, and if that passes, fetching it out

3:34 good ole imperative style. i'm very keen to use a better method if one exists

3:34 i can't modify the source vector, though. i can pre-process it to make it a sorted-set or something if that's more appropriate

3:34 akhudek: how many elements are in this vector?

3:35 ro_st: tens at most

3:35 akhudek: unless you have millions of queries per second, I wouldn't worry too much about performance here

3:35 ro_st: another constraint: this code runs in cljs primarily

3:36 oh, indeed. showing intent in the code clearly is my main concern

3:36 akhudek: drop-while + fnext

3:37 use let-if or similar if you want to check the case where there is no next

3:37 ro_st: um, so say i have a ref to :c, and a vector, [:a :b :c :d]. using :c, i want to get :d. how would i use drop-while in this case?

3:38 edge cases are that a nil ref should fetch back :a, and a :d ref should fetch back nil. those are easy once the main case is working, of course

3:38 akhudek: ,(fnext (drop-while #(not= :c %) [:a :b :c :d]))

3:38 clojurebot: :d

3:39 hiredman: ro_st: keep :c and :c's index in the ref, and then just inc :c's index

3:39 ro_st: oh right. drop-while finds the ref, and fnext grabs the next one

3:39 akhudek: ,(fnext (drop-while #(not= :c %) [:a :b :c]))

3:39 clojurebot: nil

3:39 ro_st: that's very elegant, akhudek!

3:40 akhudek: if you need to check that no :d exists, just do if-let

3:40 ro_st: hiredman: that has the problem of me needing to determine the index, which i've been told is Naughty :-)

3:40 hiredman: ro_st: how do you not know the index? do you not start at 0?

3:42 akhudek: I'm off to sleep, night ro_st

3:42 ro_st: the fn returns the element, which is then kept elsewhere. the next time the fn is used, i pass in the previously returned element

3:42 sleep well

3:43 so using index is adding complexity. akhudek's drop-while + fnext solution works a charm

3:43 hiredman: ro_st: if you need the index, why not pass it around?

3:43 ro_st: i don't need the index :-) i need the element

3:43 i was using the index before because that's how my n00b imperative brain said i should do it

3:44 hiredman: so why are you using a vector?

3:44 ro_st: that's how it comes off the wire

3:44 deserialised json

3:45 hiredman: there is nothing imperative about indexed access

3:47 ro_st: ok :-) as i mentioned before, i was a) finding the index of the element i had b) incrementing it c) testing that value against the length of the vector d) if in bounds, returning vector[next-index] e) or if not, nil

3:47 that's imperative-y

3:47 hiredman: it is not

3:47 ro_st: oh

3:47 wingy: ro_st: hiccup is nice

3:47 ro_st: -writes that down-

3:48 -grin-

3:48 wingy: are you using enlive?

3:48 ro_st: i plan to, yes

3:48 haven't gotten there yet

3:48 wingy: hmm .. im going to use bootstrap

3:49 wingy: and thinking that writing HTML directly is more compatible with bootstrap

3:49 wow

3:49 ro_st: some nice stuff in this one

3:50 wingy: ro_st: is it maintained?

3:50 8 months from last activity

3:50 ro_st: doesn't look like it :-(

3:51 wingy: such projects are risky

3:51 ro_st: agreed

3:52 ,(if nil 1 2)

3:52 clojurebot: 2

3:53 wingy: anyway .. i thought i im using enlive/enfocus i can do separate logic with template in HTML and that would be better when using Bootstrap

3:53 ro_st: weird. i had (if var-name (stuff) (things)) where var-name is nil and (stuff) got called

3:53 switching to (if-not (nil? var-name) (…)) worked

3:53 bootstrap is predominantly css and js, isn't it?

3:55 wingy: havent used it yet but yeah its heavy in css

3:55 ro_st: wingy, check kibit out

3:55 wingy: and using jquery for animations

3:57 ro_st: yup

3:57 ro_st: it analyzes your code and tells you where you can simplify things

3:57 wingy: i see

3:57 cool

3:57 does it work?

3:58 ro_st: eg, instead of (map #(:id %) […]), it'll tell you to use (map :id […])

3:58 wingy: cool

3:58 ro_st: or (= (:id foo) =) -> (zero? (:id foo))

3:58 stuff like that

3:58 sorry

3:58 wingy: neat

3:58 ro_st: (= (:id foo) 0) -> (zero? (:id foo))

4:02 wingy: ro_st: (when (System/getenv "PORT") (Integer. (System/getenv "PORT"))) instead of: (if (System/getenv "PORT") (Integer. (System/getenv "PORT")) nil)

4:02 so cool :)

4:02 i have to play with core.logic myself when everything is setup

4:03 ro_st: did you watch edmund jackson's intro to core.logic?

4:03 search vimeo for clojure and sort by date. bottom of page 1

4:04 really cool talk

4:04 wingy: the guy who talked really fast?

4:04 and something asked him to slow down at the beginning?

4:04 ro_st: that's the one

4:04 with the south african accent

4:04 wingy: yeah ive seen it

4:05 clojure.core seems to allow us to code in a different way

4:05 in a very declarative way

4:05 ro_st: it's very interesting. definitely an area i want to play around in

4:05 wingy: yeah i hope i can use it heavily in my app

4:05 malcolmsparks: it was funny because there were a lot of europeans in the room who were really struggling with the speed of English

4:06 one German guy stood up and put both hands up pleading with the speaker to slow down :)

4:06 wingy: OTOH he talked really fast :)

4:06 ro_st: they can watch it on vimeo now and slow it down

4:06 wingy: malcolmsparks: you were there?

4:06 malcolmsparks: but it was a superb talk - hopefully someone can make a transcript one day

4:06 yes

4:06 wingy: cool

4:06 ro_st: i kept up ok, but that's because i'm used to that accent. my own is quite similar to his

4:06 wingy: malcolmsparks: how many people were there?

4:07 malcolmsparks: you don't see the baffled audience from the video :)

4:07 almost 200

4:08 ro_st: i would love to have been there

4:09 i can count the number of clojure folks in cape town that i know of on one hand!

4:09 malcolmsparks: anyone know of a Midje talk? I'm really enjoying it - only just starting playing with it - it's very cool

4:09 wingy: http://www.hackerne.ws/item?id=2683007 read ynniv's post

4:09 ro_st: have you seen marick's vids, malcolmsparks?

4:09 malcolmsparks: no - guess I should have googled before chatting

4:09 I'll look them up tonight

4:10 ro_st: are you using emacs, malcolmsparks?

4:10 malcolmsparks: never really used midje before, didn't realise how powerful it was

4:10 clgv: malcolmsparks: the midje wiki is quite good in explaining

4:10 ro_st: it ROCKS. i'm doing TDD with it

4:10 malcolmsparks: ah, train in - gotta go

4:17 wingy: wow .. bootstrap is really simple to use

4:17 always used big frameworks like extjs/sproutcore to make good looking buttons and now it's just a html class i need to add :)

4:17 towards simplicity like clj!

4:20 clgv: bootstrap?

4:21 clgv: ah ok. read that before

4:22 wingy: do you guys feel that html should be html and not in clj like hiccup is doing?

4:23 ro_st: long term, i think it's good to keep the markup separate from the logic

4:23 wingy: yeah

4:24 ro_st: hiccup is fun, but to be able to do pure css work on that markup, you need a running ring server and a knowledge of clojure sufficient to do hiccup changes to be able to complete work

4:25 wingy: good analysis

4:25 ro_st: lots of designers use (barf) dreamweaver or similar to accomplish tasks like that. it's nice to be able to keep that ability

4:26 wingy: ro_st: OTOH is it really desired to have pure designers doing HTML?

4:26 isn't it something a clojure dev can do

4:26 he knows the logic and display

4:26 ro_st: do you want to pay a clojure dev to do something a markup monkey can?

4:26 no disrespect to markup monkeys -grin-

4:27 what do you gain by using hiccup over raw html and enlive?

4:27 wingy: since im doing the markup atm i get joy :)

4:27 ro_st: is that gain worth losing the flexibility of pure html throughout your dev lifecycle?

4:27 wingy: i guess not

4:28 yeah

4:28 ro_st: the thing about code is you want as little of it as possible

4:28 hiccup is code, it's not markup

4:28 wingy: right

4:28 ro_st: that's what makes enlive great. your code is just a set of transformations, which is much easier to test

4:29 wingy: and being able to use pure HTML is kinda neat

4:29 you know what is going on

4:30 ro_st: also, pure html/css is much easier to work with in chrome

4:30 you can even use chrome dev tools' save-file features

4:30 wingy: but then you could say that about js vs cljs :)

4:31 ro_st: chrome dev tools get thoroughly spanked by emacs+repl

4:31 when it comes to logic stuff

4:31 thats just my opinion, of course :-)

4:32 but it's one formed from experience of both worlds

4:33 i wonder if cljs supports source maps

4:33 wingy: yeah i also think that writing pure html is better for long term maintenance

4:33 ro_st: chrome dev tools has excellent support for it. shows you your source language (ie, cljs) right there in the scripts panel

4:33 clgv: ro_st: they are working on source maps as far as I heard

4:34 wingy: when will that be ready you think?

4:34 ro_st: no clue

4:35 wingy: ok new policy

4:35 "close to the metal"

4:35 ro_st: yes

4:36 wingy: html, css, cljs but using js libs without transformations, clj using java libs without tranformations

4:36 ;)

4:37 ro_st: do you use a css pre-processor?

4:38 wingy: no .. im not that great in styling

4:38 bootstrap is using less

4:38 but i dont think i will have to style that much

4:39 ro_st: oh wow, nice resource

4:39 i feel this is way better than styling manually

4:39 we use bootstrap .. and everyone can provide styling template

4:40 they could open a new market

4:41 ro_st: both great resources. bootswatch is realy nice

4:41 wingy: ro_st: now i recall what rich hickey said about complecting

4:42 perhaps having logic and presentation in one is complecting things

4:42 just like you dont want to have logic and data as one like in OOP

4:42 ro_st: yes, exactly

4:44 ohpauleez did something interesting in his demo-shoreleave-findit project

4:45 he uses erb (from ruby) and rake to pre-compile static html pages, using layouts and partials

4:45 then cljs uses enfocus to munge that markup clientside

4:45 he could just as easily have used enlive to do the partials work, actually

4:53 pyr: morning

4:54 can members be removed from a clojars group ?

4:54 (from clojars i mean)

5:00 clgv: pyr: I only see an "add member" button over there

5:02 pyr: clgv: yup, me too

5:05 kral: namaste

5:08 ro_st: tashi delek!

5:34 augustl: are there any solutions to have "lein test" keep a JVM running and automatically reload changed files, for faster test runs?

5:37 ro_st: lazytest

5:37 twhume: I'm having a bit of NotFun with futures. Could anyone explain to me why this code seems to run correctly, but then drives CPU usage for the Java process to 90%+, and stays there forever? I think the future I create is being terminated correctly, but it appears not… https://gist.github.com/3124000

5:37 ro_st: are you using clojure.test or midje, augustl?

5:38 augustl: ro_st: clojure.test

5:39 mostly because of use-fixtures with :once, haven't found an equivalent for midje

5:39 ro_st: i'm using lein-midje with lazytest, which auto-runs when tests or the files the tests load change

5:39 midje has the background macro

5:42 for example: https://www.refheap.com/paste/3639

5:42 this runs all the facts inside the binding, so that the production code being tested uses the test database instead of the production one

5:43 and it only loads the fixtures once

5:43 you can use :facts instead of :contents if you want the work to be performed per fact

5:43 augustl: a fact is a test?

5:43 ro_st: yes

5:44 augustl: and :contents is one test namespace?

5:44 or the entire run?

5:44 ro_st: one test namespace

5:44 augustl: is there a way to run some code before and after the entire test suite?

5:44 ro_st: as with everything in clojure, it's all namespace bound

5:44 augustl: currently integration testing a SSO system so I would like to boot 3 jetty servers. Currently doing that for each test namespace, so it's kind of slow

5:45 ro_st: you could probably use a separate namepsace and memoize the calls

5:45 augustl: good point

5:45 ro_st: so first calls do the work, subsequent calls just return whatever work was done the first time

5:45 if you use emacs, there's midje-mode too

5:46 augustl: what does it do?

5:46 ro_st: run individual facts right there in your buffer

5:46 it pastes the output as comments above the fact

5:46 it uses your active repl

5:46 augustl: ah

5:46 ro_st: the way i work is to have lein2 midje —lazytest running in a shell, and then code tdd style in emacs, using C-c . to run individual facts as i go

5:47 lazytest helps with regression testing when i refactor stuff

5:47 augustl: typically memoization is done via function calls I suppose?

5:47 which checks a ref for nil etc

5:47 ro_st: yup. i've not done memoization with clojure before, but the concept is pretty simple

5:48 augustl: perhaps there's something built-in

5:48 reading the tests for this code should give you a thorough background on the topic

5:53 so i have a .clj with plain clojure data in it. how do i read it off disk and assign that map into a ns-bound var?

5:54 right now the file has (def name {…}) in it, and i'm using load-file

5:56 ro_st: something like that ^ ?

5:56 ro_st: superduper!

5:57 vijaykiran: leiningen loads user.clj profile, I guess that's something similar to what you are looking for

5:57 ro_st: it's precisely what i'm after, thanks very much

5:57 vijaykiran: yw

5:59 augustl: ro_st: I see, thanks

6:02 ro_st: heck i should really make a screencast showing all this working together

6:08 twhume: Anyone know why this code should lead to high CPU usage? (deref (future (loop[a 1] (recur a)) :done!) 1000 :impatient!)

6:11 cshell: infinite llop?

6:11 infinite loop?

6:11 ro_st: the loop recur is infinite

6:11 recur should be wrapped inside a conditional that checks whether recur should happen or not

6:12 cshell: it needs to increment the a value

6:12 or do something with it

6:13 ro_st: '(loop [a 1] (if (< a 3) (recur (inc a)) a))

6:13 ,(loop [a 1] (if (< a 3) (recur (inc a)) a))

6:13 clojurebot: 3

6:17 augustl: it would seem that irccloud.com just died :)

6:17 cshell: yep

6:17 twhume: shell, ro_st: yes, it's an infinite loop (it's not the actual code I want to run, but the actual code may or may not contain such a loop - hence the need for a timeout). But surely it should stop running once the future is cancelled whatever?

6:17 s/shell/cshell/

6:17 ro_st: i just got a pingdom alert for my vps as well

6:18 twhume: In practice I'm going to want to run short sequences of arbitrary bytecode inside this future, some of which may contain such loops. I've stuck a recur in there so I can be testing with the worst possible case...

6:20 ro_st: right

6:20 i've no experience with futures, i'm afraid

6:24 augustl: ro_st: are you using lein 1.x and lein-midje?

6:24 seems I need lein-midje both as a plugin and dev-dependency

6:25 also, is there a way to run midje tests with "lein test", or make "lein test" throw errors?

6:26 Fossi: they will be run

6:26 don't know what you mean with "errors"

6:26 like a negativ return code?

6:27 ro_st: i'm using lein2 for midje, augustl

6:28 augustl: Fossi, ro_st: the issue is that "lein test" is still present, and it doesn't run the midje tests, so some devs (me included) might forget about it and think they ran the tests when they did "lein test"

6:28 ro_st: with that in place, i can run lein2 midje —lazytest

6:29 i believe midje will run any existing clojure.test tests as well

6:29 so transitioning is easy

6:30 Fossi: yes

6:30 and you can use midje tests with lein test as well

6:30 at least with the version/setup we are using

6:31 not sure what that includes though

6:31 been a while since i touched it ;)

6:31 afair lein midje is just nicer output

6:31 ro_st: yeah

6:32 the lazytest reloading stuff is great too. it knows how to reload changed files and all the files that depend on those changes, but only those files

6:32 Fossi: nice

6:32 ro_st: so even with a massive suite, the testing is still fast

6:36 augustl: ro_st: how would you do this with midje? http://pastie.org/4270944

6:36 seems midje doesn't have a concept of "tests"

6:37 my tests typically do a lot of stuff, so it makes sense to reset the db between each test in clojure.test. Doesn't seem to make sense to reset the db between each fact in midje, since a fact seems to be 1:1 with assertions

6:38 these particular tests only contain one assertion but I might want to have a bunch of them, do a couple of more HTTP requests, etc

6:41 augustl: ro_st: so I can have anything I want inside a "fact"?

6:41 let, if-let, nested lets, etc?

6:42 ro_st: yup :)

6:42 augustl: not sure if I like the => syntax.. It's not very lispy

6:42 ro_st: it grows on you

6:42 augustl: 'foo operator bar' that is

6:43 ro_st: in emacs, it's bright red, so it's easy to distinguish tested code vs checker code

6:43 augustl: the only thing I like is the checkers :)

6:44 perhaps there's a more generic collection assertion library I can use

6:44 like "vector contains {:foo 123}" and so on

6:51 ro_st: do you know if midje supports a more traditional syntax?

6:52 I'd prefer (=> foo bar) to foo => bar

6:54 ro_st: i don't think so

6:54 -shrug- i like it the way it is

6:58 augustl: i suggest scanning through the midje wiki to get a sense of why brian did it they way he did

6:58 he provides a rationale and lots of great docs as well

7:07 augustl: ro_st: I see, thanks :)

7:08 ro_st: also, midje-mode #justsaying

7:44 i have an atom which contains a sorted-set of maps. i want to alter a value in one of these maps. what's the best way to update the sorted-set with the new map that update-in returns?

7:44 disj then conj?

7:46 clgv: ro_st: yes.

7:46 ro_st: for a map you could use update-in, but in a set you can not specifically adresse one of its elements

7:50 ro_st: like this? https://www.refheap.com/paste/3643

7:50 i realised the set won't be able to remove the node if i only give it the updated version

7:53 clgv: seems to do the job.

7:54 but are you sure that the set is the right datastructure in this case?

7:54 ro_st: i plan to use sorted-set-by and provide a custom sorting fn

7:55 having it sorted in a particular fashion is a User Story

7:55 i definitely have only one of each element in the structure, so a sorted-set seemed the right fit

7:56 clgv: there is also sorted-map-by where you could directly address elements via a key (e.g. id)

7:56 ro_st: i want to be able to throw nodes at it and let the sorting fn figure out what the order should be

7:56 i guess. it'll be easy to refactor to sorted-map-by if i find that i need to. i'm going to see how far i can get without having to use ids

7:59 clgv: ro_st: but you already did a first work-around with your two functions for updating an element, so that might be an indicator that a set is not the best approach there

8:00 ro_st: i guess with sorted-map-by i can use update-in instead of disj-then-conj

8:00 clgv: right

8:03 ro_st: sorted-map-by seems to pass the keys to the comparator?

8:05 clgv: ro_st: oh right. I would have assumed that you get both

8:05 ro_st: lemme just set a breakpoint and see

8:06 clgv: &(sorted-map-by (fn [x, y] (println "x =" x "y =" y) (compare x y)) :bla 10 :blubb 20)

8:06 lazybot: ⇒ x = :blubb y = :bla {:bla 10, :blubb 20}

8:11 mikem: I have a function which takes 7 arguments. I'm "stubbing" it in Midje with provided and specifying 7 anythings, one in place of each argument. Is there a way to achieve the same without being so repetitive?

8:12 ro_st: (apply fn (take 7 (constantly anything)))

8:12 *shoots from the hip*

8:13 mikem: ro_st: haha, epic fail :-)

8:13 didn't work

8:14 ro_st: ,(take 3 (constantly "five"))

8:14 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core\$constantly\$fn__2351>

8:14 ro_st: damnit. i thought i understood constantly :)

8:16 if you can find a way to make an infinite sequence of 'anything's, you can use take 7 to bite off 7 and use apply to pass em in

8:16 lemme know when you find out how :-)

8:17 vijaykiran: ,(take 3 (repeatedly (constantly "five")))

8:17 clojurebot: ("five" "five" "five")

8:17 vijaykiran: :)

8:17 ro_st: repeatedly!

8:17 (apply fn (take 7 (repeatedly (constantly anything))))

8:17 that should do it

8:18 although that's almost as long as

8:18 anything anything anything anything anything anything anything

8:18 :)

8:20 mikem: vijaykiran, ro_st: that doesn't actually work, midje explodes with a StackOverflowError

8:20 but, valiant effort!

8:21 vijaykiran: sorry, I didn't know the context - just trying to give a fix for exception that clojurebot threw

8:21 ro_st: he has (fn-name <7 anythings in a row>) and wants to know if he can instead programmatically generate 7 anythings

8:22 and pass them as args to fn-name

8:22 clgv: mikem: there are aliases for "anything", I would use the shortest one, if the amount to write is a problem

8:23 mikem: the catch is it's in a (provided) block in Midje

8:23 clgv: oh, what are the aliases?

8:23 clgv: should be in the wiki

8:24 y3di: disclojure hiatus is depressing =/

8:25 ro_st: clgv, mikem: only synomym is 'irrelevant'

8:25 clgv: damn

8:25 ro_st: nothing stopping you making your own :)

8:25 clgv: "any" or "_" would be good ^^

8:25 clojurebot: Cool story bro.

8:25 ro_st: (def :P anything)

8:26 clgv: that wont work because :P is not a symbol :P

8:26 ro_st: worth a try

8:26 looks like sorted-map-by's comparator only takes the keys as args

8:27 mikem: I guess I was thinking more of a catch-all which means any number of arguments and anything

8:27 in case the function gains or loses arguments in the future

8:27 clgv: ro_st: yep, that was the point of the above example with sorted-map-by ;)

8:27 ro_st: that sucks. i need to be able to sort based on data in the values

8:28 looks like sorted-set is the way, then

8:28 clgv: ro_st: well, do you need to keep the container sorted or is sorting when accessing all elements an option?

8:29 ro_st: i'd like to keep the container sorted

8:29 because i need to be able to process delta updates in the view (so that the entire view doesn't need to be re-rendered whenever something changes)

8:30 sorted-set-by's comparator receives the values, which works for me

8:39 cshell: Do you ugys find it easier or harder to code/develop with music on or off?

8:40 ro_st: depends on the music i guess. sometimes i must have silence. other times, jazz is great

8:40 Bronsa: prog metal is good too

8:40 ro_st: and the inception soundtrack is awesome if you want to feel like you're saving the world

8:40 Bronsa: generaly everything with very little to no lyrics at all

8:41 mprentice: classical instrument covers of rock == great coding music

8:41 vitamin string quartet, apocalyptico

8:41 cshell: Yeah, for me if I'm thinking of a solution to a problem i need silence, if I know what I'm coding, music helps

8:42 interesting, thanks guys!

8:42 ro_st: oo nice mprentice

8:43 i tried to grab some classical but it's always such a mixed bag

8:43 don't want hectic, jarring music. i find that the mellow stuff is mixed in with the crazy stuff

8:44 mprentice: :D

8:44 ro_st: these guys? http://coda.fm/artists/143

8:44 cshell: I also find that if I know the cd by heart I can focus, but new songs with lyrics seems to distract me

8:44 ro_st: same here. i can code to coldplay no problem cos i know it all so well

8:45 cshell: probably because the intervals/changes are expected by our brain

8:45 and new music surprises our brain

8:57 edoloughlin: I read an article a few years ago (don't think I can find it again) where people were given logic/math problems to solve with/without background music. Everyone solved the problems but those listening to music failed to spot threads/themes that were common to all of the problems.

9:02 cshell: Do all namespaces in the application get compiled or do they only get loaded when accessed?

9:02 lnostdal: what kind of music?

9:02 ..music with lyrics ruins everything for me for sure

9:03 cshell: me too

9:06 vijaykiran: hmm . interesting - http://faculty.nipissingu.ca/stange/courses/P2267/BackgroundMusic.pdf

9:06 augustl: hmm, the singleton-ness of the mongodb libraries for clojure bothers me. I wonder why they all seem to prefer an implicit singleton connection somewhere, instead of just passing a connection descriptor to all queries

9:06 vijaykiran: "The effect of background music and background noise on the task performance of introverts and extraverts"

9:10 cshell: augustl: You can write your functions to take whatever comes out of the library

9:10 i use congo mongo and what comes out is just a map

9:11 and I pass that map in when I want to do a search

9:21 joly: vijaykiran: I'm having trouble reading that article because of too much background noise. :P

9:23 augustl: cshell: I'm talking about the db operations, the connection is implicit

9:23 you call connect! one time and then all future calls will use that connection

9:23 cshell: ah, I don't do that with congo-mongo

9:24 I call make-connection and bind it to a var

9:24 goodieboy: anyone know if it's possible to access the resources of a dependency? For example, I have a jar that I've deployed that contains stuff in it's "resources" dir. My parent project needs to access that stuff, how to do this?

9:24 augustl: cshell: what's the API for passing that connection to queries? a with-connection like thing?

9:27 pyr: i must be doing things wrong, but while trying to load a class defined through a defrecord in a java project i get errors saying the class cannot be found (the dependency was pulled through maven)

9:27 i see the class in the jar, and when manually pulling the jar in eclipse to try out i see the class correctly

9:28 pyr: provided it was not AOT-compiled

9:30 pyr: clgv: the namespace in which the records are defined is aot compiled

9:30 duck11231: goodieboy: If you have a file in resources/ (on your classpath) you can call getSystemResourceAsStream on the classloader

9:31 clgv: pyr: humm, do you see the class files in filesystem or in the dependency-jar?

9:31 goodieboy: duck11231: OK, thanks. How can I access the classloader?

9:31 pyr: clgv: yes

9:31 clgv: pyr: you used Class.forName?

9:32 pyr: nope, it breaks at import

9:32 when i say import 'org.something.namespace.RecordName'

9:32 i get 'cannot find symbol'

9:33 symbol: RecordName

9:33 class: org.something.namespace

9:33 s,class,location

9:34 duck1123: goodieboy: that works if you're not in a sandbox

9:34 goodieboy: duck1123: cool thanks!

9:35 duck1123: there may be a better way

9:35 clgv: pyr: weird.

9:36 pyr: clgv: indeed, will dig further

9:36 uvtc: Would you recommend a Clojure novice use Noir, or straight Ring + Compojure?

9:36 Also, good morning, #clojure. :)

9:37 Er,... good *, for folks in different timezones.

9:38 clgv: uvtc: as far as the advertisement says Noir is on a higher level above Ring + Compojure

9:38 uvtc: weavejester: is it common to write web apps using just Compojure, rather than a "framework" built atop it?

9:39 lucian: i tend to take all the help i can get

9:40 duck1123: All noir is really doing is abstracting away some things and providing helpers for others. If you like those abstractions and they fit with what you want to do, then use it. But you can certainly get by without.

9:40 cshell: uvtc I just started with noir

9:40 it has a lot of helper methods that you would need for ring and compojure

9:42 uvtc: Mm. Thank you.

10:02 sh10151: Any thoughts on when to use bindings/vars and when to use explicit function parameters?

10:03 use case is an xslt transform function -- (transform stylesheet input output)

10:03 need to provide an interface for xsl:param and the like

10:11 sproc: If I have two loops, nested, and I am in the inner loop, how can I recur back to the "parent" loop?

10:12 sh10151: I don't think you want to do that...

10:12 tmciver: sproc: you can't in Clojure

10:12 sh10151: do you have some code to paste?

10:13 Generally you don't want to write recur at all

10:13 the higher-order functions take care of nearly all use cases

10:13 sproc: I'm trying to process data in functional style. I am doing work recursively in an inner loop, but if I exit that form I "lose" the data in the loop variables.

10:14 But I need that processed data in the larger loop.

10:14 sh10151: it sounds like you may need to use reduce then

10:14 it's hard to say without any code

10:17 goodieboy: duck1123: dang, i can't get this resource loading to work, hmm. I can see the resources in my dependency jar, i just can't access them in my parent project. I guess it's time for me to read up on class loaders!

10:19 sproc: sh10151: http://pastebin.com/ji5V01ig

10:20 sh10151: yea, i think a reduce is the right way to go

10:20 the accumulator value is the {:col-widths :current-col} tuple or something

10:22 sproc: Yeah, there is a column loop within a row loop, so :col-widths accumulated that while :current-col tracked which column to process next

10:22 sh10151: shouldn't even need the current-col?

10:22 that kind of iteration should be taken care of by map/reduce/for whatever

10:22 main thing is to build up the col-widths map

10:23 sproc: I used it so I could use the ResultSetMetaData.getColumnName function

10:23 (which requires the index)

10:24 sh10151: sure but use map-indexed for that

10:25 (map-indexed (fn [i thing] (str i " is " thing)) ["a" "b" "c"])

10:25 ("0 is a" "1 is b" "2 is c")

10:25 there are other functions like that too but i can never keep them straight among python scheme and clojure

10:26 sproc: Ah, I see; that will be nice. I am new to Clojure and wasn't aware of that

10:26 sh10151: it's ok

10:26 main thing to remember is that you almost never need to write loop/recur yourself

10:27 sproc: I was looking at loop/recur like using auxiliary/helper recursive functions

10:27 sh10151: Sure, but the recursions themselves have already been written for you

10:27 the big ones to understand are map and reduce

10:28 if you can start looking at nested loops as combinations of those, it should come quickly

10:28 frankly I found it easiest to learn that with Haskell since it's very difficult to really do it another way :)

10:28 duck1123: clojureatlas.com is a good resource for when you know what type of function you need, but not what it's called

10:29 sproc: Alright, thanks. That will give me some good stuff to think about

10:30 sh10151: Anytime. Do you program JavaScript? There's actually map/reduce functions in most JS libraries

10:30 my frontend code bears an (un?)fortunate resemblance to Lisp nowadays

10:32 sproc: The Javascript I've done has all been pretty trivial. I am starting to read about Node though and think about ways I might want to use that

10:32 sh10151: is that the server-side framework?

10:33 my work is all JVM all the time pretty much :(

10:33 _nmmn: node.js is massive jungle of callbacks and js caveats, imo

10:33 sproc: Yeah, it's neat because it serves requests in a non-blocking way and eliminates the need for multithreading for lots of requests

10:34 duck1123: you could also use Aleph with Clojure for that

10:34 sh10151: pretty sure nginx does that too :)

10:35 pipeline: you mean sproc

10:35 node.js only gives you a single thread

10:35 so you had BETTER damn well write non-blocking code

10:35 _nmmn: true

10:35 pipeline: or else your app stops working

10:35 _nmmn: i think its similar fab as ruby

10:35 pipeline: believe it or not this is a trivial model to handle in any language

10:35 sh10151: If you do Perl this is a pretty good book on functional programming/higher order functions: http://hop.perl.plover.com/book/

10:35 pipeline: just don't call fork() haha

10:35 perl makes the whole non-blocking event-based apps easy as hell, and has done for 10+ years: POE

10:36 this is not a new model of development

10:36 it's just that node.js gives new freedom to people who were once relegated to "front end" development

10:36 sproc: I was thinking the creator chose JS because its clojures allow you to declare several nested callback functions that have access to enclosing variables; I suppose any language supporting closures could do that

10:36 pipeline: there is an entire generation of developers who came out of design and ux backgrounds, and node.js gives these guys a server side that they are comfortable with

10:36 _nmmn: true

10:36 sh10151: select() has been around since early BSD

10:36 _nmmn: still im keeping myself from js as far as possible =]

10:36 sproc: In languages without closures it can be done but would seem to be more painful.

10:37 pipeline: (unfortunately node.js carries with it a lot of the problems you find in frontend development circa 2005: bad/no debugging, awful garbage 3rd party libraries, etc)

10:37 sproc: Yeah, there are problems getting helpful stack traces

10:37 sh10151: prototype.js :(

10:45 cshell_: Can you extend a protocol on a def record?

10:54 sproc: duck1123: Neat site

10:56 duck1123: It's great for "I need to do something to this var. Oh what's that function called again?" Also good for exploring new fns

10:56 kreig1: earthlings!

11:09 gfredericks: cshell_: I should think so

11:25 dsevilla: all

11:25 I'm searching for an introductory slides on core.logic that I found the other day, but I don't remember where

11:25 they start comparing functions with relations

11:26 functions only return one value

11:26 relations relate different input parameters and result values

11:26 I searched euroclojure, clojure/conj, etc., but now I can't find them

11:26 any of you would remember that one?

11:27 pyr: technomancy: around ?

11:27 dsevilla: woodz: Yes, I found those, nice slides, but these were not

11:27 scriptor: you'll have to download the pdf, but I'm pretty sure it's that one

11:28 sproc: Why doesn't (get 1 {1 2 3 4}) return 2 instead of nil?

11:28 dsevilla: scriptor: ahhhhhh these are!

11:28 scriptor: ,(get {1 2 3 4} 1)

11:28 clojurebot: 2

11:28 dsevilla: scriptor: thanks!

11:28 scriptor: dsevilla: no prob

11:28 dsevilla: woodz: thaks to you too

11:29 scriptor: sproc: the arguments go the other way http://clojuredocs.org/clojure_core/clojure.core/get

11:29 dsevilla: very nice talk, btw

11:48 technomancy: pyr: sure

11:49 augustl: you can alias "test" to "midje" in project.clj

12:07 pyr: technomancy: i'm trying to build java + clj projects

12:07 technomancy: where the java part loads classes defined in the clj files

12:07 technomancy: and this with leiningen, goes without saying

12:08 technomancy: i'm using lein2 and i am seeing a few weird behaviors

12:09 technomancy: first thing, even though i seem to use the correct :aot configuration the java source will never compile unless i move it elsewhere, compile my clojure classes a first time then put the java files back

12:10 technomancy: then i was never able to load a class defined through deftype in the java source code

12:10 technomancy: yeah, out of the box leiningen assumes you are going to compile java first

12:10 because the java parts of a project are typically the legacy ones

12:10 pyr: technomancy: which makes snese

12:10 technomancy: you can change it with :prep-tasks; lemme see

12:10 pyr: sense

12:10 technomancy: :prep-tasks ^:replace ["compile" "javac"] ; <- in project.clj should work

12:11 pyr: ok

12:11 i will start by trying that out

12:23 technomancy: I actually had never tried changing :prep-tasks like that; always nice when I see something like that work the way it should =)

12:33 m0smith: hi all

12:34 I am getting the dreaded: error: java.lang.IllegalArgumentException: No single method: display of interface: crossfire.protocol.peg.Peg found for function: display of protocol: Peg

12:35 any hints on how to find out what the real problem is

12:36 S11001001: m0smith: I'd start with the line numbers in the stacktrace that are actually in your code

12:36 m0smith: The compiler is not spitting out a stack trace

12:37 I am compiling in emacs using clojure-jack-in

12:37 Cc-Ck

12:37 S11001001: m0smith: then use C-c C-l instead

12:37 m0smith: ok

12:44 That does spit a stack trace but none of my code is in the stack trace, as expected because it is the compiler throwing the error

12:46 S11001001: m0smith: compiler failures also have source location

12:49 harja: Hello, I'm pretty new to this clojure-stuff. What is the most idiomatic way to get input from user in a function and provide the output to another function that is called asynchronously by a framework?

12:51 I mean something in the lines of (defn get-stuff [] (let [stuff-one (get-input) stuff-two (get-second-input)] (make-profit)) (defn use-it [] (let [stuff-from (get-stuff-added)] (profit))

12:51 would a def:d vector be fine?

12:53 joegallo: harja: suggest you gist your example code so it's more understandable. as it is, you don't have enough closing parens, so it's hard to tell quite what you mean.

12:54 harja: ah the parens :) https://gist.github.com/2a31909da1ff277a8384

12:54 scriptor: harja: so in your example, use-it should get the data returned by get-stuff?

12:54 harja: that's a part of a quil script

12:54 S11001001: harja: I would use fewer intermediate bindings

12:54 in fact, I would use only two in your example, harja

12:55 joegallo: harja: generally you just use arguments to functions to hold that stuff, nothing global. (do-some-with (this-value-im-generating-right-now))

12:55 scriptor: what's wrong with the intermediate bindings?

12:55 harja: joegallo: yeah, but how do I make the framework call on the (draw) method with my stuff in it?

12:56 normally I would have done it using args and recursion

12:56 joegallo: harja: close over the results. hand them a function or whatever that will do the whole thing.

12:56 S11001001: scriptor: draw binds *everything* to be passed as an arg; has same problem as comments that narrate code directly

12:56 joegallo: (.setIntoBlah some-framework-class #(do-something-with (this-value-im-generating-right-now)))

12:57 harja: okay, got it. is there a way to do it in quil?

12:57 joegallo: clojure's anonymous functions are runnables, for instance. if one of the interfaces that clojure's functions implement isn't workable for your case, you could reify or proxy to some other interface, with basically the same effect.

12:58 harja: be more specific, please. perhaps if you explain what it is you're trying to do, we could give better advice. as it is, this is all pretty generic. for instance, in your gist, i can't quite see what's missing...

12:59 scriptor: S11001001: those comments are considered bad because they're superfluous, since the code should say what it does

13:00 in this case, that's what the code's doing

13:00 I guess canvas-center-x and y aren't strictly necessary, but they make it more readable, don't they?

13:00 harja: joegallo: Basically I understood your advice that I should somehow re-set the draw function to the framework I am using to use an anonymous function that does not take any arguments hence making it compatible with the type of function it is expecting. My question is that if this is not possible, when am I allowed to use global data structures, if ever?

13:00 and if I'm "forced" to use such things, what would be the best option

13:01 joegallo: for \$5 i'll let you use a global data structure. but you have to pay each time. :D

13:01 S11001001: scriptor: no

13:03 scriptor: why not?

13:03 harja: joegallo: is there somekind if idiomatic way of providing these new functions to frameworks? or do I have to study every one of them if I want to use them

13:04 it would be fairly trivial if I had the execution path in my hands but it's not

13:04 not even fairly, but very trivial :)

13:04 by execution path I mean the order things are evaluated as the program progresses on

13:04 joegallo: harja: you can just magic functions up at any time with (fn [] ...)...

13:04 harja: yes, I'm familiar with that

13:05 S11001001: scriptor: every name introduces an indirection you have to follow. The expressive value of the binding has to exceed that cost

13:06 nDuff: harja: Going back to your original question -- might a promise be an appropriate tool to represent the user input you're waiting for in this case? If it's something provided only once and reused multiple times...

13:07 scriptor: S11001001: in this case it's not obvious that width and height refer to the canvas's width and height, rather than something else's, so I'd probably agree with you if that was clearer given the rest of the code

13:08 S11001001: scriptor: ok

13:08 scriptor: otherwise, you run into the indirection of trying to figure out what width and height are referring to

13:08 harja: nDuff: I have the data when the function is invoked so I don't need promises here

13:08 nDuff: Ahh; I misunderstood the question, then.

13:12 harja: nDuff: Yeah, basically I'd just need a way to pass stuff to a function whose execution is handled by the framework I am using (quil)

13:12 so, given that a user drags the mouse around, I'd be happy to add the x and y coordinates to a vector and draw lines between the successive points in the draw function

13:13 srid: technomancy: http://blog.heroku.com/archives/2012/7/17/buildpacks/ <- FYI, it was me who added buildpack support to stackato :-) i have always been a heroku fan, especially their willing use of varied technologies (go, clojure, etc..)

13:13 technomancy: srid: oh no kidding; that's cool =)

13:14 joegallo: harja: in your gist, which functions are the things you're talking about? i think we're talking past each other.

13:14 technomancy: this brings me one step closer to having all my ~/src dir be OSS

13:14 nDuff: harja: ...so, as long as the function is in a closure with access to the atom/ref/whatnot pointing to the data......

13:15 harja: joegallo: i get (mouse-x) and (mouse-y) in the (defn mouse-dragged [] ...) function. I need to "store those" and use them in the (defn draw [] ...) method

13:16 technomancy: srid: you work for activestate?

13:16 harja: nDuff: Exactly. My original question was, what is the idiomatic way to do this in Clojure

13:16 joegallo: okay. now i think i get it.

13:16 harja: since I'm very new to this language

13:17 srid: technomancy: yup, and we met briefly at clojure/conj last year. ghoseb introduced me to you, if you remember. i tried using clojure to write stackato admin UI, but it was rejected, so open sourced - https://github.com/srid/horizon

13:18 nDuff: harja: ...well, I think I answered -- close over the ref.

13:18 m0smith: s11001001: thanks. I used lein compile and it is giving much more helpful messages

13:18 joegallo: right, i agree with nDuff.

13:18 technomancy: srid: ah, too bad; that can be a hard sell sometimes

13:18 S11001001: m0smith: no prob, but that was all you I think :)

13:19 m0smith: s11001001: I wonder if swank is using a different clojure version

13:20 technomancy: m0smith: swank uses clj-stacktrace; in a few cases there are problems where generating the stack trace causes another exception =(

13:20 harja: nDuff: Okay, what is considered a closure in Clojure. Is it a context defined within a let, a namespace or something else? Can I just make the ref available in the script file I am writing or do I need to do a "global closure"?

13:20 S11001001: m0smith: if you use jack-in, compiler should be running at whatever you have set in project.clj

13:20 m0smith: thanks techomancy: I'll keep that in mind

13:21 harja: so basically am I closed under a script file

13:24 can I just do (def data (ref [])) and access that in both of those functions?

13:24 It seems to work

13:24 joegallo: you could.

13:24 harja: and use @data and updating in dosync

13:24 that seems to be working the way I want to

13:24 is that a good way to do it?

13:24 joegallo: depends on the size of the program.

13:25 small programs get more leniency than large ones.

13:25 harja: yeah, this one is easilly under 1k lines

13:25 joegallo: you're probably fine

13:25 harja: if i'd need to do a bigger program, how would this be accomplished then?

13:26 joegallo: the alternative is to generate both the draw and the mouse-dragged function from a place where they have access to the same original ref.

13:26 and then that ref isn't defined globally, just in that other function-generating-function.

13:26 which is what nDuff meant by closing.

13:26 harja: yeah

13:26 that's exactly my follow-up question

13:27 so I need to explicitly close, there is no global namespace-closure, a script file closure or anything like that

13:27 joegallo: i'm not quite sure i know what you mean, but i think the answer is yes

13:28 harja: well, you can always think a namespace could have an implicit scope it could use "internally"

13:28 or a script file for that matter

13:28 joegallo: i mean, you can always just bang on the map that *is* the namespace, but i think that's generally frowned on.

13:29 harja: Okay, so it's possible but not recommended :)

13:30 But, the original question is now answered and I get to add data to my vector and consume it. Fantastic! An epsilon-sized step, but still..

13:34 joegallo: enough of those, and the sky's the limit.

13:35 Roey_: Hello, does anyone here have experience with the Monger clojure lib for MongoDB?

13:36 gtrak: yes, not me, but I'm sure someone does

13:44 sh10151: is there any downside to using local function definitions in a let?

13:48 technomancy: sh10151: could be harder to test in isolation

13:50 ToxicFrog: sh10151: I haven't seen any so far, and I've been doing it a lot

13:50 Since I don't like the aesthetics of letfn, especially when there's already a normal let

13:52 duck1123: Roey_: What's your question?

14:03 sh10151: these are pretty straightforward

14:03 they're in a let

14:04 another style question, is it bad to rely too much on dynamic vars?

14:05 specifically the way CL uses special variables for parameterization

14:05 technomancy: sh10151: it's bad to write an API that forces callers to use dynamic variables

14:06 build around lexical scope first and add dynamic scope once you have it working if the lexical version is cumbersome

14:06 sh10151: specifically this is for the mess of attributes/parameters/error listeners/URI resolvers/etc. that XSL processors make optional

14:07 gfredericks: cemerick spent a lot of effort back in the day on designing an interface that could be used either way

14:07 I'm not sure if it ended up being worth the effort/complexity

14:07 sh10151: to avoid the mutating setFoo setBar etc. would require either dynamic vars changed with binding

14:07 or 10-argument functions

14:08 gfredericks: sh10151: maybe condense a lot of the args to a map?

14:08 technomancy: take a map and bind the default that you use if a given value isn't in the map

14:08 sh10151: there's a map for attributes

14:08 a map for parameters

14:08 a map for features

14:08 gfredericks: a map for maps!

14:08 sh10151: and a variable for error listener and a variable for uri resolver

14:09 so it's still preferable to pass in one big config-type map in this case?

14:12 gtrak: sh10151: you could parameterize the building of the map with another api

14:19 sh10151: well, the use case is, 90% of the time it will contain nothing

14:19 then occasionally one or two customizations will be needed

14:20 or xsl-params are provided

14:20 that's really the most common case

14:33 pyr: c/lear

14:40 harja: what's the Common LISP progn equivalent in Clojure?

14:41 arrdem: harja: (do) if I remember correctly

14:41 ,(doc do)

14:41 clojurebot: Gabh mo leithsc?al?

14:41 harja: yeah, found it :)

14:42 arrdem: thanks!

14:43 arrdem: (doc do)

14:43 clojurebot: I don't understand.

14:43 arrdem: technomancy: first it speaks Irish and now it's retarded. a little help here?

14:58 twhume: I'm having trouble getting futures to cancel; future-cancel returns true, but CPU usage goes through the roof, so I think my function is still running. Any ideas? I've written up the issue and had a couple of responses at http://stackoverflow.com/questions/11520394/why-do-cancelled-clojure-futures-continue-using-cpu

14:59 Right now I'm thinking of going in and doing it all myself, but I know that's exactly the kind of thing I should avoid doing if possible...

15:01 wingy_: how do i get lein server to allow connections from the outside world?

15:15 neotyk: dnolen: ping

15:15 dnolen: neotyk: pong

15:16 neotyk: dnolen: do you know the reason for using CrossPageChannel in BrowserREPL?

15:17 dnolen: neotyk: I responded on the ML, it works everywhere back o IE6, we're not going to replace it. If you want another transport give us a patch to support alternate transports.

15:21 neotyk: dnolen: I've seen stuff in clojure.browser.net, but only now it appeared to me that there is still a websocket stuff that was enabled by recent closure

15:21 nDuff: clojure-users

15:22 dnolen: neotyk: yes.

15:22 augustl: is there a way to force leiningen to download the latest snapshots?

15:22 dnolen: neotyk: if it's there I'm sure a lot of people would leverage it too.

15:22 neotyk: dnolen: let me follow up on it than

15:23 dnolen: neotyk: CrossPageChannel is slow.

15:24 neotyk: how do I make lein-cljsbuild run against local cljs build?

15:24 dnolen: neotyk: checkouts

15:25 neotyk: I'm pretty sure lein-cljsbuild mentions this.

15:28 neotyk: emezeske: just reading it, thanks

15:32 augustl: does "lein deploy" also update ~/.m2 for snapshots? Or does it just upload to the repo?

15:33 seems like it's the latter. Had some problems with a new snapshot (my own internal lib) not being available, deleting ~/.m2 fixed it though

15:40 uvtc: What else do I need to use sqlite from Clojure aside from clojure.java.jdbc? Which driver is the canonical one for sqlite?

15:41 metajack: org.xerial/sqlite-jdbc is the one i use

15:42 i use it with korma and it works out of the box.

15:42 uvtc: metajack: That's the one I see mentioned in the CP-oreilly book, but clojars has listed sqlitejdbc (zentus).

15:42 Oh.

15:43 metajack: it's not in clojars :)

15:43 hiredman: I'd recommend derby or h2 over sqlite, unless you specificly need sqlite

15:43 metajack: most of the java libs come from maven central

15:43 hiredman: why is that?

15:44 hiredman: metajack: because derby and h2 are both "native" to the jvm

15:44 uvtc: metajack: Whoops. I just realized --- it's a java lib, since it's for Java's jdbc to talk to sqlite.

15:45 hiredman: the sqlite driver, last I heard tries to load a native library, and if that fails falls back to emmulating a risc cpu on the jvm (which sounds so crazy it makes me want to google it and make sure)

15:45 uvtc: hiredman: I don't specifically need sqlite. I'm familiar with it, and like that it's small, fast, and simple though. Have not looked into derby or h2.

15:45 metajack: uvtc: I was in the same position the other day. I found it by typing "!mvn sqlite" into my search bar, which uses duckduckgo's redirection to get me to maven's search page

15:45 clojurebot: dakrone maintains clj-http

15:45 hiredman: http://nestedvm.ibex.org/

15:46 metajack: hiredman: I'll keep those in mind for future projects, although I do like the ability to use the sqlite3 commandline tool to poke and prod the database.

15:47 uvtc: hiredman: I've got sqlite3 (and libsqlite3-0) installed (on GNU/Linux).

15:47 augustl: technomancy: "17:52 < technomancy> augustl: you can alias "test" to "midje" in project.clj" - thanks, didn't notice until now :)

15:47 clojurebot: I'm no man, and she's no lady!

15:48 hiredman: uvtc: so?

15:48 uvtc: hiredman: You'd mentioned what happens if the JVM fails to load the native library.

15:48 duck11231: uvtc: you also have a ~/.m2, so having one of the others is a lein deps away

15:51 although, that seems suspect, I am pretty sure derby supports indices

15:51 augustl: technomancy: weird, `:aliases {"test" "midje"}` seems to run _both_ `lein test` and `lein midje` when I run `lein test`. Both midje and clojure.test output is there.

15:51 uvtc: hiredman: reading about derby and h2. Thanks for the recommendations.

15:52 duck11231: augustl: lein midje also runs normal tests

15:54 augustl: duck1123: right, I want "lein test" to run midje tests though

15:54 oh, I think I see what you mean

15:55 anyways, the output is different from "lein test" and "lein midje" when I alias test to midje

15:56 https://www.refheap.com/paste/3656 for an example

15:56 (prompt at line 16)

15:57 duck1123: augustl: yeah, that second one is definitely lein midje

15:57 augustl: duck1123: right, but there's some additional output there too

15:57 plain clojure.test output

15:57 which isn't present witih "lein midje"

15:58 so it's kind of weird that it is, since "lein test" is an alias to "lein midje" in this paste

15:59 duck1123: augustl: you're right, it looks like your alias isn't working

16:00 midje runs it's tests when they're evaluated, so if you have facts in your test nses, they'll be run, but unless you've wrapped them, they won't be reported on

16:01 augustl: duck1123: it does kind of work though :)

16:01 "lein test" without the alias doesn't run midje tests

16:01 oh wait, never mind, it does :)

16:01 aib: can anyone help me get penumbra to run? http://paste.ubuntu.com/1097213/

16:01 augustl: should have checked that

16:02 that is, it contains the "WORK TO DO" calls as they probably print immediately

16:02 duck1123: so it's the alias that simply isn't working

16:02 perhaps aliases is a lein 2 thing

16:02 duck1123: augustl: that's what it looks like

16:03 amalloy: aib: you really want to use leiningen; it will stop you from getting the classpath wrong (which is what's happened)

16:04 specifically, -jar ignores classpath settings, assuming the jar you pointed at has all the classes it needs

16:04 aib: ahh

16:05 this is my first (2nd?) time using clojure/lein. Any reading material would be appreciated

16:05 amalloy: to do it manually (which, again, i don't recommend) you need the classpath to include the jar and run clojure.main or something

16:05 ~leiningen

16:05 clojurebot: http://github.com/technomancy/leiningen

16:08 aib: ah, I did compile the project using "lein deps" + compile. the getting-started file then told me to run some clojure commands, that's why I did java -jar, which was probably wrong, in retrospect

16:10 in which case, https://github.com/ztellman/penumbra/wiki/getting-started - how do I run the REPL after 'lein deps' and 'lein compile' ?

16:12 oh no. there's a 'lein repl', isn't there?

16:12 of course there is.

16:31 wingy: i feel that we should pay the maintainers of a project even if it's OS

16:31 devn: hello clojurians

16:31 wingy: to have high quality libs

16:32 Raynes: wingy: Those are called donations.

16:33 wingy: they shouldn't be donations

16:33 they should be earnings

16:33 Raynes: I'll be expecting a paycheck in the mail.

16:33 wingy: you pay a carpenter making a chair for you

16:34 if someone is making a good lib and you need features added and maintenance you should pay for it

16:34 or the project might die put

16:34 out

16:34 emezeske: wingy: You can't make a perfect copy of a chair for less than one cent of electricity, though :)

16:35 wingy: kinda like ExtJS .. they started from just a lib and charged money

16:35 nDuff: wingy: You first.

16:35 wingy: now they are big .. and the thing is they can make it better

16:35 just saying

16:35 im not a lib maker

16:35 nDuff: wingy: ...or, better, you could start by reading CatB and its kin, on how and why OSS works in practice.

16:35 duck1123: So if you're forced to pay for open source software...

16:35 wingy: nothing wrong to charge for things .. if they need to make a living they wont have time to fix the libs

16:36 fulltime

16:36 nDuff: wingy: Nonsense. If your software is useful enough, companies will pay people to improve it in their own self-interest. That's not theory, it's actual practice.

16:37 wingy: I've spent a damn lot of time fixing up OSS code while on salary, as do most people here. If that isn't paying to fund software development, what is?

16:37 wingy: there is a diff between pet projects and actual production ready projects with high doc and support quality

16:37 emezeske: wingy: I totally agree that there's nothing wrong with charging. I do think for certain projects, though, the "payment" can be in terms of bug reports, bug fixes, extra eyeballs, patches, etc

16:37 wingy: emezeske: yes

16:38 nDuff: wingy: "pet project" something someone is doing only because they choose to. I'm talking, again, about people doing work on payroll with authorization, but without their employer receiving direct remuneration for that effort.

16:39 technomancy: the software I love using most is generally written because the author couldn't not write it

16:39 wingy: i don't think a person chooses doing pet projects .. he just doesn't have the resource making it better and going all in for it

16:39 nDuff: *sigh*.

16:39 emezeske: technomancy: That is a great indicator! :)

16:39 nDuff: wingy: again, you're assuming this silly dichotomy that anything that isn't work-for-hire is a "pet project". It's frankly insulting.

16:40 wingy: nDuff: no .. i meant terse doc .. no maintenance

16:40 just saying you may have the skills and knowledge but you need the fuel

16:41 just another ingredience

16:41 nDuff: wingy: I've pointed you at some essays on how and why the ecosystem works. Please read them before continuing this conversation.

16:41 wingy: be good at development, be good at business

16:41 the market needs it

16:43 emezeske: wingy: Keep in mind that some people are motivated by things other than money, though.

16:43 wingy: well we all know why Ubuntu is getting more popular than Debian … they know business as well

16:43 hiredman: not I, money money money

16:44 wingy: emezeske: cant agree more .. im not talking about we do it for money..im talking about money can help

16:44 emezeske: hiredman: I guess that's why you're "hiredman" instead of "volunteerman" :)

16:44 wingy: and not trying to start a flame war but we do have to agree a lot of potential projects could be more solid

16:45 technomancy: the original meaning of the word "amateur" actually comes from the root "amor"; in other words, done out of love.

16:45 emezeske: wingy: Sure, but money isn't always a fix

16:45 mattmoss: Throwing money at things is not an automatic win.

16:45 wingy: emezeske: didnt say that .. it helps

16:45 clojurebot: Pardon?

16:45 mattmoss: However, throwing money at me is a wonderful thing.

16:45 wingy: mattmoss: i agree .. throw it on top devs coding for love

16:45 emezeske: Heh, it sometimes helps.

16:46 wingy: but they need to make a salary as well

16:46 emezeske: technomancy: Interesting fact!

16:46 wingy: not everyone wants to use java/php at their job

16:46 mattmoss: wingy: What if they're already salaried? You seem to have ignored nDuff's points.

16:46 duck1123: throw money at me and I consider it a win. Just not pennies, those hurt

16:46 technomancy: emezeske: call me a professional amateur =)

16:46 mattmoss: Pennies aren't worth anything anyway.... except for making large penny pyramids.

16:47 emezeske: technomancy: Same here!

16:47 wingy: mattmoss: not everyone works on the thing they really want to work on

16:47 mattmoss: some work for money only, no love at jobs

16:48 mattmoss: You seem to be conflating a few different arguments. Perhaps sticking to one at a time?

16:48 wingy: mattmoss: i dont get what you mean .. everything is connected?

16:48 mattmoss: Everything is connected? I highly doubt that.

16:49 wingy: you do what you love .. you make a living out of it .. you can throw more resources at it .. KISS people

16:49 technomancy: everything is intertwigled

16:49 wingy: not saying money is everything so stop throwing that at me

16:49 duck1123: mattmoss: You've obviously never taken acid

16:49 mattmoss: Complected?

16:49 duck1123: That's true.

16:49 Did you hear the one about the Buddist in New York City who asked a hot dog vendor, "Make me one with everything." ?

16:49 * emezeske high fives duck1123.

16:50 technomancy: I'm all for contributing money to oss projects, but the idea that the devs can use their donations to work on their projects full-time only works with very high-profile projects

16:51 wingy: technomancy: yes

16:51 i mean .. my parents sell food for just a small town .. they make more money than 10 developers in total

16:51 one dev makes a lib 500-1000 people are using .

16:52 i say that is not that hard as we have seen, but no money in? makes me wonder .. money isn't evil..taking charge somehow can be good for everyone, the users especially

16:53 if devs know how to take charge i think the OS market would be more solid and with good quality, doc, testing etc

16:53 technomancy: you have to have a lot of money (and a predictable stream of it) before you can quit your job to do something full time

16:54 aaelony: you need a pipeline of work or a rainmaker :)

16:54 wingy: technomancy: you make what you love at freetime as you always do and then take charge for it when you have > 300 users

16:55 more than 300 users using your thing .. yeah that is a product you have

16:55 uvtc: mattmoss: the customer paid for the hot dog with a 10, but the vendor didn't give him any change. When the customer asked for his change, the hot dog vendor said, "Change comes from within."

16:55 duck1123: There was a site I saw that let you set Bitcoin bounties for checking in passing commits or fixing bugs, but I can't seem to find the original link

16:56 mattmoss: uvtc: Good one.

16:56 wingy: im not the "i need to charge guy" im the "i pay you just make good docs and better features so I feel happier" .. that's what we are used to when buying iphone/android apps .. pay a small fee for something you want .. you are not participating in an evil cult

16:56 the OS projects could definitely be charged as apps

16:57 technomancy: I'll happily pay for software as long as it's open source

16:57 wingy: me 2

16:58 mattmoss: wingy: It's not an evil cult, no, but your "i pay you..." statement comes off as a demand, not a request.

16:59 joegallo: i wonder how that model is working out for the itext guy.

16:59 mattmoss: Great thing about open-source... fork and improve.

16:59 uvtc: ... and send pull-request. :)

17:01 wingy: mattmoss: didn't solve the resource problem

17:01 mattmoss: wingy: What resource problem?

17:01 wingy: :/

17:02 mattmoss: The resources necessary for developing software are human effort.

17:02 One way to acquire that is through money to an interested developer, but is hardly the only way.

17:02 kreig1: wingy: can you guess why I am skeptical of your perspective on open-source software and what goes into the process of making software?

17:03 mattmoss: The developer you are demanding write docs in exchange for \$\$\$ may be more interested in throwing around the football with his kids...

17:03 ...meanwhile another developer who likes writing docs (if there is such a thing) would happily fork and improve the project if asked.

17:03 wingy: mattmoss: what a company does with their money i cannot control .. but i think we all we'll see the outcome for each version

17:04 mattmoss: Or a company decides it is in their best interests to hire/pay for those docs.

17:04 kreig1: and whose to say the best part of software production is the software?

17:04 wingy: and i doubt that passionate devs would wanna kill their baby project

17:04 it's their life

17:04 nDuff: wingy: ...so, just took you off ignore to explain something. You gave ExtJS as an example of a project "doing it right". For me, it's an example of a project I can't use commercially, because my employers (the last several of them!) won't touch software with for-cost licensing, no matter how useful it is, period -- and that hurts the project, because I contribute real, useful things -- well-researched bug reports, fixes, new f

17:04 eatures, etc.

17:04 mattmoss: wingy: You are making many unfounded assertions.

17:05 nDuff: wingy: ...so, you're actively advocating a model that would make my life worse by increasing the range of Stuff I Can't Use.

17:05 wingy: nDuff: first of all i didn't ignore anything .. if there is something i didn't address just ask again .. its a quite broad discussion

17:06 nDuff: well if you put it in that way i can't argue anymore

17:06 kreig1: hehe

17:06 good, then stop

17:06 so, how about those macros

17:06 * mattmoss goes back to his paid, proprietary software development. *snicker*

17:08 scriptor: there was an article about how soldiers reacted when the red cross started charging for formerly free donuts

17:09 not sure how relevant it is, but it's interesting to think of the psychology

17:09 technomancy: gratis donuts, you mean

17:09 scriptor: donuts libre

17:09 technomancy: the soldiers weren't improving the donut recipe as they ate them, though that would be awesome if they could

17:10 kreig1: according to e. coli they were

17:10 technomancy: "hm; have you considered what a little nutmeg would do to the flavor profile here?"

17:10 scriptor: more like, "this donut doesn't work horribly unformatted donut-mulch attached plz fix thx"

17:10 mattmoss: Mmm, donuts libre. *drool*

17:11 technomancy: the red cross is all "HAVE YOU SIGNED PAPERWORK"

17:12 mattmoss: Curious if anyone is doing heavy Java interop... I'm split over passing around lots of POJOs vs. wrapping them in maps (with extra info at times).

17:13 Like... (defn create-foo [a b] (Foo. a b)) vs. (defn create-foo [a b] {:instance (Foo. a b)})

17:25 gfredericks: mattmoss: I don't think it'd be idiomatic to wrap them except for the purpose of the extra info; i.e., not for its own sake

17:27 duck1123: It really depends on how close to the line you're working

17:27 mattmoss: gfredericks: I suppose what I was mulling over was passing around maps of things and shoving them into POJOs at the point of a Java call, or requiring use of POJOs spread throughout the clojure code.

17:27 The former seems cleaner, "nicer", Clojure code... hiding away the "nasty" details of POJOs.

17:28 But I may just be needlessly worrying.

17:37 nDuff: I'm interested in temporarily disabling watches on a known list of atoms during test setup/teardown. Is a mechanism available?

17:38 technomancy: nDuff: can you just with-redefs the associated vars to (constantly true)

17:38 I guess that only works if you pass the var in as the watcher, not the function itself

17:40 nDuff: ...so, I could see doing that to just put in entirely new atoms, but the effects of the watches are a big part of what I want to test during operation.

17:40 * nDuff supposes he might just put calls in his logic to set up and tear down the watches, and call it done.

17:41 wingy: do you guys use a statechart/statemachine in frontend cljs when coding? if not, how do you usually organize your code?

17:44 siscia: aaelony, thank you also for jiraph ;-D

17:44 duck1123: wingy: Have you seen Waltz?

17:45 I just refactored some of my code this past weekend to use that, seems pretty nice so far

17:49 wingy: duck1123: ill give it a try .. seems to be the most popular one in cljs land

17:50 in worse case scenario if that won't cut it I see if I can use http://stativ.us/ with cljs

17:51 if the oop style would work nicely

17:51 duck1123: wingy: Heres what I did with Waltz. https://github.com/duck1123/jiksnu/blob/dev/src-cljs/jiksnu/websocket.cljs

17:52 still a WIP, obviously

17:52 hiredman: b

17:53 aaelony: siscia: thank flatland folks... who are awesome to the hilt

17:54 wingy: duck1123: great i can use your project as a template for frontend :)

17:54 duck1123: And on that note, I'm out of here. Time to get home and trade in my Java and js for Clojure and cljs.

17:54 wingy: haha

17:54 duck1123: wingy: have at it. Share and enjoy

17:55 Raynes: amalloy: Here that, Alan? To the hilt.

17:55 Hear, even.

17:55 Here, there, whatever.

17:55 fsmunoz: If you allow an external observation, you clojure guys seem permanently in a state of bliss. Every time I read the buffer it's all about people saying nice things about the language, the libs, the weather.

17:56 Raynes: Clojure rocks! I sampled everything in the medicine cabinet for comparison, but I think that this euphoria is the Clojure.

17:56 technomancy: fsmunoz: just wait; we've overdue for someone to announce their independent re-invention of "lisp without parens, to make it easier for newbies" on the mailing list

17:57 emezeske: Raynes: Nice, you got your doctor to write you a clojure-script?

17:58 aperiodic: (inc emezeske)

17:58 lazybot: ⇒ 1

17:58 fsmunoz: technomancy, Raynes: heheh

18:04 SegFaultAX|work2: The documentation format for special-forms and macros kinda sucks.

18:05 (fn name? ([params* ] exprs*)+) <- it's like a weird mixture of ad-hoc sexp and regex.

18:06 TimMc: It's more like BNF, really.

18:06 SegFaultAX|work2: TimMc: Except for not.

18:06 TimMc: But if I squint really hard, I see your point.

18:07 TimMc: Either way, the usage of ? + and * (and the implied meaning of each) makes it look more like a syntax based on regex.

18:07 clojurebot: the best way to represent X is as a regular clojure map. (for most values of x)

18:07 TimMc: Like BNF that has been condensed. You can do that more easily with languages whose syntax is close to their AST.

18:08 fsmunoz: speaking of weird, is there a reason why the doc string is before the args? It looks weird to me, but I suppose there is a language feature that makes this sensible?

18:08 TimMc: clojurebot: We value your input. Please wait for the next available logger.

18:08 clojurebot: It's greek to me.

18:08 SegFaultAX|work2: TimMc: Except for BNF has the descriptive power of telling me exactly valid and invalid syntaxes. This format is only approximate and doesn't really describe anything about the form in any detail.

18:09 TimMc: fsmunoz: I could come up with philosophical reasons re: doc-driven development, but the real answer probably lies somewhere in the multi-arity syntax.

18:09 SegFaultAX|work2: That would be my guess as well.

18:09 fsmunoz: TimMc: yes, that was what I was suspecting

18:09 ty

18:11 TimMc: It's easy to accidentally write (defn foo [args] \n "docstring but not really" ...) and have a fake docstring. :-/

18:11 Anyone know if ibit catches that?

18:11 *kibit

18:11 SegFaultAX|work2: TimMc: Is that a clojure linter

18:12 Ah, static code analysis.

18:19 wingy: what do you think about http://emberjs.com/documentation/ for frontend with cljs .. it's using MVC/OOP approach

18:19 statemachine is one of the things included

18:21 SegFaultAX|work2: wingy: I like backbone. Ember is pretty heavy for what I'm usually looking for.

18:21 wingy: Just my \$0.02

18:21 wingy: SegFaultAX|work2: but is using a MVC/OOP framework OK even for a FP lang?

18:22 SegFaultAX|work2: wingy: Those don't really have anything to do with each other.

18:22 wingy: SegFaultAX|work2: now you have to put your maps/vectors into their models i guess?

18:22 SegFaultAX|work2: wingy: MVC is a design pattern for separation of concerns. In a nutshell: Models are for application state and business logic, views are for UI/UX, and controllers are a bridge between them.

18:24 wingy: yeah i know, was curious about if that would break something important now when I think data and logic should be kept separate

18:24 fsmunoz: I think that they can match well, especially if one considers that the view is mostly about side-effects

18:25 SegFaultAX|work2: wingy: That isn't really related to MVC, so you're probalby good there if that pattern matches your problem.

18:25 fsmunoz: and the model can be thus more "pure", containing the actual logic and not polluted by (doto (.JFrame)...)

18:25 (or whatever it is really like)

18:25 wingy: ok

18:25 seems that we are all green to go

18:26 that's is one of the selling point to clj/cljs to me that it's pragmatic to leverage the current libs/frameworks in the host env

18:26 SegFaultAX|work2: fsmunoz: Maybe if you separate models from persistence (eg Models & Repositories) but when those two concepts are coupled (which they often are) then both can be heavily side-effecting.

18:26 wingy: without wrappers

18:26 SegFaultAX|work2: fsmunoz: After all, it's up to the models to transform application state.

18:27 fsmunoz: SegFaultAX|work2: quite right, haven't thought of it that way

18:27 wingy: yay . so now we have bootstrap and emberjs including a statechart for free

18:27 SegFaultAX|work2: fsmunoz: In other words, unless the data layer is abstracted away, models will necessarily be side-effecting.

18:39 I need to interop with git, what's a good library to do that with?

18:40 Raynes: clojure.java.shell

18:40 ;)

18:40 technomancy: there are a couple jgit wrappers; don't use the one from seajure as it was a swarm-coding exercise and not further maintained

18:41 SegFaultAX|work2: Actually maybe just writing a wrapper for working with git from the shell wouldn't be so bad.

18:42 technomancy: jgit is great for reading; I haven't used it for commits and push/pull stuff

18:42 SegFaultAX|work2: technomancy: This would be read-only.

18:42 amalloy: write a wrapper for working with git from the shell? isn't that just git?

18:42 technomancy: git's CLI is beyond awful though

18:43 amalloy: whaaaat

18:43 SegFaultAX|work2: technomancy: I use it everyday.

18:43 technomancy: I don't find it that bad.

18:43 amalloy: get out of my channel, technomancy

18:43 it just is.

18:43 amalloy: there are some bad things for sure

18:43 technomancy: it overloads commands to do like five different operations

18:43 it calls the staging area the "index"

18:44 you learn about how it's bad, and you stop noticing it if you use it every day

18:45 every time I have to drop out of magit and use regular git it just feels so backwards

18:45 SegFaultAX|work2: technomancy: Your first point is somewhat true. Second one is irrelevant. As for the third, well you learn to live with the warts of any tool if it helps you Get Shit Done (tm)

18:46 technomancy: I agree; I still use git. I just think you can do better if you're going to wrap it.

18:46 SegFaultAX|work2: Which commands do you feel are too heavily overloaded?

18:46 technomancy: "checkout" is the most obvious one

18:46 SegFaultAX|work2: Why do you think that?

18:46 technomancy: because it's used for switching branches as well as discarding changes to the working copy and a few other things

18:47 there's no conceptual coherence to it

18:47 gtrak: you're not 'discarding changes', that's just a side-effect

18:47 technomancy: the underlying model of storage is very good, which is the only reason tools with a good UX like magit can be built on top of it

18:47 SegFaultAX|work2: It does exactly 1 thing, it changes your working directory based on a commit-ish.

18:47 That's all.

18:47 technomancy: no, it creates new branches too

18:48 SegFaultAX|work2: technomancy: No it doesn't. git-checkout -b does.

18:48 technomancy: yes?

18:48 clojurebot: yes isn't is

18:48 technomancy: also: IIRC git branch creates a branch without switching to it; wtf

18:48 no one has ever wanted to do that

18:48 SegFaultAX|work2: technomancy: Because all its doing under the hood is associating a ref with a commit-ish.

18:49 gtrak: I just saw in mercurial yesterday, hg resolve discards local changes and pulls up a merge tool... hg resolve -m says you've already resolved it

18:49 technomancy: SegFaultAX|work2: who cares what's happening under the hood?

18:49 SegFaultAX|work2: Sure they do. Before a rebase operation you might make a "backup" by using git-branch.

18:49 technomancy: it's ignoring the perspective of a user

18:49 SegFaultAX|work2: Which really means "I don't want to look through the reflog if I fuck this up"

18:49 gtrak: mercurial's user philosophy is supposed to be better

18:49 technomancy: I've forgotten most of my other complaints because luckily I can most things done with magit these days

18:49 gtrak: git's user experience was never its selling point

18:50 SegFaultAX|work2: technomancy: The problem is you don't grok git.

18:50 technomancy: Remembering that it started as a collection of tools instead of one big application helps.

18:50 technomancy: SegFaultAX|work2: the problem is you have to understand irrelevant details to use it effectively

18:50 SegFaultAX|work2: technomancy: Perhaps.

18:50 technomancy: oh, the other big thing was that everyone says "git pull is the same thing as git fetch plus git merge" but there are subtle details between the two, and fetch+merge is pretty much always what you want

18:51 since pull ignores certain aspects of the remote IIRC

18:51 SegFaultAX|work2: technomancy: What are the subtle details you're thinking of?

18:51 technomancy: It doesn't.

18:51 technomancy: I sort of wish I could remember, but on the other hand I'm also kind of glad I've forgotten =)

18:51 SegFaultAX|work2: technomancy: But you can certainly get weird issues if your refspecs are configured improperly, I'll give you that.

18:52 hiredman: technomancy: push pushes everything if you don't give it a branch?

18:53 SegFaultAX|work2: I'm not a git evangelist. I just hear a lot of people bitch about git without having meaningful arguments against it. "It's harder" is a fine argument all by itself which most folks won't disagree with.

18:54 technomancy: hiredman: that's a fun one too

18:54 the problem is that git devs claim that git is both porcelain and plumbing, but it's really all just plumbing with various levels of polish applied

18:55 hahaha: "Git refers to implementation details as “plumbing” and the user interface as “porcelain”, in order to make it clear that git’s designers think of git with the same reverence I think of the instrument that handles the organic waste that my body produces."

18:56 reset is another example of a single command that has many different purposes

18:57 SegFaultAX|work2: technomancy: Sorry, my connection died.

18:57 technomancy: What were you saying?

18:57 amalloy: yeah, reset is poorly named

18:58 Raynes: SegFaultAX|work2: He was saying whinewhinewimperbitchblaaaahblurggitsucks.

18:58 SegFaultAX|work2: Haha.

18:58 technomancy: SegFaultAX|work2: "reset is another example of a single command that has many different purposes"

18:58 SegFaultAX|work2: amalloy: reset is easily one of the more complicated features of git.

18:58 technomancy: I like it as an API, but it leaves a lot to be desired as an application

18:58 SegFaultAX|work2: amalloy: It allows you to interact with the tree, index, and working directory all in one.

18:58 technomancy: and usually I don't have to use it as an application, so I'm fairly happy

18:59 SegFaultAX|work2: technomancy: I agree to a certain extent that reset is overloaded. But understanding how it /actually/ works really helps.

19:00 technomancy: well-designed applications allow users to learn gradually

19:00 SegFaultAX|work2: technomancy: Most new or mid-level users of git have only a basic understanding of how git-reset operates.

19:00 amalloy: SegFaultAX|work2: i don't know why you're telling me this. i like reset

19:01 SegFaultAX|work2: amalloy: Awesome! All I got was that it's poorly named. :)

19:01 amalloy: well, it is

19:01 SegFaultAX|work2: amalloy: Dunno what else I'd call it.

19:01 amalloy: i'm very comfortable with git; i don't need evangelizing :P

19:02 SegFaultAX|work2: "ref-sync" maybe.

19:03 Raynes: I'd call it reset.

19:03 That's much better than reset.

19:03 SegFaultAX|work2: :)

19:04 gtrak: git reset --hard just makes me feel lika a badass

19:04 amalloy: and then usually an idiot, right?

19:04 SegFaultAX|work2: gtrak: git reset --hard && git clean -df

19:04 gtrak: Like a boss.

19:04 gtrak: what's that do?

19:04 Raynes: technomancy: You should use mercurial.

19:04 SegFaultAX|work2: gtrak: Also removed everything untracked.

19:04 amalloy: technomancy: i guess i would say that the git cli has the same problem emacs does: it's not very discoverable, but it's powerful and usable

19:04 gtrak: amalloy: haven't blown my foot off with that yet

19:05 technomancy: Raynes: magit solves all my problems

19:05 SegFaultAX|work2: amalloy: Some people say the same thing about vim. I think most complex tools get that wrap.

19:05 gtrak: I want your hardest reset, git... don't hold back

19:05 technomancy: git reset --hard --with-a-vengeance

19:06 duck1123: you have to pass --hard to get the special ending

19:06 SegFaultAX|work2: technomancy: Does that null out the sectors on my hdd before it resets?

19:06 duck1123: No one likes it --soft.

19:14 wingy: i need to dig deeper into git

19:15 jballanc: Question on idiomatic clojure: if I have a filter of a lazy-seq, and I want to print all of the matching entries, what's the best way?

19:15 right now I'm using println and clojure.string/join with "\n"…but it feels wrong

19:16 emezeske: jballanc: What feels wrong about that?

19:17 jballanc: I just feel like I should be able to pass println to the seq, instead of having to join the seq and pass to println

19:17 for example, if it were Ruby, I'd finish with "filtered_list.each { |elem| puts elem }"

19:18 emezeske: Well, you could (doseq [elem elems] (println elem))

19:18 jballanc: but, everything I try, I just keep ending up with more lazy-seqs

19:18 ah, doseq will realize the lazy-seq?

19:18 gtrak: jballanc: (apply println seq?)

19:18 emezeske: gtrak: Isn't apply lazy?

19:18 gtrak: ,(apply println [1 2 3 4 5])

19:18 clojurebot: 1 2 3 4 5

19:19 gtrak: emezeske: the realization is lazy, but the invocation isn't

19:19 errr...

19:20 it's not curried, so I'm not sure why it would be lazy

19:20 emezeske: jballanc: Yes, doseq's purpose is to be un-lazy

19:20 jballanc: I should say, it's purpose is for side-effects

19:20 jballanc: ah, yes…that works perfectly

19:21 thanks, emezeske!

19:21 gtrak: ,(let [_ (apply println [1 2 3 4 5]) _ (println "should happen second")] nil)

19:21 clojurebot: 1 2 3 4 5

19:21 should happen second

19:21 gtrak: emezeske: ^

19:21 emezeske: gtrak: At any rate, that's not what jballanc is trying to do

19:22 gtrak: why not?

19:22 emezeske: See his original example, he is printing each element on a separate line

19:22 gtrak: jballanc: if you want to make it feel nicer, try interpose and I think there's a \newline

19:22 ah, but still lazy

19:23 gtrak: until you do it

19:23 that's kinda the point of laziness

19:23 emezeske: jballanc: Just use doseq, that's exactly what it's made for

19:23 jballanc: right…so, to give more context, this is reading a file in the context of a with-open

19:24 it's annoying that if the expressions all evaluate lazily until you finish the with-open form, you get a Exception in thread "main" (java.io.IOException: Stream closed)

19:25 gtrak: jballanc: yea, you need to do something to actually realize it, doseq, mapv, into

19:26 jballanc: got it

19:26 I'm still learning, but I actually rather like this aspect of clojure

19:31 gtrak: jballanc: I like to think about it like lazy seqs are reified computations in value-land, and side-effects aren't compatible with that notion. What's the conceptual value of that item if it depends on a resource having not been closed yet?

19:35 jballanc: gtrak: it's a good question but, if I may be so bold, couldn't closing the stream be done lazily when the list is fully realized?

19:36 gtrak: jballanc: sure, if you're doing that you want to use a countdownlatch or something

19:36 but then what if it isn't fully realized?

19:37 but yea, that's the secret, contain as a value everything that the value depends on

19:37 jballanc: yes, not at all an easy task…in any language, I think

19:53 wingy: what is the reason for this inconsistent naming in cljs: (array) for creating an array and (js-obj) for creating an object?

19:54 gtrak: wingy: inconsistent how?

19:54 wingy: why not js-array or obj

19:55 gtrak: (def js-array array) ; mm feels so much better ;-)

19:56 kreig1: array is a shared type, js-obj is a jscript specific type?

19:56 hmm, no, not tit

19:57 Raynes: Always tit.

19:57 kreig1: there are not arrays in cljs, don't have a repl open to confirm tho

19:57 emezeske: kreig1: There are arrays in cljs

19:57 kreig1: vectors tho right?

19:59 wingy: gtrak: ...

19:59 kreig1: I know that, but it's not a native clojure type, but I have a hunch that distinction is in my head only

20:00 gtrak: I was looking for a all? instead of an every? the other day... I think it just happens sometimes

20:00 thankfully it's not that big a deal

20:02 wingy: hi there, I'm a such mature person who talks inbetween the lines all the time since i find it's contributing

20:03 instead of trying to help to answer the question i make a fool of them so they find them self in shame

20:03 gtrak: wingy: sorry I don't know the answer, it doesn't seem to me like it's intentional either way

20:37 bloudermilk: This is a very broad question and I apologize for that, but is there any reason a function would behave differently in the REPL than when running lein run?

20:37 kenneth: hey is there a way to use stuff in /usr/share/java in my class path with lein

20:38 bloudermilk: Such as environment differences?

20:38 aperiodic: bloudermilk: yes; the REPL forces evaluation of lazy sequences

20:38 gtrak: bloudermilk: the repl does bind some vars that aren't there otherwise

20:39 technomancy: bloudermilk: the repl also pulls in a few dependencies needed for clojuredocs etc.

20:39 and nrepl

20:39 bloudermilk: Ah that seems like a likely source of the problem

20:39 gtrak: aperiodic: I think I've been hit by that one

20:40 bloudermilk: aperiodic: pretty sure that's what I'm experiencing

20:40 technomancy: kenneth: short answer: no, it needs to pull from a real repository in order to avoid certain kinds of problems

20:40 ~repeatability

20:40 clojurebot: repeatability is crucial for builds, see https://github.com/technomancy/leiningen/wiki/Repeatability

20:40 aperiodic: bloudermilk: check out doall, dorun, and doseq

20:40 bloudermilk: aperiodic: Will do. Shouldn't calling map on a set evaluate it though?

20:41 emezeske: bloudermilk: map is lazy.

20:42 bloudermilk: A hah!

20:42 technomancy: clojurebot: map?

20:42 clojurebot: map is lazy

20:42 aperiodic: bloudermilk: the set will be evaluated, but the lazy sequence produced by map may not have its elements realized without something that forces it

20:42 kenneth: technomancy: what's the traditional way of dealing with JNI jars?

20:42 technomancy: weeping and gnashing of teeth

20:42 kenneth: seriously though; generally people include statically-compiled binaries inside jars

20:43 docs are a bit slim on this; best to follow the example of some of the existing native libs

20:43 kenneth: i'm compiling the JNI using an automated build script and placing the jar in /usr/share/java because the one published on clojars is broken

20:43 technomancy: what's the library?

20:43 bloudermilk: aperiodic: If I just want to call a function on all the elements in a set without caring about the return values, should I be using something other than map? Or is it a combination of do* and map

20:43 kenneth: jzmq

20:44 technomancy: there are working versions of jzmq; you don't need to roll your own

20:44 I'm not sure which they are though

20:44 aperiodic: bloudermilk: i'd use (doseq [elem set] ...)

20:45 bloudermilk: but yeah, if you want side effects, don't use map

20:45 kenneth: technomancy: i've spent literally days trying to get jzmq to work, and only got it to work by compiling it myself

20:46 bloudermilk: aperiodic: Thanks, will do. I imagine this is something I should use sparingly? I have three functions in this chain. Maybe just the outer-most function?

20:47 aperiodic: bloudermilk: sure, you can build stuff up lazily with map and then force side effects with dorun

20:48 duck1123: So just to clarify, If I connect to a browser repl, then I *should* be able to require my code and dependencies, correct? All I get is this. https://gist.github.com/3133277

20:48 bloudermilk: aperiodic: Appreciate the help. Thanks

20:52 hiredman: duck1123: depends on the optimization level

20:53 duck1123: I believe if you have adavanced opts on everything get's mangled and doing repl stuff will be very painful

20:55 duck1123: I don't have any optimization

20:56 whitespace and pretty-print

20:56 hiredman: you may need to refer cljs.core or something, if require is undefined

20:57 duck1123: It seems that I can refer to the functions directly (ie. jayq.core/\$)

20:57 hiredman: what happens if you use (cljs.core/require ...) instead of (require ...)

20:58 duck1123: same

21:14 gfredericks: I wouldn't think require would ever be defined in cljs

21:14 unless something has changed

21:15 duck1123: so you're saying that I can't require namespaces from the repl? Or I should be able to

21:15 I'm just trying to avoid needing to fully qualify everything

21:15 gfredericks: afaik you can only do it within a (ns ...)

21:16 duck1123: that makes cljs repl severely less useful

21:16 gfredericks: yeps

21:27 arrdem: is there a way I can have multiple (:use :as ) statements with the same :as?

21:29 emezeske: arrdem: You're, like, trying to combine multiple namespaces into a single alias?

21:31 arrdem: I don't think you can do that, because :as is probably implemented via refer, which doesn't create a new ns, just an alias

21:31 arrdem: emezeske: to be specific, I'm using congomongo :as db and it needs a global *mongo-config* which is __not__ in somnium.congomongo, it's in config. as a result I would like to :only import the var to db

21:31 so yes... I guess I want to merge namespaces.

21:32 emezeske: That seems like a bad idea to me; the nice thing about :use :as is that you can look at a form and trace it back to a single namespace

21:32 Whereas if you start combining namespaces, you don't know where a form came from

21:32 Anyway, I am pretty sure you can't do that with :use :as

21:34 arrdem: emezeske: 's ok. I'll just ditch the :as and bring it all into my local ns. %s/"bd/"/""/g and done.

21:34 *db/

21:34 amalloy: emezeske: that's true of :require/:as; :use/:as is generally a bad idea

21:35 Derp

22:08 clj_newb_2057290: what happened to rule based programming langauges?

22:08 why have none of them ever taken off?

22:14 nicholasf: how are people using leiningen for scripting tasks?

22:15 technomancy: nicholasf: what are you trying to do?

22:16 nicholasf: hi technomancy - I want to drop a database after a test run

22:16 technomancy: can you use test fixtures for that?

22:16 nicholasf: in this case, we have a convention that we need this scripted (for a continuous delivery system to call)

22:16 technomancy: meaning I think it should be done at runtime, not at build time

22:17 nicholasf: yeh, but regardless of the problem, how do I script a task with leiningen?

22:17 is there a way people generally do it?

22:17 technomancy: usually you use a plugin that already exists =)

22:17 * nicholasf nods

22:18 technomancy: but if you need to write your own, the plugin guide explains how: https://github.com/technomancy/leiningen/blob/master/doc/PLUGINS.md

22:18 nicholasf: thanks mate

22:18 technomancy: sure

22:50 amalloy: unlink: a week or so ago you mentioned having some troubles with slingshot - you might be interested in https://github.com/scgilardi/slingshot/issues/24, which explained to me why i was having trouble with it

23:27 gnarmis: is anyone aware of efforts to write a lang level for clojure in racket, so we can use the awesome dr racket?

23:29 yonatane: Can I add to an existing multimethod from somewhere else?

23:29 like from another namespace, to some multimethod that a third-party defined?

23:31 gfredericks: yes

23:31 you can

23:31 that's most of the motivation for multimethods I think

23:32 yonatane: gfredericks: so i can just hook my code to a third-party without dependency injection like that?

23:33 gfredericks: ...sure?

23:33 yonatane: if the caller used to invoke the default, it will now invoke my code if i configured it correctly?

23:34 gfredericks: sounds right

23:34 you should be able to experiment with that in the repl

23:35 put a (defmulti) in one namespace and a (defmethod) in another

23:35 I'm doing this right now because I've never tried it

23:36 and it worked perfectly

Logging service provided by n01se.net