#clojure log - Jan 22 2010

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

0:11 defn[_]: '

0:11 'lo

0:43 autodoc++

4:27 neotyk: Hi *

4:27 Clojure-on-Clojure is it possible to get AST already?

5:30 KarlsFriend: Hi. I have a question. This is a chatroom about the prog. language clojure right?

5:31 leafw: KarlsFriend: yes.

5:32 KarlsFriend: leafw: I've been here for 10 minutes now. 5 people joined. But nobody talks. How come?

5:32 leafw: USA is sleeping

5:32 KarlsFriend: are they pming?

5:32 leafw: most folk are over there.

5:32 KarlsFriend: ok. but if i need help with clojure this is still the right place to ask?

5:33 neotyk: yep, also mailing list is good to ask

5:33 leafw: KarlsFriend: mailing list is better. More asynch and in-depth.

5:34 KarlsFriend: i am at the very begining and wondering why my code crahes. can you take a look at it?

5:34 leafw: I can't :) to busy

5:34 LauJensen: ~paste

5:34 clojurebot: lisppaste8, url

5:34 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

5:34 LauJensen: KarlsFriend: Try pasting it

5:34 KarlsFriend: ok, thx

5:36 lisppaste8: karlsfriend pasted "Working with canvas" at http://paste.lisp.org/display/93728

5:36 Chousuke: KarlsFriend: indent less :)

5:36 KarlsFriend: ok the problem is that i expect "gamestate" to be a ref to an int.

5:36 Chousuke: KarlsFriend: two spaces is the lisp convention

5:37 KarlsFriend: do you have alink where i can look that up?

5:37 Chosuke: the whole convention thing. i never used lip

5:38 *lisp

5:38 Chousuke: well, there is a scheme style guide

5:38 it applies pretty well to clojure

5:38 with a few exceptions

5:38 http://mumble.net/~campbell/scheme/style.txt

5:38 KarlsFriend: ok thx. i will lokk over it

5:38 Chousuke: it tells you not to use [] etc. but that obviously doesn't apply to Clojure :)

5:45 spariev_: KarlsFriend: it looks like you're using function with side effects (drawF) in dosync, maybe that's why it crashes

5:46 Chousuke: KarlsFriend: one common thing to do is to have the game state be a global ref

5:47 KarlsFriend: spariev: i am goin gto try that.

5:47 Chosuke: I thought about that, but that would prevent me from having to games at the same time. Not that i would want that. But there must be another way

5:48 *two games

5:49 cgrand: KarlsFriend: (ref-set gamestate (gameF (deref gamestate) t canvas)) is better written (alter gamestate gameF t canvas)

5:50 KarlsFriend: cgrand: thx i was looking for that function

5:52 cgrand: (let [new-gamestate (dosync (alter gamestate gameF t canvas))] (drawF gfx new-gamestate canvas)) to get the side-effecting fn out of the dosync

5:53 lisppaste8: karlsfriend annotated #93728 "untitled" at http://paste.lisp.org/display/93728#1

5:54 cgrand: KarlsFriend: in your last version you aren't sure that the gamestate value when you call drawF is still the same as when you updated it in the dosync above. Does that bother you?

5:56 lisppaste8: Chousuke annotated #93728 "cleaned up a bit" at http://paste.lisp.org/display/93728#2

5:57 KarlsFriendGotDi: I got disconnected somehow. Anyone posted a solution to my problem? ;-)

5:57 cgrand: have a you a stack trace to show us?

5:58 Chousuke: http://paste.lisp.org/display/93728#2

5:58 lisppaste8: karlsfriend annotated #93728 "stacktrace" at http://paste.lisp.org/display/93728#3

5:58 Chousuke: your problem was that you forgot to deref game-state

5:58 you passed the ref to drawF

5:58 and then passed that to .drawRect

5:58 and of course it blew up

5:58 cgrand: Chousuke: nice catch

6:00 Chousuke: KarlsFriend: but yeah, having a global state ref will prevent you from running two games concurrently, that's true

6:00 KarlsFriend3: ok sorry. i closed mirc again :-/

6:00 Chousuke: :/

6:00 KarlsFriend3: (ref-set gamestate (gameF (deref gamestate) t canvas))

6:01 that did not deref it?

6:01 Chousuke: it did, but then you passed gamestate to drawF

6:01 ,(let [a (ref 1)] [a (deref a) a])

6:01 clojurebot: [#<Ref@1f49e84: 1> 1 #<Ref@1f49e84: 1>]

6:01 Chousuke: see

6:01 KarlsFriend3: ah now i see it!

6:01 thanks Cousuke

6:02 Chousuke: see my annotation as well. looks a bit better with less indentation (and no camelcase), doesn't it? :)

6:03 and you're correct about having global state limiting you to one game at a time

6:04 creating the needed ref in a let is a valid solution as well, but it'll complicate debugging a bit

6:05 KarlsF: I just switched to Win 7. I know most of you use linux. But does anyone have an idea why mirc somehow closes itself?

6:05 Chousuke: it's not crashing, is it?

6:06 KarlsF: no i now see i have it open 3 times

6:06 Chousuke: so maybe it's just minimised? :/

6:06 in the system tray or something

6:08 http://clojure-log.n01se.net/ you can follow #clojure logs here to see things you might've missed

6:09 it's not real-time though.

6:14 AWizzArd: Chousuke: if you want real-time come here :-)

6:14 Chousuke: well, doesn't help if you have a connection like KarlsF :P

6:49 tcrayford: Any idea why the second to last test in this fails? http://gist.github.com/283706

6:50 am using (is (thrown? exceptionclass body)) to check if an exception is thrown

6:51 and clojure-test-mode is showing an error message with IllegalArgumentException displayed

6:51 just not a passing test

6:52 lein test is showing up with an error as well, with my IllegalArgumentException as the error

7:17 LauJensen: tcrayford: Where is thrown? defined?

7:45 jcromartie: what am I failing to comprehend here:

7:45 ,(re-matches #"x" "xyz")

7:45 clojurebot: nil

7:46 jcromartie: does it have to match the entire string?

7:49 for example, in JavaScript or Ruby a simple regex of "x" matches the "x" in "xyz"

7:55 I guess it's just a Java regex

8:38 chouser: jcromartie: re-find

8:38 jcromartie: ,(re-find #"x" "xyz")

8:38 clojurebot: "x"

8:38 jcromartie: hmm

8:39 chouser: some regex engines, like java's and python's have two different entrypoints. One function for matching the whole string, and a different one for searching for a match within a string.

8:39 jcromartie: the matches/find distinction seems strange but I guess it's the underlying Java library

8:39 LauJensen: ~regex

8:39 clojurebot: Sometimes people have a problem, and decide to solve it with regular expressions. Now they have two problems.

8:40 jcromartie: right

8:40 :)

8:41 LauJensen: re-seq is also handy

9:02 chouser: fogus: you got on lambda the ultimate!

9:03 fogus: I'm amazed at the traction of those slides...

9:04 I just stuck them up on my site so that the CAP CLUG folks could see them ... weird

9:05 chouser: :-)

9:08 cemerick: I had forgotten about the fine-grained locals clearing. That's in master at this point, right?

9:09 chouser: cemerick: I think so, yeah

9:09 rhickey: fogus: what were you trying to demonstrate on the transients slide in the bad things section?

9:09 chouser: cemerick: sorry, that was weak. Yes, that's in master.

9:10 cemerick: chouser: I'm a big boy, I could have looked it up myself if I weren't so lazy. But thanks. :-D

9:12 fogus: rhickey: My only point was that if it's at all possible to localize the transient to a function or block then do so. In my actual talk I noted that they were isolated to single threads and an attempt to mod in another would except. That dialogue is of course not reflected in the slide

9:13 rhickey: fogus: but it is ok to write a chain of functions that build up a transient.

9:15 nothing bad can happen, and I wouldn't want people to write unusually large functions in an effort to confine a transient to a block

9:15 fogus: rhickey: understood, and I think I mentioned that, but the word "always" is terribly misleading.

9:16 rhickey: the one thing that can leak is a transient to the same thread. If you kept the transient around and continued to interact with it, reads of that transient could produce different values at different times

9:17 never subject to race conditions or corruption though

9:18 I have been working on a model that puts transient use into a new reference type

9:19 chouser: rhickey: any thoughts about nested transients?

9:19 cgrand: rhickey: you mean like transients being owned by an agent (sort of an asynchronous accumulator) instead of a thread?

9:19 fogus: rhickey: Better? http://www.fogus.me/static/preso/clj1.1+/content/transients.txt

9:19 rhickey: chouser: putting them in a reference type makes that easy

9:20 cgrand: two flavors, one with single thread semantics, the other with internal locks

9:20 I'd be happy to describe them as long as everyone understand these are not fully baked

9:22 * cgrand would be happy to read that

9:22 rhickey: let me start here, so you all can ask questions

9:23 the basic idea, recognized by transients, is that the birth of a new value might be a composite operation

9:23 If you look at the are we there yet slides, you see the epochal time model

9:23 the transition from state to state is described as an atomic function

9:24 and it is atomic, from the standpoint of states - no such thing as an in-between state

9:24 but if you crack open F, you might see something like transients inside, which is fine

9:25 the reason it is fine, and the key to reconciling this whole notion of immutable states with the mutable memory everyone knows is there, has to do with visibility

9:26 a state must exist in order to be observed

9:26 between observations, process can occur, such process might have an extent, but exists between two moments in time

9:27 so, we have a reference type that can accumulate the effects of process, and manages time as always by providing states, the key being that a state won't be produced until observed

9:28 so, it looks like a reference type, except it can call transient on the thing placed in it. You send it functions, and it will process them transiently, you deref, it call persistent

9:29 but you can then keep going, unlike current transients which terminate

9:29 chouser: ah, neat.

9:29 rhickey: anyone whose observed has a perfectly fine value in hand

9:29 who has

