#clojure log - Oct 26 2012

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

0:00 egghead: ;)

0:00 Sgeo: Heard of it, didn't pay much attention

0:00 ynniv: Sgeo: that's what we all want...

0:01 egghead: Sgeo: they have optional types and mirror-based reflection like strongtalk, but it's a browser thing...

0:01 * Sgeo doesn't exactly understand mirrors

0:01 Sgeo: I've heaerd of them in the context of Newspeak

0:06 bfabry: *sigh* nope, lein trampoline repl still gives me a repl that doesn't reload when I tell itto

0:21 amalloy: i think ynniv missed my point, which was that *especially* if your codebase is mostly correct, any rate of false positives will lead you to get more false positives than true positives

0:55 uroborus_labs: Does anyone know of a good example of using a jquery plugin with clojurescript?

0:56 I seem to be having trouble mostly with the externs I think...

1:44 tomoj: standard java.util.concurrent.Future behavior seems to be that .cancel permamently breaks the Future

1:45 shouldn't we get something better for clojure?

1:54 antares_: tomoj: what should .cancel do in your opinion?

1:58 uroborus_labs: Is there a dedicated clojurescript channel?

1:59 ivan: uroborus_labs: yes but nobody uses it

1:59 uroborus_labs: Yeah noticed that...

1:59 I have having a lot of trouble getting externs to work with it

1:59 ivan: nobody uses the channel, that is

2:01 uroborus_labs: did you add some :externs to your project.clj for lein-cljsbuild?

2:02 uroborus_labs: Yup

2:02 ivan: have you written working externs before?

2:02 uroborus_labs: I placed the file in resources/externs/myexternfile.js

2:02 Nope

2:02 Does cljsbuild auto scan for changes in project.clj?

2:03 ivan: I have no idea, I'm only familiar with the vanilla Closure Library toolchain

2:03 uroborus_labs: ahh ok

2:04 * ivan notices ./doc/RELEASE-NOTES.md:1. Automatically add `closure-js/libs` to `:libs` and `closure-js/externs` to `:externs`. This means that libraries can put their libs and externs in `resources/closure-js/libs/<library-name>` and `resources/closure-js/externs/<library-name>`, respectively, and lein-cljsbuild will automatically pick them up.

2:04 dnolen: uroborus_labs: have you seen http://lukevanderhart.com/2011/09/30/using-javascript-and-clojurescript.html?

2:04 uroborus_labs: also you should look at how jayq does it.

2:05 uroborus_labs: Yeah I read that and scaned the jayq source code

2:05 Multiple times

2:05 lol

2:05 ivan: how do you know your extern isn't working? are you seeing renamed properties in the compiled code?

2:06 uroborus_labs: Yes

2:06 dnolen: uroborus_labs: there's also a thread about that on the Clojure ML right now

2:10 uroborus_labs: ivan: Thanks for the release-notes link. Doing some digging now about the auto extern loading

2:25 Momol: hi there

2:26 is anyone progamming in clojure uses a BSD system ?

2:58 uroborus_labs: Good lord, 3 hours of BS bug finding on why I was not doing externs correctly when the issue was somewhere in setting cljsbuild compilation from :advanced to :simple

3:00 I should say setting :optimizations

3:00 tomoj: you abandoned advanced?

3:00 uroborus_labs: Found this out through testing https://github.com/clojure/clojurescript/tree/master/samples/hello-js

3:00 The examples in the readme failed to work unless advanced was set

3:00 tomoj: Any idea why that would be?

3:00 Or anyone else for that matter?

3:01 I should say, the example while following the readme failed when :optimizations was set to :advanced

3:02 Setting it to :simple both allowed the example to work and fixed the issue I have been stuck on for many many hours.

3:02 Is this a bug?

3:08 amalloy: Momol: everyone on osx, right?

3:09 Momol: amalloy: was thinking about openbsd and freebsd

3:09 amalloy: ~anyone

3:09 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

3:13 Momol: I wanted to know if BSD are a good system for clojure developpment. Java is not popular on these systems so

3:13 for linux, you have libraries and all tools to develop quickly in clojure, but I have some doubt on *BSD. Maybe it is complex

3:14 tkoskine: OpenBSD ports/packages (on -current) have clojure and leiningen.

3:16 amalloy: the only thing you need is the jre, and a bash interpreter for leiningen

3:17 famous last words maybe, but as far as i know that's all you need

3:23 Momol: amalloy: and jre isn't a prob on *BSD ?

3:26 tkoskine: Well, you could go and test it :). If there is a bug the jre maintainers on *BSDs would probably like to know about it.

3:26 tomoj: was the question about advanced and externs answered?

3:34 Sgeo: Hmm.

3:35 Can someone help me please?

3:35 shachaf: Sorry, Sgeo.

3:35 Sgeo: I need to know what the likely response would be if I asked, can someone help me please?

3:36 tomoj: anyone?

3:36 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

3:36 Sgeo: ....I fail at humor

3:36 tomoj: no, I do

3:36 shachaf: Nope, it's definitely Sgeo.

3:36 tomoj: :)

3:36 Sgeo: I think shachaf is likely to poke fun at me in any event.

3:38 Which is good, because I like collecting fun, and every planck time of every planck length is an event.

4:02 tomoj: hmmm https://gist.github.com/32b0838b3d1f6322a10b

4:04 &(next (reductions conj [] [1 2 3]))

4:05 lazybot: ⇒ ([1] [1 2] [1 2 3])

4:05 tomoj: better way?

4:06 bosie: https://gist.github.com/3957533 why is my output empty?

4:07 tomoj: for?

4:07 clojurebot: for is not a loop

4:07 tomoj: lazy?

4:07 clojurebot: lazy is hiredman

4:07 tomoj: :(

4:07 well

4:08 bosie: tomoj: not sure i understand you ;)

4:08 tomoj: because for is lazy, i wrapped it in take

4:08 tomoj: take is lazy too

4:08 bosie: dang

4:08 tomoj: (doseq [x [0 1 2 3] y [3 2 1 0] :while (< 0 x)] (println x y))

4:09 bosie: tomoj: right but then i have to change my for loop

4:09 tomoj: wouldn't doall do what i want?

4:09 * josteink finds himself wanting to type "ls" when in a new namespace in the clojure repl

4:10 Sgeo: tomoj, doc is a macro

4:11 bosie, doall works if you want the results from the for

4:11 So yes

4:11 bosie: Sgeo: cheers

4:12 tomoj: Sgeo: that's not the problem

4:13 bosie: I doubt you want all the nil return values of println

4:13 you can use dorun

4:13 amalloy: he probably doesn't want the printing effect of println either. just use for and return a bunch of vectors

4:13 bosie: tomoj: good point

4:14 Sgeo: bosie, is that your exact code, or is it a substitute for ... hmm

4:14 Ah. I wasn't sure

4:14 bosie: Sgeo: exact code. i was just playing with for in the repl

4:14 Sgeo: Ah

4:14 Hmm, usually attempting to show a lazy-seq at the REPL forces the lazy-seq to be fully realized

4:15 Although of course a take would allow for only the realization of ... you get the point

4:16 bosie: Sgeo: yes, i overlooked that take is lazy too

4:17 Sgeo: And the fun thing is, by using take at the REPL like that, you actually prevented the entire lazy sequence from the for from being realized

4:17 bosie: fun isn't the word i would have used ;)

4:19 thanks

4:21 josteink: is there any shell-like command like ls to list out the members of a namespace?

4:22 tomoj: shell-like? you mean you want to use it from a shell?

4:22 &(keys (ns-publics (find-ns 'clojure.repl)))

4:22 lazybot: java.lang.SecurityException: You tripped the alarm! ns-publics is bad!

4:23 josteink: tomoj: a repl often gives me the same feeling as a shell :)

4:23 lets see

4:25 cool

4:26 is there some function to call to get the name/symbol of the current repl namespace?

4:26 Sgeo: ,*ns*

4:26 clojurebot: #<Namespace sandbox>

4:27 * Sgeo isn't sure how to get a symbol from that

4:27 josteink: oh

4:27 I see

4:27 thanks

4:27 Sgeo: ,(ns-name *ns*)

4:27 clojurebot: sandbox

4:28 Sgeo: ,(special-symbol? '*ns*)

4:28 clojurebot: false

4:30 tomoj: &(.name *ns*)

4:30 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Namespace is bad!

4:30 tomoj: :(

4:30 I think namespaces should be Named

4:30 oh

4:30 ns-name

4:31 Sgeo: It just calls .getName

4:31 ,(.getName *ns*)

4:31 clojurebot: sandbox

4:31 josteink: now if I could find a way to quote that, I would actually have an automated ls command

4:31 Sgeo: ,(ns-name 'sandbox)

4:31 clojurebot: sandbox

4:32 Sgeo: quote?

4:32 clojurebot: quote is is unsyntax quote and '

4:32 tomoj: :(

4:32 Sgeo: josteink, what do you mena?

4:32 mean

4:32 josteink: (ns-name *ns*) => user

4:32 I want 'suer

4:32 er

4:32 'user

4:33 Sgeo: Without ' is how symbols typically print

4:33 Hmm

4:33 josteink: so that I can pass it to (keys (ns-publics (find-ns NS)))

4:33 lets test

4:33 Sgeo: ,(pr-str 'foo)

4:33 clojurebot: "foo"

4:33 Sgeo: ,*print-readably*

4:33 clojurebot: true

4:33 josteink: my bad

4:33 amalloy: josteink: i don't think you understand quoting yet. the value is the symbol user (which doesn't have any special decoration on it); you put the ' in to ask the compiler not to try to evaluate it

4:33 Sgeo: Somehow I don't think printing the symbol foo as foo is "readable"

4:33 josteink: (keys (ns-publics (find-ns (ns-name *ns*)))) actually print out things correctly

4:34 Sgeo: heh

4:34 amalloy: Sgeo: of course it is (let [f 'foo] (= f (read-string (pr-str f))))

4:34 Sgeo: ,(read-string "foo")

4:34 clojurebot: foo

4:35 Sgeo: huh.

4:35 I have a feeling I'm derping a bit

4:35 josteink, I have to know why you're doing ns-name then find-ns

4:35 ,(doc find-ns)

4:35 clojurebot: "([sym]); Returns the namespace named by the symbol or nil if it doesn't exist."

4:36 Sgeo: They're approximately inverses

4:36 josteink: Sgeo: oh I see

4:37 agreed. this is much simpler

4:37 (defn ls [] (keys (ns-publics *ns*)))

4:37 * Sgeo wonders though if ns-publics might not reveal all you want to know

4:40 Mr_Bond: hey josteink, where are you from?

4:40 Scandinavia?

4:40 josteink: norway

4:40 Mr_Bond: Same, kewl ;)

4:41 josteink: basically just thought it would be useful to have a "ls command" to investigate the namespaces Im in when running tutorials from git-repos

4:41 :)

4:42 you know, when the tutorial starts with "git clone", "lein repl" and "(load"

4:54 Mr_Bond: josteink: good idea! :) Clojure is fun, just started learning it my self.

4:55 Only thing that I find difficult, is pinpointing issues turning up in java backtrace

4:55 josteink: heh

4:55 tomoj: a hopefully soon-to-be-released library may help with that

4:58 Mr_Bond: tomoj: yeah, that would be very nice. Is there one on the roadmap?

4:58 I would still use clojure without one.

5:00 amalloy: tomoj's boundless optimism is an inspiration to us all

5:00 tomoj: http://www.infoq.com/presentations/Clojure-Stack-Trace

5:04 josteink: anyone know who runs infoq or what their primary target/aim is?

5:05 ive seen it mentioned quite a few times for programming related content and functional programming in paritcular

5:09 Raynes: josteink: http://www.infoq.com/about

5:10 josteink: well that was easy :)

5:10 * josteink wonders if they can be added to his google currents

5:11 Raynes: I liked Google currents when my phone had the space to use it.

5:11 That thing sucks up disk like a vacuum cleaner.

5:11 josteink: heh

5:12 I have 6GBs space or so on my galaxy nexus

5:12 that should be gooxd enough :)

5:12 Raynes: I have about 10MB of space on my Evo.

5:12 josteink: evo....

5:12 is that the carrier-mungled version of the galaxy s1?

5:13 * josteink can never make sense of the non-international version naming

5:13 Raynes: No idea.

5:13 This is the old evo, anywyas.

5:13 anyways*

5:13 josteink: ah. htc desire

5:13 Raynes: Not actually mine anymore. Giving it to my mother since I got an iPhone 5 today.

5:13 josteink: known for its infinitely insufficent storagecapacity

5:13 Raynes: No kidding.

5:16 kral: namaste

6:18 leoncamel: hey. As a newbie, I can def a variable, like this (def a 1). But, how can I *undefine* a ?

6:18 (def ^:dynamic a 1)

6:19 sorry, wrong window. :)

6:19 tomoj: (ns-unmap *ns* 'a)

6:19 leoncamel: tomoj: OK. cool. thansk.

6:19 shachaf: You can do that (it seems), but are you sure you want to?

6:20 tomoj: I understood "undefine" to mean "completely undo the effect of the def on the namespace"

6:20 but I wonder about "make it appear as if the root is unbound"

6:21 leoncamel: What is the side-effect about (ns-unmap *ns* 'a) ?

6:22 tomoj: if you do that, evaluating 'a would cause "Unable to resolve symbol: a in this context"

6:22 as if you had never evaluated '(def a 1)

6:23 leoncamel: I am newbie, just playing in my REPL. When I type "(def a 1)", a quick question just come to my mind: How can I undefine(or remove) symbol a from current environment.

6:24 tomoj: yes, that sounds like ns-unmap

6:24 (doc ns-unmap)

6:24 clojurebot: "([ns sym]); Removes the mappings for the symbol from the namespace."

6:24 leoncamel: tomoj: OK. I got it.

6:25 tomoj: wow, datomic will not let you stick a long in a double field

6:31 bosie: tomoj: since you mentioned datomic, how is the "db is effectively local"?

6:31 tomoj: I like it so far

6:32 bosie: tomoj: in sql terms, it would query the entire dataset and process it locally? (e.g. apply a filter on it)

6:32 tomoj: not necessarily the entire index

6:32 er, dataset

6:32 bosie: no but the entire 'table'

6:32 tomoj: well there are no tables

6:32 but there are indices

6:32 bosie: right

6:33 tomoj: depending on how you write a query, it may not need to fetch much more than needed

6:33 bosie: tomoj: without processing on the server?

6:34 tomoj: if by "server" you mean the transactor, it only does writes

6:34 bosie: ok

6:36 tomoj: with the free version a peer has to talk to some processes the transactor starts to fetch data

6:36 bosie: wow

6:36 just saw the pricing for datomic pro

6:36 AtKaaZ: tomoj: what?

6:36 tomoj: what what

6:37 AtKaaZ: tomoj: on the free version the transactor fetches the data? ie. reads

6:37 tomoj: well, I don't understand the internals very well. the free transactor starts processes that listen on 3 ports. the peers have to talk to one or more of those to fetch data from the transactor-local storage

6:38 I suspect one of them is an h2 sql db which the peer talks to, but I'm not sure

6:38 AtKaaZ: I don't know that many details, but I guess that could still mean that the transactor isn't used to read data ie. queries

6:39 tomoj: right, that seems likely

6:39 bosie: AtKaaZ: so if the transactor isn't reading the data, who is?

6:39 AtKaaZ: as I understand it the peers "talk" directly to the storage (so to speak)

6:40 tomoj: peers run queries, the transactor handles writes (and sometimes may run queries to service transactions..)

6:40 in pro the transactor and peer machines don't have to communicate directly at all, they just both talk to postgres or dynamodb

6:40 AtKaaZ: tomoj: like the nested queries? those with d/entity

6:41 tomoj: I mean, when does transactor run queries?

6:41 tomoj: when a transaction function called in a transaction runs a query

6:41 bosie: AtKaaZ: http://www.datomic.com/uploads/3/5/9/7/3597326/6646785_orig.jpg

6:42 AtKaaZ: that makes sense

6:42 tomoj: like :db.fn/retractEntity probably runs a query to figure out what to retract?

6:43 s/directly at all/directly at all (for queries)/

6:45 AtKaaZ: bosie: that Cache you see in peer app server, is reads/queries done by peer (directly getting them from storage/memcached) as I understand it

6:46 bosie: AtKaaZ: hm, then the arrows are wrong i guess

6:47 AtKaaZ: bosie: the two arrows point to cache as in: reads from storage/memcached into cache

6:47 bosie: AtKaaZ: sorry, i misread you

6:48 AtKaaZ: query gets its data from liveindex+cache, where liveindex would be updated when trasactor did a write

6:50 tomoj: I wonder if a :db.fn with like Thread.sleep can hold the transactor

6:51 tomoj: I'd think so

6:51 no reason to sleep I can think of

6:51 nothing's going to be different when you wake up

6:52 AtKaaZ: but I'm just thinking if some evil function would take too long to compute

6:52 tomoj: yeah, dunno

7:07 bairui: tomoj: s/foo/foo bar/ == s/foo/& bar/

7:08 tomoj: orly

7:08 bairui: in vim, anyway :)

7:08 tomoj: neat

7:09 sed too

7:09 bairui: yep; sed: vim, I am your father.

7:11 well... grandfather? ancestor?

7:11 AtKaaZ: no no, leave it at that, it was funny;)

7:12 bairui: :) fair

7:26 Girvo: hey everyone

7:27 q: is TDD viable in Lisp/Clojure? I'm working in a dialect called Pharen, quite inspired by clojure (compiles to PHP) and am used to TDD using classes. how does it work with just functions?

7:31 any good resources for TDD in clojure?

7:35 Cheiron: Grivo: check speclj

7:38 Girvo: cheers @Cheiron

7:39 Cheiron: Grivo: and of course clojure.test , midje

7:41 JulioBarros: Hi. I'm coming back to a web app I have not touched in a long time. Had to resolve a couple of dependency issues but now am getting "Could not locate ring/util/serve__init.class"

7:41 Any ideas on what could be causing it?

8:01 josteink: what's the difference between (ns somenamespace) and (in-ns 'somenamespace) ?

