#clojure log - Mar 22 2012

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

0:04 * muhoo listens intently for the answer to rhc's question

0:05 gfredericks: I think there's something about (def foo #'bar)?

0:05 * gfredericks doesn't know what he's talking about but if nobody else is gonna say anything...

0:10 brehaut: #' is var quote; #' is equivalent to (var bar)

0:11 if you quote the var, you get the var itself rather than whatever it points to

0:11 * gfredericks can't tell if brehaut is supporting his idea or not

0:11 brehaut: so if the var is updated (eg, by def) then anything calling through that var gets the new version

0:11 yes

1:35 y3di: how do you go about finding a mentor?

2:14 coltnz: hi can anyone suggest the idiomatic way to prevent this:

2:14 user[9]: (apply str/trim []) --------------------------------------------------------------------------- clojure.lang.ArityException: Wrong number of args (0) passed to: string$trim

2:16 ivan: coltnz: how many items can your vector have?

2:16 coltnz: well it can have 0+ and its the zero bit thats the problem

2:17 ivan: (user=> (map clojure.string/trim ["hey " " hi"])

2:17 ("hey" "hi")

2:17 and really? it doesn't take more than 1 arg here

2:18 coltnz: hmm maybe i do want map

2:45 Raynes: You do.

2:56 rudyl313: is (def ^{:private true} sym "val") the only way to make the sym symbol namespace private?

5:22 muhoo: (= fun-fun-fun (reduce + [clojure incanter couchdb clutch]))

5:22 clgv: muhoo: what are you doing?

5:27 amalloy: aw, (apply + ...) is surely more appropriate here

5:27 you're not adding pairwise, you're throwing them all into a big pot and stirring

5:28 alcy: folks, is there something like a Learn you some clojure apart from tryclojure(which was great while it lasted!)

5:29 Raynes: Damn. Now I feel bad for not writing more tutorial.

5:30 alcy: http://java.ociweb.com/mark/clojure/article.html is a pretty nice introduction.

5:31 alcy: Raynes: yep, tryclojure site suggested that, just didnt feel as awesome as tryclojure :) will work with it anyway

5:31 Licenser: dun dun dun

5:32 Raynes: http://www.unexpected-vortices.com/clojure/brief-beginners-guide/ I think this is more recent.

5:32 Not sure of quality though.

5:32 alcy: I apologize. :(

5:32 I'd write more tutorial but I'm also writing a book that will be freely available online and thus a bit more of a resource than tryclojure.

5:33 I was hoping somebody else would come along and add some tutorial but nobody has done so.

5:33 alcy: Raynes: you wrote tryclojure ? awesome, thanks for that! good to know about the ebook, should be nice

5:33 Raynes: I did. With plenty of help, of course. :)

5:34 alcy: i have played with higher order perl some and so this looks familiar a bit, will spend some time on data structures

5:36 Raynes: anyway, thanks for the hel

5:36 lol s/hel/help

5:36 Raynes: You're welcome for both the hel and the help.

5:44 clgv: alcy: get you a book ;)

5:46 Raynes: your second link seems to be more of a bootstrap summary for clojure ;)

8:19 casperc: I am messing around a bit with records, and I am wondering - is it possible to have a private field on the record which is not initialized when creating the record but loaded later?

8:34 fliebel: casperc: Why would you want to do that?

8:35 I suppose you could play some nasty scope tricks..

8:46 clgv: sounds too OOPy ;)

8:51 casperc: Yeah, it probably is too OOPy indeed.

9:50 solussd: so, I'm experimenting with Noir for a project that will have both an html front-end and a RESTful interface. Does anyone know how I can check the "Accept" header to see if it is, e.g., application/json, so I can determine what format to respond with?

9:51 cemerick: solussd: there are a couple of content negotiation libraries out there that work well with ring.

9:53 solussd: Something like webmachine is the Right Way to do stuff like this though. It's not done yet, but bishop looks promising: https://github.com/tnr-global/bishop

9:53 solussd: I was looking at the noir.request/ring-request function, which I think is suppose to return the request, but I haven't been able to squeeze headers from it. :/

9:54 cemerick: If it's actually returning the ring request, it must have :headers

9:54 solussd: hmm. i'll checkout the clojure web machine port, thanks

9:55 cemerick: Accept-* headers can get gnarly though. I wouldn't really want to parse them myself.

9:56 solussd: i was hoping to build on top of noir for both the web and rest side of things and dip down into the lower levels when needed

9:56 cemerick: there's no reason why you shouldn't be able to use noir where you want.

9:57 it's all ring handlers; from the readme of bishop, you should be able to map content types to ring handlers, including noir'rs.

9:58 solussd: k. I got some reading to do then. :D

10:11 ohpauleez:  lynaghk ping, again

10:17 fishmacs: I found clojure use vector instead list in many places, is it because of JVM?

10:19 solussd: fishmacs: it looks different than a list, so it stands out against the parentheses; it's more efficient to construct new vectors from existing ones when you're not adding to the front

10:19 RickInGA: fishmacs: probably lots of reasons, for me, I like not having to quote vector…. and what solussd said :)

10:24 fishmacs: I doubt syntax convenient is not a big reason for vector, seems a "modern" choice ?

10:26 RickInGA: fishmacs: the code seems a lot easier to read when it isn't all parens

10:26 fishmacs: RickInGA: yes, it is true. but is it main reason?

10:28 stuartsierra: By convention, Clojure uses Vectors instead of Lists to distinguish "data" from "code." |n Clojure syntax, Lists almost always mean "call a function, macro, or special form." Vectors are commonly used for things that are not directly executed, like function parameters. There are exceptions to this convention, notably in the `ns` macro.

10:29 ejackson: I figure also vectors are much like lists with the added advantage of O(1) lookup by index, rather than O(n).

10:29 fishmacs: stuartsierra, but in lisp, code is the data?

10:29 RickInGA: fishmacs: also, vector useful when you want to find things by index, and someitmes you want to add stuff at end. If you want to grow at front, use list and to hell with convention!

10:29 stuartsierra: fishmacs: Yes, but there's "data that represents code to be executed" (lists, usually) and "data that's just data" (vectors, usually).

10:30 fishmacs: ejackson: vector may waste many memory space

10:31 ejackson: i usually have more memory than time...

10:31 stuartsierra: Clojure's vectors and lists are both persistent tree-like data structures which make pretty efficient use of memory.

10:31 fishmacs: Oh, I think vectors are array-like?

10:32 stuartsierra: fishmacs: Clojure's vectors offer similar behavior to classical arrays (indexed, near-constant-time lookup) but they are actually trees.

10:35 fishmacs: thinks stuartsierra, I forgot vector is immutable

10:35 stuartsierra: yes, all Clojure's data structures are immutable and persistent

10:37 fishmacs: stuartsierra, you said both vector and list are tree-like, is clojure list the conventional FP list?

10:38 stuartsierra: fishmacs: It is not a conventional singly-linked list, if that's what you mean.

10:38 fishmacs: stuartsieera: yes,this is what I meant

10:38 stuartsierra: But Clojure also has sequences, which are an abstraction that behaves similarly to the lists in functional languages like Haskell.

10:42 _andrew_k: what about maps ?

10:42 fishmacs: is old list in functional language out of time? I had read some posts talk performanace penalty of list

10:43 patrikkarlin: depends on how you use it

10:44 ejackson: _andrew_k: maps are also perstistent, tree like structures

10:45 in fact they are trees under the hood

10:45 check out http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice/ and the link to Vectors

10:45 fishmacs: why clojure give up conventional list as its basic data structure?

10:46 patrikkarlin: most of my code is lists

10:46 clgv: fishmacs: immutability and structure sharing between original and "mutation"

10:47 fishmacs: clgv: I think conventional lists also provide immutability and sharing

10:48 clgv: fishmacs: a simple single linked list can't do that

10:50 fishmacs: clgv: single linked lists can share their tails

10:50 ejackson: yeah, but tries can share anything and are very fast.

10:50 clgv: fishmacs: but they could be edited as well.

10:52 djwhitt: hmm... isn't this the implementation: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentList.java

10:52 stuartsierra: I take back my earlier statement. Clojure's lists ARE singly-linked lists, with a few extra features.

10:53 djwhitt: yeah, was about to say, that looks a lot like a singly linked list to me :)

10:53 stuartsierra: djwhitt: I was thinking of vectors instead.

10:53 ok, time for me to get back to work

11:02 fishmacs`: think about (vec (map + [1 2 3] [4 5 6])), I have to convert back and forth between vector and sequence, I must pay some price?

11:03 ejackson: fishmacs`: map works with seq, which is very fast to create,

11:04 so you get a seq over [1 2 3] and [4 5 6], and then construct a vector for the results

11:04 no more than any other immutable system

11:06 fishmacs`: ejackson: so if clojure is pure, it would select sequence as its basic data structure?

11:06 ejackson: sequence is basic abstraction

11:06 but its not a datatype

11:07 cemerick: fishmacs`: actually needing a vector instead of a sequence is rare

11:07 fishmacs`: I mean an implement of the abstraction, just like the implement you get from [1 2 3] and [4 5 6]

11:10 yeah, I'm a newbie, just a little confusing about the choice of data type. I think imperial languages's basic data types are array-like, and functional languages's are singly-linked list

11:11 TimMc: fishmacs`: Traditionally, yes. Not with Clojure.

11:12 $google clojure vector tree 32-way