9:29 cgrand: can you send function afterwards? (calling trasnient again on the persisted/observed state)

9:29 rhickey: cgrand: right

9:30 so, this fits right in with Whitehead, where a composite set of thing might influence the next moment

9:30 chouser: would there need to be a way to send non-transient update fns?

9:30 rhickey: chouser: hang on to that

9:30 chouser: ok

9:31 rhickey: it has a neat kind of quantum truth to it

9:32 so then, there are two models for composite forces creating the next state. One is sequential - multiple action from same vector

9:32 that is the same thread model of transients currently

9:32 the other model is parallel forces

9:33 this is a multithreaded model

9:33 it would be implemented via locking inside, basically enforcing the notion of place

9:34 then multiple threads could send actions into a cell (I've been calling these cells, with no connection to CL Cells)

9:34 the results of those actions would accrete

9:35 any observation would make concrete

9:35 a la Schr��dinger's cat

9:35 cgrand: :-)

9:36 rhickey: so, to chouser's question, there's no reason the thing inside a cell would have to be transient-able. Regular fns would work too

9:36 there is possibility for defining what transient meant, even for POJO's

9:37 i.e. could be clone

9:37 so this is a way to bring some of that unsafe existing OO into the safe fold

9:38 obviously, being based on locks, we don't want to inherit the problems of locks

9:38 cgrand: so StringBuilder could be used as a transient String

9:38 rhickey: the main one being the inherent danger of nesting

9:38 cgrand: yes, right

9:38 so, cells wouldn't support nesting

9:39 but they could safely support declarative parallel influencing of several cells at once

9:39 this is a different model than transactions, which support arbitrary, discover as you go, subsets

9:40 with cells you could do (inside [cell-a cell-c cell-b] ...)

9:40 multiple insides could always be made safe, as I can sort for lock acquisition order

9:41 i.e. if someone else simultaneously did (inside [cell-a cell-b cell-c] ...)

9:42 so, it inherits a limitation of locks, no arbitrary composition, but no danger

9:42 that's the basic idea

9:44 * fogus glad he set up this tunnel in order to reliably connect to IRC

9:45 rhickey: chouser: there is definitely work in determining what functions/methods work inside a cell

9:46 since many OO mutators return nothing

9:46 but transients would be a start, and clean

9:47 chouser: the cell itself would be doing the transient/persistent! calls, right?

9:47 rhickey: yes

9:47 cgrand: so a cell would take an init value, a transient function and a persistent! function (and/or transient and persistent! would be redefined as a protocol)

9:47 chouser: so that would have to be some kind of configuration option of the cell.

9:47 rhickey: and they would be a protocol

9:47 chouser: ok

9:47 cgrand: ok

9:47 rhickey: or could be property of cell if supplied explicitly

9:48 then single-threadednes would be cell property, not in the data structure

9:48 not sure if there should be 2 different cell types or not

9:49 the POJO part is least baked, but promising I think

9:50 cgrand: with the sequential type replacing the current model? (or the current model being reimplemented on top of the sequential type)

9:50 rhickey: but I like putting transients inside something much more than what we have now

9:50 so, yes, replacing current model of transient in hand

9:51 I still value the 'keep the same shape' concept

9:52 but once transients are out of view, then they can support regular conj/assoc in a transient way

9:52 thus making the change to exiting code even less

9:52 chouser: for a single cell to support both transient and non-transient actions, the mutation-causer fn (update, alter, whatever) would need at least a flag

9:52 rhickey: but, we need a new send/alter operator, and, unfortunately, a different arg order would be better

9:53 chouser: not if it is just a polymorphic fn

9:53 cgrand: why a different arg order?

9:53 rhickey: conj on transient vector does transient conj (wht conj! did)

9:53 cgrand: so switching preserves most shape

9:54 cgrand: of course

9:54 rhickey: (let [a (cell []] (=> conj a 42) @a)

9:55 currently refs would use (=> a conj 42)

9:55 the recipe would be, wrap in cell, prefix calls with =>, deref on return

9:56 you would also need to send 'reads' of cell in, like so (<= count a)

9:57 in order to avoid realization

9:57 as (count @a) would require

9:59 jcromartie: Are there any guidelines for using (:foo bar) over (bar :foo) where 'bar' is a map?

9:59 rhickey: of course, you could use this to introduce less functional style code, but that's true of atom too

9:59 * cgrand has to go

9:59 lpetit: a danger not to be underestimated

10:00 rhickey: lpetit: true, but the alternative is - people don't use functional langs because they are too slow, people switch from persistent data structures to ArrayLists

10:01 dnolen: rhickey: I accidentally read <= as a left point arrow. Would it be useful to have a function say <- to safely read blocking reference types (promises and futures for examples)?

10:01 rhickey: one whole aspect of Clojure is recognizing the need for this and making it safe and sound

10:01 stuartsierra: jcromartie: no, but (:foo bar) seems to be more common

10:01 jcromartie: it seems more lispy

10:01 treating the :keyword as a getter function

10:01 stuartsierra: right

10:02 rhickey: dnolen: I'd have to think about that

10:02 chouser: jcromartie: if the key is a literal keyword like that, it's probably best to put it first.

10:02 stuartsierra: jcromartie: But sometimes you want to treat the map as a "lookup function", in which case (bar :foo) may makes sense.

10:03 rhickey: jcromartie: one rule of thumb is, if :foo feels to you like an attribute, put it first, if it feels like an element in a collection, put the collection first

10:03 jcromartie: hmm, good guideline

10:03 chouser: jcromartie: then it will survive the map being nil, and in some cases will get you significantly better performance.

10:03 jcromartie: ah, yes, the map being nil is the tricky part

10:03 dnolen: rhickey: perhaps most useful at the REPL when playing around with promise/deliver/future since trying to print them always blocks. Just a thought.

10:04 rhickey: dnolen: what would it return if not ready?

10:05 lpetit: rhickey: sure. Was just reminding me some abuses of atoms that can come up on the ml from time to time (not so many, though)

10:05 chouser: dnolen: futures print :pending instead of blocking

10:05 perhaps promise should too

10:05 dnolen: rhickey: chouser: that would be nice I think.

10:05 lpetit: I couldn't follow you guys, too much shared implicit assumptions, to much shared implicit knowledge for me :)

10:07 rhickey: the other thing about cells is that they could provide a safe model for 'mutable' primitive locals/members, turning into nothing if non-escaping - still on the fence about that

10:07 lpetit: questions welcome

10:08 lpetit: First, the word cell is really connoted (want it or not), and I'm tempted to link old (partial) knowledge to new (understood) bits of knowledge

10:08 rhickey: lpetit: think jail cell

10:09 only one visitor allowed at a time

10:09 lpetit: the following visitors may or may not wait (block) ?

10:10 rhickey: wait

10:10 lpetit: by visitor, you mean readers as well as writers

10:11 rhickey: there are two separate notions, obtaining the value (state), happens via dereferencing and does not block

10:12 asking the prisoner a question requires a visit, using the (<= count a) function

10:12 that blocks, and is pretty special purpose, just for composite operations

10:13 a dereference during a process (change in another thread) see the last-produced state/value, the next one doesn't exist yet

10:13 chouser: does it block on its own, or is it required to be in a (cell ...) form that will do the blocking?

10:13 lpetit: ok, so while somebody is in the jail, every other reader continue to read the future old state's value

10:14 rhickey: chouser: cell just creates the reference, do you mean (inside ...) ?

10:14 lpetit: yes

10:15 chouser: rhickey: Ok, I guess I do.

10:15 lpetit: could jail or jail-cell be a replacement term for cell ? (carries more meaning at least to me)

10:15 rhickey: basically its a Kafkaesque jail - people can bail you out (via dereference) but they only get a clone, you stay in jail

10:16 lpetit: and has the good property of being less overloaded than cell

10:16 rhickey: chouser: I'm hoping not, that => will do the right thing, but there are some efficiency issues with nesting-testing

10:18 chouser: it might be that => works alone for single-thread cells, but needs to be inside (inside) for MT cells

10:19 note that transients and persistent data structures are still critical for this system

10:19 lpetit: rhickey: how could the (<= count a) question be interesting, if the next time I open the jail, I'm not faced with the same value again (if someone else hit the prisoner in the face during my two (=>) calls ?

10:19 "my two (<=) calls I meant"

10:21 rhickey: lpetit: it makes more sense in the single-threaded scenario, or when inside several cells in the MT scenario, then there will be no intervention

10:21 but you still don't want to realize a state yet

10:21 chouser: ah. a deref inside and 'inside' may actually be heavier than a <=

10:22 rhickey: yes, a deref always creates a state if the current state isn't, er, current

10:22 chouser: while outside, deref (when it does what you want) will likely be lighter, at least when the prisoner is a transient.

10:23 rhickey: that in and of itself is cheap, with transients, but it means you are starting from scratch on subsequent processing

10:23 chouser: yes

10:23 rhickey: a deref in a processing loop kills the perf benefit

10:24 i.e. it just degrades to persistent

10:24 but with OO cells, could be devastating as most transitions will be full copies/clones

10:25 er, POJO cells

10:25 chouser: right

10:25 rhickey: still, putting POJOs in cells is much better than current "you're on your own with that"

10:25 lpetit: what's the precise semantics of (inside), again ?

10:26 rhickey: lpetit: inside essentially lets you get the keys to multiple cells, and visit those prisoners back and forth, without anyone else intervening

10:26 chouser: taking locks on multiple cells in a sorted (therefore deadlock-proof) order

10:27 rhickey: i.e. it is a safe composite lock

10:27 chouser: right

10:27 and with nesting prevention

10:27 no insides inside inside

10:28 * rhickey loves English

10:28 * fogus parsing

10:28 chouser: no 'inside's inside 'inside'

10:28 hm. maybe that didn't help.

10:29 rhickey: insides don't nest

10:29 lpetit: np I understood : no nested inside :

10:29 fogus: Time flies like an arrow

10:29 lpetit: no nesting of insides :)