8:02 tomoj: (ns foo.bar) can do more, like (ns foo.bar (:require foo.baz)), and it also refers to clojure.core automatically

8:04 shachaf: Lenses are "pretty nifty".

8:04 Do they have those in Clojure?

8:04 josteink: tomoj: ah ok. thanks

8:05 tomoj: I don't know

8:05 are lenses anything like conal's semantic editor combinators?

8:05 cgrand referenced lenses in a talk

8:05 josteink: google says "Lenses are the coalgebras for the costate comonad "

8:05 tomoj: but I only read the slides

8:06 josteink: lenses are coco

8:06 tomoj: and I think the conclusion was "that's too complicated for this task"

8:06 http://vimeo.com/45695419

8:08 shachaf: tomoj: Yep, they're related.

8:08 A simple version of a lens is a (getter,setter) pair.

8:08 tomoj: I still don't understand semantic editors, but I feel vaguely like I want them in clojure

8:09 shachaf: They can be composed, which is the nice part.

8:09 The new "lens" library for Haskell way generalizes them, of course.

8:27 * josteink is having a nice clojured day

8:30 antoineB: hello, i would like get the "first" element of a concurrent list, and update the list to "rest"

8:30 should i use a ref or atom?

8:32 (first @my-list) (swap! my-list rest) is unsafe between the two sexp

8:32 josteink: so ... you are creating a queue? :)

8:33 antoineB: yes

8:33 FIFO

8:34 _ulises: antoineB: why do you say those two sexps are unsafe?

8:35 antoineB: the thread can stop at end of first sexp, and another can start at fist sexp

8:36 the two thread will peek the same "first" element

8:36 _ulises: antoineB: I didn't know you were talking threads :)

8:36 sorry for the silly question

8:40 josteink: _ulises: when you are talking "concurrent" you are talking about threads ;)

8:40 _ulises: josteink: I'll blame it on the lack of caffeine

8:40 josteink: heh

8:40 personally I usually blame that I mostly ready the bottom 5 lines, not a 2 page backlog :P

8:41 _ulises: what backlog?

8:42 josteink: http://invalid.ed.ntnu.no/~jostein/uploads/irc_backlog.png

8:42 whatever has passed out of the screen

8:42 :)

8:43 _ulises: 1) I can see myself 2) I meant "what backlog" in a "I don't read the backlog at all" kind of way

8:44 ;)

8:44 josteink: ah

8:44 heh

8:44 antoineB: josteink: you can ignore connection/deconnection of user in irssi

8:45 to get it more clear

8:45 josteink: antoineB: considering it. Im no longer a channel-op in busy, troll-ridden channels

8:46 so to quickly be able to spot a bad host is no longer that important ;)

8:50 /ignore -channels #clojure,#scheme,#linux * JOINS PARTS QUITS NICKS"

8:51 there we go :)

8:51 AntelopeSalad: i have a question, sort of... i've been reading through the clojure programming book and recently watched a video tutorial from one of the authors

8:51 antoineB: nobody answer my question

8:51 AntelopeSalad: he built a url shortener using compojure and ring

8:51 my question is, everyone claims clojure is great because everything is immutable

8:51 but right off the bat he setup mutable variables

8:51 Mr_Bond: wow, your in both clojure and scheme. Isn't that a bit mongamist? :P

8:51 josteink: antoineB: Im not competent enough to answer it. I would have cheated and just faceded a java concurrentqueue :)

8:52 Mr_Bond: monogamist..

8:52 AntelopeSalad: what's the point in boasting about immutable data structures if you're just doing to use the function that makes things mutable?

8:52 *doing = going

8:52 _ulises: antoineB: what operations are you trying to implement on the queue? peek or pop?

8:52 josteink: AntelopeSalad: well.. you probably need a sequence-number generatator

8:52 antoineB: pop

8:52 josteink: AntelopeSalad: that function will probably need some mutable data

8:53 antoineB: but a concurrent pop

8:53 AntelopeSalad: josteink: he uses an atom on some counter and also made a mutable map

8:53 _ulises: antoineB: so pop returns (first...) and updates to (rest...) right?

8:53 ambrosebs: Can someone please point me to a library that can call private Java methods/access Java fields?

8:53 josteink: AntelopeSalad: ah well. havent seen the video. cant tell if the guy does stupid things or not :)

8:53 antoineB: yes

8:53 cemerick: AntelopeSalad: Using an atom (or other reference type) does not make the data structures it holds mutable; rather, it provides a stable identity that does change over time.

8:53 ambrosebs: Is it in contrib?

8:53 antoineB: and i can't do the two in swap! or reset

8:53 AntelopeSalad: josteink: he's the co-author of the clojure programming book, he can't be that stupid

8:54 josteink: heh

8:54 _ulises: antoineB: why not? (please excuse me if it's a silly question)

8:54 cemerick: AntelopeSalad: We discuss this in chapter 4

8:54 AntelopeSalad: i didn't get to chapter 4 yet in the book, i did a lot of reading in the past 2 days and then wanted to watch a video tutorial

8:55 _ulises: antoineB: I think I get why you can't

8:55 get it*

8:55 AntelopeSalad: cemerick: you were the video author right?

8:55 _ulises: not my day today obviously

8:55 AntelopeSalad: i vaguely remember the name in the slide

8:55 cemerick: AntelopeSalad: FWIW, yeah

8:56 AntelopeSalad: your book is really good btw

8:56 i was just curious if a lot of web oriented clojure apps end up having a ton of mutable data (or things that act like they are mutable)

8:56 is there no real downside to using atom? it seemed handy in that counter use case

8:57 cemerick: AntelopeSalad: Having a single identity is hardly a "ton", compared to typical imperative programming environments.

8:57 In the URL shortener example, it's just a convenient stand-in for an external database.

8:57 antoineB: _ulises: swap! and reset update the atom with the return of the function

8:58 _ulises: antoineB: yeah, I realised that after I asked you the question :(

8:58 AntelopeSalad: ah, i see. so normally you would be getting a count of entries from a db

8:59 tomoj: is it possible that .take on a LinkedBlockingQueue never returns, while the queue fills up with items?

8:59 AntelopeSalad: cemerick: btw, do you have any other video tutorials floating around? i didn't see anymore in your channel

9:00 tomoj: hmm

9:00 I switched to openjdk and the problem seemed to go away

9:00 not sure if that was voodoo

9:01 cemerick: AntelopeSalad: I've done a couple, but they're not on youtube.

9:01 Nothing as comprehensive, though.

9:02 AntelopeSalad: ok

9:05 cemerick: can you post the links to them? even if they touch on some subjects in the book it wouldn't hurt to watch them

9:07 Kototama: Hi, I know about checkouts but is there a way with leiningen to run lein clean / lein deps / lein install for 4 differents projects at once?

9:08 TimMc: Kototama: With shell scripting, yes.

9:08 cemerick: AntelopeSalad: old, old, old: http://cemerick.com/2010/11/02/continuous-deployment-of-clojure-web-applications/ http://cemerick.com/2010/03/25/why-using-maven-for-clojure-builds-is-a-no-brainer/

9:08 The maven one in particular is quite irrelevant at this point.

9:09 AntelopeSalad: ah, yeah you explained that lein is its successor

9:09 TimMc: Kototama: for p in repos/foo repos/bar repos/etc ; do (cd -- "$p"; lein clean deps install); done

9:09 antoineB: _ulises: i used ref

9:10 _ulises: antoineB: I was going to say that that's what you probably want if you want blocking reads, etc.

9:10 TimMc: And once I get to work, I'll be able to paste a little modification that makes that for loop stop if any of those repos fails to build.

9:10 _ulises: antoineB: care to share the code? :)

9:11 antoineB: is not realy usefull because is not a generic queue

9:11 https://gist.github.com/3958679

9:11 Kototama: TimMc: I need something platform independent

9:11 I'm trying to get rid of our shell scripts

9:14 TimMc: Write it in Python then.

9:15 Python is great for cross-platform automation.

9:15 Kototama: i don't want windows developpers to have to install python to develop on a clojure project

9:15 TimMc: Do they have Cygwin?

9:15 Kototama: nope

9:15 antoineB: jscript ?

9:16 Kototama: yeah jscript lol but then I need to main two different set of build script

9:16 maintain

9:16 TimMc: What's wrong with installing Python?

9:16 antoineB: never touch jscript

9:16 TimMc: "installing" maybe

9:17 TimMc: Maven

9:17 * TimMc runs away

9:17 antoineB: Kototama: build a new clojure dsl, one for jscript and one for bash ? :)

9:17 Kototama: "please install java, leiningen, git" and also python but just two runs two shell commands thanks

9:18 i think i'll create a lein plugin that go up one directory and launch the same commadn in the other if it's possible :p

9:18 TimMc: Kototama: I think there's a lein plugin to develop multiple projects in the same tree.

9:19 Kototama: but which one? I found https://github.com/maravillas/lein-multi but it's not what i'm looking for, nor checkouts directory solve the problem

9:19 TimMc: lein itself uses something...

9:19 Kototama: i'm not even sure they work on windows, can you create a symlink on windows?

9:19 TimMc: Not really.

9:20 NTFS has some weird shit that I don't know about, though...

9:20 Maybe just have a "parent" (outer) project with a lein hook that distributes the commands in order to the various "subprojects"...

9:22 Kototama: If you can write the same thing in Windows batch scripting, just have two scripts.

9:22 That's not an uncommon or unreasonable thing to do.

9:22 Kototama: how do hooks work?

9:23 TimMc: I don't recall, but I've used one... let me check.

9:23 josteink: Kototama: you can create symlinks on windows with NTFS. Its just that the OS provides no tools for it ;)

9:23 Kototama: or I use the lein exec plugin and write a clojure script that do the 4 lein commands :D

9:24 josteink: the filesystem itself supports it fully

9:24 well screw me sideways

9:24 http://pastebin.com/N0XDinvC

9:24 there you go :)

9:25 Kototama: ahhhhh maybe https://github.com/kumarshantanu/lein-sub

9:25 TimMc: josteink: Cool!

9:25 Kototama: josteink: not so bad :-)

9:25 it does not solve the install problem though

9:26 TimMc: It doesn't?

9:26 Kototama: no checkouts is more to augment the classpath than anything else

9:26 TimMc: Oh, you mean checkouts, not lein-sub.

9:26 Kototama: yep

9:27 i'm trying lein sub write know... we will see...

9:31 lol the cljsbuild hook get applied to all projects ;-(

9:34 but otherwise it seems to work, this is really great

9:37 clgv: tools.logging: does not really give me correct line numbers within a namespace although I use the convenience macros. whats wrong there?

9:39 Kototama: with profiles I can discriminate with project needs to be build a war or not, everything fine.

10:40 tomoj: crazy to find me asking a question hours ago on the second page of related google results

10:41 clgv: tomoj: it's a pretty unique question then?

10:42 tomoj: not really

10:42 "LinkedBlockingQueue clojure seq" oslt

10:42 clgv: what do you want to know?

10:43 happens that I currently have the LinkedBlockingQueue javadoc open ;)

10:44 tomoj: I just want a seq from it

10:45 clgv: with or without blocking?

10:45 tomoj: blocking, of course

