Re: Patch: callable defstruct (PersistentStructMap$Def extends AFn)

2008-11-06 Thread Parth Malwankar



On Nov 6, 9:19 am, Chouser [EMAIL PROTECTED] wrote:
 On Wed, Nov 5, 2008 at 12:10 AM, Chouser [EMAIL PROTECTED] wrote:
   The attached patch allows:

  user= (point 42 11)
  {:x 42, :y 11}


Seems like a very nice enhancement to me. It would make
the code more terse.

Parth


 The right tool for the job makes all the difference.  Attached is a
 much simpler patch to accomplish the same thing.

 --Chouser

  structmap-def-extends-restfn.patch
 1KViewDownload
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



sort with custom comparator

2008-11-06 Thread [EMAIL PROTECTED]

The doc of sort states that you need to implement
java.util.Comparator in order to use custom sorting. Why then does
this not cause any error?

user= (defn my-comp [x y] (cond ( x y) 1 (= x y) 0 :else -1))
#=(var user/my-comp)
user= (sort [5 3 1 2])
(1 2 3 5)
user= (sort my-comp [5 3 1 2])
(5 3 2 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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: sort with custom comparator

2008-11-06 Thread [EMAIL PROTECTED]

To answer my own question - AFn.java implements java.util.Comparator.

On Nov 6, 10:18 am, [EMAIL PROTECTED] [EMAIL PROTECTED]
wrote:
 The doc of sort states that you need to implement
 java.util.Comparator in order to use custom sorting. Why then does
 this not cause any error?

 user= (defn my-comp [x y] (cond ( x y) 1 (= x y) 0 :else -1))
 #=(var user/my-comp)
 user= (sort [5 3 1 2])
 (1 2 3 5)
 user= (sort my-comp [5 3 1 2])
 (5 3 2 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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: A trivial question about type and class

2008-11-06 Thread Chanwoo Yoo

Thanks~ clojure.lang.PersistentHashMap works~ :) But I feel
something is strange.. See next code, especially arrowed line.

user clojure.lang.PersistentHashMap
#=clojure.lang.PersistentHashMap
user (= (class {:a 1 :b 2}) clojure.lang.PersistentHashMap)
true
user (= (class {}) clojure.lang.PersistentHashMap)
true
user (= (class {:a 1 :b 2}) (class {}))
true
user (= (class {:a 1}) (class {}))  ;; =
false
user (= (class {:a 1}) clojure.lang.PersistentHashMap)  ;; =
false
user (= (class (hash-map :a 1)) clojure.lang.PersistentHashMap)
true
user (= (class (hash-map :a 1)) (class {:a 1})) ;; =
false
user (:a {:a 1})
1

Is {:a 1} not a hash-map? It seems that there is some inconsistency...

On 11월6일, 오후4시27분, Michael Wood [EMAIL PROTECTED] wrote:
 On Thu, Nov 6, 2008 at 8:25 AM, Chanwoo Yoo [EMAIL PROTECTED] wrote:

  Hi all. In Stuart's book - Programming Clojure, there is a multi
  method like following:

  (defmulti blank? class)
  (defmethod blank? String [s] (every? #{\space} s))
  (defmethod blank? nil [_] true)

  After reading the method, I was curious about type or class of native
  data structures of Clojure. So I typed next code in slime. Hmm.. I
  didn't understand why classes of {:a 1} and {} are not same. Like
  Stuart's code, to make multi method branching based on clojure data
  structure type(map, vector, list), what symbol should I use? (Like
  String for string, Is there a Map for {:a 1}? I tried
  PersistentHashMap, HashMap, Map, so on.. I didn't find it.)

 I think what you're looking for is clojure.lang.PersistentHashMap
 instead of just PersistentHashMap.

 user= String
 java.lang.String
 user= PersistentHashMap
 java.lang.Exception: Unable to resolve symbol: PersistentHashMap in this 
 context
 [...]
 user= clojure.lang.PersistentHashMap
 clojure.lang.PersistentHashMap
 user=

 I don't know much about Clojure, though, so I suspect there is better
 advice than the above :)

  user (= (class abc) String)
  true
  user (class {:a 1 :b 2})
  #=clojure.lang.PersistentHashMap
  user (class {})
  #=clojure.lang.PersistentHashMap
  user (= (class {:a 1}) (class {}))
  false
  user (= (class {:a 1}) (class {:b 2}))
  true

 That seems rather strange to me too.

 --
 Michael Wood [EMAIL PROTECTED]
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: A trivial question about type and class

2008-11-06 Thread mb

Hi,

On 6 Nov., 13:30, Chanwoo Yoo [EMAIL PROTECTED] wrote:
  Is {:a 1} not a hash-map? It seems that there is some inconsistency...

Clojure holds promises about the interface and the performance
characteristics of the provided functions. In general Clojure is
a lot about abstract interfaces. The underlying thing may change
as necessary to provide the best implementation for the specific
case.

An array map may be good for maps with a very small number of
entries, but inappropriate for maps with a big number of entries.
Since Clojure only promises the interface, it's free to decide
that assoc should now return a converted map for performance
reasons.

At least this is the impression I got from Rich's talk at - I think -
the Boston Lisp Group. I think he mentioned something like this.
Please correct me if I'm wrong.

Sincerely
Meikel


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: sort with custom comparator

2008-11-06 Thread Rich Hickey


On Nov 6, 2008, at 7:05 AM, [EMAIL PROTECTED] wrote:


 On Nov 6, 12:43 pm, Rich Hickey [EMAIL PROTECTED] wrote:
 On Nov 6, 5:23 am, [EMAIL PROTECTED] [EMAIL PROTECTED]
 wrote:

 To answer my own question - AFn.java implements  
 java.util.Comparator.

 That is documented here:

 http://clojure.org/special_forms

 IFns implement the Java Callable, Runnable and Comparator
 interfaces.

 Pedantically speaking IFn extends Callable and Runnable, and AFn
 implements IFn and additionally Comparator (and Serializable). I was
 checking IFn.java first but couldn't see the Comparator interface
 being listed there which made me writing my initial post. Now reading
 the sentence above I wonder if it counts as a bug that IFn doesn't
 extend from Comparator?


It's a documentation bug - it should say fns and not IFns, and now does.

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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: sort with custom comparator

2008-11-06 Thread Chouser

On Thu, Nov 6, 2008 at 7:05 AM, [EMAIL PROTECTED]
[EMAIL PROTECTED] wrote:

 I was checking IFn.java first but couldn't see the Comparator
 interface being listed there which made me writing my initial post.

This is a more convenient and reliable way to check inheritance:

(ancestors (class #()))

Cleaned up output:

#{#=clojure.lang.AFn
  #=clojure.lang.IFn
  #=clojure.lang.IObj
  #=clojure.lang.Obj
  #=java.io.Serializable
  #=java.lang.Object
  #=java.lang.Runnable
  #=java.util.Comparator
  #=java.util.concurrent.Callable}

--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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: prefer-method print-method problem

2008-11-06 Thread Chouser

On Thu, Nov 6, 2008 at 7:53 AM, MikeM [EMAIL PROTECTED] wrote:

  But when I try to prefer this:

 (prefer-method print-method clojure.lang.PersistentTreeMap
 clojure.lang.IPersistentMap)

You don't need this, because PersistentTreeMap is already a more
specific type than IPersistentMap -- you get the right behavior by
default:

user= (sorted-map 1 2 3 4 5 6)
#=(sorted-map 1 2,3 4,5 6)

That still doesn't get read in right, and I'm not sure why.  But it
seems to be printing ok.

--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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: A trivial question about type and class

2008-11-06 Thread Chanwoo Yoo

I really appreciate your answer... and exciting 'Clojure', 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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: A trivial question about type and class

2008-11-06 Thread hoeck



On Nov 6, 8:27 am, Michael Wood [EMAIL PROTECTED] wrote:
 On Thu, Nov 6, 2008 at 8:25 AM, Chanwoo Yoo [EMAIL PROTECTED] wrote:

  Hi all. In Stuart's book - Programming Clojure, there is a multi
  method like following:

  (defmulti blank? class)
  (defmethod blank? String [s] (every? #{\space} s))
  (defmethod blank? nil [_] true)

  After reading the method, I was curious about type or class of native
  data structures of Clojure. So I typed next code in slime. Hmm.. I
  didn't understand why classes of {:a 1} and {} are not same. Like
  Stuart's code, to make multi method branching based on clojure data
  structure type(map, vector, list), what symbol should I use? (Like
  String for string, Is there a Map for {:a 1}? I tried
  PersistentHashMap, HashMap, Map, so on.. I didn't find it.)

 I think what you're looking for is clojure.lang.PersistentHashMap
 instead of just PersistentHashMap.

 user= String
 java.lang.String
 user= PersistentHashMap
 java.lang.Exception: Unable to resolve symbol: PersistentHashMap in this 
 context
 [...]
 user= clojure.lang.PersistentHashMap
 clojure.lang.PersistentHashMap
 user=

 I don't know much about Clojure, though, so I suspect there is better
 advice than the above :)

  user (= (class abc) String)
  true
  user (class {:a 1 :b 2})
  #=clojure.lang.PersistentHashMap
  user (class {})
  #=clojure.lang.PersistentHashMap
  user (= (class {:a 1}) (class {}))
  false
  user (= (class {:a 1}) (class {:b 2}))
  true

 That seems rather strange to me too.

 --
 Michael Wood [EMAIL PROTECTED]



On Nov 6, 8:27 am, Michael Wood [EMAIL PROTECTED] wrote:
 On Thu, Nov 6, 2008 at 8:25 AM, Chanwoo Yoo [EMAIL PROTECTED] wrote:

  Hi all. In Stuart's book - Programming Clojure, there is a multi
  method like following:

  (defmulti blank? class)
  (defmethod blank? String [s] (every? #{\space} s))
  (defmethod blank? nil [_] true)

  After reading the method, I was curious about type or class of native
  data structures of Clojure. So I typed next code in slime. Hmm.. I
  didn't understand why classes of {:a 1} and {} are not same. Like
  Stuart's code, to make multi method branching based on clojure data
  structure type(map, vector, list), what symbol should I use? (Like
  String for string, Is there a Map for {:a 1}? I tried
  PersistentHashMap, HashMap, Map, so on.. I didn't find it.)

 I think what you're looking for is clojure.lang.PersistentHashMap
 instead of just PersistentHashMap.

 user= String
 java.lang.String
 user= PersistentHashMap
 java.lang.Exception: Unable to resolve symbol: PersistentHashMap in this 
 context
 [...]
 user= clojure.lang.PersistentHashMap
 clojure.lang.PersistentHashMap
 user=

 I don't know much about Clojure, though, so I suspect there is better
 advice than the above :)

If you are just playing or if the class is only used once in your file/
namespace then this is absolutely okay (clojure does this in
boot.clj) :).
Or you type (import '(clojure.lang PersistentHasMap)),
or (ns my-namespace (:import (clojure.lang PersistentHashMap))) on top
of your file.

  user (= (class abc) String)
  true
  user (class {:a 1 :b 2})
  #=clojure.lang.PersistentHashMap
  user (class {})
  #=clojure.lang.PersistentHashMap
  user (= (class {:a 1}) (class {}))
  false
  user (= (class {:a 1}) (class {:b 2}))
  true

 That seems rather strange to me too.

This is a reader optimization. For very short hashmaps (currently 1
element), the clojure reader uses a clojure.lang.PersistentArrayMap
instead of a full fledged HashMap. The reader does this because he
knows that this map ({:a 1}) will only be constructed with one
MapEntry.

user (= (class (into {} '([:a 1]))) (class {}))
true
Here the reader doesn't see any literal maps and (into {} '([:a 1]))
evals to a PersistentHashMap with one MapEntry.

Multimethods use the isa? function for dispatch, so to dispatch on a
Map type in general, one would use a java.util.Map or a
clojure.lang.IPersistentMap as the dispatch-value.

user (and (isa? (class {}) java.util.Map) (isa? (class {:a 1})
java.util.Map))
true

There is also a similar optimization for clojure vectors. They are
constructed as c.l.LazilyPersistentVector which is basically a wrapper
arround a java array. Once you conj onto them, they turn into a
c.l.PersistentVector.

user (let [v [1 2]] [(class v) (class (conj v 3))])
[#=clojure.lang.LazilyPersistentVector
#=clojure.lang.PersistentVector]

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



prefer-method print-method problem

2008-11-06 Thread MikeM

I would like to print sorted maps readably (otherwise my sorted maps
when printed and read back get turned into the default map), so I
tried this:

(defmethod print-method clojure.lang.PersistentTreeMap [o,
#^java.io.Writer w]
   (let [eprint (fn eprint [e sep?] (do (print-method (key e) w)
(.write w  )
(print-method (val e) w)
(if sep? (.write w ,) )))]
  (.write w (if *print-readably* #=(sorted-map  {))
  (loop [s (seq o)]
 (if (rest s)
   (do (eprint (first s) true) (recur (rest s)))
   (eprint (first s) nil)))
  (.write w (if *print-readably* ) }

 But when I try to prefer this:

(prefer-method print-method clojure.lang.PersistentTreeMap
clojure.lang.IPersistentMap)

I get an exception because clojure.lang.IPersistentMap is already
preferred to clojure.lang.PersistentTreeMap.

Questions:

Where does the preference for IPersistentMap come from? Is it from the
following in boot.clj:
 (prefer-method print-method clojure.lang.IPersistentMap
java.util.Map)
since PersistentTreeMap is a java.util.Map?
Is there a work-around to allow what I'm trying to do?
Can MultiFn be changed to allow inspection of the preferTable? I'm
thinking something like (get-prefers multifn) which would return the
preferTable to help with diagnosing problems such as the above.

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: A trivial question about type and class

2008-11-06 Thread Chanwoo Yoo

Aha, I'm sorry for my laziness and spamming. {:a 1} is not a hash-map.
I guess there is some reason of performance about this... Anyway, as
mac pointed out, dispatching based on types will be inappropriate to
clojure data structures. Thank you mac for the thread link~

user (class {:a 1})
#=clojure.lang.PersistentArrayMap

On 11월6일, 오후9시22분, Chanwoo Yoo [EMAIL PROTECTED] wrote:
 Thanks~ clojure.lang.PersistentHashMap works~ :) But I feel
 something is strange.. See next code, especially arrowed line.

 user clojure.lang.PersistentHashMap
 #=clojure.lang.PersistentHashMap
 user (= (class {:a 1 :b 2}) clojure.lang.PersistentHashMap)
 true
 user (= (class {}) clojure.lang.PersistentHashMap)
 true
 user (= (class {:a 1 :b 2}) (class {}))
 true
 user (= (class {:a 1}) (class {}))  ;; =
 false
 user (= (class {:a 1}) clojure.lang.PersistentHashMap)  ;; =
 false
 user (= (class (hash-map :a 1)) clojure.lang.PersistentHashMap)
 true
 user (= (class (hash-map :a 1)) (class {:a 1})) ;; =
 false
 user (:a {:a 1})
 1

 Is {:a 1} not a hash-map? It seems that there is some inconsistency...

 On 11월6일, 오후4시27분, Michael Wood [EMAIL PROTECTED] wrote:

  On Thu, Nov 6, 2008 at 8:25 AM, Chanwoo Yoo [EMAIL PROTECTED] wrote:

   Hi all. In Stuart's book - Programming Clojure, there is a multi
   method like following:

   (defmulti blank? class)
   (defmethod blank? String [s] (every? #{\space} s))
   (defmethod blank? nil [_] true)

   After reading the method, I was curious about type or class of native
   data structures of Clojure. So I typed next code in slime. Hmm.. I
   didn't understand why classes of {:a 1} and {} are not same. Like
   Stuart's code, to make multi method branching based on clojure data
   structure type(map, vector, list), what symbol should I use? (Like
   String for string, Is there a Map for {:a 1}? I tried
   PersistentHashMap, HashMap, Map, so on.. I didn't find it.)

  I think what you're looking for is clojure.lang.PersistentHashMap
  instead of just PersistentHashMap.

  user= String
  java.lang.String
  user= PersistentHashMap
  java.lang.Exception: Unable to resolve symbol: PersistentHashMap in this 
  context
  [...]
  user= clojure.lang.PersistentHashMap
  clojure.lang.PersistentHashMap
  user=

  I don't know much about Clojure, though, so I suspect there is better
  advice than the above :)

   user (= (class abc) String)
   true
   user (class {:a 1 :b 2})
   #=clojure.lang.PersistentHashMap
   user (class {})
   #=clojure.lang.PersistentHashMap
   user (= (class {:a 1}) (class {}))
   false
   user (= (class {:a 1}) (class {:b 2}))
   true

  That seems rather strange to me too.

  --
  Michael Wood [EMAIL PROTECTED]
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: A trivial question about type and class

2008-11-06 Thread Rich Hickey



On Nov 6, 7:50 am, mb [EMAIL PROTECTED] wrote:
 Hi,

 On 6 Nov., 13:30, Chanwoo Yoo [EMAIL PROTECTED] wrote:

   Is {:a 1} not a hash-map? It seems that there is some inconsistency...

 Clojure holds promises about the interface and the performance
 characteristics of the provided functions. In general Clojure is
 a lot about abstract interfaces. The underlying thing may change
 as necessary to provide the best implementation for the specific
 case.

 An array map may be good for maps with a very small number of
 entries, but inappropriate for maps with a big number of entries.
 Since Clojure only promises the interface, it's free to decide
 that assoc should now return a converted map for performance
 reasons.

 At least this is the impression I got from Rich's talk at - I think -
 the Boston Lisp Group. I think he mentioned something like this.
 Please correct me if I'm wrong.


You are right - this is the correct answer to the question.

Clojure is about programming to abstractions, among other things. So
you don't want to rely on the exact concrete types of things, but
rather the interfaces they implement.

There are many useful interfaces in Clojure. Chouser put together a
nice visualization:

http://clojure.googlegroups.com/web/chart.png

If you use class as a dispatch function in a multimethod, you can use
an interface, like IPersistentMap, as a dispatch value and it will
match all classes that extend IPersistentMap, since multimethod
dispatch uses isa?

There are also predicates that correspond to most of the interfaces,
like map?, list?, vector?, sorted? etc, all of which internally use
(instance? someInterface x). The aforementioned chart includes the
corresponding predicates.

In general, it is bad style to use class equality, as in (= (class
this) (class that)) - better to use instance? or isa?.

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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: sort with custom comparator

2008-11-06 Thread Rich Hickey



On Nov 6, 5:23 am, [EMAIL PROTECTED] [EMAIL PROTECTED]
wrote:
 To answer my own question - AFn.java implements java.util.Comparator.


That is documented here:

http://clojure.org/special_forms

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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: prefer-method print-method problem

2008-11-06 Thread Chouser

On Thu, Nov 6, 2008 at 10:01 AM, MikeM [EMAIL PROTECTED] wrote:

 I can reproduce what you did in a fresh local REPL (SVN 1075), but my
 server (also at SVN 1075) doesn't do this. I'm trying to find out how
 this can be. Any idea where I can find the code that generates the
 #=(sorted-map ... printing? I've looked but can't find it in
 boot.clj.

Now *I'm* confused. It's your code that's printing #=(sorted-map ...
for me, without any call to prefer-method required.

--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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: prefer-method print-method problem

2008-11-06 Thread MikeM



 Now *I'm* confused. It's your code that's printing #=(sorted-map ...
 for me, without any call to prefer-method required.

 --Chouser

Well, you're not the only one confused. I thought the #=(sorted-
map ... came from boot.clj somehow, but I now realize my local REPL
pulled in user.clj, where I had the print-method defined. I
periodically forget that user.clj is read automatically.

Sorry for being dense, and thanks again.
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: jEdit Mode for Clojure

2008-11-06 Thread tkosan

Daniel wrote

 Mostly for amusement, I created a jEdit mode for Clojure a while
 back.  I don't get a chance to play with Clojure all that much, so it
 hasn't been heavily tested (go-to *is* a Clojure keyword,
 right?).  ;-)  It's primarily based upon the Vim mode in terms of what
 keywords it supports and how.  Auto-indentation was something I looked
 at, but it isn't something I actually bothered to support due to time
 constraints (jEdit is capable of some pretty slick auto-indenting
 where Lisp-like languages are concerned).

This is good timing for me.  I am in the process of integrating
clojure into a jEdit-based Mathematics Computing Environment I am
creating called MathRider:

   http://mathrider.org

MathRider currently includes clojure but syntax highlighting is not
complete yet.  I will look at your jEdit mode to see if it is more
functional than what MathRider is currently using.  If you have time
to add auto-indentation, that would be great.

If anyone wants to experiment with clojure in MathRider, there is a
file called clojure_examples.mrw in the mathrider/examples
directory.

Ted Kosan

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Bug in genclass?

2008-11-06 Thread Michael Reid

Hi,

I am getting the following error trying to extend java.lang.Exception
in the latest revision of Clojure:

user=(defmacro defexception [name]
  `(try
(gen-and-load-class (quote ~name) :extends Exception)
(catch java.lang.LinkageError le#
 (. le# (printStackTrace)

user= (defexception my.Exception)
java.lang.ClassFormatError: JVMCFRE114 field name is invalid;
class=my/Exception, offset=0
at java.lang.ClassLoader.defineClassImpl(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:265)
at java.lang.ClassLoader.defineClass(ClassLoader.java:202)
at 
clojure.lang.DynamicClassLoader.defineClass(DynamicClassLoader.java:39)
at clojure.gen_and_load_class__2231.doInvoke(genclass.clj:461)
at clojure.lang.RestFn.invoke(RestFn.java:443)
at user.fn__2491.invoke(Unknown Source)
at clojure.lang.AFn.applyToHelper(AFn.java:182)
at clojure.lang.AFn.applyTo(AFn.java:175)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:2664)
at clojure.lang.Compiler.eval(Compiler.java:4116)
at clojure.lang.Repl.main(Repl.java:91)
nil
user=

The 'defexception macro is actually from swank-clojure. I have used
this successfully in the past, the difference here is that I am using
the IBM 1.6.0 JRE in this case:

   [EMAIL PROTECTED] trunk]$ java -version
   java version 1.6.0
   Java(TM) SE Runtime Environment (build pxi3260sr2-20080818_01(SR2))
   IBM J9 VM (build 2.4, J2RE 1.6.0 IBM J9 2.4 Linux x86-32
jvmxi3260-20080816_22093 (JIT enabled, AOT enabled)
   J9VM - 20080816_022093_lHdSMr
   JIT  - r9_20080721_1330ifx2
   GC   - 20080724_AA)
   JCL  - 20080808_02

I'm not sure if this is Clojure's bug or IBM's. I don't have the
luxury of testing this on any other JVMs at the moment. I presume that
since everyone is able to use swank-clojure at the latest revision
that this is not happening on other JVMs?

/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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



lancet: Clojure controlling Ant

2008-11-06 Thread Stuart Halloway

Hi all,

I am playing around with using Clojure to control Ant, something along  
the lines of Groovy's Gant. I don't know how far I will take this-- 
right now it is serving as a code example for the book.

Two questions:

(1) Anybody interested in seeing lancet carried forward into a real  
project?

(2) Below is an example of lancet syntax (compare with Clojure's own  
build.xml). Any big likes/dislikes?

Cheers,
Stuart

(project {:name clojure :default jar}

  (properties :src src
 :jsrc (i :src /jvm)
 :cljsrc (i :src /clj)
 :build classes
 :clojure_jar clojure.jar
 :bootclj (i :cljsrc /clojure/boot.clj))

  (target {:name test}
   (echo {:message init target}))

  (target {:name compile :depends init
  :description Compile Java sources.}
   (javac {:srcdir (i :jsrc) :destdir (i :build)
  :includejavaruntime yes
  :debug true
  :target 1.5}))

  (target {:name init}
   (tstamp)
   (mkdir {:dir (i :build)}))

  (target {:name clean
  :description Remove autogenerated files and directories}
   (delete {:dir (i :build)}))

)


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Clojure Maven integration

2008-11-06 Thread Brian Doyle
Does anyone know of any Clojure maven integration?
What I'd like to see is something that will modify Clojure's
classpath updated based upon a given pom.xml file.
Thanks.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Clojure group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: lancet: Clojure controlling Ant

2008-11-06 Thread Brian Doyle
On Thu, Nov 6, 2008 at 11:48 AM, Stuart Halloway
[EMAIL PROTECTED]wrote:


 Hi all,

 I am playing around with using Clojure to control Ant, something along
 the lines of Groovy's Gant. I don't know how far I will take this--
 right now it is serving as a code example for the book.

 Two questions:

 (1) Anybody interested in seeing lancet carried forward into a real
 project?


Yes, I hate ant and pretty much anything would be better!  I might have
some time to help out with the implementation.




 (2) Below is an example of lancet syntax (compare with Clojure's own
 build.xml). Any big likes/dislikes?


No complaints from me.  I like the syntax.




 Cheers,
 Stuart

 (project {:name clojure :default jar}

  (properties :src src
 :jsrc (i :src /jvm)
 :cljsrc (i :src /clj)
 :build classes
 :clojure_jar clojure.jar
 :bootclj (i :cljsrc /clojure/boot.clj))

  (target {:name test}
   (echo {:message init target}))

  (target {:name compile :depends init
  :description Compile Java sources.}
   (javac {:srcdir (i :jsrc) :destdir (i :build)
  :includejavaruntime yes
  :debug true
  :target 1.5}))

  (target {:name init}
   (tstamp)
   (mkdir {:dir (i :build)}))

  (target {:name clean
  :description Remove autogenerated files and directories}
   (delete {:dir (i :build)}))

 )


 


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Having struggle in understanding FP (and Clojure question)

2008-11-06 Thread Konrad Hinsen

On 05.11.2008, at 17:16, Mark H. wrote:

 and replace copies with destructive writes.  I haven't seen a purely
 functional formulation of LU factorization but it could be done
 without too much trouble.  Of course there's no reason to go through
 that effort because people spend so much time optimizing LU and its
 constituent components that you would be better off reusing their
 work.

For the immediate future, yes. But with changing computer  
architectures, the existing algorithms and routines may lose much of  
their interest in the future.

 To me the more interesting and rewarding task is to figure out how to
 splice existing HPC libraries into a functional framework, without
 losing the ability to reason functionally about the components.

Unfortunately, it is already a bit of a pain to link existing HPC  
libraries (written in Fortran, C, or C++) to functional code in any  
decent language. Clojure won't help there, as there are still very  
few HPC libraries for the JVM and JNI adds too much of an overhead.

 Definitely!  We've got at least one fellow here who uses Common Lisp
 to generate stencil codes.  He's been thinking about switching to
 Clojure ever since he and I worked on a thorny Lisp problem
 together ;-)

I am looking forward to a nice Clojure library then :-)

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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: jEdit Mode for Clojure

2008-11-06 Thread Daniel Spiewak

After I posted this, I realized that it was a little silly to talk
about a Lisp editor mode without auto-indentation.  It has been
added!  The main caveat is it doesn't seem to handle multiple
unindents with the correctness I would like.  For example:

(defn say-hi [n]
  (println
(str Hello,  n)))

; more code here

Obviously, the third line should result in two levels of
undindenting.  However, due to limitations in the way that jEdit
handles auto-indenting, I don't think I can do both levels at once.
Specifically, the auto-indenting would assume that the ; more code
here line should be indented at level 1, despite the fact that all
parens are closed by that point.  It's possible that I may be able to
leverage jEdit's brace matching to unindent properly, but that will
require some more experimentation.

Daniel

On Nov 6, 11:41 am, tkosan [EMAIL PROTECTED] wrote:
 Daniel wrote

  Mostly for amusement, I created a jEdit mode for Clojure a while
  back.  I don't get a chance to play with Clojure all that much, so it
  hasn't been heavily tested (go-to *is* a Clojure keyword,
  right?).  ;-)  It's primarily based upon the Vim mode in terms of what
  keywords it supports and how.  Auto-indentation was something I looked
  at, but it isn't something I actually bothered to support due to time
  constraints (jEdit is capable of some pretty slick auto-indenting
  where Lisp-like languages are concerned).

 This is good timing for me.  I am in the process of integrating
 clojure into a jEdit-based Mathematics Computing Environment I am
 creating called MathRider:

    http://mathrider.org

 MathRider currently includes clojure but syntax highlighting is not
 complete yet.  I will look at your jEdit mode to see if it is more
 functional than what MathRider is currently using.  If you have time
 to add auto-indentation, that would be great.

 If anyone wants to experiment with clojure in MathRider, there is a
 file called clojure_examples.mrw in the mathrider/examples
 directory.

 Ted Kosan
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: lancet: Clojure controlling Ant

2008-11-06 Thread carlitos

On Nov 6, 7:48 pm, Stuart Halloway [EMAIL PROTECTED] wrote:
 I am playing around with using Clojure to control Ant, something along  
 the lines of Groovy's Gant. []

I know next to nothing about ant, and what kind of control will lancet
provide, but the proposed syntax reminds me of what I got playing with
XML generation.
As an exercise, I tried to reproduce clojure's build.xml and pom.xml
(the output of the code below differs only in whitespace).
Your proposal is more succint (in particular when it comes to
properties), but I think it can be easily expanded to the
representation below (which maps directly into XML).

Cheers,

Carlos

(defn write-attributes [key val  attrs]
  (print (format  %s=\%s\ (name key) val))
  (when attrs (apply write-attributes attrs)))

(defn write-tag [data close]
  (let [tag (name (if (coll? data)
(first data)
data))]
(print (format %s tag))
(when (coll? data)
  (apply write-attributes (rest data)))
(if close
  (do (print /) nil)
  (do (print ) tag

(defn write-xml [tree]
  (if (coll? tree)
(let [values (rest tree)
  close-tag (write-tag (first tree) (not values))]
  (when (or (not (= 1 (count values)))
(coll? (first values)))
(println))
  (doall (map write-xml values))
  (when close-tag
(println (format /%s close-tag
(print tree)))

;; build.xml

(write-xml
 '((:project :name clojure :default jar)
   (:description Build with \ant jar\ and then start the REPL
via \java -cp clojure.jar clojure.lang.Repl src/boot.clj\.)
   ((:property :name src :location src))
   ((:property :name jsrc :location ${src}/jvm))
   ((:property :name cljsrc :location ${src}/clj))
   ((:property :name build :location classes))
   ((:property :name clojure_jar :location clojure.jar))
   ((:property :name bootclj :location ${cljsrc}/clojure/
boot.clj))
   ((:target :name init)
(:tstamp)
((:mkdir :dir ${build})))
   ((:target :name compile :depends init :description Compile
Java sources.)
((:javac :srcdir ${jsrc} :destdir ${build} :includeJavaRuntime
yes :debug true :target 1.5)))
   ((:target :name jar :depends compile :description Create jar
file.)
((:jar :jarfile ${clojure_jar} :basedir ${build})
 ((:fileset :dir ${cljsrc} :includes **/*.clj))
(:manifest
 ((:attribute :name Main-Class :value clojure.lang.Repl))
 ((:attribute :name Class-Path :value .)
   ((:target :name clean :description Remove autogenerated files
and directories.)
((:delete :dir ${build})

;; pom.xml

(defn write-pom [pom]
  (println ?xml version=\1.0\ encoding=\UTF-8\?)
  (write-xml
   (conj pom '(:project
   :xmlns http://maven.apache.org/POM/4.0.0;
   :xmlns:xsi http//www.w3.org/2001/XMLSchema-instance
   :xsi:schemaLocation http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd;

(write-pom
 '((:modelVersion 4.0.0)
   (:groupId jvm.clojure)
   (:artifactId clojure-lang)
   (:name clojure-lang)
   (:version 1.0-SNAPSHOT)
   (:url http://clojure.org/;)
   (:build
(:sourceDirectory src/jvm)
(:scriptSourceDirectory src/clj)
(:plugins (:plugin
   (:artifactId maven-compiler-plugin)
   (:configuration (:source 1.5) (:target 1.5) (:optimize
true
 (:resources (:resource (:directory src/clj/))


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: lancet: Clojure controlling Ant

2008-11-06 Thread Stephen Wrobleski

On Thu, Nov 06, 2008 at 01:48:43PM -0500, Stuart Halloway wrote:
 
 Hi all,
 
 I am playing around with using Clojure to control Ant, something along  
 the lines of Groovy's Gant. I don't know how far I will take this-- 
 right now it is serving as a code example for the book.
 
 Two questions:
 
 (1) Anybody interested in seeing lancet carried forward into a real  
 project?

Oh yes please! I had started playing around with something like this, got
far enough to compile some Java source (a static base for some Clojure code
of course), and haven't really touched it sense.

 (2) Below is an example of lancet syntax (compare with Clojure's own  
 build.xml). Any big likes/dislikes?

I've never liked XML DSLs because they lack standard general purpose
language features and go on to invent their own ad-hoc versions.

Is a property not just a 'def' ?

Is a target not a just function? (which only performs its actions if needed)

Isn't a project just a mapping from target names to functions, and dynamic
bindings during the build process?


; properties
(def src src)
(def jsrc (str src /jvm))
(def cljsrc (str src /clj))
(def target classes)
(def clojure.jar clojure.jar)
(def bootclj (str cljsrc /clojure/boot.clj))

; deftarget is like defn but takes no args, and wraps the body in machinery
; that will only call it once per session.

(deftarget clean
  Remove autogenerated files and directories
  (delete :dir target))

(deftarget init
  (tstamp)
  (mkdir :dir target))

(deftarget compile-java
  Compile java sources  
  (init)
  (javac :srcdir jsrc :destdir target
 :includejavaruntime true
 :debug true
 :target 1.5))


A project could be defined explicitly, or could be created through
reflection (deftarget would also add some metadata in that case)

This syntax seems Clojurish rather than happens-to-be-on-Clojure. I think it
shows off both the cognitive simplicity of FP and the powerful incremental
nature of a Lisp based internal DSL.


Regards,
Steve

--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Generalized Type Inference Optimization

2008-11-06 Thread Daniel Spiewak

I've been perusing Stu Halloway's beta of Programming Clojure and I
came across the following example:

(defn describe-class [c]
  {:name (.getName c)
   :final (java.lang.reflect.Modifier/isFinal (.getModifiers c))})

As demonstrated by the *warn-on-reflection* flag, Clojure is unable to
determine a type for c, therefore all (or rather, almost all) of the
calls made upon it must be handled reflectively.  The performance
solution suggested in the book is just to annotate the c parameter
with a type:

(defn describe-class [#^Class c] ...)

This is a perfectly valid solution, but it seems a little ugly to me.
The thought that I had is perhaps the Clojure compiler could actually
infer this type automatically.  Languages like ML and Haskell have
been doing this for decades.  Traditionally, Hindley-Milner isn't
applied to object-oriented languages (or rather, languages which deal
with uncontrolled OO constructs), but from what I understand, most of
the reasoning behind this does not apply to Clojure.  For example,
Clojure doesn't have structural or parametric types because of its
dynamic nature.  There would be no *need* to infer any type parameters
on calls out to Java, so the type system could be treated as nominal.

The algorithm I'm thinking of would be something like this:

* Maintain a multi-map of method and field names to classes (this
could be done incrementally based on what classes the compiler knows
are in scope)
* For each parameter with an unfixed type:
   * Traverse the FnExpr AST and find all Java member access to that
parameter
   * For each access, obtain a set of possible classes from the scope
multi-map
   * At each step, intersect the previous set of possible classes with
the subsequent one (think: a fold)
   * Final set can be optimized by choosing the most-specific type
(eliminating the inheritance case)
   * If the final set has size of 1, then the type has been inferred
and can be used to avoid reflection
   * If the set has size 0, then fallback on reflection
   * If the set has size 1, either fallback on reflection or get more
sophisticated

Improvements on this could be added to the 1 case where the second
pass could look for methods of a given name *and* a specific arity.
Subsequent passes could also incorporate inferred types for the method
parameters.

It's not a complete inference algorithm, but it doesn't have to be.
There's nothing stopping Clojure from falling back on reflection for
unfixed types.  The whole logic behind this dance is to avoid
reflection as much as possible, producing a fairly serious
optimization in Java-interop without requiring those ugly type
annotations.

I briefly looked at implementing this myself, but Clojure's compiler
code is...well, it's a compiler.  :-)  At first glance, I couldn't
even figure out where to place the appropriate hooks to kick off this
process.  A better question though is: has this been tried/considered
before?  What are your overall thoughts with regards to 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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Generalized Type Inference Optimization

2008-11-06 Thread Rich Hickey



On Nov 6, 4:31 pm, Daniel Spiewak [EMAIL PROTECTED] wrote:
 I've been perusing Stu Halloway's beta of Programming Clojure and I
 came across the following example:

 (defn describe-class [c]
   {:name (.getName c)
:final (java.lang.reflect.Modifier/isFinal (.getModifiers c))})

 As demonstrated by the *warn-on-reflection* flag, Clojure is unable to
 determine a type for c, therefore all (or rather, almost all) of the
 calls made upon it must be handled reflectively.  The performance
 solution suggested in the book is just to annotate the c parameter
 with a type:

 (defn describe-class [#^Class c] ...)

 This is a perfectly valid solution, but it seems a little ugly to me.
 The thought that I had is perhaps the Clojure compiler could actually
 infer this type automatically.  Languages like ML and Haskell have
 been doing this for decades.  Traditionally, Hindley-Milner isn't
 applied to object-oriented languages (or rather, languages which deal
 with uncontrolled OO constructs), but from what I understand, most of
 the reasoning behind this does not apply to Clojure.  For example,
 Clojure doesn't have structural or parametric types because of its
 dynamic nature.  There would be no *need* to infer any type parameters
 on calls out to Java, so the type system could be treated as nominal.

 The algorithm I'm thinking of would be something like this:

 * Maintain a multi-map of method and field names to classes (this
 could be done incrementally based on what classes the compiler knows
 are in scope)
 * For each parameter with an unfixed type:
* Traverse the FnExpr AST and find all Java member access to that
 parameter
* For each access, obtain a set of possible classes from the scope
 multi-map
* At each step, intersect the previous set of possible classes with
 the subsequent one (think: a fold)
* Final set can be optimized by choosing the most-specific type
 (eliminating the inheritance case)
* If the final set has size of 1, then the type has been inferred
 and can be used to avoid reflection
* If the set has size 0, then fallback on reflection
* If the set has size 1, either fallback on reflection or get more
 sophisticated

 Improvements on this could be added to the 1 case where the second
 pass could look for methods of a given name *and* a specific arity.
 Subsequent passes could also incorporate inferred types for the method
 parameters.

 It's not a complete inference algorithm, but it doesn't have to be.
 There's nothing stopping Clojure from falling back on reflection for
 unfixed types.  The whole logic behind this dance is to avoid
 reflection as much as possible, producing a fairly serious
 optimization in Java-interop without requiring those ugly type
 annotations.

 I briefly looked at implementing this myself, but Clojure's compiler
 code is...well, it's a compiler.  :-)  At first glance, I couldn't
 even figure out where to place the appropriate hooks to kick off this
 process.  A better question though is: has this been tried/considered
 before?  What are your overall thoughts with regards to this?

It's not a bad idea, and I'm sure Clojure could do more inference than
it does, but the devil's in the details as usual.

You'd want the least specific type.

The best you could do is make a type-inferred fastpath, since you
could always be wrong:

  In the case above, let's say you had imported Class (actually
Clojure did that for you), and nothing else you imported had getName
and getModifiers methods. Making the inference 'must be Class' could
be wrong, since the function should work fine on
java.lang.reflect.Method, for instance, and maybe that was the intent.

So you'd need a runtime instanceof test for Class, and use the
fastpath if true, reflection if not.

Perf could be harder to pin down, as adding an import could cause
previously fast code to get slow.

Calls can be made only in specific conditional branches, which some
higher-level logic might understand maps to non-overlapping types, so
the inference should be of the call site, not the parameter itself -
i.e. it's perfectly fine to write fns that expect a set of unrelated
types, without being duck-typed. In fact it's even ok to type hint it
even though the hint is only correct in one path.

You have to allow for by-name duck-type calls or call them out
specifically. Right now they are allowed.

I think a simple version of this would be easy to do, when I get some
time.

I think it hasn't been a priority as it takes very few hints at the
moment to remove reflection, given that types are tracked from calls
to new and static calls, and from any other hinted calls. But it would
be great to not need them at all!

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 [EMAIL PROTECTED]
For more options, 

Re: Generalized Type Inference Optimization

2008-11-06 Thread Daniel Spiewak

 So you'd need a runtime instanceof test for Class, and use the
 fastpath if true, reflection if not.

 Perf could be harder to pin down, as adding an import could cause
 previously fast code to get slow.

Actually, I was thinking of performing the inference based on *all*
classes on the classpath, not just the ones which have been imported.
However, considering the fact that Clojure allows dynamic additions to
the classpath, coupled with the fact that not all available classes
need to be loaded, this might not be the best idea.  The idea of call-
point import scoping is an interesting one, I'm not sure how solid you
could make it though.  I mean, don't you look at the FnExpr types
prior to analyzing its usage?  (at least, that's how I've always
written my compilers)  At the very least, it might make library
functions a little more interesting (certainly ruling out any pre-
compilation).

With respect to the separate paths issue, I assume that you're talking
about something like this:

(defn bad-boy [c x]
  (if c
(.getMethods x)
(.length x)))

I think in this case the proper inference would be #{} -- in other
words, reflection.  The overhead of trying to fastpath and then
fallback in certain branches would probably outweigh any benefits in
this sort of edge case.

 The best you could do is make a type-inferred fastpath, since you
 could always be wrong

Yeah, that is annoying.  I hadn't thought of the fact that you could
infer at declaration point and get a totally unambiguous type but
still be wrong (since calls in different scopes could pass unexpected
types that happen to fulfill the structural signature).  How much
overhead does #getClass() impose these days?  I heard they were
optimizing some of that in Java 6, but I haven't actually benchmarked
anything.  I suppose a simple check of that sort wouldn't ever be more
expensive that a full-blown reflective call, but still.

At what point are functions actually compiled?  Is it possible to
apply some of the techniques used in tracing VMs (e.g. V8) to get some
improved context before performing the inference?  In that case, you
could actually create several different fast-path compilations
+fallback.  There are just so many complicated places you could go
with this, it's just a question of implementation details (and of
course, time to do it).

Daniel

On Nov 6, 4:26 pm, Rich Hickey [EMAIL PROTECTED] wrote:
 On Nov 6, 4:31 pm, Daniel Spiewak [EMAIL PROTECTED] wrote:



  I've been perusing Stu Halloway's beta of Programming Clojure and I
  came across the following example:

  (defn describe-class [c]
    {:name (.getName c)
     :final (java.lang.reflect.Modifier/isFinal (.getModifiers c))})

  As demonstrated by the *warn-on-reflection* flag, Clojure is unable to
  determine a type for c, therefore all (or rather, almost all) of the
  calls made upon it must be handled reflectively.  The performance
  solution suggested in the book is just to annotate the c parameter
  with a type:

  (defn describe-class [#^Class c] ...)

  This is a perfectly valid solution, but it seems a little ugly to me.
  The thought that I had is perhaps the Clojure compiler could actually
  infer this type automatically.  Languages like ML and Haskell have
  been doing this for decades.  Traditionally, Hindley-Milner isn't
  applied to object-oriented languages (or rather, languages which deal
  with uncontrolled OO constructs), but from what I understand, most of
  the reasoning behind this does not apply to Clojure.  For example,
  Clojure doesn't have structural or parametric types because of its
  dynamic nature.  There would be no *need* to infer any type parameters
  on calls out to Java, so the type system could be treated as nominal.

  The algorithm I'm thinking of would be something like this:

  * Maintain a multi-map of method and field names to classes (this
  could be done incrementally based on what classes the compiler knows
  are in scope)
  * For each parameter with an unfixed type:
     * Traverse the FnExpr AST and find all Java member access to that
  parameter
     * For each access, obtain a set of possible classes from the scope
  multi-map
     * At each step, intersect the previous set of possible classes with
  the subsequent one (think: a fold)
     * Final set can be optimized by choosing the most-specific type
  (eliminating the inheritance case)
     * If the final set has size of 1, then the type has been inferred
  and can be used to avoid reflection
     * If the set has size 0, then fallback on reflection
     * If the set has size 1, either fallback on reflection or get more
  sophisticated

  Improvements on this could be added to the 1 case where the second
  pass could look for methods of a given name *and* a specific arity.
  Subsequent passes could also incorporate inferred types for the method
  parameters.

  It's not a complete inference algorithm, but it doesn't have to be.
  There's nothing stopping Clojure from falling 

Re: lancet: Clojure controlling Ant

2008-11-06 Thread Stuart Halloway

Stephen,

You are absolutely right, and I hope to have all your syntax  
suggestions implemented tomorrow.

By way of background: When I started, it seemed there were three  
obvious avenues to pursue:

(1) write a Clojure DSL that generates the Ant XML
(2) write a Clojure DSL that sticks close to the underlying Ant object  
model
(3) stick to Clojure idioms and use individual Ant classes when they  
fit in

I rejected #1 out of hand--I don't think that the Ant XML has value,  
and so wrapping it (and having it leak in the form of error messages)  
was unappealing.

I picked #2 because I thought there were a ton of objects in the Ant  
model I would end up wanting, and that they would be so intertwined  
that I would need to use most of them in order to use any of them.

A few hours working on #2 was enough to convince me that there not  
much in Ant that I wanted to keep. In particular targets, properties,  
and subtask elements aren't worth their weight. That leaves only tasks  
(and a stubbed-out project object).

So now I am proceeding through door #3. The work on #2 wasn't a total  
waste -- I now know enough of the Ant object model to fake out the few  
things I need (so far).

Cheers,
Stuart

 On Thu, Nov 06, 2008 at 01:48:43PM -0500, Stuart Halloway wrote:

 Hi all,

 I am playing around with using Clojure to control Ant, something  
 along
 the lines of Groovy's Gant. I don't know how far I will take this--
 right now it is serving as a code example for the book.

 Two questions:

 (1) Anybody interested in seeing lancet carried forward into a real
 project?

 Oh yes please! I had started playing around with something like  
 this, got
 far enough to compile some Java source (a static base for some  
 Clojure code
 of course), and haven't really touched it sense.

 (2) Below is an example of lancet syntax (compare with Clojure's own
 build.xml). Any big likes/dislikes?

 I've never liked XML DSLs because they lack standard general purpose
 language features and go on to invent their own ad-hoc versions.

 Is a property not just a 'def' ?

 Is a target not a just function? (which only performs its actions if  
 needed)

 Isn't a project just a mapping from target names to functions, and  
 dynamic
 bindings during the build process?


 ; properties
 (def src src)
 (def jsrc (str src /jvm))
 (def cljsrc (str src /clj))
 (def target classes)
 (def clojure.jar clojure.jar)
 (def bootclj (str cljsrc /clojure/boot.clj))

 ; deftarget is like defn but takes no args, and wraps the body in  
 machinery
 ; that will only call it once per session.

 (deftarget clean
  Remove autogenerated files and directories
  (delete :dir target))

 (deftarget init
  (tstamp)
  (mkdir :dir target))

 (deftarget compile-java
  Compile java sources
  (init)
  (javac :srcdir jsrc :destdir target
 :includejavaruntime true
 :debug true
 :target 1.5))


 A project could be defined explicitly, or could be created through
 reflection (deftarget would also add some metadata in that case)

 This syntax seems Clojurish rather than happens-to-be-on-Clojure. I  
 think it
 shows off both the cognitive simplicity of FP and the powerful  
 incremental
 nature of a Lisp based internal DSL.


 Regards,
 Steve

 


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: lancet: Clojure controlling Ant

2008-11-06 Thread Stuart Halloway

Carlos,

I went down a similar road once before, using a Ruby DSL to generate  
the XML for Spring DI. This approach may offer the quickest initial  
return, but it hits a ceiling very quickly. You end up having two APIs  
with a totally unnecessary XML layer in between. Worse, the XML layer  
spews error messages that are totally meaningless in terms of the new  
object model.

I am going to skip the XML entirely and program against the parts of  
the Ant object model I want to keep. It may be worthwhile to write a  
tool that goes in the other direction, reading XML and emitting  
lancet, for people porting existing buildfiles.

Cheers,
Stuart


 On Nov 6, 7:48 pm, Stuart Halloway [EMAIL PROTECTED] wrote:
 I am playing around with using Clojure to control Ant, something  
 along
 the lines of Groovy's Gant. []

 I know next to nothing about ant, and what kind of control will lancet
 provide, but the proposed syntax reminds me of what I got playing with
 XML generation.
 As an exercise, I tried to reproduce clojure's build.xml and pom.xml
 (the output of the code below differs only in whitespace).
 Your proposal is more succint (in particular when it comes to
 properties), but I think it can be easily expanded to the
 representation below (which maps directly into XML).

 Cheers,

 Carlos

 (defn write-attributes [key val  attrs]
  (print (format  %s=\%s\ (name key) val))
  (when attrs (apply write-attributes attrs)))

 (defn write-tag [data close]
  (let [tag (name (if (coll? data)
   (first data)
   data))]
(print (format %s tag))
(when (coll? data)
  (apply write-attributes (rest data)))
(if close
  (do (print /) nil)
  (do (print ) tag

 (defn write-xml [tree]
  (if (coll? tree)
(let [values (rest tree)
 close-tag (write-tag (first tree) (not values))]
  (when (or (not (= 1 (count values)))
   (coll? (first values)))
   (println))
  (doall (map write-xml values))
  (when close-tag
   (println (format /%s close-tag
(print tree)))

 ;; build.xml

 (write-xml
 '((:project :name clojure :default jar)
   (:description Build with \ant jar\ and then start the REPL
 via \java -cp clojure.jar clojure.lang.Repl src/boot.clj\.)
   ((:property :name src :location src))
   ((:property :name jsrc :location ${src}/jvm))
   ((:property :name cljsrc :location ${src}/clj))
   ((:property :name build :location classes))
   ((:property :name clojure_jar :location clojure.jar))
   ((:property :name bootclj :location ${cljsrc}/clojure/
 boot.clj))
   ((:target :name init)
(:tstamp)
((:mkdir :dir ${build})))
   ((:target :name compile :depends init :description Compile
 Java sources.)
((:javac :srcdir ${jsrc} :destdir ${build} :includeJavaRuntime
 yes :debug true :target 1.5)))
   ((:target :name jar :depends compile :description Create jar
 file.)
((:jar :jarfile ${clojure_jar} :basedir ${build})
 ((:fileset :dir ${cljsrc} :includes **/*.clj))
(:manifest
 ((:attribute :name Main-Class :value clojure.lang.Repl))
 ((:attribute :name Class-Path :value .)
   ((:target :name clean :description Remove autogenerated files
 and directories.)
((:delete :dir ${build})

 ;; pom.xml

 (defn write-pom [pom]
  (println ?xml version=\1.0\ encoding=\UTF-8\?)
  (write-xml
   (conj pom '(:project
  :xmlns http://maven.apache.org/POM/4.0.0;
  :xmlns:xsi http//www.w3.org/2001/XMLSchema-instance
  :xsi:schemaLocation http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/maven-v4_0_0.xsd;

 (write-pom
 '((:modelVersion 4.0.0)
   (:groupId jvm.clojure)
   (:artifactId clojure-lang)
   (:name clojure-lang)
   (:version 1.0-SNAPSHOT)
   (:url http://clojure.org/;)
   (:build
(:sourceDirectory src/jvm)
(:scriptSourceDirectory src/clj)
(:plugins (:plugin
  (:artifactId maven-compiler-plugin)
  (:configuration (:source 1.5) (:target 1.5) (:optimize
 true
 (:resources (:resource (:directory src/clj/))


 


--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Having struggle in understanding FP (and Clojure question)

2008-11-06 Thread cwyang

Thanks everyone.

I've read all the replies, and I might understand something.
(Though it seems that discussion goes to beyond my current
understanding in the middle of this discussion threads)
To explore further, I become another owner of 'Programming
Clojure' :-)

For my second question, I'll keep thinking and repost question.
I'm really concern about concurrency of Clojure,
since the concurrency in my world means
_the C10K problem_, that is supporting simultaneous
1 connections or over for networking applications.
(http://www.kegel.com/c10k.html)
In YAWS, Erlang have shown one solution, so I'm curios that
Clojure could be another viable alternative,
and that how well-suited Clojure is for that kind of concurrency.

My expectation is these:
1) For C10K problem (or C100K), application must not use
native threads. Big stack size means low concurrency
2) For application developer, thread model is easy to develop
and follow.
3) Therefore, underlying system should support
concurrency facility like micro-thread, lightweight process (in
Erlang)
, agent (in Clojure), or whatever.
In this case, underlying facility should have high-performance.
4) At the same time, there must be ways for connecting conceptual
gap between 2) and 3). In other words, the way for suspending current
execution of function, saving current execution snapshot
(normally native thread stack, but may be different),
and switching to other functions are needed when the request for I/O
should be blocked. It's important that the size of current execution
snapshot should be small, since it determine the degree of
concurrency.

After I invest some time to learn Clojure, I'll repost.

Thank you.

- cw
--~--~-~--~~~---~--~~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Having struggle in understanding FP (and Clojure question)

2008-11-06 Thread Mark H.

On Nov 6, 11:58 am, Konrad Hinsen [EMAIL PROTECTED] wrote:
 On 05.11.2008, at 17:16, Mark H. wrote:
 For the immediate future, yes. But with changing computer  
 architectures, the existing algorithms and routines may lose much of  
 their interest in the future.

Haha, yes, we're working on this ;-)  (a number of my colleagues are,
at least).

  To me the more interesting and rewarding task is to figure out how to
  splice existing HPC libraries into a functional framework, without
  losing the ability to reason functionally about the components.

 Unfortunately, it is already a bit of a pain to link existing HPC  
 libraries (written in Fortran, C, or C++) to functional code in any  
 decent language. Clojure won't help there, as there are still very  
 few HPC libraries for the JVM and JNI adds too much of an overhead.

Does the JNI require copy-in / copy-out for arrays of floating-point
numbers?  I know Java has messed-up floating-point (Sun stupidly took
away x87's 80-bit temps and other good things) but I'd at least like
to avoid copy overhead for matrix and vector ops.  I don't mind the
extra function call out of JVM space as long as I can amortize it over
the cost of a big matrix operation.  (No way I'm writing loops in
Clojure for that.)

There are a number of Python-based projects to do what you mentioned
(link HPC libraries in Fortran or C to a higher-level language), so
it's not impossible.  It's just a lot of tedious work for some unlucky
coders.

  Definitely!  We've got at least one fellow here who uses Common Lisp
  to generate stencil codes.  He's been thinking about switching to
  Clojure ever since he and I worked on a thorny Lisp problem
  together ;-)

 I am looking forward to a nice Clojure library then :-)

We'll see -- he's got it working in CL now and he's got a deadline, so
he may not bother migrating it.  Plus he likes the ECL / C linkup;
Java may not be so helpful for him.

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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Recommending Approach to Performance Critical Code

2008-11-06 Thread Mark H.

On Nov 6, 7:05 pm, CuppoJava [EMAIL PROTECTED] wrote:
 I'm doing some heavy numerical matrix crunching and would like to
 write it in as elegant a way as possible without sacrificing any
 speed.

Can you define matrix crunching more precisely?

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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---