10:29 where with transactions it's possible to nest

10:29 rhickey: exactly

10:30 lpetit: and concerning the multi thread scenario

10:30 ?

10:30 rhickey: lpetit: what's the question?

10:31 lpetit: all the primitives are there ?

10:31 rhickey: ?

10:31 lpetit: never mind

10:31 rhickey: no please, I'm sorry which primitives?

10:32 lpetit: no, *I'm* sorry, I need to clarify my mind on other topics first

10:32 rhickey: it works with ordinary threads, as do all of Clojure's constructs

10:33 if multiple simultaneous insides overlap on one or more cells, some will wait, but no deadlock possible

10:33 lpetit: If one has 'inside, and a deref "publishes" a new value of the currently "edited" state to the external world, then I don't understand what <= and => are used for ?

10:34 rhickey: => is the 'send/alter' function of cells

10:35 <= is the trickier - asking the current process for some visibility on the value being created, must interleave with that process

10:36 lpetit: but if all operations on editable cells occur inside an 'inside, one couldn't consider they are all opened by inside and closed at the end, and if one wants to emit an intermediate value as a new state value, one calls deref inside inside ?

10:37 rhickey: but the functions you are using aren't functions of cells, they are functions of their values

10:37 you need to send them into the cell

10:37 same model as all of Clojure state

10:38 calling deref is an observation, causing the realization of a new state and production of its value

10:38 lpetit: indeed, even inside (dosync) one calls deref & al . It's just the fact that one has to specify the cells he wants to place the lock on, that made me think about that

10:39 rhickey: deref calls persistent on the value-in-progress

10:40 so every time you do that, the process starts anew, and no efficiencies of transience cross persistent calls

10:40 lpetit: I understand

10:41 so for this composite value creation, one will not have to use a functional style such the one one had to use while manipulating transients, one has to adopt an imperative style

10:42 or maybe not, if => and <= return the cell, humm...

10:42 rhickey: lpetit: you don't have to adopt an imperative style - it will be even nicer than current transients in supporting the same shape

10:43 <= can't return the cell

10:43 lpetit: oh really ?

10:43 rhickey: just like count doesn't return the collection

10:43 but => will

10:44 lpetit: why can't <= return the cell ?

10:44 oh, <= will return the persistent value

10:45 rhickey: because it's job is to return some information about the value in progress: (<= count acell)

10:45 returns a number

10:45 lpetit: <= is intended to be called from outside the (inside), e.g. another thread willing to see what the construction process has been able to produce so far ?

10:45 rhickey: deref/@ returns the state/value

10:46 lpetit: more likely from inside. Just consider, you want to add things until you have 100. How to you test for that?

10:47 if you say (= 100 (count @acell)), you've lost efficiency

10:47 instead (= 100 (<= count acell))

10:47 all of this useful inside a process

10:47 peeking with <= much less useful, and may block

10:47 lpetit: oh yes, and I can not really count before entering the (inside) call, or I will be facing potential race conditions ...

10:48 rhickey: lpetit: exactly, this looking with <= is logically part of this 'process'

10:49 lpetit: I first thought of <= was meant to do inter-process communication of "progression", but I now realized it's not the primary intent of the primitive

10:49 s/realized/realize/

10:49 rhickey: of course, I've been using => and <=, but names are welcome

10:49 jcromartie: rhickey: Slightly orthogonal to Clojure-the-language, but I have to ask: Are you able to use Clojure professionally, or is the language development taking up all of your time? And same goes for anybody else contributing heavily.

10:49 rhickey: especially since <= is taken

10:50 jcromartie: some, yes

10:50 * jcromartie is trying to make use of Clojure in a place with assumptions like "we will use Ruby and Rails because that's what agile shops do"

10:51 * rhickey needs more tea

10:52 jcromartie: nobody knows I'm *not* using Rails yet :P

10:53 lpetit: => and =< for a start :)

10:53 _schulte_: any recommendations on how to use an imperative Java library which works through side effects from inside of a clojure function?

10:53 I've tried a number of variations on the following http://gist.github.com/283864 with no success

10:53 lpetit: yes, with great care :-)

10:54 the-kenny: _schulte_: The map isn't working, right?

10:54 jcromartie: _schulte_: map produces a lazy seq, you need to force it's evaluation

10:54 the-kenny: _schulte_: For things like this, you would use "dolist"

10:55 jcromartie: s/it's/its

10:55 _schulte_: jcromartie: AH!, and here I thought it was something complicated with variable reference

10:55 lpetit: doseq

10:55 jcromartie: the-kenny: I think you mean doseq/dorun

10:56 fogus: http://www.lambdassociates.org/blog/klambda.htm -- Interesting from a cinc perspective

10:56 the-kenny: ,(doc dolist)

10:56 clojurebot: Pardon?

10:56 _schulte_: thanks for the help, it's working with that simple wrapper

10:56 the-kenny: ,(doc doseq)

10:56 clojurebot: "([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."

10:56 jcromartie: dorun being a function, doseq being a macro

10:56 the-kenny: Of course, doseq :)

10:56 Sorry, I'm reading some things in the CL Hyperspec at the moment

10:56 jcromartie: heh

10:58 lpetit: _schulte_: using local vars is just a way to convince yourself you're doing it right, but really doesn't buy you anything. It's the instructionList internals which is mutable, and placing a var over the instrunctionList instance will neither prevent that, neither help

10:58 _schulte_: lpetit: so I could just as easily us a let w/o all the var-get calls?

10:59 lpetit: _schulte_: and using map as a way to loop over asm, if you're not interested in any value produced by map, is just space overhead by creating all those needless seq values

10:59 chouser: jcromartie: any time I spend on clojure-the-language is "spare time" for me. At work I use mostly C++ and Clojure.

11:00 lpetit: _schulte_: I would just go with plain loop

11:00 _schulte_: lpetit: ah, thanks, so should I use loop and recur?

11:00 lpetit: alright, I'll give that a try

11:00 jcromartie: I think loop/recur is a little less elegant for iterating over a seq

11:01 there are so many constructs just to do that

11:01 clojurebot: _ato is a rockstar

11:01 AWizzArd: chouser: when you can get rid of the C++ stuff then your language mix will be perfect

11:02 chouser: AWizzArd: exactly

11:02 jcromartie: _schulte_: (let [lst (InstructionList.)] (doseq [x asm] (.append lst x)) lst)

11:02 lpetit: _schulte_: oh sorry, if the seq is already there, of course doseq is ideal

11:03 jcromartie: (I don't mean to be doing peoples' homework)

11:03 _schulte_: jcromartie: ah, thanks, I was just about to complain about the lack of a map which discards output, but looks like doseq fits that bill

11:03 lpetit: h��h��

11:03 _schulte_: jcromartie: don't worry, it's not homework

11:03 jcromartie: Figuratively speaking :)

11:04 lpetit: more like grownwork :)

11:04 jcromartie: heh

11:04 _schulte_: jcromartie: acutal real life, but yes, this is much appreciated :)

11:05 lpetit: _schulte_: even worse, you now owe him a penny :)

11:06 _schulte_: I'll cite you in my working notes :)

11:16 rober2: hi

11:16 after i converted a bean to a map with (bean��obj), how can i convert it back to a bean?

11:19 stuartsierra: rober2: I think you have to write that yourself.

11:20 jcromartie: keep the original object...

11:20 it doesn't seem like a good idea to pass around the result of (bean x)

11:21 at least if x is some mutable Java object

11:21 cgrand: and going back and forth between POJOs and maps with bean/unbean (yet to be written) isn't efficient (lot of reflection going on)

11:21 jcromartie: yeah unbean would have to involve proxy, wouldn't it?

11:22 or, no

11:22 cgrand: not if you pass it a target object

11:22 jcromartie: since the bean spec requires a zero-arg constructor and set* for every get*

11:23 cgrand: (defn unbean [obj map] (doseq [[k v] map] (Reflector/setInstanceField obj (name k) v)))

11:23 jcromartie: ,(bean "")

11:23 clojurebot: {:empty true, :class java.lang.String, :bytes #<byte[] [B@ee419f>}

11:23 jcromartie: the :class key should be used to instantiate the object

11:24 ,(new (:class (bean "")))

11:24 clojurebot: java.lang.IllegalArgumentException: Unable to resolve classname: (:class (bean ""))

11:24 jcromartie: oops...

11:24 Chousuke: (.newInstance (:class (bean "")))

11:24 ,(.newInstance (:class (bean "")))

11:24 clojurebot: ""

11:24 jcromartie: there we go... unbean is almost ready for prime time :)

11:26 (defn unbean [m] (let [obj (.newInstance (:class m))] (doseq [[k v] (dissoc m :class)] (clojure.lang.Reflector/setInstanceField obj (name k) v)) obj))

11:27 hmm, needs to check for getters first

11:27 rober2: thx a lot :)

11:29 jcromartie: I think bean is a little overzealous about what is a bean property

11:30 crios: hi all

11:31 jcromartie: hi

11:31 are there any good classes to test as beans?

11:31 * esj sets about writing his has-bean? predicate

11:33 jcromartie: http://gist.github.com/283890

11:34 it works for the simplest cases

11:38 esj: ,(has-bean? 'imperative-programming)

11:38 clojurebot: java.lang.Exception: Unable to resolve symbol: has-bean? in this context

11:46 cgrand: jcromartie: http://gist.github.com/283896

11:47 jcromartie: very nice

11:47 cgrand: forgot to return obj :-)

11:58 Raynes: http://www.infoq.com/presentations/Value-I...ate-Rich-Hickey <-- That's the most hilarious place I've ever seen an ellipsis.

11:58 "I...ate-Rich-Hickey"

11:59 Chousuke: :P

12:02 hmm, my new patched emacs has a curious bug.

12:02 I can't type R

12:02 if I enable clojure-mode

12:02 esj: !

