Re: struct question

2009-01-22 Thread Jason Wolfe


On Jan 21, 11:48 pm, Mark Engelberg mark.engelb...@gmail.com wrote:
 Thanks for the thread links.  This is basically what I suspected -- if
 you want to use structs in multimethods, you have to roll your own
 constructor which adds some kind of type tag to either the hashmap
 or the metadata.

 It just seems like a common case, so I was hoping there was a more
 convenient way.  But I guess that's what macros are for...

In that vein, there's this thread:

http://groups.google.com/group/clojure/browse_thread/thread/257caab7867aa09c?hl=en#

which may do something like what you would like.  This is also an
issue I'm interested in, and I was planning on making some group/blog
posts about it in the near future.

FYI, I usually follow the following pattern:

My interface files contain a bunch of (defmulti ...)s, which mostly
dispatch on the :class of the first argument

Then, my class files contain
(derive ::MyClass :namespace/ParentClass)
(defstruct my-class :class :a :b :c)
(defn make-my-class [a b c]
(struct my-class ::MyClass a b c))
followed by a bunch of (defmethod ...)s

But this does involve a bit of repetition, and I'm not sure if this is
the most idiomatic way to do things currently.

-Jason


--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread Konrad Hinsen

On 22.01.2009, at 07:48, Mark Engelberg wrote:

 Is there any way to determine whether something is a struct (versus
 an ordinary hash map), and if so, determine which kind of struct it
 was built from?

Not that I know. I have been searching for a while, and ended up  
using my own tag attached to the struct as metadata. In clojure.zip  
there is a similar use of metadata: methods are implemented as  
functions passed in the metadata.

I am not entirely happy with this approach though. If everyone starts  
to use metadata for various purposes, such type tags may well  
disappear by some function replacing the metadata on an object  
without preserving the tags that are already there. This is all the  
more likely because there is nothing in the standard library to add a  
tag to an existing metadata map. All there is is (with-meta ...),  
which replaces the metadata map completely.

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
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: struct question

2009-01-22 Thread David Nolen
Finally started a GitHub repo just for this project.
http://github.com/swannodette/cljos/tree/master

The earlier version of course was very flawed/buggy.  OK start, but the
macros in it were written with little/no understanding about how symbols are
resolved into their namespaces in Clojure (or Lisp for that matter). If
anybody is interested at all please feel free to fork or to leave comments.
 In particular I found no way to capture the symbols and their true
namespaces without resorting to eval and some wacky macros.  That said, it
does indeed work.  defclassed structs always refer to the namespace in which
they were declared, and parents correctly reflect their originating
namespace as well.

New stuff:

(instance-of? my-platypus platypus)
(member-of? a-circle shape)

No need for tags.  The only time you need tags is when defining
multimethods.  There's no real clean way to get around this except
implementing a macro around defmethod, and I'm not really sure creating a
macro around defmethod is so hot.  The discussion earlier about multiple
hierarchies for multimethod, especially predicate support would solve this
cleanly.

defclass now returns the struct.  I've also been toying around with an
optional Smalltalk message based dispatch.  Note the special applym, a
special version of apply that first checks to see if a struct responds? to a
multimethod.  If not it checks to see if there is a proxy and forwards the
message with the args to proxy.  This could allow for some interesting
interactions.

(defclass my-spore-animal [platypus]
  (:third-eye true))

(defclass bacteria [object]
  (:digest-grass true))

(def my-spore (make-instance my-spore-animal))
(def my-parasite (make-instance bacteria))

(defmulti digest :tag)
(defmethod digest ::bacteria [obj]
  (println Munch munch!))

;; we can pass messages to a proxy class
(applym digest (assoc my-spore :proxy my-parasite)) ;; Munch Munch!


The most exciting thing however is multimethod reflection (many thanks to
Rich).  The following is all the code it takes to see all the multifns that
specializes a particular tag.  In fact, really it should check all the
ancestors of the tag as well in order and I'm open to suggestions on what
the best way to implement that would be.

(defn has-dispatch? [multifn tag]
  (not (= (tag (methods multifn))
  nil)))

(defn responds? [obj multifn]
  (has-dispatch? multifn (:tag obj)))

