Re: Functions and vars and meta-data

2009-11-27 Thread Stefan Kamphausen
Hi Alex,

first of all thank your this exhaustive explanation.

I still don't get some things, though, and kindly ask for more
enlightenment.

On Nov 8, 3:46 am, Alex Osborne  wrote:
> So after resolving, it then has a Var object.  A Var, is as it's
> name suggests, a variable.  It consist of a name (symbol+ 
> namespace),metadatamap and a value (called the binding).

As far as the documentation says, Vars can't have metadata:

"Symbols and collections support metadata," -- http://clojure.org/metadata

"Symbols, Lists, Vector, Sets and Maps can have metadata" --
http://clojure.org/reader

I tried to understand the Java implementation underneath which seems
to be in line with the documentation.  E.g. a symbol extends AFn,
which extents Obj which implements IObj, which in turn extends IMeta
which seems to be the relevant implementation of the metadata
interface.

However, there is some metadata code in Var.java which indicates that
Vars *can* have metadata, but according to documentation they can't.

An example also seems to indicate that Vars can have metadata:

user=> (def #^{:hasmeta "yes"} my-var [1 2 3])
#'user/my-var
user=> (meta my-var)
nil
user=> (meta (var my-var))
{:ns #, :name my-var,
  :file "NO_SOURCE_PATH", :line 63, :hasmeta "yes"}


> Now formetadata"on" functoins.  When you write this:
>
> (defn #^{:xxx 1} greet [] "hello")
>
> The #^{...} syntax means that Clojure creates a list of two symbols
> (defn and greet), and empty vector and a string "hello".  The second symbol 
> greet has
> the metadata{:xxx 1} associated with it.

Really? Then why the metadata of the symbol empty?
user=> (meta 'greet)
nil

Or am I not accessing the symbol's metadata that way?

This question is also related to the following part of your
explanation.

> The greet symbol still keeps it's metadata.  Now the def special form:
>
> 1. Creates a var.
> 2. Copies the metadata{:xxx 1} from the symbol greet to the var.
> 3. Binds the var to the function (fn ([] "hello")).
> 4. Creates a mapping in the current namespace ("user") from the symbol
> greet to the var.

All items agreed, except for 2. which I don't grok yet.


I think for me it boils down to

* Is the documentation wrong or my understanding of it?
* What part of the (Java)-code should I read to understand the
implementation of metadata (if I assume that my understanding of how
the classes extent/implement is not correct).

The reason for asking this is, that I *really* want to understand what
I am talking about.

Kind regards,
Stefan

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Space leak with lazy sequences.

2009-11-27 Thread Miron Brezuleanu
Hi,

not sure if it works here, but what about adapting advice from Stuart
Halloway's Programming Clojure (pages 159-160, 'Losing your head') and
use a function returning a sequence instead of a 'bound by let' name
(the actual advice in the book is to use functions returning sequences
instead of vars holding the head)? This is basically a delayed
evaluation trick similar to your workaround with atoms.

On Fri, Nov 27, 2009 at 3:38 AM, David Brown  wrote:
> On Thu, Nov 26, 2009 at 05:05:17PM -0800, David Brown wrote:
>>On Thu, Nov 26, 2009 at 04:00:34PM -0800, David Brown wrote:
>>
>>>For now, I'll do without the with-open, since in this particular case,
>>>errors are going to be fairly fatal anyway.
>>
>>BTW, I still haven't been able to figure out how to write this
>>function without hanging onto the collection across the call to
>>'write-mapping'.
>
> Ugh, I have found a very ugly hack that works.
>
> It seems that the compiler only nulls out locals before a call in the
> tail position, even if earlier calls don't reference the value any
> more.
>
> So, I went down in my call-chain to the first function that uses the
> sequence directly (in a doseq), and do something like this:
>
>   (let [real-coll @coll]
>     (swap! coll (constantly nil))
>     (doseq [item real-coll] ...))
>
> I just have to wrap the collection in an atom up where I create it,
> and make sure I never keep a reference to it around.
>
> David
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en



-- 
Miron Brezuleanu

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Alex Osborne
Stefan Kamphausen  writes:

> On Nov 8, 3:46 am, Alex Osborne  wrote:
> As far as the documentation says, Vars can't have metadata:
>
> "Symbols and collections support metadata," -- http://clojure.org/metadata
>
> "Symbols, Lists, Vector, Sets and Maps can have metadata" --
> http://clojure.org/reader

I don't think the documentation is *wrong* per se, it just only seems to
cover the immutable types.  Vars, refs, atoms, agents and namespaces can
all have metadata as well, but it works a little differently for them as they
are mutable.  You change their metadata using the alter-meta!
function.  The with-meta function will not work on them.

> Really? Then why the metadata of the symbol empty?
> user=> (meta 'greet)
> nil
>
> Or am I not accessing the symbol's metadata that way?

You are creating a new symbol 'greet, which doesn't have metadata.
Symbols are immutable types, you can't alter them and you can't alter
their metadata.  Instead what you do is create a new symbol with
metadata attached.

It might make more sense if we consider the case of metadata on
collections.  I can create a new empty vector with metadata using either
#^ or with-meta:

  (meta (with-meta [] {:foo true})) ; => {:foo true}
  (meta #^{:foo true} [])   ; => {:foo true}

Having done so doesn't change the original empty vector "[]", as vectors
are immutable:

  (meta []) ; => nil

The same is true for symbols:

  (meta (with-meta 'greet {:a 1})) ; => {:a 1}
  (meta 'greet) ; => nil

Note that (perhaps suprisingly) this doesn't work:

  (meta #^{:a 1} 'greet) ; => {:a 1}

Why?  Well because #^ attaches the metadata to the next read form.
What's the next read form?  It's 'greet.  But in fact 'greet is just
sugar for (quote greet).  So we're actually affixing the metadata to a
list containing two symbols (quote and greet).  When the compiler
evaluates (quote greet) it turns it into just the symbol greet and then
throws the list (and thus our metadata) away.

> * What part of the (Java)-code should I read to understand the
> implementation of metadata (if I assume that my understanding of how
> the classes extent/implement is not correct).

I think you are just being confused by the differences in how metadata
works with mutable and immutable types.

There are three interfaces to do with metadata:

IMeta.java   meta -- reading metadata
IObj.javawith-meta -- "changing" metadata on immutables
IReference.java  alter-meta! reset-meta! -- changing metadata on mutables

For the immutable types the implementation is in Obj.java.  For mutables
it is in AReference.java.

I hope that helps clarify things a bit.

Alex

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


combining vimclojure, classpaths and leiningen

2009-11-27 Thread bOR_
Hi All,

Is there any obvious way by which you can combine vimclojure and
leiningen easily? If I use leiningen to download and arrange all my
jar dependencies, they all end up in a ~/.m2/repositories/... etc
directory, and in the /lib directory of whatever project.

I think I cannot escape spelling out the ~/.m2/paths to clojure.jar
and clojure-contrib.jar in vimclojures' local.properties file, but is
there any way I can get start the nailgun server from my projects'
directory and it just takes ./lib as its classpath?

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: combining vimclojure, classpaths and leiningen

2009-11-27 Thread Alex Osborne
bOR_  writes:

> I think I cannot escape spelling out the ~/.m2/paths to clojure.jar
> and clojure-contrib.jar in vimclojures' local.properties file, but is
> there any way I can get start the nailgun server from my projects'
> directory and it just takes ./lib as its classpath?

java -cp 'src:classes:lib/*:nailgun.jar' \
 com.martiansoftware.nailgun.NGServer 127.0.0.1

Even easier there's a lein-nailgun plugin which has been uploaded by
gilbertl:

http://clojars.org/lein-nailgun

Just add it to :dev-dependencies in your project.clj.  Then you should
be able to just do:

lein nailgun

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Stefan Kamphausen
Hi,

that have been some really embarrassing typos in my post (typing too
fast in too stupid an interface, I think).

On Nov 27, 12:52 pm, "Alex Osborne"  wrote:
> Stefan Kamphausen  writes:
> > On Nov 8, 3:46 am, Alex Osborne  wrote:
> > As far as the documentation says, Vars can't have metadata:
>
> > "Symbols and collections support metadata," --http://clojure.org/metadata
>
> > "Symbols, Lists, Vector, Sets and Maps can have metadata" --
> >http://clojure.org/reader
>
> I don't think the documentation is *wrong* per se, it just only seems to
> cover the immutable types.

Which is kind of wrong, isn't it?  I strongly believe that this should
be changed.

>  Vars, refs, atoms, agents and namespaces can
> all have metadata as well, but it works a little differently for them as they
> are mutable.  You change their metadata using the alter-meta!
> function.  The with-meta function will not work on them.

While I understand that the mutating functions will not apply to
immutable types, I don't get why I can't create the metadata using the
same interface.

> > Really? Then why the metadata of the symbol empty?
> > user=> (meta 'greet)
> > nil
>
> > Or am I not accessing the symbol's metadata that way?
>
> You are creating a new symbol 'greet,

A *new* symbol?   I would have thought I'm getting the original symbol
again.
OK, but I see:

user=> (resolve 'greet)
#'user/greet
user=> (meta (resolve 'greet))
{:ns #, :name greet,
  :file "NO_SOURCE_PATH", :line 66, :arglists ([]), :xxx 1}

Sometimes the 'E' in 'REPL' stands for Enlightenment, and the 'P' must
be Pleasure then.  Don't ask me about 'R' and 'L', though. ;-)

> It might make more sense if we consider the case of metadata on
> collections.

I think I already understood them.  At least I can align things I read
in documentation and implementation with what I find in experiments on
the REPL.

> Note that (perhaps suprisingly) this doesn't work:
>
>   (meta #^{:a 1} 'greet) ; => {:a 1}
>
> Why?  Well because #^ attaches the metadata to the next read form.
> What's the next read form?  It's 'greet.  But in fact 'greet is just
> sugar for (quote greet).  So we're actually affixing the metadata to a
> list containing two symbols (quote and greet).  When the compiler
> evaluates (quote greet) it turns it into just the symbol greet and then
> throws the list (and thus our metadata) away.

This is subtle!  It really feels like one of those things that will
still feel creepy another 50 years from now.
I'll have to meditate on this a bit.

> > * What part of the (Java)-code should I read to understand the
> > implementation of metadata (if I assume that my understanding of how
> > the classes extent/implement is not correct).
>
> I think you are just being confused by the differences in how metadata
> works with mutable and immutable types.

Definitely, and I don't like the distinction too much either.

> There are three interfaces to do with metadata:
>
> IMeta.java       meta -- reading metadata
> IObj.java        with-meta -- "changing" metadata on immutables
> IReference.java  alter-meta! reset-meta! -- changing metadata on mutables

OK, I see.  I missed the last one.

> I hope that helps clarify things a bit.

It does.  I get a growing feeling of understanding how things work
under the hood here.

Your help is highly appreciated, thank you very much.

Regards,
Stefan

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: combining vimclojure, classpaths and leiningen

2009-11-27 Thread bOR_
using vimclojures' nailgun, I would have a line like this added to
my .vimrc file. Can I still use that?

let vimclojure#NailgunClient = "/home/boris/opt/vimclojure/ng"


On Nov 27, 1:43 pm, "Alex Osborne"  wrote:
> bOR_  writes:
> > I think I cannot escape spelling out the ~/.m2/paths to clojure.jar
> > and clojure-contrib.jar in vimclojures' local.properties file, but is
> > there any way I can get start the nailgun server from my projects'
> > directory and it just takes ./lib as its classpath?
>
> java -cp 'src:classes:lib/*:nailgun.jar' \
>      com.martiansoftware.nailgun.NGServer 127.0.0.1
>
> Even easier there's a lein-nailgun plugin which has been uploaded by
> gilbertl:
>
> http://clojars.org/lein-nailgun
>
> Just add it to :dev-dependencies in your project.clj.  Then you should
> be able to just do:
>
> lein nailgun

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: combining vimclojure, classpaths and leiningen

2009-11-27 Thread bOR_
Hmm. Need a bit of handholding (can't find any documentation yet on
this either.)

There is a vimclojure coming with adding [[lein-nailgun/lein-nailgun
"0.1.0"]] to dev-dependencies (org/clojars/gilbert1/vimclojure). Do I
add that to the dependencies as well?


On Nov 27, 4:16 pm, bOR_  wrote:
> using vimclojures' nailgun, I would have a line like this added to
> my .vimrc file. Can I still use that?
>
> let vimclojure#NailgunClient = "/home/boris/opt/vimclojure/ng"
>
> On Nov 27, 1:43 pm, "Alex Osborne"  wrote:
>
>
>
> > bOR_  writes:
> > > I think I cannot escape spelling out the ~/.m2/paths to clojure.jar
> > > and clojure-contrib.jar in vimclojures' local.properties file, but is
> > > there any way I can get start the nailgun server from my projects'
> > > directory and it just takes ./lib as its classpath?
>
> > java -cp 'src:classes:lib/*:nailgun.jar' \
> >      com.martiansoftware.nailgun.NGServer 127.0.0.1
>
> > Even easier there's a lein-nailgun plugin which has been uploaded by
> > gilbertl:
>
> >http://clojars.org/lein-nailgun
>
> > Just add it to :dev-dependencies in your project.clj.  Then you should
> > be able to just do:
>
> > lein nailgun

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: combining vimclojure, classpaths and leiningen

2009-11-27 Thread bOR_
Got it working. The only thing I need next to leiningen to set up my
working environment + project is the ng client from vimclojure, the
correct lines in .vimrc and the vimclojure vim plugin parts (in .vim)

Good!

On Nov 27, 4:16 pm, bOR_  wrote:
> using vimclojures' nailgun, I would have a line like this added to
> my .vimrc file. Can I still use that?
>
> let vimclojure#NailgunClient = "/home/boris/opt/vimclojure/ng"
>
> On Nov 27, 1:43 pm, "Alex Osborne"  wrote:
>
>
>
> > bOR_  writes:
> > > I think I cannot escape spelling out the ~/.m2/paths to clojure.jar
> > > and clojure-contrib.jar in vimclojures' local.properties file, but is
> > > there any way I can get start the nailgun server from my projects'
> > > directory and it just takes ./lib as its classpath?
>
> > java -cp 'src:classes:lib/*:nailgun.jar' \
> >      com.martiansoftware.nailgun.NGServer 127.0.0.1
>
> > Even easier there's a lein-nailgun plugin which has been uploaded by
> > gilbertl:
>
> >http://clojars.org/lein-nailgun
>
> > Just add it to :dev-dependencies in your project.clj.  Then you should
> > be able to just do:
>
> > lein nailgun

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: A Clojure Highlife

2009-11-27 Thread John Harrop
On Thu, Nov 26, 2009 at 4:37 AM, Chris Jenkins  wrote:
>
> (defn flip-cell [b x y]
>   (let [row  (nth b y)
> cell (nth row x)
> new-cell (- 1 cell)
> new-row  (assoc row x new-cell)]
> (assoc b y new-row)))
>

(defn flip-cell [b x y]
  (update-in b [y x] #(- 1 %)))

:)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Functions and vars and meta-data

2009-11-27 Thread Meikel Brandmeyer
Hi,

On Nov 27, 10:19 am, Stefan Kamphausen  wrote:

> As far as the documentation says, Vars can't have metadata:
>
> "Symbols and collections support metadata," --http://clojure.org/metadata
>
> "Symbols, Lists, Vector, Sets and Maps can have metadata" 
> --http://clojure.org/reader
>
> I tried to understand the Java implementation underneath which seems
> to be in line with the documentation.  E.g. a symbol extends AFn,
> which extents Obj which implements IObj, which in turn extends IMeta
> which seems to be the relevant implementation of the metadata
> interface.
>
> However, there is some metadata code in Var.java which indicates that
> Vars *can* have metadata, but according to documentation they can't.

Vars are one of the four reference types implementing IReference. The
other three are Refs, Agents and Atoms. All IReference types support
metadata.

> An example also seems to indicate that Vars can have metadata:
>
> user=> (def #^{:hasmeta "yes"} my-var [1 2 3])
> #'user/my-var
> user=> (meta my-var)
> nil

meta is a normal function. That means in the above case that meta is
called in the vector.

user=> (def #^{:hasmeta "yes"} my-var (with-meta [1 2 3] {:foo :bar}))
#'user/my-var
user=> (meta my-var)
{:foo :bar}

> Really? Then why the metadata of the symbol empty?
> user=> (meta 'greet)
> nil

Because the is a different symbol which happens to have the same name.

user=> (= 'greet 'greet)
true
user=> (identical? 'greet 'greet)
false
user=> (= 'greet (with-meta 'greet {:foo :bar}))
true

> Or am I not accessing the symbol's metadata that way?

You are. But of a different symbol. ;)

> * Is the documentation wrong or my understanding of it?

Hmm.. It seems missing, but I'm sure I read somewhere about the
reference types. Maybe in one Rich's talks? Hmmm..

> * What part of the (Java)-code should I read to understand the
> implementation of metadata (if I assume that my understanding of how
> the classes extent/implement is not correct).

The chain is Var -> Aref -> AReference -> IReference -> IMeta

> The reason for asking this is, that I *really* want to understand what
> I am talking about.

That's a Good Thing. We live to much from assumptions.

Sincerely
Meikel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Sneak Peek

2009-11-27 Thread Martin Coxall


On Nov 25, 2:32 pm, jim  wrote:
> Graham,
>
> That's exactly what it is. I used the continuation monad from
> clojure.contrib.monads.

Mention it on the website, and you instantly win +50 bonus Web 2.0
points for buzzword-compliance. Congraturation!

> After I get the code out, I'll be writing a
> tutorial on how it works which will also explain the continuation
> monad. I found that monad to be the most difficult to get my head
> around, but it's hugely powerful.

I'd like to read that tutorial. Will you be as explicit about creative
use of continuations as Haskell is?

"Abuse of the Continuation monad can produce code that is impossible
to understand and maintain."

That sounds like a challenge. THAR BE DRAGONES.

Martin

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: combining vimclojure, classpaths and leiningen

2009-11-27 Thread Meikel Brandmeyer
Hi,

On Nov 27, 1:43 pm, "Alex Osborne"  wrote:

> Just add it to :dev-dependencies in your project.clj.  Then you should
> be able to just do:
>
> lein nailgun

And make sure that the vimclojure.jar is in your classpath. It will
happily use whatever nailgun is there.

Sincerely
Meikel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Query regarding `conj'

2009-11-27 Thread nipra
Hi,
  (rest *v1) is equal to *v2 in the below mentioned example. Then why
  `conj' operation on them is returning different things.

user> (def *v1 [1 2 3 4 5])
#'user/*v1
user> (def *v2 [2 3 4 5])
#'user/*v2
user> (= (rest *v1) *v2)
true
user> (def *v3 (conj (rest *v1) 0))
#'user/*v3
user> *v3
(0 2 3 4 5)
user> (def *v4 (conj *v2 0))
#'user/*v4
user> *v4
[2 3 4 5 0]
user> (map #(class %) (list *v1 *v2 *v3 *v4))
(clojure.lang.PersistentVector clojure.lang.PersistentVector
clojure.lang.Cons clojure.lang.PersistentVector)
user>

Regards,
nipra

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Meikel Brandmeyer
Hi,

On Nov 27, 2:45 pm, Stefan Kamphausen  wrote:

> A *new* symbol?   I would have thought I'm getting the original symbol
> again.

If you get back the original symbol back, it can't carry metadata...

> Definitely, and I don't like the distinction too much either.

But it makes sense. A Var represents an identity and hence always
stays the same. Just the thing it points to might change. So we
obviously need to modify the Var in order to change the meta. If we'd
get a new Var, we would have a new identity. Clojure makes the
distinction between such side-effecting functions and pure functions
very clear.

> It does.  I get a growing feeling of understanding how things work
> under the hood here.

Watch the talk be Rich: 
http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey

There he explains the different notions and why they are required.

Sincerely
Meikel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


reordering agent messages sent from a locked area, is it possible?

2009-11-27 Thread Sergey Didenko
Hi,

Can I assume that messages sent to an agent inside a locked area will
keep their order ( the locking order)? Or is it still possible for
them to be reordered like in general case when you send the messages
from different threads?

The following code will be run from different threads:

(locking mylock
  (let [
 somedata (somefunc)
  ]
  (send myagent myhandler somedata)
)

Regards, Sergey.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread John Harrop
On Fri, Nov 27, 2009 at 8:45 AM, Stefan Kamphausen
wrote:

> > Why?  Well because #^ attaches the metadata to the next read form.
> > What's the next read form?  It's 'greet.  But in fact 'greet is just
> > sugar for (quote greet).  So we're actually affixing the metadata to a
> > list containing two symbols (quote and greet).  When the compiler
> > evaluates (quote greet) it turns it into just the symbol greet and then
> > throws the list (and thus our metadata) away.
>
> This is subtle!  It really feels like one of those things that will
> still feel creepy another 50 years from now.
> I'll have to meditate on this a bit.


Maybe this ought to be fixed; i.e., if the reader sees #^{meta} 'foo it
applies the metadata to foo first, then quotes it, resulting in the same
thing as (quote #^{meta} foo).

It would mean the reader would have to see #^{meta} and then store that,
then read the next item. Currently, if the next item is also a reader macro,
it expands that and then applies the meta to the result. Instead, if the
next item was a read macro with an "argument" (like ' or even ^ or @ or
whatever) it would apply the meta to the argument, then apply the new reader
macro.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: roll call of production use?

2009-11-27 Thread John Harrop
We're maintaining a large database of tagged images and had a need to
perform "fuzzy search" of the database. The existing search tool takes exact
queries only. So it was necessary to hack up a little tool to sit between
the query source and the engine and transform the query into a "fuzzy
query". You can think of it like this: the input query is something like x
AND y and the output is something like (x AND (y OR y2 OR y3)) OR (y AND (x
OR x2 OR x3)) where y2 and y3 are in some sense "near" y and x2 and x3
"near" x. The query transformation is simple enough, but it was really handy
being able to test it at a REPL, and even hot-swap modifications and do live
testing and tweaking of e.g. the neighborhood graphs used to "fuzzify" query
terms.

(Right now it only allows "slop" in one query term; sort of a
Hamming-distance-1 matcher. Extending it further would invite a
combinatorical explosion as well as lead to noisier, less useful results.
Distance 1 seems to be the "sweet spot" for our app.)

The code takes the input query, takes apart the terms, and generates seqs of
alternatives, with some (butlast (interleave foo (repeat "OR"))) type stuff
here and there, and cobbles them together again using seq functions, str,
and java.lang.String methods. (Some query terms need to be parsed, e.g. are
a hyphenated entity the first part of which should be fuzzy-matchable while
the second part should stay constant, etc.)

Rather boring? Little things like this incrementally improve services. Two
guys hacking like this in their garage went on to start Google. :) We don't
have such lofty aspirations, but it's still something to keep in mind.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: combining vimclojure, classpaths and leiningen

2009-11-27 Thread Meikel Brandmeyer
Hi,

On Nov 27, 4:16 pm, bOR_  wrote:

> using vimclojures' nailgun, I would have a line like this added to
> my .vimrc file. Can I still use that?
>
> let vimclojure#NailgunClient = "/home/boris/opt/vimclojure/ng"

You still need this. Leiningen only starts the server, will this is
the client. Without telling VC where to find the client, you cannot
talk to the server. So this is required.

Sincerely
Meikel

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: reordering agent messages sent from a locked area, is it possible?

2009-11-27 Thread Sergey Didenko
I wrote a simple test to check it and it does not see reordering on
multiprocessing system. But it does not prove anything of course.


(def transaction-lock
(java.util.concurrent.locks.ReentrantLock.) )

(def transaction-counter (atom 0))

(def counting-agent (agent {:count 1}))

(defn check [agent-state transaction-id]
(if (not= (:count agent-state) transaction-id)
(throw (RuntimeException. "Reordering happened"))
(assoc agent-state :count (inc transaction-id)) ))

(defn work []
(locking transaction-lock
(let [
transaction-id (swap! transaction-counter inc)
]
(send counting-agent check transaction-id)
;(println (str transaction-id " id sent."))
)))

(defn workn [n]
(loop [cnt n]
(when (not (zero? cnt))
(work)
(recur (dec cnt)

(defn work1 [] (workn 1))

(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(.start (Thread. work1))
(workn 1)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Sneak Peek

2009-11-27 Thread Martin Coxall


On Nov 25, 2:59 pm, Konrad Hinsen  wrote:
> On 25.11.2009, at 15:32, jim wrote:
>
> > That's exactly what it is. I used the continuation monad from
> > clojure.contrib.monads. After I get the code out, I'll be writing a
> > tutorial on how it works which will also explain the continuation
> > monad. I found that monad to be the most difficult to get my head
> > around, but it's hugely powerful.
>
> I can confirm that impression... And only wish you good luck writing  
> that tutorial!
>

>From the Haskell boys:

"Abuse of the Continuation monad can produce code that is impossible
to understand and maintain."

That sounds to me like a challenge.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Lein adding repos

2009-11-27 Thread David Nolen
Is there currently a simple way to add new maven2 repos to download from?

David

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Query regarding `conj'

2009-11-27 Thread Lauri Pesonen
Hi Nipra,

2009/11/27 nipra :
> Hi,
>  (rest *v1) is equal to *v2 in the below mentioned example. Then why
>  `conj' operation on them is returning different things.
>
> user> (def *v1 [1 2 3 4 5])
> #'user/*v1
> user> (def *v2 [2 3 4 5])
> #'user/*v2
> user> (= (rest *v1) *v2)
> true
> user> (def *v3 (conj (rest *v1) 0))
> #'user/*v3
> user> *v3
> (0 2 3 4 5)
> user> (def *v4 (conj *v2 0))
> #'user/*v4
> user> *v4
> [2 3 4 5 0]
> user> (map #(class %) (list *v1 *v2 *v3 *v4))
> (clojure.lang.PersistentVector clojure.lang.PersistentVector
> clojure.lang.Cons clojure.lang.PersistentVector)
> user>

(rest) returns a seq rather than a vector:

user> (class (rest *v1))
clojure.lang.PersistentVector$ChunkedSeq

and (conj) does different thing on seqs and vectors:

user> (conj '(1 2 3) 0)
(0 1 2 3)
user> (conj [1 2 3] 0)
[1 2 3 0]

namely, conj on a vector appends the new element to the vector, and
conj on a seq (or a list) prepends the new element.

So, in effect you are testing the equality of (0 2 3 4 5) and [2 3 4 5
0] which are not the same, as you found out.

Finally, the equality check on (rest *v1) and *v2 succeeds, because
(=) treats both (rest *v1) and *v2 as seqs and traverses both checking
each element for equality, i.e. it does not care that the containers
are of different types.

> Regards,
> nipra

-- 
  ! Lauri

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Richard Newman
> Maybe this ought to be fixed; i.e., if the reader sees #^{meta} 'foo  
> it applies the metadata to foo first, then quotes it, resulting in  
> the same thing as (quote #^{meta} foo).

Why introduce that special case, when you can simply do the second?

I don't support the view that it's OK for programmers to not know what  
they're doing, which in this case means knowing that 'foo reads as  
(quote foo).

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Query regarding `conj'

2009-11-27 Thread Richard Newman
>  (rest *v1) is equal to *v2 in the below mentioned example. Then why
>  `conj' operation on them is returning different things.

rest is giving you a seq. conj is thus producing a cons where the  
first is 0 and the rest is that seq. (Essentially, seqs are treated as  
lists, and thus print with parens.)

user=> (rest [1 2 3 4 5])
(2 3 4 5)

user=> (type (rest [1 2 3 4 5]))
clojure.lang.PersistentVector$ChunkedSeq

user=> (conj (rest [1 2 3 4 5]) 1)
(1 2 3 4 5)

user=> (type *1)
clojure.lang.Cons

user=> (rest *2)
(2 3 4 5)

user=> (type *1)
clojure.lang.PersistentVector$ChunkedSeq


If you want conj to act as if it's working on a vector, you need to  
give it a vector:

user=> (conj (vec (rest [1 2 3 4])) :a)
[2 3 4 :a]

user=> (conj (rest [1 2 3 4]) :a)
(:a 2 3 4)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Lein adding repos

2009-11-27 Thread Luke Renn
On Nov 27, 12:40 pm, David Nolen  wrote:
> Is there currently a simple way to add new maven2 repos to download from?

I haven't done it, but looking at the code you just add :repositories
[[id url]] to your project.clj.

Luke

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Sneak Peek

2009-11-27 Thread jim
I discovered a rather subtle bug as I was coding an example web-app,
so I haven't got the code out yet. Will ASAP.

That tutorial is going to take a little time to write, because as the
Haskell folks note, "Here be dragons!". The continuation monad is one
of the most powerful and can be considered the mother of all monads:

http://blog.sigfpe.com/2008/12/mother-of-all-monads.html

But it will turn your brain to mush if you're not careful.

Jim

Martin Coxall wrote:
> On Nov 25, 2:59 pm, Konrad Hinsen  wrote:
> > On 25.11.2009, at 15:32, jim wrote:
> >
> > > That's exactly what it is. I used the continuation monad from
> > > clojure.contrib.monads. After I get the code out, I'll be writing a
> > > tutorial on how it works which will also explain the continuation
> > > monad. I found that monad to be the most difficult to get my head
> > > around, but it's hugely powerful.
> >
> > I can confirm that impression... And only wish you good luck writing  
> > that tutorial!
> >
>
> From the Haskell boys:
>
> "Abuse of the Continuation monad can produce code that is impossible
> to understand and maintain."
>
> That sounds to me like a challenge.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Lein adding repos

2009-11-27 Thread Phil Hagelberg
On Nov 27, 10:09 am, Luke Renn  wrote:
> On Nov 27, 12:40 pm, David Nolen  wrote:
>
> > Is there currently a simple way to add new maven2 repos to download from?
>
> I haven't done it, but looking at the code you just add :repositories
> [[id url]] to your project.clj.

That's correct. I'll try to document this more thoroughly for the next
release.

-Phil

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Lein adding repos

2009-11-27 Thread David Nolen
Yes this worked for me. I was trying to add JOGL jars a dependency to a
project. Unfortunately now running into java.lang.Security Exceptions
because the JOGL jars are signed. blech.

On Fri, Nov 27, 2009 at 1:28 PM, Phil Hagelberg wrote:

> On Nov 27, 10:09 am, Luke Renn  wrote:
> > On Nov 27, 12:40 pm, David Nolen  wrote:
> >
> > > Is there currently a simple way to add new maven2 repos to download
> from?
> >
> > I haven't done it, but looking at the code you just add :repositories
> > [[id url]] to your project.clj.
>
> That's correct. I'll try to document this more thoroughly for the next
> release.
>
> -Phil
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Strange little difference with the reader and the java float parsers

2009-11-27 Thread Nathan Cunningham
I was working on a system that used the reader / pprint to load and
save data too and from the disk and I ran into a strange issue when I
reloaded my work from a JTable

Apparently there are cases where read will return a slightly different
float then the Float constructor will. For example:

(- (new Float "1786.28") (read-string "1786.28"))
2.929687502728484E-5

I'm not sure if its just my machine or not, (Ubuntu 9.04, AMD 64
Athlon X2, Using the Sun VM 6 and JDK 6)
any ideas or links?

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Strange little difference with the reader and the java float parsers

2009-11-27 Thread Hugo Duncan
On Fri, 27 Nov 2009 14:50:27 -0500, Nathan Cunningham  
 wrote:

> Apparently there are cases where read will return a slightly different
> float then the Float constructor will. For example:
>
> (- (new Float "1786.28") (read-string "1786.28"))
> 2.929687502728484E-5

read-string returns a Double for me...

--
Hugo Duncan

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Space leak with lazy sequences.

2009-11-27 Thread David Brown
On Fri, Nov 27, 2009 at 01:52:05PM +0200, Miron Brezuleanu wrote:

>not sure if it works here, but what about adapting advice from Stuart
>Halloway's Programming Clojure (pages 159-160, 'Losing your head') and
>use a function returning a sequence instead of a 'bound by let' name
>(the actual advice in the book is to use functions returning sequences
>instead of vars holding the head)? This is basically a delayed
>evaluation trick similar to your workaround with atoms.

That seems to work as long as you aren't using the sequence as part of
IO where the sequence is consumed in the middle.  I think the atom
trick is needed for my case as far as I can tell.

David

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Strange little difference with the reader and the java float parsers

2009-11-27 Thread Joost
On Nov 27, 9:32 pm, "Hugo Duncan" 
wrote:
> read-string returns a Double for me...

Yeah:

user> (class (read-string "1786.28"))
java.lang.Double
user> (- (new Double "1786.28") (read-string "1786.28"))
0.0

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread John Harrop
On Fri, Nov 27, 2009 at 12:46 PM, Richard Newman  wrote:

> > Maybe this ought to be fixed; i.e., if the reader sees #^{meta} 'foo
> > it applies the metadata to foo first, then quotes it, resulting in
> > the same thing as (quote #^{meta} foo).
>
> Why introduce that special case, when you can simply do the second?
>
> I don't support the view that it's OK for programmers to not know what
> they're doing, which in this case means knowing that 'foo reads as
> (quote foo).


I'm not advocating in favor of programmers not knowing what they're doing.
I'm advocating in favor of avoiding as many subtle gotchas as possible.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Functions and vars and meta-data

2009-11-27 Thread John Harrop
On Fri, Nov 27, 2009 at 1:23 PM, John Harrop  wrote:

> On Fri, Nov 27, 2009 at 12:46 PM, Richard Newman wrote:
>
>> > Maybe this ought to be fixed; i.e., if the reader sees #^{meta} 'foo
>> > it applies the metadata to foo first, then quotes it, resulting in
>> > the same thing as (quote #^{meta} foo).
>>
>> Why introduce that special case, when you can simply do the second?
>>
>> I don't support the view that it's OK for programmers to not know what
>> they're doing, which in this case means knowing that 'foo reads as
>> (quote foo).
>
>
> I'm not advocating in favor of programmers not knowing what they're doing.
> I'm advocating in favor of avoiding as many subtle gotchas as possible.
>

Interestingly, you can do what I suggested manually:

user=> (meta '#^{:foo 1}foo)
{:foo 1}

It's a bit ugly, but it works.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: Strange little difference with the reader and the java float parsers

2009-11-27 Thread Ron Thomas
user=> (- (new Double "1786.28") (read-string "1786.28"))
0.0

Following uip on what Hugo said, modifying your code to a double
returns the following.


On Nov 27, 1:32 pm, "Hugo Duncan" 
wrote:
> On Fri, 27 Nov 2009 14:50:27 -0500, Nathan Cunningham  
>
>  wrote:
> > Apparently there are cases where read will return a slightly different
> > float then the Float constructor will. For example:
>
> > (- (new Float "1786.28") (read-string "1786.28"))
> > 2.929687502728484E-5
>
> read-string returns a Double for me...
>
> --
> Hugo Duncan

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Alex Osborne
Stefan Kamphausen  writes:

>> I don't think the documentation is *wrong* per se, it just only seems to
>> cover the immutable types.
>
> Which is kind of wrong, isn't it?  I strongly believe that this should
> be changed.

Indeed.

> While I understand that the mutating functions will not apply to
> immutable types, I don't get why I can't create the metadata using the
> same interface.

Because the two operations have completely different semantics.  With
immutables a new object is created, with mutables an existing object is
changed.  Clojure could hide this behind the same function name, but
you'd still need to know the distinction anyway to work with these two
types of objects.  Clojure makes this explicit.  See what I say below on
Rich's avoidance of "apparent simplicity but hidden complexity".

> A *new* symbol?   I would have thought I'm getting the original symbol
> again.

Yes, one of the differences between symbols and keywords is that symbols
are created fresh each time while keywords are interned:

(identical? 'foo 'foo) ; => false
(identical? :foo :foo) ; => true

Both are immutable, thus symbols can have metadata (as you can have two
symbols that differ only by their metadata) but keywords can't, as two
keywords with the same name are the same object.

>> Note that (perhaps suprisingly) this doesn't work:
>>
>> (meta #^{:a 1} 'greet)

Perhaps I should also note that this *does* work:

  (meta '#^{a 1} greet)

As it becomes:

  (meta (quote greet))  ; <-- this greet symbol has metadata

> This is subtle!  It really feels like one of those things that will
> still feel creepy another 50 years from now.
> I'll have to meditate on this a bit.

Clojure is a very opinionated language and one of those opinions is that
Rich tries very hard to avoid incidental complexity.  At times this
means things may at first appear more complex on the surface than in
other languages, but this is because Clojure isn't trying to hide what's
going on under the hood from you. It's one of the things I really enjoy
about it: there's no "magic".  Clojure simplicity is real simplicity,
not apparent simplicity created by hiding the complexity under the bed.

It's possible and perhaps should even be expected for most Clojure
programmers to have a good understanding of how things work underneath.
With other languages, even if I've been using them for years I still
have little clue about how things actually get evaluated.  If I've taken
a course in compiler writing, I might know about things like abstract
syntax trees, parsers and lexers and all the special cases involved in
parsing if-then-else statements, but how it works in a particular
language is going to be a mystery unless I've written my own compiler.

As Meikel suggested, watch Rich's talks.  I think it's important to try
to understand the philosophy behind Clojure's design.  Rich has some
very strong messages and even if you don't agree with them, they're
definitely worth listening to and thinking about.

Cheers,

Alex

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: performance issues with multi-dimensional array

2009-11-27 Thread Christophe Grand
On Thu, Nov 26, 2009 at 11:49 AM, Amnon  wrote:

> I did, and it works like a charm. Couldn't figure out how to hint an
> array of objects (what should I put instead of the old #^objects?
> I still get it to work in 300 ms (which is not great but something I
> can live with).
>

You have to replace #^objects with #^"[Ljava.lang.Object;" (don't use a more
specialized type: it wouldn't help with aget/aset).



> Thanks for the replies,
>
> On Nov 25, 8:01 pm, David Nolen  wrote:
> > Read Christophe's post about multi-dim arrays. Reflection is getting in
> the
> > way here.
> >
> >
> >
> > On Wed, Nov 25, 2009 at 2:55 AM, Amnon  wrote:
> > > Hi Konrad,
> > > In the original post, I put in the code, it was removed by the post
> > > editor.
> > > The way I wanted it implement, I have the main in java (gui and
> > > stuff). I create a 3D array in java, it's an int array (i.e. int arr[]
> > > [][] ) and call with that array to clojure.
> >
> > > It can be done in java at least 3 orders of magnitude faster so I'm
> > > sure there is something I'm doing wrong.
> > > I'll appreciate any suggestion.
> > > Thanks,
> > > Amnon
> >
> > > I've squeezed my example into two functions:
> >
> > > (defn light [arr x y]
> > >(+ (aget arr x y 0) (aget arr x y 1) (aget arr x y 2))
> > >)
> >
> > > (defn grey [arr]
> > >(dotimes [x (length arr)]
> > >(dotimes [y (alength (aget  arr 0))]
> > >(let [lg (int (/ (light arr x y) 3))]
> > >(aset arr x y 0 lg)
> > >(aset arr x y 1 lg)
> > >(aset arr x y 2 lg)
> > >
> >
> > > On Nov 24, 8:35 pm, Konrad Hinsen  wrote:
> > > > On 24 Nov 2009, at 17:30, Amnon wrote:
> >
> > > > > I hope it's not the billion time you get the question.
> > > > > I wanted to use clojure for image processing. I have a 3
> dimensional
> > > > > array I'm passing to clojure from java.
> > > > > I then loop on the array to manipulate it.
> > > > > Even the simplest task takes about half a minutes (I expected it to
> be
> > > > > over in less than a second)
> >
> > > > Could you give some more details? For example, what is the Java class
> > > > you use for the 3D arrays? How are you accessing it from Clojure? How
> > > > do  you do the loops? How do you create the destination array, and
> how
> > > > do you fill it with the grey-scale values? I suspect that many of
> > > > these steps could be optimized, but it's hard to say without knowing
> > > > how your current code works.
> >
> > > > Konrad.
> >
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Clojure" group.
> > > To post to this group, send email to clojure@googlegroups.com
> > > Note that posts from new members are moderated - please be patient with
> > > your first post.
> > > To unsubscribe from this group, send email to
> > > clojure+unsubscr...@googlegroups.com
> >
> > > For more options, visit this group at
> > >http://groups.google.com/group/clojure?hl=en
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>



-- 
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.cgrand.net/ (en)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: AOT'd namespaces lose their metadata

2009-11-27 Thread Phil Hagelberg
Tom Faulhaber  writes:

> I'm super-excited about Leiningen, btw. I've been thinking about how
> to turn my autodoc stuff into a Leiningen plugin so that we can get
> easy doc for any project.

Awesome. We've already got someone started working on a doc plugin;
please join the leiningen mailing list if you'd like to coordinate work
on that. The contrib HTML documentation is really great, and I'd love it
if it were easier for more projects to produce output like that.

http://groups.google.com/group/clojure

-Phil

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Stefan Kamphausen
Hi,

On Nov 27, 11:06 pm, "Alex Osborne"  wrote:
> > A *new* symbol?   I would have thought I'm getting the original symbol
> > again.
>
> Yes, one of the differences between symbols and keywords is that symbols
> are created fresh each time while keywords are interned:
>
> (identical? 'foo 'foo) ; => false
> (identical? :foo :foo) ; => true

Whoa!  Cool example.  This is rather an important point, I think.  I
mean it's not important, when your "only" programming with Clojure,
which will usally work, and you always have the REPL...  But it
becomes more important for those, trying to understand.  It's about
grokking a language's design vs. experimenting with the code long
enough so that it seems to work.

> >> Note that (perhaps suprisingly) this doesn't work:
>
> >> (meta #^{:a 1} 'greet)
>
> Perhaps I should also note that this *does* work:
>
>   (meta '#^{a 1} greet)

To be honest, I think it looks even worse.  There is some reader macro
which by happy accident works in a certain way together with the other
read syntax.  No, I don't think it should work.

> Clojure is a very opinionated language and one of those opinions is that
> Rich tries very hard to avoid incidental complexity.

Which is a Good Idea(tm).

> At times this
> means things may at first appear more complex on the surface than in
> other languages, but this is because Clojure isn't trying to hide what's
> going on under the hood from you. It's one of the things I really enjoy
> about it: there's no "magic".  Clojure simplicity is real simplicity,
> not apparent simplicity created by hiding the complexity under the bed.

Hm, is it possible you're coming from Java here?  For me, coming more
from CL than Java, some things in Clojure feel very --let's say--
Perlish: there is so much syntax there.  Don't get me wrong, I think
Clojure delivers what arc promised, it does a hell of a job
revolutionizing Lisp.  I hardly can disagree with many of the design
principles, I just like the documentation to tell the whole story so
not everyone new to Clojure will have to figure it out for him/
herself.

> It's possible and perhaps should even be expected for most Clojure
> programmers to have a good understanding of how things work underneath.

Agreed.  The docs should say so, agreed?  I'd very much like to
volunteer on docs, but I just don't know how I could keep up with
development, since I am doing almost all my Clojure stuff after work
when the children are in bed.

> With other languages, even if I've been using them for years I still
> have little clue about how things actually get evaluated.

That may be related to the lesser importance of order of evaluation in
other languages.  I mean, Perl has a *lot* of syntax, but usually it
all takes place at the same time, or at least, you as a developer
won't have to care.  Anyway, not worth a discussion.

> As Meikel suggested, watch Rich's talks.

I do, and I really like them.  One can hear, that Rich's got a story
to tell.  They are very valuable for understanding the philosophy
behind many of Clojure's design decisions.  The screencast/
presentation/video-thing helps learning a new language nowadays.

>  I think it's important to try to understand the philosophy behind Clojure's 
> design.

Wait, I've heard that before... Deja vu?

> Rich has some
> very strong messages and even if you don't agree with them, they're
> definitely worth listening to and thinking about.

There, another Deja vu. ;-)


Alex, John, Meikel, Richard,
thanks for taking your time.

Kind regards,
Stefan

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Richard Newman
> Whoa!  Cool example.  This is rather an important point, I think.  I
> mean it's not important, when your "only" programming with Clojure,
> which will usally work, and you always have the REPL...  But it
> becomes more important for those, trying to understand.  It's about
> grokking a language's design vs. experimenting with the code long
> enough so that it seems to work.

Yeah, pretty awesome :)

I love how almost any technical question on this list can be answered  
by a three-line REPL interaction!

>>   (meta '#^{a 1} greet)
>
> To be honest, I think it looks even worse.  There is some reader macro
> which by happy accident works in a certain way together with the other
> read syntax.  No, I don't think it should work.

It's not really a happy accident, it's as specified. ' quotes the next  
read form. #^ applies metadata to the next read form. Granted, I have  
some experience with reader macros from CL, but I feel this should be  
an area that a moderately well-educated programmer should encounter,  
perhaps trip up, say "oh yes, I see why that happens", and move on,  
rather than viewing it as some kind of fault to be corrected.

When you realize that reader macros and quotation marks are a way of  
communicating with the reader that's parsing the text of your code,  
things become a little simpler.

> Hm, is it possible you're coming from Java here?  For me, coming more
> from CL than Java, some things in Clojure feel very --let's say--
> Perlish: there is so much syntax there.

Coming from CL myself, I have two inputs to this debate.

Firstly, CL has more syntax than one at first thinks (for a Lisp, at  
least) — particularly the raft of reader macros (including  
configurable ones), but also things like format string keywords. It  
simply doesn't have a plurality of *delimiters*: just double-quote,  
block comment, and parens, really.

Secondly, I view most of Clojure's syntax — mainly delimiters for  
literal maps, sets, and vectors — to be completely worth the sacrifice  
of simplicity. The delimiter characters are there, and it would be  
foolish to waste them.

The things that makes Perl "Perlish" to me are the special variable  
line-noise ($/, $_, $&, etc.), contexts (scalar etc.), and extreme  
parse-time lexical manipulation, all of which conspire to make the  
meaning of a piece of code enormously context- and runtime-dependent.  
(For example, you can't parse Perl without executing it.)

I don't think Clojure's additional delimiters compared to Common Lisp  
moves it towards Perl in this way. I hate Perl, and I don't have that  
reaction to Clojure! :)


> I just like the documentation to tell the whole story so
> not everyone new to Clojure will have to figure it out for him/
> herself.

As I'm sure you know, this is an unfortunate consequence of Clojure's  
youth. Clojure only turned 2 last month, so I think its vibrant  
library collection and community are actually surprisingly large and  
vigorous. Docs take time to accrete, and Rich is devoted more to  
development than to filling in perceived gaps; a lot of knowledge is  
tied up in mailing list posts, videos, and presentations. I know Tom  
and others have been working to improve the doc situation.

> Alex, John, Meikel, Richard,
> thanks for taking your time.

My pleasure. I love this community!

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread Alex Osborne
Stefan Kamphausen  writes:

>>   (meta '#^{a 1} greet)
>
> To be honest, I think it looks even worse.  There is some reader macro
> which by happy accident works in a certain way together with the other
> read syntax.  No, I don't think it should work.

I agree this is ugly and unintuitive and I wouldn't use it in a real
program, I'd use with-meta instead.  I included it as an illustration
that some reader macros like ~, ' and @ are just shorthand for regular
macros: unquote, quote and deref respectively, while others change the
behaviour of the reader, like #^, ; and #_.

Unfortunately syntax-quote (`) currently falls into the latter camp, but
I hope that will change in Clojure-in-Clojure.  Try this to see
something scary:

'`(foo)
=> (clojure.core/seq
(clojure.core/concat
 (clojure.core/list 
  (quote user/foo

The reason it needs to break the list down like that is so that it can
implement splicing-unquote.

> Hm, is it possible you're coming from Java here?  For me, coming more
> from CL than Java, some things in Clojure feel very --let's say--
> Perlish: there is so much syntax there.  Don't get me wrong, I think
> Clojure delivers what arc promised, it does a hell of a job
> revolutionizing Lisp.

Yes, I have a mainly non-lisp background, much C, Python, Ruby and
some Java and Haskell and various other languages.  I had dabbled in
Common Lisp and Scheme a bit before discovering Clojure but found Common
Lisp very complex and Scheme very verbose and the lack of syntax for
common data structures like hash tables frustrating.  So perhaps I fall
towards the slightly more sugary side of the spectrum compared to
Scheme, especially when it comes to data structures but I do agree that
things might be clearer without the ^ and #' reader macros and
restricting #^ just to type hints.

> I hardly can disagree with many of the design
> principles, I just like the documentation to tell the whole story so
> not everyone new to Clojure will have to figure it out for him/
> herself.

Yes.  Stuart's book "Programming Clojure" is a much better introduction
to the language.  The website is mostly okay as a reference but it is
incomplete and usually out of date.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Functions and vars and meta-data

2009-11-27 Thread DTH
On Nov 27, 5:46 pm, Richard Newman  wrote:
>
> I don't support the view that it's OK for programmers to not know what
> they're doing, which in this case means knowing that 'foo reads as
> (quote foo).

FWIW I *strongly* agree; getting reader macros straight in my head was
a *big* help in macro writing; the special case would reinforce the
"wrong" impression, IMO

On Nov 27, 10:06 pm, "Alex Osborne"  wrote:
> Clojure is a very opinionated language and one of those opinions is that
> Rich tries very hard to avoid incidental complexity.  At times this
> means things may at first appear more complex on the surface than in
> other languages, but this is because Clojure isn't trying to hide what's
> going on under the hood from you. It's one of the things I really enjoy
> about it: there's no "magic".  Clojure simplicity is real simplicity,
> not apparent simplicity created by hiding the complexity under the bed.
>

Yes! One of the greatest aspects of Clojure is the clean consistency
of the base language.  One of the things that put me off really using
Scala in anger was that the language itself seemed to have a lot of
corner cases etc. (1)  Scala was easier to pick up coming from Java,
but Clojure easier to really get to grips with.

-Dave

1. This is entirely subjective of course; if you consider Scala well-
nigh spherical in its lack of corners, roll on.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Krishnamurthi's Automata in Clojure (OutOfMemoryError)

2009-11-27 Thread Charles Gordon
I've been working on a problem that requires me to write a small state
machine for processing XML documents. Out of curiousity (I'm new to
functional programming) I hit Google to see how automata are written
in other functional languages. I found Shriram Krishnamurthi's paper:

http://lambda-the-ultimate.org/node/569

It is discussed further, along with a Clojure implementation,  here:

http://list.cs.brown.edu/pipermail/plt-scheme/2007-November/thread.html#21571

The implementation listed there doesn't work, and is before Rich
introduced "letfn", so I decided to try my own implementation using
letfn and trampoline:

(defn machine [start-stream]
  (letfn [(init [stream]
#(cond (empty? stream) true
(= \c (first stream)) (more (rest stream))
:else false))
  (more [stream]
#(cond (empty? stream) true
(= \a (first stream)) (more (rest stream))
(= \d (first stream)) (more (rest stream))
(= \r (first stream)) (end (rest stream))
:else false))
  (end [stream]
   #(cond (empty? stream) true
   :else false))]
(trampoline init start-stream)))

This works, but if I try to run it on an infinite sequence, it
eventually runs out of memory:

(machine (iterate (fn [c] (if (= c \c) \a \d)) \c))

Java heap space
  [Thrown class java.lang.OutOfMemoryError]

I don't understand the underlying model of Clojure's runtime well
enough to understand why this is occurring. I'm not getting a stack
overflow error, so it seems likely that something is holding onto
memory (perhaps the entire stream?). Does anyone have any insight into
this?

Thanks!
Charles Gordon

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Atomic reloads and snapshots of namespaces

2009-11-27 Thread André Thieme
On 27 Nov., 04:33, pmf  wrote:
> On Nov 26, 7:39 pm, Richard Newman  wrote:
>
> > "Re consistency: I seem to recall Pascal Costanza working on  
> > activation of layers, so you can swap a whole set of stuff across your  
> > program. He spoke about it at ILC2009, but I'm not sure I've found the  
> > right paper. Common Lisp-specific, though."
>
> > He showed a website, paused mid-request, where he swapped out several  
> > functions. Unpausing the request still ran to completion with the old  
> > functions. A new request ran with the new functions. Impressive.
>
> CLOS and the MOP allows you to change a class and have all already
> existing instances be transformed into the new form (in an automatic
> or user defined way), which makes these things much easier to achieve
> than in Java- and Clojure-world.

I think there is a misunderstanding here.
Clojure makes it easy to update state, and a MOP is not needed.
But I am not talking about adding/removing slots to an object, but
instead
of modifying *functions*.

Let‘s say we have the functions A, B, C, D, E, F and G.
A is calling B, B is calling C, C is calling D, and so on.
Now a request R1 comes in, function A is called and this chain
continues to,
say, E.
Now a reload happens. Some functions A-G are changed. B now may expect
C
to return not a value v1, but instead a vector of the values [v1 v2].
Even if the signatures didn‘t change and no exception would be thrown,
it
could destroy consistency of the data anyway.
What I want is that any request R1, R2, R3, ... will continue to use
the
chain A-G.
A reload should happen atomically. All functions should load and eval
in
the background and only become callable if everything was reloaded.
All new incoming requests will now go through the new chain A-G (maybe
some
new functions came in and it is now A-Z, or others were removed so
that it
will be A-Z but without D and E) while at the same time R1 continues
with
the old set of functions.
That way each user of (my) web services would get a constintent
answer.

Some users may be in a session that can go for minutes or hours or
even
days. In such a case we may be interested that as long this session
exists
this users requests will always be handled with the old set of
functions.
So, a way to make a “namespace snapshot” would be interesting. Each
time
when a request comes in one can snapshot the code, and only then begin
to
handle the request. If a session gets created one can store the
snapshoted
functions in the session object and read it out of there.

I don‘t know if this makes sense and what problems may arise, and even
if
such a proposal sounds nice in theory it may be too hard to develop,
for
now.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Krishnamurthi's Automata in Clojure (OutOfMemoryError)

2009-11-27 Thread Mark Triggs
Hi Charles,

I notice I can stop your version from running out of memory with a very
small change.  Changing from:

  ;; the [f & args] form of trampoline
  (trampoline init start-stream)

to:

  ;; the [f] form of trampoline
  (trampoline #(init start-stream))

seems to work as expected.  I would hazard a guess that this might be
the same issue as described in this thread:

  http://groups.google.com/group/clojure/msg/dfb1c1d68ac7e742

Cheers,

Mark


Charles Gordon  writes:

> The implementation listed there doesn't work, and is before Rich
> introduced "letfn", so I decided to try my own implementation using
> letfn and trampoline:
>
> (defn machine [start-stream]
>   (letfn [(init [stream]
> #(cond (empty? stream) true
> (= \c (first stream)) (more (rest stream))
> :else false))
>   (more [stream]
> #(cond (empty? stream) true
> (= \a (first stream)) (more (rest stream))
> (= \d (first stream)) (more (rest stream))
> (= \r (first stream)) (end (rest stream))
> :else false))
>   (end [stream]
>#(cond (empty? stream) true
>:else false))]
> (trampoline init start-stream)))
>
> This works, but if I try to run it on an infinite sequence, it
> eventually runs out of memory:
>
> (machine (iterate (fn [c] (if (= c \c) \a \d)) \c))
>
> Java heap space
>   [Thrown class java.lang.OutOfMemoryError]

-- 
Mark Triggs


-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Atomic reloads and snapshots of namespaces

2009-11-27 Thread John Harrop
On Fri, Nov 27, 2009 at 7:48 PM, André Thieme
wrote:

> Let‘s say we have the functions A, B, C, D, E, F and G.
> A is calling B, B is calling C, C is calling D, and so on.
> Now a request R1 comes in, function A is called and this chain
> continues to,
> say, E.
> Now a reload happens. Some functions A-G are changed. B now may expect
> C
> to return not a value v1, but instead a vector of the values [v1 v2].
> Even if the signatures didn‘t change and no exception would be thrown,
> it
> could destroy consistency of the data anyway.
> What I want is that any request R1, R2, R3, ... will continue to use
> the
> chain A-G.
> A reload should happen atomically. All functions should load and eval
> in
> the background and only become callable if everything was reloaded.
> All new incoming requests will now go through the new chain A-G (maybe
> some
> new functions came in and it is now A-Z, or others were removed so
> that it
> will be A-Z but without D and E) while at the same time R1 continues
> with
> the old set of functions.
> That way each user of (my) web services would get a constintent
> answer.
>

There is one way to achieve something like that already, though you have to
explicitly set up certain functions to be replaceable in this transactional
manner:

...

(def B (ref (fn [args] body)))

(def A (ref (fn [args] body ... (@B foo bar) ...)))

(defn something-that-calls-A [args]
  (dosync
(@A some-stuff)
etc.))

(defn replace-A-and-B [new-A-fn new-B-fn]
  (dosync
(ref-set A new-A-fn)
(ref-set B new-B-fn)))

During the something-that-calls-A dosync everything will see a snapshot of
the "ref world" in which no replace-A-and-B transaction is half-completed,
so a particular compatible pair of functions will be seen.

Related means could also be used, e.g.

(def fn-set (atom {:B (fn [fn-set other-args] body)
   :A (fn [fn-set other-args]
   body ... ((:B fn-set) fn-set foo bar) ...)}))

(defn session-start [params]
  (let [fns @fn-set]
((:A fns) fns params)))

(defn replace-fn-set [fn-map]
  (reset! fn-set fn-map))

Each session or whatever holds a reference to a map of the functions to
call, and the functions pass the map around and call the functions through
the map. The map, being a Clojure map, is immutable, so a session is
guaranteed to always use a consistent group of functions. Changing the
function map in the global atom changes the map used by new sessions,
without affecting pre-existing ones.

If each session or whatever is associated with its own thread, you can also
go with

(def *fn-map* nil)

(def fn-set (atom {:B (fn [args] body)
   :A (fn [args]
body ... ((:B *fn-map*) foo bar) ...)}))

(defn session-start [params]
  (binding [*fn-map* @fn-set]
((:A *fn-map*) params)))

(defn replace-fn-set [fn-map]
  (reset! fn-set fn-map))

which avoids the ugliness of passing the session's function map as a
parameter all over the place. You can even dispense with the keyword lookups
with a bit more effort:

(def *A* nil)

(def *B* nil)

(def fn-set (atom {:B (fn [args] body)
   :A (fn [args]
body ... (*B* foo bar) ...)}))

(defn session-start [params]
  (let [fn-map @fn-set]
(binding [*A* (:A fn-map)
  *B* (:B fn-map)]
  (*A* params

(defn replace-fn-set [fn-map]
  (reset! fn-set fn-map))

This version uses separate thread-local bindings for the individual
functions, which can be called like normal Clojure functions (because they
ARE normal Clojure functions). Each session binds all of them based on a
single dereference of the fn-set atom, so again has a consistent set of
functions, which replace-fn-set will change for subsequent (but not
preexisting) sessions.

I'm sure you can dream up more ways to achieve similar results. (A cookie if
you can think up one using agents.)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en