12:03 Raynes: They are having this 52 weeks of code challenge thing on dreamincode.net, where every week they have a simple challenge to expose users to new technologies and such. This week was a Twitter challenge. I wrote my submission in Clojure, and so far, I think it's the most complex yet. :D

12:03 Chousuke: Raynes: complex, as in most featureful or the most contrived? :D

12:04 Raynes: Featureful. I wrote a http://reddit.com/r/clojure bot.

12:04 arohner: rhickey: cells sound really interesting. My only request is that there be "real" names (i.e. words) for => and <=. I grow weary of the explosion of ->, ->>, -?>, etc

12:04 Raynes: When means I parsed HTML, used the bit.ly API to shorten links, and posted results to twitter after processing them.

12:04 Most people just write a little GUI to update twitter.

12:05 arohner: and it would be great if -> and ->> had real names as well, so we could refer to them as "thread-first", "thread-last". It would reduce the incentive to come up with crazy function names like -@>

12:05 cemerick: arohner: just aliases though, right?

12:05 arohner: cemerick: right.

12:05 Raynes: But arrows are prettier.

12:05 :(

12:06 arohner: Raynes: just wait until the day where you have to explain the difference between ->>, -?>, -@>, -!>

12:06 Raynes: I would do it with honor.

12:06 :>

12:06 lpetit: arohner: you missed :>>

12:07 esj: zakly, Agincourt was not pretty.

12:07 lpetit: :)

12:07 I will defend -?> forever, though ! :-p

12:07 Raynes: I'm slowly converting the people on dreamincode.net to FP. Riches talks combined with sweet sweet envy.

12:07 jcromartie: -?!?!->

12:08 My friend told me yesterday: "next I'll say I'm making cheeseburgers and you'll say Why don't you come over for some Clojureburgers"

12:08 esj: jcromartie: that's a kebab

12:08 arohner: esj: you need some @'s in there for a kebab

12:08 :-)

12:12 lpetit: Ranyes: the site you're mentioning has really horrible colors :-(

12:13 Raynes: lpetit: It has really horrible users too, but yeah.

12:22 (def mytree (Tree (Tree nil nil) (Tree (Tree nil nil) nil))) ; MY EYES! THEY BURN!!

12:23 esj: Is there a big memory / execution penalty to fine grained refs ? Specifically I'm creating a very big map of small objects which are mutated individually. I'd prefer the fine granularity of being able to have each element in the map as a ref, rather than make the entir e map a ref, but am concerned about the implications ? Thoughts ?

12:23 if its not suicidal I'll probably do it, but don't want to produce something obviously daft.

12:24 chouser: I'd like to hear rhickey's reaction to that, but if you think it seems to fit your problem, I'd go for it.

12:25 esj: chouser: thanks.

12:26 jcromartie: esj: I think you should measure it

12:26 I have a feeling that a ref containing the whole map is going to be better than many refs

12:27 esj: jcromartie: testing sounds far too sensible :)

12:27 Raynes: I'll put 10 dollars on jcromartie.

12:27 jcromartie: my understanding is that deriving new instances of the persistent types is efficient and shares memory

12:28 chouser: multiple threads? each transaction fiddling with a subset of the values? the subsets over time may overlap rather than being cleanly partitionable?

12:28 jcromartie: i.e. if you had a vector of 1000 items, and you created 1000 new vectors with the first item changed each time, it would not take 1000 x 1000 the space

12:28 chouser: "no" to more than one or two of those would suggest a smaller number of refs.

12:28 jcromartie: my rule is refs for the largest chunk possible

12:28 esj: now usually I'd agree. Thing is one reason I'm mutating as that each element in the map has a keyword :endured, which I'm using to flag whether it has gone to the database. I'm worried that if I ref the whole map I'm going to find the I/O to the database will take its own sweet time, and retries on the ref commit will kill me.

12:29 now it could be that this flag should be separated from the main map

12:31 multiple threads: yes. Transaction subset: yes, but not overlapping.

12:32 chouser: so you might consider on ref per non-overlapping subset.

12:32 then again, if that requires more complex code, start with a simpler solution and see if it is fast "enough"

12:32 esj: chouser: nice idea !

12:33 But we all agree that the fewer refs you can get away the better ?

12:33 Raynes: defn: http://stackoverflow.com/questions/2115021/learning-a-lisp-variant-suggestions :(

12:33 esj: barring heroic coding

12:35 thanks guys.

12:45 partitioning is the answer.

12:48 jcromartie: are my assumptions about the space efficiency of persistent vectors/maps/sets etc. correct?

12:49 Chousuke: yes

12:49 jcromartie: that's good

12:49 I'd be interested in testing the tradeoffs

12:50 Chousuke: there are a few blog posts about the data structures around

12:50 jcromartie: too bad Java doesn't like being memory profiled :)

12:51 Chousuke: the persistent structures aren't particularly memory efficient if you're storing lots of small objects :/

12:52 ie. primitives. :P

12:53 but I think Rich is planning to introduce specialised variants for longs and doubles at least.

12:54 jcromartie: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

12:54 jcromartie: awesome stuff

12:55 a little bedtime reading

12:55 Chousuke: there's also an article for persistenthashmap

14:11 devinus: can anybody link me to an article on how to get started with clojure/clojure-contrib/slime/swank/clojure-mode/emacs on OS X ?

14:13 the-kenny: devinus: wait.. there's a good blog post

14:17 jkdufair: devinus: apparently ELPA has a clojure slime/swank package that will grab the latest clojure itself too

14:17 haven't done it yet but it was discussed here yesterday

14:18 the-kenny: Yeah, just use elpa to install slime and swank-clojure

14:18 And one of my recommendations after that would be leiningen

14:18 so you can just M-x swank-clojure-project RET dir RET to start a repl with matching classpath etc. for the project

14:21 joegg: I would like to make this shorter and sweeter: http://paste.lisp.org/display/93750 Can anyone offer some advice? I don't want to play clojure-golf, but if there's something I could do that's better, I would love to know.

14:21 I'm still trying to learn the basics.

14:22 Chousuke: I think the (comparator #(> ...)) thing can be shortened to just > :)

14:23 joegg: SO COOL!

14:23 Of course!

14:23 hiredman: http://www.reddit.com/r/programming/comments/asm7h/scala_a_postfunctional_language/ <-- it's interesting how little immutable values come up in debates over the definition of functional languages

14:24 Chousuke: joegg: also the one-branch ifs could be replaced with when to express your intent better

14:25 joegg: Ah, if's without else's --> when.

14:26 Chousuke: other than that, I can't see anything really wrong with it.

14:27 though since you're using let to create a "private" lookup table, you could move the private defn to it too

14:27 chouser: joegg: since you're using a sorted seq, could do: (defn match [num] (first (subseq numbers >= num)))

14:27 joegg: Chousuke: Thanks for looking! Glad to have a more knowledgable pair of eyes.

14:27 Chousuke: eg (let [numbers ..., match (fn [num] ...)] (defn speak-num ...))

14:29 joegg: Chousuke: That was going to be one of my questions, is it better style do to an internal utility function as a binding in a let, or not? It appears that the answer is yes. :)

14:29 The defn- doesn't make it local to the binding, but rather local to the (non-existent) namespace, right?

14:29 Chousuke: well, it's just marked as private

14:30 but there are ways to get to it from the outside

14:30 joegg: Good to know, thanks!

14:30 chouser: joegg: I'd actually recommend going the other direction. put numbers in a var, like (def numbers ...) instead of a let

14:30 Chousuke: anyway, I don't have a clear preference for either method. They're both okay

14:30 chouser: that makes it easier to redefine individual pieces as you're working on it.

14:32 joegg: chouser: How so? Just because the let syntax is out of the way better?

14:35 chouser: if you start with what you wrote in the repl and want to try out a new definition of 'match', you have to reload the whole 'let' block.

14:35 if 'numbers' were a var instead of a local, you could just redefine 'match' and try it

14:36 that said, there are certainly times where it makes sense to put everything in a let, helper functions too.

14:36 joegg: Okay. That makes sense. I'm very much used the edit/compile/run approach, and not the repl, so that explanation was very enlightening.

14:37 Would it be normal to start by just approaching everything as defs when you are first working the in the repl, but then move more toward a let/def approach when it is in a finalized and sharable form?

14:37 Like, say I wanted this in clojure-contrib (which, of course, I don't), then would the let/def approach make more sense than just multiple defs?

14:38 chouser: not necessarily. it's fine to have top-level def and defn's that rely on each other

14:38 hiredman: I would recomend defs for anything that is not a local sort of scratch value

14:39 joegg: chouser: Because the an (ns ...) would prevent this from just clobbering the global namespace.

14:39 hiredman: vars are rebindable and just make you code more amendable to various work arounds

14:39 chouser: joegg: there is no "global" namespace

14:39 hiredman: your

14:39 joegg: I'm approaching this from something of a javascript background, and so I keep thinking "gotta put my code in a closure".

14:40 Right. But in my mind, I'm still stuck in javascript.

14:40 Where this is.

14:40 chouser: joegg: ah, yeah, don't worry about that. put your code in a namespace. :-)

14:40 Chousuke: in javascript, namespaces are closures, aren't they? :P

14:40 joegg: Yes.

14:41 chouser: Before "releasing" your code, you would want to make sure you've got your own ns declared at the top of the file, but that's all you need.

14:41 Chousuke: of course you shouldn't declare needlessly public vars

14:42 you could make numbers a private var with (def #^{:private true} numbers ...)

14:42 chouser: yes, though if people aren't being promiscuous with :use, it shouldn't matter too much

14:43 hiredman: even if they are, you get an exception

14:47 joegg: Okay, awesome. I'm going to make the changes that everyone suggested and I'll repaste it. Thank you all for your help!

14:49 rhickey: I'm back from lunch meeting - any lingering questions on transient cells?

14:51 chouser: can we do ccinc first? :-D

14:51 Chousuke: :P

14:51 related: is it possible to implement cells purely in Clojure?

14:51 rhickey: chouser: no deps either way

14:53 I don't want to go another release without transients squared away

14:53 i.e. change sooner rather than later

14:53 * chouser resigns himself to putting cells in the book

14:53 rhickey: chouser: is that bad?

14:53 chouser: heh. no.

14:54 Chousuke: the naming is a bit unfortunate again. :/

14:54 rhickey: names are completely up for grabs right now

14:55 chouser: most of the book is stuff I already know -- little or no new "research" needed. protocols and deftype I need to know better though, and cells would definitely be in that category of course.

14:55 so more work, but no not ultimately bad at all.

14:55 rhickey: one nice thing is that cells and ccinc will be good proving grounds for deftype and protocols

14:56 fogus: chouser: Well, we have a place-holder for it already. ;-)

14:56 rhickey: presuming I don't need volatile for cells

14:56 chouser: fogus: cells!?

14:56 * chouser checks the TOC

14:57 fogus: chouser: Yes. That was incredible foresight no?

14:57 ;0

14:57 ;)