10:45 clgv: just do (repeatedly #(.take lbq))

10:46 ejackson: tomoj: I've used cgrand's code for this to great effect: http://clj-me.cgrand.net/2010/04/02/pipe-dreams-are-not-necessarily-made-of-promises/

10:46 tomoj: yeah I saw that, and based this on it

10:46 clgv: ejackson: tomoj: he added a close-fn that put's an EOF in it.

10:46 tomoj: https://gist.github.com/d5207c5a5074af29b4ac

10:47 rich is producing, not me, so don't need that

10:47 ejackson: rightio

10:48 clgv: tomoj: ok then you could just use (repeatedly #(.take lbq))

10:48 tomoj: that gist is only more verbose

10:48 tomoj: ah!

10:48 I felt there must have been a better way

11:25 ToBeReplaced: first time using lein midje; when i do lein midje, i show my failures, then Subprocess failed before I get to any lein test summary.... lein test has no issues... anyone have any guesses where to look? Leiningen 2.0.0-preview10 on Java 1.7.0_09-icedtea OpenJDK 64-Bit Server VM

11:25 leoncamel: what is proper way to execute a external command? I can not find clojure.contrib.duck-streams now.

11:27 clgv: ~contrib

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

11:28 clgv: "clojure.java.shell" or "conch" will help you

11:29 leoncamel: clgv: OK. thanks.

11:30 AtKaaZ: anyone using emacs 24.2 can paste their init.el ?

11:31 * dakrone considers pasting his 700-line init.el...

11:31 antares_: I have an entire repo for emacs.d :)

11:31 AtKaaZ: lol that's a lot of lines

11:32 cool I'll check that

11:32 antares_: AtKaaZ: http://github.com/michaelklishin/emacsd, although it is by no means an example of an impressive Emacs setup

11:32 leoncamel: AtKaaZ: what are you looking for? configurations for nREPL+emacs?

11:33 AtKaaZ: leoncamel: yes exactly (on windows)

11:35 hyPiRion: AtKaaZ: https://github.com/bodil/emacs.d is a good one to look at.

11:36 AtKaaZ: thanks I'll check, antares_'s seems to be using .emacs I was expecting init.el

11:36 hyPiRion: Though it's not for windows.

11:37 AtKaaZ: understood

11:39 Bodil: hyPiRion: Thanks, I guess. :)

11:39 leoncamel: AtKaaZ: My emacs.d become complex and complex, I don't know if it helps. But, I would like recommend this repo : https://github.com/purcell/emacs.d

11:40 * nDuff is a fan of Emacs Live

11:40 nDuff: AtKaaZ: See https://github.com/overtone/emacs-live -- there are videos showing the features and such.

11:41 S11001001: AtKaaZ: my emacs config is top secret, can't share without risking national security

11:41 AtKaaZ: :))

11:41 leoncamel: nDuff: yes. It so dam cool... :) I LOVE that.

11:45 AtKaaZ: awesome video, I wonder if the text really glows like that

11:46 adu: which video?

11:46 AtKaaZ: http://vimeo.com/22798433

11:47 adu: doubtful

11:47 AtKaaZ: yep I just saw the end:)

11:48 ambrosebs: Just released Typed Clojure 0.1, please try it out https://github.com/frenchy64/typed-clojure

11:48 adu: OMG

11:48 typed clojure!

11:48 nDuff: sweet!

11:48 adu: is it anything like typed racket?

11:48 * nDuff very much liked what he saw reading the paper yesterday

11:49 ambrosebs: it's wannabe typed racket, yes :)

11:49 nDuff: thanks!

11:49 nDuff: adu: If you're curious, you should read the paper ambrosebs published.

11:49 adu: ambrosebs: I think something just happened in my pants

11:49 which paper?

11:49 ambrosebs: should be in the readme

11:49 clgv: ambrosebs: does it work without a modified clojure?

11:50 adu: "A Practical Optional Type System for Clojure"?

11:50 ambrosebs: clgv: It only works on 1.5.0-beta1

11:50 clgv: probably

11:50 adu: yep

11:51 clgv: ambrosebs: why i "tc-ignore" not metadata?

11:51 adu: ambrosebs: did I show you my typed lisp thing?

11:51 http://andydude.github.com/droscheme/cmd/gos.html

11:52 it's just an S-expr representation of Go code

11:53 ambrosebs: clgv: the library "analyze" generates an AST from the Clojure compiler. Sometimes metadata doesn't make it through, so as a rule I don't do any metadata where you might expect.

11:54 clgv: It was the quickest thing that works.

11:55 clgv: ambrosebs: ah ok. then that might be a future feature ;)

11:56 ambrosebs: clgv: I don't see how (tc-ignore 1) would work with metadata though.

11:57 clgv: ambrosebs: would `1` be type checked?

11:57 ambrosebs: I mean, 1 isn't IMeta

11:57 clgv: I know. but would it make sense to wrap it in tc-ignore?

11:58 ambrosebs: clgv: probably not. Until we have a new compiler, I'm happy with tc-ignore.

11:59 which may be never :)

11:59 adu: new compiler?

11:59 clgv: ambrosebs: despite from tc-ignore you could have the "typed clojure" annotations in a different namespace, right?

11:59 ambrosebs: adu: ie. CLJS

12:00 adu: I thought CLJS was as good as CLJ

12:00 ambrosebs: clgv: sure

12:00 clgv: these are the sorts of issues I haven't fleshed out yet though.

12:00 clgv: ambrosebs: that was why tc-ignore disturbed me ;)

12:00 ambrosebs: clgv: yes, it's a horrible hack of course!

12:01 adu: CLJS compiler is much nicer to work with.

12:01 adu: hmm, maybe I should check it out, I've only used CLJ

12:02 ambrosebs: adu: check out the compiler namespace, it's just multimethods and maps.

12:02 quite remarkable.

12:04 I would be grateful if anyone's tried Typed Clojure 0.1 to let me know that it works.

12:05 I've been the only user for so long, it's a little nerve wrecking releasing it :)

12:05 I probably screwed up something.

12:11 adu: I'd like to try it

12:12 ambrosebs: adu: Glad to help if you run into any trouble.

12:17 adu: ambrosebs: "Could not find artifact typed:typed:jar:0.1 in central (http://repo1.maven.org/maven2)"

12:17 o wait n/m "Retrieving typed/typed/0.1/typed-0.1.jar (71k)from https://clojars.org/repo/&quot;

12:18 ambrosebs: I actually just pushed it 1m ago LOL

12:18 adu: sweet

12:18 ambrosebs: forgot to release the release

12:19 wunki: is there a thumbnail library in Clojure?

12:20 adu: ambrosebs: is there a "defn>"?

12:21 ambrosebs: adu: nope, I wouldn't encourage one either.

12:21 nDuff: wunki: If you don't find anything on Clojuresphere, the typical thing is to pick a Java library that looks sane.

12:21 technomancy: ambrosebs: would it be possible to specify annotations as metadata on vars?

12:21 ambrosebs: adu: just use (ann var type)

12:22 adu: ambrosebs: is this important: "CompilerException java.lang.RuntimeException: Unable to find static field: COLUMN_AFTER in class clojure.lang.Compiler, compiling:(analyze/core.clj:825)"?

12:22 ambrosebs: technomancy: no reason why not.

12:22 wunki: nDuff: doesn't seem to be. Adding java to the google query :)

12:22 ambrosebs: adu: ah.

12:22 technomancy: ambrosebs: seems like the natural place for it provided you're not annotating someone else's code

12:23 adu: ambrosebs: I got that after "(use 'typed.core)" in "lein repl"

12:23 ambrosebs: adu: *clojure-version* ?

12:23 nDuff: wunki: ...by the way, I _do_ recommend clojuresphere (http://www.clojuresphere.com/) as a good place to look for Clojure libraries.

12:23 adu: ambrosebs: 1.4.0

12:23 nDuff: wunki: ...notably, searching there, it _does_ find a thumbnail library.

12:24 ambrosebs: adu: ok, it only supports 1.5.0-beta1

12:24 adu: oic

12:24 let me change the project

12:24 ambrosebs: adu: can you run "lein deps :tree" and paste it somewhere?

12:24 or just let me know where 1.4.0 is coming from

12:24 TimMc: adu: http://refheap.com

12:25 ambrosebs: technomancy: is there a particular reason why you'd prefer metadata? I don't personally see the difference.

12:26 adu: https://www.refheap.com/paste/6161

12:26 technomancy: ambrosebs: just that clojure already has a mechanism for annotating vars; seems odd to make up your own when one already exists

12:26 gensymv: hello, clojure newbiew here: what is the use case for "lein repl" starting a server?

12:26 *newbie

12:26 jkkramer: wunki: I use Scalr in a clojure project. I have a ~100 line clj file to make working with loading/saving images a bit easier that I could open source

12:26 ambrosebs: technomancy: fair enough. Blindly copied Typed Racket there.

12:26 gensymv: *starting to listen

12:26 adu: gensymv: I just used lein repl to test stuff

12:26 ambrosebs: adu: what's your project.clj

12:27 * nDuff would have gone the metadata approach as well, frankly -- didn't bring up the failure to do so yesterday on account of assuming it was for cause.

12:27 wunki: nDuff: I didn't know clojuresphere was a site, I though it was a "saying". Thanks

12:27 gensymv: adu, my question has nothing to do with the code you posted^^

12:27 i am just curious.

12:27 technomancy: gensymv: leiningen used to have issues with stdin from within your project, so it had to set up a socket for repl communication

12:27 gensymv: turns out it's a useful property to have for remote debugging anyway

12:28 gensymv: so if i don't really know what i am doing (which is the case), i might as well continue using clojure with rlwrap.

12:28 technomancy,thanks.

12:28 technomancy: rlwrap is pretty crappy actually

12:28 adu: ambrosebs: ok, now that I have 1.5.0-beta1 in the project, leing repl/use now says "WARNING: defrecord already refers to: #'clojure.core/defrecord in namespace: user, being replaced by: #'typed.core/defrecord"

12:29 gensymv: technomancy, why do you say that?

12:29 technomancy: gensymv: history support isn't as good; no tab completion

12:29 ambrosebs: adu: just require it, don't use

12:29 (require 'typed.core)

12:29 wunki: jkkramer: you don't have to do it for me. I'm only using for a side project. If however you wanted to do it anyway. Let me know

12:30 jkkramer: pm me if so, gotta go eat

12:30 adu: I thought it didn't matter

12:30 jkkramer: wunki: it's short and relative self contained. i'll gist it...

12:30 gensymv: technomancy, as far as i see leiningen repl doesn't have tab completion either

12:30 ambrosebs: adu: could you possibly start a new file?

12:30 technomancy: gensymv: lein1 or lein2?

12:30 adu: ambrosebs: ok

12:30 jkkramer: wunki: https://gist.github.com/3959731

12:30 gensymv: technomancy, 1.7

12:31 technomancy: gensymv: yeah, that's just using rlwrap. lein2 has a much better repl.

12:31 ambrosebs: adu: (:require [typed.core :refer [check-ns ann]])

12:32 TimMc: technomancy: At least it's not jline.

12:33 adu: I tried "(require [typed.core :refer [check-ns ann]])" in the repl and got a ClassNotFoundException

12:33 technomancy: TimMc: jline1 is the crappy one; jline2 is sweet

12:33 TimMc: adu: Put a ' before [typed...

12:33 technomancy: Oh, interesting.

12:34 adu: YEY

12:34 that worke

12:34 TimMc: adu: require is a fn, not a macro, for better or worse -- so it needs to have the libspec quoted.

12:34 ambrosebs: adu: typed.core/cf checks a form, you might want that to experiment with

12:34 adu: try (cf 1)

12:35 adu: ambrosebs: I get "[(quote 1) {:then tt, :else ff} empty-object]"

12:35 ambrosebs: great

12:35 adu: I have no idea what that means

12:36 ambrosebs: adu: it's a bit complex. (quote 1) is the singleton type containing just one.

12:36 adu: the rest is extra stuff.

12:37 try (ann-form (fn [a] a) (All [x] [x -> x]))

12:37 and import ann-form

12:37 it should all be working.

12:38 technomancy: what kinds of better inference were you expecting from Typed Clojure?

12:38 adu: ambrosebs: "(typed.core/cf (Math/sqrt 4))" gives me "AssertionError Assert failed: (class? cls) typed.core/Class->symbol (core.clj:2275)"

12:38 ambrosebs: adu: that's not right :)

12:39 adu: do I win a beta testing chocolate cookie?

12:40 technomancy: ambrosebs: well, trivially in the collatz example, it should be possible to infer the return value, right?

12:40 ambrosebs: adu: the first bug report :)

12:41 technomancy: yes, IMO that's only handy for anonymous functions. I have a convoluted syntax that infers the return: (fn> [[a :- Number]] a)

12:41 TimMc: technomancy: COuld not reproduce, I was able to get a value other than 1.

12:42 technomancy: ambrosebs: sure; cool

12:43 TimMc: (Never mind, my joke fails because his Collatz function doesn't actually check for loops, per se.)

12:44 technomancy: is it a goal at all to support checking code that's unannotated based on guesses coming from inference?

12:45 ambrosebs: technomancy: that's for a separate tool.

12:45 technomancy: ok, I see

12:47 ambrosebs: technomancy: a tool between those is one that gives a pretty good guess of the types, and allows the user to double check them before being used like normal.

12:48 edward_123: anyone used compojure knows how to redirect to a custom 404 page when 404 happens? right now i only have route/not-found "page not found."

12:48 technomancy: ambrosebs: I expect there's also room for a tool that can avoid reflection that way too

12:49 ambrosebs: technomancy: yes, just need to figure out how to integrate it into the Compiler.

12:49 dnolen: ambrosebs: so you see typed clojure as kind of a final pass after an more robust inferencer pass?

12:51 ambrosebs: dnolen: I meant porting a large amount of untyped code could be pretty annoying, so a decent inferencer would help there. Typed Clojure is fundamentally bidirectional checking only.

12:52 adu: fixed it, any more ;)

12:54 adu: ambrosebs: nice

12:54 egghead: edward_123: just put the html instead of "page not found."

12:58 dnolen: ambrosebs: ejackson mentioned S Peyton-Jones was excited about Typed Clojure at FPDays ;)

12:58 ejackson: indeed !

12:59 I pointed him at your dissertation - hot off the presses.

12:59 edward_123: @egghead, oh it can also be dynamic content if I can corresponding function as long as the function returns string right?

12:59 egghead: ya edward_123

13:01 edward_123: Thanks!

13:08 dnolen: ejackson: so did you get any feedback from folks that were familiar w/ constraint solvers?

13:08 ambrosebs: dnolen: ejackson: no way!

13:09 ejackson: ambrosebs: yes way. He is working at the moment on optional static typing in Haskell too.

13:10 dnolen: word on the street is that all the cool kids are doing it

13:10 ejackson: The idea is that it turns all static errors into warnings at compile time, and throws at runtime instead

13:10 technomancy: sounds like a hard sell to haskellers

13:10 dnolen: technomancy: it's already in GHC

13:10 ejackson: stuff is available and more coming.

13:11 apparently their main use case is refactoring

13:11 technomancy: sure, haskellers just like to talk about how runtime errors are a thing of the past

13:12 ambrosebs: Well, we're about to find out if the monads in my dissertation are actually well typed then ;)

13:12 ejackson: dnolen: feedack - not really. Did have a prologer cut off one of my answers to say how much more expressive core.logic was than prolog in solving the soduku puzzle.

