On 10 March 2010 02:19, K. <kotot...@gmail.com> wrote:
> How should I compare two persistent lists ?

Is it acceptable for you to use '='
user=> (= '(1 2) '(3 4))
false
user=> (= '(1 2) '(1 2))
true
or do you really really need the +1 0 -1 behavior?


Is there any problem with ISeq requiring compareTo? In principal I
think that should be fine

tprat...@apis:~/projects/clojure$ clj
Clojure 1.2.0-master-SNAPSHOT
user=> (compare '(1 2) '(3 4))
-1
user=> (compare '(1 2) '(0 4))
1
user=> (compare (seq {:a 1})  (seq {:a 1}))
0

;; though is it really meaningful to write something like:
user=> (compare (seq {:b 2, :a 1})  (seq {:a 1, :b 2}))
1

;; I guess it doesn't matter much at the end of the day :)


Attached is a patch to that effect. Happy to raise a ticket if this is
welcome, and/or make a PersistentList only compareTo patch.


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
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
From 633d8b03ecb304e94e43d41ef57eab8fbb354533 Mon Sep 17 00:00:00 2001
From: Timothy Pratley <timothyprat...@gmail.com>
Date: Wed, 10 Mar 2010 22:14:13 +1100
Subject: [PATCH] Made ISeq Comparable

---
 src/jvm/clojure/lang/ASeq.java                |   22 ++++++++++++++++-
 src/jvm/clojure/lang/ISeq.java                |    4 ++-
 src/jvm/clojure/lang/LazySeq.java             |    7 ++++-
 src/jvm/clojure/lang/PersistentList.java      |   32 ++++++++++++++++++++++++-
 test/clojure/test_clojure/data_structures.clj |   10 ++++++-
 5 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/src/jvm/clojure/lang/ASeq.java b/src/jvm/clojure/lang/ASeq.java
index 73f88da..baaed1e 100644
--- a/src/jvm/clojure/lang/ASeq.java
+++ b/src/jvm/clojure/lang/ASeq.java
@@ -12,7 +12,7 @@ package clojure.lang;
 
 import java.util.*;
 