14:57 saml: hey, @Foo(a=32) private Something x; this is from Java code, is there a short way to get the value 32 from clojure? should i use Java interop?

14:57 chouser: hm. "cells" in the concurrency section isn't ... quite ... um...

14:58 fogus: chouser: I just kidding. That section was for Tilton (like) Cells

14:58 saml: in java, I 'd have to do SomeClass.class.getField("x").getAnnotation(Foo.class).a()

14:58 chouser: fogus: yeah :-) I know.

14:58 hiredman: saml: then that should work in clojure

14:58 fogus: But Kafkaesque cells could take that space instead.

14:58 saml: hiredman: thanks

14:58 hiredman: (-> SomeClass (.getField "x") (.getAnnotation Foo) .a)

15:01 rhickey: so we've heard from some who'd prefer chunked seqs not be the default, but I've had no reports from the field on chunked seqs, they've been in master for months. What does everyone else think - do you want to have to ask for chunks explicitly?

15:01 http://blog.fogus.me/2010/01/22/de-chunkifying-sequences-in-clojure/

15:02 Chousuke: I vote for explicit de-chunking

15:02 angerman: Hmm. my rfe code for libsvm works.

15:02 fogus: rhickey: I like chunked by default. I tend not to calculate explosive sequences.

15:03 drewr: rhickey: I haven't had any problems, but I'm sympathetic to the least-surprise argument

15:03 stuartsierra: I vote chunked by default with explicit de-chunking.

15:03 angerman: Ohh, de-chunking? ... me too. But I'd like to make it explicift if I want it or not. I don't care what's the default, but I want to have an explicit way to do the non-chunked/chunked way

15:03 the-kenny: Without being much into the topic, I'd vote for explicit chunking (for example map vs. map-chunked

15:03 chouser: I'm with stuartsierra

15:03 angerman: In the end it will boil down to what is anchored as default in my brain.

15:03 chouser: and Chousuke

15:04 angerman: How do other languages handle this? The default is non-chunked, right?

15:04 scgilardi: would explicit dechunking the head of a chain of lazy seqs make the whole chain one-at-a-time lazy?

15:05 rhickey: note also that many seqs will never be chunked

15:05 Chousuke: angerman: few languages even have an analogy. :/

15:05 chouser: scgilardi: generally, yes

15:05 scgilardi: then I'm with chouser and stuartsierra

15:05 angerman: Chousuke: Nah, I mean with lazy-sequences.

15:05 rhickey: scgilardi: you'd need to dechunk the source of a chain, then everything would be one at a time

15:05 not the head

15:05 chouser: I've heard even less call for a collect-chunks step

15:06 scgilardi: I see. That seems sufficient based on what we've seen.

15:06 angerman: can we have a configureable chunk size too?

15:06 chouser: angerman: why?

15:06 angerman: (e.g. I know I can read 10 itms at a time (memory), but 32 would blow it

15:06 Chousuke: angerman: the point is that the chunk size is optimised for the underlying representation.

15:06 rhickey: angerman: no, because choosing a chunk size not aligned with the data makes things worse, not better

15:07 chouser: angerman: probably not much value in chunking that at all then -- just read the first 10 individually

15:07 angerman: ok, maybe 10 was a bad choice

15:07 are ther other "favorable" sized?

15:07 rhickey: it might make sense when the data is generated, i.e. not sourced from a data structure

15:07 angerman: *sizes?

15:08 Chousuke: angerman: if you make your own chunked seq you're free to use whatever buffer size is optimal, though.

15:08 rhickey: some research shows a sharp dropoff in benefit as you move too far from 32-512

15:08 chouser: it seems likely that the value of adjusting the chunk size coming from e.g. 'range' would rarely pay for the extra complexity

15:08 rhickey: 32 being a sweet spot for chunking and the persistent data structures

15:08 chouser: true

15:09 angerman: Chousuke: that's right. Scratch what I said. I've looking at the problem from the wrong direction

15:09 chouser: though maybe a separate collect-chunk step in the pipeline would work for those rare occasions

15:10 rhickey: chouser: what does that do, chunkify?

15:11 chouser: right, would takes individual items and stuffs them into a chunk-buffer. I assume would require unusal performance profile downstream to be worth while.

15:11 angerman: so basically the generator has to decide what's the optimal chunk size, right?

15:12 chouser: angerman: yes

15:12 rhickey: angerman: everything about this discussion of different chunk sizes seems like premature optimization to me

15:12 32

15:12 there

15:12 chouser: :-)

15:12 angerman: rhickey: to me it looks more like a datastructure problem.

15:14 rhickey: if the data structure has specific requirements, that should dominate

15:14 chunk size follows

15:15 chouser: I do think it would be good to have something like seq1, so that it can be used in pipelines where you know you want one-at-a-time, even if your source is not currently chunked.

15:16 rhickey: chouser: yes, the whole issue is - is seq1 a wrapper or a request for a non-chunked seq directly supported by all chunked seqs?

15:16 chouser: ah

15:16 Chousuke: I don't think a wrapper will be problematic.

15:17 chouser: less work for each collection. I assume there's a worry over performance?

15:17 angerman: Hm. how about a seq-wrapper generator?

15:17 Chousuke: since if you want to avoid generating more than once item at once, it must not be a very quick operations.

15:17 -s

15:17 angerman: (def seq1 (chunked-seq 1))?

15:17 Chousuke: and the overhead of a seq wrapper would be inconsequential

15:18 chouser: angerman: chunks of size 1 are not exactly the same as unchunked. seq1 would probably just go unchunked.

15:18 angerman: chouser: ok, so basically like a flag?

15:19 isn't that what "meta" is supposed to give?

15:19 rhickey: as it stands, a wrapper can only throttle down post a chunked seq, so is working for range and the current data-based chunked seqs, but they actually are producing chunks. If you had a chunked source and didn't want chunks at any point, an adapter can't do that for you

15:19 i.e. if iterate was chunked

15:20 Chousuke: when would you need that much control? :/

15:20 angerman: rhickey: right. so it's all about the producer, right?

15:21 rhickey: angerman: iff things like iterate became chunked, it would be

15:21 angerman: Thus we would need at "consumer" level a way flag message the producer, wether or not it should emit chunks?

15:21 rhickey: data that's already in memory or ephemeral and cheap like range, adapting works fine

15:21 chouser: that would be the kind of context where explicitly asking for chunks makes more sense to me. chunked-repeatedly in particular

15:22 angerman: rhickey: ok. We had "no chunking" before. And that worked consistnely accross the board?

15:22 rhickey: angerman: yes, and adapting the things that are currently chunked would work fine too

15:23 making something like iterate or repeatedly always chunk would be a mistake

15:23 so they don't chunk now

15:23 and may never

15:23 * angerman imagins standing on an aircraft carrier. (i'm the consumer) and having an extra flag, to ask the planes to come down in chunks.

15:23 chouser: right, but it seems like overkill to make vectors know about seq1 just so repeatedly would have that option.

15:24 rhickey: chouser: yes

15:25 chouser: so, seq1 as a wrapper with the possibility of chunked-iterate or chunked-repeatedly later?

15:25 Chousuke: if chunked seqs were "degradable", wouldn't that complicate creating them? :/

15:25 rhickey: chouser: I need to think more about it, that's why seq1 wasn't in 1.1

15:26 chouser: ok

15:26 rhickey: need recognized, though

15:26 angerman: Chousuke: that's the point why we do not have (send-1) and (send-chunk) on producers, right?

15:26 rhickey: so, what does everyone think about this clojureconf idea in the fall?

15:27 angerman: where_

15:27 rhickey: bay area I think

15:27 fogus: :-(

15:27 angerman: hmm. that's east? west?

15:27 hiredman: california

15:27 angerman: It's at least over the pond, that I know

15:27 rhickey: san francisco

15:27 angerman: ohh the earth-quake area

15:27 hiredman: no doubt about it

15:27 angerman: ok

15:27 rhickey: san jose?

15:27 fogus: I love the idea -- hate the location.

15:28 chouser: It's nice and cheap to fly into Indianapolis.

15:28 Chicago's a great town

15:28 * fogus it's all about me

15:28 chouser: no, me!

15:28 angerman: fogus: Munich?

15:28 * angerman is for Munich

15:28 fogus: angerman: Is that anywhere near Washington DC? ;)

15:29 angerman: fogus: i think it's close to the airport

15:29 :D

15:29 rhickey: well, chime in for locations here: http://groups.google.com/group/clojure/browse_frm/thread/7723d2afca4245c5

15:29 chouser: but seriously, I'd love to go and/or present present, but I'm not likely to pay my own way there.

15:29 the-kenny: Munich would be ok for me :) (At least it's in germany :D)

15:29 chouser: er "present something"

15:29 angerman: chouser: meta presenting is ok too ;)

15:30 fogus: angerman: I'll be in Tyrol next fall, so Munich is not too far from there