13:12 i certainly wasn't about to disagree.

13:13 dnolen: ejackson: heh

13:13 technomancy: just like the SMLers & OCamlers before them.

13:14 technomancy: dnolen: ocaml struck me as a much more chill community

13:14 "Oh, you absolutely need speed? It's cool if you write mutable code then. We won't judge you."

13:15 much less dogmatic

13:15 dnolen: technomancy: maturity of community perhaps?

13:15 technomancy: couldn't say for sure. maybe being slightly more industry-leaning than haskell.

13:16 Iceland_jack: Haskell is too divided between research and usability I feel

13:19 egghead: Iceland_jack: why do you say that? haskell is certainly useable, just not necessarily accessible :)

13:19 Iceland_jack: I probably wasn't specific enough

13:20 It is useable but sometimes you need stability of ideas as much as you need stability of libraries or code

13:22 With Haskell there are always new things--arrows, lenses--that mix with people trying to solve problems

13:22 I do love Haskell though

13:23 gtrak`: I find myself writing this a lot in async code, is there a better way? (let [call #(if % (%))] ... (call some-param))

13:24 djcoin: I'm far from being an expert, but my trouble with haskell is functional overengineering maybe and laziness. Ocaml is more pragmatic but for ~20 years it seems it did not evolved as much as it should have (and by the way, not used at much as it should I guess - when I see how Go is getting traction .. it seems to me as a weaker OCaml). Again, i'm far from an expert.

13:25 Iceland_jack: I think Haskell is definitely on the right track

13:25 technomancy: yeah, it's a shame Go has so much momentum while OCaml comparatively languishes

13:25 Iceland_jack: OCaml is an excellent language

13:25 djcoin: Yeah, it is a total incomprehension for me. You can take OCaml + Lwt, and you get basically Go

13:26 technomancy: it's the curly braces

13:26 * technomancy sighs deeply

13:26 djcoin: :(

13:26 gtrak: curly braces make it go fast

13:27 dnolen: technomancy: I don't think I'll ever use Go myself but I understand the appeal for the mainstream devs.

13:28 djcoin: dnolen: maybe their were told that it is web scale yet imperative :)

13:29 they *

13:29 technomancy: maybe it's like the groovy of systems-level code

13:29 the appeal comes from addressing the obvious pain points without requiring you to change the way you think

13:30 * nDuff has a sudden brain-ache at the mention of groovy

13:30 nDuff: ${DEITY} that thing is awful

13:30 technomancy: yeah that's probably not quite fair to go

13:30 nDuff: bloody near impossible to tell what a given piece of code does without ridiculous amounts of context

13:30 * nDuff thought Ruby was bad about that... then he met Groovy.

13:31 technomancy: it's not *bad* (apart from ignoring interactive development, which is unforgivable) it's just unambitious

13:34 ToBeReplaced: okay i can't get midje to work at all >> has anyone else had any issues? i'm reckoning that i just don't know what i'm doing with java

13:35 if i do lein new foo; cd foo; lein midje; i get ran 1 test, yadda yadda, then finally "Subprocess failed"

13:37 egghead: can anyone speak to clj-metrics vs something like reimann ?

13:45 ambrosebs: adu: Gos is pretty cool!

13:45 adu: any macros?

13:46 adu: or is that more droscheme's thing?

13:53 adu: ambrosebs: right

13:53 ambrosebs: droscheme is the macros, and gos is just a transpiler from S-expr => Go

13:54 ambrosebs: adu: and the types are just directly from Go?

13:54 adu: yes

13:54 ambrosebs: cool

13:54 adu: I've been meaning to do a release of droscheme

13:54 but I've been so busy with my new job

13:55 iirc, the andrew-working branch (https://github.com/andydude/droscheme/tree/andrew-working) is half-way between master branch and what I have now

13:57 ambrosebs: I should go to bed :) Hearing SPJ knows about Typed Clojure kept me up another hour :P

13:57 adu: nice

13:58 ambrosebs: thanks a bunch for being the first known user of Typed Clojure xD

13:58 seriously.

13:58 adu: np :)

13:58 ambrosebs: cya

13:58 adu: later

14:07 mac_: Hello folks! Anybody up for a short code review (80-odd lines)? I'm getting performance that's surprising me with its slowness, and I thought somebody might see where I've gone wrong.

14:07 emezeske: ~anyone

14:07 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

14:07 emezeske: mac_: Nothing wrong with pasting the code in question

14:08 mac_: But people might not want to commit to a code review before seeing it :)

14:08 mac_: oh, of course.

14:09 grzm: Just getting started with clojurescript and following along Mark McGranaghan's node.js clojurescript demo at http://mmcgrana.github.com/2011/09/clojurescript-nodejs.html and am getting the following error:

14:09 .ObjMap.fromObject(["Content-Type"], {"Content-Type":"text/plain"}).strobj());

14:09 ^

14:09 TypeError: Property 'strobj' of object {"Content-Type" "text/plain"} is not a function

14:09 mac_: It's a backtracking sudoku: https://gist.github.com/3960341

14:09 dnolen: grzm: it's probably unwise to follow that particular tutorial it's quite old.

14:09 grzm: This is when running the first http example.

14:09 dnolen: that's what I was gathering.

14:09 dnolen: grzm: it's relies on private implementation details

14:10 grzm: dnolen: and that too, from here : http://stackoverflow.com/questions/9193705/where-in-clojurescript-is-the-strobj-function-defined

14:10 dnolen: any pointers on more modern places to start? In particular, I'm interested in using cljs with node.js

14:12 emezeske: mac_: Probably not performance-related, but do you know about get-in and assoc-in?

14:12 * mac_ goes to look

14:12 grzm: dnolen: btw, I'm incredibly impressed with the level of activity you're able to maintain on the lists, Stackoverflow, and I see it extends to IRC as well :)

14:12 dnolen: grzm: wild west that. node.js support is still early days.

14:12 mac_: emezeske: I see I've reinvented the wheel.

14:12 dnolen: grzm: ohpauleez is forging some ground there.

14:12 mac_: Thought I might have.

14:13 emezeske: mac_: Only a little bit :)

14:13 grzm: dnolen: cheers. I'll take a look

14:13 mac_: That implementation is slower than a Python implementation that's using (broadly) the same algorithm; Python gets mutable arrays, of course, so there's likely a meaningful win there, but I'm still surprised.

14:14 (Python wins when I have it do many boards, in an attempt to amortize startup costs)

14:14 ohpauleez: grzm: Let me scroll back a second and catch up

14:15 grzm: I'm your man!

14:15 __zfn__: Hi all/

14:15 I use lein with clojure 1.2.1

14:15 grzm: ohpauleez: good to hear :)

14:16 __zfn__: How to update clojure version?

14:16 dnolen: mac_: you are constructing many transient values tho right? lots of conversions to set, and calls to set/difference. that's not the case in the Python code if I recall

14:16 technomancy: three remaining blockers on lein2 rc; woo

14:16 ohpauleez: I have a full app - disk-io, lots of Clojure/edn data, core.logic, interaction with unix utilities - all on node.js

14:16 mac_: dnolen: I'm constructing many transient sets in my python version, as well.

14:16 ohpauleez: as a scripting app

14:16 technomancy: anyone want to fix https://github.com/technomancy/leiningen/issues/805?

14:16 dnolen: mac_: by converting to python sets?

14:16 mac_: I'm assuming you're basing this on Norvig's version?

14:17 mac_: dnolen: No, from-scratch by me.

14:17 ohpauleez: technomancy: exciting!

14:17 grzm: Are you stuck with anything in particular or just looking for starting points?

14:17 grzm: ohpauleez: currently googling you and node.js to see what you've got out there, but currently only see links to irc logs. do you have any node.cljs articles/projects out there I might take a gander at?

14:17 mac_: dnolen: My python version does the same build-three-sets thing that my clj version does; mutability is likely adventageous there too, though.

14:18 dnolen: mac_: are you running the JVM w/ -server?

14:18 mac_: dnolen: dunno; lemme see.

14:18 grzm: ohpauleez: just getting started. Haven't done extensive js work, much less node.js, and thought using clojurescript would make it a little less painful

14:18 dnolen: mac_: if you're using lein you probably are

14:18 mac_: dnolen: using the clj wrapper script from homebrew.

14:18 ohpauleez: grzm: I was going to hold off pushing mine to Github, but let me add that remote and I'll link you

14:18 mac_: it's not passing -server.

14:18 Lemme try.

14:18 grzm: ohpauleez: so I was going to work through Mark's demo

14:19 ohpauleez: cheers

14:19 ohpauleez: grzm: That's a good place to start - the latest Google Closure Lib has promises in it (they're called Resultes)

14:19 You need to use them to escape callback hell and program with values

14:19 technomancy: never mind; I think that issue I linked to is already fixed

14:19 ohpauleez: I'm going to highlight that in my Conj talk this year

14:20 mac_: dnolen: can't tell if that made a difference.

14:20 My "benchmarking" (using the term loosely) isn't good enough to tel.

14:20 dnolen: mac_: you generally need multiple runs for the JVM to warm up, how long does it take to solve your board?

14:21 emezeske: mac_: This is probably micro-micro optimization, but it seems like representing the board using numbers instead of strings would be appropriate

14:21 dnolen: mac_: also if you're doing this at the terminal w/ clj then you're messing JVM+Clojure+compile your script startup time

14:21 you're measuring I mean

14:21 mac_: dnolen: yeah, I know I'm paying all the startup time every time.

14:22 But if I have it solve say 20 boards, python still wins.

14:22 grzm: ohpauleez: I take it https://github.com/ohpauleez/ttt is what I'm looking forward to?

14:22 ohpauleez: yes

14:22 :)

14:22 dnolen: mac_: how long does it take?

14:22 mac_: oh, hang on.

14:23 at ~20 boards, clj takes ~13 seconds wall time, and python takes ~20.

14:23 So it looks like I'm catching up after all.

14:23 (Although that second thread means my CPU time is higher)

14:23 Clearly, I need to examine this more closely.

14:23 (I take it from the other quietness that nobody has seen a drastic performance foulup in that implementation?)

14:24 dnolen: mac_: it's actually pretty nice looking code, minor things here and there.

14:24 mac_: dnolen: thanks!

14:24 It's my first real lisp program.

14:24 Done a fair amount of functional (OCaml, mostly), but never typed this many parentheses in a row before.

14:25 dnolen: mac_: i was going to say, it seemed like you done some FP before

14:25 amalloy: yeah, agreed it reads pretty well mac_. that last (if (empty? wins) nil (first wins)) could just be (first wins)

14:25 Kneferilis: how clojure compares to falcon?

14:25 mac_: amalloy: oh, excellent. What I did felt gross.

14:26 Got a meeting to run to. Thanks for the help!

14:26 amalloy: oh, and (apply str (interleave x y)) is (clojure.string/join x y)

14:28 hyPiRion: ,(clojure.string/join "," [1 2 3])

14:28 clojurebot: "1,2,3"

14:28 tomoj: it seems clj-http is incompatible with cheshire.custom? :(

14:28 hyPiRion: ,(apply str (interleave "," [1 2 3]))

14:28 clojurebot: ",1"

14:29 amalloy: oh, i see. i was thinking of interpose, because it's such a common pattern

14:29 thanks hyPiRion

14:30 hyPiRion: I tend to mix them up as well, I feel like I always have to check if I'm using the right one

14:31 Apage43: tomoj: you can always ask clj-http for a stream and pass it to decode-stream

14:31 tomoj: encoding is the problem

14:32 otherwise I could maybe implement a custom response coercion (except clutch won't use it)

14:40 amalloy: am i totally crazy for wanting to turn an if-let into let+if? i have something like (if-let [x (...)] (f x) (let [x' (...)] (g x))), where f and g are very similar-looking expressions. it seems like it might read better to do (if (x-exists?) (let [x (...)] (f x)) (let [x' (...)] (g x)))

14:43 dakrone: tomoj: check out https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L41-51

14:43 tomoj: you can rebind the fns for it if you want to use whatever you'd like

14:43 tomoj: ohh

14:43 I didn't notice they were dynamic

14:43 excellent, thanks

14:44 hiredman: amalloy: we need compiler magic to take let-if-try-let do the right thing

14:44 Apage43: oh neat, that means I could pull in clj-http without cheshire. Mind I don't think I've ever actually used one and not the other in any project yet..

14:44 hiredman: like other lisps have cdddddr

14:45 dakrone: Apage43: yes, it's all set up so you can exclude cheshire from the deps if you don't want to use it

14:45 spligak: could someone explain this idiom to me? I understand you can drop a hash-map into it, but I'm curious as to what's happening in the function arguments. is there some implicit conversion going on? https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L75

14:46 tomoj: destructuring?

14:46 clojurebot: destructuring is http://clojure.org/special_forms#let

14:46 amalloy: good idea. if the compiler sees you've mashed the names of six built-ins together into a single symbol, it should figure out what the heck you want that to do

14:46 hiredman: yes

14:46 dwim

14:46 dakrone: spligak: the response map is being destructured, the :status key is being pulled out and bound to 'status'

14:47 tomoj: (g x') I assume?

14:47 amalloy: i remember having a hell of a time figuring out destructuring from the examples in JoC. might have been the hardest part of the book for me to understand

14:47 tomoj: yep, good catch

14:47 ohpauleez: grzm: Take a look now: https://github.com/ohpauleez/ttt

14:47 shield your eyes from all the hacks

14:47 :)

14:48 tomoj: hmm

14:48 ohpauleez: it's very much a scratching pad for me

14:48 dakrone: http://clojure-doc.org/articles/language/functions.html#destructuring_of_function_arguments

14:49 spligak: tomoj, dakrone interesting. thanks for the direction here - had skimmed a bit on the topic. was jarring to see it in the wild for the first time.

14:49 (very new to clojure)

14:50 Gurragchaa: so Clojure runs anywhere that has a JVM installed, right? And if so, can it call all the functions from the Java API, OpenGL in particular?

14:50 spligak: dakrone, oh wow. those examples are excellent. thanks.

14:50 technomancy: Gurragchaa: not really, OpenGL is typically native code

14:50 egghead: hey sjl are you around?

14:51 dakrone: spligak: np, good luck!

14:51 sjl: egghead: yes

14:52 egghead: sjl: I was playing with your wrapper around codahale's metrics -- by default all my bean metrics are under default.default.metricname -- is there any way to change this?

14:52 emezeske: Gurragchaa: If OpenGL can be used by Java on a given platform, then yes, Clojure can use OpenGL via the Java APIs.

14:52 sjl: egghead: http://metrics-clojure.readthedocs.org/en/latest/names.html

14:53 Gurragchaa: so Clojure could theoretically be useful for cross-platform OpenGL game development?

14:53 egghead: d'oh, figures I would have missed it, thanks sjl

14:53 sjl: np

14:53 emezeske: Gurragchaa: Yes

14:53 Gurragchaa: https://github.com/ztellman/penumbra

14:54 Gurragchaa: Look in the test/ directory for examples of simple games

14:54 technomancy: Gurragchaa: yeah, but not everywhere Java runs

14:55 tomoj: dakrone: needs to be bound at middleware time, though?

14:55 technomancy: just on whatever subset of platforms have lwjgl support

14:55 tomoj: hmm, that shouldn't be the case, I must have screwed up

14:55 dakrone: tomoj: I didn't think it did, but I haven't actually tried it with a different library

14:55 * dakrone makes a note to add a test for that

14:57 tomoj: oh, looks like clutch calls cheshire.core/generate-string directly

14:58 dakrone: ahh, can't help there then

15:15 frawr: Hi, I have some weird behaviour with lein uberjar. When I run the project with lein run it works, but when i java -jar my standalone jar my main can't be found. Any clues?

15:16 technomancy: frawr: missing a gen-class

15:16 frawr: Only needed in the main's ns right?

15:17 dnolen: ohpauleez: so I see ttt is out there.

15:18 technomancy: frawr: specifically for uberjar, yes

15:18 antares_: frawr: for the standalone jar to work, yes, it is unlikely that you are implementing Java classes in Clojure if you are asking this

15:19 frawr: (ns ap.server.setup (:gen-class)) and in the project definition :main ap.server.setup/quick-start, and quick-start is a fn with only the rest argument in the labdalist

15:19 TimMc: frawr: You can also use my lein-otf plugin if you don't want to have your code AOT'd (so gen-class would be unnecessary of course).

15:20 Someone has made a fork of it for lein 2 as well.

15:20 technomancy: frawr: you can also do java -cp my-standalone.jar clojure.main -m my.ns

15:20 frawr: antares_: I don't think that's what I'm asking

15:20 technomancy: without any aot

15:20 antares_: technomancy: isn't :main supposed to take an ns name?

15:20 technomancy: antares_: it can take a var name too, but that's not very well-tested

15:20 could be a bug

15:21 antares_: technomancy: I am curious how that works for uberjars

15:21 if Main-Class in the jar manifest is a class

15:21 technomancy: oh yeah, not at all

15:21 it's only for lein run

15:21 frawr: that's your problem

15:21 should probably put a warning around that or something

15:22 not really any way we could support that

15:22 antares_: frawr: your main class ns should have a function named -main and in :main you should specify only namespace, not a var/function

15:22 amalloy: technomancy: whaaaat, of course you could. emit your own gen-classed -main that calls the named var

15:22 frawr: Aah ok

15:22 technomancy: amalloy: right, I mean not without violating the prime directive

15:22 amalloy: $google leiningen prime directive

15:22 lazybot: [compilation - FileNotFoundException when making a jar file from the ...] http://stackoverflow.com/questions/3246883/filenotfoundexception-when-making-a-jar-file-from-the-clojure-file

15:23 frawr: didn't know that

15:23 amalloy: i'm disappointed

15:23 technomancy: I just made that up

15:23 clojurebot: I don't understand.

15:23 technomancy: but it sounds good

15:23 antares_: $google what is clojurebot

15:23 lazybot: [irc log: #clojure on 2012-10-12] http://www.unexpected-vortices.com/clojure/irc-logs/2012/10-12.html

15:23 amalloy: it sure does. in this context what does it mean? don't make up code in the user's project or something?

15:23 frawr: and when using java -cp standalone.jar clojure.main -m my.ns, should my.ns be just a ns with a -main too?

15:25 amalloy: yes

15:25 antares_: frawr: basically, you run namespaces. By convention they must have the -main function that takes & args

15:27 frawr: The error running my jar makes more sense too then, it listed the fn i wanted to use as mai as part of the ns, with a dot instead of a slash

15:29 thnx, works!

15:33 grzm: ohpauleez: thanks! looking forward to it (was pulled away from my desk for a bit)

15:39 technomancy: frawr: yeah, we should probably warn in uberjar when :main is set to a var

15:39 it's useful for specifying several run targets in aliases but not or uberjars

15:39 frawr: Didn't really think about it, but that makes sense.

15:42 Cheiron: clojurebot: besame mucho

15:42 clojurebot: It's greek to me.

15:49 frawr: Anyone from the netherlands here?

15:59 jamii: Fun with parsing - http://scattered-thoughts.net/blog/2012/10/25/strucjure-reading-the-readme/

16:03 flying_rhino: hello guys

16:04 AntelopeSalad: is there anything better than ring/jetty out there for powering a web server?

16:04 dnolen: jamii: neat stuff, is there some specific you have planned for strucjure?

16:04 emezeske: AntelopeSalad: Do you have a specific problem with ring/jetty?

16:05 AntelopeSalad: emezeske: yes, it's getting destroyed under load by artifical benchmarks

16:05 flying_rhino: I am wondering is it possible to program in clojure in imperative way, like in Java. I am not saying imperative is better, I just want to know is it doable in principle?

16:05 hiredman: flying_rhino: no

16:05 emezeske: AntelopeSalad: And you're convinced that this is ring or jetty's fault?

16:05 nDuff: ...well...

16:05 ivan: flying_rhino: yes

16:05 AntelopeSalad: emezeske: no, that's why i asked if there's an alternative to test against

16:05 nDuff: flying_rhino: _possible_, yes, but very painful.

16:06 ivan: is it really that painful to use doto and mutable objects?

16:06 it's just freakishly ugly

16:06 AntelopeSalad: i basically put up a node/express server vs clojure/ring (i would have used compojure but the documentation is bad) , and the ring setup was getting beat up, i was hoping there was an alternative

16:06 nDuff: ivan: When all your language facilities are built to work with immutible objects? Yes.

16:07 dnolen: AntelopeSalad: ring/jetty and are very fast.

16:07 emezeske: AntelopeSalad: It's pretty unlikely that the bottleneck is in ring or jetty, as opposed to your application code

16:07 jamii: dnolen: I'm really excited by http://www.viewpointsresearch.org/html/work/ifnct.htm and http://boom.cs.berkeley.edu/

16:07 dnolen: AntelopeSalad: you probably testing w/ a bunch of silly dev route stuff in place.

16:07 flying_rhino: the thing is, I like some stuff about lisp (like macro system and first class functions), and I even like a lot of things about immutability but there are things I can't use it for. For example, game development (I am thinking of developing a game for JVM), almost screams mutable state.

16:07 AntelopeSalad: i dunno, the app code came from the ring documentation

16:07 jamii: dnolen: I want to apply the same kind of thinking to building p2p networks

16:08 dnolen: I'm going to start porting bloom to clojure next week

16:08 dnolen: AntelopeSalad: doesn't mean much. I've done a ton of pointless benchmarking of netty/jetty/node.js in the past. netty can eat Node.js for breakfast.

16:08 AntelopeSalad: jetty is fine for nearly any workload that's not a chat server.

16:08 AntelopeSalad: all i did for clojure was setup a handler to report back hello world with no templating

16:09 ohpauleez: dnolen: ttt is in the wild, but shield your eyes - I did it premature so there was an example of some node.js magic people could work from

16:09 AntelopeSalad: and then i did the same with express

16:09 then i ran it against ab

16:09 flying_rhino: so basically what do you do for things that are best done in mutable way (like some things in game development?)

16:09 tomoj: sounds like a good test if you're going to be serving 100000 'hello world's a second

16:09 AntelopeSalad: http://pastebin.com/FP5vxyWT

16:09 ohpauleez: I ripped the logic query out temporarily and restored the working, but extremely naive for-comprehension

16:09 AntelopeSalad: that is the test setup and results

16:09 dnolen: AntelopeSalad: do some more homework, look at the Jetty docs, if you seeing less than 4000-5000 req/s you're doing something wrong. if you're building a regular website, who cares anyway.

16:10 AntelopeSalad: this is on my horrible computer running in a VM so the reqs/s will be low for both

16:10 dnolen: ohpauleez: still looks like it will be a really sweet resource!

16:11 tomoj: the req/s differences there look.. unimportant

16:11 flying_rhino: guys?

16:11 ohpauleez: dnolen: Here's hoping! :)

16:11 emezeske: AntelopeSalad: How are you running the clojure code? lein ring?

16:11 AntelopeSalad: tomoj: look at the -c 150 one, the node server is pumping out 50% more reqs/s

16:12 that is a non-trivial amount

16:12 emezeske: i followed the ring's documentation

16:12 dnolen: jamii: yeah I've been following along - sounds like you've finally find some time to put it together. You're at HackerSchool right?

16:12 AntelopeSalad: https://github.com/mmcgrana/ring/wiki/Getting-Started

16:12 i used this exactly, except ring 1.1.6

16:12 and clojure 1.4

16:12 jamii: dnolen: Yep. I really needed this kind of environment to actually get moving. Far too easily distracted otherwise :)

16:12 tomoj: yeah, if you're just serving hello worlds

16:13 dnolen: jamii: been wanting to find some time to really dig into Bloom but I've been busy w/ other things, look forward to seeing the trail you blaze.

16:13 jamii: dnolen: thanks

16:13 dnolen: jamii: yeah I love the VPRI/FONC stuff

16:13 AntelopeSalad: tomoj: what do you propose is a better test, should i return a 5kb string instead?

16:14 ordnungswidrig: hmm, me has only 500/s for a simple "OK" response with -c 50

16:14 osx seems to do sth wrong

16:14 dnolen: AntelopeSalad: actually those benches look about right, the difference doesn't look large enough to care though. Once you have template, DB, etc I can't imagine there being an interesting diff.

16:14 ohpauleez: amalloy: Thanks for the typo catches

16:15 AntelopeSalad: dnolen: 50% isn't enough to care about?

16:15 what about an api server that doesn't serve templates?

16:15 or a game backend that's just returning json too with websockets, etc.

16:15 emezeske: AntelopeSalad: That benchmark is fairly useless with respect to both of those examples

16:15 ordnungswidrig: AntelopeSalad: is it tuned until no more? Regarding settings, buffer sizes etc?

16:16 AntelopeSalad: ordnungswidrig: not at all, i have no experience with clojure. i was just bored this afternoon and wanted to setup a comparison between it and node

16:16 because i'd like to learn something as a general purpose web language

16:16 dnolen: AntelopeSalad: if you want better than Node.js async perf, I already said use Netty.

16:16 ordnungswidrig: AntelopeSalad: don't do it :-)

16:17 AntelopeSalad: ordnungswidrig: don't do what?

16:17 dnolen: will that still work with ring and compojure?

16:17 dnolen: AntelopeSalad: w/o seeing a real workload, it's hard to extract any meaning from those numbers.

16:17 AntelopeSalad: i like the way compojure handles routes a lot

16:17 emezeske: AntelopeSalad: To answer your question earlier, 50% is definitely not enough to care about, compared to other factors like developer productivity

16:18 AntelopeSalad: Unless you really, really know you're going to be serving tens of thousands of qps or something

16:18 dnolen: AntelopeSalad: I believe Aleph may have ring compat.

16:18 ordnungswidrig: AntelopeSalad: such tests, when you don't know how to tweek to max performance

16:18 AntelopeSalad: yeah, it's just bs tests atm, there's no real world data to run it against

16:19 ordnungswidrig: I do web development since 15 years and I never had a case where the bottleneck was the http server implementation :)

16:20 AntelopeSalad: i only asked because cost might be a deciding factor at some point

16:20 i figured "oh man, 50% wtf... that's going to be 50% more expensive"

16:20 emezeske: ordnungswidrig: I've run into cases where the HTTP server was the bottleneck, and the answer was _easily_ "throw a couple more servers at it."

16:20 nDuff: AntelopeSalad: I've never, ever seen the bottleneck be there.

16:21 AntelopeSalad: it's pretty much always datastore, occasionally inefficient app-layer logic...

16:21 emezeske: AntelopeSalad: Unless you are serving at a massive, massive scale, paying for engineers dominates paying for servers

16:21 nDuff: AntelopeSalad: "50% more" doesn't matter if that 50% is 0.5% of your runtime.

16:21 ordnungswidrig: emezeske: sure, there are those cases. But they are special in my experience. and often enough you can change application architecture to reduce the necessary load on servers, conditional requests, caching etc.

16:21 AntelopeSalad: emezeske: yeah of course, if it gets really big then you're in a great position to hire people who know how to deal with it

16:21 ordnungswidrig: nDuff: exactly!

16:22 AntelopeSalad: i was looking at it from a perspective of playing a game

16:22 ordnungswidrig: AntelopeSalad: it's like having to pay income tax. it's a good sign, saying that you acutally have income

16:22 AntelopeSalad: it may involve sending back and forth a lot of small size packets

16:22 emezeske: ordnungswidrig: We agree: 50% means basically nothing. :)

16:23 ordnungswidrig: AntelopeSalad: your problem will be more likely how many connection can be handled at once.

16:23 nDuff: AntelopeSalad: ...also, you want to pay attention (lots of attention!) to how things scale on multi-core architectures

16:23 AntelopeSalad: ...which is not really one of node's strengths, but the direction hardware has been heading in for ages.

16:23 AntelopeSalad: ord: from those tests it looks like the jetty server would eventually crumble with more concurrency

16:23 dnolen: AntelopeSalad: I ran a Netty+Clojure benchmark on an Amazon Compute Cluster 2 years - I had no idea what I was doing & the hello world benchmark hit >20K req/s.

16:24 AntelopeSalad: nDuff: my VM is only running off 1 core, and scaling node to use multi-cores is nearly automatic and super easy

16:24 * nDuff scrolls back, and... ugh, pastebin.com?

16:24 dnolen: AntelopeSalad: I'm sure Jetty could break 10-15K on the same machine.

16:25 technomancy: flying_rhino: you can use java arrays and such from clojure

16:25 AntelopeSalad: dnolen: i'm not sure what that is, some type of server cluster?

16:25 dnolen: AntelopeSalad: 8 core 23gb box.

16:25 flying_rhino: technomancy: that's good to know

16:25 AntelopeSalad: processor concurrency is something clojure gives us for free right?

16:26 emezeske: AntelopeSalad: Jetty is _not_ going to be your bottleneck for serving http. It just isn't worth worrying about.

16:26 dnolen: AntelopeSalad: my point is, I'd trust any JVM lib for scaling over Node.js

16:26 technomancy: flying_rhino: http://meshy.org/2009/12/13/widefinder-2-with-clojure.html <- good example of falling back to java-like code when speed is more important than maintainability

16:26 AntelopeSalad: i mean, to utilize >1 core there's nothing you have to touch?

16:26 dnolen: AntelopeSalad: Jetty & Netty autoscale yes.

16:26 flying_rhino: can I create something like Java struct? (mutable class with no methods)

16:26 dnolen: AntelopeSalad: of course in a real app you probably need to do a lot of knob twiddling.

16:26 technomancy: flying_rhino: you can do that with deftype, but usually it's a waste of time

16:27 it's there for those 2% cases when mutability is actually a problem, but it's extremely rare

16:27 antares_: AntelopeSalad: there is no such as "concurrency for free". If your server or app does use concurrency in bottleneck areas, with multiple cores you will get close-to-linear throughput increase.

16:27 flying_rhino: technomancy: well some things about games are inherently mutable, unfortuantely

16:27 technomancy: that's one opinion

16:27 AntelopeSalad: antares_: i meant from a writing code perspective

16:27 antares_: jetty will make use of extra cores to some extent, given that you have many concurrent requests

16:28 nDuff: flying_rhino: Remember the ants demo? :)

16:28 AntelopeSalad: if you setup a few lines of logic to handle spawning child processes in node it'll do its thing automatically give you multi-core usage

16:28 technomancy: the only thing inherent about mutability is the fact that you're running on a Von Neumann architecture

16:28 hyPiRion: I've made a lot of different simulators and agents for different bots without mutability

16:28 flying_rhino: technomancy: you pretty much have to update entire state every tick. In case of RPG I intend to make taht's every 0.25 seconds.

16:28 AntelopeSalad: antares_: ok, that sounds good

16:28 hyPiRion: /s/bots/games

16:28 antares_: AntelopeSalad: Clojure gives you safe defaults and building blocks. No "concurrency for free" with any language.

16:28 AntelopeSalad: yeah except that spawning a new OS process is dead slow

16:29 emezeske: flying_rhino: It's perfectly possible to write a Clojure game without using mutable structs

16:29 flying_rhino: nDuff: I am not aware of any ants demo. Can you provied me a link.

16:29 antares_: comparatively to a new thread or Erlang process/Gorouting

16:29 technomancy: flying_rhino: you're coming at the problem with preconceived biases that aren't based on empirical measurements

16:29 nDuff: flying_rhino: https://gist.github.com/1093917

16:29 amalloy: $google functional retro games

16:29 lazybot: [Purely Functional Retrogames, Part 1] http://prog21.dadgum.com/23.html

16:30 AntelopeSalad: btw i didn't intend for this to be any type of flame-y conversation

16:30 i seriously like clojure a lot

16:30 (from what i've read so far at least in the "clojure programming" book and fooling around with the repl)

16:30 nDuff: flying_rhino: ...or, for a newer version: https://www.refheap.com/paste/3099

16:30 antares_: AntelopeSalad: me neither, I find node.js a good choice for Web apps. See http://aphyr.com/posts/244-context-switches-and-serialization-in-node

16:31 riddochc: Sorry, been busy.

16:32 emezeske: amalloy: That's a good entry, although some of the problems he runs into are pretty erlang-specific

16:32 ordnungswidrig: hmm, any idea why stock run-jetty will stop at 50% cpu on both cores?

16:32 AntelopeSalad: antares_: this looks like a good article but wouldn't you share state in the db most of the time anyways?

16:32 seems like suicide to have state locked into your app process

16:32 ordnungswidrig: with stop I mean, limit

16:32 AntelopeSalad: then you lose any form of scaling out

16:32 emezeske: amalloy: Like I guess erlang doesn't let you keep shadowing the same local, e.g. (let [a 1 a (+ a 1) a (- a 5)] ...) ?

16:32 antares_: AntelopeSalad: this is a typical Web app developer perspective

16:32 emezeske: amalloy: I could see how that would be annoying

16:32 ordnungswidrig: AntelopeSalad: you will limit yourself to how fast you can seek a disk.

16:32 antares_: AntelopeSalad: google for Wooga and Erlang. They used to share state via data stores. 24 boxes. In-process state with Erlang in the app — 1 box.

16:33 AntelopeSalad: i mean, if i wanted to store session info on a user. i'd surely put it into redis or some other third party memory storage not the app

16:33 ordnungswidrig: AntelopeSalad: session does not scale. it's shared state that forces you to synchronization, transactions etc.

16:33 antares_: AntelopeSalad: yeah, that's what Wooga did in one of their games

16:34 AntelopeSalad: this way you could have 1 or 50 app servers reading from the same redis server

16:34 antares_: AntelopeSalad: grew up to 24 machines. Shoveled state in and out all the time for no reason. In-process state reduced hardware requirements to 1 machine.

16:34 amalloy: emezeske: i actually haven't read much of it, but i don't think that matters. it's a series on writing games without state, which must be of interest

16:34 antares_: AntelopeSalad: when all you do is Web apps, everything looks like a bunch of stateless servers and shared state in Redis

16:34 a lot of software is not like that or should not be like that

16:35 AntelopeSalad: antares_: yeah, that is good right?

16:35 ordnungswidrig: AntelopeSalad: datomic has a nice model: a writer (transaction) multiple reader nodes having local caches for indexes etc.

16:35 emezeske: amalloy: Oh, it is very much of interest.

16:35 antares_: AntelopeSalad: how is that good?

16:35 AntelopeSalad: if you keep state out of your process, then you can freely scale out without it being a big deal

16:35 antares_: AntelopeSalad: having just 1 option you try to apply to everything does not sound good to me

16:35 AntelopeSalad: *app process

16:35 emezeske: amalloy: I think I ended up on that blog from that series, and ended up reading every entry exhaustively... O_o

16:35 amalloy: yeah, i like his blog too

16:36 antares_: AntelopeSalad: is a game something you'd do like that?

16:36 AntelopeSalad: with game/player state always being stored in and taken out of Redis?

16:36 AntelopeSalad: for a game? i'm not sure. i haven't really thought about that fully ever

16:37 if it's important data i'd probably save it on disk and have a copy in memory for faster access

16:37 antares_: AntelopeSalad: see http://www.slideshare.net/wooga/erlang-factory-sanfran

16:37 ordnungswidrig: AntelopeSalad: btw. think of cutting your state into parts. maybe you can distribute the state on different nodes then. or you can work with eventual consistency.

16:38 AntelopeSalad: wow this talk looks like it'll be quite interesting

16:40 antares_: do you happen to know if the video of this is posted anywhere?

16:40 antares_: AntelopeSalad: I don't know. Another talk by the same person: http://www.slideshare.net/hungryblank/getting-real-with-erlang, see slide 46

16:41 AntelopeSalad: app servers don't need to be monolithic either

16:42 antares_: the only reason is why so much software is I/O bound is because a lot of software is written that way: all state is always sholved in and taken out of a data store, even if there is no real reason for doing so

16:42 "we just have always been doing it, right?"

16:43 AntelopeSalad: right

16:43 antares_: that's not at all how things are in many other areas of software

16:43 AntelopeSalad: i think it's because we can't even trust our web servers

16:43 they need to be restarted pretty frequently

16:43 emezeske: antares_: You know... there are some good reasons for how web apps are architected, with databases, etc. Right?

16:44 AntelopeSalad: also (maybe not in clojure's case tho) if you push a new build that requires restarting the app

16:44 antares_: with erlang and to some extent Clojure (or Scala and Java w/ Akka), you can have sane state management and recovery

16:44 so keeping state in-process is not a problem

16:44 emezeske: there are good reasons but Web developers blindly apply the same approach to EVERYTHING

16:45 AntelopeSalad: i thought one of clojure's main philosophies was to eliminate state and only deal with pure data

16:45 emezeske: antares_: Well, it turns out that most web apps are kinda similar to one another

16:45 antares_: and then spread the gospel of node.js, redis and other stuff that is only necessary if you do things in a particular way

16:45 hyPiRion: AntelopeSalad: Clojure's main philosophy is to make software development less complex.

16:46 antares_: AntelopeSalad: eliminate state? Useful programs always have state. The question is how you change and incapsulate it.

16:47 AntelopeSalad: antares_: in the first slide show, what are those blue dots on slide 46?

16:47 are they supposed to be processes?

16:47 antares_: presumably processes, Erlang or not

16:47 the point is that in Erlang, distribution is transparent and processes across machines form a single "cluster"

16:48 ordnungswidrig: why ist there still no OTP for clojure? Seems so natural.

16:49 AntelopeSalad: what would be contained in each process in this example?

16:49 antares_: AntelopeSalad: in their game example, one player's state

16:49 AntelopeSalad: some piece of the final app and then the "process cluster" is the combination of each sub-app?

16:49 antares_: but there are always additional processes that carry out smaller tasks

16:49 ordnungswidrig: http://www.12factor.net/processes

16:51 antares_: ordnungswidrig: keep in mind that that "guide" assumes that what you build is Web apps, on multiple layers. Assets packagers clearly indicate that.

16:52 ordnungswidrig: absolutely. but the idea of process as an complete processing unit is nice.

16:52 AntelopeSalad: i'm not sure i understand how their state is stored and gotten back out

16:52 antares_: AntelopeSalad: in erlang processes. Do you know anything about Erlang?

16:53 AntelopeSalad: it is NOT stored until a round or the entire game is over

16:53 AntelopeSalad: i know nothing except a lot of people joke at how cryptic its syntax is

16:53 antares_: not stored to a database

16:54 erlang VM can have up to millions of Erlang processes, some of them store state for the duration of a game round

16:54 when the round is over, it is stored to the database

16:55 but all intermediate changes are not stored there, they are kept in the app and propagated to players

16:55 AntelopeSalad: sounds dangerous

16:55 antares_: this cuts number of requests by 99%, as slide 46 indicates

16:55 AntelopeSalad: what happens if something goes wrong and the process crashes?

16:55 antares_: AntelopeSalad: it is not dangerous because Erlang has the concept of supervision trees

16:56 AntelopeSalad: it is restarted by its supervisor. Whole trees of processes can be restarted.

16:56 AntelopeSalad: and it knows what to put back in?

16:56 antares_: AntelopeSalad: that is NOT an OS process, so process crashes means you have issues in your code or something like a network split has happened

16:56 AntelopeSalad: ah

16:57 antares_: AntelopeSalad: it can load something form a database or simply start from scratch

16:57 in an interactive game if a piece of state is gone, it sucks but you cannot make every single change persistent anyway

16:57 there are too many of them

16:57 AntelopeSalad: i was thinking of it as a worst case scenario like

16:57 what if you pay for something in the game and then something happens with the process, the round isn't over yet

16:57 if it crashes and restarts you lose what you paid for

16:57 antares_: so they are batched in some shape or form. The difference is that if an OS process goes down, you lose a lot of state + need to reinitialize everything

16:58 in Erlang, a process that goes down is usually monitored by another process and will be restarted

16:58 (or not, it is up to developers)

16:58 AntelopeSalad: changes that you pay for are probably not stored just in process

16:58 AntelopeSalad: but 99% of state changes can be

16:59 AntelopeSalad: i see an item moving into your inventory as being a state change

16:59 antares_: AntelopeSalad: that does not happen that often

16:59 if you care, you can store that

17:00 but movements that happen all the time, it makes no sense to try to store every single one of them

17:00 that's just too wasteful

17:00 AntelopeSalad: yeah, i agree with that, trying to store every single one would be a bit much

17:00 antares_: and if you crash it does not necessarily make sense to recover EVERYTHING

17:00 AntelopeSalad: it would only be useful if you wanted to make a full on replay of something

17:01 antares_: AntelopeSalad: databases have buffers and periodically flush data to disk, nobody seems to be too concerned about that

17:01 one database goes so far its clients do not check for network errors, and Web developers go gaga over its benchmarks

17:01 Apage43: ..

17:01 AntelopeSalad: in most cases that is their job

17:01 antares_: AntelopeSalad: but it's the same thing

17:01 emezeske: /join #erlang

17:01 antares_: you cannot persist everything, it will be too time consuming

17:02 so you choose what to store (in case of databases, fsync), apparently in many cases that is a tiny fraction of total state changes

17:02 AntelopeSalad: you might not need to persist everything, but you'll probably have to handle everything in your app

17:02 like, player x moved from old-coords to new-coords

17:03 antares_: so?

17:03 Cheiron: A java method requires Class as a parameter, how to pass that in clj?

17:03 Sgeo: ,(class Object)

17:03 clojurebot: java.lang.Class

17:03 AntelopeSalad: i was just getting that in the end you will transfering back and forth a lot of traffic

17:03 antares_: Cheiron: (class x) or (Class/forName "String")

17:04 AntelopeSalad: eh?

17:04 TimMc: Cheiron: Just write the classname.

17:04 antares_: AntelopeSalad: no you won't. 99% of your state changes happen in-process.

17:04 or at least they can

17:04 Cheiron: TimMC: using the class name is throwing classnotfoundexception

17:04 clojure: ohpauleez: so is ttt pretty zippy on the command line?

17:04 AntelopeSalad: client moves from old to new -- client sends that to the server -- server says ok, it's a legit movement back to the client -- client continues

17:05 antares_: AntelopeSalad: well, if clients cannot talk to each other directly, there is no way around that

17:05 a lot of state can even be stored on the client only (maybe not in multiplayer games, but just software)

17:05 ohpauleez: For those curious, here's a screencast of me using ttt and how to use it (2 min): http://www.pauldee.org/TTT-Intro.mov

17:05 dnolen: ohpauleez: oops that was my question, about ttt's on the command line.

17:05 AntelopeSalad: you might need to check vs a central server to make sure it's within a specific bounds

17:05 dnolen: ohpauleez: sweet!

17:05 ohpauleez: dnolen: ^ very zippy

17:05 antares_: AntelopeSalad: and how is it different when your server is completely stateless?

17:05 AntelopeSalad: sort of like having validation code running on your server, of course you need it -- you can't just trust the client (javascript) straight up

17:06 antares_: it is not but you send even more data around, for no good reason

17:06 AntelopeSalad: again, why?

17:06 AntelopeSalad: yeah it's not different in the end

17:06 antares_: because Ruby on Rails works that way?

17:06 dnolen: ohpauleez: are you going to publicize this or waiting to clean it up a bit?

17:06 AntelopeSalad: i have no idea, i never used rails

17:06 antares_: of course you can (again, maybe not in games, but in general you can)

17:06 Apage43: multiplayer games do a -lot- client side. The server is there mostly to make sure the things the clients say make sense (aren't cheating), and that they sync up.

17:06 nDuff: *nod*.

17:06 antares_: in games client-side state means cheaters will try to exploit it

17:06 emezeske: antares_: Are you suggesting that you can leave validation to the client?

17:07 antares_: but you sure can store and change a lot of the state in the client

17:07 ohpauleez: dnolen: I'm ok with people checking it out now, but I'm going to clean it up a little bit before I hit the list with it

17:07 antares_: emezeske: absolutely

17:07 dnolen: ohpauleez: cool

17:07 nDuff: AntelopeSalad: ...you don't need to make the server validate _every_ move -- those can be batched.

17:07 antares_: emezeske: the only case where it won't work is if you also have an API

17:07 nDuff: No point to making your app unnecessarily latency-sensitive.

17:07 ohpauleez: dnolen: The best piece of code in there is "blocking-deref" which I think is pretty essential for sane use of Node.js

17:07 AntelopeSalad: nDuff: yeah, i'm not a game dev -- i'm sure there's all sorts of tweaks you can do to minimize the back and forth traffic

17:07 but it's something i want to persue in the future

17:07 dnolen: ohpauleez: is that a macro?

17:08 TimMc: Cheiron: You'll need to (:import ..) it then.

17:08 emezeske: antares_: Uh...

17:08 dnolen: ohpauleez: demo looks cool, and yeah, fun to see command line usage of Clojure that isn't glacial

17:08 antares_: AntelopeSalad: on crappy mobile networks, again, a lot of state is kept in the client for at least some time

17:08 TimMc: Cheiron: or use the pacakge-qualified name.

17:08 antares_: emezeske: Uh what?

17:08 ohpauleez: dnolen: Function - it just ticks Node.js until a promise is fulfilled

17:08 dnolen: ohpauleez: neat

17:09 ohpauleez: sounds worthy of blog post

17:09 antares_: emezeske: are you saying that nobody does that? How about lots-of-state-on-the-client libraries like Ember or even backbone?

17:09 ohpauleez: dnolen: it's coming :)

17:09 AntelopeSalad: antares_: handling a lot of state on the client seems worse for mobile dev

17:09 antares_: AntelopeSalad: yeah? what will you do when your app detects there is no network connection?

17:09 AntelopeSalad: if you're talking about stiching up templates with js template libs, that's going to be put serious stress on a mobile device

17:10 *stitching

17:10 emezeske: antares_: You made it sound like the server doesn't need to validate input it's receiving. If that's not what you mean, then fine.

17:10 Sgeo: I'm under the impression that multiplayer games sometimes do store quite a bit of state client-side that server doesn't check, because a bit of cheating is not as bad as having a server that barely runs because it needs to check everything

17:10 And using a lot of bandwidth and time for every frame that the client needs to display

17:10 ordnungswidrig: Sgeo: the server can batch-validate later

17:10 antares_: AntelopeSalad: what will your super-neat server-based mobile app do when it has no network connection? it has to either keep state in the app for at least some time or drop it on the floor

17:10 AntelopeSalad: Sgeo: there's probably client side prediction to make it look smooth without crushing the server, but then every x frames or milliseconds it checks back to make sure you're in bounds

17:11 Sgeo: Can't batch-validate whether client is using semitransparent textures on walls in 3d games

17:11 emezeske: Sgeo: The server in a multiplayer game should check *all* state that could affect the outcome of the game

17:11 antares_: so, it turns out, completely stateless apps is just one historically formed case with "traditional Web apps"

17:11 AntelopeSalad: antares_: i don't know, i don't develop for mobile devices yet

17:11 emezeske: Sgeo: Of course graphical state doesn't matter, e.g. in counterstrike source, the ragdoll physics are not synced among clients because they don't really affect the outcome

17:11 antares_: with mobile clients, real-time games and data processing, in-process state is an important part of the equation

17:12 dnolen: ohpauleez: cool to see the datalog query lang, I checked out the core.logic bits seems like a nice and simple use case.

17:12 emezeske: Sgeo: For things like transparent texture hacking, they do a lot of hashing to check things server side, but obviously that's a cat and mouse game

17:13 ohpauleez: dnolen: I agree; it's a simple way to say, "Here's a quick way logic makes this easy"

17:13 Sgeo: But the possibility of cheating is still better than the alternative of having the server compute every bitmap and send it to the client

17:13 AntelopeSalad: antares_: in the case of losing connection, i have to guess that the server will keep everything in order and keep trying until it eventually either times out or the client comes back from the dead

17:13 ohpauleez: dnolen: I agree with martin - you can get pretty far with unify, binding-map, set, and filter

17:13 antares_: AntelopeSalad: that's not what I am talking about

17:13 AntelopeSalad: my network is down, the user added something in the app

17:13 AntelopeSalad: what do you do if you cannot send a piece of data to your shiny node.js backend?

17:13 emezeske: Sgeo: Well, onlive did it the latter way (server computes everything), although they did not do well as a business

17:14 antares_: AntelopeSalad: drop the change or keep it in the app until network access is back? I think the answer is obvious.

17:14 AntelopeSalad: antares_: in that case, keep it in the app for sure -- if we're talking about a content oriented web app that isn't really multi-player

17:15 but "app" in this case would be javascript on the client most likely

17:15 antares_: AntelopeSalad: so there you go, you are dealing with more sophisticated state changes. If that happens to include concurrency, bam, it's a lot of fun. Clojure is one of a few languages where state management is much more predictable, even with a lot of concurrency going on.

17:16 AntelopeSalad: i'm not sure why node would fail with that use case

17:16 antares_: AntelopeSalad: javascript or not, the belief that all software is stateless or should be such is wrong

17:16 dnolen: ohpauleez: yep. lynaghk is working on some cool things it's giving me ideas for things to work on.

17:16 AntelopeSalad: your state would be partially stored in some client side code that is 100% isolated from the server -- the server choice at this point has no bearing

17:16 antares_: AntelopeSalad: node tries to hide concurrent state management from you by only having 1 thread and callback soups everywhere

17:17 AntelopeSalad: it auto-spawns child processes and manages them internally, i don't know the exact details though

17:17 dnolen: ohpauleez: I think by making it clear how to build simple rules system maybe be a better entry point for most people than the raw miniKanren itself

17:17 Apage43: wait what

17:17 antares_: AntelopeSalad: yeah, I guess you never developed anything that's not a Web app and my point will not get across

17:17 ohpauleez: dnolen: We were just hacking on all that stuff this past weekend - you should have seen the whiteboard - so.much.core.logic.

17:17 antares_: AntelopeSalad: it does not autospawn a thing

17:17 dnolen: ohpauleez: ah right, did you meat up with Kevin in NYC?

17:17 ohpauleez: oh, your in Portland now right?

17:18 AntelopeSalad: antares_: if you use the cluster module it forks children and then has its own messaging system setup

17:18 antares_: AntelopeSalad: maybe some servers do, again, this can be "automatic" only as long as there is no need to share any state and process interactions are trivial

17:18 ohpauleez: dnolen: I totally agree - more than happy to help with those efforts. Yeah, I'm out in Portland mostly full-time now

17:19 dnolen: ohpauleez: he's got some neat things he wants to do w/ the grammar of graphics stuff, a lot of it really can be done w/ simple unification + simple constraints (my new idea)

17:19 AntelopeSalad: antares_: i think that brings us in a full circle haha

17:19 antares_: AntelopeSalad: but that's not Node. That's some cluster module. And fork(2) is an expensive operation.

17:20 AntelopeSalad: it might not be able to handle state in that case which is why people just throw their state in redis

17:20 cluster is a core module for node

17:20 just like http is a core module for node

17:21 ohpauleez: dnolen: For sure. I'd be interested in taking a look at what you cook up for simple constraints- it's one area of core.logic I haven't ventured into yet

17:21 Apage43: I remember when it wasn't =P

17:21 that is, it used to be its own thing

17:22 * Sgeo wants a library that makes it easy to define easy-to-use lazy data structures

17:22 Apage43: it's been pulled into the standard distribution, but it doesn't do anything "special" to make it work well with node

17:22 Sgeo: Similarly to how lazy-seq exists, something for developers to make their own lazy-seq like things

17:22 Apage43: it just sets up a way for you to message the leader, basically

17:22 AntelopeSalad: Apage43: yeah

17:22 it works though

17:22 Sgeo: Such that client code does not have to deal with forcing

17:22 AntelopeSalad: and it's basically hands free once you set it up

17:23 Apage43: right, assuming no shared state

17:23 AntelopeSalad: yep

17:23 dnolen: ohpauleez: basically a simple way to take any predicate and attach it to a var, soon as the var becomes ground it will run. This will let people say things like only unify if number, or if this class, etc.

17:23 AntelopeSalad: that's why everyone keeps their web servers statelesss

17:23 and all of this stemmed from the TL;DR part of this: http://aphyr.com/posts/244-context-switches-and-serialization-in-node

17:23 ohpauleez: dnolen: YES!!!

17:24 Apage43: because it sucks to write a stateful one in node =P

17:24 AntelopeSalad: he basically says it's not an issue if you keep state out of the app

17:24 ohpauleez: It's like you were sitting on my laptop last night

17:24 I was in the weeds working on core.contracts+test.generative+Alloy and facing that exact situation

17:24 AntelopeSalad: Apage43: and in clojure it won't be a problem to run a multi-core/server stateful app?

17:24 i haven't gotten to managing state and concurrency yet in the book

17:25 Apage43: not nearly so much as in node, no

17:25 multi-server you have the same issues

17:25 but not with multi-core

17:25 AntelopeSalad: multi-server seems pretty standard to me

17:25 ohpauleez: dnolen: ^ (my current approach is a generic "spec" hashmap that gets unified and processed for each any backend. Making it open for extension)

17:25 antares_: AntelopeSalad: I am convinced that Web developers run everything stateless because 1) they have never seen a different approach because Web devs only work on Web apps, 2) almost all modern languages suck at error handling and recovery, which is very important for in-app state

17:26 it has nothing to do with "scaling out". Your state is still shared, you just shifted the bottleneck to the database. And once you have a few DB machines, the whole consistency/availability dance begins.

17:26 AntelopeSalad: no matter what choice you make, a single server is eventually going to crumble with enough pressure

17:26 ordnungswidrig: antares_: and today's web developers know only database for persistence.

17:26 nDuff: AntelopeSalad: Nobody is denying the need to scale to multiple servers.

17:27 antares_: AntelopeSalad: cool, why again should I keep my app completely stateless?

17:27 Apage43: AntelopeSalad: sure, but with the node-cluster approach you couldn't easily do something like distributing users over the works, but then giving the users affinity to a particular worker, and then just manage that state on that worker

17:27 technomancy: I dunno, I think people spend way too much time thinking "what if we become the next facebook"

17:27 Apage43: *workers

17:27 antares_: AntelopeSalad: I can keep it mostly stateful and sync when important evens happen

17:27 *events

17:27 nDuff: ...trying to hard to keep things stateless means your caches aren't close to your requests

17:27 AntelopeSalad: Apage43: can't you use a load balancer that handles sticky sessions?

17:27 antares_: that's what the presentation above basically demonstrates

17:27 Apage43: AntelopeSalad: not with node-cluster..

17:28 nDuff: so you move things out into memcached or such, but then you're going over a network rather than being able to refer to local memory.

17:28 AntelopeSalad: Apage43: why not?

17:28 Apage43: because once it hits a server you don't get to pick what worker the connection goes to

17:28 nDuff: Apage43: ...well, that's not quite true; there are techniques for that.

17:28 Apage43: since its dispatched before you know who it's from

17:28 AntelopeSalad: your clustered app is running on 1 port, it doesn't spawn a "real" new process

17:29 nDuff: Apage43: First person to get a request assigns a cookie. Cookie comes through on all future requests. Load balancer looks at it to pick first-choice handler.

17:29 AntelopeSalad: as far as your load balancer knows, it's just a single app (i would think, i never tested it full hand)

17:29 *first

17:29 ivan: can I query postgres with datalog queries yet?

17:30 nDuff: ...oh, you're talking about separate-process workers being locally dispatched w/ something not as smart as HAProxy or such? Ugh.

17:30 antares_: nDuff: this means now you have a stateful load-balancer ;) won't you want to scale load balancers once you become the next facebook?

17:30 AntelopeSalad: i don't even care about scaling right now haha

17:30 i just didn't want to spent 50% more

17:30 and you guys cleared it up that it won't be a direct 50% cost increase

17:30 nDuff: antares_: Yes, I have a stateful load balancer. There are damned good ones on the market -- but it doesn't need to be as stateful as you think, if it's just using a hash of the cookie for assignment.

17:30 wingy: technomancy: or they are just curious about how it works :)

17:31 antares_: nDuff: I was kidding. "Smart proxies" definitely can solve some problems well, and there are good off-the-shelf solutions.

17:32 AntelopeSalad: nDuff: are you running any decently large sites atm with ring serving everything?

17:32 dnolen: ohpauleez: another thing would be "ghost" values

17:33 ohpauleez: values which can be replaced by other values w/ failing unification

17:33 nDuff: AntelopeSalad: Nope. My last decently large site was a Django shop. Python's not exactly a high-performance language, not Django a high-performance stack... but it didn't matter, because we did a decent job at horizontal scaling.

17:33 AntelopeSalad: Same thing applies here, except that the JVM is one helluva faster runtime than CPython.

17:34 dnolen: ohpauleez: w/o I mean

17:34 AntelopeSalad: can you give me a ballpark on how much traffic you guys had and how much it cost per month for hosting?

17:34 doesn't need to be exact, just a rough estimate

17:35 ohpauleez: dnolen: ahh gotcha - would be useful when doing a lot of data-oriented unification

17:37 nDuff: AntelopeSalad: In PM.

17:37 wei_: in clojure, you extend the reader by rebinding *data-readers*. how to do so in clojurescript? looks like *data-readers* is not bound.

17:41 dnolen: wei_: hasn't been done yet as far as I know. could be wrong

17:42 wei_: i see, thanks

17:44 Cheiron: Hi, any idea what is this ? http://pastie.org/5120925

17:45 scriptor: what's the code giving that error, Cheiron

17:45 Cheiron: trying to test Storm topology with Storm provided macros

17:54 riddochc1: that feels like chaos

17:54 SOrry.

17:54 Wrong channel.

17:55 Cheiron: it it possible to exclude a namespace from :aot of lein?

18:01 technomancy: Cheiron: ...yes?

18:02 Cheiron: I checked the sample.project.clj

18:02 but didn't find an option to exclude a namespace from :aot

18:02 technomancy: :aot is a vector

18:03 oh, you mean exclude it from :aot :all? there's nothing for that, no.

18:04 Cheiron: I see, thanks!

18:05 technomancy: I think :aot might support a vector of regexes as well though

18:07 aperiodic: it does

18:10 Cheiron: it does? so something like com.domain.* will compile the whole name space but not clojure.pprint ?

18:11 aperiodic: it will compile every namespace that match com.domain.* and any namespaces they use/require

18:12 as far as i know there's no way around that

18:13 Cheiron: I see

18:14 wingy: does aleph work with ring/compojure?

18:14 technomancy: yeah, that's a long standing clojure bug

18:25 ivan: wingy: pretty sure it does

18:27 Apage43: wingy: you can even use compojure to route async stuff

18:27 see (wrap-ring-handler) and (wrap-aleph-handler) in the Aleph API

18:28 wingy: https://github.com/ztellman/aleph/wiki/HTTP

18:28 yeah .. nice

18:28 now i can choose when to do (a)synchronous handling

18:28 Apage43: yup.

18:30 you can do stuff like use compojure to dispatch to a websocket handler

18:31 wingy: are there reasons to use jetty instead of aleph? seems like aleph scales better

18:32 tomoj: :(

18:32 Apage43: well if you stick with pure ring, you get the rest of the servlet ecosystem

18:32 if you're into that kind of thing

18:33 you can spit out WAR files that you can just drop on any servlet-compatible container and have them go

18:33 xeqi: wingy: source?

18:33 wingy: okay .. im not familiar with WAR files and servlets .. have to read up on that

18:34 Apage43: it's the sort of thing that's more valuable if you have lots of existing Java infrastructure

18:34 wingy: xeqi: coming from node.js where we learned async handling = higher performance

18:35 Apage43: i see

18:36 Apage43: there are places where it's faster to just respond immediately, rather than do the whole async queueing hoopla, especially if its a request that you can fulfill very quickly (don't have to hit network or disk) and without much computation

18:38 async handling isn't magic, it's just a way of coordinating work that happens to make a lot of sense if you have lots of things that wait on other things

18:40 wingy: isnt that the case when doing web apps with a database?

18:40 emezeske: I feel like the disadvantages of async I/O aren't mentioned enough

18:40 It makes things harder to debug, and opens you up to spaghetti callback code

18:41 You can also introduce horrible problems by accidentally doing CPU-intensive work in the worker

18:41 Apage43: ++

18:42 yeah, there's a lot you have to be careful around

18:42 wingy: emezeske: what if you don't have to mess with callbacks

18:42 emezeske: wingy: All the other things still apply

18:42 * technomancy spent a couple weeks doing some async code

18:42 technomancy: never thought I'd be so happy to see a proper stack trace after that

18:42 wingy: if you just wrap your functions with an async handler that will take care of putting your return value to the callback (https://github.com/ztellman/aleph/wiki/HTTP)

18:43 emezeske: technomancy: Exactly -- async callstacks are so not helpful

18:43 wingy: so it makes sense to just stick with jetty instead of aleph?

18:43 emezeske: wingy: Unless you have a very specific workload where jetty is just not working out for you? Yes. (IMHO)

18:44 wingy: lets just do that then .. jetty .. you are a damn lucky server

18:44 aperiodic: i get the impression that everybody who uses node.js writes their own idiosyncratic flow control library in order to avoid losing their mind

18:45 emezeske: aperiodic: Yep! Everyone ultimately tries to create a synchronous-looking API on top of the async :)

18:45 Apage43: aperiodic: not everyone, a lot of them have already lost their minds and have become comfortable with it :)

18:45 wingy: everyone is using async.js

18:46 emezeske: aperiodic: haha

18:47 wingy: the fact is that i feel synchronous coding where you don't have to think about server arhictecture is better .. you just focus on the domain problem

18:47 emezeske: wingy: Synchronous code is undoubtedly easier to read.

18:48 Apage43: and reason about

18:48 wingy: screw scaling .. i want a happy life :)

18:49 emezeske: wingy: You can scale both ways

18:49 * Apage43 would really like one of those too

18:53 tomoj: async.js seems way off

18:56 wingy: tomoj: it's whatever node.js needs it to be

18:59 dnolen: ohpauleez: LOGIC-63 resolved

18:59 ohpauleez: dnolen: Excellent, I'll take a look at the ticket now to see the resolution, I'm definitely curious

18:59 dnolen: ohpauleez: typo :P

19:00 ohpauleez: :(

19:00 dnolen: I apologize

19:00 dnolen: ohpauleez: from copy and pasting Clojure into ClojureScript, -withMeta -> -with-meta

19:00 ohpauleez: on LCons deftype

19:00 ohpauleez: nah, wasn't obvious

19:00 Sgeo: Why does tryclj allow def and the bots don't?

19:00 ohpauleez: Ahh that makes sense

19:01 dnolen: ohpauleez: thanks for actually trying / using core.logic on CLJS :)

19:01 ohpauleez: dnolen: Thank you for providing me with something to try!

19:06 technomancy: Sgeo: probably because everyone in the channel shares a sandbox with lazybot

19:06 Raynes: Sgeo: Well clojurebot doesn't use clojail, so it has no def sandboxing at all.

19:06 technomancy: whereas tryclj can build the notion of a session

19:06 Raynes: Sgeo: On tryclj, everyone gets their own sandbox. In this channel, everybody shares a single sandbox.

19:06 Sgeo: It is entirely possible to make lazybot work like tryclj, I just haven't done it.

19:09 dnolen: ohpauleez: whenever I work on core.logic on CLJS - I realize, CLJS is pretty freaking awesome.

19:10 ohpauleez: dnolen: It really is incredible - the reader, protocols, rich data types, and macros - you can pretty much build anything

19:11 dnolen: ohpauleez: LOGIC-61 resolved

19:11 ohpauleez: I think that's it for your CLJS tickets

19:12 ohpauleez: dnolen: Thank you so much, definitely very helpful (I needed partial-map for something)

19:12 dnolen: ohpauleez: partial maps will no longer escape, really meant to be used internally anyway. They always become regular maps when they become a result

19:13 ohpauleez: excellent, that totally works for me

19:39 dnolen: core.logic 0.8.0-beta2 going out

19:40 pandeiro: dnolen: know anything about elm?

19:40 dnolen: pandeiro: yeah I saw a presentation about it at ELC

19:40 at StrangeLoop

19:41 pandeiro: just discovered it, some interesting ideas applicable to cljs dev

19:41 * technomancy couldn't keep elm and roy straight

19:41 technomancy: which one was presented first?

19:42 dnolen: technomancy: Elm was I think

19:42 pandeiro: what in particular?

19:42 pandeiro: dnolen: functional reactive programming

19:43 technomancy: elm was the more reactive one, yeah

19:43 that was rockin'

19:44 pandeiro: something like Mouse.position always having the cursor's coords, is that really 'functional'?

19:44 i am not interested in paradigm purity, just trying to understand things

19:44 dnolen: pandeiro: it's very interesting I'd like to see much more non-trivial examples though. I also wasn't sold on hiding the details of the platform

19:45 pandeiro: my impression was a FP version of Lively Kernel but much less mature.

19:45 pandeiro: dnolen: i am torn on that b/c it seems js can be so low level for a high level language

19:45 the way you have to do things

19:45 the need for jquery

20:06 ohpauleez: To those interested in learning more about ClojureScript+Node.js

20:06 http://www.pauldee.org/blog/2012/clojurescript-and-node-js-an-experience-report/

20:15 wingy: is there a way to add a key/value pair to a map if the key value pair is inside a list or vector?

20:15 [key value]

20:16 black_joe: (keyword) will convert data of another type into a key.

20:16 Raynes: Not what he wants.

20:16 wingy: nope

20:17 Raynes: &(apply assoc {:a :b] [:c :d])

20:17 lazybot: java.lang.RuntimeException: Unmatched delimiter: ]

20:17 Raynes: &(apply assoc {:a :b} [:c :d])

20:17 lazybot: ⇒ {:c :d, :a :b}

20:17 Raynes: wingy: ^

20:17 wingy: (some-fn {} [key value]) ;=> {key value}

20:17 jkkramer: &(conj {:a :b} [:c :d])

20:17 lazybot: ⇒ {:c :d, :a :b}

20:18 Raynes: Huh, cool.

20:18 wingy: jkkramer: there you go

20:18 jkkramer: &(conj {:a :b} '(:c :d)) ;but not this

20:18 lazybot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map$Entry

20:19 wingy: yeah vector only

20:25 Sgeo: Are there any good libraries for making lazy data types and functions to operate on them?

20:32 dnolen: ohpauleez: nice post

20:32 ohpauleez: dnolen: Thanks, I hope people find it useful (and don't mind the bits of passive voice use)

20:34 ivan: does tools.nrepl support any kind of incremental response? I'd like to write command-line tools that don't want for all of stdout before writing something

20:53 Sgeo: When is it appropriate to use get?

20:53 (doc get)

20:53 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

20:58 ohpauleez: Sgeo: When your key is not a keyword

20:58 or when your collection can be a number of things (all that support get)

20:58 Sgeo: ,({1 2 3 4} 1)

20:58 clojurebot: 2

20:59 ohpauleez: ,([1 2 3 4] 1 2)

20:59 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: PersistentVector>

20:59 Sgeo: ,(get [1 2 3 4] 1 2)

20:59 ohpauleez: ,(get [1 2 3 4] 6 2)

20:59 clojurebot: 2

20:59 2

21:00 ohpauleez: ,(get {"a" 1} "a" 2)

21:00 clojurebot: 1

21:00 jamii: I keep getting bitten by this:

21:00 secd.core> NIL

21:00 #secd.core.NIL-I{}

21:00 secd.core> (class NIL)

21:00 secd.core.NIL-I

21:00 secd.core> (class #secd.core.NIL-I{})

21:00 clojure.lang.PersistentArrayMap

21:00 ohpauleez: ,(get {"a" 1} "b" 2)

21:00 clojurebot: 2

21:00 ohpauleez: Sgeo: does that help?

21:00 Sgeo: Yes

21:01 ohpauleez: excellent

21:01 jamii: What is it you're trying to do?

21:01 technomancy: Sgeo: OTOH calling the map without get will do the same thing

21:01 so get is typically used if the map might be nil

21:01 ohpauleez: jamii: Ohh, nil is lowercase

21:01 technomancy: and you're looking up a non-keyword key

21:02 ohpauleez: yes

21:02 I use it most in threading macros

21:02 for that reason

21:02 jamii: ohpauleez: this is a record called NIL. The name is not important. The problem is whenever you use record literals to construct a record that has zero args, the resulting object is a map.

21:02 ohpauleez: Which breaks protocol dispatch

21:02 amalloy: technomancy: get can probably optimize better than calling the map as well

21:03 gfredericks: what are records that have zero args?

21:03 ohpauleez: jamii: Definitely sounds like a bug to me. Is there any literature against creating Records of zero args?

21:03 gfredericks: (defrecord Foo [] ...)?

21:03 ohpauleez: gfredericks: My thought too

21:03 gfredericks: the point is to have a mappish thing of a custom type, but not caring about any particular fields?

21:04 amalloy: on reflection i don't think that's true actually, never mind

21:04 ohpauleez: jamii: Would you better served with deftype?

21:04 jamii: ohpauleez: deftypes don't have literals at all, so I can't prn and then read them

21:05 ohpauleez: jamii: You could define reader-literals (if you're ok using 1.5.0-beta1)

21:05 actually - they're in 1.4 too

21:06 jamii: secd.core> (class `~NIL)

