Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Mark Engelberg
On Fri, Nov 13, 2009 at 12:58 AM, Konrad Hinsen
 wrote:
> Coming from a Python background, I don't think access restrictions are
> necessary. However, flagging fields as "not meant for use by
> outsiders" could be of interest for documentation tools, to make it
> clear what client code can safely rely on.

Even Python has the ability to mangle names so that they are
effectively private.  They aren't truly hidden, but there's no way
you'll misunderstand and call a private thing by accident.

As a longtime Python programmer, I guess that's the level of privacy I like.

In general, I really hate it when it's difficult to tell what parts of
an API are the things that the end-user is really supposed to call,
and what part of the data you're supposed to access directly versus an
accessor method.  It bugs me when I call (:real complex) to extract
the real part out of a complex number, only to discover later that I
was supposed to call (get-real complex) because the accessor is the
only "safe way" to get the value I want.

I think anything in datatypes or protocols that help library designers
separate the data that's safe to access directly from the data that's
not, or the functions that are safe to call versus those that are not
-- I think that's a good thing.

I don't really care how strictly the language *enforces* that
separation, but I think the ability to specify that separation is a
good thing.

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 3:45 AM, Mark Engelberg wrote:

> On Fri, Nov 13, 2009 at 12:58 AM, Konrad Hinsen
>  wrote:
> > Coming from a Python background, I don't think access restrictions are
> > necessary. However, flagging fields as "not meant for use by
> > outsiders" could be of interest for documentation tools, to make it
> > clear what client code can safely rely on.
>
> Even Python has the ability to mangle names so that they are
> effectively private.  They aren't truly hidden, but there's no way
> you'll misunderstand and call a private thing by accident.
>
> As a longtime Python programmer, I guess that's the level of privacy I
> like.
>
> In general, I really hate it when it's difficult to tell what parts of
> an API are the things that the end-user is really supposed to call,
> and what part of the data you're supposed to access directly versus an
> accessor method.  It bugs me when I call (:real complex) to extract
> the real part out of a complex number, only to discover later that I
> was supposed to call (get-real complex) because the accessor is the
> only "safe way" to get the value I want.
>
> I think anything in datatypes or protocols that help library designers
> separate the data that's safe to access directly from the data that's
> not, or the functions that are safe to call versus those that are not
> -- I think that's a good thing.
>
> I don't really care how strictly the language *enforces* that
> separation, but I think the ability to specify that separation is a
> good thing.


+1 for ability to specify, especially if it's recognized by tools such as
IDEs and they filter private stuff from other namespaces from what they use
as possible completions, etc.

Particularly, I'm in favor of removing the exception throw when a private
var is dereferenced from outside its namespace, particularly as it will
solve the macro-expansion-uses-private-implementation-function issue (making
the expansion generate the function as a local function or anonymous
function seems messy to me when the function's own content does not depend
on the macro arguments). Let :private true in a var's metadata influence
tools like IDEs and documentation generators, so they don't show as part of
the API, and let IDEs give warnings if they see a symbol that resolves to an
external private var in your code (though not in the expansions of
non-private macros you call). That should suffice to prevent accidental
self-inflicted gunshot wounds to the foot, while preserving maximum
flexibility.

-- 
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: local constants in functions or static locals/Hilbert curve in clojure (no images:)

2009-11-14 Thread ajuc
> > I would like to somehow hide the global hilbert-map into my function,
> > but I can't see how to do that.
>
> Just put the literal directly into the function.
>
> > Is this possible? I know that I can just inert literal into my let,
> > but that degrades performance, when function is called many times.
>
> Have you tested it, using (time ...), preferably on the server VM? I
> wouldn't be surprised if a calculation that produces a constant gets
> optimized away to just the constant.