15:30 chouser: heh. those are called "introductions" or sometimes "keynotes"

15:30 angerman: fogus: that's right.

15:30 * angerman wonders if he could talk his university into sparing a room.

15:30 dysinger: I hate it

15:30 danlarkin: conj!!!

15:30 dysinger: conj!

15:31 angerman: though as Munich is most likely the unlikeliest location anyway.

15:31 the-kenny: Leiningen would be a cool location too. But I think it's a bit far away from any internation airport

15:31 technomancy: definitely needs to be called ClojureConj.

15:31 danlarkin: clojure conj 2010!!! choo choo!!

15:31 hiredman: (conj clojure you)

15:33 rhickey: dysinger: hate what?

15:33 dysinger: ClojureConf

15:33 Chousuke: the name? :P

15:33 dysinger: y

15:33 Chousuke: yeah, it's a bit plain

15:33 dysinger: I wanted it to be called Clojure Conj

15:34 danlarkin: we want conj!

15:34 rhickey: oh, my bad, I didn't mean to imply that was the real name

15:34 jimduey: conj

15:34 dysinger: It's a play on "Cons" like BSD Con

15:34 rhickey: sure Clojure Conj

15:34 dysinger: and it's a function that's about bringing things together

15:34 which is fun

15:34 chouser: fn

15:34 "ClojureConj 2010 -- It's more fn!"

15:34 * rhickey worked an embarrassingly long time on naming conj

15:34 dysinger: I am just explaining my justification - You probably know what conj is rhickey :)

15:35 * lypanov wonders what clojureconj is

15:36 Chousuke: I think it might be better to not write it together, but instead as Clojure Conj :/

15:36 rhickey: dysinger: what about location? I'm most concerned we enable the greatest attendance

15:36 lypanov: amsterdam!

15:36 danlarkin: sf bay area

15:36 lypanov: (so i can come :P)

15:36 the-kenny: Amsterdam is nice for me too :)

15:37 (Almost everything in countries next to Germany is ok :D)

15:37 jasapp_: Oklahoma is a very central location

15:37 halfway between SF and Europe

15:37 chouser: heh

15:37 rhickey: NY!

15:37 jimduey: Kansas City

15:37 Great ribs

15:37 lypanov: iceland!

15:37 Chousuke: unless it's held in Finland I'm very unlikely to be able to attend, but...

15:38 cemerick: Northampton, halfway between NYC and boston ;-)

15:38 hiredman: Seattle!

15:38 * Chousuke should buy a couple lottery tickets

15:38 jasapp_: jimduey: the bbq in kc leaves a little to be desired ;)

15:38 technomancy: currently the largest gathering of Clojurists ever has been in SF

15:38 the-kenny: We should go swimming in the Atlantic

15:38 rhickey: cemerick: dream on

15:38 jimduey: jasapp_:not

15:38 dysinger: I would rather have SF since Amit and I are organizing

15:38 and it has the biggest clojure group in the US

15:38 angerman: Chousuke, the-kenny: let's buy a boat :D

15:38 technomancy: you have to have an organizer in the city where the conference is held

15:39 AndiXng: hi

15:39 technomancy: so if you're arguing for your home city, it should be taken as implicitly volunteering to help run it. =)

15:39 angerman: yea, the clojure community is quite weak in munich. I'd say it's part of the lisp user group but even those don't get to have regular meetings. :D

15:39 tbatchelli2: at disclojure.org, most of the readership is from the US, and of those, most of them located in CA... I don't know how representative this data is though

15:40 * rhickey wishes wikispaces' stats were working right now

15:40 tbatchelli2: 23% California, 10% Ohio, 7% Massachusetts and NY

15:40 * chouser clicks reload more

15:41 angerman: chouser: you are diqualified for cheating.

15:41 cemerick: chouser: I think we're pretty much hosed :-/

15:41 chouser: d'oh

15:41 rhickey: clojure site has been consistently 45% US

15:41 jasapp_: isn't that what curl is fore?

15:41 for

15:41 angerman: rhickey: ok, so not US

15:41 chouser: cemerick: not the least because we aren't even pulling for the same town :-)

15:41 fogus: For what it's worth my blog is CA, NY, TX

15:42 dysinger: Texas!!!

15:42 :)

15:42 scgilardi: clojure map: http://bit.ly/4CKYzO

15:42 dysinger: j/x

15:42 angerman: dysinger: I'm not gonna set a foot into that part of the world

15:42 tbatchelli2: Americas 51%, Europe 40%, Asia 5.5%

15:42 dysinger: angerman: but they have Whataburger!

15:43 * the-kenny adds himself to the map

15:43 * dysinger also

15:43 AndiXng: can anybody help me with the following question about deftype: the doc says that fields "can have type hints", but this seems to work only for primitive types, not classes. how is this useful for direct Java interop anyway, because I have to cast each time before using a field?

15:43 rhickey: Do they let NYers into Texas?

15:43 dysinger: Hawaii represent!

15:43 fogus: Although NY, NY is the #1 reader for my site

15:43 cemerick: chouser: I'll come to ohio just to represent the hinterland locales generally.

15:43 chouser: cemerick: ok! I'd drive to ohio

15:43 technomancy: the east coast has a lot of people, but pretty spread out

15:43 cemerick: chouser: aren't you in ohio? or crap, was it IN?

15:43 chouser: people in chicago could drive there too

15:43 technomancy: the density of clojurists around the SF Bay is pretty serious

15:44 chouser: cemerick: heh. yeah, IN. I know, pretty much interchangable to you coastal folk. :-P

15:44 technomancy: also: the map is probably not updated much, so take a grain of salt w/ that

15:44 tbatchelli2: I get 3 times as many visits from SF than from NYC

15:45 hiredman: hayward would be nice

15:45 rhickey: http://www.google.com/trends?q=clojure&ctab=0&geo=all&date=ytd&sort=0

15:45 technomancy: hiredman: kevins still outnumber non-kevins in Seattle

15:45 cemerick: chouser: people talk about coming to w. mass. like it's the same as scaling K2, so I feel you.

15:45 hiredman: boo yeah

15:45 chouser: cemerick: :-)

15:45 * rhickey went to w. mass

15:45 chouser: cemerick: I've actually been to w. mass. There's six flags out there, right?

15:46 cemerick: rhickey: yeah, that's what makes you the man. :-D

15:46 chouser: yeah, haven't been to it in a *long* time though. People here still call it Riverside (which was the independent park that Six Flags took over and basically ruined).

15:46 chouser: ah. went there once when I lived in NH

15:48 angerman: How about Vietnam?

15:48 Can Tho is pretty nice.

15:48 Cheap, warm, sunny :D

15:49 And it's likely equally far away from each of us :]

15:52 dysinger: Vietnam ???

15:53 angerman: yea, good, cheap food.

15:53 * chouser wonders about wifi and cell coverage there.

15:53 angerman: cell coverage is no issue

15:53 * lypanov usually goes for a total cost estimate for interesting parties rather than a location based average

15:53 angerman: wifi usually not

15:53 dysinger: I think I would have a hard time paying for my team flying to vietnam

15:53 fogus: I would be all for Tokyo. Clojure is getting big in Japan

15:53 angerman: fogus: Tokyo is so expensive

15:54 hiredman: Seoul!

15:54 angerman: hiredman: ok, haven't been there.

15:54 patrkris: LauJensen: Hey. Will the changes to the front-end be available in ClojureQL 1.0 or will it come in a later version?

15:54 dysinger: We could have some interesting conversations while wifi-ing at some amsterdam coffee shops if it where there (thinking)

15:54 lypanov: yeah!

15:54 and anyone that wishes can sleep at my place in den haag

15:55 (well, limit 4 people)

15:55 hiredman: if it was in seoul I most likely could get my parents to pay for my flight

15:55 dysinger: hehehehe

15:55 technomancy: I was going to say... how big is your place? =)

15:55 dysinger: lypanov: I hope there is at least 100 that come

15:55 danlarkin: ok hiredman we'll plan the conference around your budget

15:55 hiredman: :P

15:55 danlarkin: I would appreciate it

15:55 danlarkin: s/your/your parents/

15:55 lypanov: my budget is negative

15:55 does that mean we get paid to come? :D

15:56 dabd: anyone from here is coming for the european lisp conference in Lisbon (May 2010)?

15:56 angerman: Hmmm if I can get my Prof into thinking that Clojure is important, maybe I can get the money from the university.

15:56 danlarkin: so we're all agreed, SF, Chicago or NY. Probably SF

15:56 book it

15:56 hiredman: in the fall right?

15:56 danlarkin: yeah

15:57 chouser: I guess I knew what I was doing when I decided to not live in CA.

15:57 lypanov: dabd: oo, thats very doable for me in comparison to anything states side.

15:57 hiredman: gah

15:57 technomancy: if it's not near an airport with lots of non-stop flights it complicates things a lot

15:57 hiredman: you can fly from SEA to SFO for like $69

15:57 lypanov: amsterdam!! ...

15:58 hiredman: technomancy: really?

15:58 technomancy: well, one-way at least

15:58 lypanov: i suppose a few can fit in my basement! as long as its summer!

15:58 * technomancy did so last week

15:58 hiredman: I was just looking at priceline and it looked like $250 for a roundtrip in september

15:59 technomancy: hiredman: I came down for the Clojure meetup around JavaOne for only a bit over a hundred

15:59 * lypanov wonders if there are any companies doing clojure that want someone new as he's out of a job starting 1st march ish *meh*

16:00 lypanov: (man, as much as i love .nl. jobs blow :) )

16:00 * Apage43 wonders the same as he's hoing to hate his job starting feb 1 :D

16:00 Apage43: *going

16:01 * lypanov wonders how much he could get sponsered for to start his gwt/clojure project

16:01 lypanov: probably enough for my morning toast :D

16:02 dabd: lypanov: it would be interesting to see some Clojure people in Lisbon http://www.european-lisp-symposium.org/