(defn is-multi? [metadata]
  (and (:tag metadata)
  (= clojure.lang.MultiFn (:tag metadata

(defn who-specializes-tag? [tag]
  (filter #(and (is-multi? (meta %))
(has-dispatch? (var-get %) tag))
  (flatten (map #(vals (ns-interns %)) (all-ns)

(defmacro who-specializes? [constructor]
  `(who-specializes-tag?
(:class (meta (var ~(symbol (name constructor)))

--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread David Nolen

 I am not entirely happy with this approach though. If everyone starts
 to use metadata for various purposes, such type tags may well
 disappear by some function replacing the metadata on an object
 without preserving the tags that are already there. This is all the
 more likely because there is nothing in the standard library to add a
 tag to an existing metadata map. All there is is (with-meta ...),
 which replaces the metadata map completely.

 Konrad.


Permanently changing the tag of an object after instantiation probably isn't
such a safe thing to do anyway. That's where functions like pose-as and
applym can come in handy.

--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread Christophe Grand

Konrad Hinsen a écrit :
 there is nothing in the standard library to add a  
 tag to an existing metadata map. All there is is (with-meta ...),  
 which replaces the metadata map completely.
   
It itched me before and since there's already alter-meta! maybe there 
should also be an alter-meta (or better name) in core.clj.

Christophe

(defn alter-meta
 Returns an object of the same type and value as obj, with
  (apply f (meta obj) args) as its metadata.
 [obj f  args]
  (with-meta o (apply f (meta o) args)))



--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread Konrad Hinsen
On 22.01.2009, at 09:30, Konrad Hinsen wrote:

 Not that I know. I have been searching for a while, and ended up
 using my own tag attached to the struct as metadata. In clojure.zip
 there is a similar use of metadata: methods are implemented as
 functions passed in the metadata.

After a quick look at the Clojure source code, I had an idea for  
implementing something better, and did it :-) A patch is attached.

This patch adds:

- a Java method on structmaps that returns the structure basis (the  
object created by defstruct).

- a few Clojure functions to work with this:
(struct-basis x)  returns the structure basis of structmap x
(struct? x) returns true if x is a structmap
(struct? x s) returns true if x is a structmap with basis s
(struct-basis? s) returns true if s it a structure basis

- a minimal patch to derive that allows structure basis objects to be  
used in hierarchies

At the end of this message is a simple illustration of what can be  
done with these changes. Any feedback is welcome of course!

Konrad.


(defstruct rectangle :x :y :w :h)
(defstruct circle :x :y :r)

(defmulti area struct-basis)

(defmethod area rectangle
   [r]
   (* (:w r) (:h r)))

(defmethod area circle
   [c]
   (let [r (:r c)]
 (* (. Math PI) r r )))

(area (struct rectangle 0. 0. 2. 3.))
(area (struct circle 0. 0. 1.))


(derive rectangle ::shape)
(derive circle ::shape)

(defmulti center struct-basis)

(defmethod center ::shape
   [s]
   [(:x s) (:y s)])

(defmethod center rectangle
   [r]
   (let [{:keys [x y w h]} r]
 [(/ (+ x w) 2) (/ (+ y h) 2)]))

(center (struct rectangle 0. 0. 2. 3.))
(center (struct circle 0. 0. 1.))


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
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
-~--~~~~--~~--~--~---



structs_in_multimethods.diff
Description: Binary data


Re: Clojure Web Libraries

2009-01-22 Thread James Reeves

On Jan 21, 9:39 pm, Frank ffai...@gmail.com 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.

There's Compojure, which looks like this:

(defservlet demo-servlet
  (GET /
(html [:h1 Hello World]))

( http://github.com/weavejester/compojure )

Weld, which I believe looks like this (Mark, please correct me if I've
misrepresented Weld):

(def config
  {'weld.routing/*router*
(compiled-router [['index-page :index :get /]])})

(defn index-page [req]
  (respond (html [:h1 Hello World])))

( http://github.com/mmcgrana/weld )

And Webjure, which looks like this:

(defh / [] {:output :html}
  `(:h1 Hello World))

( http://code.google.com/p/webjure )

Out of the three frameworks, it's possible that Compojure is the most
popular: at least, I've seen more tutorials and sites written with it.
But since I'm the author of Compojure, I can't exactly claim I'm
unbiased :)

- James
--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread Konrad Hinsen

On 22.01.2009, at 10:51, Konrad Hinsen wrote:

 At the end of this message is a simple illustration of what can be
 done with these changes. Any feedback is welcome of course!

Maybe I should reply immediately to some objections I expect to come:

1) Why create a secondary type system around structs? Why not  
something more general?

Many languages have type system grown out of structures, e.g. C++, or  
Scheme. It works pretty well. I'd happily propose something more  
general if I had a great idea.

In the meantime, there is a real need for something like a type  
system for use with multimethods, as the topic comes up repeatedly on  
this group. It looks strange to see a language in which it is easy to  
define a type hierarchy (using derive) but in which putting the type  
label on an object is a pain.

2) Using metadata is more general.

A bit, but metadata is limited to collections as well. Moreover, it  
is used for many different applications, which creates the risk of  
conflicts. Finally, it is invisible (not part of the printed  
representation) and not used in comparisons etc. It is not considered  
part of the value of a data item, whereas type information normally  
*is* part of the value, even an important one.

3) Structmaps are just an optimized implementation of maps.

That's what they are now, but that doesn't mean they can't evolve  
into something else. For structs to become an official type system,  
some more changes would be useful:
- Structure basis objects should have a printed representation that  
includes the name given in defstruct (or nil for an anonymous one  
created by create-struct)
- Structure basis objects could acquire some methods, e.g. for  
obtaining the keys.

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
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: Agent as a processing queue

2009-01-22 Thread Greg Harman

Thanks Tim, I'll have a look at that.

To clarify my use case, I was thinking of events that can be processed
sequentially but that may take a non-trivial amount of time to
complete (both CPU and IO bound at different stages of processing) so
it's ideal to have a thread pool to process different tasks in
parallel, even though they are independent. (That's step one. Step two
will be spreading that thread pool out over multiple JVMs running on
different hardware).

On Jan 22, 2:39 am, Timothy Pratley timothyprat...@gmail.com wrote:
 Hi Greg

 Here is a proof of concept of one approach you could 
 take:http://groups.google.com/group/clojure/web/job-queue.clj

 A set of agents are maintained to represent computation jobs. When the
 results are gathered, the agent is thrown away. I think using multiple
 agents in this way could be quite convenient as it means the jobs can
 be done in parallel.

 If you run the script from the command line you should get something
 like this:
 C:\javaclj job-queue.clj
 (4 3)
 (0 nil Hi mum)
 Which are the results of multiple queued computations taken at two
 subsequent points in time.

 From your post it wasn't clear to me if your 'events' imply sequential
 processing (which could be achieved with a single agent).

 Regards,
 Tim.
--~--~-~--~~~---~--~~
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
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: Gorilla issue with recent builds?

2009-01-22 Thread Mark Feeney

Hi Meikel,

On Jan 21, 3:01 pm, Meikel Brandmeyer m...@kotka.de wrote:
 There was a breakage some time ago, which made it necessary
 to release a bug fix release. The revisions are named on the
 vim.org page, where you can download Gorilla. Please check
 there if this solves your problem. If not, please send me the revisions
 of clojure and clojure-contrib and the version of Gorilla you are using.

I have the 1.1.1 version of Gorilla, yes.

I ran some tests and I've determined when it breaks:

clojure rev, clojure-contrib rev, vim repl working
1214, 405, yes
1215, 405, no

So some change in Clojure from 1214 - 1215 causes the Vim Repl to
stop working.  The clojure-contrib version appears not to be a
factor.  I haven't had a chance to dig deeper, but this additional
info may shed a bit more light...

Thanks,


Mark.

--~--~-~--~~~---~--~~
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
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: Streams work

2009-01-22 Thread Rich Hickey



On Jan 22, 12:53 am, Mark H. mark.hoem...@gmail.com wrote:
 On Jan 21, 5:21 pm, e evier...@gmail.com wrote:

  I would think it would be useful to have something exactly like a stream but
  that allowed as many iterators as you like but that a mutex prevented any
  two from consuming the same piece of information.

 That might be useful for something, but it's hard to make correct in
 all cases.  The reason is that both stream elements and connections
 between stream elements are mutable and shared.  Here follows an
 example.

 Imagine iterating over a singly-linked list, where you delete each
 node (explicitly, not by losing the reference) _and_ the link to the
 next node right after you get the next node.  (For example, a
 directory of files might be implemented as a singly-linked list, and
 you want to delete all the files _and_ the directory itself and print
 all the files deleted, by only making one pass over the directory.)
 You could implement this as a generator which is a closure over a let-
 bound Java object (I've made up some utility function names below):

 (defn make-dir-gen [dirname]
   (let [dirstart (directory-list dirname)]
 (fn [eos]
   (loop [dirent dirstart]
 (if (dir-empty? dirent)
   eos
   (let [link (next-link dirent)]
  next (next-entry link)]
 (delete-file! dirent)
 (delete-link! link)
 (recur next)))

 Now imagine two threads T1 and T2 accessing this generator at the same
 time.  Suppose they reach the same node at the same time, and suppose
 that you've protected file deletion and link deletion each
 individually with a mutex (and forbade multiple deletions silently).
 T1 might delete the file and the link and get to recur next before
 T2 can call (next-entry link).  Now T1 goes on but T2 is stuck:
 link is _gone_ so (next-entry link) goes nowhere.

 Protecting the data for access by multiple threads has to be the
 responsibility of the person implementing the generator function,
 because a generator function can have arbitrary side effects and
 iterate over arbitrary mutable data structures with constantly
 changing topology.  (Imagine a generator that goes five times around a
 circular list, then breaks the circular link and splices the list into
 another list, leaving a list fragment floating.)  It's too hard to try
 to imagine a streams implementation that could automatically make
 everything thread-safe, or even to imagine what thread-safe means
 in the context of general mutable data structures.


Those are important things to think about.

There are, in fact, thread semantics for the streams mechanism, as for
the rest of Clojure. Currently, I've made it such that the stream/iter/
seq combination ensures serialized access to the generator, allowing
use of generators over otherwise unsynchronized multi-step activities.

Obviously, stream-backed seqs are safe, being persistent and
immutable. but it is also currently the case that the stream iter is
MT safe as well. All calls to next! on an iter are atomic re: its
generator, i.e. no 2 threads can be in the generator code at once.
That means that, within a private consumer, you could fire up multiple
threads that share the same iter and coordinate to produce a result,
and return the result or a stream upon it.

Used correctly, this is a powerful feature. However, I'm reluctant to
expose/guarantee it, lest people start using iters as connection
points and invalidating the whole stream protection model. A well-
written API should take/return streams/seqs, never iters, so MT use of
an iter should always be an implementation detail of a single stream
step. But I can't enforce that.

For those looking to experiment with such things, feel free to try it
now and provide feedback.

Thanks,

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
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: Streams work

2009-01-22 Thread e

 Now imagine two threads T1 and T2 accessing this generator at the same
 time.  Suppose they reach the same node at the same time, and suppose
 that you've protected file deletion and link deletion each
 individually with a mutex (and forbade multiple deletions silently).
 T1 might delete the file and the link and get to recur next before
 T2 can call (next-entry link).  Now T1 goes on but T2 is stuck:
 link is _gone_ so (next-entry link) goes nowhere.


hmm.  Good point.  I'm sure there's a lot to think about, but, at first,
that sounds like a challenge.  Like now I'm wondering if what you could do
is have the generator automatically update the list of handed out iterators
automatically.  Then I realize you'd have to update eos, too.  But the
client may already have checked eos.  So I see that Rich's idea is more
obvious.  Rather than making magic streams, he shows how one might do the
same thing by sharing a single iterator.

--~--~-~--~~~---~--~~
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
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: Agent as a processing queue

2009-01-22 Thread Greg Harman

I like the example, and I should be able to adapt it. I do have one
question about the example (probably not related to agents:

; queue up some work to be done
(defn add-job [func]
  (let [a (agent nil)]
(send a (fn [_] (func)))
(swap! jobs #(conj %1 a

What is the notation fn [_]? I can't seem to find any documentation
for what _ as a function argument means...

On Jan 22, 6:14 am, Greg Harman ghar...@gmail.com wrote:
 Thanks Tim, I'll have a look at that.

 To clarify my use case, I was thinking of events that can be processed
 sequentially but that may take a non-trivial amount of time to
 complete (both CPU and IO bound at different stages of processing) so
 it's ideal to have a thread pool to process different tasks in
 parallel, even though they are independent. (That's step one. Step two
 will be spreading that thread pool out over multiple JVMs running on
 different hardware).

 On Jan 22, 2:39 am, Timothy Pratley timothyprat...@gmail.com wrote:

  Hi Greg

  Here is a proof of concept of one approach you could 
  take:http://groups.google.com/group/clojure/web/job-queue.clj

  A set of agents are maintained to represent computation jobs. When the
  results are gathered, the agent is thrown away. I think using multiple
  agents in this way could be quite convenient as it means the jobs can
  be done in parallel.

  If you run the script from the command line you should get something
  like this:
  C:\javaclj job-queue.clj
  (4 3)
  (0 nil Hi mum)
  Which are the results of multiple queued computations taken at two
  subsequent points in time.

  From your post it wasn't clear to me if your 'events' imply sequential
  processing (which could be achieved with a single agent).

  Regards,
  Tim.
--~--~-~--~~~---~--~~
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
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: Streams work

2009-01-22 Thread Konrad Hinsen

On 21.01.2009, at 20:33, Rich Hickey wrote:

 I've started documenting the streams work I have been doing, for those
 interested:

 http://clojure.org/streams

Nice!

I have played a bit with the stream implementation, and I came across  
a behaviour that I do not understand:

First, define a random stream that calls rand, and an iter on it:

(def rand-stream (stream (fn [_] (rand
(def rand-iter (stream-iter rand-stream))

Calling it a few times shows that it works:

(next! rand-iter nil)
(next! rand-iter nil)

Next, try to use it as a seq:

(take 4 rand-stream)

This fails, as it should:

java.lang.IllegalStateException: Already iterating (NO_SOURCE_FILE:0)

Detach the iter and try again:

(detach! rand-iter)
(take 4 rand-stream)

Now it works - fine. But what happened to the seq that now owns the  
stream? Nothing refers to it, so it should be gone. Did it perhaps  
liberate the stream, so that I can create an iter again? Let's try:

(def rand-iter (stream-iter rand-stream))
(next! rand-iter nil)
(next! rand-iter nil)

It seems so. But... let's be mean:

(take 4 rand-stream)

I would expect this to throw the IllegalStateException again, but it  
doesn't: it returns the same four-number sequence as the last time it  
was called. Where was that one stored? In the stream itself? Or does  
the stream keep a reference to the seq, so that it never disappears?  
But then I shouldn't be able to create another iterator.

Let's be mean again:

(next! rand-iter nil)
(take 10 rand-stream)
(next! rand-iter nil)
(next! rand-iter nil)
(take 15 rand-stream)

All of these work - it seems I have both an iter and a seq on the  
same stream, with the iter returning values that are also in the seq.

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
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: struct question

2009-01-22 Thread Rich Hickey



On Jan 22, 4:46 am, Christophe Grand christo...@cgrand.net wrote:
 Konrad Hinsen a écrit : there is nothing in the standard library to add a
  tag to an existing metadata map. All there is is (with-meta ...),
  which replaces the metadata map completely.

 It itched me before and since there's already alter-meta! maybe there
 should also be an alter-meta (or better name) in core.clj.


Me too. I've added vary-meta in SVN 1223.

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
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: printing deeply nested things

2009-01-22 Thread Stuart Halloway

Hi Rich,

It is a small real problem: in the book I demonstrate an incorrect,  
stack-consuming recursion that blows up on a deeply nested structure.  
When the recursion is fixed, it *still* blows up because the REPL  
cannot print it, so I introduce *print-level*.

I don't think printing super-deep structures at the REPL is  
particularly important, but I am curious how you would go about  
implementing it.

Stuart

 On Jan 21, 8:43 pm, Stuart Halloway stuart.hallo...@gmail.com wrote:
 Consider the function deeply-nested:

 (defn deeply-nested [n]
   (loop [n n
 result [:bottom]]
 (if (= n 0)
   result
   (recur (dec n) [result]

 If you print it at the REPL for small values of n, no problem:

 (deeply-nested 25)
 - [[:bottom]]

 But for large values of n:

 (deeply-nested 100)
 - java.lang.StackOverflowError

 You can dodge this problem by setting *print-level*

 (set! *print-level* 25)
 - 25
 (deeply-nested 100)
 - [#]

 But what if you really want to print a deeply nested structure? What
 is the simplest modification to core_print.clj that gets the job  
 done?
 Is this a good use case for trampoline, or is there a better  
 Clojurish
 way?

 Is this a real problem or a theoretical one?

 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
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: Agent as a processing queue

2009-01-22 Thread Christian Vest Hansen

On Thu, Jan 22, 2009 at 2:52 PM, Greg Harman ghar...@gmail.com wrote:

 I like the example, and I should be able to adapt it. I do have one
 question about the example (probably not related to agents:

 ; queue up some work to be done
 (defn add-job [func]
  (let [a (agent nil)]
(send a (fn [_] (func)))
(swap! jobs #(conj %1 a

 What is the notation fn [_]? I can't seem to find any documentation
 for what _ as a function argument means...

It's a conventional name for unused/ignored arguments.



 On Jan 22, 6:14 am, Greg Harman ghar...@gmail.com wrote:
 Thanks Tim, I'll have a look at that.

 To clarify my use case, I was thinking of events that can be processed
 sequentially but that may take a non-trivial amount of time to
 complete (both CPU and IO bound at different stages of processing) so
 it's ideal to have a thread pool to process different tasks in
 parallel, even though they are independent. (That's step one. Step two
 will be spreading that thread pool out over multiple JVMs running on
 different hardware).

 On Jan 22, 2:39 am, Timothy Pratley timothyprat...@gmail.com wrote:

  Hi Greg

  Here is a proof of concept of one approach you could 
  take:http://groups.google.com/group/clojure/web/job-queue.clj

  A set of agents are maintained to represent computation jobs. When the
  results are gathered, the agent is thrown away. I think using multiple
  agents in this way could be quite convenient as it means the jobs can
  be done in parallel.

  If you run the script from the command line you should get something
  like this:
  C:\javaclj job-queue.clj
  (4 3)
  (0 nil Hi mum)
  Which are the results of multiple queued computations taken at two
  subsequent points in time.

  From your post it wasn't clear to me if your 'events' imply sequential
  processing (which could be achieved with a single agent).

  Regards,
  Tim.
 




-- 
Venlig hilsen / Kind regards,
Christian Vest Hansen.

--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread Rich Hickey



On Jan 22, 2:48 am, Mark Engelberg mark.engelb...@gmail.com wrote:
 Thanks for the thread links.  This is basically what I suspected -- if
 you want to use structs in multimethods, you have to roll your own
 constructor which adds some kind of type tag to either the hashmap
 or the metadata.

 It just seems like a common case, so I was hoping there was a more
 convenient way.  But I guess that's what macros are for...

For now, yes. Struct bases are largely an implementation detail at
this point. I don't want people marrying the current implementation.
Doing something more for structs is on the agenda, but just what is an
open question.

It's pretty easy to write a trivial struct system, much harder to
address performance, interop, compilability, dynamicity etc
constraints.

As a simple case, if a defstruct is re-evaluated, will objects created
after that be of the same 'type' as objects created before? What if
fields have been added/removed? There are people using structs right
now who are very interested in the interface they present to Java
clients.

I'd prefer people experiment with libraries built on the existing
facilities, with an open mind as to the possibilities of categorizing
things other than by their structure.

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
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: Streams work

2009-01-22 Thread Christian Vest Hansen

On Thu, Jan 22, 2009 at 2:18 PM, Rich Hickey richhic...@gmail.com wrote:

 Those are important things to think about.

 There are, in fact, thread semantics for the streams mechanism, as for
 the rest of Clojure. Currently, I've made it such that the stream/iter/
 seq combination ensures serialized access to the generator, allowing
 use of generators over otherwise unsynchronized multi-step activities.

 Obviously, stream-backed seqs are safe, being persistent and
 immutable. but it is also currently the case that the stream iter is
 MT safe as well. All calls to next! on an iter are atomic re: its
 generator, i.e. no 2 threads can be in the generator code at once.
 That means that, within a private consumer, you could fire up multiple
 threads that share the same iter and coordinate to produce a result,
 and return the result or a stream upon it.

 Used correctly, this is a powerful feature. However, I'm reluctant to
 expose/guarantee it, lest people start using iters as connection
 points and invalidating the whole stream protection model. A well-
 written API should take/return streams/seqs, never iters, so MT use of
 an iter should always be an implementation detail of a single stream
 step. But I can't enforce that.

Hmm... could we imagine a (synced-iter an-iter) that returned a
wrapped iter that _did_ guarantee MT safety?

Ofcourse this only makes sense if you end up not guaranteing MT safety
of ordinary iters, and I don't know enough to prefer one approach over
the other.


 For those looking to experiment with such things, feel free to try it
 now and provide feedback.

 Thanks,

 Rich

 




-- 
Venlig hilsen / Kind regards,
Christian Vest Hansen.

--~--~-~--~~~---~--~~
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
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-01-22 Thread Mark McGranaghan

I'd suggest using Compojure for your first project - its fairly widely
used, is easy to pick up, and has a growing set of docs.

I'm not sure that Webjure is maintained anymore (i.e. no commits to
its repo in a few months).

Weld is still a work in progress - I'm trying to stabilize it now but
it needs some more time.

- Mark

On Thu, Jan 22, 2009 at 5:08 AM, James Reeves
weavejes...@googlemail.com wrote:

 On Jan 21, 9:39 pm, Frank ffai...@gmail.com 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.

 There's Compojure, which looks like this:

 (defservlet demo-servlet
  (GET /
(html [:h1 Hello World]))

 ( http://github.com/weavejester/compojure )

 Weld, which I believe looks like this (Mark, please correct me if I've
 misrepresented Weld):

 (def config
  {'weld.routing/*router*
 (compiled-router [['index-page :index :get /]])})

 (defn index-page [req]
  (respond (html [:h1 Hello World])))

 ( http://github.com/mmcgrana/weld )

 And Webjure, which looks like this:

 (defh / [] {:output :html}
  `(:h1 Hello World))

 ( http://code.google.com/p/webjure )

 Out of the three frameworks, it's possible that Compojure is the most
 popular: at least, I've seen more tutorials and sites written with it.
 But since I'm the author of Compojure, I can't exactly claim I'm
 unbiased :)

 - James
 


--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread Konrad Hinsen

On 22.01.2009, at 15:26, Rich Hickey wrote:

 It's pretty easy to write a trivial struct system, much harder to
 address performance, interop, compilability, dynamicity etc
 constraints.

Indeed.

 As a simple case, if a defstruct is re-evaluated, will objects created
 after that be of the same 'type' as objects created before?

I'd say no, which resolves the next question:

 What if fields have been added/removed?

Anyway, I don't think that re-evaluation is a serious issue, except  
in interactive development sessions. The typical use would be  
defining a struct once and then not touch it any more.

 I'd prefer people experiment with libraries built on the existing
 facilities, with an open mind as to the possibilities of categorizing
 things other than by their structure.

The added flexibility of multimethods is quite appreciable in non- 
trivial situations. But at the moment there is no simple way to  
handle simple situations. Using structs is straightforward and  
familiar from other languages. It is certainly not *the* solution to  
categorizing, but it's a simple one that is good enough for many  
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
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: Streams work

2009-01-22 Thread Rich Hickey



On Jan 22, 9:08 am, Konrad Hinsen konrad.hin...@laposte.net wrote:
 On 21.01.2009, at 20:33, Rich Hickey wrote:

  I've started documenting the streams work I have been doing, for those
  interested:

 http://clojure.org/streams

 Nice!

 I have played a bit with the stream implementation, and I came across
 a behaviour that I do not understand:

 First, define a random stream that calls rand, and an iter on it:

 (def rand-stream (stream (fn [_] (rand
 (def rand-iter (stream-iter rand-stream))

 Calling it a few times shows that it works:

 (next! rand-iter nil)
 (next! rand-iter nil)

 Next, try to use it as a seq:

 (take 4 rand-stream)

 This fails, as it should:

 java.lang.IllegalStateException: Already iterating (NO_SOURCE_FILE:0)

 Detach the iter and try again:

 (detach! rand-iter)
 (take 4 rand-stream)

 Now it works - fine. But what happened to the seq that now owns the
 stream? Nothing refers to it, so it should be gone.

No, the stream must refer to it, in order to keep its promise to
return the same seq every time.

 Did it perhaps
 liberate the stream, so that I can create an iter again? Let's try:

 (def rand-iter (stream-iter rand-stream))
 (next! rand-iter nil)
 (next! rand-iter nil)

 It seems so. But... let's be mean:

 (take 4 rand-stream)

 I would expect this to throw the IllegalStateException again, but it
 doesn't: it returns the same four-number sequence as the last time it
 was called. Where was that one stored? In the stream itself? Or does
 the stream keep a reference to the seq, so that it never disappears?
 But then I shouldn't be able to create another iterator.

What you've created an iter on the second time is the seq of the
stream. Right now, once you've treated a stream as a seq it will
always behave like one. So this second stream-iter call actually
creates an iter on a stream on that seq.


 Let's be mean again:

 (next! rand-iter nil)
 (take 10 rand-stream)
 (next! rand-iter nil)
 (next! rand-iter nil)
 (take 15 rand-stream)

 All of these work - it seems I have both an iter and a seq on the
 same stream, with the iter returning values that are also in the seq.


No, you've got a generator, a stream on that, a seq on that, a stream
on that seq and an iter on that stream - that's why you are getting
the same values. You'll never have a seq and an iter on the same
generator, i.e. interleaved values.

I understand this may not be intuitive or clear yet from the docs. Nor
am I set in this being the behavior. The case I am looking towards is
this one:

(def s (stream (range 10)))
(if (seq s)
  (take 4 (map-stream inc s))

A stream is used as a seq and then passed to a stream function.
Without this seqed-stream-behaves-as-seq capability, this will fail
with Already iterating, and would have to be written:

(if (seq s)
  (take 4 (map-stream inc (seq s

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
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: Agent as a processing queue

2009-01-22 Thread Timothy Pratley

 (both CPU and IO bound at different stages of processing) so
 it's ideal to have a thread pool to process different tasks in
 parallel, even though they are independent.

If you use the agents, the underlying implementation uses two thread
pools:
(1) static relative to your processors, use send to access it - best
to only use this for cpu hungry threads where you want to maximize
throughput while limiting context switching.
(2) the other grows on demand, use send-off to access it - better
choice if IO blocking is involved, otherwise you have a limited number
of threads not doing much.
As such it might be more convenient if the stages you describe were
treated as separate tasks, so they can be queued on the appropriate
thread pool.

 (That's step one. Step two
 will be spreading that thread pool out over multiple JVMs running on
 different hardware).

Clojure doesn't have any built in distributed features afaik, so you'd
need to develop a custom protocol or use a popular java lib.



--~--~-~--~~~---~--~~
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
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: Streams work

2009-01-22 Thread Konrad Hinsen

On 22.01.2009, at 16:27, Rich Hickey wrote:

 Now it works - fine. But what happened to the seq that now owns the
 stream? Nothing refers to it, so it should be gone.

 No, the stream must refer to it, in order to keep its promise to
 return the same seq every time.

OK.

 Did it perhaps
 liberate the stream, so that I can create an iter again? Let's try:

 (def rand-iter (stream-iter rand-stream))
 (next! rand-iter nil)
 (next! rand-iter nil)

 What you've created an iter on the second time is the seq of the
 stream. Right now, once you've treated a stream as a seq it will
 always behave like one. So this second stream-iter call actually
 creates an iter on a stream on that seq.

Does that mean that calling seq on a stream converts the stream into  
a seq for all practical purposes? That sounds a bit dangerous  
considering that so many operations in Clojure call seq implicitly.  
One can easily have a seq steal a stream and not notice it before  
all memory is used up by the seq.

 I understand this may not be intuitive or clear yet from the docs. Nor
 am I set in this being the behavior. The case I am looking towards is
 this one:

 (def s (stream (range 10)))
 (if (seq s)
   (take 4 (map-stream inc s))

 A stream is used as a seq and then passed to a stream function.
 Without this seqed-stream-behaves-as-seq capability, this will fail
 with Already iterating, and would have to be written:

 (if (seq s)
   (take 4 (map-stream inc (seq s

I think the second is in fact clearer. It seems weird in a largely  
functional context to have an enormous side-effect of calling seq on  
a stream.

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
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-01-22 Thread Stuart Sierra

Hi Frank,
I'd also recommend looking at Restlet http://www.restlet.org/ and
the Java Servlets API.
-Stuart Sierra

On Jan 21, 4:39 pm, Frank ffai...@gmail.com 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
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: very simple javascript source using clojurescript?

2009-01-22 Thread Chouser

On Thu, Jan 22, 2009 at 12:33 AM, Allen Rohner aroh...@gmail.com wrote:

 Chouser, how usable is clojurescript to generate extremely simple
 javascript calls? When creating HTML templates, I find myself using
 ugly string interpolation to generate the .js. I would really love it
 if I could do something like:

 (clojurescript/str (swfobject/embedSWF open-flash-chart.swf
 my_chart, 500, 200, 9.0.0, false, {:data-file /my/data}))

 turns into:

 script type=text/javascript
  swfobject.embedSWF(open-flash-chart.swf, my_chart, 550, 200,
 9.0.0, expressInstall.swf, {data-file:/my/data});
 /script

ClojureScript currently requires a patch to Clojure in order to work
(no breaking changes, though), and so the code is not in the regular
clojure-contrib path.  That said, the API for that example would
currently be:

(require '[clojure.contrib.clojurescript :as cljs])

(cljs/formtojs '(.embedSWF swfobject open-flash-chart.swf
  my_chart 500 200 9.0.0 false {:data-file /my/data}))

There's a couple things to note there.  The most important is that
JavaScript objects don't have packages or static members like Java
objects, so you use the instance-method call format a lot more often
in ClojureScript than in Clojure.

Another thing to note is commas are witespace. :-)

Anyway, the above returns this string (after adding whitespace by hand):

(function __user_fn_571(){
  return ((clojure.JS.resolveVar(swfobject,user)).embedSWF(
open-flash-chart.swf,my_chart,(500),(200),9.0.0,false,
clojure.core.hash_map(clojure.core.keyword(,data-file),/my/data)))
}).apply(null,[])

The most important item to note here is that your {:data-file ...}
map is a Clojure hash-map, not a JavaScript Object.  ClojureScript
doesn't currently do JSON-like translations for you.  And unlike Java,
JavaScript doesn't have any way (that I know of) to provide a custom
object (like hash-map) that provides the same interface as the
builtin collection.

This is the kind of useful, practical, missing feature that probably
still abounds in ClojureScript.  I'm not sure if there'd be a way to
use an existing clojure-to-json lib for this, or if something would
have to be ported.  At least it could be written in ClojureScript
instead of JavaScrtipt!

You can try out ClojureScript and see what works (and likely uncover
bugs) with the browser-based REPL:

http://clojurescript.n01se.net/repl/

I haven't figured out yet why my clojure-created applets sometimes
fail on Mac, so that may not work in a Mac browser.  I've made no
attempt to trim the size of either the applet or the .js code on that
page, so it may take a while to download and get everything started.
But once the applet rectangle has gone blank and the word
ClojureScript is on the page, you can try some expressions:

(alert hi)

(- document .body (.appendChild (.createTextNode document Hello World)))

The most extensive example of ClojureScript code is, perhaps
unsurprisingly, the browser REPL itself:

http://clojurescript.n01se.net/repl/repl.cljs

--Chouser

--~--~-~--~~~---~--~~
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
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: Agent as a processing queue

2009-01-22 Thread Emeka
Tim,

Could you explain atoms the way you explained agents?\

Emeka

--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread David Nolen
http://lispnyc.org/soc2009.clp

Forget most of what I said, it seems the BDFL already has these things in
mind ;)  Enough of types and structs for me, time for me dive into the less
familiar territory of Clojure.
On Thu, Jan 22, 2009 at 12:25 PM, David Nolen dnolen.li...@gmail.comwrote:

 Can't some elements of the problem be solved with some form of predicate
 dispatching as proposed by Meikel?  Predicate dispatching would allows us to
 use _anything_ as a type (i.e. structs themselves), as well as allowing user
 defined functions to do the matching instead of being limited to isa? and
 the global hierarchy.  This of course has some performance implications I
 imagine...

 http://groups.google.com/group/clojure/browse_thread/thread/f8b1be403c927b03/438c21a80072a105?lnk=gstq=hierarchy#438c21a80072a105

 I have to say that I find the lack of a type system around structs to be
 fairly liberating.  You can invent one if you need one, but you are not
 constrained by it.  However, if somebody comes up with something like CLJOS
 as a set of handy macros, or extracts whatever parts they deem relevant, why
 not put that in clojure-contrib so that people can at least have something
 to use for the simple cases as pointed out by Konrad?


 On Thu, Jan 22, 2009 at 10:25 AM, Konrad Hinsen konrad.hin...@laposte.net
  wrote:


 On 22.01.2009, at 15:26, Rich Hickey wrote:

  It's pretty easy to write a trivial struct system, much harder to
  address performance, interop, compilability, dynamicity etc
  constraints.

 Indeed.

  As a simple case, if a defstruct is re-evaluated, will objects created
  after that be of the same 'type' as objects created before?

 I'd say no, which resolves the next question:

  What if fields have been added/removed?

 Anyway, I don't think that re-evaluation is a serious issue, except
 in interactive development sessions. The typical use would be
 defining a struct once and then not touch it any more.

  I'd prefer people experiment with libraries built on the existing
  facilities, with an open mind as to the possibilities of categorizing
  things other than by their structure.

 The added flexibility of multimethods is quite appreciable in non-
 trivial situations. But at the moment there is no simple way to
 handle simple situations. Using structs is straightforward and
 familiar from other languages. It is certainly not *the* solution to
 categorizing, but it's a simple one that is good enough for many
 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
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: Streams work

2009-01-22 Thread Stuart Sierra

On Jan 21, 2:33 pm, Rich Hickey richhic...@gmail.com wrote:
 I've started documenting the streams work I have been doing, for those
 interested:

Cool!  3 questions:

1. Can you feed things into a stream?

2. Could streams be used for I/O?

3. Can streams have clean-up/close code when they are emptied or go
out of scope?

-Stuart Sierra
--~--~-~--~~~---~--~~
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
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: struct question

2009-01-22 Thread Meikel Brandmeyer

Hi,

Am 22.01.2009 um 18:25 schrieb David Nolen:

Can't some elements of the problem be solved with some form of  
predicate dispatching as proposed by Meikel?  Predicate dispatching  
would allows us to use _anything_ as a type (i.e. structs  
themselves), as well as allowing user defined functions to do the  
matching instead of being limited to isa? and the global hierarchy.   
This of course has some performance implications I imagine...


No, Rich mentioned predicate dispatching. :) I barely
wrote a simple patch to allow per def-multi hierarchies.

However I looked at the a paper by Chambers and Chen
on predicate dispatch and it looks a little more involved
than the patch mentioned above. ;)

This is really interesting. Although I think that I didn't
even test the current multimethod system to its limits.

Sincerely
Meikel



smime.p7s
Description: S/MIME cryptographic signature


File, Line Number and Usage Info

2009-01-22 Thread Peter Wolf

Here's a dumb question which has been answered before... but I can't 
find it in the docs.

How does one find out the file and line number upon which a symbol was 
defined?  I want to use it for go-to-defintion in the IntelliJ plugin.

Also, is there any way to find all the code that is referencing a 
symbol?  I need that to implement find-usages, rename and move.

Thanks
Peter

--~--~-~--~~~---~--~~
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
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: File, Line Number and Usage Info

2009-01-22 Thread Chouser

On Thu, Jan 22, 2009 at 1:20 PM, Peter Wolf opus...@gmail.com wrote:

 Here's a dumb question which has been answered before... but I can't
 find it in the docs.

user= (map (meta (var take)) [:file :line])
(core.clj 1434)

Which is to say, the file and line number are stored in the metadata of
the Var.  The namespace, docstring, and other useful tidbits are there
too.

This information is used by the clojure.contrib.repl-utils/source macro:

user= (source take)
(defn take
  Returns a lazy seq of the first n items in coll, or all items if
  there are fewer than n.
  [n coll]
(when (and (pos? n) (seq coll))
  (lazy-cons (first coll) (when ( n 1) (take (dec n) (rest coll))
nil

--Chouser

--~--~-~--~~~---~--~~
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
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: Streams work

2009-01-22 Thread Rich Hickey


On Jan 22, 2009, at 11:17 AM, Konrad Hinsen wrote:


 On 22.01.2009, at 16:27, Rich Hickey wrote:

 Now it works - fine. But what happened to the seq that now owns the
 stream? Nothing refers to it, so it should be gone.

 No, the stream must refer to it, in order to keep its promise to
 return the same seq every time.

 OK.

 Did it perhaps
 liberate the stream, so that I can create an iter again? Let's try:

(def rand-iter (stream-iter rand-stream))
(next! rand-iter nil)
(next! rand-iter nil)

 What you've created an iter on the second time is the seq of the
 stream. Right now, once you've treated a stream as a seq it will
 always behave like one. So this second stream-iter call actually
 creates an iter on a stream on that seq.

 Does that mean that calling seq on a stream converts the stream into
 a seq for all practical purposes? That sounds a bit dangerous
 considering that so many operations in Clojure call seq implicitly.
 One can easily have a seq steal a stream and not notice it before
 all memory is used up by the seq.


Calling seq on a stream yields a seq that will forever own the stream  
- if you think about it a bit, you'll see why that has to be the case.

OTOH, that seq is lazy, so I'm not sure what the memory issue is.

 I understand this may not be intuitive or clear yet from the docs.  
 Nor
 am I set in this being the behavior. The case I am looking towards is
 this one:

 (def s (stream (range 10)))
 (if (seq s)
  (take 4 (map-stream inc s))

 A stream is used as a seq and then passed to a stream function.
 Without this seqed-stream-behaves-as-seq capability, this will fail
 with Already iterating, and would have to be written:

 (if (seq s)
  (take 4 (map-stream inc (seq s

 I think the second is in fact clearer. It seems weird in a largely
 functional context to have an enormous side-effect of calling seq on
 a stream.


Again, I don't see the enormous side effect. Steams form a safe,  
stateful pipeline, you'll generally only call seq on the end of the  
pipe. If you ask for a seq on a stream you are asking for a (lazy)  
reification. That reification and ownership is what makes the pipeline  
safe.

I am working on seq/stream api unification right now,  and we will see  
how often we'll be calling seq fns yet subsequently using as a stream.  
Many of those places where seq is called will now call stream instead  
(e.g. sequence fn entry points), and there may be a non-generator- 
capturing function for determining eos.

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
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: Streams work

2009-01-22 Thread Rich Hickey


On Jan 22, 2009, at 12:36 PM, Stuart Sierra wrote:


 On Jan 21, 2:33 pm, Rich Hickey richhic...@gmail.com wrote:
 I've started documenting the streams work I have been doing, for  
 those
 interested:

 Cool!  3 questions:

 1. Can you feed things into a stream?

Yes, you can put a generator on the end of a queue.



 2. Could streams be used for I/O?


Yes, that's one of the primary use cases.

 3. Can streams have clean-up/close code when they are emptied or go
 out of scope?


I'm addressing the resource cleanup issue more generally in a scope  
mechanism, also present in the streams SVN branch. Still in progress,  
but you can get the gist of it here:

http://paste.lisp.org/display/73838

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



newbie: namespaces and load-file

2009-01-22 Thread Paul Henning

Suppose I have a clojure file called app.clj that contains something
like:

(ns app)
(defn foo [] (println hello))
(defn reader [filename] (load-file filename))

and a file called data that simply contains

(foo)

What I would like to see, from the REPL, is:

user= (load-file app.clj)
user= (app/reader data)
hello

As described, this doesn't work.  load-file looks up symbols in the
current namespace (user in this case), but foo is interned in app.
I found that I could get the behavior I wanted if I changed the
definition of reader to:

(defn reader [filename] (binding [*ns* (the-ns 'app)] (load-file
filename)))

But this has a sort of evil feeling to it.  Is there a better way of
doing this?

Thanks,
Paul

P.S. I know that doing (load-file app.clj) (in-ns 'app) (reader
data) from the REPL works as well, but I don't want to force the
user to switch namespaces.








--~--~-~--~~~---~--~~
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
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: newbie: namespaces and load-file

2009-01-22 Thread Stephen C. Gilardi


On Jan 22, 2009, at 12:46 PM, Paul Henning wrote:


As described, this doesn't work.  load-file looks up symbols in the
current namespace (user in this case), but foo is interned in app.


At some point in this process, Clojure needs to know which foo you're  
talking about. It can't retrieve the var associated with foo without  
knowing which namespace it's in. That determination can either be  
explicit or it can be made via the current namespace (*ns*), but it  
has to be made somehow.



I found that I could get the behavior I wanted if I changed the
definition of reader to:

(defn reader [filename] (binding [*ns* (the-ns 'app)] (load-file
filename)))


That's one way to say that foo is in namespace app.


But this has a sort of evil feeling to it.  Is there a better way of
doing this?


Another way is to use symbols with namespaces in data:

(app/foo)

Another way is to declare within data the namespace in which the  
symbols it contains should be resolved:


(in-ns 'app)
(foo)

One nice feature of loading in Clojure is that any namespace changes  
are reverted at the end of the file. After the repl commands you used  
in your example, the repl namespace will still be user.


--Steve



smime.p7s
Description: S/MIME cryptographic signature


Re: newbie: namespaces and load-file

2009-01-22 Thread Paul Henning

 At some point in this process, Clojure needs to know which foo you're  
 talking about. It can't retrieve the var associated with foo without  
 knowing which namespace it's in. That determination can either be  
 explicit or it can be made via the current namespace (*ns*), but it  
 has to be made somehow.

Years of using C++ namespaces have rotted my brain, but I think the
surprise here was that (load-file) uses the current namespace from
the run-time environment, rather than the compile-time environment.
To my way of thinking, anything appearing beneath the (ns whatever)
should operate in that namespace.

As long as no one cares if I muck with *ns*, I can make it work the
way I want.  Thanks for pointing out that namespaces revert at the end
of a load.  Clearly matches observed behavior, but I hadn't thought
about it before.

Paul
--~--~-~--~~~---~--~~
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
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: File, Line Number and Usage Info

2009-01-22 Thread lpetit

Hello,

Here is how I get an hierarchical data structure of information on ns
in clojure-dev :

The tree has really just 3 levels : one root node representing all ns,
one child node of the root node representing one ns each, one child
node per ns node for ns interned symbols.
Each node is represented as a map, with a simple convention : the
type of the node is at key :key, the children of the node are at
key :children, and are a vector of maps. Other information for the
given node are other keys.

And now the code (that uses (var ..) :

(defn- meta-info [v]
  (reduce (fn [m e] (merge m { (first e) (str (second e)) })) {} (meta
v)))

(defn- var-info [v]
  (merge { :type var :name (str v) } (meta-info v)))

(defn- ns-info [n]
  { :name ((comp str ns-name) n)
:type ns
:children (apply vector (map #(var-info (second %)) (ns-interns
n))) })

(defn namespaces-info []
  { :name namespaces :type namespaces
:children (apply vector (map ns-info (all-ns))) })

HTH,

Regards,

--
Laurent

On 22 jan, 19:20, Peter Wolf opus...@gmail.com wrote:
 Here's a dumb question which has been answered before... but I can't
 find it in the docs.

 How does one find out the file and line number upon which a symbol was
 defined?  I want to use it for go-to-defintion in the IntelliJ plugin.

 Also, is there any way to find all the code that is referencing a
 symbol?  I need that to implement find-usages, rename and move.

 Thanks
 Peter
--~--~-~--~~~---~--~~
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
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 Clojure from Java (again)

2009-01-22 Thread Peter Wolf

This is a rejuvenation of the old calling Java from Clojure thread

I have been looking at the solutions from Mark
/
   1) From a Java application, read a text file containing Clojure code
   and invoke specific functions it defines from Java code.
   2) Compile Clojure code to bytecode and use it from a Java application
   just like any other Java code.

   An example of the first option is provided at
   
http://markmail.org/message/tx23zaxf77b6widh#query:%22calling%20Clojure%22%20%22from%20Java%22+page:1+mid:tx23zaxf77b6widh+state:results.
 

  /   

and Stuart
/
   Here's how I do it:

   import clojure.lang.RT;
   import clojure.lang.Var;
   ...
   RT.loadResourceScript(source/file/on/classpath/here.clj);
   Var myfunction = RT.var(my-namespace, my-function);
   myfunction.invoke(arg 1, arg 2, ...); /


Where is the documentation on this Java API?  In particular, all these 
functions seem to side-effect a single Clojure image.

Can I create several disjoint images?  Can I stop or destroy an image 
that has run amok? 

I want to use this for the IntelliJ plugin, and I don't want bogus user 
code to clobber the IDE.  I also want the defined symbols for a file to 
be a function just of the code in that file, not all the files that 
happen to be loaded by the IDE at the moment.  How does Swank handle this?

Thanks
Peter

--~--~-~--~~~---~--~~
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
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: newbie: namespaces and load-file

2009-01-22 Thread Stephen C. Gilardi


On Jan 22, 2009, at 3:56 PM, Paul Henning wrote:


As long as no one cares if I muck with *ns*, I can make it work [...]


That brings up an important point. The var *ns* may look like a global  
variable in C++, but it's really a dynamic variable--something quite  
a bit safer and more powerful. The value of the var named *ns* is  
not (in the general case) a single piece of data. In the general case  
it's many pieces of data simultaneously. These different values are  
isolated from each other such that at any given time, each piece of  
running code sees only one of them. They are separated by thread--each  
thread has its own stack of values, and by binding depth--the  
effective value at any given point in the thread's runtime is the one  
that's associated with the nearest enclosing call to binding. (This  
may be the value bound at the time binding was called, or it may be  
a value set subsequently with set!.)


When you use in-ns, one of its internal operations is a set! of  
*ns*. For that to succeed, *ns* must have a thread-local binding in  
effect at the time of the set!. Calling in-ns only changes the  
effective namespace in the thread that calls it and only until that  
binding is popped off the stack by the code exiting the binding form.


The overall effect of this is that when you muck with *ns*, only your  
code (and code it calls) will see what you did. That isolation makes a  
Clojure's var much easier to reason about than a global variable would  
be--especially in the case of many threads accessing its value  
concurrently.


Thanks for pointing out that namespaces revert at the end of a  
load.  Clearly matches observed behavior, but I hadn't thought about  
it before.


You're quite welcome.

--Steve



smime.p7s
Description: S/MIME cryptographic signature


Re: Clojure Web Libraries

2009-01-22 Thread Frank

Thanks to everyone for their responses.  I will be looking into all
these libraries.  I wanted to add two other references to this thread
that I will also be researching.  I found two libraries written by
Christophe Grand:

Ring - http://github.com/mmcgrana/ring/tree/master
Enlive - http://github.com/cgrand/enlive/tree/master

Ring is described as Clojure web application library: abstracts HTTP
to allow modular and concise webapps and Enlive is described as a
selector-based (à la CSS) templating system for Clojure.

-Frank

On Jan 22, 11:44 am, Stuart Sierra the.stuart.sie...@gmail.com
wrote:
 Hi Frank,
 I'd also recommend looking at Restlet http://www.restlet.org/ and
 the Java Servlets API.
 -Stuart Sierra

 On Jan 21, 4:39 pm, Frank ffai...@gmail.com 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
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 Clojure from Java (again)

2009-01-22 Thread Michael Reid

On Thu, Jan 22, 2009 at 4:43 PM, Peter Wolf opus...@gmail.com wrote:

 This is a rejuvenation of the old calling Java from Clojure thread

 I have been looking at the solutions from Mark
 /
   1) From a Java application, read a text file containing Clojure code
   and invoke specific functions it defines from Java code.
   2) Compile Clojure code to bytecode and use it from a Java application
   just like any other Java code.

   An example of the first option is provided at

 http://markmail.org/message/tx23zaxf77b6widh#query:%22calling%20Clojure%22%20%22from%20Java%22+page:1+mid:tx23zaxf77b6widh+state:results.

  /

 and Stuart
 /
   Here's how I do it:

   import clojure.lang.RT;
   import clojure.lang.Var;
   ...
   RT.loadResourceScript(source/file/on/classpath/here.clj);
   Var myfunction = RT.var(my-namespace, my-function);
   myfunction.invoke(arg 1, arg 2, ...); /


 Where is the documentation on this Java API?  In particular, all these
 functions seem to side-effect a single Clojure image.

 Can I create several disjoint images?  Can I stop or destroy an image
 that has run amok?

 I want to use this for the IntelliJ plugin, and I don't want bogus user
 code to clobber the IDE.  I also want the defined symbols for a file to
 be a function just of the code in that file, not all the files that
 happen to be loaded by the IDE at the moment.  How does Swank handle this?


Clojure has no notion of an environment. Its environment is the JVM
in which it is running, just like Java.

There was a thread about this awhile back, its long, but it goes over
some the issues I think you're getting at:

  
http://groups.google.com/group/clojure/browse_thread/thread/d98cedb860f16a34/18c930d1c76aa31c

The bottom line is that you can only isolate Clojure within a single
JVM in the same you that you can isolate Java in a single
JVM--ClassLoaders.

The other heavy-weight option is to run multiple JVMs.

I don't think you need to worry about user code hijacking the IntelliJ
IDE--Clojure cannot redefine Java classes which have already been
loaded. It is however possible for Clojure code to clobber previously
compiled Clojure code, so if you are worried about that, then I think
you'll need to look at an isolation mechanism like ClassLoaders or
launching a new JVM.

I don't think Swank really deals with the issue at all. I just checked
and it is entirely possible to re-def swank functions from the Emacs
SLIME repl.

/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
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: File, Line Number and Usage Info

2009-01-22 Thread lpetit

Peter,

A weird thing seems to happen often those days, and I have remarked
it's related to you.

You start a new post, but it appears to be in the continuation of a
previous one, with the subject changed.

This does not look good to me. Are you doing something like this to
start a new post : open the last e-mail received by the ml, click on
reply, change the subject, throw the body out and replace it by my
own ?

If so, then please consider creating a new e-mail each time you start
a new subject ?
If not so, then your mailer may have a problem with googlegroups ?
Regards,

--
Laurent

On 22 jan, 19:20, Peter Wolf opus...@gmail.com wrote:
 Here's a dumb question which has been answered before... but I can't
 find it in the docs.

 How does one find out the file and line number upon which a symbol was
 defined?  I want to use it for go-to-defintion in the IntelliJ plugin.

 Also, is there any way to find all the code that is referencing a
 symbol?  I need that to implement find-usages, rename and move.

 Thanks
 Peter
--~--~-~--~~~---~--~~
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
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-01-22 Thread James Reeves

On Jan 22, 10:15 pm, Frank ffai...@gmail.com wrote:
 I found two libraries written by Christophe Grand:

Only Enlive was written my Christophe; Ring was written by Mark. From
what I gather Ring is an abstraction layer like Rack, and isn't
designed to be used directly to build web applications. Rather, it's a
common interface for frameworks like Weld and Compojure to handle HTTP
requests and responses.

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



function that takes primitives?

2009-01-22 Thread Korny Sietsma

Hi folks,
Is there any way to make a function that takes primitive parameters?
It seems you can't, but I might be missing something.
I have the following code (a start to playing with mandelbrot sets):

(defn step [x0, y0, xn, yn]
  (let [xm (+(-(* xn xn)(* yn yn)) x0)
 ym (+(* 2 xn yn) y0)
 ]
[xm ym]
)
  )

(defn try_to_solve [x0, y0, xn, yn, n, max_n]
  (let [m (+ n 1)
[xm ym] (step x0 y0 xn yn)
zm (+(* xm xm)(* ym ym))
]
(cond
  ( zm 2.0) m
  (= n max_n) [x0, y0, xm, ym, m, max_n]
  true (recur x0, y0, xm, ym, m, max_n)
  )
)
  )

This works fine (it's my first clojure code, so I'm sure there are
things I could do better, but I'm happy with it as a start)
However, I want to do this a lot, so I was trying to coerce the
paramters to primitive doubles.
It seems you can't write:
  (defn step [#^double x0, #^double y0, #^double xn, #^double yn]
and from comments I've seen before, I get the impression if I use type
hinting, clojure will use Doubles and boxing, which is a speed
overhead I don't want.

I get the impression I can rewrite try_to_solve to use a loop/recur,
and then can use primitives - but I can't see any way to make calls to
step use primitives, short of inlining the function...

- Korny
-- 
Kornelis Sietsma  korny at my surname dot com

--~--~-~--~~~---~--~~
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
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: File, Line Number and Usage Info

2009-01-22 Thread Peter Wolf

Ooops!  How embarrassing :-(

Yes, that's exactly what I am doing.  It did not occur to me that there 
is extra information embedded in the reply that marks it as being part 
of a thread.

Sorry, won't happen again
P

lpetit wrote:
 Peter,

 A weird thing seems to happen often those days, and I have remarked
 it's related to you.

 You start a new post, but it appears to be in the continuation of a
 previous one, with the subject changed.

 This does not look good to me. Are you doing something like this to
 start a new post : open the last e-mail received by the ml, click on
 reply, change the subject, throw the body out and replace it by my
 own ?

 If so, then please consider creating a new e-mail each time you start
 a new subject ?
 If not so, then your mailer may have a problem with googlegroups ?
 Regards,

 --
 Laurent

 On 22 jan, 19:20, Peter Wolf opus...@gmail.com wrote:
   
 Here's a dumb question which has been answered before... but I can't
 find it in the docs.

 How does one find out the file and line number upon which a symbol was
 defined?  I want to use it for go-to-defintion in the IntelliJ plugin.

 Also, is there any way to find all the code that is referencing a
 symbol?  I need that to implement find-usages, rename and move.

 Thanks
 Peter
 
 

   


--~--~-~--~~~---~--~~
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
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 Clojure from Java (again)

2009-01-22 Thread Peter Wolf

Thanks for the lengthy reply Laurent,  Replies in-line

lpetit wrote:
 Peter,

 We asked us the same question some weeks ago, on clojuredev.

 We took the path to follow how eclipse launches a java application
 when the user requires it to test it.
 So we created a customized launch configuration (sorry, eclipse
 jargon), that is just a classical eclipse java launcher with some
 options predefined.
   
Yes, this is exactly what I do also, and it is even called a 
configuration in IntelliJ
 To enable the user work against the clojure version he wants, we
 require him to have clojure library as a standard library dependency
 on the classpath of his eclipse project.

 I think you could do quite the same thing for IntelliJ.

 We did that because of several reasons :

 - we wanted the user to be able use his own version of clojure, not an
 imposed one
 - we wanted the user to be able to have several clojures running at
 the same time
 - we absolutely wanted to prevent the user run his code in the eclipse
 VM !
 - we wanted regular eclipse users to feel at home with clojuredev,
 having in mind that having a smooth migration path from java to
 clojure, first by just incorporating bits of clojure in a (n already
 existing) java project codebase, could be a good thing.
   
Yep.  Same solution, same reasons.
 So we took the road you described by quoting Stuart. We call a bridge
 function that takes strings and returns strings (or core clojure
 datastructures : maps, vectors, strings, keys, java.lang basic types).

 This bridge function runs on the eclipse JVM, and calls a server we
 systematically install in the remote JVM when the user launches his
 project.

 The code for the client part is here :
 http://code.google.com/p/clojure-dev/source/browse/clojuredev/trunk/src/clojuredev/debug/clientrepl.clj
 The code for the server part is here :
 http://code.google.com/p/clojure-dev/source/browse/clojuredev/trunk/src/clojuredev/debug/serverrepl.clj
 (and yes, it's yet another variation on the repl over socket)

   
Thanks, I shall take a look at this.

However, if there is only one Clojure image used for references and the 
like, what happens if someone calls an infinite loop, or infinite 
recursion, in a file.  Does the Clojure server hang/blow up?  How do you 
detect it/protect from it?

For example, I was using the SmallSnake code for testing, and when that 
file is loaded, it pops up a window and runs a process forever.  I don't 
want that to happen, just because someone included that file in their 
IntelliJ project.

This must be a problem common to all Swank based IDEs.  What is the 
Clojure way here?

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



what when (some identity maps) mean?

2009-01-22 Thread wubbie

Hi,

Here is def of merge:

(defn merge

  [ maps]
  (when (some identity maps)
(reduce #(conj (or %1 {}) %2) maps)))

How can I interpret  when (some identity maps)?

Thanks
-sun

--~--~-~--~~~---~--~~
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
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: Agent as a processing queue

2009-01-22 Thread e
wow.  I wonder if I could use this for the quicksort I was talking about.  I
would need to have the function being added as a job be able to add it's own
jobs recursively . . .  .and kill jobs when they are done.  But do you have
to sleep, or is there a way to join the children when they are done?  And is
there a way to throttle the total number of agents?  I'm lazy, so if this is
something I should be reading about on my own, I totally understand.  I'm
wondering if this post is enough of a clue to get started is all.

So any frame in the stack is responsible for taking any sequence of at least
one element and:
1) first element is the pivot.
2) if there are elements less than pivot, make a job to quicksort them when
there is an available agent.
3) fire off a quicksort for stuff greater than pivot when there is an
available agent.
4) join back with the two child tasks and grab their now sorted subsequences
5) kill the child jobs
6) glue the subsequences with the pivot in the middle
7) return to the parent code

At first, there will only be one thread for the first pass, but the number
will grow as subtasks fire sub-sub tasks.  I am sure this is a silly way to
sort because the threadspawning time is so much longer than the filtering
time, but it's just an exercise.

Is that example (provided in the link) enough knowledge to get started on
this?

Thanks.

On Thu, Jan 22, 2009 at 2:39 AM, Timothy Pratley
timothyprat...@gmail.comwrote:


 Hi Greg

 Here is a proof of concept of one approach you could take:
 http://groups.google.com/group/clojure/web/job-queue.clj

 A set of agents are maintained to represent computation jobs. When the
 results are gathered, the agent is thrown away. I think using multiple
 agents in this way could be quite convenient as it means the jobs can
 be done in parallel.

 If you run the script from the command line you should get something
 like this:
 C:\javaclj job-queue.clj
 (4 3)
 (0 nil Hi mum)
 Which are the results of multiple queued computations taken at two
 subsequent points in time.

 From your post it wasn't clear to me if your 'events' imply sequential
 processing (which could be achieved with a single agent).


 Regards,
 Tim.

 


--~--~-~--~~~---~--~~
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
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: what when (some identity maps) mean?

2009-01-22 Thread Stuart Sierra

Hi,

It means that some of the maps can be nil, but at least one of them
has to be non-nil. some requires a predicate, but since nil is
logical false, we can just use identity.  Here's the behavior:

user (merge nil nil nil)
nil
user (merge {:a 1} nil {:b 2})
{:b 2, :a 1}

-Stuart Sierra


On Jan 22, 7:16 pm, wubbie sunj...@gmail.com wrote:
 Hi,

 Here is def of merge:

 (defn merge

   [ maps]
   (when (some identity maps)
     (reduce #(conj (or %1 {}) %2) maps)))

 How can I interpret  when (some identity maps)?

 Thanks
 -sun
--~--~-~--~~~---~--~~
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
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 Clojure from Java (again)

2009-01-22 Thread Stuart Sierra

On Jan 22, 6:51 pm, Peter Wolf opus...@gmail.com wrote:
 However, if there is only one Clojure image used for references and the
 like, what happens if someone calls an infinite loop, or infinite
 recursion, in a file.  Does the Clojure server hang/blow up?  

If you code an infinite loop, the SWANK server will run an infinite
loop. The only solution is to kill off the Java process. If you wanted
to get clever, you could load the file in a separate thread and just
kill off that thread.

 For example, I was using the SmallSnake code for testing, and when that
 file is loaded, it pops up a window and runs a process forever.  

 That's an unfortunate side effect of using Clojure as a scripting
language like Perl or Python. Perhaps it would be more proper for the
distributed file to define a function that will run the application.

-Stuart Sierra
--~--~-~--~~~---~--~~
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
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: Streams work

2009-01-22 Thread evins.mi...@gmail.com



On Jan 21, 1:33 pm, Rich Hickey richhic...@gmail.com wrote:
 I've started documenting the streams work I have been doing, for those
 interested:

 http://clojure.org/streams

 Feedback welcome,

 Rich

This work reminds me in a general way of the old Dylan iteration
protocol. They're not the same, and the Dylan iteration protocol does
not provide the safety for concurrency that you're working on. Still,
just in case any of the old ideas happen to be useful, I thought I'd
provide a link:

http://amigos.rdsathene.org/other/prefix-dylan/book.annotated/ch12.html#iteration%20protocol0

(this link is to a webbed version of the 1992 lisp-syntax version of
Dylan. the manual is getting increasingly hard to find online.)
--~--~-~--~~~---~--~~
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
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: Inheritance multiple inheritance using structs

2009-01-22 Thread evins.mi...@gmail.com



On Jan 19, 12:38 am, David Nolen dnolen.li...@gmail.com wrote:
 Of course it might be the case that not many people are interested in the
 implementing ideas from CLOS for Clojure

It's definitely interesting. I'd like to have eql specializers and the
ability to build hierarchies of arbitrary types (e.g. a hierarchy of
strings for one particular application I'm working on), so any hacking
around with CLOS-like dispatching and specializers is interesting to
me.



--~--~-~--~~~---~--~~
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
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: Agent as a processing queue

2009-01-22 Thread Mark H.

On Jan 22, 4:24 pm, e evier...@gmail.com wrote:
 At first, there will only be one thread for the first pass, but the number
 will grow as subtasks fire sub-sub tasks.  I am sure this is a silly way to
 sort because the threadspawning time is so much longer than the filtering
 time, but it's just an exercise.

It's also not so efficient because in Quicksort, the pivot isn't
always in the middle of the current subarray.  That means different
agents will probably get different array sizes and thus you will lose
performance through load imbalance.  Parallel Quicksort can only be
made efficient if the language supports efficient nested parallelism.

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



Any way we can get this in clojure-contrib?

2009-01-22 Thread Matt Moriarity

Under the suggestion of some people in the #clojure channel, I started
working on a date library for Clojure since the built-in Java one is
kind of a mess. It's not totally complete, but I think it could be
quite useful. It supports getting the current date and time, and
creating dates based on input. It also has excellent date formatting
and parsing support, which allows users do define they're own custom
date formats as well as using the built-in java ones.

The code is here: http://gist.github.com/49656

I was wondering if this could get added to clojure-contrib. I'm not
really sure how things work for the project, but I figured this would
be the best place to ask. Dates are a pretty basic data structure, so
I think many would benefit from having 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
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: Any way we can get this in clojure-contrib?

2009-01-22 Thread Matt Moriarity

By the way, I'm in the process of sending in my contributor agreement.
Just so you know :)
--~--~-~--~~~---~--~~
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
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: Inheritance multiple inheritance using structs

2009-01-22 Thread aria42

[sorry for duplicating content from the email i sent you David]

Would anyone be interested in simplifying some of the boilerplate for
defining methods in clojs? Currently you have to do this,

(defclass circle [shape]
  (:radius 10))
(defmulti area :tag)
(defmethod area ::circle [this] (* (:radius this) (:radius this) (Math/
PI)))

But it seems like 99% of the time this is boilerplate b/c you want
multi-methods to dispatch on :tag, so we should maybe have a shortcut
to let us do this...

(defclass circle [shape]
  (:radius 10)
  (defmethod area [] (* :radius :radius Math/PI)))

I'm not a macro-wiz but it must be possible to alter that defmethod to
check if it's defined and to wrap the symbol refrences with (:symbol
this) and cons this to the argument list.

Just a thought, Aria

On Jan 22, 7:55 pm, evins.mi...@gmail.com evins.mi...@gmail.com
wrote:
 On Jan 19, 12:38 am, David Nolen dnolen.li...@gmail.com wrote:

  Of course it might be the case that not many people are interested in the
  implementing ideas from CLOS for Clojure

 It's definitely interesting. I'd like to have eql specializers and the
 ability to build hierarchies of arbitrary types (e.g. a hierarchy of
 strings for one particular application I'm working on), so any hacking
 around with CLOS-like dispatching and specializers is interesting to
 me.
--~--~-~--~~~---~--~~
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
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: Any way we can get this in clojure-contrib?

2009-01-22 Thread Nick Vogel
That sounds interesting; you might take a look at Joda
Timehttp://joda-time.sourceforge.net/.
Although I've never used it myself, from what I've heard it's the Java
library that people actually use for dates/times (I do know that Google uses
it).  Doing a quick search, it looks like Mark McGranaghan is working on a
Clojure wrapper for Joda Time here
http://github.com/mmcgrana/clj-garden/tree/master under clj-time.

On Thu, Jan 22, 2009 at 11:51 PM, Matt Moriarity
matt.moriar...@gmail.comwrote:


 By the way, I'm in the process of sending in my contributor agreement.
 Just so you know :)
 


--~--~-~--~~~---~--~~
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
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: Any way we can get this in clojure-contrib?

2009-01-22 Thread Matt Moriarity

We discussed Joda Time, but it was decided that it wasn't a good idea
to add another dependency, since this is something so integral to the
language. I don't know what other people think, though. This was just
an informal decision on #clojure.

On Jan 23, 12:05 am, Nick Vogel voge...@gmail.com wrote:
 That sounds interesting; you might take a look at Joda
 Timehttp://joda-time.sourceforge.net/.
 Although I've never used it myself, from what I've heard it's the Java
 library that people actually use for dates/times (I do know that Google uses
 it).  Doing a quick search, it looks like Mark McGranaghan is working on a
 Clojure wrapper for Joda Time 
 herehttp://github.com/mmcgrana/clj-garden/tree/masterunder clj-time.

 On Thu, Jan 22, 2009 at 11:51 PM, Matt Moriarity
 matt.moriar...@gmail.comwrote:



  By the way, I'm in the process of sending in my contributor agreement.
  Just so you know :)
--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



updated pdf of clojure manual?

2009-01-22 Thread Korny Sietsma

Hi folks;
Is there any way to get an updated dump of clojure.org as a pdf file?
I like to print out stuff and read it on the train, and the
clojure_manual.pdf available on the google groups site is a tad old,
good for an introduction, but I'd like to read the bleeding edge stuff
off-line.

- Korny
-- 
Kornelis Sietsma  korny at my surname dot com

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