11:12 lazybot: [Understanding Clojure's PersistentVector implementation | Higher ...] http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

11:13 fishmacs`: think you guys, I need read a lot more to understand the decisions made under hood

11:15 TimMc: fishmacs`: All you really need to know here is that vectors, maps, and sets in Clojure have O(n log n) insertion time.

11:15 ejackson: where log is base 32... so FAST

11:15 TimMc: Basically linear.

11:16 clgv: TimMc: errm, n*log n? that sounds not right

11:16 fishmacs`: O(log n)

11:17 rhc: yeah n log n for a vector would be pretty bad

11:17 considering non-immutable usually has o(1)

11:17 ejackson: yeah, log_32 n.

11:17 rhc: and its supposed to be "equivalent", right?

11:18 mknoszlig: rhc: in practice, yes

11:19 fishmacs`: rhc: what supposed to be equivalent? O(1) and O(log_32 n)?

11:19 rhc: fishmacs`: right, that's my understanding

11:19 ejackson: ,(/ (log 10000) (log 32))

11:19 rhc: considering log_32 2^32 is 6

11:19 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: log in this context, compiling:(NO_SOURCE_PATH:0)>

11:19 rhc: means, a pretty bad case will result in 6 tree traversals

11:20 mknoszlig: rhc: in big O, 6 = 1 ;)

11:20 ejackson: ,(/ (Math/log 10000) (Math/log 32))v

11:20 clojurebot: 2.65754247590989

11:20 rhc: mknoszlig: well yes, once you know n

11:20 ejackson: log_32 is a strong function

11:20 rhc: in bigO O(log n) and O(log_32 n) are equivalent too

11:20 TimMc: Eep, O(log n), right.

11:20 rhc: luckily people are realizing there's more than just 1, log n, n log n, and quadratic of n

11:21 especially whne you have an awesome fast O(1) alg with a massive constant time

11:21 so its super fast for n = 2^32 and slow for n = 100

11:21 TimMc: Right, that's why we have benchmarks. :-)

11:21 rhc: and profiling :)

11:21 same thing I guess :D

11:21 mknoszlig: rhc: that's two different aspects of optimization, no?

11:21 TimMc: Nah, profiling is better.

11:22 err

11:22 Ignore me today, I am having trouble with words.

11:22 What I *meant* was, performance tests on your real data is better than benchmarks on made-up data.

11:23 rhc: i figured as much

11:39 Bronsa: hmhm

11:39 I have a question.

11:39 suppose i define a protocol P and extend it to String from the namespace a

11:40 if i extend it again from a namespace b, is there anyway to refer to the implementation defined in the namespace a?

11:40 *any way

11:42 TimMc: You're trying to extend the same protocol to the same class twice?

11:42 Bronsa: yes

11:42 it's just ipotetic, not really sure if this will ever happen to be needed

11:47 TimMc: I haven't worked with protocols, but my understanding is that extending protocol P to type T is only done when you own either P or T.

11:48 So in this case you'd do the extension in the same ns where you define the protocol and be done with it.

11:52 konr: What's the right way to add a library with its current version to project.clj? Manually copying the line from clojars.org? If so, is there a way to automatize that?

11:57 clgv: konr: what do you want to automatize? resolution of the current version?

11:57 konr: clgv: yes

11:58 fishmacs`: q

11:58 clgv: konr: but often you will have to decide which version you really want to use

11:58 e.g. basic question: stable vs snapshot

11:59 konr: lein search should help you finding out what versions exist

12:04 konr: clgv: thanks!

12:08 cemerick: TimMc: You can extend P to T even if you don't own P or T. That's one of the big draws of protocols.

12:23 romanandreg: hey dnolen, where can I find the source code for PersistenVectors in cljs?

12:23 dnolen: romanandreg: https://github.com/laczoka/clojurescript/commit/a1409dfe6a1dfb4c3f35aba69bd43a0e281af5a5

12:24 romanandreg: dnolen: awesome! thanks

12:39 TimMc: cemerick: But is that wise?

12:41 cemerick: TimMc: well, if you need some type to participate in a protocol, there aren't a lot of alternatives.

12:41 If one of the owners does introduce support later on, you can retract your extension.

12:47 technomancy: isn't that the moral equivalent of monkeypatching though?

12:48 not that you should never do it, but that it renders protocols advantages over monkeypatching void

12:51 dnolen: technomancy: not quite. protocols mean something. If someone else extends String to ISeq, not a big deal.

12:52 technomancy: dnolen: well, monkeypatching is also not a big deal when there are no collisions.

12:53 dnolen: technomancy: not even remotely the same guarantee.

12:54 even if several implementations replace one another, in the protocol case - who cares?

12:54 technomancy: presumably the one that loses cares?

12:54 dnolen: technomancy: why?

12:55 if someone is side-effecting in an ISeq implementation - that's their problem.

12:55 they have a broken implementation.

12:55 technomancy: sure, but what if the broken one wins?

12:55 dnolen: technomancy: one library you'll never use again.

12:55 technomancy: yes

12:55 so... exactly the same as monkeypatching

12:56 dnolen: technomancy: no because in the monkeypatching case there no zone of agreement.

12:57 technomancy: it's still easy to get bitten by subtle differences

12:57 probably not on ISeq, but as a rule

12:58 dnolen: technomancy: as a rule it should never matter. if it does you probably shouldn't be writing a protocol.

12:59 technomancy: well that won't be a problem for me then =)

13:02 wmealing_: I'm sure there is a better way to do this (functionally) can someone help me with the terms/ideas i should be learning to implement it correctly ( http://hastebin.com/qakobinudu.lisp )

13:04 lpetit: Just released Counterclockwise (An Eclipse Plugin for Clojure projects) version 0.6.0. http://code.google.com/p/counterclockwise/wiki/CuttingAReleaseRecipe

13:04 wmealing_: its short, its sweet, and you know it complete known as fizz buzz or something something

13:04 dnolen: lpetit: cool! is that the right url?

13:05 lpetit: crap

13:05 Counterclockwise Release Note: http://code.google.com/p/counterclockwise/wiki/ReleaseNotes?ts=1332435665&updated=ReleaseNotes

13:05 dnolen: thx

13:05 devn: ugh, parsing the clojure cheatsheet is a bummer

13:05 lpetit: crap again

13:06 What's wrong with me today :)

13:06 http://code.google.com/p/counterclockwise/wiki/ReleaseNotes

13:07 dnolen: lpetit: neat that you've got the beginnings of ClojureScript support in there

13:07 lpetit: dnolen: as stated, really minimalistic, but definitely on the roadmap, right after Leiningen support

13:07 wmealing_: sweet, i shall try it.

13:09 dnolen: wmealing_: https://gist.github.com/2159796 is how I would do it.

13:12 wmealing_: looking now dnolen

13:12 ah

13:13 thanks, didnt know about else being used that way

13:18 technomancy: https://blogs.oracle.com/jrose/entry/value_types_in_the_vm <- interesting that John Rose says it's dangerous to allow identity? to be called on value objects

13:19 cemerick: lpetit: Do you know what "real" cljs support would look like?

13:19 i.e. I wonder if, once lein tasks are available, that simply "use lein-cljsbuild" would be enough.

13:20 lpetit: cemerick: not really. The tricky part will be if one wants to use the REPL, right ?

13:20 dnolen: cemerick: I would think so, there should be support to launch ClojureScript REPLs (Rhino, Browser) as well

13:21 lpetit: what does lein-cljsbuild provide, in short?

13:22 dnolen: lpetit: tricky? since you control the environment you can just fire up a regular Clojure REPL and start the Rhino CLJS REPL

13:22 lpetit: or start the Clojure REPL and start the browser REPL on the user defined port

13:23 cemerick: lpetit: auto-compliation of cljs files, among other things

13:23 lpetit: cemerick: this auto compilation of cljs files could be easily accomplished via a ClojureScript Eclipse Builder, right?

13:24 cemerick: or does lein-cljsbuild embed too much goodness related to this auto compilation stuff to be ignored? (or maybe this can be extracted in a non-leiningen-based dependency?)

13:24 cemerick: or maybe just use lein-cljsbuild :)

13:24 cemerick: lpetit: probably, but I'd think cljs is moving too fast yet to expect such a thing to keep up vs. an easily-upgradable lein plugin

13:25 lpetit: cemerick: I understand, and that's part of the idea of not having done cljs support first, and rather leiningen first

13:25 cemerick: right

13:25 lpetit: cemerick: My concern is wrt to Windows support in third-party leinigen plugins

13:26 cemerick: whereas I know that Eclipse handles OS specifics very well

13:26 cemerick: It's a valid concern, but hardly one exclusive to eclipse.

13:26 i.e. if cljsbuild falls down on windows, that'll get noticed pretty quickly I'd think

13:27 lpetit: cemerick: no option is discarded atm. We'll see what the state of the art is when a first round of leiningen support is done, and there's room to work on cljs support

13:28 cemerick: re: REPLs, we can quite trivially run a cljs repl, but a lot of the expectations around REPLs fall down in that scenario. i.e. no completion, no go-to-declaration, not sure what sessions look like, no potential (or use for?) rich content returns…

13:29 it's sort of an uncanny valley situation where, it's a REPL all right, but everything is different by one or two degrees.

13:29 technomancy: no metadata ಥ_ಥ

13:29 cemerick: Right. Insofar as everything we've built for Clojure depends on a dynamic running introspectable environment…

13:30 dnolen: technomancy: cemerick: metadata is preserved. introspective facilities is an open ticket on JIRA.

13:32 cemerick: What do tools look like for Coffeescript? Is it an equivalent to cljsbuild + a console + a text editor + chrome inspector, or has anyone worked out anything more sophisticated than that?

13:33 dnolen: cemerick: CoffeeScript dev mostly like JS dev, with the added step that you start of the compiler to watch files.

13:33 lpetit: CCW Version 0.5.0 has been downloaded 7093 times, let's see whether Version 0.6.0 can do better :)

13:33 dnolen: cemerick: CLJS dev is already quite a bit more sophisticated if the tools support it - Emacs, SublimeText 2 is very good.

13:35 technomancy: dnolen: metadata on defns? or just metadata that's explicitly attached to data structures?

13:36 patrikkarlin: Oo has sublimetext 2 anny slime esk things?

13:36 dnolen: technomancy: all the usual stuff that can't exist in the evaluation environment lives in an atom - namespaces.

13:37 technomancy: cool; is that new-ish?

13:37 dnolen: technomancy: all that's required is a cljs.reflect|introspect to call back into the complier to request information

13:37 technomancy: no been there the whole time as far as I know.

13:38 technomancy: aha

13:38 lpetit: dnolen: there are a bunch of core functions which are not yet implemented, right, such as clojure.core/public-*, right ?

13:38 photex: so figured out that my inability to clojure-jack-in last night was that rlwrap was hitting SIGFPE when run from emacs

13:38 Zoka: lpetit: do you use latest nREPL in CCW 0.6.0?

13:39 photex: I had finally gotten around to installing it to get rid of the warning when running lein

13:39 lpetit: Zoka: this has been saved for CCW 0.7.0.

13:39 dnolen: lpetit: yes anything that requires reified vars/nses has not been implemented yet.

13:39 lpetit: Will be released as a BETA version soon, next thursday

13:39 photex: so heads up in case anybody hits the same issue

13:39 lpetit: Zoka: ^^

13:39 dnolen: patrikkarlin: not slime stuff, more like inferior lisp via SublimeREPL

13:40 Zoka: lpetit: Thanks

13:40 lpetit: dnolen: if I understand correctly, a new implementation, specific to cljs, of these functions can be written, based on the content of the atom you mentioned above?

13:40 photex: quick question for anyone who might know: clojure.java.shell <- is this the recommended way to launch and monitor long running processes?

13:41 I don't see an obvious mention of streaming output back into my app

13:41 should I just punt and look at native java solutions?

13:41 dnolen: lpetit: yes, we already have communication between compiler and runtime environment - we just need to extend it to support introspection.

13:42 technomancy: photex: yeah, leiningen had to reimplement clojure.java.shell since it assumes you're going to want to wait till the process exits

13:42 photex: cool, thanks technomancy

13:43 technomancy: photex: also, rlwrap should be disabled if it detects $INSIDE_EMACS

13:43 is that not the case for you?

13:43 lpetit: dnolen: I have existing code which uses the usual suspects in clojure.core for introspection. Is the intent of the issue mentioned above to implement those same usual suspects (so that my introspection code can work the same without adapting my code)?

13:43 photex: technomancy apparently not, I just built it from source though

13:43 at work I use CentOS 5.3

13:43 technomancy: photex: why from source?

13:43 photex: rlwrap

13:43 technomancy: the 1.x branch?

13:44 photex: I didn't pay attention actually

13:44 technomancy: the master branch doesn't use rlwrap

13:44 dnolen: lpetit: pretty much.

13:44 photex: I built rlwrap 0.37

13:44 dnolen: technomancy: wow, this is a cool feature of lein 2, http://sunng.info/blog/2012/03/my-favorite-feature-in-leiningen-2/ !

13:45 photex: oh, I'm using Leiningen 1.7.0

13:46 whenever I run lein I get the rlwrap warning; so I installed it and didn't notice the issue right away

13:46 at first I thought .emacs.d was hosed because of a power outtage

13:46 technomancy: dnolen: a transitive feature, if you will; that's all cemerick and xeqi.

13:46 but yeah, handy to have around for sure

13:46 dnolen: technomancy: that is RAD

13:47 photex: but then I realized that the SIGFPE error was prefixed by rlwrap:

13:47 so I renamed rlwrap to rlwarp.BAK in my ~/bin

13:47 problem disapeared

13:47 technomancy: photex: what version of emacs? maybe checking $INSIDE_EMACS isn't reliable.

13:48 photex: I had to build Emacs from git

13:48 I think it's 24.0.x

13:48 xeqi: dnolen: got to be careful with that. if you pull in two dependencies seperatly you can get some conflicts if they rely on different versions of a sub-dependency

13:48 but it works well enough

13:48 photex:

13:48 xeqi: for simple playing around with a library

13:49 cemerick: xeqi: we'll be able to warn or fail in such scenarios eventually

13:49 technomancy: photex: weird. can you open an issue on github for that?

13:49 photex: sure thing

13:49 technomancy: definitely shouldn't be a problem

13:49 cemerick: and here I considered pulling the add-classpath stuff out of pomegranate some while back :-P

13:50 dnolen: technomancy: the speed at which lein2 launches is a repl is pretty slick.

13:52 technomancy: dnolen: there was a bug fixed in 1.3 that allows us to put the whole uberjar on the bootclasspath; that's where most of the boost is coming from

13:53 ldopa: ls

13:55 i'm surprised that doesn't happen more often to people using term-mode/rcirc

13:55 technomancy: ldopa: different color themes helps =)

13:57 cemerick: just as long as it's not a password or copy/paste snafu... ;-)

14:00 stuartsierra: Just noticed that lein 1.x highlight matches parens and lein2 doesn't. Is that a feature of rlwrap?

14:02 technomancy: stuartsierra: yeah, lein2 uses jline2, which has nearly all the features of rlwrap, but apparently not all of them

14:02 stuartsierra: ok

14:03 technomancy: Minor issue. Great work all around!

14:04 technomancy: thanks

14:04 the repl stuff was all Raynes and trptcolin though

14:04 dnolen: pure awesomeness is what that is.

14:04 technomancy: and also some scala guys making jline2 actually a respectable rlwrap replacement