16:03 angerman: dabd: hmm. let's hold the clojure conj _inside_ the els

16:03 dysinger: I think you'll find that the universe pretty much covers everything..

16:10 lypanov: dysinger: mars! its equally far from us all!

16:10 hiredman: NSA was giving away shuttle engines

16:11 angerman: NSA?

16:11 tbatchelli2: lypanov: it depends on the time of the day, doesn't it?

16:11 hiredman: pardon

16:11 NASA

16:11 they tried to sell them but no one would buy them

16:11 angerman: clojureconj on mars would definitely cause some media attention

16:13 well. bye.

16:13 lypanov: lol

16:13 ah, dabd is in pt. explains. hehe

16:14 bit far for me, but far more doable than the states.

16:14 and i'd just love to come :(

16:17 joshua-choi: ,(list* ())

16:17 clojurebot: nil

16:17 joshua-choi: Is there a particular reason why list* called on an empty sequence returns nil instead of the empty list?

16:20 hiredman: ,(doc list*)

16:20 clojurebot: "([args] [a args] [a b args] [a b c args] [a b c d & more]); Creates a new list containing the items prepended to the rest, the last of which will be treated as a sequence."

16:20 hiredman: I think "as a sequence" is they key point

16:23 slashus2: Hello everyone.

16:25 cemerick: It's seems like fns such as atoi should be in core...

16:27 DeusExPikachu: is there something like this clojure (from python) somevector[1:-1]

16:27 headius: FYI: http://gist.github.com/284140

16:27 I know some of you dig JRuby

16:30 * talios wanders on in

16:31 rhickey: headius: so all fields of Clojure::Object derivees are refs?

16:31 cemerick: talios: welcome :-)

16:32 talios: cemerick: howdy :) I need to fire up my IRC client more often and lurk more.

16:33 DeusExPikachu: nm, subvec

16:33 cemerick: talios: you could pimp clojure-maven-plugin, anyway ;-)

16:33 talios: true - and maven-polyglot-clojure - which I need to do some work on as well.

16:34 cemerick: that's a new one on me.

16:34 * talios wishes I could do clojure at work, sadly we're going the OSGi game :(

16:34 cemerick: talios: does clojure still have issues under osgi?

16:35 * rhickey still awaits a good description of what people expect of Clojure under OSGi

16:35 talios: mmm, to be honest I've not tried under 1.1.0 - but the last time I tried it every namespace/function got defined under the classloader for RT, but unloading the bundle leaves those classes around

16:36 I was meaning to look into trying a bundle-deactivator which calls an 'unload namespace' to remove it from clojure's RT, but havn't had a chance to try it

16:37 cemerick: talios: I *think* that's no longer a problem.

16:37 at least, such issues don't occur in NetBeans Platform apps anymore (which use an osgi-esque classloader structure)

16:37 talios: cemerick: oh cool, I'll have to dig out my OSGi clojure test code and give it a bash

16:38 rhickey: I'd like to improve the story there, if I knew what was needed

16:38 talios: cemerick: http://polyglot.sonatype.org/clojure.html <- polyglot maven - write your POMs in clojure (pom.clj)

16:38 Write, and -script- your POMs that is

16:38 cemerick: oh, sonatype-hosted, even, nice

16:39 talios: so the objective is to have complete parity with xml-based poms?

16:39 talios: cemerick: yep,so far theres clojure, scala, yaml, and ruby DSLs

16:39 cemerick: yep, theres a transformer as well: ./bin/transform pom.xml pom.clj - converts the XML to a clojure version and vice versa

16:39 cemerick: how well baked is it, relative to clojure-maven-plugin?

16:40 talios: cemerick: its independant of clojure-maven-plugin, however - the compiler plugin is "automatically added" to the POM model, so it compiles clojure out of the box

16:41 the polyglot side of it is solely the maven POM, not clojure compiling etc

16:41 * cemerick is nervous about stepping away from xml poms

16:41 talios: its's experimental :) Currently I know the release plugin will break, as theres no easy way to update version numbers if/when the pom is a scripted magic foo

16:42 cemerick: well, the release plugin is broken for me anyway :-P

16:42 talios: heh

16:43 cemerick: no, seriously, it doesn't work right with git + hudson

16:43 dysinger: headius: when is the jvm language summit each year and where ?

16:44 talios: Hrm. I use the release plugin with git without problem, how does hudson play into that?

16:44 cemerick: talios: see the comments near the bottom of http://wiki.hudson-ci.org/display/HUDSON/Git+Plugin

16:44 rhickey: dysinger: http://openjdk.java.net/projects/mlvm/jvmlangsummit/

16:45 cemerick: you really want to have your CI environment do the release, but hudson's git plugin doesn't check out refs, so there's no way to push back.

16:45 dysinger: rhickey: headius maybe we could do the clojure conj 2010 around the same time.

16:46 it's in santa clara nearby

16:46 * talios love to head to the JVM summit or clojure conj, way too expensive from NZ thou :(

16:47 rhickey: dysinger: would be useful for me, but don't expect much overlap in attendees otherwise - language summit is for implementors

16:48 dysinger: yeah I am only thinking of usefulness

16:48 talios: cemerick: mmm, personally I'd rather do the release locally, so that I know no random commits are leaking in - unless the CI server pulled out a specific release branch.

16:48 rhickey: dysinger: I wonder if there will be a Java One, nevermind JVM lang summit

16:48 dysinger: Are we going to have to get a Pledgie button to get chouser out here ?

16:49 talios: cemerick: A while ago I was thinking I'd love a release plugin "hack" that did the tag/branch etc., but then created a new "Release Build" profile in TeamCity (which we use) so that does that build.

16:49 dysinger: rhickey: true

16:49 talios: rhickey: Javaone's now mentioned on the moscone website

16:49 cemerick: talios: that's what Brad is talking about there -- even if you tell hudson to build a particular branch, it won't use that branch's ref for checking out, so no pushing. You should be able to build, release, push on a release branch, if that's your bag.

16:49 dysinger: I'll go to the airport with my coffee cup and guitar to raise money to get chouser out here :)

16:50 rhickey: talios: they would have to seriously alter their process, no call for papers yet even - last year they were vetting accepted presentation at this point

16:50 talios: rhickey: http://www.moscone.com/site/do/event/view?nav.type=0&nav.filter=1005&nav.base=1001&id=440

16:50 06/22/10 - 06/25/10

16:51 rhickey: chouser has to come to clojure conj!

16:51 talios: rhickey: true. Whats interesting is that the moscone details went up the day the EU agreed to let Oracle buy Sun, and the Mosone webpage shows a photo of Larry

16:53 rhickey: talios: great!

16:57 dysinger: Do we have any good contacts for a cheap (but good designer) for clojure conference website?

16:57 rhickey: thickey:

16:57 the-kenny: rhickey's Brother?

16:58 rhickey: yes

16:58 Raynes: rhicky and thicky. What a pair. What a pair I say, what a pair.

17:00 headius: rhickey: yes, all refs

17:00 stepped away for a bit

17:00 @foo and @foo = are just deref and set

17:01 rhickey: headius: one of the issues with making each field its own ref, is you can't see (i.e. read) a consistent object unless you are in a transaction

17:02 headius: I presume that would be the same problem if you are dealing with a set of refs

17:02 this is just a shortcut for passing around a set of refs as though it were an object

17:03 rhickey: if you put the entire (immutable) state of the object in a ref, then you could have a deref method that returned a snapshot of the object, out of a transaction

17:03 headius: yes, but sets of refs are not that great

17:03 headius: mmm interesting

17:03 rhickey: have the snapshot implement the read interface of the original

17:04 headius: so instead of a set of refs, you have a ref to a set

17:04 and replace it en masse

17:04 rhickey: that is in keeping with the ideas behind refs and Clojure state

17:04 right, ref to a map

17:05 headius: wouldn't be hard to modify this to work that way

17:05 jruby fields aren't kept in a map, they're just in an indexed structure (an array normally)

17:05 so it would just be a ref to a vector of values

17:05 rhickey: I ecommend it - independent refs do not an object make

17:06 whatever the structure, it needs to be immutable

17:10 the-kenny: Whoa.. macoexpansion at compile time got me again.

17:11 twbray: rhickey: It's not obvious that you need transaction semantics across all the fields in an object. Hmmm

17:12 dnolen: from ML, nice: http://lisperati.com/vijual/

17:13 the-kenny: dnolen: whoa

17:13 headius: twbray: I guess I'm still confused why you wouldn't need that in either case...if you're going to work with multiple of them, you'll want that work to be done in dosync

17:13 in which case whether they're separate refs or a single ref, they're all part of the transaction, no?

17:14 * twbray shuffles away to look at some app code

17:20 rhickey: headius: a key point of the Clojure system is that reads generally fall outside of the coordination system - get your composite value and be on your way

17:21 separate refs means you must read in a transaciton

17:22 headius: makes sense

17:24 if you had any sort of javadocs at all, this would be easier :)

17:26 rhickey: http://clojure.org/state

17:29 headius: hmm

17:29 RT doesn't appear to like being loaded from bootclasspath

17:30 rhickey: you know .class.getClassLoader returns null when loaded from bootclasspath, yes?

17:31 RT.baseLoader doesn't check for that

17:35 I'll work around it for now

17:50 nathanmarz: technomancy: can leiningen be used as the build system for a regular java project?

18:12 jkkramer: ping

18:12 i just made an ns cheatsheet for myself that others might find handy: http://gist.github.com/284230

18:53 mabes: anyone know if, in compojure, you can combine multiple routes when passing it the the servlet? Meaning, I have used the defroutes macro twice and I want to pass both resulting vars to the servlet function

18:57 danlarkin: technomancy: ping

18:59 alexyk: did you guys have to register your nicks today?

18:59 I'm inserting pairs like ["a" 0.1] into a vector. I'd like them to be inserted in a sorted order by the number. Is there a core data structure to do that?

