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