14:05 stuartsierra: We've been making a lot of use of custom tasks and `lein run -m` for bigger projects. It makes a nice way to portably invoke some Clojure code.

14:05 technomancy: for a while we were using a scala-specific fork of jline even

14:05 stuartsierra: cool. are you aware of the trampoline higher-order task?

14:06 saves memory in that kind of scenario

14:06 stuartsierra: aware it exists, but haven't explored it

14:06 cemerick: almost no one uses it

14:06 viz. the survey

14:07 * stuartsierra reads docs

14:07 stuartsierra: So it still launches 2 JVMs, but only leaves one running instead of two?

14:07 technomancy: stuartsierra: yeah, it's like clojure.core/trampoline, but for JVMs instead of functions

14:08 stuartsierra: cool

14:08 * stuartsierra has time to play while waiting for a very slow integration test

14:10 cemerick: I've been using :eval-in :classloader for one project to optimize the startup time

14:11 technomancy: cemerick: there have been concerns that the classloader stuff conflicts with the bootclasspath; have you found that to be the case?

14:11 I guess it would only manifest if you needed a different version of Clojure from Leiningen itself

14:11 cemerick: I haven't hit a problem.

14:12 Although yes, it could easily be a problem if your project shares a dep with one of Lein's.

14:12 stuartsierra: I don't think we'll ever be able to have two different versions of Clojure in the same ClassLoader.

14:12 Hierarchical ClassLoaders suck.

14:12 technomancy: cemerick: I wonder if lein could be smart enough to switch that on if it can determine it's safe

14:12 cemerick: well, :eval-in :classloader uses a different classloader.

14:12 pandeiro: has anyone done a wrapper for geotools?

14:13 stuartsierra: cemerick: oh, so it doesn't inherit anything from Lein's classloader?

14:14 cemerick: stuartsierra: no, it does, but that's not trying to have different revs of Clojure in the same classloader.

14:14 Hrm, actually, that might not be right.

14:14 Classlojure could be (or get to be) crafty enough to ignore the bootclassloader too.

14:15 technomancy: cemerick: I definitely need to do some science on that before the final 2.0.0

14:15 stuartsierra: To paraphrase Sartre, Hell is other people's ClassLoaders.

14:16 cemerick: right, so it doesn't; just gloms onto the ext classloader at the moment.

14:17 stuartsierra: nice

14:18 technomancy: this is a broader problem that can't be solved statically; remember my ranting about the dynamic changes that lein.repl does

14:19 technomancy: if you would refresh my memory?

14:19 cemerick: I'll bet that's just the tip of the iceberg.

14:19 lein.repl adds nrepl vXXX (and others) to the project classpath, which might already contain vYYY.

14:19 technomancy: oh, sure

14:20 but isn't that addressed by task-specific profiles that defer upon conflict?

14:20 profile merge logic already handles conflicting deps

14:20 cemerick: Not given multiple classloaders, or middleware magic.

14:20 Or, I wouldn't think so.

14:21 technomancy: I think middlewares that touch :dependencies will only be safe if they use merge-profiles

14:21 and perhaps we can only use an in-process classloader if we detect that there are no conflicts between the project and Leiningen itself

14:22 cemerick: You could always shade everything in leiningen's uberjar!

14:22 * cemerick *ducks*

14:23 technomancy: ಠ_ಠ

14:23 cemerick: did you get a new emote minor mode or something? :-)

14:25 technomancy: https://github.com/technomancy/dotfiles/blob/master/.emacs.d/phil/cosmetics.el#L38

14:26 joegallo: omg. slow clap.

14:26 fliebel: Clojure does class loading and code generation at runtime, right?

14:28 arohner: clojurebot: inc technomancy

14:28 clojurebot: Cool story bro.

14:28 arohner: who does that?

14:28 scriptor: (inc technomancy)

14:28 lazybot: ⇒ 22

14:28 stuartsierra: fliebel: yes

14:28 arohner: ah, of course

14:29 fliebel: stuartsierra: Ok. To bad... I'd like to run Clojure on the LEGO NXT, but it does some statick linking to save space.

14:29 stuartsierra: fliebel: if you AOT-compile everything then you don't need any run-time classloading.

14:30 But the JARs are still bloated with run-time metadata.

14:30 That's why Clojure on Android still doesn't work too well.

14:31 fliebel: stuartsierra: Right... I wonder what JVM language other than Java could run on the NXT.

14:31 technomancy: fliebel: mirah is nice for a "it doesn't hurt as much as java" without bringing along runtime baggage

14:32 but it doesn't have a repl. =(

14:32 fliebel: technomancy: That's one of the pages I have open in my browser at the moment

14:32 technomancy: fliebel: for me personally, it's hard to have fun in a language that doesn't have a repl.

14:32 fliebel: technomancy: Yea, I miss the repl on NXT. pbLua is the only one that has it, as far as I know.

14:33 pbLua has other shortcomings though.

14:33 technomancy: I think Mirah is valuable for targeting Android because currently the other existing options are awful, but I have a hard time recommending it recreationally until it gets a repl.

14:35 fliebel: technomancy: How would you do a repl, without runtime deps?

14:35 technomancy: fliebel: clojurescript manages it somehow. =)

14:36 stuartsierra: The ClojureScript REPL is brittle and hackish compared to the Clojure REPL.

14:36 For now.

14:36 fliebel: technomancy: But JS has a repl of itself, and ClojureScript has quite some runtime deps right?

14:36 technomancy: yeah, that may not be a good example since JS has eval

14:38 fliebel: the repl wouldn't be an integral part of the language; repl-enabled mirah would boot much more slowly than raw mirah

14:38 fliebel: technomancy: I guess nailgun is interesting... I don;t quite remember what it is though.

14:38 technomancy: but for development you wouldn't care

14:38 fliebel: technomancy: It can generate java source, so maybe beanshell is an option?

14:39 technomancy: maybe. I haven't looked into it

14:39 sandover: dnolen: you tweeted the other day that sublime text is not a bad clojure dev environment. tweet more on this? I've been frustrated by lack of indent support, funny key cmds (ctl-p ctl-n), hanging repls, etc.

14:40 emezeske: fliebel: I think nrepl/jark supercede nailgun

14:55 pcavs: Is it possible to use a macro to do something like (defmacro my-macro [obj foo] (.myMethodCalled~foo obj)) such that (my-macro obj "Bar") ==> (.myMethodCalledBar obj) ? Messing around it seems not, so I was wondering if there is a way to do this?

14:56 patrikkarlin: use the syntax (. obj myMethodCalledBar)

14:56 pcavs

14:56 emezeske: ,(symbol (str ".myMethodCalled" "Bar"))

14:56 clojurebot: .myMethodCalledBar

14:56 pcavs: awesome, many thanks.

14:57 * emezeske has no idea if that is suitable.

14:57 pcavs: haha, we'll find out

14:58 emezeske: ,`(~(symbol (str ".len" "gth")) "hello")

14:58 clojurebot: (.length "hello")

14:58 emezeske: ,(eval `(~(symbol (str ".len" "gth")) "hello"))

14:58 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

14:58 pcavs: no eval I think in the jailhouse

14:58 emezeske: Ah, yeah

14:59 pcavs: trapped like rats!

14:59 ClusterCat: Hi, as an emacs beginner, how do I get the output (like a failure stacktrace) in emacs when using C-c C-k?

15:01 slyrus: technomancy: any idea which version of slime I should be using with swank-clojure 1.5.0?

15:02 patrikkarlin: clusterCat: u can use C-c C-l instead it showes a stacktrace

15:02 i had newer used C-c C-k before :S

15:03 arohner: anyone have a good workflow for reviewing ~100 commits in GitHub?

15:04 photex: masters of lein: I'd like to access a namespace in my project from control.clj but the classpath doesn't seem to get setup correctly

15:04 is this a project.clj issue, or the plugin not being setup to handle this?

15:04 amalloy: arohner: just get a rubber stamp like http://www.webdesign-guru.co.uk/icon/wp-content/uploads/ok.gif

15:05 photex: more specifically, I'd like to just access libs I depend on in project.clj

15:05 but I'm getting stacktraces out the wazoo

15:05 ClusterCat: patrikkarlin, not for me. In fact no buffer shows any output. It is an clojure/seesaw programm. When running via 'lein run -m foo.core' it throws an exception which I don't see in emacs.

15:06 amalloy: seriously though, aside from using the compare/diff view to get all the commits in one place, i don't have any great ideas like a way to mark commits as good

15:06 arohner: my main issue is just viewing them in something that has a good workflow for reading, like google reader

15:07 photex: before I file an issue with the plugin project I'd like to make sure it's not an issue with my project setup

15:07 arohner: but if I add a github RSS feed, I only get ~30 commits, I can't scroll back in time

15:07 amalloy: arohner: https://github.com/4clojure/4clojure/compare/e5e4c920...8f7e5aa2 ?

15:07 arohner: yeah, I find that really annoying. Reaching for the mouse, waiting for page refreshes, etc

15:08 no hotkeys to visit next commit

15:08 amalloy: open them all in tabs, C-w to close tabs you're done with

15:08 arohner: and that munges commits together, rather than reading one at a time

15:09 amalloy: or do it from git instead of github - git log --patch-with-stat a...b

15:09 arohner: yeah, I'm playing with magit's log viewer now

15:09 patrikkarlin: ClusterCat: what happends if you import the ns from the slime repl and run?

15:09 emezeske: amalloy: Thank you for bringing --patch-with-stat to my attention. Awesomeness.

15:09 mk: arohner: what are the problems with how you expect to do it? just the delay between reviews?

15:10 arohner: mk: my ideal would be something like google reader. hotkeys to move between commits, and marking read vs. unread

15:10 mk: I'd use google reader if I could get it to display more than 30 commits when adding a new feed

15:11 slyrus: or, put another away, how do I keep my clojure process from dying soon after accepting my first C-c C-k?

15:11 mk: perhaps you could mess with the feed you give to the reader

15:11 yahoo pipes lets you alter the feed in various ways, maybe you could cut off the most recent N, and do it in 4 batches, or something

15:13 ClusterCat: patrikkarlin, it throws a class not found o.O

15:14 patrikkarlin: clusterCat: witch is not the exeption you get by running it?

15:16 ClusterCat: patrikkarlin, no, when I run the program via lein, I get an AWT-whatever-exception, a seesaw related error. I think I'll try to set up a debugging buffer if I find out how :-D

15:19 patrikkarlin: clusterCat: have you changed you deps sins you started the slime session?

15:21 ClusterCat: patrikkarlin, nope. Maybe I am using something wrong? I start emacs foo.clj, M-x clojure-jack-in, then C-c C-k. If everthing is correct a swing frame is displayed. If there is an error, I see absolutely nothing.

15:22 dnolen: sandover: https://github.com/swannodette/cljs-demo

15:23 patrikkarlin: theres a slime events buffewr

15:23 buffer*

15:25 tacoman: everyone in the Haskell community (or at least on Reddit) seems to think monads are the best thing to ever happen to FP, whereas I've found a few tutorials on them from Clojurians, but they seem to be mostly ignored. is there any real point to them in a Clojure program/are they worth learning about, practically?

15:26 emezeske: tacoman: There was a nice talk at Clojure/West about using the state and maybe monads for implementing DSLs

15:26 scriptor: tacoman: if you read the reddict comments from those who know their stuff, monads are by far *not* the most important things on FP

15:26 patrikkarlin: the core.logic libary sems to be monadic

15:26 amalloy: tacoman: they're neat and something clojure people wish they understood better. but they're less useful/easy/necessary than they are in haskell, so we mostly wind up not getting them

15:28 dnolen: tacoman: Haskell absolutely needs them. They aren't the best anything. They are a thing.

15:30 sandover: monads are a solution to the problem of how to tractably do operations that have side effects in a purely functional language. Clojure isn't purely functional.

15:30 tractable isn't quite the right word

15:30 amalloy: sandover: that's overly specific. monads do lots of things that aren't related to state at all

15:31 sandover: maybe, but what they do that's actually _important_ is save haskell's pure functional bacon! ;)

15:42 llasram: Eh. The sequence and maybe monads are pretty important too

