Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Meikel Brandmeyer
Salut Laurent,

On 17 Nov., 16:53, Laurent PETIT  wrote:

> while a good description of how things work in 1.2

It doesn't even do that. This is exactly *not* the way it works in
1.2, because self-references don't go through the Var. I'd be curious
to know, why calling the function itself is made a special case. To
allow this assignements to a different Var and re-defing/removal of
the original Var?

> it's not accurate for 1.3, and my point was that Stu's description
> of how 1.3 works (by using words like "the function is recompiled")
> does not match with my own knowledge of what had been done
> in 1.3 the days just before the conj.

Forgetting for a second that my explaination is plain wrong... There
wouldn't be a difference between 1.2 and 1.3. "retrieve something from
the Var" does say nothing about this "retrieval" being cached in some
way or not. Even putting the reference directly there and recompiling
(or doing some other magic to make Repl development make work again)
has basically the same effect. So the description would be valid for
1.2 and 1.3 if the self reference would go through the Var. But as I
said: it doesn't. So the description is "Quark",

> Since then, I've been away from #clojure (to my regret) and maybe I've
> missed new evolutions on the way it's handled in master.

I'm missing where development is going on in general. Nothing on the
mailing list anymore. The last times I lurked #clojure there was no
dev talk there. Some stuff seems to be done on dev.clojure.org. But I
find it hard to follow this stuff. Clojure has gone "closed
development", so to say. (I have no problem with Rich coming up with
ideas beyond democratic decisions. In fact I think this non-democracy
is a Good Thing. However I'd like to follow what's going...)

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: Calling function in required library in a different namespace

2010-11-17 Thread Meikel Brandmeyer
Hi,

On 18 Nov., 04:48, Adrian Cuthbertson 
wrote:

> > in db.clj
> > I have
> >  (:require [some-library :as mylib])
> > in api.clj:
> > I have (:require [myapp.db :as db])
> > I then want to call mylib/somefunction -
>
> You can use "some-library/..." directly after requiring db, e.g;
>
> xxlib.clj...
> (ns xxlib)
> (defn xxfoo [] :xxfoo)
>
> db.clj...
> (ns db
>   (:require [xxlib :as mylib]))
> (defn dbfoo[] :dbfoo)
>
> repl...
> Clojure 1.2.0
> (require ['db :as 'db])
> (xxlib/xxfoo)
> :xxfoo

Please, no! This hides the dependency on a third library. As long as
automatic loading for unresolved namespace references is in place,
this is not a good idea. And even then an explicit require should be
preferred.

What is wrong about: (require '[myapp.db :as db] '[some.xxl.ib :as
some-lib])?

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: Ghost Vars?

2010-11-17 Thread Alex Osborne
Hi Alyssa,

Alyssa Kwan  writes:

> For what I'm doing (making functions durable), it raises the
> question:  If you persist a function that points to a var, restart the
> JVM, and deserialize/load the function from a data store, what should
> happen?

So you're doing something like this?

   (def x 5)
   (def myref (dref (fn [] x) :somekey store))

I guess the issue we're talking about at the moment is persisting var
references, not fns (which as Ken mentioned is its own kettle of fish)
so I'll simplify to just a dref containing a reference to a var:

   (def x 5)
   (def myref (dref #'x :somekey store))

> 1) In the loading thread, if a var exists with the same namespace and
> symbol, set the internal reference to that var.
>a) If the function is then passed to a different thread that has a
> different var with that same namespace and symbol, the function will
> still point to the one that was in the loader thread at the time the
> function was deserialized/loaded.

I don't think this situation is possible because Namespace.mapping
(which maps symbols to vars and classes) is *not* thread-local.  For a
given namespace and symbol all threads will resolve the same var object.

It's the binding of the Var to a value that can be thread-local.
You shouldn't have to worry about it, as it happens in the dynamic
environment when the fn is called, not when it is loaded.

> 2) In the loading thread, if a var does not exist with that same
> namespace and symbol:
>a) Throw an exception saying that the var doesn't exist.
>b) Create the var with no namespace and symbol and no value.  Wait
> until the function is called to throw an exception saying that the var
> is unbound.

Ow, this is making my head hurt. ;-)  Consider this fairly common case:

;; sydney.clj
(ns sydney)

(def some-dref (dref nil :somekey store))

;; melbourne.clj
(ns melbourne
  (:require sydney))

(def some-var 1)

(dosync 
  (when (nil? @sydney/some-dref)
 (ref-set sydney/some-dref #'some-var))

Suppose you execute melbourne.clj.  What happens?  On the first run:

1. sydney.clj is loaded, some-dref is initialized to nil.

2. melbourne.clj is loaded, the transaction is exeucted, some-dref is
now #'some-var, this gets saved to disk.

Then you restart the JVM and:

1. sydney.clj is loaded, some-dref's value is deserialized, but whoops,
#'some-var doesn't exist yet.

Okay, perhaps you can get around that by only deserializing when
first derefed, instead of at initialization like you currently do.

My preference would probably lean towards (2a).  Anyone using drefs is
going to have to deal explicitly with the issue of objects that aren't
serializable (sockets, streams), so make them be very careful about what
they put in them.

>c) Create the var with no namespace and symbol but with the value
> that the var had in the persisting thread.  There's no way to access
> the var to modify it.
>d) Create the var with no namespace and symbol but with the value
> that the var had in the persisting thread.  It's accessible somehow
> (maybe the meta map), so the user can recover it and dynamically bind
> over it.
>e) Create the var with the namespace and symbol in the function,
> modifying the RT var-space of the loading thread.  Don't initialize
> the var.  This gives the user a chance to dynamically bind over it.
> If the function is called before binding the var to something, throw
> an exception saying that the var is unbound.
>f) Create the var with the namespace and symbol in the function,
> with the value that the var had in the persisting thread.

Ppersisting the value of the var quickly leads to a cascade of extra
stored data, because you not only have to persist it, but any vars it
references in turn. 

Setting :static aside for the moment, suppose you persist this:

(fn [x] (empty? x))

Then you have to persist the value of #'empty? which is:

(fn [coll] (not (seq coll)))

So then you have to persist #'not and #'seq as well and so on.

> The normal case (1) is straightforward, and (1a) is what would happen
> without se/des anyways.  (2) is tricky.  (2f) is most robust, but
> really violates least surprise.  I think Meikel's comments lean
> towards (2a).
>
> Also, the thread-local nature of vars raises the question of what
> should happen when deserializing the same function from different
> threads.  If I create durable refs from different threads pointing to
> the same store/key combo, does the thread that gets there first
> control which var the deserialized function references?  Or does each
> thread get it's own ref?  If so, how do you reconcile that there are
> multiple refs being stored under the same store/key?  That's
> untenable, but it seems totally arbitrary to simply say that the first
> thread that gets there determines which var the function is bound to
> for the duration of the JVM instance.

As I said above, it's the value of the var that is thread-local, not

Re: Closures eat permgen?

2010-11-17 Thread Matt Fowles
Ken~

CMS (Concurrent Mark Sweep) is part of a multi-stage generational GC.  It is
the newest GC in a released version of the JVM (the G1 GC not having been
released yet).

With the below settings, the young gen is divided into Eden and two survivor
spaces.  The survivor spaces act as generations for young objects before
they are tenured into the old gen.  The concurrent mark sweep is only used
for the old generation and is far more than a simple mark-sweep GC.

If you are curious I can provide a somewhat more detailed explanation of the
different collectors and phases, but I can assure you that these settings
are very good defaults for high performance systems.

Matt

On Wed, Nov 17, 2010 at 10:37 PM, Ken Wesson  wrote:

> On Wed, Nov 17, 2010 at 10:12 PM, Matt Fowles 
> wrote:
> > Ken~
> > Not sure what jvm args you are running with, but not all GC settings will
> > sweep or clear the permgen.  You should try it with:
> > -XX:+CMSClassUnloadingEnabled
> > -XX:+CMSPermGenSweepingEnabled
> > -XX:+UseParNewGC
> > -XX:+UseConcMarkSweepGC
> > -XX:+CMSParallelRemarkEnabled
>
> Maybe I will.
>
> (Use a mark-sweep GC instead of the generational one that all newer
> JVMs use by default, though? That will really hurt GC performance.)
>
> --
> 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

Re: Calling function in required library in a different namespace

2010-11-17 Thread Adrian Cuthbertson
> in db.clj
> I have
>  (:require [some-library :as mylib])
> in api.clj:
> I have (:require [myapp.db :as db])
> I then want to call mylib/somefunction -

You can use "some-library/..." directly after requiring db, e.g;

xxlib.clj...
(ns xxlib)
(defn xxfoo [] :xxfoo)

db.clj...
(ns db
  (:require [xxlib :as mylib]))
(defn dbfoo[] :dbfoo)

repl...
Clojure 1.2.0
(require ['db :as 'db])
(xxlib/xxfoo)
:xxfoo

Does that help?
- Rgds, Adrian.

-- 
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: Calling function in required library in a different namespace

2010-11-17 Thread Ken Wesson
On Wed, Nov 17, 2010 at 10:26 PM, Victor -  wrote:
> On Wed, Nov 17, 2010 at 9:51 PM, Ken Wesson  wrote:
>> Why not just have, in db.clj.
>>
>> (def somefunction mylib/somefunction)
>
> I used to do that before, but I realized I was introducing a level of
> indirection at a stage when the exact function signatures weren't clear yet.
> I do agree that the preferred final solution can well be to always call
> through function in the other namespace, though I think there may be
> exceptions..

If you're worried about having files that don't themselves :require or
:use mylib break if mylib/somefunction's signature changes, you can
add a real layer of indirection:

(defn somefunction [& args]
  (apply mylib/somefunction args))

and if mylib later changes, you can change db/somefunction to do
something more complicated when calling mylib/somefunction. JIT will
mostly kill the overhead of the extra indirection. Of course it's
still possible a change to mylib's somefunction will require changes
at all of db/somefunction's call sites and not just a change to
db/somefunction, but a kind of compilation-unit-granularity Law of
Demeter is at least observed now, where mylib changes may mean db
needs to change (db :requires or :uses mylib) and db changes may mean
foobar needs to change (foobar :requires or :uses db).

P.S. please don't top-post. It's a shame that the behavior of the
gmail/Google Groups interface seems to encourage top-posting; try to
resist this.

-- 
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: Closures eat permgen?

2010-11-17 Thread Ken Wesson
On Wed, Nov 17, 2010 at 10:12 PM, Matt Fowles  wrote:
> Ken~
> Not sure what jvm args you are running with, but not all GC settings will
> sweep or clear the permgen.  You should try it with:
> -XX:+CMSClassUnloadingEnabled
> -XX:+CMSPermGenSweepingEnabled
> -XX:+UseParNewGC
> -XX:+UseConcMarkSweepGC
> -XX:+CMSParallelRemarkEnabled