(time (dotimes [_ (int 1)] (point-to-hilbert (rand-int (int
-1000)) (int 1) (int 16
(time (dotimes [_ (int 1)] (point-to-hilbert-2 (rand-int (int
-1000)) (int 1) (int 16

"Elapsed time: 892.041865 msecs" - version with global
"Elapsed time: 1152.569949 msecs" - version with literal in let
statement inside the function

I only tested on client java 6, I have to install enterprise jdk, I
think, to be able to add parameter -server to the command line, now it
returns error.
Anyway, requiring users of for example game, to install non standard
java just to have the game run at good speed isn't the best way, so
I'll probably optimize for java -client anyway.

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread Konrad Hinsen
On 13 Nov 2009, at 23:03, Stuart Sierra wrote:

>> This example has maybe a problem : doesn't the symmetry of these
>> Arithmetic operators seems to be crying for type multiple dispatch in
>> this particular case ? :-)
>
> Yes, in the general case, arithmetic requires multimethods.  But
> multimethods -- or any dynamic type dispatch -- are too slow for math-
> heavy code anyway.

That depends on how it is used and on what types.  
clojure.contrib.complex has a multimethod-based implementation which  
moreover does a multimethod dispatch on the real/imaginary parts,  
making it possible to use any numeric type, built-in or not, inside  
the complex type. That's about as inefficient as it can get, but also  
very flexible. You can do symbolic computing with that kind of  
framework, and then the overhead is tolerable, but for number  
crunching it is not.

I think arithmetic is a bad "first example" for just about any  
implementation technique. Doing it well is very hard, and as far as I  
know no one has yet come up with any technique that is fully  
satisfying for all applications.

Konrad.

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Konrad Hinsen
On 14 Nov 2009, at 02:50, Mark Engelberg wrote:

> together.  So would it make sense for multimethods to be included as
> part of protocols, or should there be some similar grouping system for
> multimethods?

The "old ideas/scratchpad" section of

http://www.assembla.com/wiki/show/clojure/Protocols

mentions multiprotocols, which are about what you describe.

> basically gives you partial implementation.  But it seems to me that a
> lot of times, several interface functions will share some sort of
> local state, using closures.


The shared state would normally be stored in the object that the  
dispatching acts on.

> If I'm visualizing this correctly, these sorts of partial  
> implementations couldn't possibly be mixed-in,
> because there would be no way to share that state.

They could still all reference a common var, just like any set of  
functions can. But...

> Off the top of my head, I don't yet have a concrete example of this  
> -- has anyone
> encountered this yet in their experiments with protocols?

... me neither, so it seems premature to discuss the details.

Konrad.

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


why a defn- but not a def- ?

2009-11-14 Thread Mike Hogye
Why is there an easy way to def a private function (defn-), but no
similarly easy way to def an arbitrary var as private?

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread Jonas Enlund
Hi there!

I have built a simple Matrix datatype with defprotocol and deftype.
You can take a look at it at http://gist.github.com/234535
(constructive criticism welcome!). Some simple examples are provided
at the end of the file.

I have a few questions.

- Why must i write (matrix/Matrix ...) instead of (Matrix ...) inside
the deftype body? Is this a bug? I didn't have to write it that way in
earlier versions of the new-branch.
- Am I supposed to have all the interface implementations inside the
deftype body? I didn't figure out how to move the implementation of
the clojure.lang.* interfaces to (extends ...).

/Jonas

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread Konrad Hinsen
On 14 Nov 2009, at 09:45, Mark Engelberg wrote:

> In general, I really hate it when it's difficult to tell what parts of
> an API are the things that the end-user is really supposed to call,
> and what part of the data you're supposed to access directly versus an
> accessor method.  It bugs me when I call (:real complex) to extract

I agree. The distinction should be clear, even though not enforced by  
the language.

A privacy indication that would fit well with the rest of Clojure is  
to tag the field name in the deftype with the "private" metadata  
field. The question is just how to make this information accessible to  
IDEs and documentation tools. In fact, the first question is how an  
IDE can get any information about the fields of a type. There doesn't  
seem to be a documented way to do it. One source would be the doc  
string of the constructor function.

Konrad.

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


Re: why a defn- but not a def- ?

2009-11-14 Thread Albert Cardona
On Fri, Nov 13, 2009 at 11:26 PM, Mike Hogye  wrote:
> Why is there an easy way to def a private function (defn-), but no
> similarly easy way to def an arbitrary var as private?


The way I see it, def- would encourage gratuitous variable declaration
imperative style.

By private var what one means is a local variable.

If you want a private variable use a let binding:

(let [my-private-var "Something not to be shared"]
  (defn my-public-fn
"Do something"
[a b]
(str a b my-private-var)))

If you need the private variable to be mutable, use a ref and dosync
changes on it. That goes a long way towards correctness.

Albert
--
http://albert.rierol.net

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread Rich Hickey


On Nov 14, 8:28 am, Jonas Enlund  wrote:
> Hi there!
>
> I have built a simple Matrix datatype with defprotocol and deftype.
> You can take a look at it athttp://gist.github.com/234535
> (constructive criticism welcome!). Some simple examples are provided
> at the end of the file.
>
> I have a few questions.
>
> - Why must i write (matrix/Matrix ...) instead of (Matrix ...) inside
> the deftype body? Is this a bug? I didn't have to write it that way in
> earlier versions of the new-branch.

Inside the method bodies, the type name (Matrix) now designates the
class, so you can use it to call the ctor instead of the factory fn:

;change all (Matrix a b c) to (Matrix. a b c)

(Matrix. 1 (count v) (into [] v))


> - Am I supposed to have all the interface implementations inside the
> deftype body?

Yes.

> I didn't figure out how to move the implementation of
> the clojure.lang.* interfaces to (extends ...).
>

Interface methods have nothing to do with protocol fns. They go in
separate places.

Rich

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread Rich Hickey


On Nov 14, 1:32 am, cody koeninger  wrote:
> On Nov 13, 9:42 am, Sean Devlin  wrote:
>
> > In this case, you provide the docs for each method after parameters.
> > Would the following be possible:
>
> > (defprotocol AProtocol :on AnInterface
> >   "A doc string for AProtocol abstraction"
> >   (bar "bar docs" [a b] :on barMethod)
> >   (baz "baz docs" ([a] [a b] [a b & c])))
>
> > This matches the rhythm of the rest of the language.
>
> > Sean
>
> +1 for docstring position that matches the rest of the language.  I
> actually think this is a big deal.
>
> Other issue regarding docstrings:
>
> user=> (doc AProtocol)
> -
> user/AProtocol
> nil
>   protocol doc
> nil
> user=> (doc bar)
> -
> user/bar
> ([a b])
>   bar doc
> nil
>
> doc gives no indication of any relationship between bar and AProtocol,
> other than the shared namespace.  

Making the doc refer to the protocol is on the todo list.

> Is the idea to use a convention of
> max 1 protocol per namespace?

No. But all functions of protocols in the same ns live in the ns, so
you must have unique function names across protocols on the same ns.

Rich

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


Idiomatic way to remove & in binding?

2009-11-14 Thread Sean Devlin
Hi,

I recently was writing a macro that creates requires creating a worker
fn, and the wrapping a worker fn with an adapter fn.  The adapter fn
is what I intend to have called.  To give you an idea what's going on:

user=>(doc my-fn)
"This calls my-fn* to do some work, after my-fn calls a multimethod to
adapt the input."

user=>(doc my-fn*)
"This does the work"

In order for it to work it needs access to the symbols in the binding
vars.  The problem is that the bindings might be variadic, so I need
to remove the & symbol.  Here's the macro.

(defmacro defmod [sym docstring binding body]
  (let [base-sym (symbol (str sym "*"))
base-doc (str "This is the base function designed to work on a
string. \n\n" docstring)
versatile-doc (str "multifn - This is the wrapped multimethod
designed to work on strings, keywords or symbols. \n\n  " docstring)]
`(do
  (defn ~base-sym ~base-doc ~binding ~body)
  (defn ~sym ~versatile-doc ~binding
(apply mod ~base-sym ~@(remove #{'&} binding))

Is the ~@(remove #{'&} binding) the proper s-exp to do this?

Thanks!
Sean

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


Multiarray design study

2009-11-14 Thread Konrad Hinsen
Following recent discussions on this list about how to work with  
multiarrays (n-dimensional arrays, data cubes) in Clojure, I have  
started a project on Google Code that is at the moment more of a  
design study than an implementation meant for use. It contains

- a protocol definition for multiarray functions
- a Clojure implementation (using the new deftype feature) of  
multiarrays and the protocol
- protocol implementations for
   - a representation based on nested Clojure vectors
   - the Java multiarray class from the Unidata libraries (netCDF etc.)
   - the Java multiarray class from CERN's Colt library

Note that the current state is very incomplete. Comments and  
contributions of all kinds are welcome. My goal is to get this right  
rathen then to get out a working library quickly, so take your time...

The code is at:

http://code.google.com/p/clj-multiarray/

Konrad.

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


Re: local constants in functions or static locals/Hilbert curve in clojure (no images:)

2009-11-14 Thread Wilson MacGyver
The server VM is part of the standard JDK.

To use it you can either do

java -server

or

set environment variable JAVA_OPS like this on linux/OSX

export JAVA_OPTS="-server"

On Sat, Nov 14, 2009 at 6:19 AM, ajuc  wrote:
>> > I would like to somehow hide the global hilbert-map into my function,
>> > but I can't see how to do that.
>>
>> Just put the literal directly into the function.
>>
>> > Is this possible? I know that I can just inert literal into my let,
>> > but that degrades performance, when function is called many times.
>>
>> Have you tested it, using (time ...), preferably on the server VM? I
>> wouldn't be surprised if a calculation that produces a constant gets
>> optimized away to just the constant.
>
> (time (dotimes [_ (int 1)] (point-to-hilbert (rand-int (int
> -1000)) (int 1) (int 16
> (time (dotimes [_ (int 1)] (point-to-hilbert-2 (rand-int (int
> -1000)) (int 1) (int 16
>
> "Elapsed time: 892.041865 msecs" - version with global
> "Elapsed time: 1152.569949 msecs" - version with literal in let
> statement inside the function
>
> I only tested on client java 6, I have to install enterprise jdk, I
> think, to be able to add parameter -server to the command line, now it
> returns error.
> Anyway, requiring users of for example game, to install non standard
> java just to have the game run at good speed isn't the best way, so
> I'll probably optimize for java -client anyway.
>
> --
> 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



-- 
Omnem crede diem tibi diluxisse supremum.

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


Deep deref

2009-11-14 Thread André Thieme
I watched http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey
and it is a very nice video. Rich mentioned around minute 9 to 10:05 a
big problem:
when some code gets handed data, can it be sure this thing is
immutable?

Clojure wants to help, because it encapsulates state in refs, which we
can deref.
When we deref something it feels like an immutable copy which will
never be
touched.

But in real programs things are not so easy. We have refs in refs.
To illustrate this I want to make up a simple example. Let‘s say we
have a web
application where people can register, and become friends with each
other.

To represent a person we want to have a (defstruct
person :name :age :friends)
(this could also be a deftype of course).
We want to store all persons on our website in a map. Their name will
be the
key. As more and more people register we need to update our map, so it
must
be a ref (or atom):
(def *persons* (ref {}))

Each person can also be changed, for example when he/she gets older,
or when
she found new friends.
Initially when someone registers he/she has no friends yet. To add a
user we
want something like:
(defn make-person [name age]
  (let [p (ref (struct person name age []))]
(dosync
  (alter *persons* assoc name p))
p))

Now three people register, and we have:
(make-person "Karl" 20)
(make-person "Jeff" 22)
(make-person "Tina" 19)

Dereferencing *persons* will result in:
{"Tina" #,
 "Jeff" #,
 "Karl" #}
Great so far.

People can become friends, so we need
(defn add-friend [#^String person #^String friend]
  (dosync
(let [p (get @*persons* person)
   f (get @*persons* friend)]
(alter p update-in [:friends] conj f

So, Tina can get the friends Karl and Jeff:
(add-friend "Tina" "Karl")
(add-friend "Tina" "Jeff")

Now the problem is: *persons* acts as our data base, and
when a request comes in (to our web application, hosted by,
say, Compojure) we want to see a consistent snapshot of the
DB.
But derefing *persons* won't do this for us.
Even when we deref Tina, we can not be sure who her friends
are, as those live in their own refs.
They have to. If Karl gets one year older then we only want to
change his date, and not traverse all persons first and see if
they have Karl as a friend and if yes updating his age there too.

How can we handle this situation?
Is it possible to implement a function “deep-deref” which works
as blindingly fast as deref does?
I find this very important, and this is of great practical relevance
for me. Please share your ideas.

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


Map a list of agents to a list of their values

2009-11-14 Thread Kevin Q
I have a list of agents, each of which has a hasmap state. I want to
get a list of values from the list of agents, naturally I used the map
function and print the result of the map:

(println
  (map #(@%) agents))

However, when I run this, I got error "Wrong number of args passed to:
PersistentHashMap"

I'm wondering why is this happening? Prior to calling the map
function, I did (apply await agents) to wait for all my agents to
finish. Does it affect things?

Thanks,

-- 
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: Map a list of agents to a list of their values

2009-11-14 Thread Sean Devlin
Try

(map deref agents)

On Nov 14, 12:49 pm, Kevin Q  wrote:
> I have a list of agents, each of which has a hasmap state. I want to
> get a list of values from the list of agents, naturally I used the map
> function and print the result of the map:
>
> (println
>   (map #(@%) agents))
>
> However, when I run this, I got error "Wrong number of args passed to:
> PersistentHashMap"
>
> I'm wondering why is this happening? Prior to calling the map
> function, I did (apply await agents) to wait for all my agents to
> finish. Does it affect things?
>
> Thanks,

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


ExceptionInInitializerError in eval with user defined functions

2009-11-14 Thread gun43
Using r1366 under Win XP.

A user defined function:
1:27 user=> (defn plus2 [x] (+ x 2))
#'user/plus2
1:28 user=> (plus2 5)
7

can only be eval'd
1:29 user=> (list plus2 5)
(# 5)
1:30 user=> (eval (list plus2 5))
java.lang.ExceptionInInitializerError (repl-1:30)

when passed with #'
1:31 user=> (list #'plus2 5)
(#'user/plus2 5)
1:32 user=> (eval (list #'plus2 5))
7

in contrast to a core function
1:33 user=> (inc 5)
6

which works without
1:34 user=> (list inc 5)
(# 5)
1:35 user=> (eval (list inc 5))
6

and with #'.
1:36 user=> (list #'inc 5)
(#'clojure.core/inc 5)
1:37 user=> (eval (list #'inc 5))
6

This is a real problem for anonymous functions.
1:38 user=> (#(+ % 2) 5)
7
1:54 user=> (list #(+ % 2) 5)
(# 5)
1:55 user=> (eval (list #(+ % 2) 5))
java.lang.ExceptionInInitializerError (repl-1:55)

Is this a bug or am I doing something wrong.
This stuff all worked under r1338.

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread Richard Newman
> I don't really care how strictly the language *enforces* that
> separation, but I think the ability to specify that separation is a
> good thing.

I'd go so far as to request that it does not enforce separation. I'm  
sure anyone who's spent enough time using Other People's Libraries has  
hit instances where the only way to get things to work is to use the  
(lower-level, undocumented) API because the high-level API doesn't  
allow you to pass some crucial parameter, or where you need to reuse  
some internal function or spend the time to rewrite it yourself.

In an ideal world (read: fantasy land) you can just fix the library  
and send a push request on GitHub, but we rarely live in that place.

Similarly, I'm sure lots of people have had tons of 'fun' with final  
classes, private and protected members, and so on in Java... "if I  
could just call that method...". I recall several experiences where if  
I could have called a protected method I could have worked around a  
bug in an application server. Instead, I had to patch their runtime  
libraries, and wait a few weeks for the change to roll upstream.

> As a longtime Python programmer, I guess that's the level of privacy  
> I like.

As a Common Lisper and Python programmer, I'm quite fond of this  
too... "there but hidden".

I like CL's package support for this kind of situation, where  
unexported symbols can still be reached via foo::bar, at the cost of  
an obvious "code smell".

To *really* enforce hiding, you can actually unintern symbols,  
rendering the things they named unreachable. Unusual, but possible.

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


Re: why a defn- but not a def- ?

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 8:55 AM, Albert Cardona  wrote:

> On Fri, Nov 13, 2009 at 11:26 PM, Mike Hogye 
> wrote:
> > Why is there an easy way to def a private function (defn-), but no
> > similarly easy way to def an arbitrary var as private?
>
>
> The way I see it, def- would encourage gratuitous variable declaration
> imperative style.
>
> By private var what one means is a local variable.
>
> If you want a private variable use a let binding:
>
> (let [my-private-var "Something not to be shared"]
>  (defn my-public-fn
>"Do something"
>[a b]
>(str a b my-private-var)))
>
> If you need the private variable to be mutable, use a ref and dosync
> changes on it. That goes a long way towards correctness.
>

I find top-level lets to be messy compared to defining global constants like
this:

(def +the-constant+ value)

There's a defvar that adds docstring capability to def, and a private-making
version defvar-, in clojure.contrib.def.

My own style preference would be to put important constants in defs at the
top of the file, rather than use let or (worse) embed "magic numbers" or the
like in individual functions that might need to be tweaked. Constants that
are truly constant because they're forced to be by math, the algorithm used,
or whatever might be locally letted in the function that uses them, to name
them while keeping them with the rest of the algorithm, though.

-- 
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: local constants in functions or static locals/Hilbert curve in clojure (no images:)

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 6:19 AM, ajuc  wrote:

> > > I would like to somehow hide the global hilbert-map into my function,
> > > but I can't see how to do that.
> >
> > Just put the literal directly into the function.
> >
> > > Is this possible? I know that I can just inert literal into my let,
> > > but that degrades performance, when function is called many times.
> >
> > Have you tested it, using (time ...), preferably on the server VM? I
> > wouldn't be surprised if a calculation that produces a constant gets
> > optimized away to just the constant.
>
> (time (dotimes [_ (int 1)] (point-to-hilbert (rand-int (int
> -1000)) (int 1) (int 16
> (time (dotimes [_ (int 1)] (point-to-hilbert-2 (rand-int (int
> -1000)) (int 1) (int 16
>
> "Elapsed time: 892.041865 msecs" - version with global
> "Elapsed time: 1152.569949 msecs" - version with literal in let
> statement inside the function
>

Eeeuw.

Was this with a Clojure literal in the let, or with a non-trivial
calculation using constants?

If it's with a literal, it's an optimization Rich can make pretty easily: if
a function being compiled contains a let bind whose value, or a loop bind
whose initial value, is (after macro expansion) pure data (no function or
special form invocations -- just vectors, sets, maps, etc. with leaves that
are integers, strings, doubles, etc.), then change that value to a private
static final field in the function class, and in the "let" case the places
where the function requests that variable can compile to bytecode to access
that field. The "loop" case just requires the loop initialization grab the
field value as the initial value of the loop binding, then behave as usual
for the loop body and recur.

Some function and special form calls can even be allowed, with a little
finesse: clojure.core/list for one, quote, and nested let:

(let [x (let [y [1 2]] [y y])] ...)

can be reduced to bytecode equivalent to this pseudo-Java

private static final IPersistentVector X = [[1 2] [1 2]];

public Object invoke blah blah blah {
// ... uses X
}

-- 
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: Deep deref

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 11:42 AM, André Thieme
wrote:

> Dereferencing *persons* will result in:
> {"Tina" #,
>  "Jeff" #,
>  "Karl" #}
> Great so far.
>
> People can become friends, so we need
> (defn add-friend [#^String person #^String friend]
>  (dosync
>(let [p (get @*persons* person)
>   f (get @*persons* friend)]
>(alter p update-in [:friends] conj f
>
> So, Tina can get the friends Karl and Jeff:
> (add-friend "Tina" "Karl")
> (add-friend "Tina" "Jeff")
>
> Now the problem is: *persons* acts as our data base, and
> when a request comes in (to our web application, hosted by,
> say, Compojure) we want to see a consistent snapshot of the
> DB.
> But derefing *persons* won't do this for us.
> Even when we deref Tina, we can not be sure who her friends
> are, as those live in their own refs.
> They have to. If Karl gets one year older then we only want to
> change his date, and not traverse all persons first and see if
> they have Karl as a friend and if yes updating his age there too.
>
> How can we handle this situation?


I think the design in this sort of case needs changing.

Repeated structure references also pose a problem for storage and retrieval
(at least if not using a real DB) as Clojure's prn and read will turn shared
substructures into separate copies.

What's needed here is to make all person lookups go through one point, the
*persons* table, so the :friends key would store a vector not of person
struct references but simply of names.

When you start using a real DB this won't change; only the name of the
concept will, to a "key column". Name will be a key column in the *persons*
table and will be how you get at particular rows (persons) in the table.

-- 
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: ExceptionInInitializerError in eval with user defined functions

2009-11-14 Thread Jarkko Oranen


On Nov 14, 8:08 pm, gun43  wrote:
> Using r1366 under Win XP.
r1366? From Subversion? That's ancient. Clojure moved to git ages ago;
see
http://github.com/richhickey/clojure

>
> A user defined function:
> 1:27 user=> (defn plus2 [x] (+ x 2))
> #'user/plus2
> 1:28 user=> (plus2 5)
> 7
>
> can only be eval'd
> 1:29 user=> (list plus2 5)
> (# 5)
> 1:30 user=> (eval (list plus2 5))
> java.lang.ExceptionInInitializerError (repl-1:30)
>
> when passed with #'
> 1:31 user=> (list #'plus2 5)
> (#'user/plus2 5)
> 1:32 user=> (eval (list #'plus2 5))
> 7
>
> in contrast to a core function
> 1:33 user=> (inc 5)
> 6
>
> which works without
> 1:34 user=> (list inc 5)
> (# 5)
> 1:35 user=> (eval (list inc 5))
> 6
>
> and with #'.
> 1:36 user=> (list #'inc 5)
> (#'clojure.core/inc 5)
> 1:37 user=> (eval (list #'inc 5))
> 6
>
> This is a real problem for anonymous functions.
> 1:38 user=> (#(+ % 2) 5)
> 7
> 1:54 user=> (list #(+ % 2) 5)
> (# 5)
> 1:55 user=> (eval (list #(+ % 2) 5))
> java.lang.ExceptionInInitializerError (repl-1:55)
>
> Is this a bug or am I doing something wrong.
> This stuff all worked under r1338.

I had no idea that this worked at all. Usually eval evaluates lists of
symbols and other primitives, eg.
(eval (list 'user2 2 3)). Hm. Anyway, try upgrading your Clojure. :)

--
Jarkko

-- 
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: Multiarray design study

2009-11-14 Thread Rock
Great news Konrad!

I'll be having a look as soon as possible, and I hope I can help out.

Thank you!

Rock

On Nov 14, 3:54 pm, Konrad Hinsen  wrote:
> Following recent discussions on this list about how to work with  
> multiarrays (n-dimensional arrays, data cubes) in Clojure, I have  
> started a project on Google Code that is at the moment more of a  
> design study than an implementation meant for use. It contains
>
> - a protocol definition for multiarray functions
> - a Clojure implementation (using the new deftype feature) of  
> multiarrays and the protocol
> - protocol implementations for
>    - a representation based on nested Clojure vectors
>    - the Java multiarray class from the Unidata libraries (netCDF etc.)
>    - the Java multiarray class from CERN's Colt library
>
> Note that the current state is very incomplete. Comments and  
> contributions of all kinds are welcome. My goal is to get this right  
> rathen then to get out a working library quickly, so take your time...
>
> The code is at:
>
>        http://code.google.com/p/clj-multiarray/
>
> Konrad.

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


Re: Deep deref

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 2:11 PM, John Harrop  wrote:

> On Sat, Nov 14, 2009 at 11:42 AM, André Thieme <
> splendidl...@googlemail.com> wrote:
>
>> Dereferencing *persons* will result in:
>> {"Tina" #,
>>  "Jeff" #,
>>  "Karl" #}
>> Great so far.
>>
>> People can become friends, so we need
>> (defn add-friend [#^String person #^String friend]
>>  (dosync
>>(let [p (get @*persons* person)
>>   f (get @*persons* friend)]
>>(alter p update-in [:friends] conj f
>>
>> So, Tina can get the friends Karl and Jeff:
>> (add-friend "Tina" "Karl")
>> (add-friend "Tina" "Jeff")
>>
>> Now the problem is: *persons* acts as our data base, and
>> when a request comes in (to our web application, hosted by,
>> say, Compojure) we want to see a consistent snapshot of the
>> DB.
>> But derefing *persons* won't do this for us.
>> Even when we deref Tina, we can not be sure who her friends
>> are, as those live in their own refs.
>> They have to. If Karl gets one year older then we only want to
>> change his date, and not traverse all persons first and see if
>> they have Karl as a friend and if yes updating his age there too.
>>
>> How can we handle this situation?
>
>
> I think the design in this sort of case needs changing.
>
> Repeated structure references also pose a problem for storage and retrieval
> (at least if not using a real DB) as Clojure's prn and read will turn shared
> substructures into separate copies.
>
> What's needed here is to make all person lookups go through one point, the
> *persons* table, so the :friends key would store a vector not of person
> struct references but simply of names.
>
> When you start using a real DB this won't change; only the name of the
> concept will, to a "key column". Name will be a key column in the *persons*
> table and will be how you get at particular rows (persons) in the table.
>

Actually, often you have to go further. For example, in the example above,
to accommodate name changes, the name field can't be the key field or you're
back to having to update every reference. There's also the possibility of
duplicate names for two different people; you don't want it to blow up (or
worse, mix two peoples' private data and make it all visible to both) as
soon as your Facebook clone's second John Smith signs up.

In situations like these, a computer-generated id is typically used as an
immutable key field:

table person

idname agefriends
000   Karl 20 [002]
001   Jeff 22 [002]
002   Tina 19 [000 001]

(I took the liberty of assuming you actually want friends to be a symmetric
relation, so add-friend will friend each person to the other. If not, it's
still a viable example of using a numeric GUID (globally-unique identifier).
Of course the UI can still display names rather than numbers in most
situations (the URLs generated by your web framework will need URLs -- if
you had http://myfacebookclone.com/profile/john_smith as a URL, which John
Smith? Better http://myfacebookclone.com/profile/1653782 even if it's less
human-understandable. Manually typing in URLs is rare user behavior anyway,
if your page linkage structure is decent).

-- 
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: Map a list of agents to a list of their values

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 12:49 PM, Kevin Q  wrote:

> I have a list of agents, each of which has a hasmap state. I want to
> get a list of values from the list of agents, naturally I used the map
> function and print the result of the map:
>
> (println
>  (map #(@%) agents))
>
> However, when I run this, I got error "Wrong number of args passed to:
> PersistentHashMap"
>
> I'm wondering why is this happening?


For situations like this, I find it handy to discover what reader-macros are
expanding to. This works well:

user=>(defmacro expand [arg] (println arg))
#'user/expand
user=>(expand #(@%))
(fn* [p1__6536] ((clojure.core/deref p1__6536)))

So it will have the same effect as (map deref agents), though the latter is
clearer.

I don't know why it's failing, but it seems unlikely that switching to (map
deref agents) will fix it.

-- 
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: Deep deref

2009-11-14 Thread Danny Woods
André Thieme wrote:
> How can we handle this situation?
> Is it possible to implement a function “deep-deref” which works
> as blindingly fast as deref does?
> I find this very important, and this is of great practical relevance
> for me. Please share your ideas

Hi André,

I had a similar issue with an application I wrote a while back.  The
initial structure was simple: a grid-based map, containing a number of
entities, each entity having a name, an owner, dimensions, etc.  The
map was behind a ref, and the entities were initially refs themselves,
embedded within the map structure.  Then I realised that it was
difficult to know with certainty what was in the deref'd map.

It kind of struck me then that I was thinking about the problem
incorrectly.  My object-oriented hat made me want to have the map and
entities as separate things, each in charge of its own state.  When I
re-wrote the code so that the entities were themselves an immutable
part of an immutable map, and that changes to entities resulted in an
*entirely new map*, those problems went away.  All the various
interactions with the UI and with the network updated the map and
entities transactionally, with a new, consistent map after each
alteration.  What a relief that was!

In your case, adding someone to a friend list should result in what is
conceptually a completely new database, that shares almost all of its
structure with its predecessor.  This top-level structure can sit
behind a ref, with immutable person structs as constituent parts.
This makes proper use of immutability and negates the need for a deep
deref.

That's just my experience.  I'd be interested to know if anyone has an
honest need for refs within refs (especially in a larger system).

Cheers,
Danny.

-- 
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: local constants in functions or static locals/Hilbert curve in clojure (no images:)

2009-11-14 Thread ajuc
> Eeeuw.
>
> Was this with a Clojure literal in the let, or with a non-trivial
> calculation using constants?

The only difference is literal map of maps in let form.
Full code here: http://clojure.pastebin.com/m17b8d69


I have to install java one more time, when I try to start java -
server, I get:
Error: no `server' JVM at `F:\Program Files\Java\jre6\bin\server
\jvm.dll

The difference in speed isn't that bad, and I can understand why
clojure depends on hot-spot for performance, especially in such a
young stage of development. But this optimisation would be nice :)

-- 
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: Map a list of agents to a list of their values

2009-11-14 Thread Kevin Q
Thanks! That works.
However, why wouldn't (map #(@%) agents) work?

On Nov 14, 1:01 pm, Sean Devlin  wrote:
> Try
>
> (map deref agents)
>
> On Nov 14, 12:49 pm, Kevin Q  wrote:
>
> > I have a list of agents, each of which has a hasmap state. I want to
> > get a list of values from the list of agents, naturally I used the map
> > function and print the result of the map:
>
> > (println
> >   (map #(@%) agents))
>
> > However, when I run this, I got error "Wrong number of args passed to:
> > PersistentHashMap"
>
> > I'm wondering why is this happening? Prior to calling the map
> > function, I did (apply await agents) to wait for all my agents to
> > finish. Does it affect things?
>
> > Thanks,

-- 
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: Map a list of agents to a list of their values

2009-11-14 Thread Kevin Q
Hi,
Thanks for the hint. I tried (map deref agents) and it did work. I
don't know if this is a bug?

On Nov 14, 2:31 pm, John Harrop  wrote:
> On Sat, Nov 14, 2009 at 12:49 PM, Kevin Q  wrote:
> > I have a list of agents, each of which has a hasmap state. I want to
> > get a list of values from the list of agents, naturally I used the map
> > function and print the result of the map:
>
> > (println
> >  (map #(@%) agents))
>
> > However, when I run this, I got error "Wrong number of args passed to:
> > PersistentHashMap"
>
> > I'm wondering why is this happening?
>
> For situations like this, I find it handy to discover what reader-macros are
> expanding to. This works well:
>
> user=>(defmacro expand [arg] (println arg))
> #'user/expand
> user=>(expand #(@%))
> (fn* [p1__6536] ((clojure.core/deref p1__6536)))
>
> So it will have the same effect as (map deref agents), though the latter is
> clearer.
>
> I don't know why it's failing, but it seems unlikely that switching to (map
> deref agents) will fix it.

-- 
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: Datatypes and Protocols - early experience program

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 1:42 PM, Richard Newman  wrote:

> I like CL's package support for this kind of situation, where
> unexported symbols can still be reached via foo::bar, at the cost of
> an obvious "code smell".


This suggests an alternate fix for the private functions in macros problem:

1. Keep the throw when dereferencing another ns's private vars.
2. Add a way to override that throw when dereferencing -- a
   "deref-private" that always works.
3. Add a reader macro, say #!, with the property that #!foo expands
   to (deref-private #'foo).
4. Macros can use #!priv-fn in their expansions to produce an
   expansion that calls a private function without issues.
5. #! outside of this circumstance would be a code smell.
6. Optionally, syntax-quote, when resolving symbols into fully
   qualified ones, might auto-#! all that reference private vars IN
   THE CURRENT NAMESPACE. Then no explicit #! is needed on the
   hypothetical priv-fn in the macro: `(priv-fn foo ~bar) instead of
   `(#!priv-fn foo ~bar). At the same time, referencing a *foreign*
   private function in a macro still needs the #!.Then #! is ALWAYS a
   smell.

-- 
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: local constants in functions or static locals/Hilbert curve in clojure (no images:)

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 3:03 PM, ajuc  wrote:

> I have to install java one more time, when I try to start java -
> server, I get:
> Error: no `server' JVM at `F:\Program Files\Java\jre6\bin\server
> \jvm.dll
>

You need to use the one in F:\Program Files\Java\jdk6 instead.

I'm surprised your IDE didn't select that one automatically. Mine
(Enclojure) did.

-- 
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: Map a list of agents to a list of their values

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 2:51 PM, Kevin Q  wrote:

> Hi,
> Thanks for the hint. I tried (map deref agents) and it did work. I
> don't know if this is a bug?


Nah, it's just being really sneaky.


> > (fn* [p1__6536] ((clojure.core/deref p1__6536)))
>

Even I didn't notice it before. There's an extra pair of parens, so it's
double-dereferencing. The problem is that #() brings in one pair, and @ in
expanding to (deref the-argument) brings in a second.

Just use (map deref agents).

General advice: Avoid directly using another reader macro inside #(); the
first thing should always be a symbol or a call that evaluates to a
function, e.g. #((function-returning-function arg) other-arg).

-- 
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: Map a list of agents to a list of their values

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 3:24 PM, John Harrop  wrote:

> On Sat, Nov 14, 2009 at 2:51 PM, Kevin Q  wrote:
>
>> Hi,
>> Thanks for the hint. I tried (map deref agents) and it did work. I
>> don't know if this is a bug?
>
>
> Nah, it's just being really sneaky.
>
>
>>  > (fn* [p1__6536] ((clojure.core/deref p1__6536)))
>>
>
> Even I didn't notice it before. There's an extra pair of parens, so it's
> double-dereferencing. The problem is that #() brings in one pair, and @ in
> expanding to (deref the-argument) brings in a second.
>

As for the seemingly irrelevant error message: I guess the agent's state was
a map, so it deref'd it and then invoked the map. Maps can be invoked, but
expect one argument (a key to look up) and it got zero. If the error had
been cannot cast to IFn, it would have been more apparent what was happening
quicker. There isn't much that can be done about the error message confusion
in cases like this, though; it goes with the territory of having a highly
dynamic language. Learning to interpret them is an art, one I'm still
mastering.

-- 
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: with-command-line and empty/nil args list

2009-11-14 Thread Mike Hogye
Thanks!

-- 
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: Deep deref

2009-11-14 Thread André Thieme
On 14 Nov., 20:22, John Harrop  wrote:
> On Sat, Nov 14, 2009 at 2:11 PM, John Harrop  wrote:
> > On Sat, Nov 14, 2009 at 11:42 AM, André Thieme <
> > splendidl...@googlemail.com> wrote:
>
> >> Dereferencing *persons* will result in:
> >> {"Tina" #,
> >>  "Jeff" #,
> >>  "Karl" #}
> >> Great so far.
>
> >> People can become friends, so we need
> >> (defn add-friend [#^String person #^String friend]
> >>  (dosync
> >>    (let [p (get @*persons* person)
> >>           f (get @*persons* friend)]
> >>    (alter p update-in [:friends] conj f
>
> >> So, Tina can get the friends Karl and Jeff:
> >> (add-friend "Tina" "Karl")
> >> (add-friend "Tina" "Jeff")
>
> >> Now the problem is: *persons* acts as our data base, and
> >> when a request comes in (to our web application, hosted by,
> >> say, Compojure) we want to see a consistent snapshot of the
> >> DB.
> >> But derefing *persons* won't do this for us.
> >> Even when we deref Tina, we can not be sure who her friends
> >> are, as those live in their own refs.
> >> They have to. If Karl gets one year older then we only want to
> >> change his date, and not traverse all persons first and see if
> >> they have Karl as a friend and if yes updating his age there too.
>
> >> How can we handle this situation?
>
> > I think the design in this sort of case needs changing.
>
> > Repeated structure references also pose a problem for storage and retrieval
> > (at least if not using a real DB) as Clojure's prn and read will turn shared
> > substructures into separate copies.

Well, I want to have a real in-ram db. Just not a relational one.
My in-ram data structures can express very well what I want to say.
I wrote a serialize and restore function that can print refs, even
circular
referential refs containing each other.


> > What's needed here is to make all person lookups go through one point, the
> > *persons* table, so the :friends key would store a vector not of person
> > struct references but simply of names.

Ok, so you would vote for having my own my-ref and my-deref functions,
which
references/dereferences my objects, using an ID under the hood.


> > When you start using a real DB this won't change; only the name of the
> > concept will, to a "key column". Name will be a key column in the *persons*
> > table and will be how you get at particular rows (persons) in the table.

I see your point, I just want to mention that we are maybe so trained
to use
relational db system that we see only them as a “real db” :-)


> Actually, often you have to go further. For example, in the example above,
> to accommodate name changes, the name field can't be the key field or you're
> back to having to update every reference. There's also the possibility of
> duplicate names for two different people; you don't want it to blow up (or
> worse, mix two peoples' private data and make it all visible to both) as
> soon as your Facebook clone's second John Smith signs up.
>
> In situations like these, a computer-generated id is typically used as an
> immutable key field:
>
> table person
>
> id            name             age        friends
> 000           Karl             20         [002]
> 001           Jeff             22         [002]
> 002           Tina             19         [000 001]

Okay, that makes sense. Basically the idea is having my own
ref and deref function, and then have a ref on a hashmap of a global
object container. Good, that would work and not change my programming
model, as the current one also requires the use of (deref ..) at
several
places.


> (I took the liberty of assuming you actually want friends to be a symmetric
> relation, so add-friend will friend each person to the other.

Yeah, that‘s fine. My example is just made up to illustrate the point.

Thanks for your idea, this seems to be the right way to do it.
So, now I need to look into how I can get @ to be extended to deref
(= run a function I specify) instances of the
(deftype my-ref ...) type.

-- 
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: Deep deref

2009-11-14 Thread André Thieme


On 14 Nov., 20:32, Danny Woods  wrote:
> André Thieme wrote:
> > How can we handle this situation?
> > Is it possible to implement a function “deep-deref” which works
> > as blindingly fast as deref does?
> > I find this very important, and this is of great practical relevance
> > for me. Please share your ideas
>
> Hi André,
>
> I had a similar issue with an application I wrote a while back.  The
> initial structure was simple: a grid-based map, containing a number of
> entities, each entity having a name, an owner, dimensions, etc.  The
> map was behind a ref, and the entities were initially refs themselves,
> embedded within the map structure.  Then I realised that it was
> difficult to know with certainty what was in the deref'd map.
>
> It kind of struck me then that I was thinking about the problem
> incorrectly.  My object-oriented hat made me want to have the map and
> entities as separate things, each in charge of its own state.  When I
> re-wrote the code so that the entities were themselves an immutable
> part of an immutable map, and that changes to entities resulted in an
> *entirely new map*, those problems went away.  All the various
> interactions with the UI and with the network updated the map and
> entities transactionally, with a new, consistent map after each
> alteration.  What a relief that was!
>
> In your case, adding someone to a friend list should result in what is
> conceptually a completely new database, that shares almost all of its
> structure with its predecessor.  This top-level structure can sit
> behind a ref, with immutable person structs as constituent parts.
> This makes proper use of immutability and negates the need for a deep
> deref.

Danny, could you maybe hack up a possible very simple example of what
you mean?
I am not sure how complete my understanding of what you said is.


> That's just my experience.  I'd be interested to know if anyone has an
> honest need for refs within refs (especially in a larger system).

The idea behind my posting is a in-ram db system.
I don‘t want to use a relational db.
Now I have many objects, be it defstructs or deftypes. Those things
need
to be changable. And other objects must be able to reference them.
In the example I made up Tina has the friend Karl.
I can not simply store a copy of the Karl person in Tinas :friends
slot,
because when Karl gets one year older, then I don‘t want to go through
all persons, looking for Karls, and have their age updated.
Instead it is preferred to have
(defn update-age [#^String person new-age]
  (dosync
(alter (get @*persons* person) assoc :age new-age)))

When we then (update-age "Karl" 25), then the Karl in Tinas :friends
slot will also be 25.

And each object needs to live in at least one index. In my example
this index is called *persons* and maps from the name to a person
instance.
There can be other indexes, for example *age-to-persons*, and when we
look up there who is 42 years old, then we will get a set of person
instances who are older.
These indexes need to be refs also, because we constantly want to put
new objects in there or delete them. So, refs in refs are really
interesting when you want to have your own in-ram db system.

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


ANN: Clojure API for AllegroGraph

2009-11-14 Thread Mike Hinchey
Franz Inc and I just put the AllegroGraph 3.2 Java API on github with my new
Clojure API.  The clojure is a wrapper of the java client, which is an
implementation of openrdf/sesame.  The wrapper is mostly to make it more
idiomatic clojure so you don't have to deal with so many java classes,
mutable objects, and resources that have to be closed.  It's a
work-in-progress, of course, and any feedback is appreciated.

The master branch is for the future release AG 4.0, so you'll want to use
the agraph32 branch for the current release.
http://github.com/franzinc/agraph-java-client/tree/agraph32

This is the code I'll be presenting tomorrow at the Semantic Web
installfest.
http://www.meetup.com/The-San-Francisco-Semantic-Web-Meetup/calendar/11788554/

My future plans for this are to have more advance ways of manipulating
triples, especially having them linked up in trees rather than a flat lists
referring to each other, which is what you get back from a query.

By the way, I included the clojure-1.0.jar because I assume this will be
used by companies that need a stable release, but last I checked, the code
works fine with master, and I'm happy to officially support master if that's
what anyone wants.

-Mike

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

YAClojureBlog

2009-11-14 Thread Seth
As I spelunk through Clojure my experiences are being posted to
http://blogs.foognostic.net/topics/code/clojure/. Recently, I have
been implementing some basics of poker with the goal of playing it at
the REPL. Any and all comments -- including scathing code reviews! --
would be very welcome.

BTW, I would encourage everyone to check out Clojure's IRC channel --
Chouser especially has been patient and pedagogical (positively so!).
irc://irc.freenode.net/#clojure

-- 
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: Clojure Web Libraries

2009-11-14 Thread ngocdaothanh
Hi Stuart,

Can you elaborate on Restlet? After some short investigation I think
it uses annotation but Clojure does not support it, so Clojure is not
"Restlet-ready".

Thanks


On Jan 23, 1:44 am, Stuart Sierra  wrote:
> Hi Frank,
> I'd also recommend looking atRestlet and
> the Java Servlets API.
> -Stuart Sierra
>
> On Jan 21, 4:39 pm, Frank  wrote:
>
> > Hi,
>
> > I am interested in trying to use Clojure to develop web-based
> > applications.  Can someone point me to any Clojure libraries that have
> > been written that I can use.  Thanks.
>
> > Frank

-- 
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: Clojure Web Libraries

2009-11-14 Thread Stuart Sierra
The latest restlet versions use annotations.  I stil use 1.1, which uses
ordinary classes.  I'm bothered by restlet's move to annotations, but
hoefully the old API is still available.

sent from my phone

On Nov 14, 2009 10:58 PM, "ngocdaothanh"  wrote:

Hi Stuart,

Can you elaborate on Restlet? After some short investigation I think
it uses annotation but Clojure does not support it, so Clojure is not
"Restlet-ready".

Thanks


On Jan 23, 1:44 am, Stuart Sierra  wrote:
> Hi Frank,
> I'd also recommend looking atRestlet and
> the Java Servlets API.
> -Stuart Sierra
>
> On Jan 21, 4:39 pm, Frank  wrote:
>
> > Hi,
>
> > I am interested in trying to use Clojure to develop web-based
> > applications.  Can someone point me to any Clojure libraries that have
> > been written that I can use.  Thanks.
>
> > Frank

-- 
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: Clojure Web Libraries

2009-11-14 Thread David Brown
>> On Jan 21, 4:39 pm, Frank  wrote:
>>
>> > I am interested in trying to use Clojure to develop web-based
>> > applications.  Can someone point me to any Clojure libraries that have
>> > been written that I can use.  Thanks.

I spent a couple of days this week using Compojure both in anger, and
for fun.  The anger stuff isn't source-available, but my fun project
is:

   

There is (hopefully) a live version at:

   

The app itself probably isn't that interesting itself, since it
generates the reports for my weight management program.

Part of my goal was to be well integrated with Maven, but also have
decent interactive use.

   - setup-repl.sh uses Maven to download the dependencies and put them
 in a place that 'run.sh' is expecting them.  Combined with the
 user.clj I wrote, it allows me to do things like:

   ./run.sh -Dwork-ns=org.davidb.webweight.daily

 and get a REPL where (l) will reload this namespace, (t) will load
 one with the name of org.davidb.webweight.test_daily and run tests
 on it (there aren't tests in this code yet), and (i) will switch
 to the dev namespace.  It doesn't reload sub-required namespaces,
 so isn't perfect, but still quite useful.

   - mvn compile should work with the maven-clojure-plugin.  It'll also
 package a jar file.

   - mvn assembly:assembly will make a jarfile containing the
 dependents.  There's a org.davidb.webweight.main that can run it
 directly.

All in all, it's a fairly quick framework to setup.

My github page also has my patches to compojure to build it under
Maven.  The json library is from Tim Dysinger's repo:
.  I just installed these
locally.

The "in anger" project connects to a PostgreSQL database and interacts
with a backend auto-build system.

David

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