-public abstract class ASeq extends Obj implements ISeq, List, Streamable{
+public abstract class ASeq extends Obj implements ISeq, List, Streamable, Comparable{
 transient int _hash = -1;
 
 public String toString(){
@@ -59,6 +59,26 @@ public boolean equals(Object obj){
 
 }
 
+public int compareTo(Object obj){
+
+	if(!(obj instanceof Sequential || obj instanceof List))
+		throw new UnsupportedOperationException();
+	ISeq ms = RT.seq(obj);
+	for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next())
+		{
+		if(ms == null)
+		       return 1;
+		int c = Util.compare(s.first(), ms.first());
+		if ( c != 0 )
+			return c;
+		}
+	if(ms == null)
+	       	return 0;
+	else
+		return -1;
+
+}
+
 public int hashCode(){
 	if(_hash == -1)
 		{
diff --git a/src/jvm/clojure/lang/ISeq.java b/src/jvm/clojure/lang/ISeq.java
index 6edb519..dbeb957 100644
--- a/src/jvm/clojure/lang/ISeq.java
+++ b/src/jvm/clojure/lang/ISeq.java
@@ -16,7 +16,7 @@ package clojure.lang;
  * ISeqs are immutable values, i.e. neither first(), nor rest() changes
  * or invalidates the ISeq
  */
-public interface ISeq extends IPersistentCollection, Sequential{
+public interface ISeq extends IPersistentCollection, Sequential, Comparable{
 
 Object first();
 
@@ -26,4 +26,6 @@ ISeq more();
 
 ISeq cons(Object o);
 
+int compareTo(Object o);
+
 }
diff --git a/src/jvm/clojure/lang/LazySeq.java b/src/jvm/clojure/lang/LazySeq.java
index a853e9b..2c2ecb4 100644
--- a/src/jvm/clojure/lang/LazySeq.java
+++ b/src/jvm/clojure/lang/LazySeq.java
@@ -14,7 +14,7 @@ package clojure.lang;
 
 import java.util.*;
 
-public final class LazySeq extends Obj implements ISeq, List{
+public final class LazySeq extends Obj implements ISeq, List, Comparable{
 
 private IFn fn;
 private Object sv;
@@ -74,6 +74,11 @@ public int count(){
 	return c;
 }
 
+public int compareTo(Object o){
+	ISeq ms = RT.seq(o);
+	return seq().compareTo( ms );
+}
+
 public Object first(){
 	seq();
 	if(s == null)
diff --git a/src/jvm/clojure/lang/PersistentList.java b/src/jvm/clojure/lang/PersistentList.java
index 477d1cb..5a0f1a2 100644
--- a/src/jvm/clojure/lang/PersistentList.java
+++ b/src/jvm/clojure/lang/PersistentList.java
@@ -12,7 +12,7 @@ package clojure.lang;
 
 import java.util.*;
 
-public class PersistentList extends ASeq implements IPersistentList, IReduce, List, Counted{
+public class PersistentList extends ASeq implements IPersistentList, IReduce, List, Counted, Comparable{
 
 private final Object _first;
 private final IPersistentList _rest;
@@ -124,6 +124,27 @@ public Object reduce(IFn f, Object start) throws Exception{
 	return ret;
 }
 
+public int compareTo(Object o){
+	PersistentList ll = (PersistentList) o;
+	if(count() < ll.count())
+		return -1;
+	else if(count() > ll.count())
+		return 1;
+	ISeq ms = RT.seq(o);
+	for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next())
+		{
+		if(ms == null)
+		       return 1;
+		int c = Util.compare(s.first(), ms.first());
+		if ( c != 0 )
+			return c;
+		}
+	if(ms == null)
+	       	return 0;
+	else
+		return -1;
+}
+
 
     static class EmptyList extends Obj implements IPersistentList, List, ISeq, Counted{
 
@@ -181,6 +202,15 @@ public Object reduce(IFn f, Object start) throws Exception{
 		return 0;
 	}
 
+	public int compareTo(Object o){
+		if ( o instanceof EmptyList )
+			return 0;
+		else if ( o instanceof List )
+			return -1;
+		else
+			throw new UnsupportedOperationException();
+	}
+
 	public ISeq seq(){
 		return null;
 	}
diff --git a/test/clojure/test_clojure/data_structures.clj b/test/clojure/test_clojure/data_structures.clj
index 5a6bba8..6af3ffe 100644
--- a/test/clojure/test_clojure/data_structures.clj
+++ b/test/clojure/test_clojure/data_structures.clj
@@ -616,7 +616,6 @@
       #{} ; #{1 2}
   )
   ; cannot be cast to java.lang.Comparable
-  (is (thrown? ClassCastException (sorted-set '(1 2) '(1 2))))
   (is (thrown? ClassCastException (sorted-set {:a 1 :b 2} {:a 1 :b 2})))
   (is (thrown? ClassCastException (sorted-set #{1 2} #{1 2})))
 
@@ -669,7 +668,6 @@
   ; cannot be cast to java.lang.Comparable
   ; NB: not a ClassCastException, but a RuntimeException is thrown,
   ; requires discussion on whether this should be symmetric with test-sorted-set
-  (is (thrown? Exception (sorted-set-by compare '(1 2) '(1 2))))
   (is (thrown? Exception (sorted-set-by compare {:a 1 :b 2} {:a 1 :b 2})))
   (is (thrown? Exception (sorted-set-by compare #{1 2} #{1 2})))
 
@@ -791,3 +789,11 @@
       (disj #{#{nil}} #{nil}) #{} ))
 
 
+(deftest test-compare
+  (are [x y] (= x y)
+       (compare 1 2) -1
+       (compare '(1 2) '(3 4)) -1
+       (compare (seq {:a 1}) (seq {:a 1})) 0
+       (compare (seq {:b 2, :a 1})  (seq {:a 1, :b 2})) 1))
+
+
-- 
1.6.3.3

Reply via email to