19:00 technomancy: alexyk: yeah, I couldn't speak in this channel without registering.

19:01 alexyk: I could speak fine in other channels, but #clojure must be configured differently

19:01 alexyk: I wonder what's up with that. No more ___ and ` and |away

19:01 jkkramer: mabes: defroutes accepts route variables, so you can do something like: (defroutes all-routes foo-routes bar-routes), then (servlet all-routes)

19:01 alexyk: perhaps the clojurebot decided it's HAL?

19:01 mabes: jkkramer: perfect. Thanks!

19:02 alexyk: clojurebot: did you get drunk and fight nickserv again?

19:02 ah! clojurebot has to register too

19:05 it's like mute hordes show up, bang on the doors, and leave silently

19:06 hiredman: clojurebot is registered

19:07 must be netsplitted

19:07 clojurebot: ping?

19:07 clojurebot: PONG!

19:11 ubii: clojurebot: Open the pod bay doors, HAL.

19:11 clojurebot: the nest sentence is true

19:11 ubii: damn, I was hoping he would respond by saying "I'm sorry, Dave. I'm afraid I can't do that."

19:12 guess he really isn't HAL

19:16 hiredman: clojurebot: Open the pod bay doors, HAL is <reply>I'm sorry, Dave. I'm afraid I can't do that.

19:16 clojurebot: In Ordnung

19:16 hiredman: clojurebot: Open the pod bay doors, HAL.

19:16 clojurebot: I'm sorry, Dave. I'm afraid I can't do that.

19:17 ubii: nice :)

19:17 hiredman: clojurebot: Open the pod bay doors, HAL is <reply>I'm sorry, #who. I'm afraid I can't do that.

19:17 clojurebot: 'Sea, mhuise.

19:17 hiredman: clojurebot: Open the pod bay doors, HAL.

19:17 clojurebot: I'm sorry, hiredman. I'm afraid I can't do that.

19:17 hiredman: :P

19:18 ubii: even better

19:52 alexyk: how do I convert a seq of pairs ([1 2][3 4]) into a map most efficiently?

20:03 KirinDave: So

20:03 Can someone explain to me why this macro freaks out Clojure?

20:03 https://gist.github.com/198e96fbdf697b98d3d3

20:03 It works on the repl.

20:03 But if I try to use it in code, it dies.

20:03 With no error from the compiler.

20:05 alexyk: still -- how do I convert a seq of pairs ([1 2][3 4]) into a map most efficiently?

20:07 the-kenny: alexyk: (hash-map (apply concat seq))?

20:08 ,(hash-map (apply concat '([1 2] [3 4

20:08 clojurebot: EOF while reading

20:08 the-kenny: ,(hash-map (apply concat '([1 2] [3 4])))

20:08 clojurebot: java.lang.IllegalArgumentException: No value supplied for key: clojure.lang.LazySeq@e93c3

20:08 the-kenny: ,(hash-map (apply concat [[1 2] [3 4]]))

20:08 clojurebot: java.lang.IllegalArgumentException: No value supplied for key: clojure.lang.LazySeq@e93c3

20:08 the-kenny: ,(apply hash-map (apply concat [[1 2] [3 4]]))

20:08 clojurebot: {1 2, 3 4}

20:08 the-kenny: ha!

20:08 alexyk: yay!

20:10 or (flatten theseq)

20:11 so what's with into? I thought hiredman had a way to (into {} ...)

20:12 but can't remember how

20:12 clojurebot: with style and grace

20:13 KirinDave: So, uh, no one?

20:13 Why that macro fails?

20:14 https://gist.github.com/198e96fbdf697b98d3d3

20:14 Cuz it works in macroexpand.

20:15 tolstoy: If you have, say, a connection pool (DB), and you want to initiate it on first use, is a "ref" the way to go?

20:15 alexyk: I'm working a huge transient map of transient vectors. Then I need to persistent!-ize it back. Here's the result of toil:

20:15 ,(->> (transient {:a (transient [1])}) (persistent!) (map (fn [[k v]] [k (persistent! v)])) (apply concat) (apply hash-map))

20:15 clojurebot: {:a [1]}

20:15 alexyk: is this reasonable?

20:16 using the new Deutsch import from the-kenny in the end

20:18 the-kenny: alexyk: huh? Deutsch import?

20:18 alexyk: the-kenny: like a shiny BMW

20:19 I'm doing your trick of precise engineering in the end of that ->> :)

20:19 the question is, ios it the efficient way -- to persist! the map first, then the leaves

20:20 the-kenny: alexyk: Ah :) got it

20:22 alexyk: headius: did you have to register too?

20:22 * alexyk ah, he's about to have fun too

20:23 headius: hi

20:23 what's up?

20:24 alexyk: headius: do you know who inflicted this Guantanamo-style registration on us?

20:24 it was weird here all day

20:24 headius: Freenode probably

20:24 there was a big spam attack this weekend and they set channels +R

20:25 operator can turn it off though...I did in JRuby

20:25 #jruby

20:25 alexyk: ah ok

20:43 chouser: alexyk: into

20:43 alexyk: into

20:43 ,(into {} [[1 2] [3 4]])

20:43 clojurebot: {1 2, 3 4}

20:54 alexyk: chouser: I've tried with

20:54 ,(into {} ([1 2][3 4]))

20:54 clojurebot: java.lang.IllegalArgumentException: Key must be integer

20:54 alexyk: and it failed

20:55 why does (vec..) fix it?

20:56 chouser: that's just the literal list getting evaluated

20:56 ,(into [] (list [1 2] [3 4]))

20:56 clojurebot: [[1 2] [3 4]]

20:56 chouser: ,(into {} (list [1 2] [3 4]))

20:56 clojurebot: {1 2, 3 4}

20:57 alexyk: ah nice

20:58 vec's almost obliterate 'quoting

20:58 chouser: yep

20:59 and (list ...)

21:04 alexyk: chouser: cgrand : is this a good way tp persist a transient map of transient vectors:

21:04 ,(->> (transient {:a (transient [1])}) (persistent!) (map (fn [[k v]] [k (persistent! v)])) (into {}))

21:04 clojurebot: {:a [1]}

21:05 alexyk: i.e. least reallocation?

21:08 limux: what's the meaning of "fn*"

21:11 would I walk around the google to find the anwser or have to read the source of clojure?

21:15 alexyk: limux: where did you see fn* ?

21:15 mattrepl: probably read clojure/core.clj. it has to do with not having a destructuring fn while bootstrapping.. in fact the comments say as much =)

21:16 limux: sorry, i forget it

21:18 but you can use fn* to def a func which can work well

21:19 mattrepl: hmm, I think my answer is only partially correct

21:20 limux: in REPL, (fn a [] ()) => #<user$eval__3567$a__3569 user$eval__3567$a__3569@f4c0275>

21:20 but, (fn* a [] ()) => #<user$eval__3567$a__3569 user$eval__3567$a__3569@f4c0275>

21:20 mattrepl: but it has something to do with bootstrapping and special forms

21:20 limux: all is ok

21:21 i remeber i saw someone use fn* in his app on github

21:22 but i forget his proj

21:25 mattrepl: fn is a macro, so expand it and you'll see how fn* is used underneath

21:27 limux: i read only part of the sources of clojure

21:28 fn* a [] ()) => #<user$eval__3575$a__3577 user$eval__3575$a__3577@22cb4138>

21:29 a bit diffence to fn

21:29 mattrepl: ,(macroexpand (fn [x] (inc x)))

21:29 clojurebot: #<sandbox$eval__5090$fn__5092 sandbox$eval__5090$fn__5092@1d39053>

21:29 mattrepl: ,(macroexpand '(fn [x] (inc x)))

21:29 clojurebot: (fn* ([x] (inc x)))

21:33 limux: any more clealy explain?

21:34 ,(macroexpand (fn* [x] (inc x)))

21:34 clojurebot: #<sandbox$eval__5099$fn__5101 sandbox$eval__5099$fn__5101@beaff3>

21:34 limux: #<user$eval__3628$fn__3630 user$eval__3628$fn__3630@1a71d29a>

21:35 ,(macroexpand (fn [x] (inc x)))

21:35 clojurebot: #<sandbox$eval__5105$fn__5107 sandbox$eval__5105$fn__5107@1d998e8>

21:35 limux: #<user$eval__3637$fn__3639 user$eval__3637$fn__3639@7991ba7>

21:35 mattrepl: you need to quote macroexpand's argument

21:35 limux: ok

21:35 mattrepl: ,(macroexpand '(fn [x] (inc x)))

21:35 clojurebot: (fn* ([x] (inc x)))

21:37 limux: ,(macroexpand '(fn [x] (inc x)))

21:37 clojurebot: (fn* ([x] (inc x)))

21:38 limux: ,(macroexpand '(fn [x] (inc x))) => (fn* ([x] (inc x)))

21:38 clojurebot: (fn* ([x] (inc x)))

21:38 limux: ,(macroexpand '(fn* [x] (inc x))) => (fn* [x] (inc x))

21:38 clojurebot: (fn* [x] (inc x))

21:39 limux: fn is macro

21:40 (def

21:40 #^{:macro true}

21:40 fn (fn* fn [& decl] (cons 'fn* decl)))

21:43 let, loop do the same as fn

21:43 let* loop*

21:47 chouser: sorry, what was the question?

21:48 mattrepl: chouser: the purpose of fn*

21:53 limux: in compliler.java, static final Symbol FN = Symbol.create("fn*)

22:17 hiredman: fn is a macro that emits calls to the special form fn*

22:25 jlb: my "...more fn" t-shirt arrived today! http://img113.yfrog.com/i/kzml.jpg/

22:33 chouser: jlb: cool! quality of the shirt and printing ok?

22:35 jlb: chouser: yeah... I customized w/ an American Apparel shirt, but it looks great

22:41 chouser: great.

Logging service provided by n01se.net