15:43 amalloy: right. i kinda assume sandover has never written any haskell (not that i've written much)

15:46 sandover: i've written some haskell, though not for production. i enjoy & respect the cult of monads, though I think it's beneficial not to take it too seriously.

15:47 it's an amazing hammer that is still looking for the right nails.

15:49 emezeske: The maybe monad definitely seems like the right nail

15:49 sandover: beyond pure functional languages, do you think?

15:49 in them, for sure.

15:50 emezeske: Yeah, I definitely think

15:50 _andrew_k_: we can use monads not only in pure functional languages

15:50 we use list and set monads in almost every language

15:51 emezeske: Whenever you are transforming some value with a bunch of operations, any of which might return "no value", the maybe monad is great

15:51 _andrew_k_: exception is a kind of monad, too

15:52 monads is more about how we process the data

15:52 sandover: are there any monads in clojure core libraries?

15:52 _andrew_k_: yep

15:52 sandover: (not implied ones, formally defined ones)

15:52 dakrone: sandover: https://github.com/clojure/algo.monads is used in a few

15:52 sandover: monad-as-design pattern doesn't count

15:53 dnolen_: sandover: not that I'm aware of.

15:55 _andrew_k_: in 1.2 there was clojure.contrib.monads

15:58 llasram: https://github.com/clojure/algo.monads is a 1.3 official contrib library

15:58 sandover: understood; that's the hammer.

15:59 llasram: Oh, sorry

15:59 Hah!

15:59 sandover: :)

15:59 llasram: I only saw _andrew_k_'s comment 1.2

16:04 _andrew_k_: i played with it last time in 1.2, and didn't know what it's now .. )

16:10 mk: what's the difference between a symbol and a var?

16:10 dnolen_: mk: a symbol just another kind of Lisp value.

16:10 brehaut: a var is a reference type, a symbol is just an identifier

16:10 patrikkarlin: symbol is a data type a var is a reference

16:11 amalloy: in brief: a symbol is a name, a var is a name and a container

16:11 Raynes: And amalloy is a genius.

16:11 Bow to him.

16:12 mk: so x is a symbol. It's like "x", or 99, or whatever, but it's a value that tends to be used by the "language" itself more than anything

16:12 * ibdknox bows

16:13 mk: javascript blurs this, for example, by having maps everywhere: .foo is actually "foo", but lisp distinguishes between strings and symbols - right?

16:13 and keywords are just like symbols...

16:13 aperiodic: keywords and symbols have completely different evaluation symantics

16:14 mk: but they are both just values, and values of different types, right?

16:14 dnolen_: mk: many values self-evaluate at the REPL, an *unquoted* symbol at the REPL will be resolved - the var will be found and the value it contains returned.

16:14 ,'first

16:14 vs.

16:14 clojurebot: first

16:14 dnolen_: ,first

16:14 clojurebot: #<core$first clojure.core$first@5396e1>

16:14 pandeiro: is there a way to make clojure-jack-in recognize the repl namespace in :repl-init and start there?

16:15 amalloy: mk: yes, they are. dnolen's point is about what happens when you attempt to evaluate one (eg by typing it in at the repl or as source code)

16:15 technomancy: pandeiro: not currently

16:15 mk: I'm reading an intro article that says def returns a var - I think this is confusing, because why not just bind to a symbol and return the symbol?

16:16 dnolen_: mk: symbols are not containers, their just regular Lisp values like I said above.

16:17 mk: right, but nothing is really a container, not even a list (it's just a value with relations to other values)

16:17 dnolen_: mk: vars are containers

16:17 _andrew_k_: symbols are the values themselves, var it's a label of container

16:17 dnolen_: ,#'first

16:17 clojurebot: #'clojure.core/first

16:17 dnolen_: ,(type #'first)

16:17 clojurebot: clojure.lang.Var

16:17 mk: if I evaluate a symbol, don't I get the bound value?

16:17 _andrew_k_: you get the symbols itself

16:17 dnolen_: mk: symbols don't self-evaluate at the REPL.

16:18 mk: I'm not sure I follow. If I type x, it evaluates to 5 because I did (def x 5) earlier

16:19 so where does the var come in?

16:19 TimMc: mk: That's because it is compiled.

16:20 dnolen_: mk: symbol -> var -> var's value

16:20 mk: quoted symbol -> symbol

16:20 Bronsa: it's not completly true that symbol -> var, isnt it?

16:21 mk: oh. Why not symbol -> bound value?

16:21 TimMc: Bronsa: That's the resolve step

16:21 Bronsa: it's more like the evaluator when encounter a symbol, resolves to a var

16:21 dnolen_: mk: because it's useful to manipulate symbols by themselves and not their values.

16:22 mk: dnolen_: what do you mean? Presumably I'd still be able to quote the symbol to just get the symbol

16:23 dnolen_: mk: macros, Clojure itself is defined in terms of being able to manipulate data structures and values - including symbols.

16:23 mk: ok, I follow so far

16:24 Chousuke: mk: in clojure, symbols are just names for things. vars are the actual containers of values

16:24 mk: why have symbol -> var -> value, instead of symbol -> value?

16:25 Chousuke: but how does one know which var corresponds to which symbol?

16:25 ldopa: mk: both concepts exist in other languages, but are usually implicit

16:25 _andrew_k_: var is reference, symbol is name of var

16:25 dnolen_: mk: some symbols may represent things which are not top level - think about locals

16:25 Chousuke: mk: the var has a name.

16:25 _andrew_k_: when you use a var - clojure looks up the var in namespace by symbol

16:25 dnolen_: mk: symbols may even get reused

16:25 mk: why not look up the value in the namespace by symbol?

16:26 dnolen_: mk: locals

16:26 Chousuke: mk: in namespace foo, bar and foo/bar resolve to the same var, but are not the same symbol

16:26 mk: dnolen_: not familiar - I'm somewhat new to the language

16:26 Chousuke: mk: if symbols held values, you'd get into trouble

16:27 dnolen_: mk: local bindings

16:27 _andrew_k_: ,(def x 5)

16:27 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

16:28 Chousuke: mk: it has the added benefit of making symbols immutable which helps when processing them

16:28 vars are the mutable things and they have mutation semantics like other ref types

16:28 _andrew_k_: ,filter

16:28 clojurebot: #<core$filter clojure.core$filter@c9c89f>

16:28 _andrew_k_: ,'filter

16:28 clojurebot: filter

16:28 _andrew_k_: ,#'filter

16:28 clojurebot: #'clojure.core/filter

16:28 _andrew_k_: the first is value - function

16:29 the second is symbol

16:29 and the third is var

16:29 mk: symbols would still be immutable, though namespaces would be mutable. If I def, do both x and namespace/x get bound to the new var?

16:29 Chousuke: mk: no, symbols don't get bound to anything

16:29 mk: but a var named namespace/x will get created

16:30 aperiodic: mk: i think the reason is that it if you went from symbol->value, then in order to implement local bindings, declaring a local binding would have to mutate the value of the symbol in whatever you're using to lookup symbol values, at whichi point the thing isn't really a local binding at all

16:30 Chousuke: and within that namespace, and any namespace that imports the x, the symbol x will *resolve* to that var

16:30 in another namespace, the symbol x might resolve to a different var

16:33 mk: what is a local binding?

16:33 Bronsa: let

16:33 mk: what does it do?

16:34 Bronsa: ,(let [x 1] x)

16:34 clojurebot: 1

16:34 aperiodic: mk: in (let [x 42] x), x is a local binding which has the value of 42 only in the body of the let

16:34 Chousuke: in that case, the symbol x is still only a name for the local value

16:34 Bronsa: it binds the symbol `x` to the value 1 in the lexical scope inside the let

16:34 Chousuke: its storage is a detail of the compiler implementation

16:35 in common lisp values actually do get stored in symbols, ie. they are pointers. but in clojure they're just names.

16:36 aperiodic: mk: if you haven't already, I'd highly recommend reading clojure.org's page on evaluation (http://clojure.org/evaluation)

16:37 mk: I'm somewhat familiar with how javascript does this, so maybe I'm thinking about it in the wrong way - in javascript, there is a chain of maps. Failure to resolve a symbol (in js, a string) in the first map means that the parent map will be checked, and so on

16:37 pandeiro: iwillig: do you use geoscript with clojure 1.3? i can't get geoscript.geometry to evaluate without error, gonna investigate when i have time tonight

16:37 Bronsa: ,(let [x 1] (let [x 2] x))

16:37 mk: if I have clojure right, a namespace maps symbols to ...vars (I thought values)

16:38 clojurebot: 2

16:38 Chousuke: mk: yeah

16:38 dnolen_: mk: in JS symbols are not user manipulatable values, nor are the containers for defined things reified in the language

16:38 Chousuke: mk: values are immutable, but bindings can change, so vars are needed

16:38 vars are not immutable

16:39 iwillig: hi pandeiro, you know i have not looked at geoscript for a long time

16:39 mk: dnolen_: they are. When you type x = 1 on the outermost scope, this remaps x. You can also push objects (maps) onto the chain using: with (foo)

16:39 iwillig: pandeiro, can you past me your error ?

16:39 Chousuke: symbols could have var-style semantics for mutation but then you'd have the problem I mentioned earlier. if symbol foo/x holds a value, then should x hold the same value, or something else?

16:40 mk: are namespaces immutable?

16:40 Chousuke: nah, you add bindings to a namespace.

16:40 with def and require etc.

16:40 dnolen_: mk: they are not reified in JS you cannot manipulate them and there is no interface to them. scope chain and vars are not the same thing.

16:41 mk: but is a namespace essentially a map?

16:41 Chousuke: dnolen_: well can't you add keys to some global object to create a binding in javascript?

16:41 mk: yeah

16:41 mk: with symbols instead of strings as keys

16:42 javascript in essence has strings instead of symbols for names, and then pretends that variables are something special :P

16:42 mk: dnolen_: in js, symbols are strings, and all objects are maps. object.prop is the same as object["prop"]

16:43 Chousuke: object aren't quite maps IIRC. there's some gotcha but I can't recall it :/

16:43 objects*

16:43 mk: Chousuke: var foo = 5 does precisely that. It adds the key "foo" (a string) with value 5 to the global scope object

16:44 Chousuke: mk: in clojure (def foo 5) would add an entry with the symbol foo as key pointing to a var named foo that holds the value, instead

16:44 well, var named namespace/foo actually

16:45 mk: Chousuke: the gotcha might have something to do with the possibility of native objects (which can do arbitrary things according to spec), but conceptually they are definitely maps and can be treated as such

16:45 Chousuke: then whenever foo is referred, that var is dug up. and when its value is needed, deref is called on the var to get the current bound value

16:46 the deref is implicit in most code but sometimes you need to use vars directly

16:46 if you eg, want to be able to dynamically rebind a function that you pass as a parameter to something

16:46 you pass the var instead and it works.

16:47 terom: mk: I think "var foo = 5" adds key to local scope instead of global scope, but foo = 5 (without declaring it as a var) adds to global scope. But I might recall this incorrectly...

16:47 Chousuke: scope is weird in javascript anyway

16:47 dynamically scoped this is the weirdest thing ever

16:48 mk: terom: foo = 5 will look up the value "foo" along the scope chain. If found, it will bind it at that level.

16:48 Chousuke: I try to not think of it as "this" in the first place, just some context object that holds whatever context we are running in.

16:48 dnolen_: mk: it's still not quite the same as vars in Clojure, you can't get the container in JS. there's also the problem that many things that are normal symbols in Clojure are special in JS - operators.

16:48 Chousuke: it makes more sense to me that way

16:50 amalloy: i never really thought about the fact that this is dynamically scoped. i don't really do enough js to care, but hopefully that insight will help me understand it next time

16:50 _andrew_k_: i think it's bad idea - trying to understand clojure in terms of js )(

16:51 technomancy: amalloy: hopefully there won't be a next time

16:52 Chousuke: there are worse options than JS :P

16:52 terom: _andrew_k_: could be, or maybe if there would be a good comparision available, it would be helpful :)

16:53 Chousuke: if you're used to prototypal OO in JS working with plain data structures in clojure should feel quite natural

16:54 mk: _andrew_k_: yeah, definitely. I feel like an idiot for bringing it up, but it's how I understand scope, and is probably the reason I'm not following the quadruple namespace+symbol+var+value resolution system

16:55 Chousuke: mk: you should think of them as separate things, not something complicated

16:55 _andrew_k_: mk: ask what the difference between let and binding and you get real brain storm )

16:55 Chousuke: namespaces hold bindings. symbols name things. vars hold values. values are values :P

16:56 _andrew_k_: values are bytes

16:56 bytes are bits

16:56 scgilardi: no turtles?