Maybe I will.

(Use a mark-sweep GC instead of the generational one that all newer
JVMs use by default, though? That will really hurt GC performance.)

-- 
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: Ghost Vars?

2010-11-17 Thread Ken Wesson
On Wed, Nov 17, 2010 at 9:57 PM, Alyssa Kwan  wrote:
> Hi Alex,
>
> OK, I agree.  Dynamic vars are not the same as traditional dynamic
> scoping.
>
> For what I'm doing (making functions durable), it raises the
> question:  If you persist a function that points to a var, restart the
> JVM, and deserialize/load the function from a data store, what should
> happen?

How are you planning to persist a function? The clojure reader can't
read functions output with spit or println.

I can think of at least three ways to build a framework for persisting
functions but none run into problems with vars.

If the functions are expressible in terms of parameters and a finite
set of codes/algorithms that use the parameters together with the
function arguments, you can persist just the parameters; for example,

(defn make-my-fn [foo bar]
  [{:foo foo :bar bar} (fn [baz quux] (do-stuff-with foo bar baz quux))])

(defn call-my-fn [f baz quux]
  ((second f) baz quux))

(defn save-my-fn [f file]
  (spit file (first f)))

(defn load-my-fn [file]
  (let [parm-map (with-open ... blah blah ... file ... blah blah ...)])
  (make-my-fn (:foo parm-map) (:bar parm-map)))

If the functions are more varied and the code is different every
time/arbitrary, you need something more sophisticated.

Option 2 is to turn to the Dark Side and use eval:

(defn make-fn* (arg-vec & body)
  [[arg-vec body] (eval `(fn ~arg-vec ~...@body))])

(defmacro make-fn (arg-vec & body)
  (make-my-fn* ~arg-vec (quote ~...@body)))

(defn call-fn [f & args]
  (apply (second f) args))

(defn save-fn [f file]
  (spit file (first f)))

(defn load-fn [file]
  (let [[arg-vec body] (with-open ... blah blah ... file ... blah blah ...)])
  (apply make-fn* arg-vec body))

This of course runs into the permgen-leak problem mentioned in another
thread recently.

A third option avoids evil eval and the permgen leak but won't run the
custom functions nearly as fast at runtime and is much, MUCH more work
to implement. It probably makes security easier, though (e.g. avoiding
infectability of your app by macro viruses like MSWord is vulnerable
to).

That option is to implement an interpreter for a custom language whose
code is written and read. It may again use sexps (and that will save
you from having to write a parser -- Clojure's reader will do that job
handily for you); the structure will probably be similar to make-fn
etc. directly above, but with call-fn invoking the interpreter on the
function source and the "function" object being just the source, not a
vector of the source and a compiled function. You might also create a
compiled representation (e.g. bytecode) and interpret that instead of
sexps in call-fn; make-fn* would compile a sexp to bytecode and the
"function" object would be a vector of bytecode. The bytecode or
directly-interpreted source would also be what got saved and loaded
from disk (so load-fn would no longer go through make-fn*, and in the
directly-interpreted case, make-fn* and make-fn would no longer exist
but you'd probably want call-fn to become call-fn* and have a call-fn
macro that quotes the second argument for you).

The var binding issue is not present in any of the three cases.
Closures would bind the appropriate vars where they appeared in your
project's source code and there'd be no mucking about with vars when
loading saved parameters to recreate a closure with particular
closed-over parameter values.

Eval would see whatever vars are visible in the environment in which
eval runs. Unfortunately, (doc eval) doesn't have much detail, and in
particular doesn't say what environment eval sees, though it doesn't
seem to include local variables in the eval's lexical surrounds:

user=> (let [x 1] (eval 'x))
#

It does however seem to see global variables in the *current*
namespace when eval is called:

user=> (def x 1)
#'user/x
user=> (eval 'x)
1
user=> (ns goober)
nil
goober=> (def x 2)
#'goober/x
goober=> (defn foo [] (eval 'x))
#'goober/foo
goober=> (foo)
2
goober=> (ns user)
nil
user=> x
1
user=> (goober/foo)
1

Note that foo returns 1 when called from in user and 2 when called
from in goober. This can be fixed with syntax quote:

goober=> (defn foo [] (eval `x))
#'goober/foo
goober=> (foo)
2
goober=> (ns user)
nil
user=> x
1
user=> (goober/foo)
2

or by putting (def goober-ns *ns*) in goober and putting a (binding
[*ns* goober-ns] ... ) around the call to eval to force the eval to
occur in the goober namespace.

Finally, the interpreter option allows full freedom: any of your
application's vars can be made visible or not within the interpreter,
under whatever names, and each one may be made read-only or
redefinable as you see fit. (If any are redefinable with the changes
needing to be visible outside the interpreter, then the interpreter
needs to have an instruction that results in a set! call.) Again,
though, the interpreter is considerably more work and will run the
custom functions slower than the other two options.

-- 
You received this mess

Re: Calling function in required library in a different namespace

2010-11-17 Thread Victor -
I used to do that before, but I realized I was introducing a level of
indirection at a stage when the exact function signatures weren't clear yet.
I do agree that the preferred final solution can well be to always call
through function in the other namespace, though I think there may be
exceptions..

On Wed, Nov 17, 2010 at 9:51 PM, Ken Wesson  wrote:

> On Wed, Nov 17, 2010 at 9:36 PM, Victor Olteanu 
> wrote:
> > Hi,
> > Please excuse my newbie ignorance - I would like to do something that
> seems
> > pretty basic, yet I couldn't figure it out yet.
> > I would like to call a function that is loaded in a different namespace,
> but
> > without having to load the library again in the current namespace - more
> > precisely:
> > in db.clj
> > I have
> >  (:require [some-library :as mylib])
> > in api.clj:
> > I have (:require [myapp.db :as db])
> > I then want to call mylib/somefunction - essentially a function in the
> > loaded library in the "db" namespace. Trying to do "db/somefunction",
> > perhaps obviously, is failing.
> > I then attempted to write a macro that would call a function in a
> different
> > namespace than the current one, but I couldn't find a way to specify a
> > namespace in a macro definition.
>
> Why not just have, in db.clj.
>
> (def somefunction mylib/somefunction)
>
> ?
>
> --
> 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

Re: Closures eat permgen?

2010-11-17 Thread Matt Fowles
Ken~

Not sure what jvm args you are running with, but not all GC settings will
sweep or clear the permgen.  You should try it with:

-XX:+CMSClassUnloadingEnabled
-XX:+CMSPermGenSweepingEnabled
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled

Matt

PS - http://blogs.sun.com/watt/resource/jvm-options-list.html  is quite
useful.

On Wed, Nov 17, 2010 at 10:00 PM, Ken Wesson  wrote:

> I ran some tests:
>
> (defn domany [n s] (reduce (fn [a b] (assoc a :foo (.getClass b))) {}
> (take n s)))
>
> (def fnseq (iterate (fn [_] (fn [x] (+ 2 x))) 0))
>
> (domany 1000 fnseq)
>
> With these, the last operation grinds away for a long time (a lot more
> than 10x what it takes with only 100 iterations) and I suspect the
> garbage collector is working hard (the Java process reaches the -Xmx
> size and stays there) but it works.
>
> But:
>
> (def fnseq (iterate (eval '(fn [_] (fn [x] (+ 2 x 0))
>
> (domany 1000 fnseq)
>
> spews an OOME after a couple of minutes.
>
> It looks like eval-generated functions, unlike closures, don't get
> (completely) garbage collected if all references to them are dropped.
> The message didn't actually say it ran out of permgen but it looks
> like using eval as a run-time plugin loader or similarly has caveats,
> but using ordinary closures a lot does not.
>
> It would be unloading and reloading plugins on demand that would have
> the caveat; loading plugins on demand but keeping them for session
> lifetime thereafter won't leak permgen but letting plugins become
> "garbage" and reloading them if needed again would leak permgen. It'd
> be a tradeoff; I assume the partly-unloaded plugin would take up less
> memory than a fully loaded one, but repeated reloads would chew up
> more and more.
>
> And loading identical code repeatedly still would leak, as the example
> (which has a fixed s-expression as the argument to eval) shows.
>
> Long story short: if you're going to dynamically load code at runtime,
> and may want to load, discard, and load more constantly in a
> long-running task, you'll need to write an interpreter unless/until
> eval and/or Java's classloader mechanism are fixed so that
> unreferenced eval-generated objects and/or dynamically-loaded Java
> classes in general are fully garbage collectable.
>
> --
> 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

Re: Closures eat permgen?

2010-11-17 Thread Ken Wesson
I ran some tests:

(defn domany [n s] (reduce (fn [a b] (assoc a :foo (.getClass b))) {}
(take n s)))

(def fnseq (iterate (fn [_] (fn [x] (+ 2 x))) 0))

(domany 1000 fnseq)

With these, the last operation grinds away for a long time (a lot more
than 10x what it takes with only 100 iterations) and I suspect the
garbage collector is working hard (the Java process reaches the -Xmx
size and stays there) but it works.

But:

(def fnseq (iterate (eval '(fn [_] (fn [x] (+ 2 x 0))

(domany 1000 fnseq)

spews an OOME after a couple of minutes.

It looks like eval-generated functions, unlike closures, don't get
(completely) garbage collected if all references to them are dropped.
The message didn't actually say it ran out of permgen but it looks
like using eval as a run-time plugin loader or similarly has caveats,
but using ordinary closures a lot does not.

It would be unloading and reloading plugins on demand that would have
the caveat; loading plugins on demand but keeping them for session
lifetime thereafter won't leak permgen but letting plugins become
"garbage" and reloading them if needed again would leak permgen. It'd
be a tradeoff; I assume the partly-unloaded plugin would take up less
memory than a fully loaded one, but repeated reloads would chew up
more and more.

And loading identical code repeatedly still would leak, as the example
(which has a fixed s-expression as the argument to eval) shows.

Long story short: if you're going to dynamically load code at runtime,
and may want to load, discard, and load more constantly in a
long-running task, you'll need to write an interpreter unless/until
eval and/or Java's classloader mechanism are fixed so that
unreferenced eval-generated objects and/or dynamically-loaded Java
classes in general are fully garbage collectable.

-- 
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: Ghost Vars?

2010-11-17 Thread Alyssa Kwan
Hi Alex,

OK, I agree.  Dynamic vars are not the same as traditional dynamic
scoping.

For what I'm doing (making functions durable), it raises the
question:  If you persist a function that points to a var, restart the
JVM, and deserialize/load the function from a data store, what should
happen?

1) In the loading thread, if a var exists with the same namespace and
symbol, set the internal reference to that var.
   a) If the function is then passed to a different thread that has a
different var with that same namespace and symbol, the function will
still point to the one that was in the loader thread at the time the
function was deserialized/loaded.
2) In the loading thread, if a var does not exist with that same
namespace and symbol:
   a) Throw an exception saying that the var doesn't exist.
   b) Create the var with no namespace and symbol and no value.  Wait
until the function is called to throw an exception saying that the var
is unbound.
   c) Create the var with no namespace and symbol but with the value
that the var had in the persisting thread.  There's no way to access
the var to modify it.
   d) Create the var with no namespace and symbol but with the value