21:06 secd.core.NIL-I

21:06 secd.core> (class (eval `~NIL))

21:06 clojure.lang.PersistentArrayMap

21:06 ohpauleez: and if you need the the reader, what's wrong with using nil, which would give you the protocol dispatch

21:07 amalloy: jamii: `~x is always identical to x

21:07 jamii: amalloy: ok, so this is the core of the problem

21:07 secd.core> NIL

21:07 #secd.core.NIL-I{}

21:07 secd.core> (eval NIL)

21:07 {}

21:08 Compared to:

21:08 secd.core> (SEL 't 'f)

21:08 #secd.core.SEL-I{:then t, :else f}

21:08 secd.core> (eval (SEL 't 'f))

21:08 #secd.core.SEL-I{:then t, :else f}

21:08 Records with zero args eval to maps, not themselves

21:08 amalloy: why are you calling eval on a defrecord? like, agreed it probably shouldn't behave this way, but...

21:08 gfredericks: record literals in the code get eval'd right?

21:09 jamii: amalloy: I'm splicing a record into a macro. Then trying to figure out why the result has a map in it.

21:10 amalloy: https://www.refheap.com/paste/6177

21:12 I think record literals with zero args are broken and splicing in macros is just one of the places it shows up

21:13 gfredericks: jamii: this isn't actually a blocker for you, right? you could emit a call to the constructor instead?

21:13 amalloy: well '(run NIL empty-registers) isn't the same as `(run ~NIL ~x), it's the same as `(run ~'NIL ~x)

21:13 jamii: gfredericks: I'm just playing around anyway so its not blocking anything important.

21:14 amalloy: ok, say we do this the other way around

21:15 amalloy: huh, thats interesting - this actually works

21:16 https://www.refheap.com/paste/6178

21:17 But this doesn't: https://www.refheap.com/paste/6179

21:17 Sgeo: I should set up an IRC bot based on .... a UMLbox bot in another channel

21:17 Would be nice to have a Clojure bot where defmacro works

21:17 amalloy: of course. in the first, instr is the symbol NIL, and in the other it's the value of NIL in your namespace

21:18 you want the symbol, not the value, so what happens when you eval a record shouldn't be relevant to you

21:18 jamii: amalloy: Right. Except I am actually using eval at runtime.... :)

21:19 amalloy: Ok, so what I'm actually trying to probably do doesn't make much sense and I'm not at all blocked on this. I'm just trying to verify that the eval behaviour is wrong.

21:19 amalloy: looks wrong to me

21:19 jamii: amalloy: ok

21:19 So I'm sane

21:19 Huzzah

21:20 amalloy: the code that ran into this was (eval `(fn [registers#] (run ~(vary-meta form assoc :tag (class form)) registers#)))

21:20 amalloy: Since I have to run those instructions a couple of thousand times I was wondering if it would be faster to replace them by a clojure where the dispatch was already known

21:21 amalloy: But it doesn't work because the zero-arg instructions eval to {} in the above

21:21 Sgeo: o.O eval is broken?

21:21 jamii: Sgeo: I think so? Records should probably eval to themselves

21:24 Aha - http://dev.clojure.org/jira/browse/CLJ-1093

21:25 Workaround - (eval (assoc NIL :dummy nil))

21:34 wingy: is it possible to use clojure to make android apps?

21:35 Raynes: Yes.

21:36 https://github.com/alexander-yakushev/lein-droid

21:36 wingy: thx

21:47 tbaldridge: so, I'm trying to install the clojure-starter-kit for emacs 24.2 on osx (in terminal mode)

21:47 for some reason it's not doing anything at all

21:47 I'm doing this: https://github.com/technomancy/clojure-mode/blob/master/README.md

21:48 but emacs complains that "clojure-mode is not available for install"

21:48 any ideas?

21:52 so for the logs...aparently it's M-x package-install starter-kit

22:39 Sgeo: Oh hey, Clojure Conj is in NYC?

22:40 Oh, it differs every year. Darn.

22:42 TimMc: Has it ever been in NYC?

22:44 amalloy: no

22:44 TimMc: That's what I thought.

22:45 Sgeo: Hmm, what is http://www.meetup.com/Clojure-NYC/events/16166984/

22:54 ToBeReplaced: what does "Core was generated by `java -client -XX:+TieredCompilation -Xbootclasspath/a:/home/ToBeReplaced/.lein/'" mean?

22:55 TimMc: Sgeo: "NYC Clojure Users Group" - "Clojure Conj 2011 Roundup"

22:55 Deviously misleading title, I'll agree.

22:56 Sgeo: Oh.

22:56 Well, hey, at least I learned there's an NYC Clojure users group

22:56 Wonder if I should try going

Logging service provided by n01se.net