16:56 Chousuke: that goes below the abstraction that clojure provides :P

16:56 _andrew_k_: bits are electorns in transistors

16:56 mk: well, I'd hesitate to call js oo. The whole language is really just a bunch of maps, as well as prototype-style inheritance, and scope. You can encapsulate with closures and so on, but you don't have to

16:57 ok, so symbols are values, namespaces are maps, vars are pointers (and values are values ;)

16:57 Chousuke: symbols are not values, symbols are names :P

16:58 aperiodic: symbols are values that are often used as names

16:58 Chousuke: well, a symbol is a value too, just like everything else, but yeah.

16:58 aperiodic: at macro-expand time, symbols are just values

16:58 mk: (namespaces map symbols to all sorts of value types; keys to map-values)

16:59 dnolen_: mk: JS is definitely OO, with a sensible does of FP.

16:59 dose

17:00 Chousuke: mk: understanding why you need var containers for values is probably easier if you consider threading. a simple pointer can't provide any sort of sane semantics in a multithreaded environment

17:00 vars provide the ability to thread-locally dynamically rebind their value

17:00 mk: I suspect that there's a very good reason why there's an extra pointer in there, because the map itself could have just pointed to the value. If you're using scope chains anyway, then let should just add to the chain. Smart people had the option of doing it that way, but didn't, so I wonder why

17:01 dnolen_: mk: injecting objects into scope chains is dog slow - thus it's removal in "strict mode"

17:02 mk: can I access the namespace object in clojure?

17:02 Chousuke: yes

17:02 dnolen_: mk: yes