that the var had in the persisting thread.  It's accessible somehow
(maybe the meta map), so the user can recover it and dynamically bind
over it.
   e) Create the var with the namespace and symbol in the function,
modifying the RT var-space of the loading thread.  Don't initialize
the var.  This gives the user a chance to dynamically bind over it.
If the function is called before binding the var to something, throw
an exception saying that the var is unbound.
   f) Create the var with the namespace and symbol in the function,
with the value that the var had in the persisting thread.

The normal case (1) is straightforward, and (1a) is what would happen
without se/des anyways.  (2) is tricky.  (2f) is most robust, but
really violates least surprise.  I think Meikel's comments lean
towards (2a).

Also, the thread-local nature of vars raises the question of what
should happen when deserializing the same function from different
threads.  If I create durable refs from different threads pointing to
the same store/key combo, does the thread that gets there first
control which var the deserialized function references?  Or does each
thread get it's own ref?  If so, how do you reconcile that there are
multiple refs being stored under the same store/key?  That's
untenable, but it seems totally arbitrary to simply say that the first
thread that gets there determines which var the function is bound to
for the duration of the JVM instance.

What do you think?

Thanks,
Alyssa Kwan

On Nov 17, 8:20 pm, Alex Osborne  wrote:
> Alyssa Kwan  writes:
> > I understand exactly why this situation exists.  I just think the
> > behavior is unexpected.  When I create a function with a dynamic
> > binding, I expect the function to keep a reference to the *name*, not
> > the var that the name resolves to at compile/clinit time.
>
> Oh, I see what you mean.  I guess you're expecting something more like
> Python's behaviour:
>
>     >>> x = 5
>     >>> def foo():
>     ...     return x
>     ...
>     >>> foo()
>     5
>     >>> del x
>     >>> foo()
>     Traceback (most recent call last):
>       File "", line 1, in 
>       File "", line 2, in foo
>     NameError: global name 'x' is not defined
>
> In the case of Python, globals are a mutable map of names directly to
> values and are presumably looked up at runtime.  Python doesn't have
> Clojure's concept of "vars".
>
>     >>> globals()
>     {..., 'x': 5, 'foo': , ...}
>
> > I guess the question is:  what do other people expect?  Am I alone in
> > thinking that this is unexpected and undesirable?
>
> It makes sense to me.  I have a mental picture of functions closing over
> the (lexical) environment as it existed when the function was defined
> and that includes the dynamic vars as they were named at that moment.
>
> Similarly in Python you can do this:
>
>     def foo():
>         return bar()
>
>     def bar():
>         return 5
>
> Whereas in Clojure you would need to declare bar before foo.
>
> That may mean dynamic vars are not exactly the same thing as traditional
> dynamic scoping, but I don't see anything obviously unexpected or
> undesirable about it.  In fact quite the opposite, it's an intentional
> design choice.  It's consistent with the Clojure philosophy of
> identities being first class.  One of the major themes that distinguishes
> Clojure's programming model from traditional languages is that names,
> identities and values are distinct concepts.
>
> A single var can be mapped into different namespaces under different
> names (for example using the :rename argument to "use").  So the same
> identity (var) may be referred to by multiple names (symbols), but it's
> the identity you are dynamically binding a value to, not the name.

-- 
You received this message because you are subscribed to the Googl

Re: Calling function in required library in a different namespace

2010-11-17 Thread Ken Wesson
On Wed, Nov 17, 2010 at 9:36 PM, Victor Olteanu  wrote:
> Hi,
> Please excuse my newbie ignorance - I would like to do something that seems
> pretty basic, yet I couldn't figure it out yet.
> I would like to call a function that is loaded in a different namespace, but
> without having to load the library again in the current namespace - more
> precisely:
> in db.clj
> I have
>  (:require [some-library :as mylib])
> in api.clj:
> I have (:require [myapp.db :as db])
> I then want to call mylib/somefunction - essentially a function in the
> loaded library in the "db" namespace. Trying to do "db/somefunction",
> perhaps obviously, is failing.
> I then attempted to write a macro that would call a function in a different
> namespace than the current one, but I couldn't find a way to specify a
> namespace in a macro definition.

Why not just have, in db.clj.

(def somefunction mylib/somefunction)

?

-- 
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


Calling function in required library in a different namespace

2010-11-17 Thread Victor Olteanu
Hi,
Please excuse my newbie ignorance - I would like to do something that seems
pretty basic, yet I couldn't figure it out yet.
I would like to call a function that is loaded in a different namespace, but
without having to load the library again in the current namespace - more
precisely:

in db.clj
I have
 (:require [some-library :as mylib])

in api.clj:
I have (:require [myapp.db :as db])
I then want to call mylib/somefunction - essentially a function in the
loaded library in the "db" namespace. Trying to do "db/somefunction",
perhaps obviously, is failing.
I then attempted to write a macro that would call a function in a different
namespace than the current one, but I couldn't find a way to specify a
namespace in a macro definition.

Thanks,
V

-- 
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: fastest way to remove nils

2010-11-17 Thread Ken Wesson
On Wed, Nov 17, 2010 at 7:55 PM, Robert McIntyre  wrote:
> So, just to be clear,
>
> user> (def nil-seq (doall (interleave (repeat 1e5 nil) (repeat 1e5
> "whatever"))) )
> #'user/nil-seq
>
> user> (time (doall (keep identity nil-seq)))
> "Elapsed time: 122.485848 msecs"
>
> user> (time (doall (remove nil?  nil-seq)))
> "Elapsed time: 149.71484 msecs"

I have to run these all a few times before the times quit shrinking
(JITting being done). Then:


user=> (time (do (doall (keep identity nil-seq)) nil))
"Elapsed time: 70.24324 msecs"
nil
user=> (time (do (doall (remove nil? nil-seq)) nil))
"Elapsed time: 40.47016 msecs"
nil
user=> (time (do (doall (filter identity nil-seq)) nil))
"Elapsed time: 36.70256 msecs"
nil

It seems on my system keep identity is actually almost twice as SLOW
as remove nil? and filter identity is slightly faster; filter identity
is almost exactly twice as fast as keep identity. Filter identity
does, of course, discard falses as well as nils, but when that's
acceptable it's worth knowing it's fastest.

I wonder if the difference is that I'm using the -server vm?

It's especially interesting, in light of the likelihood that identity
is probably compiling away to nothing when the JIT is done inlining
everything, that both the slowest and the fastest use identity. It
suggests that keep is inherently somewhat slow, in particular.

-- 
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: Enclojure for Clojure 1.2

2010-11-17 Thread Ken Wesson
On Wed, Nov 17, 2010 at 3:54 PM, Harrison Maseko  wrote:
> Does Enclojure support Clojure 1.2 yet?

Yes. I've been using Clojure 1.2/Enclojure 1.4/NB 6.9.1 for the past
few weeks myself.

-- 
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: Ghost Vars?

2010-11-17 Thread Alex Osborne
Alyssa Kwan  writes:

> I understand exactly why this situation exists.  I just think the
> behavior is unexpected.  When I create a function with a dynamic
> binding, I expect the function to keep a reference to the *name*, not
> the var that the name resolves to at compile/clinit time.

Oh, I see what you mean.  I guess you're expecting something more like
Python's behaviour: 

>>> x = 5
>>> def foo():
... return x
... 
>>> foo()
5
>>> del x
>>> foo()
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in foo
NameError: global name 'x' is not defined

In the case of Python, globals are a mutable map of names directly to
values and are presumably looked up at runtime.  Python doesn't have
Clojure's concept of "vars".

>>> globals()
{..., 'x': 5, 'foo': , ...}

> I guess the question is:  what do other people expect?  Am I alone in
> thinking that this is unexpected and undesirable?

It makes sense to me.  I have a mental picture of functions closing over
the (lexical) environment as it existed when the function was defined
and that includes the dynamic vars as they were named at that moment.

Similarly in Python you can do this:

def foo():
return bar()

def bar():
return 5

Whereas in Clojure you would need to declare bar before foo.

That may mean dynamic vars are not exactly the same thing as traditional
dynamic scoping, but I don't see anything obviously unexpected or
undesirable about it.  In fact quite the opposite, it's an intentional
design choice.  It's consistent with the Clojure philosophy of
identities being first class.  One of the major themes that distinguishes
Clojure's programming model from traditional languages is that names,
identities and values are distinct concepts.

A single var can be mapped into different namespaces under different
names (for example using the :rename argument to "use").  So the same
identity (var) may be referred to by multiple names (symbols), but it's
the identity you are dynamically binding a value to, not the name.

-- 
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: fastest way to remove nils

2010-11-17 Thread Robert McIntyre
So, just to be clear,

user> (def nil-seq (doall (interleave (repeat 1e5 nil) (repeat 1e5
"whatever"))) )
#'user/nil-seq

user> (time (doall (keep identity nil-seq)))
"Elapsed time: 122.485848 msecs"

user> (time (doall (remove nil?  nil-seq)))
"Elapsed time: 149.71484 msecs"


--Robert McIntyre