17:03 Bronsa: ,(the-ns 'clojure.core)

17:03 clojurebot: #<Namespace clojure.core>

17:03 pandeiro: iwillig: yeah it's this: http://sprunge.us/fbUY ... i think it's just a matter of updating the dependencies

17:03 aperiodic: ,(apropos 'ns)

17:03 clojurebot: (ns-aliases booleans the-ns instance? gensym ...)

17:03 Chousuke: namespaces are named by symbols too :P

17:03 and now that I think of it, java methods, classes, etc. are named by symbols too

17:04 mk: so I can map the symbols "ns/x" and "x" in both the global and current namespaces to 4 different vars, or the same single var?

17:04 pandeiro: iwillig: i am working with shapefiles for the first time and i was happy to find geoscript and your clojure implementation... i will see if i can fix it tonight, and if so send you a pull request

17:05 Chousuke: mk: if you're in namespace ns, ns/x should always refer to the var #'ns/x in that namespace. but x could refer to #another.ns/x

17:05 iwillig: thanks pandeiro... however i to apologize because geoscript is unfinished and looks to be broken. never got a chance to fix it

17:05 Chousuke: mk: if, for example, you somehow unmap the original mapping of x

17:06 pandeiro: iwillig: even if it only digests shapefiles, can simplify and output to geojson, and vice versa, that would be really useful

17:07 Chousuke: most often it's the other way around though. you might eg. want to remove the default mapping of = (which refers to clojure.core/=) and replace it with your own def of = in your namespace

17:07 pandeiro: the reading and converting part works, the simplifying doesn't b/c of geoscript.geometry

17:07 mk: do vars contain/point to their original symbol as well as the value, then?

17:07 Chousuke: mk: no, they just have a symbol object that represents their name

17:07 mk: it might be the same symbol object, or it might not be

17:08 there is nothing that prevents you from having a dozen different objects that are the same symbol as far as clojure is concerned

17:08 ,(identical? 'foo (symbol "foo"))

17:08 clojurebot: false

17:08 Chousuke: ,(= 'foo (symbol "foo"))

17:08 clojurebot: true

17:08 _andrew_k_: Chousuke: symbol x always point to the current namespace - it's short form of ns/x (when you are in namespace ns)

17:09 Chousuke: _andrew_k_: but it can point to a var in another namespace

17:09 ,*ns*

17:09 clojurebot: #<Namespace sandbox>

17:09 Chousuke: ,#'=

17:09 clojurebot: #'clojure.core/=

17:09 mk: _andrew_k_: but the namespace is a map. You can presumably map the symbol x to be anything you want, even not ns/x

17:09 Chousuke: ,(ns-mappings *ns*)

17:09 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ns-mappings in this context, compiling:(NO_SOURCE_PATH:0)>

17:10 Chousuke: hm, what was the function :P

17:10 aperiodic: ,(ns-map *ns*)

17:10 clojurebot: {sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, keyword? #'clojure.core/keyword?, unchecked-inc-int #'clojure.core/unchecked-inc-int, ...}

17:10 Chousuke: right. so it quite literally is a map :P

17:11 mk: is there something like a proper spec for clojure?

17:11 Chousuke: nah

17:11 it's implementation-defined

17:11 by several different implentations

17:11 _andrew_k_: when you change var of symbol x - ns/x changes too

17:11 it's the same

17:11 mk: you mean clj and cljs?

17:11 Chousuke: (ie. clojure implementations for different hosts do differ, intentionally)

17:12 aperiodic: mk: have you read through all the side links on clojure.org? they're fairly comprehensive (for the JVM implementation) though they are a bit academic in tone

17:13 mk: _andrew_k_: did you try adding one symbol or the other to the map directly? If it's a normal map, it shouldn't update both in the way you describe

17:13 Chousuke: mk: The way I see it, Clojure has some big ideas at the core and symbiosis with the host is one of them

17:13 so you can't really create a portable spec of clojure that you could implement on several hosts

17:14 because that would conflict with the philosophy of embracing the host.

17:14 mk: aperiodic: I should probably have a look at that - thanks

17:14 technomancy: Chousuke: well, there could; it just wouldn't be practical for building applications

17:14 dnolen_: mk: cljs is actually a pretty interesting case study in in some of the design decisions in Clojure around symbols, var, namespaces

17:14 mk: in CLJS namespaces are indeed just objects, and definitions are just properties on those objects.

17:15 _andrew_k_: https://gist.github.com/2164617

17:15 Chousuke: I guess you don't need vars in cljs

17:15 since it's single-threaded

17:15 dnolen_: mk: all the symbol manipulation and resolution happens in the compiler.

17:16 Chousuke: and JS makes redefinition simple unlike the JVM

17:16 mk: ok wait, are vars just a way to synchronize on key-value pairs without locking the entire namespace map?

17:16 Chousuke: _andrew_k_: I think you misunderstood what I meant

17:16 _andrew_k_: you're not changing the mapping of x in user there, you're redefining the var's value

17:17 _andrew_k_: but you COULD map x to point to the var in user2

17:17 by using eg, use

17:17 dnolen_: mk: vars are also Clojure's mechanism for supporting redefinition on a host designed for a much less dynamic language - Java.

17:19 mk: so they're not so much a theoretical thing, like the way that lists are evaluated, but a component that helps deal with the host?

17:21 Chousuke: I suppose

17:21 though bear in mind that vars are not the only reference type clojure has

17:21 there are refs, agents and atoms as well

17:21 vars are just the default used for globals

17:21 mk: right :)

17:21 technomancy: it's worth noting that vars are the only one for which idiomatic usage does not involve deref

17:22 dnolen_: mk: not completely - they serve a few purposes - dynamically bound thread locals. They also store metadata so useful for introspection

17:22 technomancy: mk: there was a talk on this at clojure/west

17:22 until the videos are up you might find the slides helpful? https://github.com/strangeloop/clojurewest2012-slides/blob/master/Andera-Namespaces-Symbols-Vars.zip

17:23 mk: awesome - thanks. Yeah, I've been looking forward to the videos

17:23 dnolen_: mk: that said, they are puzzling - it took me a long time to understand them - but not understanding them doesn't really impair everyday Clojure programming.

17:24 technomancy: yeah, just dive in; you'll figure it out by osmosis eventually

17:24 Bronsa: lol

17:24 patrikkarlin: like in final fantasy :P

17:24 only place i heard that word

17:25 Chousuke: :P

17:25 technomancy: yeah, just be sure to use lightning vars against water-based problems and you'll be fine.

17:26 Chousuke: I was ahead of my peers in English classes because I played Final Fantasy games and learned lots of new words from them.

17:29 mk: using a language I don't understand feels like a bit of a grind. But that's probably the only way to do it at the very start

17:30 dnolen_: mk: learning ain't easy

17:30 my initial reaction to JS was close to WTF. I like it alright now.

17:31 bsteuber: in lein2, where do I put dev-dependencies that I want to reuse in every project?

17:31 brehaut_: any language that doesnt feel like a grind at the start probably isnt worth learning either

17:32 BostX: hi all.

17:32 technomancy: bsteuber: that'd be the :user profile

17:32 bsteuber: I tried :profiles {:dev {:dependencies [[...]]}} under :user

17:32 BostX: guys do you know what should I use instead of global-singleton from former clojure.contrib.singleton ??

17:32 lazybot: BostX: What are you, crazy? Of course not!

17:33 mk: the initial curve tends to put me off, but I like the payoff. I spent days with the ecma262-3rd spec, it was great - js is actually a rather elegant language

17:33 technomancy: bsteuber: you don't want :dev there; bring it up a level

17:33 :dev is for project.clj files

17:33 https://github.com/technomancy/leiningen/wiki/Upgrading

17:34 mk: but there's no way I would have read that ugly thing unless I was somewhat into js already

17:36 dnolen_: mk: JS has too many dark corners to call it elegant - but it was influenced by good languages.

17:37 mk: and the combining of OO & FP principles was forward-looking

17:37 amalloy: wow, global-singleton looks like a terrible idea to begin with. you could easily replicate its functionality in a threadsafe way with ##(doc delay) and ##(doc force)

17:37 lazybot: (doc delay) ⇒ "Macro ([& body]); Takes a body of expressions and yields a Delay object that will invoke the body only the first time it is forced (with force or deref/@), and will cache the result and return it on all subsequent force calls. See also - realized?"

17:37 (doc force) ⇒ "([x]); If x is a Delay, returns the (possibly cached) value of its expression, else returns x"

17:37 clojurebot: "([x]); If x is a Delay, returns the (possibly cached) value of its expression, else returns x"

17:37 "([& body]); Takes a body of expressions and yields a Delay object that will invoke the body only the first time it is forced (with force or deref/@), and will cache the result and return it on all subsequent force calls. See also - realized?"

17:38 lancepantz: dnolen_: mk: i've been doing some js myself recently, overall i've enjoyed it

17:38 the api is a bit lacking

17:38 but jquery makes up for it, although it does end up looking strange

17:38 bsteuber: technomancy: is there something wrong with https://gist.github.com/2164741 ?

17:39 mk: dnolen_: it has a core that's rather nice, but a lot of bad things happened to it, probably because of how standardization went

17:39 bsteuber: technomancy: it seems midje doesn't find its way into my classpath

17:39 mk: dnolen_: which languages was it influenced by, which were good?

17:40 Bronsa: scheme i guess?

17:40 dnolen_: mk: Scheme & Self

17:41 brehaut_: and java in the wrong ways

17:41 dnolen_: mk: also I'm sure Brendan must have know something about the various 80s OO Schemes

17:42 mk: brehaut_: that turned out for the best, I think - the familiar syntax etc. brought people into a functional language

17:42 bsteuber: technomancy: nevermind, I'm a bit tired :)

17:42 mk: I didn't know that it was influenced by either of those

17:42 bsteuber: technomancy: works now, thank you

17:45 brehaut_: mk, the classical OO notation bolted onto a prototypal OO system has done lasting damage to JS

17:46 technomancy: bsteuber: cool

17:46 mk: the elegant thing about js (I think) is its map chaining, which is used both for prototypes and for scope. The core of the language can be inefficiently implemented in not that many lines of code.

17:47 brehaut_: do you mean the dot notation? obj.foo and obj["foo"] ?

17:47 bsteuber: technomancy: another thing I'm wondering about.. when I switch profiles, I'll have to manually clean stuff that has to be compiled differently, like cljsbuild advanced vs simple

17:47 but of course it's a hard problem, unless you want to clean all the time

17:47 brehaut_: mk, no i mean needing a new keyword, not supporting prototypal operations (till recently or via crockfords functions)

17:48 the inclusion of privileged constructors is a bit horrible in general actually

17:48 bsteuber: it would be great though if leiningen could somehow discover which parts have to be cleaned with the new profile

17:50 technomancy: bsteuber: hm; yeah. maybe some kind of mechanism plugins could use to specify staleness

17:51 a staleness predicate that could write checksums of relevant project map entries to disk

17:52 bsteuber: technomancy: sounds cool - but I guess there are more important things on your lein2 list ^^

17:53 technomancy: bsteuber: well, that's something that sounds like it would require some solid design since it could affect a number of 3rd-party plugins

17:53 bsteuber: indeed

17:54 technomancy: bsteuber: feel like starting a github issue or mailing list thread on which to brainstorm?

17:54 bsteuber: technomancy: sure, I'll open one :)

17:55 mk: brehaut_: yeah, all of that wasn't done very well. It seems to be getting patched up now, though.

17:55 bsteuber: technomancy: one more thing - is there a simple way to find out from my (non-plugin) code in which profile I am?

17:55 technomancy: bsteuber: no, I don't see that as a good idea.

17:56 bsteuber: consider parallels between user-agent sniffing and checking for specific features.

17:57 bsteuber: technomancy: the problem I'm trying to solve is having a single view deal with both advanced and simple cljs compilation depending on the profile

17:57 my current way is adding a different implementation of the same tiny namespace to the classpath in both profiles

17:57 technomancy: bsteuber: you'd want to check for a specific value within the profile rather than the name of the profile

17:58 dnolen_: mk: it's going to be a while before we see the benefits. Clojure already covers pretty much all the interesting JS.next territory under discussion and way, way more.

17:58 bsteuber: technomancy: and how could that be made available to normal code?

17:58 technomancy: bsteuber: you could have the profile put something in :injections if you must

17:59 that should be a seq of forms that get inserted into every eval-in-project call

17:59 but there's probably a better way to do this; maybe emezeske understands the problem better than I

18:00 bsteuber: technomancy: possibly I am doing something fundamentally wrong here

18:00 maybe I'll open another discussion in a cljsbuild issue :)

18:01 technomancy: so injections will be evaluated even in compiled code?

18:01 aot, I mean

18:01 technomancy: they will be evaluated while performing AOT, but they don't happen inside the call to clojure.core/compile

18:02 dnolen_: bsteuber: I was actually surprised by the fact that cljsbuild takes a vector instead of a named map of builds.

18:02 emezeske: ^

18:03 emezeske: dnolen_: Yeah, I guess that would make sense, so you could build specific ones by name?

18:04 dnolen_: emezeske: yeah - "lein cljsbuild once :adv"

18:04 technomancy: also probably "lein cljsbuild" should do something useful

18:05 emezeske: dnolen_: I like it... feel free to open a case ^_^

18:05 technomancy: That should print out a help message, does it not?

18:06 bsteuber: emezeske: I guess your default solution to multiple views for adv vs nil is not using nil as optimization level?

18:06 the problem is, without the out/ folder being used, the chrome js debugger is way less useful

18:06 technomancy: emezeske: I'd recommend having it do the most commonly-used subtask

18:07 emezeske: technomancy: Hmm, I might have to figure out what that is :). Probably 'cljsbuild once' if I had to guess. But I should measure...

18:07 bsteuber: I don't know if I understand the problem fully

18:07 technomancy: once is probably more commonly-invoked just because by nature it needs to be run more often than auto =)

18:08 dnolen_: emezeske: done.

18:08 emezeske: dnolen_: thanks!

18:09 dnolen_: bsteuber: hopefully all of this will be resolved when we start producing source maps

18:09 emezeske: sweet, sweet delicious source maps

18:09 bsteuber: emezeske: I use :optimizations nil and :output-dir together so the js doesn't get compiled in just one file for better debugging

18:10 but that means, I'll have to change the view again for loading goog.base and so on

18:11 emezeske: bsteuber: Ah, I see. I do something similar, but I compile in debug and prod at the same time, and just switch which I include in the views

18:11 bsteuber: But either way you do have to change the way the javascript is included

18:12 bsteuber: and that's what I am trying to get rid of

18:12 well, actually I did, but it's really ugly :)

18:13 emezeske: I haven't thought much about how to avoid that, really

18:13 bsteuber: maybe I'm just too lazy :)

18:18 dnolen_: what are source maps?

18:18 dnolen_: bsteuber: everything you ever wanted http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/

18:18 bsteuber: you could just always develop in advanced mode. and you'd get sexpr level stepping during debugging.

18:19 emezeske: Source maps fix 99% of my complaints about clojurescript

18:19 bsteuber: cooooool

18:21 will it also help finding out which file is breaking advanced compilation? :)

18:23 dnolen_: by the way, how's your research on predicate dispatch going?

18:24 recently, I've used some sort of poor man's dispatch several times

18:24 dnolen_: bsteuber: moving slowly , though some new steps will land in the next core.match alpha.

18:25 bsteuber: cool, I'll check it out then

18:26 with a problem this hard, slow progress is already awesome..

18:27 dnolen_: emezeske: bsteuber: the main challenge is that I think we'll need to analyze the Closure advanced sourcemap and use that to map to generated JS and then back to ClojureScript

18:27 and use that info to produce our own sourcemap.

18:29 emezeske: Yeah, that is definitely the tricky bit

18:29 Two levels of indirection need to be melded into one

18:30 Seems like a general purpose sourcemap merging utility could be of use. I wonder if such a tool would be applicable to other languages?

18:31 dnolen_: emezeske: hmmm ... that's not a bad idea, and yes I think it would be applicable - coffeescript will probably need the same thing.

18:32 ibdknox: I looked at it a bit and that was my assessment as well - reconciling the two steps will be the hard part

18:33 emezeske: Bwuaha, if we write the sourcemap merge in clojure, we can sneak clojure into all the other languages' build processes

18:33 dnolen_: ibdknox: I don't think so hard actually, just work.

18:34 ibdknox: dnolen_: yeah, I guess that's a better qualification. None of it looked particularly hard, just time consuming

18:34 emezeske: Seems like we'd want a basic sourcemap library for clojure, then the CLJS compiler could use that, and the merger tool could use it as well

18:34 dnolen_: ibdknox: for example we don't need mappings for intermediate things really - we produce a lot of generated symbols which are irrelevant for debugging.

18:35 ibdknox: also true

18:35 dnolen_: emezeske: yes exactly

18:35 anyways exciting times!

18:35 ibdknox: I was wondering how many problems macro expansion would cause

18:36 emezeske: ibdknox: Ooh, interesting

18:36 * emezeske *cough* GSOC project *cough*

18:36 ibdknox: haha

18:41 eggsby: if I have a vector of ~things~, and I want to iterate over those ~things~ until some condition is met, and then change that ~thing~ and return the new set, what would be the easiest way?

18:42 so like say is5 if the number is 5 turn it into 20 instead where [1 2 3 4 5 6] will return [1 2 3 4 20 6]

18:42 arohner: eggsby: for a vector (or map), you can use update-in

18:42 bsteuber: ,(map #(if (= 5 %) 20 %) (range 1 6))

18:43 clojurebot: (1 2 3 4 20)

18:43 arohner: (update-in [1 2 3 4 5 6] [5] + 15)

18:43 patrikkarlin: you only whant to change one of the items?

18:43 arohner: ,(update-in [1 2 3 4 5 6] [5] + 15)

18:43 clojurebot: [1 2 3 4 5 ...]

18:43 eggsby: ya basically I have 'buckets' and if something can fit in the bucket I want to shove it in there and recur on the rest of the things i'm testing

18:43 mk: ,(map #(if (= 5 %) 20 %) (1 2 3 4 5 5 6))

18:43 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

18:44 mk: ,(map #(if (= 5 %) 20 %) (list 1 2 3 4 5 5 6))

18:44 clojurebot: (1 2 3 4 20 ...)

18:44 eggsby: thanks that works mk

18:44 mk: it wasn't mine, I was just testing

18:44 I think it fails because it updates all fives, not just the first one it sees

18:44 eggsby: ya

18:45 hm

18:45 right so map won't work...

18:45 time to read documentation for update-tin

18:45 er, -t

18:45 mk: arohner's is better, but it updates the rightmost 5

18:46 arohner: ,(update-in [1 2 3 4 5 6] [3] + 15)

18:46 clojurebot: [1 2 3 19 5 ...]

18:46 arohner: stupid off-by-one. Actually, mine updates the index of the vector. I didn't read the original problem carefully enough

18:47 eggsby: the index hmm

18:47 ya, hm

18:47 I wrote some stupid nasty long piece of code full of conds and I don't like it :(

18:47 arohner: (map #(if ...)) sounds like a better fit for 'fix items matching this condition'

18:48 eggsby: update-in requires vectors or maps (not seqs or lists)

18:49 eggsby: ya, map would work if I could figure out how to say 'only meet this condition once'

18:49 bsteuber: ,(split-with #(not= 5 %) [1 2 3 4 5 6 7 8 5])

18:49 clojurebot: [(1 2 3 4) (5 6 7 8 5)]

18:49 bsteuber: maybe work from here

18:50 mk: eggsby: what you need is to say "the leftmost one that meets this condition". A parallel scan, for example, might meet the condition in the middle of [5 5 5 5 5 5].

18:53 arohner: you could use reduce to match once, but that feels a little more cumbersome than necessary

18:54 actually, map will do that

18:54 emezeske: eggsby: have you looked at map-indexed?

18:54 eggsby: nope, I'm new to clojure in general. I wrote some 100 line function to do this but its terrible

18:54 I feel like I should be able to do it more elegantly

18:54 arohner: (let [found? (atom false)] (map #(if (and (not @found?) ....) (do (do-stuff) (swap! found? (constantly true))

18:55 alexbaranosky: arohner, seems yucky to use an atom for that though, no?

18:55 emezeske: yeah, don't use an atom

18:55 arohner: alexbaranosky: yeah

18:56 alexbaranosky: (update-in [1 2 3 4 5] [(idx-of-first-match [1 2 3 4 5])] + 15)

18:56 bsteuber: eggsby: https://gist.github.com/2165263

18:57 this is what I would write

18:57 alexbaranosky: then just write idx-of-first-match

18:57 mk: the clojure core docs suck. Why isn't there a categorized listing? Like functions that apply to lists, etc.

18:58 alexbaranosky: bsteuber, pretty nice

18:58 mk you haven't written it :)

18:58 Actually I think there are some cheatsheet style webpages out there

18:59 aperiodic: mk: you mean like http://clojure.org/cheatsheet?

18:59 eggsby: https://refheap.com/paste/1307 is what I've got so far after scrapping my old monster implementation

18:59 i'll look at update-in alexbaranosky

19:00 mk: aperiodic: maybe :) I'm looking at http://clojure.github.com/clojure/clojure.core-api.html though, which is the first result, and it ain't pretty

19:00 eggsby: err, wrapping my head around that bsteuber

19:00 thanks you guys

19:01 mk: what's wrong with using alexbaranosky's updatein + indexof?

19:01 technomancy: mk: yeah, that's generated from the docstrings, which are reference material, not introductory

19:01 alexbaranosky: mk you have to write the index of function, though :)

19:01 eggsby: oh mk these are all just new functions to me I have to learn to use them first mk :)

19:01 mk: technomancy: yeah, but that's where I end up when I search

19:01 eggsby: oops, didn't mean to doubleping

19:02 technomancy: mk: yes, google is not kind to the aspiring Clojure learner

19:03 bsteuber: some day we will have something like hoogle using core.logic :)

19:03 technomancy: there's always findfn

19:04 mk: technomancy: that can't be an excuse when we have control over the page it points to

19:04 technomancy: huh?

19:05 I don't think restructuring a web site based on referer logs and guesses is a good idea

19:07 mk: just make the "core-api"... friendlier, without making it any less an api.

19:07 aperiodic: a link to the cheat sheet somehere on the core-api page wouldn't be a bad idea

19:08 emezeske: have you guys seen this super-epic cheatsheet? http://homepage.mac.com/jafingerhut/files/cheatsheet-clj-1.3.0-v1.0/cheatsheet-clojuredocs.html

19:08 technomancy: more links to the material people are likely to find helpful is a lot more productive

19:08 mk: or even a notice that says "this page is a mirror of doc, and won't help you find the function you're looking for - hit back and try again" :P

19:08 technomancy: unfortunately no one in here has permission to edit that page

19:09 mk: perhaps someone could send an email

19:10 aperiodic: oh awesome, cheat sheet on steroids

19:10 thanks, emezeske!

19:11 emezeske: ^_^

19:11 amalloy: eggsby: 100 lines!? that is way too many lines for any function; i wrote a 50-line function once and it's very embarrassing. if you had a clear description of what you're trying to accomplish (i can't make heads or tails of the comment in your paste) it's probably possible in at most ten lines

19:11 TimMc: technomancy: Not true.

19:11 technomancy: TimMc: ah, would love to be wrong on that one =)

19:11 TimMc: technomancy: Well, replaca has access, maybe not *permission*. :-P

19:12 technomancy: clojurebot: epigram 71

19:12 clojurebot: No entiendo

19:12 technomancy: clojurebot: 71

19:12 clojurebot: Gabh mo leithscéal?

19:12 eggsby: I know amalloy :(

19:12 TimMc: ~71

19:12 clojurebot: Excuse me?

19:12 technomancy: dang it clojurebot

19:12 "Documentation is like term insurance: It satisfies because almost no one who subscribes to it depends on its benefits." - Perlis

19:12 amalloy: ~#71

19:12 clojurebot: 71. Documentation is like term insurance: It satisfies because almost no one who subscribes to it depends on its benefits. -- Alan J. Perlis

19:12 technomancy: ah; there we go; thanks amalloy

19:13 mk: clojurebot needs a "did you mean" in place of its gibberish talk

19:14 amalloy: but how else would you learn to say "i don't understand" in welsh?

19:15 technomancy: mk: he does have some kind of fuzzy matching based on edit distance

19:15 mk: maybe we could set it up to say such things on a random timer

19:15 aperiodic: *that's* what that is

19:17 TimMc: mk: Or better, if the channel has been quiet for an hour?

19:17 mk: much better :)

19:18 as if he'd been thinking about it for a while

19:18 slyrus: yay. after a many month hiatus, clojure/emacs/slime/swank-clojure are all playing nicely (roughly speaking anyway) with CDK and it's 2-d molecule rendering routines.

19:26 bsteuber: technomancy: https://github.com/technomancy/leiningen/issues/468

19:26 will be interesting to see where this leads

19:28 technomancy: yeah, definitely

19:31 sandover: technomancy: thanks for the tip on lein search --update

19:31 technomancy: sandover: sure; no problem

19:31 it sure would be nice if you could update the maven central search indices incrementally rather than blowing them away

19:55 Jetien: Hi! I'd like to (require) a clojure lib that doesn't live in a file but a buffer. Is that - or anything equivalent - possible somehow? do i need to write a class loader for that?

19:58 Zoka: Tehnomancy: Do you have an idea how solve this little annoyance? http://groups.google.com/group/heroku/browse_thread/thread/2c7ed99b65531a75#

19:59 technomancy: Zoka: no, unfortunately it's pretty common to do stuff like echo "\n" >> project.clj && git commit --amend -a && git push --force

19:59 once a slug is built it's immutable

20:00 Zoka: Thanks

20:00 technomancy: if you load pomegranate you could do it via ringmon though =)

20:00 noir

20:00 sorry

20:00 http://sunng.info/blog/2012/03/my-favorite-feature-in-leiningen-2/

20:01 Zoka: I will have a look thanks

20:21 Frozenlock: Ok, I know you guys must take it for granted by now, but I think the fact that -keys are funtions of a map- is incredible.

20:21 And so Oh convenient!

20:22 mk: Frozenlock: and vice-versa, of course

20:23 Frozenlock: Of course :P

20:23 Equally amazing.

20:23 mk: Frozenlock: I forgot the talk, but there was a sorting example

20:25 erlang2clojure: hello, java/clojure newbie here. Need help getting cascalog to work (within clojure)

20:25 mk: usually, that part in java is something like ... well, you define an anonymous comparator, and it takes about 7 lines of mess. In clojure, the equivalent part of the code is like... :lastname

20:26 erlang2clojure: On ubuntu, created ~/cascalog directory then lein2 repl

20:26 ould not locate cascalog/playground__init

20:27 Frozenlock: mk: coming from emacs and CL, I'm baffled by how much java is verbose. I'm happy to see Clojure didn't inherit this characteristic.

20:27 mk: erlang2clojure: try ctrl-f in http://clojure-log.n01se.net/date/2011-11-05.html

20:29 Frozenlock: it's an adopted child. It inherits the platform without inheriting various language features

20:30 qbg: Though Java does occasionally rear its head

20:31 bsteuber: Frozenlock: but I believe you'll feel about CL in a similar way after using clojure for a while

20:31 of course it's not verbose

20:31 but overly complex

20:32 technomancy: clojurebot: equal rights for functional objects?

20:32 clojurebot: Equal Rights for Functional Objects is Baker's paper on equality and why it's impossible to define sensible equality in the presence of mutable data structures: http://home.pipeline.com/hbaker1/ObjectIdentity.html

20:32 bsteuber: and somehow not fitting this time

20:32 qbg: bsteuber: More like old

20:32 bsteuber: ^^

20:32 mk: looks like a dead link

20:33 technomancy: what!? nooooo

20:33 aperiodic: archive.org?

20:33 technomancy: http://www.pipeline.com/~hbaker1/ObjectIdentity.html

20:33 bsteuber: but not just that, I mean, a language which is born out of a commitee merging 5 ancestor languages being pushed by different parties - that has to become messy

20:33 technomancy: anyway, that paper convinced me that CL's notion of equality is broken beyond repair

20:34 erlang2clojure: @mk -- thanks. reading. I had done git clone cascalog to get the cascalog in, then lein deps brought in deps, but lein compile failed. So I figured if I do lein repl within cascalog directory it will just create all that's necessary automagically

20:34 technomancy: clojurebot: forget Equal Rights for Functional Objects |is| Baker's paper on equality and why it's impossible to define sensible equality in the presence of mutable data structures: http://home.pipeline.com/hbaker1/ObjectIdentity.html

20:34 clojurebot: I forgot that Equal Rights for Functional Objects is Baker's paper on equality and why it's impossible to define sensible equality in the presence of mutable data structures: http://home.pipeline.com/hbaker1/ObjectIdentity.html

20:34 technomancy: clojurebot: Equal Rights for Functional Objects |is| Baker's paper on equality and why it's impossible to define sensible equality in the presence of mutable data structures: http://www.pipeline.com/~hbaker1/ObjectIdentity.html

20:34 clojurebot: Alles klar

20:36 mk: what's the summary of that paper?

20:37 technomancy: defining meaningful equality semantics between mutable objects is impossible

20:37 mk: why?

20:37 clojurebot: mk: because you can't handle the truth!

20:38 qbg: Mutable objects change

20:38 I love that Clojure has egal

20:38 Life is so much better than it was in CL...

20:38 mk: sure, but presumably you can define equivalence between what we always refer to as identity

20:38 bsteuber: "two changing things are only equal if they will be equal all the time"

20:39 technomancy: mk: sure; should have said "meaningful equality semantics between different mutable objects"

20:40 the paper actually does argue that "identical?" is the only meaningful equality for mutable objects

20:41 mk: so comparing the values of two unequal identities at a point in time is useless?

20:41 technomancy: well... not if they're truly values

20:41 because values are immutable by definition

20:42 amalloy: mk: you asked for a summary of the paper, and now it seems like you're quizzing technomancy on all the details. why not just read it?

20:42 technomancy: it's pretty accessible

20:43 mk: amalloy: baker might have a knockdown point that's easy to mention, but which he omits in the abstract because he doesn't want to ruin the fun

20:44 muhoo: how would i start a clojure process as a daemon from lein, with a repl port i can connect to, but no stdin/stdout (no repl on controlling terminal?)

20:44 mk: I get that the paper's saying "you can't have equality", I'm wondering why. I'll skim the paper, though :)

20:44 muhoo: i have :repl-port set in the project.clj

20:44 * technomancy likewise refuses to ruin the fun, though more because it's been a while since he's read it than for any other reason

20:46 * qbg is suddenly reminded of circular source code

20:46 muhoo: circular... source code?

20:46 qbg: In CL you can read circular structures

20:47 #1=(1 . #1#) if I remember the syntax

20:47 mk: cyclical?

20:47 qbg: Any graph really

20:47 muhoo: ah, i see, lein run will do it.

20:48 qbg: Quines become too easy

20:50 TimMc: In JS too.

20:50 Well, depends on the impl. I think Mozilla's JS does that.

20:52 muhoo: no, that's a fal

20:52 fail

20:53 lein trampoline run does NOT start up the repl listener, even if :repl-port is set in project.clj

20:53 lein trampoline repl DOES start up the socket listener, but only if it has a controlling terminal :-(

20:54 rhc: hmm, is there a good way to get a monotonically increasing timer in clojure?

20:55 or should i just use java.util.Date

20:55 technomancy: (System/currentTimeMillis) is what you want

20:56 rhc: ah, thank you technomancy

20:56 muhoo: technomancy: any thoughts on how to get a repl on a socket from lein, starting lein without a controlling terminal?

20:57 technomancy: you can just eval-in-project the repl-form stuff from the repl task

20:57 with your own task

20:58 muhoo: ah, ok, thanks.

21:03 TimMc: rhc: There is also a nanos timer that guarantees better precision but no accuracy

21:04 rhc: TimMc: i saw that, i also laughed at the caveat

21:04 Differences in successive calls that span greater than approximately 292 years (263 nanoseconds) will not accurately compute elapsed time due to numerical overflow.

21:04 TimMc: 2^63

21:04 rhc: i like to think my programs will be around for awhile... but i'm also realistic :)

21:04 TimMc: clipboard format conversion fail :-)

21:05 rhc: ah, yeah, on the site the 63 is shifted vertically :)

21:05 superscripted

21:08 muhoo: hmm, not quite

21:08 if i start clojure.main/repl from inside the project, the socket doesn't start

21:09 ok, eval-in-project. gonna have to dive deep, looks like.

21:11 mstump: given an uberjar I created via lein how can I invoke some class? the machine doesn't have lein installed, if it did I could just use that.

21:13 muhoo: mstump: i think the classes show up if you unzip the jar and loook at it

21:13 like lancet$untar__405.class , those ugly names, you can call from java i bet

21:14 mstump: will that avoid "Failed to load Main-Class manifest attribute from"

21:22 mephist0: hi there: i thought (reduce + 1 {:a 1, :b 2}) should return 4 but it says "clojure.lang.MapEntry cannot be cast to java.lang.Number". Is there a function capable for this? Thanx

21:23 ibdknox: ,(reduce + 1 (vals {:a 1 :b 2}))

21:23 clojurebot: 4

21:25 mephist0: <ibdknox>: thank you very much.

21:39 ,(if true "yes im a bot")

21:39 clojurebot: "yes im a bot"

21:41 brehaut_: ,"values are expression too"

21:41 clojurebot: "values are expression too"

21:42 cjfrisz: ,"Functions are values."

21:42 clojurebot: "Functions are values."

21:44 ibdknox: ,:scooby-doo?

21:44 clojurebot: :scooby-doo?

21:45 scriptor: ,(if ((fn [] true)) "clojurebot does functions!" "No it doesn't :()

21:45 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading string>

21:45 scriptor: ,(if ((fn [] true)) "clojurebot does functions!" "No it doesn't :(")

21:45 clojurebot: "clojurebot does functions!"

21:45 scriptor: whee

21:48 cafesofie: ,(list (take 48 (cycle (str (Math/sqrt -2)))) "Batman!")

21:48 clojurebot: ((\N \a \N \N \a ...) "Batman!")

21:48 cafesofie: aww, truncated :(

21:49 aperiodic: ,(list (take 16 (cycle [(str (Math/sqrt -2))])) "Batman!")

21:49 clojurebot: (("NaN" "NaN" "NaN" "NaN" "NaN" ...) "Batman!")

21:50 cafesofie: the original haskell was better, but after a brief attempt i couldn't translate it

21:50 ((++" Batman!") . take 48 . cycle . show) (0/0)

21:51 ivan: failed port, you're supposed to get 17 NaNs ;)

21:51 aperiodic: cafesofie: the character literals were because you're passing the string itself to cycle, so it's being treated as a list

21:52 cafesofie: aperiodic: yeah once i hit the absence of 'show' i just gave up on translating it :)

22:00 scriptor: hmm, almost there...

22:00 aperiodic: ,(apply str (concat ((comp (partial take 17) repeat) (Math/sqrt -1)) [" Batman"]))

22:00 clojurebot: "NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN Batman"

22:01 aperiodic: unfortunately the succinctness of Haskell's point-free syntax is hard to beat

22:01 though i remember amalloy showing me a clojure DSL that came close

22:03 arohner: does paredit break for anyone else, when there is a paren in a comment? i.e. ;; (

22:04 scriptor: ,(->> [(Math/sqrt -2)] cycle (take 16) (reduce str) (#(str %1 " Batman!")))

22:04 clojurebot: "NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN Batman!"

22:05 scriptor: somewhat close to the haskell implementation, to make it cleaner you'd use join from clojure.string and some existing function to flip arguments instead of that ugly anonymous function at the end

22:05 aperiodic: of course, the threading macro!

22:05 scriptor: :)

22:19 cgag: i'm messing around with clojurescript, using noir/crate/jay, when I try to create some html using crate/html, then append it to a div, it only shows up if it's a single tag

22:19 TimMc: arohner: It can happen, yeah.

22:19 cgag: for example appending (crate/html [:p "hello"]) works, while (crate/html [:p "hello"] [:p "goodbye]), does not

22:20 lancepantz: cgag: you are missing a '"'

22:20 cgag: anyone have any experience with those libs? also if i should be in a clojurescript chanel let me know

22:20 lancepantz: if you had a compiler error, that's why

22:20 cgag: that was just a typo, i have it in my code

22:20 lancepantz: ah, k :)

22:21 but yeah, not familiar with them

22:25 m0smith: I have a noir/ring/jetty question

22:25 hi all

22:31 hello?

22:31 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline m0smith

22:32 cgag: hi

22:33 m0smith: I have a question about using JNDI with noir/ring/jetty. Where or where would I find some pointers?

22:33 unlink: What is the conventional way to scope the lifetime of a resource in Clojure? In my case, I am okay with lexically scoping my resource management, but I would prefer not to bake a new macro for each kind of resource I am closing.

22:34 ibdknox: cgag: you'd need to create them separately or wrap them in a container of some kind

22:38 weavejester: m0smith: Isn't JNDI orthagonal to Ring?

22:39 m0smith: weavejester: how so?

22:40 weavejester: m0smith: Well, JNDI is just a directory service, right? It could be accessed from a GUI, a CLI, or from a web app without the back end changing.

22:40 m0smith: Why would you need anything special for Ring/Noir?

22:40 cgag: ah ok, doing something like [:div [:p "hello"] [:p "goodbye"]] worked

22:41 m0smith: Just wondering how to enable it in the underlying jetty

22:41 Since Jetty is embedded I am having a hard time finding how to get it to work

22:41 weavejester: m0smith: Jetty is a web server. How would JNDI be enabled?

22:42 m0smith: Do you mean using JNDI for basic auth or something like that?

22:42 m0smith: weavejester: no, for database connections

22:43 weavejester: m0smith: But the web server has nothing to do with database connections

22:43 m0smith: Usually anyway

22:43 m0smith: There might be some weirdness in the Java web stack I'm unaware of.

22:43 ibdknox: why aren't you using JDBC anyways?

22:43 m0smith: weavejester: I want my app to be able to rely on the container, be it Jetty, Tomcat, or Glassfish to use JNDI to retrieve the data source

22:44 Iibdknox: I am using JDBC (hibernate actually)

22:44 ibdknox: By moving the data base connection info into JNDI, I can deploy my app on several different servers

22:45 weavejester: m0smith: Are you interfacing with a legacy Java app, then?

22:45 cemerick: m0smith: JNDI isn't in-scope for ring. You should just use the usual routes for configuring it (i.e. InitialContext, etc). You're going to need to use .war deployment and each container's specific configuration bits though.

22:46 JNDI is crazy-overkill for nearly everything IMO, but to each his own.

22:46 m0smith: It is a new Noir based app

22:46 In my case it works out nice to be able to separate the database configuration from the app

22:46 weavejester: If it's completely new, you should probably stay weeeeeell away from JNDI.

22:46 cemerick: In that case, just use env vars or system properties for your JDBC props.

22:47 weavejester: I prefer env vars myself. :)

22:47 m0smith: I am not sure if I can do that on jelastic

22:47 cemerick: I quite dislike env vars, but, yeah, sure. :-)

22:47 weavejester: JNDI is very much a Java thing, and not very "Clojurey"

22:47 ibdknox: env var for mode + config maps = win ;)

22:47 cemerick: It's not even a Java thing, really. It's easy to avoid it, regardless of the language you're using.

22:47 m0smith: It is, but it is also well supported on all the platforms

22:48 ibdknox: m0smith: what exactly does it provide you

22:48 I can definitely deploy to all the things you mentioned without jndi

22:48 cemerick: weavejester: I wonder if I can reopen the notion of optionally getting e.g. :servlet-request into request maps in the jetty adapter with you?

22:49 m0smith: ibdknox: I would like to know if oyu will share. My goal is to not have to change the WAR file regardless of where it is deployed

22:49 cemerick: I see it's come up before on the list. I ended up using hooke to get it into my request maps, so I could use a library that required an HttpServletRequest as a method parameter. :-(

22:49 weavejester: Hmm...

22:49 ibdknox: m0smith: connecting to the DB has nothing to do with the war file?

22:49 cemerick: m0smith: system properties FTW :-)

22:50 weavejester: Maybe if it was an option… by default turned off...

22:50 cemerick: yeah

22:51 I didn't mind using a hook, but it'd get a lot messier if I happened to need the response (!).

22:51 m0smith: ibdknox: The code needs to be able to find the database connection, even if it is at a different URL

22:51 weavejester: I don't want to encourage HttpServletRequest use, but sometimes when all your fellow libraries are doing it, you need to give into peer pressure.

22:51 cemerick: The odd thing to me is that it's the default in defservice, but totally absent in the jetty adapter.

22:51 ibdknox: m0smith: so just have a couple of different config objects and read an env var to determine which to use

22:51 m0smith: the only thing you fundamentally need to know is "what mode am I in?"

22:52 everything after that can be handled by the app

22:52 weavejester: cemerick: Well, defservice means you're interfacing with some legacy Java servlet container

22:53 cemerick: Whilst an adapter is supposed to be free of that, or at least pretend its not there.

22:53 cemerick: As you can't rely on an adapter being built on top of a servlet container like Jetty

22:53 cemerick: And you should be able to switch adapters without changing your code.

22:54 cemerick: OK, I can see that. I had always thought of the defservice/adapter distinction as one of container vs. containerless deployment.

22:54 m0smith: ibdknox: I am not sure how I feel about that .... Basically recreating the functionality that JNDI provides

22:55 ibdknox: lol

22:55 cemerick: FWIW, here's the janky API that requires the actual servlet req: https://code.google.com/p/jopenid/source/browse/trunk/src/main/java/org/expressme/openid/OpenIdManager.java#86

22:55 bleh :-|

22:55 ibdknox: m0smith: okidoke, good luck with JNDI - I literally know nothing about it :(

22:56 cemerick: weavejester: anyway, just a data point. The workaround isn't tough, of course.

22:56 ibdknox: fwiw, the funtionality we're talking about here is like 2 calls?

22:56 so I'm not sure I understand the reservation, but to each his own :)

22:56 weavejester: It looks like jelastic is very "old-school Java"

22:57 No 12-factor apps there

22:57 cemerick: m0smith: JNDI is basically a glorified key/value map. Not a lot special going on.

22:57 m0smith: weavejester: It is. I am creating a noir webapp and deploying to glassfish

22:57 weavejester: It doesn't appear as if you can set environment variables in jelastic

22:57 Which is a little crazy.

22:58 m0smith: weavejester: exactlym hence the JNDI configuration

22:58 weavejester: m0smith: Yeah, I can see why you're doing it now

22:58 m0smith: It looks like it's the way jelastic encourages

22:59 m0smith: weavejester: and to be honest, I have been writing Java webapps for a long time and it just makes sense to me

22:59 weavejester: m0smith: But hang on, there's a Java example on how to use it.

22:59 m0smith: weavejester: use what?

22:59 weavejester: m0smith: http://jelastic.com/docs/connection-to-db-via-jndi

23:00 m0smith: weavejester: Yes, my question is how to enable JNDI in jetty under ring. I know how to do it in a standalone jetty

23:00 weavejester: (-> (InitialContext.) (.lookup "java:comp/env/jdbc/jelasticDb") (.getConnection))

23:01 That apparent gets you your database connection

23:01 And that should be it.

23:02 As cemerick said, it's just a key-value lookup.

23:02 m0smith: it is. Unfortuntely it is not unabled in jetty by default and the lookup throws an exception

23:02 lancepantz: whoa whoa whoa, wtf is this http://www.techworld.com.au/article/419328/clojure_inventor_hickey_now_aims_android/?fp=16&fpid=1

23:02 m0smith: enabled I mean

23:03 lancepantz: did i miss something?

23:03 cemerick: lancepantz: ?

23:03 m0smith: so deploy a war into jelastic and you have standalone jetty/tomcat/whatever?

23:04 Dunno, a host that requires JNDI for simple stuff is a host that I'd avoid. *shrug*

23:04 lancepantz: cemerick: rich is targeting android?

23:04 m0smith: cemerik: exactly, but I like to do my inital testing using "lein run" which starts up in jetty

23:04 weavejester: m0smith: Oh, the configuration comes from web.xml...

23:04 cemerick: lancepantz: There's various tweaks that have been on the table for a while for android. I have no idea how that tangent in the interview ended up being the headline.

23:05 m0smith: weavejester: exactly

23:05 weavejester: m0smith: Hm. You might be on your own here. I need to get to sleep :)

23:05 cemerick: Probably the one that could get the most juice for the piece, I guess.

23:05 lancepantz: cemerick: yeah, i just noticed that too as i actually read it, all he says is "people are working on it"

23:05 m0smith: weavejester: thanks, just hoping someone know

23:05 how to configure jetty

23:05 lancepantz: just a sensationlized headline

23:05 weavejester: I'm inclined to agree with cemerick, though.

23:05 cemerick: yeah

23:05 and a roughly-edited interview to boot

23:06 weavejester: I'd avoid jelastic until it supports a third way aside from hard coding the database or using JNDI

23:06 cemerick: I've deployed to a lot of hosts, but never heard of one that *required* JNDI. That's nuts, even for a Java app.

23:07 m0smith: ok, thanks for the advice

23:07 cemerick: All FWIW, of course. :-)

23:07 and worth every penny! :-D

23:10 m0smith: lol

23:42 cemerick: emezeske: that's rough (re: your ML post, which ironically arrived after 24 hours) :-(

23:42 muhoo: heh, running a network connected repl from lein trampoline repl via a systemd startup service, it looks like this in ps: https://refheap.com/paste/1313

23:44 my guess is that's the whole repl as source code

23:49 emezeske: cemerick: Heh, thanks :)