On Wed, Nov 17, 2010 at 5:57 AM, Steve Purcell  wrote:
> Miki  writes:
>> user=> (time (remove nil? (repeat 100 nil)))
>> "Elapsed time: 0.079312 msecs"
>> ()
>> user=> (time (filter identity (repeat 100 nil)))
>> "Elapsed time: 0.070249 msecs"
>> ()
>>
>> Seems like filter is a bit faster, however YMMV
>
>
> You're not timing the execution, just the construction of a lazy seq:
>
> user> (time (remove nil? (repeat 100 nil)))
> "Elapsed time: 0.044 msecs"
> ()
> user> (time (doall (remove nil? (repeat 100 nil
> "Elapsed time: 772.469 msecs"
> ()
>
> -Steve
>
>
>



>
>
>>
>> On Nov 16, 4:48 pm, Glen Rubin  wrote:
>>> What is the fastest way to remove nils from a sequence?
>>>
>>> I usually use the filter function, but I see there are other functions
>>> like remove that should also do the trick.
>
> --
> 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


Re: REQUEST for feedback on http://clojure.org

2010-11-17 Thread Allen Johnson
I think annotations support was added in 1.2. Could we add some
information to the Java Interop section regarding this?

https://groups.google.com/group/clojure/browse_thread/thread/d2128e1505c0c117?pli=1

Allen

On Sat, Oct 30, 2010 at 10:38 PM, Alex Miller  wrote:
> Hi all,
>
> I'm doing a bit of doc cleanup on http://clojure.org and I'd welcome
> your feedback on things that are broken or could be improved.  I'm not
> looking (or likely authorized :) to make any drastic changes but if
> there are things that you have run into, please drop a line here or in
> email to alexdmiller at yahoo.com.  Ideally, I'd like people to be
> logging tickets in jira, but I'm not sure it's quite ready for that
> yet.
>
> Some recent changes I've already made:
> - switched all of the old richhickey github references to clojure
> - cleaned up some factually wrong or out of date stuff on getting
> started and download pages
> - added Protocol and Datatypes pages to left nav (the pages have
> existed for 6 months)
> - added a page on starting a user group (still in review, not yet
> linked)
> - currently working on updating the cheat sheet to the 1.2 version
> (and adding links!)
>
> I'm particularly interested in:
> - new user groups or suggestions for the community page
> - stuff that is just wrong or out of date
>
> This DOES NOT include stuff in the API or Contrib autodoc pages.
> Please raise those issues or file tickets on those but that's not what
> I'm focusing on at the moment.
>
> 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

-- 
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


Enclojure for Clojure 1.2

2010-11-17 Thread Harrison Maseko
Does Enclojure support Clojure 1.2 yet?
Thanks,
-h.

-- 
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


Converting from 1.2 to 1.3-alpha3

2010-11-17 Thread nicolas.o...@gmail.com
Dear all,

I am trying top port some code from 1.2 to 1.3 and I end up with this error:


Unknown location:
  error: java.lang.VerifyError: (class:
nicolasoury/distributions/core/HashNodeDistribution, method:
delete_BANG_ signature: (Ljava/lang/Object;I)Ljava/lang/Object;)
Expecting to find integer on stack


The class is a deftype implementing an interface defined by a
definterface in the same file. On of the argument of the method in the
definterface is an hint.
Is it a problem with a call or with the definition of the method?

Should I always hint a call with an int?

Best,

Nicolas.

-- 
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: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Alyssa Kwan
Thanks everyone!
Alyssa Kwan

On Nov 17, 11:10 am, Stuart Halloway 
wrote:
> I am wrong, there was a bug here, and Rich just fixed it.
>
> https://github.com/clojure/clojure/commit/8225407032ea643cbe3db7f35ef...
>
> Please retry against master, and sorry for inflicting more confusion.
>
> Stu
>
>
>
> > Meikel,
>
> > while a good description of how things work in 1.2, it's not accurate for 
> > 1.3, and my point was that Stu's description of how 1.3 works (by using 
> > words like "the function is recompiled") does not match with my own 
> > knowledge of what had been done in 1.3 the days just before the conj.
>
> > Since then, I've been away from #clojure (to my regret) and maybe I've 
> > missed new evolutions on the way it's handled in master.
>
> > Anyway, this concept of "the function is recompiled" feels "weird".
>
> > My own comprehension of how things work in 1.3:
>
> > Each function works through a cached set of var's values, and there's just 
> > a check to see if the cache is stale or not. If the cache is stale (some 
> > vars have been redef's, e.g. their root value has been changed), then the 
> > cache is recomputed.
>
> > 2010/11/17 Meikel Brandmeyer 
> > Hi,
>
> > On 17 Nov., 16:29, David Sletten  wrote:
>
> > > > => (defn a
> > > >    ([x] x)
> > > >    ([x y] (+ (a x) (a y
> > > > #'user/a
> > > > => (a 1 2)
> > > > 3
> > > > => (def b a)
> > > > #'user/b
> > > > => (b 1 2)
> > > > 3
> > > > => (defn a [x]
> > > >    (- x))
> > > > #'user/a
> > > > => (b 1 2)
> > > > -3
>
> > > Let's call the original function assigned to 'a' a0 and the new one a1. 
> > > After 'a' has been redefined to a1, 'b' still refers to a0. So the 2nd 
> > > call to 'b' invokes a0 with two args (in fact, a1 only takes one arg 
> > > now). But within a0 itself the references to 'a' are being resolved at 
> > > runtime to a1 now, not as references to a0 as before.
>
> > > Are you saying that inside a0 Clojure detects that 'a' means something 
> > > else now and recompiles a0 to point to a1?
>
> > > In any case, this behavior seems weird.
>
> > Isn't that completely logical? Let's name things differently to keep
> > functions and Vars apart. You define a function f and store it in Var
> > a. f references Var a internally. Then you define Var b and store f in
> > it by retrieving it from Var a. By executing (b 1 2) you basically
> > retrieve f from b and call it with two arguments. Inside f, f itself
> > is retrieved from the Var a and called with one argument.
>
> > Now you create a new function g, which you store in Var a (assumption:
> > re-defing an existing Var just replaces its value and does not unmap
> > and map again a fresh Var). Again you execute (b 1 2). Same thing
> > happens: f is retrieved and called with two arguments. Inside f
> > however, now g is retrieved from Var a and called with one argument.
>
> > This actually allows to define memoized recursive functions.
>
> > 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
>
> > --
> > 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- Hide quoted text -
>
> - Show quoted text -

-- 
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: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Stuart Halloway
I am wrong, there was a bug here, and Rich just fixed it. 

https://github.com/clojure/clojure/commit/8225407032ea643cbe3db7f35ef97b1230fc65b8

Please retry against master, and sorry for inflicting more confusion.

Stu

> Meikel, 
> 
> while a good description of how things work in 1.2, it's not accurate for 
> 1.3, and my point was that Stu's description of how 1.3 works (by using words 
> like "the function is recompiled") does not match with my own knowledge of 
> what had been done in 1.3 the days just before the conj.
> 
> Since then, I've been away from #clojure (to my regret) and maybe I've missed 
> new evolutions on the way it's handled in master.
> 
> Anyway, this concept of "the function is recompiled" feels "weird". 
> 
> My own comprehension of how things work in 1.3:
> 
> Each function works through a cached set of var's values, and there's just a 
> check to see if the cache is stale or not. If the cache is stale (some vars 
> have been redef's, e.g. their root value has been changed), then the cache is 
> recomputed.
> 
> 
> 2010/11/17 Meikel Brandmeyer 
> Hi,
> 
> On 17 Nov., 16:29, David Sletten  wrote:
> 
> > > => (defn a
> > >([x] x)
> > >([x y] (+ (a x) (a y
> > > #'user/a
> > > => (a 1 2)
> > > 3
> > > => (def b a)
> > > #'user/b
> > > => (b 1 2)
> > > 3
> > > => (defn a [x]
> > >(- x))
> > > #'user/a
> > > => (b 1 2)
> > > -3
> >
> > Let's call the original function assigned to 'a' a0 and the new one a1. 
> > After 'a' has been redefined to a1, 'b' still refers to a0. So the 2nd call 
> > to 'b' invokes a0 with two args (in fact, a1 only takes one arg now). But 
> > within a0 itself the references to 'a' are being resolved at runtime to a1 
> > now, not as references to a0 as before.
> >
> > Are you saying that inside a0 Clojure detects that 'a' means something else 
> > now and recompiles a0 to point to a1?
> >
> > In any case, this behavior seems weird.
> 
> Isn't that completely logical? Let's name things differently to keep
> functions and Vars apart. You define a function f and store it in Var
> a. f references Var a internally. Then you define Var b and store f in
> it by retrieving it from Var a. By executing (b 1 2) you basically
> retrieve f from b and call it with two arguments. Inside f, f itself
> is retrieved from the Var a and called with one argument.
> 
> Now you create a new function g, which you store in Var a (assumption:
> re-defing an existing Var just replaces its value and does not unmap
> and map again a fresh Var). Again you execute (b 1 2). Same thing
> happens: f is retrieved and called with two arguments. Inside f
> however, now g is retrieved from Var a and called with one argument.
> 
> This actually allows to define memoized recursive functions.
> 
> 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
> 
> 
> -- 
> 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

Re: Ghost Vars?

2010-11-17 Thread Tim Daly

 In a common lisp setting a symbol could be represented
as vector containing slots. Two of the slots are of interest,
the function slot and the value slot. The symbol looks like:

--
| function | value | package | alist | 
-


You can place a function in either the function or value slots.
The (defun...) function places it in the symbol's function slot.

You can define a naked function using lambda thus:
(lambda () 5)

You can execute this function thus:
(funcall (lambda () 5)) ==> 5

Now you can assign this function to the symbol A in two ways:

(setf A (lambda () 'value-slot))  ;fill the value slot
(setf (symbol-function A) (lambda () 'function-slot)) ;fill the function 
slot


The first fills in the value-slot of A. You can call it with:
(funcall A) ==> value-slot

The second fills in the function-slot of A. You can call it with:
(A) ==> function-slot

So now you take a new symbol B with both a value-slot and a function-slot.
You want to "copy" something about the symbol A into B.
What is it you expect to copy?

(setf B A)
   == copy the value slot of A into the value-slot of B
  so that (funcall B) ==> value-slot
(setf B (symbol-function 'A))
   == copy the function slot of A into the value-slot of B
   so that (funcall B) ==> function-slot
(setf (symbol-function 'B) A)
   == copy the value-slot of A into the function-slot of B
  so that (B) ==> value-slot
(setf (symbol-function 'B) (symbol-function 'A))
   == copy the function-slot of A into the function-slot of B
  so that (B) ==> function-slot

Subsequent changes to A (either the function-slot or the value-slot)
will not affect the behavior of B. To do that you need to define B
in terms of A, such as:

(defun B () (A)) == call the function-slot of A
(defun B () (funcall A)) == call the value-slot of A

Which of the many behaviors were you expecting?

On 11/17/2010 7:39 AM, Alyssa Kwan wrote:

Hi Alex,

I understand exactly why this situation exists.  I just think the
behavior is unexpected.  When I create a function with a dynamic
binding, I expect the function to keep a reference to the *name*, not
the var that the name resolves to at compile/clinit time.  Using with-
bindings* seems terribly unsupported as well.

I guess the question is:  what do other people expect?  Am I alone in
thinking that this is unexpected and undesirable?

Thanks,
Alyssa Kwan

On Nov 17, 3:04 am, Alex Osborne  wrote:

Hi Alyssa,

Alyssa Kwan  writes:

ns-unmap isn't typically used.  But for durability, we can think of
JVM shutdown/startup as unmapping everything and starting fresh.
Therefore, expected behavior for ns-unmap should be the same as
behavior for deserializing and loading an object after a new JVM
startup.

I think the point that you're missing is that vars are just plain old
first class objects.  This includes being managed by the garbage
collector so they'll continue to exist until all references to them are
released.  You can pass them around, put them in vectors etc.


  Here's another issue I ran into:
=>  (def a 1)
#'user/a
=>  (defn b [] a)
#'user/b

When you compile this, a reference to the var #'user/a is embedded in
your b function.  This reference is directly to the var object.


So far so good...
=>  (ns-unmap *ns* 'a)
nil
=>  a
java.lang.Exception: Unable to resolve symbol: a in this context
=>  (b)
2

The var has been unmapped from the namespace, but it still exists
because the function b has a reference to it.  Vars don't need to live
in a namespace.  For example, the "with-local-vars" macro creates a
"local" var which doesn't belong to a namespace.




=>  (binding [a 3]
  (b))
java.lang.Exception: Unable to resolve var: a in this context
So what's the expected behavior here?  I would think that after a is
unmapped, b should no longer work.  Instead, it's hanging onto a with
the last value.

The var still exists, b holds a reference to it.


And the binding form doesn't work anymore, so there's
no way to dynamically bind over it.  It's like a weird hybrid of
lexical and dynamic binding...

The only reason this is erroring is that the symbol 'a can no longer be
mapped to your var.

Actually there is a way to dynamically bind over a var which has been
unmapped, all you need is a reference to it:

user>  (def a 1)
#'user/a
user>  (def my-a #'user/a)
#'user/my-a
user>  (defn b [] a)
#'user/b
user>  (ns-unmap *ns* 'a)
nil
user>  (b)
1
user>  (with-bindings* {my-a 30} #(b))
30


--
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,

Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Laurent PETIT
Meikel,

while a good description of how things work in 1.2, it's not accurate for
1.3, and my point was that Stu's description of how 1.3 works (by using
words like "the function is recompiled") does not match with my own
knowledge of what had been done in 1.3 the days just before the conj.

Since then, I've been away from #clojure (to my regret) and maybe I've
missed new evolutions on the way it's handled in master.

Anyway, this concept of "the function is recompiled" feels "weird".

My own comprehension of how things work in 1.3:

Each function works through a cached set of var's values, and there's just a
check to see if the cache is stale or not. If the cache is stale (some vars
have been redef's, e.g. their root value has been changed), then the cache
is recomputed.


2010/11/17 Meikel Brandmeyer 

> Hi,
>
> On 17 Nov., 16:29, David Sletten  wrote:
>
> > > => (defn a
> > >([x] x)
> > >([x y] (+ (a x) (a y
> > > #'user/a
> > > => (a 1 2)
> > > 3
> > > => (def b a)
> > > #'user/b
> > > => (b 1 2)
> > > 3
> > > => (defn a [x]
> > >(- x))
> > > #'user/a
> > > => (b 1 2)
> > > -3
> >
> > Let's call the original function assigned to 'a' a0 and the new one a1.
> After 'a' has been redefined to a1, 'b' still refers to a0. So the 2nd call
> to 'b' invokes a0 with two args (in fact, a1 only takes one arg now). But
> within a0 itself the references to 'a' are being resolved at runtime to a1
> now, not as references to a0 as before.
> >
> > Are you saying that inside a0 Clojure detects that 'a' means something
> else now and recompiles a0 to point to a1?
> >
> > In any case, this behavior seems weird.
>
> Isn't that completely logical? Let's name things differently to keep
> functions and Vars apart. You define a function f and store it in Var
> a. f references Var a internally. Then you define Var b and store f in
> it by retrieving it from Var a. By executing (b 1 2) you basically
> retrieve f from b and call it with two arguments. Inside f, f itself
> is retrieved from the Var a and called with one argument.
>
> Now you create a new function g, which you store in Var a (assumption:
> re-defing an existing Var just replaces its value and does not unmap
> and map again a fresh Var). Again you execute (b 1 2). Same thing
> happens: f is retrieved and called with two arguments. Inside f
> however, now g is retrieved from Var a and called with one argument.
>
> This actually allows to define memoized recursive functions.
>
> 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
>

-- 
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: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Meikel Brandmeyer
Hi,

On 17 Nov., 16:29, David Sletten  wrote:

> > => (defn a
> >    ([x] x)
> >    ([x y] (+ (a x) (a y
> > #'user/a
> > => (a 1 2)
> > 3
> > => (def b a)
> > #'user/b
> > => (b 1 2)
> > 3
> > => (defn a [x]
> >    (- x))
> > #'user/a
> > => (b 1 2)
> > -3
>
> Let's call the original function assigned to 'a' a0 and the new one a1. After 
> 'a' has been redefined to a1, 'b' still refers to a0. So the 2nd call to 'b' 
> invokes a0 with two args (in fact, a1 only takes one arg now). But within a0 
> itself the references to 'a' are being resolved at runtime to a1 now, not as 
> references to a0 as before.
>
> Are you saying that inside a0 Clojure detects that 'a' means something else 
> now and recompiles a0 to point to a1?
>
> In any case, this behavior seems weird.

Isn't that completely logical? Let's name things differently to keep
functions and Vars apart. You define a function f and store it in Var
a. f references Var a internally. Then you define Var b and store f in
it by retrieving it from Var a. By executing (b 1 2) you basically
retrieve f from b and call it with two arguments. Inside f, f itself
is retrieved from the Var a and called with one argument.

Now you create a new function g, which you store in Var a (assumption:
re-defing an existing Var just replaces its value and does not unmap
and map again a fresh Var). Again you execute (b 1 2). Same thing
happens: f is retrieved and called with two arguments. Inside f
however, now g is retrieved from Var a and called with one argument.

This actually allows to define memoized recursive functions.

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: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread David Sletten

On Nov 17, 2010, at 9:22 AM, Stuart Halloway wrote:

> In 1.2, functions were always looked up through their vars. While this is a 
> low-cost operation, it does not allow maximum performance.
> 
> In 1.3, function calls are "compiled through" their vars. If function a calls 
> function c inside its body, there is no runtime lookup of the var c. However, 
> each function makes a (very low cost) check on entry to see if anything has 
> been recompiled. If so, the function is recompiled. This enables the dynamic 
> repl interaction that you would expect from a lisp, with great performance.
> 
> When, as in your example, a var b refers to var a, there is no function call, 
> hence no hook point at which to make the check. If you want b to point to the 
> new a, redef b. 
> 

Stu,

This doesn't seem consistent with what Alyssa is reporting. She's getting a 
weird mix of both old 'a' and new 'a':
> => (defn a
>([x] x)
>([x y] (+ (a x) (a y
> #'user/a

> => (a 1 2)
> 3

> => (def b a)
> #'user/b

> => (b 1 2)
> 3

> => (defn a [x]
>(- x))
> #'user/a

> => (b 1 2)
> -3

Let's call the original function assigned to 'a' a0 and the new one a1. After 
'a' has been redefined to a1, 'b' still refers to a0. So the 2nd call to 'b' 
invokes a0 with two args (in fact, a1 only takes one arg now). But within a0 
itself the references to 'a' are being resolved at runtime to a1 now, not as 
references to a0 as before.

Are you saying that inside a0 Clojure detects that 'a' means something else now 
and recompiles a0 to point to a1?

In any case, this behavior seems weird.

Have all good days,
David Sletten

> Stu
> 
>> Notice that when I redefined a, I only included one arity.  If b were
>> updated with the fn that a was redefined to, then (b 1 2) should have
>> thrown an exception.  Instead, it used the old definition of a but
>> within that definition pointed to the new definition of a.  This is
>> internally inconsistent.
>> 
>> I'm not proposing making all function definitions lexically bound.
>> Yes, that would destroy interactive coding.
>> 
>> But to be internally consistent, self-references should be lexical.
>> 
>> In any case, I am using Github master and I thought I was using 1.2.
>> 1.2 has self-references lexically bound, as David Sletten points out,
>> which I agree is the correct behavior.  But something has happened on
>> 1.3 alpha that has changed that.  I don't know if it's intentional or
>> not.
>> 
>> Thanks,
>> Alyssa Kwan
>> 
>> On Nov 16, 6:01 pm, David Nolen  wrote:
>>> But that would destroy one of the most useful features Lisp has to offer,
>>> interactive coding.
>>> 
>>> Live coding would be impossible w/o this behavior as you would need to find
>>> and update all callers. Yuk.
>>> 
>>> David
>>> 
>>> On Tue, Nov 16, 2010 at 5:26 PM, Alyssa Kwan wrote:
>>> 
>>> 
>>> 
 I ran into this while working on making functions durable.  Here's a
 contrived example:
>>> 
 => (defn a
([x] x)
([x y] (+ (a x) (a y
 #'user/a
>>> 
 => (a 1 2)
 3
>>> 
 => (def b a)
 #'user/b
>>> 
 => (b 1 2)
 3
>>> 
 => (defn a [x]
(- x))
 #'user/a
>>> 
 => (b 1 2)
 -3
>>> 
 Is this what people expect?  I would think that the original
 definition of a, which is self-referencing, should point to itself no
 matter what it's named, not get resolved at invoke-time to see what
 the var is currently resolving to.
>>> 
 Thanks,
 Alyssa Kwan
>>> 
 --
 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
> 
> -- 
> 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@googleg

Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Alyssa Kwan
The issue here is not with b pointing to a. It's that b should point
to b but doesn't. This *can't* be seen to be correct.

Thanks,
Alyssa Kwan

On Nov 17, 9:22 am, Stuart Halloway  wrote:
> In 1.2, functions were always looked up through their vars. While this is a 
> low-cost operation, it does not allow maximum performance.
>
> In 1.3, function calls are "compiled through" their vars. If function a calls 
> function c inside its body, there is no runtime lookup of the var c. However, 
> each function makes a (very low cost) check on entry to see if anything has 
> been recompiled. If so, the function is recompiled. This enables the dynamic 
> repl interaction that you would expect from a lisp, with great performance.
>
> When, as in your example, a var b refers to var a, there is no function call, 
> hence no hook point at which to make the check. If you want b to point to the 
> new a, redef b.
>
> Stu
>
>
>
> > Notice that when I redefined a, I only included one arity.  If b were
> > updated with the fn that a was redefined to, then (b 1 2) should have
> > thrown an exception.  Instead, it used the old definition of a but
> > within that definition pointed to the new definition of a.  This is
> > internally inconsistent.
>
> > I'm not proposing making all function definitions lexically bound.
> > Yes, that would destroy interactive coding.
>
> > But to be internally consistent, self-references should be lexical.
>
> > In any case, I am using Github master and I thought I was using 1.2.
> > 1.2 has self-references lexically bound, as David Sletten points out,
> > which I agree is the correct behavior.  But something has happened on
> > 1.3 alpha that has changed that.  I don't know if it's intentional or
> > not.
>
> > Thanks,
> > Alyssa Kwan
>
> > On Nov 16, 6:01 pm, David Nolen  wrote:
> >> But that would destroy one of the most useful features Lisp has to offer,
> >> interactive coding.
>
> >> Live coding would be impossible w/o this behavior as you would need to find
> >> and update all callers. Yuk.
>
> >> David
>
> >> On Tue, Nov 16, 2010 at 5:26 PM, Alyssa Kwan 
> >> wrote:
>
> >>> I ran into this while working on making functions durable.  Here's a
> >>> contrived example:
>
> >>> => (defn a
> >>>     ([x] x)
> >>>     ([x y] (+ (a x) (a y
> >>> #'user/a
>
> >>> => (a 1 2)
> >>> 3
>
> >>> => (def b a)
> >>> #'user/b
>
> >>> => (b 1 2)
> >>> 3
>
> >>> => (defn a [x]
> >>>     (- x))
> >>> #'user/a
>
> >>> => (b 1 2)
> >>> -3
>
> >>> Is this what people expect?  I would think that the original
> >>> definition of a, which is self-referencing, should point to itself no
> >>> matter what it's named, not get resolved at invoke-time to see what
> >>> the var is currently resolving to.
>
> >>> Thanks,
> >>> Alyssa Kwan
>
> >>> --
> >>> 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

-- 
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: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Laurent PETIT
2010/11/17 Laurent PETIT 

>
>
> 2010/11/17 Stuart Halloway 
>
> In 1.2, functions were always looked up through their vars. While this is a
>> low-cost operation, it does not allow maximum performance.
>>
>> In 1.3, function calls are "compiled through" their vars. If function a
>> calls function c inside its body, there is no runtime lookup of the var c.
>> However, each function makes a (very low cost) check on entry to see if
>> anything has been recompiled. If so, the function is recompiled.
>
>
> Wait, what ??
>

I mean, is this new stuff since the "state of the art" of the week where the
conj occured ?
(do you have an idea of where in the irc logs one could "follow history" on
this ?)


>
>
>> This enables the dynamic repl interaction that you would expect from a
>> lisp, with great performance.
>>
>> When, as in your example, a var b refers to var a, there is no function
>> call, hence no hook point at which to make the check. If you want b to point
>> to the new a, redef b.
>>
>> Stu
>>
>> > Notice that when I redefined a, I only included one arity.  If b were
>> > updated with the fn that a was redefined to, then (b 1 2) should have
>> > thrown an exception.  Instead, it used the old definition of a but
>> > within that definition pointed to the new definition of a.  This is
>> > internally inconsistent.
>> >
>> > I'm not proposing making all function definitions lexically bound.
>> > Yes, that would destroy interactive coding.
>> >
>> > But to be internally consistent, self-references should be lexical.
>> >
>> > In any case, I am using Github master and I thought I was using 1.2.
>> > 1.2 has self-references lexically bound, as David Sletten points out,
>> > which I agree is the correct behavior.  But something has happened on
>> > 1.3 alpha that has changed that.  I don't know if it's intentional or
>> > not.
>> >
>> > Thanks,
>> > Alyssa Kwan
>> >
>> > On Nov 16, 6:01 pm, David Nolen  wrote:
>> >> But that would destroy one of the most useful features Lisp has to
>> offer,
>> >> interactive coding.
>> >>
>> >> Live coding would be impossible w/o this behavior as you would need to
>> find
>> >> and update all callers. Yuk.
>> >>
>> >> David
>> >>
>> >> On Tue, Nov 16, 2010 at 5:26 PM, Alyssa Kwan > >wrote:
>> >>
>> >>
>> >>
>> >>> I ran into this while working on making functions durable.  Here's a
>> >>> contrived example:
>> >>
>> >>> => (defn a
>> >>> ([x] x)
>> >>> ([x y] (+ (a x) (a y
>> >>> #'user/a
>> >>
>> >>> => (a 1 2)
>> >>> 3
>> >>
>> >>> => (def b a)
>> >>> #'user/b
>> >>
>> >>> => (b 1 2)
>> >>> 3
>> >>
>> >>> => (defn a [x]
>> >>> (- x))
>> >>> #'user/a
>> >>
>> >>> => (b 1 2)
>> >>> -3
>> >>
>> >>> Is this what people expect?  I would think that the original
>> >>> definition of a, which is self-referencing, should point to itself no
>> >>> matter what it's named, not get resolved at invoke-time to see what
>> >>> the var is currently resolving to.
>> >>
>> >>> Thanks,
>> >>> Alyssa Kwan
>> >>
>> >>> --
>> >>> 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
>>
>> --
>> 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

Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread nicolas.o...@gmail.com
> In 1.3, function calls are "compiled through" their vars. If function a calls 
> function c inside its body, there is no runtime lookup of the var c. However, 
> each function makes a (very low cost) check on entry to see if anything has 
> been recompiled. If so, the function is recompiled. This enables the dynamic 
> repl interaction that you would expect from a lisp, with great performance.

Wasn't it possible to have a dependency graph?
Is there some scenario where a function is called a long time after a
repl change and compilation has to be performed when perfomance is
critical?
Is it compatible with inlining by the JVM?

Best,

Nicolas.

-- 
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: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Laurent PETIT
2010/11/17 Stuart Halloway 

> In 1.2, functions were always looked up through their vars. While this is a
> low-cost operation, it does not allow maximum performance.
>
> In 1.3, function calls are "compiled through" their vars. If function a
> calls function c inside its body, there is no runtime lookup of the var c.
> However, each function makes a (very low cost) check on entry to see if
> anything has been recompiled. If so, the function is recompiled.


Wait, what ??


> This enables the dynamic repl interaction that you would expect from a
> lisp, with great performance.
>
> When, as in your example, a var b refers to var a, there is no function
> call, hence no hook point at which to make the check. If you want b to point
> to the new a, redef b.
>
> Stu
>
> > Notice that when I redefined a, I only included one arity.  If b were
> > updated with the fn that a was redefined to, then (b 1 2) should have
> > thrown an exception.  Instead, it used the old definition of a but
> > within that definition pointed to the new definition of a.  This is
> > internally inconsistent.
> >
> > I'm not proposing making all function definitions lexically bound.
> > Yes, that would destroy interactive coding.
> >
> > But to be internally consistent, self-references should be lexical.
> >
> > In any case, I am using Github master and I thought I was using 1.2.
> > 1.2 has self-references lexically bound, as David Sletten points out,
> > which I agree is the correct behavior.  But something has happened on
> > 1.3 alpha that has changed that.  I don't know if it's intentional or
> > not.
> >
> > Thanks,
> > Alyssa Kwan
> >
> > On Nov 16, 6:01 pm, David Nolen  wrote:
> >> But that would destroy one of the most useful features Lisp has to
> offer,
> >> interactive coding.
> >>
> >> Live coding would be impossible w/o this behavior as you would need to
> find
> >> and update all callers. Yuk.
> >>
> >> David
> >>
> >> On Tue, Nov 16, 2010 at 5:26 PM, Alyssa Kwan  >wrote:
> >>
> >>
> >>
> >>> I ran into this while working on making functions durable.  Here's a
> >>> contrived example:
> >>
> >>> => (defn a
> >>> ([x] x)
> >>> ([x y] (+ (a x) (a y
> >>> #'user/a
> >>
> >>> => (a 1 2)
> >>> 3
> >>
> >>> => (def b a)
> >>> #'user/b
> >>
> >>> => (b 1 2)
> >>> 3
> >>
> >>> => (defn a [x]
> >>> (- x))
> >>> #'user/a
> >>
> >>> => (b 1 2)
> >>> -3
> >>
> >>> Is this what people expect?  I would think that the original
> >>> definition of a, which is self-referencing, should point to itself no
> >>> matter what it's named, not get resolved at invoke-time to see what
> >>> the var is currently resolving to.
> >>
> >>> Thanks,
> >>> Alyssa Kwan
> >>
> >>> --
> >>> 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
>
> --
> 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

Re: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Stuart Halloway
In 1.2, functions were always looked up through their vars. While this is a 
low-cost operation, it does not allow maximum performance.

In 1.3, function calls are "compiled through" their vars. If function a calls 
function c inside its body, there is no runtime lookup of the var c. However, 
each function makes a (very low cost) check on entry to see if anything has 
been recompiled. If so, the function is recompiled. This enables the dynamic 
repl interaction that you would expect from a lisp, with great performance.

When, as in your example, a var b refers to var a, there is no function call, 
hence no hook point at which to make the check. If you want b to point to the 
new a, redef b. 

Stu
 
> Notice that when I redefined a, I only included one arity.  If b were
> updated with the fn that a was redefined to, then (b 1 2) should have
> thrown an exception.  Instead, it used the old definition of a but
> within that definition pointed to the new definition of a.  This is
> internally inconsistent.
> 
> I'm not proposing making all function definitions lexically bound.
> Yes, that would destroy interactive coding.
> 
> But to be internally consistent, self-references should be lexical.
> 
> In any case, I am using Github master and I thought I was using 1.2.
> 1.2 has self-references lexically bound, as David Sletten points out,
> which I agree is the correct behavior.  But something has happened on
> 1.3 alpha that has changed that.  I don't know if it's intentional or
> not.
> 
> Thanks,
> Alyssa Kwan
> 
> On Nov 16, 6:01 pm, David Nolen  wrote:
>> But that would destroy one of the most useful features Lisp has to offer,
>> interactive coding.
>> 
>> Live coding would be impossible w/o this behavior as you would need to find
>> and update all callers. Yuk.
>> 
>> David
>> 
>> On Tue, Nov 16, 2010 at 5:26 PM, Alyssa Kwan wrote:
>> 
>> 
>> 
>>> I ran into this while working on making functions durable.  Here's a
>>> contrived example:
>> 
>>> => (defn a
>>> ([x] x)
>>> ([x y] (+ (a x) (a y
>>> #'user/a
>> 
>>> => (a 1 2)
>>> 3
>> 
>>> => (def b a)
>>> #'user/b
>> 
>>> => (b 1 2)
>>> 3
>> 
>>> => (defn a [x]
>>> (- x))
>>> #'user/a
>> 
>>> => (b 1 2)
>>> -3
>> 
>>> Is this what people expect?  I would think that the original
>>> definition of a, which is self-referencing, should point to itself no
>>> matter what it's named, not get resolved at invoke-time to see what
>>> the var is currently resolving to.
>> 
>>> Thanks,
>>> Alyssa Kwan
>> 
>>> --
>>> 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

-- 
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: Add method implementations to proxy

2010-11-17 Thread Mark Rathwell
> Hi, i added your example (quoting the source) to
> http://clojuredocs.org/clojure_core/clojure.core/update-proxy

Great, thank
you.

On Wed, Nov 17, 2010 at 8:31 AM, atreyu  wrote:

> Hi, i added your example (quoting the source) to
> http://clojuredocs.org/clojure_core/clojure.core/update-proxy
>
>
> On Nov 17, 2:05 pm, Mark Rathwell  wrote:
> > An example of update-proxy in case it may help anyone in the future:
> >
> > user> (import java.util.Date)
> > java.util.Date
> >
> > user> (def d (proxy [Date] [] (toString [] "hello")))
> > #'user/d
> >
> > user> d
> > #
> >
> > user> (.toString d)
> > "hello"
> >
> > user> (.toGMTString d)
> > "17 Nov 2010 12:57:28 GMT"
> >
> > user> (update-proxy d {"toGMTString" (fn [this] "goodbye")})
> > nil
> >
> > user> (.toGMTString d)
> > "goodbye"
> >
> > On Wed, Nov 17, 2010 at 7:48 AM, Mark Rathwell  >wrote:
> >
> > > Beautiful.  Thank you!
> >
> > > On Wed, Nov 17, 2010 at 2:07 AM, Liam  wrote:
> >
> > >> More information from Rich himself about "update-proxy" when he first
> > >> introduced it. Could not find examples for you except from the Joy of
> > >> Clojure book on page 273, but it is very trivial... just like the doc
> > >> string sounds.
> >
> > >>http://groups.google.com/group/clojure/browse_thread/thread/ed1652132.
> ..
> >
> > >> --
> > >> 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
>

-- 
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: Add method implementations to proxy

2010-11-17 Thread atreyu
Hi, i added your example (quoting the source) to
http://clojuredocs.org/clojure_core/clojure.core/update-proxy


On Nov 17, 2:05 pm, Mark Rathwell  wrote:
> An example of update-proxy in case it may help anyone in the future:
>
> user> (import java.util.Date)
> java.util.Date
>
> user> (def d (proxy [Date] [] (toString [] "hello")))
> #'user/d
>
> user> d
> #
>
> user> (.toString d)
> "hello"
>
> user> (.toGMTString d)
> "17 Nov 2010 12:57:28 GMT"
>
> user> (update-proxy d {"toGMTString" (fn [this] "goodbye")})
> nil
>
> user> (.toGMTString d)
> "goodbye"
>
> On Wed, Nov 17, 2010 at 7:48 AM, Mark Rathwell wrote:
>
> > Beautiful.  Thank you!
>
> > On Wed, Nov 17, 2010 at 2:07 AM, Liam  wrote:
>
> >> More information from Rich himself about "update-proxy" when he first
> >> introduced it. Could not find examples for you except from the Joy of
> >> Clojure book on page 273, but it is very trivial... just like the doc
> >> string sounds.
>
> >>http://groups.google.com/group/clojure/browse_thread/thread/ed1652132...
>
> >> --
> >> 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


Re: Add method implementations to proxy

2010-11-17 Thread Mark Rathwell
An example of update-proxy in case it may help anyone in the future:

user> (import java.util.Date)
java.util.Date

user> (def d (proxy [Date] [] (toString [] "hello")))
#'user/d

user> d
#

user> (.toString d)
"hello"

user> (.toGMTString d)
"17 Nov 2010 12:57:28 GMT"

user> (update-proxy d {"toGMTString" (fn [this] "goodbye")})
nil

user> (.toGMTString d)
"goodbye"


On Wed, Nov 17, 2010 at 7:48 AM, Mark Rathwell wrote:

>
> Beautiful.  Thank you!
>
>
> On Wed, Nov 17, 2010 at 2:07 AM, Liam  wrote:
>
>> More information from Rich himself about "update-proxy" when he first
>> introduced it. Could not find examples for you except from the Joy of
>> Clojure book on page 273, but it is very trivial... just like the doc
>> string sounds.
>>
>>
>> http://groups.google.com/group/clojure/browse_thread/thread/ed1652132dfa623c/a78eac7875bd2866?#a78eac7875bd2866
>>
>> --
>> 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

Re: Add method implementations to proxy

2010-11-17 Thread Mark Rathwell
Beautiful.  Thank you!


On Wed, Nov 17, 2010 at 2:07 AM, Liam  wrote:

> More information from Rich himself about "update-proxy" when he first
> introduced it. Could not find examples for you except from the Joy of
> Clojure book on page 273, but it is very trivial... just like the doc
> string sounds.
>
>
> http://groups.google.com/group/clojure/browse_thread/thread/ed1652132dfa623c/a78eac7875bd2866?#a78eac7875bd2866
>
> --
> 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

Re: Ghost Vars?

2010-11-17 Thread Meikel Brandmeyer
Hi,

On 17 Nov., 13:39, Alyssa Kwan  wrote:

> Using with-bindings* seems terribly unsupported as well.

with-bindings* is official API and the above is a valid use.

I would expect that the current situation is there for performance
reasons. Resolving the Var each time the function is called is
probably too slow.

I personally don't see a problem with this situation. When you speak
about a virtual "restart" as unmapping *everything* and reloading
things, you might be right. But there lies the rub. You don't unmap
everything in your example. With my limited imagination I can't see a
scenario where the above could arise in a production system, since a
"hot update" which removes a but leaves the old b intact could be
considered broken since it wouldn't compile when loading in a fresh
JVM.

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: Ghost Vars?

2010-11-17 Thread Alyssa Kwan
Hi Alex,

I understand exactly why this situation exists.  I just think the
behavior is unexpected.  When I create a function with a dynamic
binding, I expect the function to keep a reference to the *name*, not
the var that the name resolves to at compile/clinit time.  Using with-
bindings* seems terribly unsupported as well.

I guess the question is:  what do other people expect?  Am I alone in
thinking that this is unexpected and undesirable?

Thanks,
Alyssa Kwan

On Nov 17, 3:04 am, Alex Osborne  wrote:
> Hi Alyssa,
>
> Alyssa Kwan  writes:
> > ns-unmap isn't typically used.  But for durability, we can think of
> > JVM shutdown/startup as unmapping everything and starting fresh.
> > Therefore, expected behavior for ns-unmap should be the same as
> > behavior for deserializing and loading an object after a new JVM
> > startup.
>
> I think the point that you're missing is that vars are just plain old
> first class objects.  This includes being managed by the garbage
> collector so they'll continue to exist until all references to them are
> released.  You can pass them around, put them in vectors etc.
>
> >  Here's another issue I ran into:
>
> > => (def a 1)
> > #'user/a
>
> > => (defn b [] a)
> > #'user/b
>
> When you compile this, a reference to the var #'user/a is embedded in
> your b function.  This reference is directly to the var object.
>
> > So far so good...
>
> > => (ns-unmap *ns* 'a)
> > nil
>
> > => a
> > java.lang.Exception: Unable to resolve symbol: a in this context
>
> > => (b)
> > 2
>
> The var has been unmapped from the namespace, but it still exists
> because the function b has a reference to it.  Vars don't need to live
> in a namespace.  For example, the "with-local-vars" macro creates a
> "local" var which doesn't belong to a namespace.
>
>
>
> > => (binding [a 3]
> >      (b))
> > java.lang.Exception: Unable to resolve var: a in this context
> > So what's the expected behavior here?  I would think that after a is
> > unmapped, b should no longer work.  Instead, it's hanging onto a with
> > the last value.
>
> The var still exists, b holds a reference to it.
>
> > And the binding form doesn't work anymore, so there's
> > no way to dynamically bind over it.  It's like a weird hybrid of
> > lexical and dynamic binding...
>
> The only reason this is erroring is that the symbol 'a can no longer be
> mapped to your var.
>
> Actually there is a way to dynamically bind over a var which has been
> unmapped, all you need is a reference to it:
>
> user> (def a 1)
> #'user/a
> user> (def my-a #'user/a)
> #'user/my-a
> user> (defn b [] a)
> #'user/b
> user> (ns-unmap *ns* 'a)
> nil
> user> (b)
> 1
> user> (with-bindings* {my-a 30} #(b))
> 30

-- 
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: bimaps in clojure

2010-11-17 Thread Sunil S Nandihalli
Hi Christophe Grand
Yea true I kind of got confused .. thanks for the solution..
Sunil

On Wed, Nov 17, 2010 at 1:12 PM, Christophe Grand wrote:

> On Wednesday, November 17, 2010, Sunil S Nandihalli
>  wrote:
> > Regarding your bimap implementation, in terms of complexity, I feel, it
> will be linear in the number of elements, when accessing the pair via the
> value .. Is that true?
>
> No I use two maps and rmap is O(1) so rmap+get is O(log32 n) like a
> direct get. What may confuse you is that only the direct map is
> hinted. The reverse map doesn't need to: no interop calls on it while
> it is in reverse position.
>
> > On Tue, Nov 16, 2010 at 2:36 PM, Christophe Grand 
> wrote:
> >
> >
> > You can implement your own, prettu easily with deftype.
> > However it can be tedious to track every methods, so we need a repl
> helper function to scaffold the code for us.
> >
> > (defn scaffold [iface]
> >   (doseq [[iface methods] (->> iface .getMethods
> > (map #(vector (.getName (.getDeclaringClass
> %))
> > (symbol (.getName %))
> > (count (.getParameterTypes %
> > (group-by first))]
> > (println (str "  " iface))
> > (doseq [[_ name argcount] methods]
> >   (println
> > (str ""
> >   (list name (into ['this] (take argcount (repeatedly
> gensym)
> >
> > user=> (scaffold clojure.lang.IPersistentMap)
> >   clojure.lang.IPersistentMap
> > (assoc [this G__441 G__442])
> > (without [this G__443])
> > (assocEx [this G__444 G__445])
> >   java.lang.Iterable
> > (iterator [this])
> >   clojure.lang.Associative
> > (containsKey [this G__446])
> > (assoc [this G__447 G__448])
> > (entryAt [this G__449])
> >   clojure.lang.IPersistentCollection
> > (count [this])
> > (cons [this G__450])
> > (empty [this])
> > (equiv [this G__451])
> >   clojure.lang.Seqable
> > (seq [this])
> >   clojure.lang.ILookup
> > (valAt [this G__452 G__453])
> > (valAt [this G__454])
> >   clojure.lang.Counted
> > (count [this])
> > nil
> >
> > Now you need to remove the duplicates (count and assoc), wrap everything
> in a deftype form and implement it:
> > (including a new protocol fn to reverse a bidi map)
> >
> > (defprotocol ReversibleMap
> >   (rmap [m]))
> >
> > (defn- rdissoc [d r v]
> >  (if-let [[_ k] (find r v)] (dissoc d k) d))
> >
> > (deftype Bimap [^clojure.lang.IPersistentMap direct reverse]
> >   Object
> >   (hashCode [x]
> > (.hashCode direct))
> >   (equals [x y]
> > (.equals direct y))
> >   clojure.lang.IPersistentMap
> > (without [this k]
> >   (Bimap.
> > (dissoc direct k)
> > (rdissoc reverse direct k)))
> > (assocEx [this k v]
> >   (if (or (contains? direct k) (contains? reverse v))
> > (throw (Exception. "Key or value already present"))
> > (assoc this k v)))
> >   java.lang.Iterable
> > (iterator [this]
> >   (.iterator direct))
> >   clojure.lang.Associative
> > (assoc [this k v]
> >   (Bimap.
> > (assoc (rdissoc direct reverse v) k v)
> > (assoc (rdissoc reverse direct k) v k)))
> > (containsKey [this k]
> >   (contains? direct k))
> > (entryAt [this k]
> >   (find direct k))
> >   clojure.lang.IPersistentCollection
> > (cons [this x]
> >   (if-let [[k v] (and (vector? x) x)]
> > (assoc this k v)
> > (reduce (fn [m [k v]] (assoc m k v)) this x)))
> > (empty [this]
> >   (.empty direct))
> > (equiv [this x]
> >   (.equiv direct x))
> >   clojure.lang.Seqable
> > (seq [this]
> >   (seq direct))
> >   clojure.lang.ILookup
> > (valAt [this k else]
> >   (direct k else))
> > (valAt [this k]
> >   (direct k))
> >   clojure.lang.Counted
> > (count [this]
> >   (count direct))
> >   ReversibleMap
> > (rmap [this]
> >   (Bimap. reverse direct)))
> >
> > (defn bimap [& kvs]
> >   (reduce (fn [m [k v]] (assoc m k v)) (Bimap. {} {}) (partition 2 kvs)))
> >
> > Some quick tests:
> > user=> (assoc (bimap :a 1 :b 2) [:c 3] [:d 4] [:e 5])
> > {[:e 5] nil, [:c 3] [:d 4], :b 2, :a 1}
> > user=> (assoc (bimap :a 1 :b 2) :c 3 :d 4 :e 5)
> > {:e 5, :d 4, :c 3, :b 2, :a 1}
> > user=> (assoc (bimap :a 1 :b 2) :c 3 :d 2 :e 5)
> > {:e 5, :d 2, :c 3, :a 1}
> > user=> (dissoc *1 :d)
> > {:e 5, :c 3, :a 1}
> > user=> (rmap *1)
> > {5 :e, 3 :c, 1 :a}
> > user=> (assoc *1 2 :c)
> > {2 :c, 5 :e, 1 :a}
> >
> > hth,
> >
> > Christophe
> >
> >
> >
> >
> >
> > On Tue, Nov 16, 2010 at 8:16 AM, Sunil S Nandihalli <
> sunil.nandiha...@gmail.com> wrote:
> >
> >
> >
> > A bimap is a map where each elements of the pair can be used as key to
> access it..
> > Sunil.
> >
> > On Tue, Nov 16, 2010 at 12:44 PM, Sunil S Nandihalli <
> sunil.nandiha...@gmail.com> wrote:
>
> --
> Professional: http://cgrand.net/ (fr)
> On Clojure: http://clj-me.cgrand.ne

Re: fastest way to remove nils

2010-11-17 Thread Steve Purcell
Miki  writes:
> user=> (time (remove nil? (repeat 100 nil)))
> "Elapsed time: 0.079312 msecs"
> ()
> user=> (time (filter identity (repeat 100 nil)))
> "Elapsed time: 0.070249 msecs"
> ()
>
> Seems like filter is a bit faster, however YMMV


You're not timing the execution, just the construction of a lazy seq:

user> (time (remove nil? (repeat 100 nil)))
"Elapsed time: 0.044 msecs"
()
user> (time (doall (remove nil? (repeat 100 nil
"Elapsed time: 772.469 msecs"
()

-Steve





>
> On Nov 16, 4:48 pm, Glen Rubin  wrote:
>> What is the fastest way to remove nils from a sequence?
>>
>> I usually use the filter function, but I see there are other functions
>> like remove that should also do the trick.

-- 
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 of seq on empty collections

2010-11-17 Thread Meikel Brandmeyer
Hi,

On 17 Nov., 09:44, Laurent PETIT  wrote:

> I don't know.
>
> But my thougts were just that if you want to measure the time for a
> particular way "W" of coding things (and a variant "Wv"), and you test this
> with other computations "OC",
>
> then
> (not=
>   (/ (time Wv)
>      (time W))
>   (/ (+ (time Wv) (time OC))
>      (+ (time W) (time OC
>
> ?
>
> Especially if (time OC) is non neglictible ... ?

This is a valid concern. I did another test run, where really only the
traversal and the access is done in the benchmark. But to be honest:
my gut feeling sound the alarm bells about "do you test what you claim
you test or does HotSpot do its magic and optimises things away?"

user=> (let [s (doall (take 1 (range)))]
 (bench
   (loop [s s i 0]
 (if (empty? s)
   i
   (recur (rest s) (first s))
Evaluation count : 42060
Execution time mean  : 1,423636 ms  95,0% CI: (1,423576 ms,
1,423708 ms)
Execution time std-deviation : 236,456463 us  95,0% CI: (235,124875
us, 238,050869 us)

Found 4 outliers in 60 samples (6,6667 %)
low-severe   4 (6,6667 %)
 Variance from outliers : 1,6389 % Variance is slightly inflated by
outliers
nil
user=> (let [s (doall (take 1 (range)))]
 (bench
   (loop [s (seq s) i 0]
 (if s
   (recur (next s) (first s))
   i
Evaluation count : 77100
Execution time mean  : 801,433279 us  95,0% CI: (801,390707
us, 801,464994 us)
Execution time std-deviation : 156,316400 us  95,0% CI: (154,780303
us, 158,550059 us)

Found 2 outliers in 60 samples (3, %)
low-severe   1 (1,6667 %)
low-mild 1 (1,6667 %)
 Variance from outliers : 1,6389 % Variance is slightly inflated by
outliers
nil

That means:

0.801433279ms / 1.423636ms ~ 0.56 => 44% improvement?

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: Dynamic Binding of Self-Referencing Functions Expected Behavior?

2010-11-17 Thread Alex Osborne
Alyssa Kwan  writes:

> In any case, I am using Github master and I thought I was using 1.2.
> 1.2 has self-references lexically bound, as David Sletten points out,
> which I agree is the correct behavior.  But something has happened on
> 1.3 alpha that has changed that.  I don't know if it's intentional or
> not.

In 1.2:

user=> (macroexpand '(defn foo [] 2))
(def foo (.withMeta (clojure.core/fn foo ([] 2)) (.meta (var foo

It's clearer if we remove the metadata and explicit namespace stuff:

(def foo (fn foo ([] 2)))

While in git master we have:

(def foo (fn ([] 2)))

This is the commit that changed it:

http://github.com/clojure/clojure/commit/52adb74f5335c8256f6468581028f44220547dca

It's not mentioned explicitly in the commit message, so my guess was it
was unintentionally clobbered when the metadata stuff was removed.
Unless the idea is to no longer treat recursive calls as a special
static binding case?

-- 
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 of seq on empty collections

2010-11-17 Thread Laurent PETIT
2010/11/16 Meikel Brandmeyer 

> Salut Laurent,
>
> On 16 Nov., 09:51, Laurent PETIT  wrote:
>
> > Agreed with the explanation, but ... 12% of what, exactly ?
>
> 6,502692ms / 7,393586ms ~ 0,88 => 12% improvement, no?
>
> But maybe this whole microbenchmarking story is paper waste. As I
> said: quick'n'dirty.
>

I don't know.

But my thougts were just that if you want to measure the time for a
particular way "W" of coding things (and a variant "Wv"), and you test this
with other computations "OC",

then
(not=
  (/ (time Wv)
 (time W))
  (/ (+ (time Wv) (time OC))
 (+ (time W) (time OC

?

Especially if (time OC) is non neglictible ... ?




> Will now drop out of perfomance discussions...
>
> 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
>

-- 
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: Ghost Vars?

2010-11-17 Thread Alex Osborne
Hi Alyssa,

Alyssa Kwan  writes:

> ns-unmap isn't typically used.  But for durability, we can think of
> JVM shutdown/startup as unmapping everything and starting fresh.
> Therefore, expected behavior for ns-unmap should be the same as
> behavior for deserializing and loading an object after a new JVM
> startup.

I think the point that you're missing is that vars are just plain old
first class objects.  This includes being managed by the garbage
collector so they'll continue to exist until all references to them are
released.  You can pass them around, put them in vectors etc.

>  Here's another issue I ran into:
>
> => (def a 1)
> #'user/a
>
> => (defn b [] a)
> #'user/b

When you compile this, a reference to the var #'user/a is embedded in
your b function.  This reference is directly to the var object.

> So far so good...
>
> => (ns-unmap *ns* 'a)
> nil
>
> => a
> java.lang.Exception: Unable to resolve symbol: a in this context
>
> => (b)
> 2

The var has been unmapped from the namespace, but it still exists
because the function b has a reference to it.  Vars don't need to live
in a namespace.  For example, the "with-local-vars" macro creates a
"local" var which doesn't belong to a namespace.

>
> => (binding [a 3]
>  (b))
> java.lang.Exception: Unable to resolve var: a in this context

> So what's the expected behavior here?  I would think that after a is
> unmapped, b should no longer work.  Instead, it's hanging onto a with
> the last value.

The var still exists, b holds a reference to it.

> And the binding form doesn't work anymore, so there's
> no way to dynamically bind over it.  It's like a weird hybrid of
> lexical and dynamic binding...

The only reason this is erroring is that the symbol 'a can no longer be
mapped to your var.

Actually there is a way to dynamically bind over a var which has been
unmapped, all you need is a reference to it:

user> (def a 1)
#'user/a
user> (def my-a #'user/a)
#'user/my-a
user> (defn b [] a)
#'user/b
user> (ns-unmap *ns* 'a)
nil
user> (b)
1
user> (with-bindings* {my-a 30} #(b))
30

-- 
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