23:49 lancepantz: yes

23:50 emezeske: cemerick: Oh well, I'm not moderated in here (yet) !

23:50 cemerick: There is an "always allow" option in the moderation panel…

23:50 emezeske: you'll always be welcome here :-)

23:51 (there's no op for the channel anyway)

23:51 emezeske: Hah

23:52 cemerick: well, there is one, but *shrug*

23:52 * emezeske hides.

23:55 cemerick: nah, he's with the Allies :-P

23:55 emezeske: did you enjoy the conf?

23:56 emezeske: cemerick: Most definitely! It was very cool to see the people behind the IRC handles :)

23:56 Excellent talks, all around

23:56 lynaghk: Too many cabbies demanding cash, I heard...

23:56 emezeske: Including a certain talk about what sucks about clojure ^_^

23:56 cemerick: heh

23:56 emezeske: lynaghk: Seriously! Jerks!

23:57 cemerick: lynaghk: what happened?

23:57 emezeske: I was honestly happy that I got out of the room without being barraged. :-)

23:57 lynaghk: cemerick: emezeske and I shared a cab, and the guy just wanted cash. emezeske was unnecessarily upset about it, I thought = P

23:58 emezeske: cemerick: Nah, it was one of those "we need to talk" kind of things, where you know it must be said

23:58 cemerick: our cabbie had a square, so that worked well.

23:58 lynaghk: cemerick: I'm not so excited about that kind of future after the hotel lobby iPad refused to let me sign out

23:58 cemerick: Yeah, I hope nothing presented was super-controversial.

23:58 Debatable maybe, but…

23:59 So that's what those things were for. I always check the in-room TV, and then talk to the desk otherwise.

23:59 lynaghk: oh, no

23:59 I mean sign out of gmail

23:59 the damn machine had an alert from my calendar on it the next day

Logging service provided by n01se.net