├── .classpath ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── README ├── epl-v10.html ├── pom.xml └── src ├── main └── java │ └── com │ └── github │ └── krukow │ ├── clj_ds │ ├── EditableCollection.java │ ├── Indexed.java │ ├── PersistentCollection.java │ ├── PersistentList.java │ ├── PersistentMap.java │ ├── PersistentSet.java │ ├── PersistentSortedMap.java │ ├── PersistentSortedSet.java │ ├── PersistentStack.java │ ├── PersistentVector.java │ ├── Persistents.java │ ├── TransientCollection.java │ ├── TransientMap.java │ ├── TransientSet.java │ ├── TransientVector.java │ └── Transients.java │ └── clj_lang │ ├── AFn.java │ ├── AFunction.java │ ├── AMapEntry.java │ ├── APersistentMap.java │ ├── APersistentSet.java │ ├── APersistentTrie.java │ ├── APersistentVector.java │ ├── ASeq.java │ ├── ATransientMap.java │ ├── ATransientSet.java │ ├── ArityException.java │ ├── ArrayChunk.java │ ├── ArraySeq.java │ ├── Associative.java │ ├── BigInt.java │ ├── Box.java │ ├── ChunkBuffer.java │ ├── ChunkedCons.java │ ├── Cons.java │ ├── Counted.java │ ├── EmptyIterator.java │ ├── Fn.java │ ├── IChunk.java │ ├── IChunkedSeq.java │ ├── IDeref.java │ ├── IEditableCollection.java │ ├── IFn.java │ ├── IHashEq.java │ ├── ILookup.java │ ├── IMapEntry.java │ ├── IMeta.java │ ├── IObj.java │ ├── IPending.java │ ├── IPersistentCollection.java │ ├── IPersistentList.java │ ├── IPersistentMap.java │ ├── IPersistentSet.java │ ├── IPersistentStack.java │ ├── IPersistentTrie.java │ ├── IPersistentVector.java │ ├── IReduce.java │ ├── ISeq.java │ ├── ITransientAssociative.java │ ├── ITransientCollection.java │ ├── ITransientMap.java │ ├── ITransientSet.java │ ├── ITransientVector.java │ ├── Indexed.java │ ├── IndexedSeq.java │ ├── InlineArrayPersistentHATTrie.java │ ├── IteratorSeq.java │ ├── LazilyPersistentVector.java │ ├── LazySeq.java │ ├── MapEntry.java │ ├── Numbers.java │ ├── Obj.java │ ├── PersistentArrayMap.java │ ├── PersistentHATTrie.java │ ├── PersistentHashMap.java │ ├── PersistentHashSet.java │ ├── PersistentList.java │ ├── PersistentQueue.java │ ├── PersistentStructMap.java │ ├── PersistentTreeMap.java │ ├── PersistentTreeSet.java │ ├── PersistentVector.java │ ├── RRBTree.java │ ├── RT.java │ ├── Range.java │ ├── Ratio.java │ ├── Reduced.java │ ├── Reflector.java │ ├── RestFn.java │ ├── Reversible.java │ ├── SeqEnumeration.java │ ├── SeqIterator.java │ ├── Seqable.java │ ├── Sequential.java │ ├── Sorted.java │ └── Util.java └── test └── java └── com └── github └── krukow └── clj_lang └── test ├── AllTests.java ├── PersistentHATTrieTest.java ├── PersistentHashMapTest.java ├── PersistentHashSetTest.java ├── PersistentNonHashMapsTest.java └── PersistentVectorTest.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .idea 3 | settings.xml 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | clj-ds 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.m2e.core.maven2Nature 21 | org.eclipse.jdt.core.javanature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Fri May 14 08:04:06 CEST 2010 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.6 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This library has been extracted from the master branch of Clojure (http://clojure.org) 2 | 3 | version 1.5.1 (as of October 2013) 4 | 5 | http://github.com/richhickey/clojure 6 | 7 | created by Rich Hickey. The core data structures and algorithms are due to him. 8 | This library is distributed with the same license as the Clojure programming 9 | language itself (EPL, see file epl-v10.html). 10 | 11 | It has been modified by Karl Krukow , and mistakes introduced are mine. 12 | 13 | 14 | Maven 15 | 16 | 17 | com.github.krukow 18 | clj-ds 19 | 0.0.4 20 | 21 | 22 | 23 | *WHY* 24 | First, I love Clojure :) ... 25 | Unfortunately sometimes clients require that I use Java... 26 | 27 | The data structures used in the Clojure programming language are a great 28 | implementation of a number of useful persistent data structures 29 | (see e.g., the section on immutable data structures on 30 | http://clojure.org/functional_programming). 31 | 32 | However, these data structures are tailor-made to work optimally in the 33 | Clojure programming language, and while it is possible to use these from 34 | Java (since Clojure is distributed as a .jar file), it is inconvenient 35 | for a number of reasons (see below). Since it is (unfortunately) not always 36 | possible to use Clojure, I've created this library to at least reap some of the 37 | Clojure benefits in environments constrained to Java. 38 | Beyond Java, other JVM languages like Erjang, Scala, JRuby and Groovy may benefit 39 | from immutability & persistence, and from this implementation. 40 | 41 | *Advantages of clj-ds when constrained to working with Java* 42 | Currently the Clojure data structures are implemented in Java. In the future, 43 | all of Clojure will be implemented in Clojure itself (known as "Clojure-in-Clojure"). 44 | This has many advantages for Clojure, but when it happens the data structures will 45 | probably be even more intertwined with the rest of the language, 46 | and may be even more inconvenient to use in a Java context. 47 | 48 | The clj-ds project will maintain Java versions of the code, and where possible attempt 49 | to "port" improvements made in the Clojure versions back into clj-ds. Thus keeping maintained 50 | versions of the Java data structures. 51 | 52 | In the current Clojure version, calling certain methods on PersistentHashMap requires 53 | loading the entire Clojure runtime, including the bootstrap process. This takes about one second. 54 | This means that the first time one of these methods is called, a Java user will experience a 55 | slight delay (and a memory-usage increase). Further, many of the Clojure runtime 56 | Java classes are not needed when only support for persistent data structures 57 | is wanted (e.g., the compiler). 58 | 59 | The clj-ds library is not dependent on the Clojure runtime nor does it run any 60 | Clojure bootstrap process, e.g., the classes that deal with compilation have been removed. 61 | This results in a smaller library, and the mentioned delay does not occur. 62 | 63 | Clojure is a dynamically typed language. Java is statically typed, and supports 64 | 'generics' from version 5. A Java user would expect generics support from a Java 65 | data structure library, and the Clojure version doesn't have this. 66 | clj-ds will support generics. 67 | 68 | Finally, a slight improvement. 69 | Certain of the Clojure data structure methods use Clojure's 'seq' abstraction 70 | in the implementation of the Java 'iterator' pattern. It is possible, to make 71 | slightly more efficient iterators using a tailor made iterator. clj-ds does this. 72 | 73 | Example stats for iterating through various data structures: 74 | (20-40% improvement, matters only for quite large structures) 75 | 76 | PersistentHashSet: 77 | ---- 78 | 500.000 elements 79 | 58 ms (Java avg.) 80 | 192 ms (Pure Clojure avg) 81 | 106 ms (clj-ds avg) 82 | --- 83 | 1 mio elements: 84 | 104 ms (Java avg.) 85 | 497 ms (Pure Clojure avg) 86 | 371 ms (clj-ds avg) 87 | 88 | --- 89 | PersistentHashMap 90 | --- 91 | 500.000 elements 92 | 94 ms (Java avg.) 93 | 189 ms (Pure Clojure avg) 94 | 131 ms (clj-ds avg) 95 | 96 | 1 mio elements: 97 | 128 ms (Java avg.) 98 | 549 ms (Pure Clojure avg) 99 | 394 ms (clj-ds avg) 100 | 101 | --- 102 | PersistentVector 103 | --- 104 | 1 mio elements: 105 | 104 ms (Java avg.) 106 | 122 ms (Pure Clojure avg) 107 | 104 ms (clj-ds avg) 108 | 109 | 2 mio elements: 110 | 186 ms (Java avg.) 111 | 223 ms (Pure Clojure avg) 112 | 184 ms (clj-ds avg) -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | com.github.krukow 4 | clj-ds 5 | jar 6 | 0.0.5-SNAPSHOT 7 | clj-ds 8 | http://github.com/krukow/clj-ds 9 | 10 | Port of Clojure's data structures to Java 11 | 12 | 13 | UTF-8 14 | 15 | 16 | 17 | org.sonatype.oss 18 | oss-parent 19 | 7 20 | 21 | 22 | 23 | 24 | Eclipse Public License - Version 1.0 25 | http://www.eclipse.org/legal/epl-v10.html 26 | repo 27 | 28 | 29 | 30 | 31 | scm:git:git://github.com/krukow/clj-ds.git 32 | scm:git:git@github.com:krukow/clj-ds.git 33 | http://github.com/krukow/tree/master 34 | 35 | 36 | 37 | 38 | 39 | sonatype-nexus-snapshots 40 | Sonatype Nexus Snapshots 41 | http://oss.sonatype.org/content/repositories/snapshots 42 | 43 | 44 | 45 | sonatype-nexus-staging 46 | Nexus Release Repository 47 | http://oss.sonatype.org/service/local/staging/deploy/maven2/ 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | junit 56 | junit 57 | 4.8.2 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-compiler-plugin 68 | 2.3.2 69 | 70 | 1.5 71 | 1.5 72 | 73 | 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-resources-plugin 78 | 2.5 79 | 80 | UTF-8 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-assembly-plugin 87 | 2.2.2 88 | 89 | gnu 90 | 91 | 92 | 93 | 94 | org.apache.maven.plugins 95 | maven-release-plugin 96 | 2.2.2 97 | 98 | forked-path 99 | 100 | 101 | 102 | 103 | org.apache.maven.plugins 104 | maven-javadoc-plugin 105 | 2.8 106 | 107 | 1.5 108 | 1.5 109 | UTF-8 110 | 1g 111 | 112 | http://java.sun.com/javase/6/docs/api/ 113 | 114 | 115 | 116 | 117 | attach-javadocs 118 | verify 119 | 120 | jar 121 | 122 | 123 | 124 | 125 | 126 | 127 | org.apache.maven.plugins 128 | maven-source-plugin 129 | 2.1.2 130 | 131 | true 132 | 133 | 134 | 135 | create-source-jar 136 | 137 | jar-no-fork 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | release-sign-artifacts 149 | 150 | 151 | performRelease 152 | true 153 | 154 | 155 | 156 | 157 | 158 | org.apache.maven.plugins 159 | maven-gpg-plugin 160 | 1.4 161 | 162 | 163 | sign-artifacts 164 | verify 165 | 166 | sign 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | krukow 179 | Karl Krukow 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/EditableCollection.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | /** 4 | * A {@link PersistentCollection} implementing this interface indicates that it 5 | * can produce a {@link TransientCollection} for efficient modifications. 6 | */ 7 | public interface EditableCollection { 8 | 9 | TransientCollection asTransient(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/Indexed.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | /** 4 | * This interface add indexed access to elements of a 5 | * {@link PersistentCollection}. "Random-access" runtime characteristics can be 6 | * expected for such collection. 7 | */ 8 | public interface Indexed { 9 | 10 | /** 11 | * @return The value at index i 12 | * @throws IndexOutOfBoundsException 13 | * If i is not in the bounds of the collection. 14 | */ 15 | E nth(int i); 16 | 17 | /** 18 | * @return The value at index i or the value notFound if i is not in the 19 | * bounds of the collection. This method nether throws an 20 | * {@link IndexOutOfBoundsException}. 21 | */ 22 | E nth(int i, E notFound); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentCollection.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import java.util.Collection; 4 | 5 | /** 6 | * The base interface for all persistent data structures. A persistent data 7 | * structure combines immutability with efficient runtime properties. For more 8 | * information read the Persistent Data 10 | * Structure article on Wikipedia. 11 | * 12 | * @param 13 | * The type of objects held in the collection. 14 | */ 15 | public interface PersistentCollection extends Collection { 16 | 17 | /** 18 | * @return An empty instance of this kind of collection. 19 | */ 20 | PersistentCollection zero(); 21 | 22 | /** 23 | * @return A new collection consisting of all elements of the current 24 | * collection together with the value val. 25 | */ 26 | PersistentCollection plus(E val); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentList.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * A persistent linked list. It implements the {@link List} interface without 7 | * the optional destructive operations. 8 | */ 9 | public interface PersistentList extends PersistentStack, List { 10 | 11 | PersistentList zero(); 12 | 13 | /** 14 | * @return A new {@link PersistentList} consisting of the value val followed 15 | * by the element of the current {@link PersistentList}. 16 | */ 17 | PersistentList plus(E val); 18 | 19 | /** 20 | * @return A new {@link PersistentList} consisting of the elements of the current 21 | * {@link PersistentList} without its first element. 22 | */ 23 | PersistentList minus(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentMap.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * {@link PersistentMap}s 7 | * 8 | * @param 9 | * The type of the keys 10 | * @param 11 | * The type of the values 12 | */ 13 | public interface PersistentMap extends Map { 14 | 15 | /** 16 | * @return An empty instance of this kind of {@link PersistentMap} 17 | */ 18 | PersistentMap zero(); 19 | 20 | /** 21 | * @return A new {@link PersistentMap} consisting of the content of the 22 | * current {@link PersistentMap} where the given key is associated 23 | * to the value val. The new association may replace a previous 24 | * association. 25 | */ 26 | PersistentMap plus(K key, V val); 27 | 28 | /** 29 | * @return A new {@link PersistentMap} consisting of the content of the 30 | * current {@link PersistentMap} where the given key is associated 31 | * to the value val. 32 | * @throws java.lang.RuntimeException 33 | * If the key is already present in the {@link PersistentMap}. 34 | */ 35 | PersistentMap plusEx(K key, V val); 36 | 37 | /** 38 | * @return A new {@link PersistentMap} consisting of the content of the 39 | * current {@link PersistentMap} without the assocation to the given 40 | * key. 41 | */ 42 | PersistentMap minus(K key); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentSet.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import java.util.Set; 4 | 5 | public interface PersistentSet extends PersistentCollection, Set, EditableCollection { 6 | 7 | PersistentSet zero(); 8 | 9 | PersistentSet plus(E val); 10 | 11 | /** 12 | * @return A new {@link PersistentSet} that consists of the elements of the 13 | * current {@link PersistentSet} without the value val. 14 | */ 15 | PersistentSet minus(E val); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentSortedMap.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import com.github.krukow.clj_lang.Sorted; 4 | 5 | public interface PersistentSortedMap extends PersistentMap, Sorted /* , SortedMap */{ 6 | 7 | PersistentSortedMap zero(); 8 | 9 | PersistentSortedMap plus(K key, V val); 10 | 11 | PersistentSortedMap plusEx(K key, V val); 12 | 13 | PersistentSortedMap minus(K key); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentSortedSet.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import com.github.krukow.clj_lang.Sorted; 4 | 5 | public interface PersistentSortedSet extends PersistentSet, Sorted /*, SortedSet */ { 6 | 7 | PersistentSortedSet zero(); 8 | 9 | PersistentSortedSet plus(E o); 10 | 11 | PersistentSortedSet minus(E key); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentStack.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | public interface PersistentStack extends PersistentCollection { 4 | 5 | PersistentStack zero(); 6 | 7 | PersistentStack plus(E o); 8 | 9 | /** 10 | * @return A new stack consisting of the current stack without its top 11 | * element. 12 | */ 13 | PersistentStack minus(); 14 | 15 | /** 16 | * @return The top element of this stack. 17 | */ 18 | E peek(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/PersistentVector.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * A {@link PersistentCollection} that has array-like runtime characteritics. 7 | * New elements are "added" at the end of the {@link PersistentVector}. 8 | */ 9 | public interface PersistentVector extends PersistentStack, List, Indexed, Comparable, EditableCollection { 10 | 11 | PersistentVector zero(); 12 | 13 | /** 14 | * @return A new {@link PersistentVector} consisting of the elements of the 15 | * current {@link PersistentVector} followed by the value val. 16 | */ 17 | PersistentVector plus(E val); 18 | 19 | /** 20 | * @return A new {@link PersistentVector} consisting of the elements of 21 | * current {@link PersistentVector} where the element at index i has 22 | * been replaced by the value val. 23 | * @throw {@link IndexOutOfBoundsException} if the index i is greater that 24 | * the current maximum index. 25 | */ 26 | PersistentVector plusN(int i, E val); 27 | 28 | /** 29 | * @return A new {@link PersistentVector} consisting of the elements of 30 | * the current {@link PersistentVector} without its last element. 31 | */ 32 | PersistentVector minus(); 33 | 34 | TransientVector asTransient(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/Persistents.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import java.util.Iterator; 4 | import java.util.Map; 5 | 6 | import com.github.krukow.clj_lang.PersistentArrayMap; 7 | import com.github.krukow.clj_lang.PersistentHashMap; 8 | import com.github.krukow.clj_lang.PersistentHashSet; 9 | import com.github.krukow.clj_lang.PersistentTreeMap; 10 | import com.github.krukow.clj_lang.PersistentTreeSet; 11 | 12 | public final class Persistents { 13 | 14 | // Factory Methods 15 | 16 | /** 17 | * @return An empty {@link PersistentVector}. 18 | */ 19 | public static PersistentVector vector() { 20 | return com.github.krukow.clj_lang.PersistentVector.emptyVector(); 21 | } 22 | 23 | /** 24 | * @return A singleton {@link PersistentVector} with the value val. 25 | */ 26 | public static PersistentVector vector(E val) { 27 | return Persistents. vector().plus(val); 28 | } 29 | 30 | /** 31 | * @return A {@link PersistentVector} consisting of the elements of the 32 | * array vals. 33 | */ 34 | public static PersistentVector vector(E... vals) { 35 | return com.github.krukow.clj_lang.PersistentVector.create(vals); 36 | } 37 | 38 | /** 39 | * @return A {@link PersistentVector} consisting of the elements of the 40 | * {@link Iterable} vals 41 | */ 42 | public static PersistentVector vector(Iterable vals) { 43 | return com.github.krukow.clj_lang.PersistentVector.create(vals); 44 | } 45 | 46 | /** 47 | * @return An empty {@link PersistentSet}; implemented as hash set. 48 | */ 49 | public static PersistentSet hashSet() { 50 | return PersistentHashSet.emptySet(); 51 | } 52 | 53 | /** 54 | * @return A singleton {@link PersistentSet} with the value val; implemented 55 | * as hash set. 56 | */ 57 | public static PersistentSet hashSet(E val) { 58 | return Persistents. hashSet().plus(val); 59 | } 60 | 61 | /** 62 | * @return A {@link PersistentSet} consisting of the elements of the array 63 | * vals; implemented as hash set. 64 | */ 65 | public static PersistentSet hashSet(E... vals) { 66 | return PersistentHashSet.create(vals); 67 | } 68 | 69 | /** 70 | * @return A {@link PersistentSet} consisting of the elements of the 71 | * {@link Iterable} vals; implemented as hash set. 72 | */ 73 | public static PersistentSet hashSet(Iterable vals) { 74 | return PersistentHashSet.create(vals); 75 | } 76 | 77 | /** 78 | * @return An empty {@link PersistentMap}; implemented as hash map. 79 | */ 80 | public static PersistentMap hashMap() { 81 | return PersistentHashMap.emptyMap(); 82 | } 83 | 84 | /** 85 | * @return A singleton {@link PersistentMap} associating the given key with 86 | * the given value; implemented as hash map. 87 | */ 88 | public static PersistentMap hashMap(K key, V val) { 89 | return Persistents. hashMap().plus(key, val); 90 | } 91 | 92 | /** 93 | * @param keyValues 94 | * An array containing key/value pairs; no type checking is made. 95 | * @return A {@link PersistentMap} with the given associations; implemented 96 | * as hash map. 97 | */ 98 | public static PersistentMap hashMap(Object... keyValues) { 99 | return PersistentHashMap.create(keyValues); 100 | } 101 | 102 | /** 103 | * @return A {@link PersistentMap} consisting of the associations of the map 104 | * init; implemented as hash map. 105 | */ 106 | public static PersistentMap hashMap(Map init) { 107 | return PersistentHashMap.create(init); 108 | } 109 | 110 | /** 111 | * @return An empty {@link PersistentMap}; implemented as array map. 112 | */ 113 | @SuppressWarnings("unchecked") 114 | public static PersistentMap arrayMap() { 115 | return PersistentArrayMap.EMPTY; 116 | } 117 | 118 | /** 119 | * @return A {@link PersistentMap} consisting of the associations of the map 120 | * init; implemented as array map. 121 | */ 122 | public static PersistentMap arrayMap(Map init) { 123 | return PersistentArrayMap.create(init); 124 | } 125 | 126 | /** 127 | * @return An empty {@link PersistentSortedMap}; implemented as a tree map. 128 | */ 129 | @SuppressWarnings("unchecked") 130 | public static PersistentSortedMap treeMap() { 131 | return PersistentTreeMap.EMPTY; 132 | } 133 | 134 | /** 135 | * @return A singleton {@link PersistentSortedMap} associating the given key 136 | * with the given value; implemented as tree map. 137 | */ 138 | public static PersistentSortedMap treeMap(K key, V val) { 139 | return Persistents. treeMap().plus(key, val); 140 | } 141 | 142 | /** 143 | * @return A {@link PersistentSortedMap} consisting of the associations of 144 | * the map init; implemented as tree map. 145 | */ 146 | public static PersistentSortedMap treeMap(Map init) { 147 | return PersistentTreeMap.create(init); 148 | } 149 | 150 | /** 151 | * @return An empty {@link PersistentSortedSet}; implemented as tree set. 152 | */ 153 | @SuppressWarnings("unchecked") 154 | public static PersistentSortedSet treeSet() { 155 | return PersistentTreeSet.EMPTY; 156 | } 157 | 158 | /** 159 | * @return An empty {@link PersistentList}; implemented as linked list. 160 | */ 161 | public static PersistentList linkedList() { 162 | return com.github.krukow.clj_lang.PersistentList.emptyList(); 163 | } 164 | 165 | /** 166 | * @return An singleton {@link PersistentList} with the value val; 167 | * implemented as linked list. 168 | */ 169 | public static PersistentList linkedList(E val) { 170 | return Persistents. linkedList().plus(val); 171 | } 172 | 173 | /** 174 | * @return A {@link PersistentList} consisting of the element of the array 175 | * vals; implemented as linked list. 176 | */ 177 | public static PersistentList linkedList(E... vals) { 178 | return com.github.krukow.clj_lang.PersistentList.create(vals); 179 | } 180 | 181 | /** 182 | * @return A {@link PersistentList} consisting of the element of the 183 | * {@link Iterator} vals; implemented as linked list. 184 | */ 185 | public static PersistentList linkedList(Iterable vals) { 186 | return com.github.krukow.clj_lang.PersistentList.create(vals); 187 | } 188 | 189 | // Utilities 190 | 191 | /** 192 | * Applies successively the method {@link PersistentList#plus(E)}. 193 | */ 194 | public static PersistentList plusAll(PersistentList list, Iterable others) { 195 | return com.github.krukow.clj_lang.PersistentList.consAll(list, others); 196 | } 197 | 198 | /** 199 | * Applies successively the method {@link PersistentList#plus(E)}. 200 | */ 201 | public static PersistentList plusAll(PersistentList list, E... others) { 202 | PersistentList result = list; 203 | for (E other : others) { 204 | result = result.plus(other); 205 | } 206 | return result; 207 | } 208 | 209 | /** 210 | * Applies successively the method {@link PersistentVector#plus(E)}. 211 | */ 212 | public static PersistentVector plusAll(PersistentVector vec, Iterable others) { 213 | TransientVector result = vec.asTransient(); 214 | for (E other : others) { 215 | result = result.plus(other); 216 | } 217 | return result.persist(); 218 | } 219 | 220 | /** 221 | * Applies successively the method {@link PersistentVector#plus(E)}. 222 | */ 223 | public static PersistentVector plusAll(PersistentVector vec, E... others) { 224 | TransientVector result = vec.asTransient(); 225 | for (E other : others) { 226 | result = result.plus(other); 227 | } 228 | return result.persist(); 229 | } 230 | 231 | /** 232 | * Applies successively the method {@link PersistentSet#plus(E)}. 233 | */ 234 | public static PersistentSet plusAll(PersistentSet set, Iterable others) { 235 | TransientSet result = (TransientSet) set.asTransient(); 236 | for (E other : others) { 237 | result = result.plus(other); 238 | } 239 | return result.persist(); 240 | } 241 | 242 | /** 243 | * Applies successively the method {@link PersistentSet#plus(E)}. 244 | */ 245 | public static PersistentSet plusAll(PersistentSet set, E... others) { 246 | TransientSet result = (TransientSet) set.asTransient(); 247 | for (E other : others) { 248 | result = result.plus(other); 249 | } 250 | return result.persist(); 251 | } 252 | 253 | /** 254 | * Applies successively the method {@link PersistentSet#minus(E)}. 255 | */ 256 | public static PersistentSet minusAll(PersistentSet set, Iterable others) { 257 | TransientSet result = (TransientSet) set.asTransient(); 258 | for (E other : others) { 259 | result = result.minus(other); 260 | } 261 | return result.persist(); 262 | } 263 | 264 | /** 265 | * Applies successively the method {@link PersistentSet#minus(E)}. 266 | */ 267 | public static PersistentSet minusAll(PersistentSet set, E... others) { 268 | TransientSet result = (TransientSet) set.asTransient(); 269 | for (E other : others) { 270 | result = result.minus(other); 271 | } 272 | return result.persist(); 273 | } 274 | 275 | /** 276 | * Applies successively the method {@link PersistentSortedSet#plus(E)}. 277 | */ 278 | public static PersistentSortedSet plusAll(PersistentSortedSet set, Iterable others) { 279 | PersistentSortedSet result = set; 280 | for (E other : others) { 281 | result = result.plus(other); 282 | } 283 | return result; 284 | } 285 | 286 | /** 287 | * Applies successively the method {@link PersistentSortedSet#plus(E)}. 288 | */ 289 | public static PersistentSortedSet plusAll(PersistentSortedSet set, E... others) { 290 | PersistentSortedSet result = set; 291 | for (E other : others) { 292 | result = result.plus(other); 293 | } 294 | return result; 295 | } 296 | 297 | /** 298 | * Applies successively the method {@link PersistentSortedSet#minus(E)}. 299 | */ 300 | public static PersistentSortedSet minusAll(PersistentSortedSet set, Iterable others) { 301 | PersistentSortedSet result = set; 302 | for (E other : others) { 303 | result = result.minus(other); 304 | } 305 | return result; 306 | } 307 | 308 | /** 309 | * Applies successively the method {@link PersistentSortedSet#minus(E)}. 310 | */ 311 | public static PersistentSortedSet minusAll(PersistentSortedSet set, E... others) { 312 | PersistentSortedSet result = set; 313 | for (E other : others) { 314 | result = result.minus(other); 315 | } 316 | return result; 317 | } 318 | 319 | // Empty Constructor 320 | private Persistents() { 321 | } 322 | 323 | } 324 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/TransientCollection.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | /** 4 | * A {@link TransientCollection} is a collection that does not retain older 5 | * versions in order to gain efficient modifications. To manipulate a 6 | * {@link TransientCollection}, one must still used the new values produced by 7 | * the "destructive" operations plus, minus, etc. However, no guarantees are 8 | * made on the previous values of the collection. 9 | */ 10 | public interface TransientCollection { 11 | 12 | /** 13 | * @return A new {@link TransientCollection} consisting of all the elements 14 | * of the current collection together with the value val (no 15 | * guarantees are made on the current collection). 16 | */ 17 | TransientCollection plus(E val); 18 | 19 | /** 20 | * @return A corresponding {@link PersistentCollection} consisting of the 21 | * elements of the current {@link TransientCollection}. 22 | */ 23 | PersistentCollection persist(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/TransientMap.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | public interface TransientMap { 4 | 5 | /** 6 | * @return A new {@link PersistentMap} consisting of the content of the 7 | * current {@link PersistentMap} where the given key is associated 8 | * to the value val (no guarantees are made on the current map). The 9 | * new association may replace a previous association. 10 | */ 11 | TransientMap plus(K key, V val); 12 | 13 | /** 14 | * @return A new {@link PersistentMap} consisting of the content of the 15 | * current {@link PersistentMap} without the association to the 16 | * given key (no guarantees are made on the current map). 17 | */ 18 | TransientMap minus(K key); 19 | 20 | PersistentMap persist(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/TransientSet.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | public interface TransientSet extends TransientCollection { 4 | 5 | TransientSet plus(E val); 6 | 7 | /** 8 | * @return A new {@link TransientSet} consisting of all the elements of the 9 | * current collection without the value val (no guarantees are made 10 | * on the current set). 11 | */ 12 | TransientSet minus(E val); 13 | 14 | PersistentSet persist(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/TransientVector.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | public interface TransientVector extends TransientCollection, Indexed { 4 | 5 | /** 6 | * @return A new {@link TransientVector} consisting of the elements of the 7 | * current {@link TransientVector} followed by the value val. (no 8 | * guarantees are made on the current collection). 9 | */ 10 | TransientVector plus(E val); 11 | 12 | /** 13 | * @return A new {@link TransientVector} consisting of the elements of 14 | * current {@link TransientSet} where the element at index i has 15 | * been replaced by the value val (no guarantees are made on the 16 | * current collection). 17 | * @throw {@link IndexOutOfBoundsException} if the index i is greater that 18 | * the current maximum index. 19 | */ 20 | TransientVector plusN(int i, E val); 21 | 22 | /** 23 | * @return A new {@link TransientVector} consisting of the elements of the 24 | * current collection together with its last element (no guarantees 25 | * are made on the current collection). 26 | */ 27 | TransientVector minus(); 28 | 29 | TransientVector pop(); 30 | 31 | PersistentVector persist(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_ds/Transients.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_ds; 2 | 3 | import com.github.krukow.clj_lang.PersistentArrayMap; 4 | import com.github.krukow.clj_lang.PersistentHashMap; 5 | import com.github.krukow.clj_lang.PersistentHashSet; 6 | import com.github.krukow.clj_lang.PersistentVector; 7 | 8 | public final class Transients { 9 | 10 | // Factory Methods 11 | 12 | public static final TransientVector transientVector() { 13 | return PersistentVector.emptyVector().asTransient(); 14 | } 15 | 16 | public static final TransientSet transientHashSet() { 17 | return PersistentHashSet.emptySet().asTransient(); 18 | } 19 | 20 | @SuppressWarnings("unchecked") 21 | public static final TransientMap transientHashMap() { 22 | return PersistentHashMap.emptyMap().asTransient(); 23 | } 24 | 25 | @SuppressWarnings("unchecked") 26 | public static final TransientMap transientArrayMap() { 27 | return PersistentArrayMap.EMPTY.asTransient(); 28 | } 29 | 30 | // Utilities 31 | 32 | public static TransientVector plusAll(TransientVector vec, Iterable others) { 33 | TransientVector tv = vec; 34 | for (E other : others) { 35 | tv = tv.plus(other); 36 | } 37 | return tv; 38 | } 39 | 40 | public static TransientVector plusAll(TransientVector vec, E... others) { 41 | TransientVector tv = vec; 42 | for (E other : others) { 43 | tv = tv.plus(other); 44 | } 45 | return tv; 46 | } 47 | 48 | public static TransientSet plusAll(TransientSet set, Iterable others) { 49 | TransientSet tv = set; 50 | for (E other : others) { 51 | tv = tv.plus(other); 52 | } 53 | return tv; 54 | } 55 | 56 | public static TransientSet plusAll(TransientSet set, E... others) { 57 | TransientSet tv = set; 58 | for (E other : others) { 59 | tv = tv.plus(other); 60 | } 61 | return tv; 62 | } 63 | 64 | public static TransientSet minusAll(TransientSet set, Iterable others) { 65 | TransientSet tv = set; 66 | for (E other : others) { 67 | tv = tv.minus(other); 68 | } 69 | return tv; 70 | } 71 | 72 | private Transients() { 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/AFunction.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Dec 16, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.io.Serializable; 16 | import java.util.Comparator; 17 | 18 | public abstract class AFunction extends AFn implements IObj, Comparator, Fn, Serializable { 19 | 20 | public IPersistentMap meta(){ 21 | return null; 22 | } 23 | 24 | public IObj withMeta(final IPersistentMap meta){ 25 | return new RestFn(){ 26 | protected Object doInvoke(Object args) { 27 | return AFunction.this.applyTo((ISeq) args); 28 | } 29 | 30 | public IPersistentMap meta(){ 31 | return meta; 32 | } 33 | 34 | public IObj withMeta(IPersistentMap meta){ 35 | return AFunction.this.withMeta(meta); 36 | } 37 | 38 | public int getRequiredArity(){ 39 | return 0; 40 | } 41 | }; 42 | } 43 | 44 | public int compare(Object o1, Object o2){ 45 | try 46 | { 47 | Object o = invoke(o1, o2); 48 | 49 | if(o instanceof Boolean) 50 | { 51 | if(RT.booleanCast(o)) 52 | return -1; 53 | return RT.booleanCast(invoke(o2,o1))? 1 : 0; 54 | } 55 | 56 | Number n = (Number) o; 57 | return n.intValue(); 58 | } 59 | catch(Exception e) 60 | { 61 | throw Util.sneakyThrow(e); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/AMapEntry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 1, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | 16 | public abstract class AMapEntry extends APersistentVector implements IMapEntry{ 17 | 18 | public Object nth(int i){ 19 | if(i == 0) 20 | return key(); 21 | else if(i == 1) 22 | return val(); 23 | else 24 | throw new IndexOutOfBoundsException(); 25 | } 26 | 27 | private IPersistentVector asVector(){ 28 | return LazilyPersistentVector.createOwning(key(), val()); 29 | } 30 | 31 | public IPersistentVector assocN(int i, Object val){ 32 | return asVector().assocN(i, val); 33 | } 34 | 35 | public int count(){ 36 | return 2; 37 | } 38 | 39 | public ISeq seq(){ 40 | return asVector().seq(); 41 | } 42 | 43 | public IPersistentVector cons(Object o){ 44 | return asVector().cons(o); 45 | } 46 | 47 | public IPersistentCollection empty(){ 48 | return null; 49 | } 50 | 51 | public IPersistentStack pop(){ 52 | return LazilyPersistentVector.createOwning(key()); 53 | } 54 | 55 | public Object setValue(Object value){ 56 | throw new UnsupportedOperationException(); 57 | } 58 | 59 | /* 60 | 61 | public boolean equals(Object obj){ 62 | return APersistentVector.doEquals(this, obj); 63 | } 64 | 65 | public int hashCode(){ 66 | //must match logic in APersistentVector 67 | return 31 * (31 + Util.hash(key())) + Util.hash(val()); 68 | // return Util.hashCombine(Util.hashCombine(0, Util.hash(key())), Util.hash(val())); 69 | } 70 | 71 | public String toString(){ 72 | StringWriter sw = new StringWriter(); 73 | try 74 | { 75 | RT.print(this, sw); 76 | } 77 | catch(Exception e) 78 | { 79 | //checked exceptions stink! 80 | throw Util.sneakyThrow(e); 81 | } 82 | return sw.toString(); 83 | } 84 | 85 | public int length(){ 86 | return 2; 87 | } 88 | 89 | public Object nth(int i){ 90 | if(i == 0) 91 | return key(); 92 | else if(i == 1) 93 | return val(); 94 | else 95 | throw new IndexOutOfBoundsException(); 96 | } 97 | 98 | private IPersistentVector asVector(){ 99 | return LazilyPersistentVector.createOwning(key(), val()); 100 | } 101 | 102 | public IPersistentVector assocN(int i, Object val){ 103 | return asVector().assocN(i, val); 104 | } 105 | 106 | public int count(){ 107 | return 2; 108 | } 109 | 110 | public ISeq seq(){ 111 | return asVector().seq(); 112 | } 113 | 114 | public IPersistentVector cons(Object o){ 115 | return asVector().cons(o); 116 | } 117 | 118 | public boolean containsKey(Object key){ 119 | return asVector().containsKey(key); 120 | } 121 | 122 | public IMapEntry entryAt(Object key){ 123 | return asVector().entryAt(key); 124 | } 125 | 126 | public Associative assoc(Object key, Object val){ 127 | return asVector().assoc(key, val); 128 | } 129 | 130 | public Object valAt(Object key){ 131 | return asVector().valAt(key); 132 | } 133 | 134 | public Object valAt(Object key, Object notFound){ 135 | return asVector().valAt(key, notFound); 136 | } 137 | 138 | public Object peek(){ 139 | return val(); 140 | } 141 | 142 | 143 | public ISeq rseq() { 144 | return asVector().rseq(); 145 | } 146 | */ 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/APersistentMap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.io.Serializable; 14 | import java.util.AbstractCollection; 15 | import java.util.AbstractSet; 16 | import java.util.Collection; 17 | import java.util.Iterator; 18 | import java.util.Map; 19 | import java.util.Set; 20 | 21 | public abstract class APersistentMap extends AFn implements IPersistentMap, Map, Iterable>, Serializable, IHashEq { 22 | int _hash = -1; 23 | int _hasheq = -1; 24 | 25 | public String toString(){ 26 | return RT.printString(this); 27 | } 28 | 29 | public IPersistentCollection cons(IMapEntry o){ 30 | return assoc(o.getKey(), o.getValue()); 31 | } 32 | 33 | public boolean equals(Object obj){ 34 | if(this == obj) return true; 35 | if(!(obj instanceof Map)) 36 | return false; 37 | Map m = (Map) obj; 38 | 39 | if(m.size() != size()) 40 | return false; 41 | 42 | for(ISeq s = seq(); s != null; s = s.next()) 43 | { 44 | Map.Entry e = (Map.Entry) s.first(); 45 | boolean found = m.containsKey(e.getKey()); 46 | 47 | if(!found || !Util.equals(e.getValue(), m.get(e.getKey()))) 48 | return false; 49 | } 50 | 51 | return true; 52 | } 53 | 54 | public boolean equiv(Object obj){ 55 | if(!(obj instanceof Map)) 56 | return false; 57 | Map m = (Map) obj; 58 | 59 | if(m.size() != size()) 60 | return false; 61 | 62 | for(ISeq s = seq(); s != null; s = s.next()) 63 | { 64 | Map.Entry e = (Map.Entry) s.first(); 65 | boolean found = m.containsKey(e.getKey()); 66 | 67 | if(!found || !Util.equiv(e.getValue(), m.get(e.getKey()))) 68 | return false; 69 | } 70 | 71 | return true; 72 | } 73 | public int hashCode(){ 74 | if(_hash == -1) 75 | { 76 | int hash = 0; 77 | for(ISeq s = seq(); s != null; s = s.next()) 78 | { 79 | Map.Entry e = (Map.Entry) s.first(); 80 | hash += (e.getKey() == null ? 0 : e.getKey().hashCode()) ^ 81 | (e.getValue() == null ? 0 : e.getValue().hashCode()); 82 | } 83 | this._hash = hash; 84 | } 85 | return _hash; 86 | } 87 | 88 | public int hasheq(){ 89 | if(_hasheq == -1) 90 | { 91 | int hash = 0; 92 | for(ISeq s = seq(); s != null; s = s.next()) 93 | { 94 | Map.Entry e = (Map.Entry) s.first(); 95 | hash += Util.hasheq(e.getKey()) ^ 96 | Util.hasheq(e.getValue()); 97 | } 98 | this._hasheq = hash; 99 | } 100 | return _hasheq; 101 | } 102 | 103 | static public class KeySeq extends ASeq{ 104 | ISeq seq; 105 | 106 | static public KeySeq create(ISeq seq){ 107 | if(seq == null) 108 | return null; 109 | return new KeySeq(seq); 110 | } 111 | 112 | private KeySeq(ISeq seq){ 113 | this.seq = seq; 114 | } 115 | 116 | private KeySeq(IPersistentMap meta, ISeq seq){ 117 | super(meta); 118 | this.seq = seq; 119 | } 120 | 121 | public Object first(){ 122 | return ((Map.Entry) seq.first()).getKey(); 123 | } 124 | 125 | public ISeq next(){ 126 | return create(seq.next()); 127 | } 128 | 129 | public KeySeq withMeta(IPersistentMap meta){ 130 | return new KeySeq(meta, seq); 131 | } 132 | } 133 | 134 | static public class ValSeq extends ASeq{ 135 | ISeq seq; 136 | 137 | static public ValSeq create(ISeq seq){ 138 | if(seq == null) 139 | return null; 140 | return new ValSeq(seq); 141 | } 142 | 143 | private ValSeq(ISeq seq){ 144 | this.seq = seq; 145 | } 146 | 147 | private ValSeq(IPersistentMap meta, ISeq seq){ 148 | super(meta); 149 | this.seq = seq; 150 | } 151 | 152 | public Object first(){ 153 | return ((Map.Entry) seq.first()).getValue(); 154 | } 155 | 156 | public ISeq next(){ 157 | return create(seq.next()); 158 | } 159 | 160 | public ValSeq withMeta(IPersistentMap meta){ 161 | return new ValSeq(meta, seq); 162 | } 163 | } 164 | 165 | 166 | public Object invoke(Object arg1) { 167 | return valAt((K) arg1); 168 | } 169 | 170 | public Object invoke(Object arg1, Object notFound) { 171 | return valAt((K) arg1, (V) notFound); 172 | } 173 | 174 | // java.util.Map implementation 175 | 176 | public void clear(){ 177 | throw new UnsupportedOperationException(); 178 | } 179 | 180 | public boolean containsValue(Object value){ 181 | return values().contains(value); 182 | } 183 | 184 | public Set> entrySet(){ 185 | return new AbstractSet>(){ 186 | 187 | public Iterator> iterator(){ 188 | return APersistentMap.this.iterator(); 189 | } 190 | 191 | public int size(){ 192 | return count(); 193 | } 194 | 195 | public int hashCode(){ 196 | return APersistentMap.this.hashCode(); 197 | } 198 | 199 | public boolean contains(Object o){ 200 | if(o instanceof Entry) 201 | { 202 | Entry e = (Entry) o; 203 | Entry found = entryAt((K) e.getKey()); 204 | if(found != null && Util.equals(found.getValue(), e.getValue())) 205 | return true; 206 | } 207 | return false; 208 | } 209 | }; 210 | } 211 | 212 | public V get(Object key){ 213 | return valAt((K) key); 214 | } 215 | 216 | public boolean isEmpty(){ 217 | return count() == 0; 218 | } 219 | 220 | public Set keySet(){ 221 | return new AbstractSet(){ 222 | 223 | public Iterator iterator(){ 224 | final Iterator> mi = APersistentMap.this.iterator(); 225 | 226 | return new Iterator(){ 227 | 228 | 229 | public boolean hasNext(){ 230 | return mi.hasNext(); 231 | } 232 | 233 | public K next(){ 234 | Entry e = (Entry) mi.next(); 235 | return e.getKey(); 236 | } 237 | 238 | public void remove(){ 239 | throw new UnsupportedOperationException(); 240 | } 241 | }; 242 | } 243 | 244 | public int size(){ 245 | return count(); 246 | } 247 | 248 | public boolean contains(Object o){ 249 | return APersistentMap.this.containsKey(o); 250 | } 251 | }; 252 | } 253 | 254 | public V put(K key, V value){ 255 | throw new UnsupportedOperationException(); 256 | } 257 | 258 | public void putAll(Map t){ 259 | throw new UnsupportedOperationException(); 260 | } 261 | 262 | public V remove(Object key){ 263 | throw new UnsupportedOperationException(); 264 | } 265 | 266 | public int size(){ 267 | return count(); 268 | } 269 | 270 | public Collection values(){ 271 | return new AbstractCollection(){ 272 | 273 | public Iterator iterator(){ 274 | final Iterator> mi = APersistentMap.this.iterator(); 275 | 276 | return new Iterator(){ 277 | 278 | 279 | public boolean hasNext(){ 280 | return mi.hasNext(); 281 | } 282 | 283 | public V next(){ 284 | return mi.next().getValue(); 285 | } 286 | 287 | public void remove(){ 288 | throw new UnsupportedOperationException(); 289 | } 290 | }; 291 | } 292 | 293 | public int size(){ 294 | return count(); 295 | } 296 | }; 297 | } 298 | 299 | /* 300 | // java.util.Collection implementation 301 | 302 | public Object[] toArray(){ 303 | return RT.seqToArray(seq()); 304 | } 305 | 306 | public boolean add(Object o){ 307 | throw new UnsupportedOperationException(); 308 | } 309 | 310 | public boolean remove(Object o){ 311 | throw new UnsupportedOperationException(); 312 | } 313 | 314 | public boolean addAll(Collection c){ 315 | throw new UnsupportedOperationException(); 316 | } 317 | 318 | public void clear(){ 319 | throw new UnsupportedOperationException(); 320 | } 321 | 322 | public boolean retainAll(Collection c){ 323 | throw new UnsupportedOperationException(); 324 | } 325 | 326 | public boolean removeAll(Collection c){ 327 | throw new UnsupportedOperationException(); 328 | } 329 | 330 | public boolean containsAll(Collection c){ 331 | for(Object o : c) 332 | { 333 | if(!contains(o)) 334 | return false; 335 | } 336 | return true; 337 | } 338 | 339 | public Object[] toArray(Object[] a){ 340 | if(a.length >= count()) 341 | { 342 | ISeq s = seq(); 343 | for(int i = 0; s != null; ++i, s = s.rest()) 344 | { 345 | a[i] = s.first(); 346 | } 347 | if(a.length > count()) 348 | a[count()] = null; 349 | return a; 350 | } 351 | else 352 | return toArray(); 353 | } 354 | 355 | public int size(){ 356 | return count(); 357 | } 358 | 359 | public boolean isEmpty(){ 360 | return count() == 0; 361 | } 362 | 363 | public boolean contains(Object o){ 364 | if(o instanceof Map.Entry) 365 | { 366 | Map.Entry e = (Map.Entry) o; 367 | Map.Entry v = entryAt(e.getKey()); 368 | return (v != null && Util.equal(v.getValue(), e.getValue())); 369 | } 370 | return false; 371 | } 372 | */ 373 | } 374 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/APersistentSet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.io.Serializable; 16 | import java.util.Collection; 17 | import java.util.Iterator; 18 | import java.util.Set; 19 | 20 | public abstract class APersistentSet extends AFn implements IPersistentSet, Collection, Set, Serializable, IHashEq { 21 | int _hash = -1; 22 | int _hasheq = -1; 23 | final IPersistentMap impl; 24 | 25 | protected APersistentSet(IPersistentMap impl){ 26 | this.impl = impl; 27 | } 28 | 29 | public String toString(){ 30 | return RT.printString(this); 31 | } 32 | 33 | public boolean contains(Object key){ 34 | return impl.containsKey(key); 35 | } 36 | 37 | public Boolean get(T key){ 38 | return (Boolean) impl.valAt(key); 39 | } 40 | 41 | public int count(){ 42 | return impl.count(); 43 | } 44 | 45 | public ISeq seq(){ 46 | return RT.keys(impl); 47 | } 48 | 49 | public Object invoke(Object arg1) { 50 | return get((T) arg1); 51 | } 52 | 53 | public boolean equals(Object obj){ 54 | if(this == obj) return true; 55 | if(!(obj instanceof Set)) 56 | return false; 57 | Set m = (Set) obj; 58 | 59 | if(m.size() != count()) 60 | return false; 61 | 62 | for(Object aM : m) 63 | { 64 | if(!contains(aM)) 65 | return false; 66 | } 67 | 68 | return true; 69 | } 70 | 71 | public boolean equiv(Object o){ 72 | return equals(o); 73 | } 74 | 75 | public int hashCode(){ 76 | if(_hash == -1) 77 | { 78 | //int hash = count(); 79 | int hash = 0; 80 | for(ISeq s = seq(); s != null; s = s.next()) 81 | { 82 | Object e = s.first(); 83 | // hash = Util.hashCombine(hash, Util.hash(e)); 84 | hash += Util.hash(e); 85 | } 86 | this._hash = hash; 87 | } 88 | return _hash; 89 | } 90 | 91 | public int hasheq(){ 92 | if(_hasheq == -1){ 93 | int hash = 0; 94 | for(ISeq s = seq(); s != null; s = s.next()) 95 | { 96 | Object e = s.first(); 97 | hash += Util.hasheq(e); 98 | } 99 | this._hasheq = hash; 100 | } 101 | return _hasheq; 102 | } 103 | 104 | public Object[] toArray(){ 105 | return RT.seqToArray(seq()); 106 | } 107 | 108 | public boolean add(Object o){ 109 | throw new UnsupportedOperationException(); 110 | } 111 | 112 | public boolean remove(Object o){ 113 | throw new UnsupportedOperationException(); 114 | } 115 | 116 | public boolean addAll(Collection c){ 117 | throw new UnsupportedOperationException(); 118 | } 119 | 120 | public void clear(){ 121 | throw new UnsupportedOperationException(); 122 | } 123 | 124 | public boolean retainAll(Collection c){ 125 | throw new UnsupportedOperationException(); 126 | } 127 | 128 | public boolean removeAll(Collection c){ 129 | throw new UnsupportedOperationException(); 130 | } 131 | 132 | public boolean containsAll(Collection c){ 133 | for(Object o : c) 134 | { 135 | if(!contains(o)) 136 | return false; 137 | } 138 | return true; 139 | } 140 | 141 | public Object[] toArray(Object[] a){ 142 | return RT.seqToPassedArray(seq(), a); 143 | } 144 | 145 | public int size(){ 146 | return count(); 147 | } 148 | 149 | public boolean isEmpty(){ 150 | return count() == 0; 151 | } 152 | 153 | public Iterator iterator(){ 154 | return new SeqIterator(seq()); 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/APersistentTrie.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.io.Serializable; 16 | import java.util.Collection; 17 | import java.util.Iterator; 18 | import java.util.Map; 19 | import java.util.Set; 20 | 21 | @SuppressWarnings({ "rawtypes", "serial" }) 22 | public abstract class APersistentTrie extends AFn implements IPersistentTrie, 23 | IPersistentSet, Collection>, Set>, Serializable { 24 | int _hash = -1; 25 | 26 | public Object invoke(Object arg1) { 27 | return get((String) arg1); 28 | } 29 | 30 | public boolean equals(Object obj){ 31 | if(this == obj) return true; 32 | if(!(obj instanceof Set)) 33 | return false; 34 | Set m = (Set) obj; 35 | 36 | if(m.size() != count() || m.hashCode() != hashCode()) 37 | return false; 38 | 39 | for(Object aM : m) 40 | { 41 | if(!contains(aM)) 42 | return false; 43 | } 44 | // for(ISeq s = seq(); s != null; s = s.rest()) 45 | // { 46 | // if(!m.contains(s.first())) 47 | // return false; 48 | // } 49 | 50 | return true; 51 | } 52 | 53 | public boolean equiv(Object o){ 54 | return equals(o); 55 | } 56 | 57 | public int hashCode(){ 58 | if(_hash == -1) 59 | { 60 | int hash = 0; 61 | for(ISeq s = seq(); s != null; s = s.next()) 62 | { 63 | Object e = s.first(); 64 | hash += Util.hash(e); 65 | } 66 | this._hash = hash; 67 | } 68 | return _hash; 69 | } 70 | 71 | public Object[] toArray(){ 72 | return RT.seqToArray(seq()); 73 | } 74 | 75 | public Object[] toArray(Object[] a){ 76 | if(a.length >= count()) 77 | { 78 | ISeq s = seq(); 79 | for(int i = 0; s != null; ++i, s = s.next()) 80 | { 81 | a[i] = s.first(); 82 | } 83 | if(a.length > count()) 84 | a[count()] = null; 85 | return a; 86 | } 87 | else 88 | return toArray(); 89 | } 90 | 91 | public int size(){ 92 | return count(); 93 | } 94 | 95 | public boolean isEmpty(){ 96 | return count() == 0; 97 | } 98 | 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ASeq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.io.Serializable; 14 | import java.util.*; 15 | 16 | public abstract class ASeq extends Obj implements ISeq, Sequential, List, Serializable, IHashEq { 17 | transient int _hash = -1; 18 | transient int _hasheq = -1; 19 | 20 | public String toString(){ 21 | return RT.printString(this); 22 | } 23 | 24 | @Override 25 | public IPersistentCollection empty() { 26 | return PersistentList.emptyList(); 27 | } 28 | 29 | 30 | protected ASeq(IPersistentMap meta){ 31 | super(meta); 32 | } 33 | 34 | 35 | protected ASeq(){ 36 | } 37 | 38 | public boolean equiv(Object obj){ 39 | 40 | if(!(obj instanceof Sequential || obj instanceof List)) 41 | return false; 42 | ISeq ms = RT.seq(obj); 43 | for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next()) 44 | { 45 | if(ms == null || !Util.equiv(s.first(), ms.first())) 46 | return false; 47 | } 48 | return ms == null; 49 | 50 | } 51 | 52 | public boolean equals(Object obj){ 53 | if(this == obj) return true; 54 | if(!(obj instanceof Sequential || obj instanceof List)) 55 | return false; 56 | ISeq ms = RT.seq(obj); 57 | for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next()) 58 | { 59 | if(ms == null || !Util.equals(s.first(), ms.first())) 60 | return false; 61 | } 62 | return ms == null; 63 | 64 | } 65 | 66 | public int hashCode(){ 67 | if(_hash == -1) 68 | { 69 | int hash = 1; 70 | for(ISeq s = seq(); s != null; s = s.next()) 71 | { 72 | hash = 31 * hash + (s.first() == null ? 0 : s.first().hashCode()); 73 | } 74 | this._hash = hash; 75 | } 76 | return _hash; 77 | } 78 | 79 | public int hasheq(){ 80 | if(_hasheq == -1) 81 | { 82 | int hash = 1; 83 | for(ISeq s = seq(); s != null; s = s.next()) 84 | { 85 | hash = 31 * hash + Util.hasheq(s.first()); 86 | } 87 | this._hasheq = hash; 88 | } 89 | return _hasheq; 90 | } 91 | 92 | //public Object reduce(IFn f) { 93 | // Object ret = first(); 94 | // for(ISeq s = rest(); s != null; s = s.rest()) 95 | // ret = f.invoke(ret, s.first()); 96 | // return ret; 97 | //} 98 | // 99 | //public Object reduce(IFn f, Object start) { 100 | // Object ret = f.invoke(start, first()); 101 | // for(ISeq s = rest(); s != null; s = s.rest()) 102 | // ret = f.invoke(ret, s.first()); 103 | // return ret; 104 | //} 105 | 106 | //public Object peek(){ 107 | // return first(); 108 | //} 109 | // 110 | //public IPersistentList pop(){ 111 | // return rest(); 112 | //} 113 | 114 | public int count(){ 115 | int i = 1; 116 | for(ISeq s = next(); s != null; s = s.next(), i++) 117 | if(s instanceof Counted) 118 | return i + s.count(); 119 | return i; 120 | } 121 | 122 | final public ISeq seq(){ 123 | return this; 124 | } 125 | 126 | public ISeq cons(T o){ 127 | return new Cons(o, this); 128 | } 129 | 130 | public ISeq more(){ 131 | ISeq s = next(); 132 | if(s == null) 133 | return (ISeq) PersistentList.emptyList(); 134 | return s; 135 | } 136 | 137 | //final public ISeq rest(){ 138 | // Seqable m = more(); 139 | // if(m == null) 140 | // return null; 141 | // return m.seq(); 142 | //} 143 | 144 | // java.util.Collection implementation 145 | 146 | public Object[] toArray(){ 147 | return RT.seqToArray(seq()); 148 | } 149 | 150 | public boolean add(T o){ 151 | throw new UnsupportedOperationException(); 152 | } 153 | 154 | public boolean remove(Object o){ 155 | throw new UnsupportedOperationException(); 156 | } 157 | 158 | public boolean addAll(Collection c){ 159 | throw new UnsupportedOperationException(); 160 | } 161 | 162 | public void clear(){ 163 | throw new UnsupportedOperationException(); 164 | } 165 | 166 | public boolean retainAll(Collection c){ 167 | throw new UnsupportedOperationException(); 168 | } 169 | 170 | public boolean removeAll(Collection c){ 171 | throw new UnsupportedOperationException(); 172 | } 173 | 174 | public boolean containsAll(Collection c){ 175 | for(Object o : c) 176 | { 177 | if(!contains(o)) 178 | return false; 179 | } 180 | return true; 181 | } 182 | 183 | public Object[] toArray(Object[] a){ 184 | return RT.seqToPassedArray(seq(), a); 185 | } 186 | 187 | public int size(){ 188 | return count(); 189 | } 190 | 191 | public boolean isEmpty(){ 192 | return seq() == null; 193 | } 194 | 195 | public boolean contains(Object o){ 196 | for(ISeq s = seq(); s != null; s = s.next()) 197 | { 198 | if(Util.equiv(s.first(), o)) 199 | return true; 200 | } 201 | return false; 202 | } 203 | 204 | 205 | public Iterator iterator(){ 206 | return new SeqIterator(this); 207 | } 208 | 209 | 210 | 211 | //////////// List stuff ///////////////// 212 | private List reify(){ 213 | return Collections.unmodifiableList(new ArrayList(this)); 214 | } 215 | 216 | public List subList(int fromIndex, int toIndex){ 217 | return reify().subList(fromIndex, toIndex); 218 | } 219 | 220 | public T set(int index, T element){ 221 | throw new UnsupportedOperationException(); 222 | } 223 | 224 | public T remove(int index){ 225 | throw new UnsupportedOperationException(); 226 | } 227 | 228 | public int indexOf(Object o){ 229 | ISeq s = seq(); 230 | for(int i = 0; s != null; s = s.next(), i++) 231 | { 232 | if(Util.equiv(s.first(), o)) 233 | return i; 234 | } 235 | return -1; 236 | } 237 | 238 | public int lastIndexOf(Object o){ 239 | return reify().lastIndexOf(o); 240 | } 241 | 242 | public ListIterator listIterator(){ 243 | return reify().listIterator(); 244 | } 245 | 246 | public ListIterator listIterator(int index){ 247 | return reify().listIterator(index); 248 | } 249 | 250 | public T get(int index){ 251 | return (T) RT.nth(this, index); 252 | } 253 | 254 | public void add(int index, T element){ 255 | throw new UnsupportedOperationException(); 256 | } 257 | 258 | public boolean addAll(int index, Collection c){ 259 | throw new UnsupportedOperationException(); 260 | } 261 | 262 | } 263 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ATransientMap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.util.Map; 14 | 15 | 16 | abstract class ATransientMap extends AFn implements ITransientMap { 17 | abstract void ensureEditable(); 18 | abstract ITransientMap doAssoc(K key, V val); 19 | abstract ITransientMap doWithout(K key); 20 | abstract V doValAt(K key, V notFound); 21 | abstract int doCount(); 22 | abstract IPersistentMap doPersistent(); 23 | 24 | public ITransientMap conj(Map.Entry o) { 25 | ensureEditable(); 26 | return assoc(o.getKey(), o.getValue()); 27 | } 28 | 29 | public final Object invoke(Object arg1) { 30 | return valAt((K) arg1); 31 | } 32 | 33 | public final Object invoke(Object arg1, Object notFound) { 34 | return valAt((K)arg1, (V) notFound); 35 | } 36 | 37 | public final V valAt(K key) { 38 | return valAt(key, null); 39 | } 40 | 41 | public final ITransientMap assoc(K key, V val) { 42 | ensureEditable(); 43 | return doAssoc(key, val); 44 | } 45 | 46 | public final ITransientMap without(K key) { 47 | ensureEditable(); 48 | return doWithout(key); 49 | } 50 | 51 | public final IPersistentMap persistentMap() { 52 | ensureEditable(); 53 | return doPersistent(); 54 | } 55 | 56 | public final V valAt(K key, V notFound) { 57 | ensureEditable(); 58 | return doValAt(key, notFound); 59 | } 60 | 61 | public final int count() { 62 | ensureEditable(); 63 | return doCount(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ATransientSet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | 16 | public abstract class ATransientSet extends AFn implements ITransientSet { 17 | ITransientMap impl; 18 | 19 | ATransientSet(ITransientMap impl) { 20 | this.impl = impl; 21 | } 22 | 23 | public int count() { 24 | return impl.count(); 25 | } 26 | 27 | public ITransientSet conj(T val) { 28 | ITransientMap m = impl.assoc(val, val); 29 | if (m != impl) this.impl = m; 30 | return this; 31 | } 32 | 33 | public boolean contains(T key) { 34 | return this != impl.valAt(key, this); 35 | } 36 | 37 | public ITransientSet disjoin(T key) { 38 | ITransientMap m = impl.without(key); 39 | if (m != impl) this.impl = m; 40 | return this; 41 | } 42 | 43 | public Boolean get(T key) { 44 | return (Boolean) impl.valAt(key); 45 | } 46 | 47 | public Object invoke(Object key, Object notFound) { 48 | return impl.valAt(key, notFound); 49 | } 50 | 51 | public Object invoke(Object key) { 52 | return impl.valAt(key); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ArityException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | /** 14 | * @since 1.3 15 | */ 16 | public class ArityException extends IllegalArgumentException { 17 | 18 | final public int actual; 19 | 20 | final public String name; 21 | 22 | public ArityException(int actual, String name) { 23 | this(actual, name, null); 24 | } 25 | 26 | public ArityException(int actual, String name, Throwable cause) { 27 | super("Wrong number of args (" + actual + ") passed to: " + name, cause); 28 | this.actual = actual; 29 | this.name = name; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ArrayChunk.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich May 24, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.io.Serializable; 16 | 17 | public final class ArrayChunk implements IChunk, Serializable { 18 | 19 | final Object[] array; 20 | final int off; 21 | final int end; 22 | 23 | public ArrayChunk(Object[] array){ 24 | this(array, 0, array.length); 25 | } 26 | 27 | public ArrayChunk(Object[] array, int off){ 28 | this(array, off, array.length); 29 | } 30 | 31 | public ArrayChunk(Object[] array, int off, int end){ 32 | this.array = array; 33 | this.off = off; 34 | this.end = end; 35 | } 36 | 37 | public T nth(int i){ 38 | return (T) array[off + i]; 39 | } 40 | 41 | public T nth(int i, T notFound){ 42 | if(i >= 0 && i < count()) 43 | return nth(i); 44 | return notFound; 45 | } 46 | 47 | public int count(){ 48 | return end - off; 49 | } 50 | 51 | public IChunk dropFirst(){ 52 | if(off==end) 53 | throw new IllegalStateException("dropFirst of empty chunk"); 54 | return new ArrayChunk(array, off + 1, end); 55 | } 56 | 57 | public Object reduce(IFn f, Object start) { 58 | Object ret = f.invoke(start, array[off]); 59 | if(RT.isReduced(ret)) 60 | return ret; 61 | for(int x = off + 1; x < end; x++) 62 | { 63 | ret = f.invoke(ret, array[x]); 64 | if(RT.isReduced(ret)) 65 | return ret; 66 | } 67 | return ret; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Associative.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | 4 | /** 5 | * Copyright (c) Rich Hickey. All rights reserved. 6 | * The use and distribution terms for this software are covered by the 7 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 8 | * which can be found in the file epl-v10.html at the root of this distribution. 9 | * By using this software in any fashion, you are agreeing to be bound by 10 | * the terms of this license. 11 | * You must not remove this notice, or any other, from this software. 12 | */ 13 | public interface Associative extends IPersistentCollection>, ILookup{ 14 | boolean containsKey(K key); 15 | 16 | IMapEntry entryAt(K key); 17 | 18 | Associative assoc(K key, V val); 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/BigInt.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* chouser Jun 23, 2010 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.math.BigInteger; 16 | import java.math.BigDecimal; 17 | 18 | public final class BigInt extends Number{ 19 | 20 | final public long lpart; 21 | final public BigInteger bipart; 22 | 23 | final public static BigInt ZERO = new BigInt(0,null); 24 | final public static BigInt ONE = new BigInt(1,null); 25 | 26 | 27 | //must follow Long 28 | public int hashCode(){ 29 | if(bipart == null) 30 | return (int) (this.lpart ^ (this.lpart >>> 32)); 31 | return bipart.hashCode(); 32 | } 33 | 34 | public boolean equals(Object obj){ 35 | if(this == obj) 36 | return true; 37 | if(obj instanceof BigInt) 38 | { 39 | BigInt o = (BigInt) obj; 40 | if(bipart == null) 41 | return o.bipart == null && this.lpart == o.lpart; 42 | return o.bipart != null && this.bipart.equals(o.bipart); 43 | } 44 | return false; 45 | } 46 | 47 | private BigInt(long lpart, BigInteger bipart){ 48 | this.lpart = lpart; 49 | this.bipart = bipart; 50 | } 51 | 52 | public static BigInt fromBigInteger(BigInteger val){ 53 | if(val.bitLength() < 64) 54 | return new BigInt(val.longValue(), null); 55 | else 56 | return new BigInt(0, val); 57 | } 58 | 59 | public static BigInt fromLong(long val){ 60 | return new BigInt(val, null); 61 | } 62 | 63 | public BigInteger toBigInteger(){ 64 | if(bipart == null) 65 | return BigInteger.valueOf(lpart); 66 | else 67 | return bipart; 68 | } 69 | 70 | public BigDecimal toBigDecimal(){ 71 | if(bipart == null) 72 | return BigDecimal.valueOf(lpart); 73 | else 74 | return new BigDecimal(bipart); 75 | } 76 | 77 | ///// java.lang.Number: 78 | 79 | public int intValue(){ 80 | if(bipart == null) 81 | return (int) lpart; 82 | else 83 | return bipart.intValue(); 84 | } 85 | 86 | public long longValue(){ 87 | if(bipart == null) 88 | return lpart; 89 | else 90 | return bipart.longValue(); 91 | } 92 | 93 | public float floatValue(){ 94 | if(bipart == null) 95 | return lpart; 96 | else 97 | return bipart.floatValue(); 98 | } 99 | 100 | public double doubleValue(){ 101 | if(bipart == null) 102 | return lpart; 103 | else 104 | return bipart.doubleValue(); 105 | } 106 | 107 | public byte byteValue(){ 108 | if(bipart == null) 109 | return (byte) lpart; 110 | else 111 | return bipart.byteValue(); 112 | } 113 | 114 | public short shortValue(){ 115 | if(bipart == null) 116 | return (short) lpart; 117 | else 118 | return bipart.shortValue(); 119 | } 120 | 121 | public static BigInt valueOf(long val){ 122 | return new BigInt(val, null); 123 | } 124 | 125 | public String toString(){ 126 | if(bipart == null) 127 | return String.valueOf(lpart); 128 | return bipart.toString(); 129 | } 130 | 131 | public int bitLength(){ 132 | return toBigInteger().bitLength(); 133 | } 134 | 135 | public BigInt add(BigInt y) { 136 | if ((bipart == null) && (y.bipart == null)) { 137 | long ret = lpart + y.lpart; 138 | if ((ret ^ lpart) >= 0 || (ret ^ y.lpart) >= 0) 139 | return BigInt.valueOf(ret); 140 | } 141 | return BigInt.fromBigInteger(this.toBigInteger().add(y.toBigInteger())); 142 | } 143 | 144 | public BigInt multiply(BigInt y) { 145 | if ((bipart == null) && (y.bipart == null)) { 146 | long ret = lpart * y.lpart; 147 | if (y.lpart == 0 || ret / y.lpart == lpart) 148 | return BigInt.valueOf(ret); 149 | } 150 | return BigInt.fromBigInteger(this.toBigInteger().multiply(y.toBigInteger())); 151 | } 152 | 153 | public BigInt quotient(BigInt y) { 154 | if ((bipart == null) && (y.bipart == null)) { 155 | return BigInt.valueOf(lpart / y.lpart); 156 | } 157 | return BigInt.fromBigInteger(this.toBigInteger().divide(y.toBigInteger())); 158 | } 159 | 160 | public BigInt remainder(BigInt y) { 161 | if ((bipart == null) && (y.bipart == null)) { 162 | return BigInt.valueOf(lpart % y.lpart); 163 | } 164 | return BigInt.fromBigInteger(this.toBigInteger().remainder(y.toBigInteger())); 165 | } 166 | 167 | public boolean lt(BigInt y) { 168 | if ((bipart == null) && (y.bipart == null)) { 169 | return lpart < y.lpart; 170 | } 171 | return this.toBigInteger().compareTo(y.toBigInteger()) < 0; 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Box.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 27, 2006 8:40:19 PM */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public class Box{ 16 | 17 | public Object val; 18 | 19 | public Box(Object val){ 20 | this.val = val; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ChunkBuffer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich May 26, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | final public class ChunkBuffer implements Counted{ 16 | Object[] buffer; 17 | int end; 18 | 19 | public ChunkBuffer(int capacity){ 20 | buffer = new Object[capacity]; 21 | end = 0; 22 | } 23 | 24 | public void add(Object o){ 25 | buffer[end++] = o; 26 | } 27 | 28 | public IChunk chunk(){ 29 | ArrayChunk ret = new ArrayChunk(buffer, 0, end); 30 | buffer = null; 31 | return ret; 32 | } 33 | 34 | public int count(){ 35 | return end; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ChunkedCons.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich May 25, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | final public class ChunkedCons extends ASeq implements IChunkedSeq{ 16 | 17 | final IChunk chunk; 18 | final ISeq _more; 19 | 20 | ChunkedCons(IPersistentMap meta, IChunk chunk, ISeq more){ 21 | super(meta); 22 | this.chunk = chunk; 23 | this._more = more; 24 | } 25 | 26 | public ChunkedCons(IChunk chunk, ISeq more){ 27 | this(null,chunk, more); 28 | } 29 | 30 | public Obj withMeta(IPersistentMap meta){ 31 | if(meta != _meta) 32 | return new ChunkedCons(meta, chunk, _more); 33 | return this; 34 | } 35 | 36 | public Object first(){ 37 | return chunk.nth(0); 38 | } 39 | 40 | public ISeq next(){ 41 | if(chunk.count() > 1) 42 | return new ChunkedCons(chunk.dropFirst(), _more); 43 | return chunkedNext(); 44 | } 45 | 46 | public ISeq more(){ 47 | if(chunk.count() > 1) 48 | return new ChunkedCons(chunk.dropFirst(), _more); 49 | if(_more == null) 50 | return PersistentList.EMPTY; 51 | return _more; 52 | } 53 | 54 | public IChunk chunkedFirst(){ 55 | return chunk; 56 | } 57 | 58 | public ISeq chunkedNext(){ 59 | return chunkedMore().seq(); 60 | } 61 | 62 | public ISeq chunkedMore(){ 63 | if(_more == null) 64 | return PersistentList.EMPTY; 65 | return _more; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Cons.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 25, 2006 11:01:29 AM */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.io.Serializable; 16 | 17 | final public class Cons extends ASeq implements Serializable { 18 | 19 | private final T _first; 20 | private final ISeq _more; 21 | 22 | public Cons(T first, ISeq _more){ 23 | this._first = first; 24 | this._more = _more; 25 | } 26 | 27 | 28 | public Cons(IPersistentMap meta, T _first, ISeq _more){ 29 | super(meta); 30 | this._first = _first; 31 | this._more = _more; 32 | } 33 | 34 | public T first(){ 35 | return _first; 36 | } 37 | 38 | public ISeq next(){ 39 | return more().seq(); 40 | } 41 | 42 | public ISeq more(){ 43 | if(_more == null) 44 | return (ISeq) PersistentList.emptyList(); 45 | return _more; 46 | } 47 | 48 | public int count(){ 49 | return 1 + RT.count(_more); 50 | } 51 | 52 | public Cons withMeta(IPersistentMap meta){ 53 | return new Cons(meta, _first, _more); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Counted.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | /** 4 | * Copyright (c) Rich Hickey. All rights reserved. 5 | * The use and distribution terms for this software are covered by the 6 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 7 | * which can be found in the file epl-v10.html at the root of this distribution. 8 | * By using this software in any fashion, you are agreeing to be bound by 9 | * the terms of this license. 10 | * You must not remove this notice, or any other, from this software. 11 | */ 12 | 13 | /* A class that implements Counted promises that it is a collection 14 | * that implement a constant-time count() */ 15 | 16 | public interface Counted { 17 | int count(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/EmptyIterator.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | import java.util.Iterator; 4 | 5 | public final class EmptyIterator implements Iterator { 6 | 7 | @Override 8 | public boolean hasNext() { 9 | return false; 10 | } 11 | 12 | @Override 13 | public Object next() { 14 | throw new IllegalStateException(); 15 | } 16 | 17 | @Override 18 | public void remove() { 19 | throw new UnsupportedOperationException(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Fn.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Nov 25, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface Fn{ 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IChunk.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jun 18, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IChunk extends Indexed{ 16 | 17 | IChunk dropFirst(); 18 | 19 | Object reduce(IFn f, Object start); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IChunkedSeq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich May 24, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IChunkedSeq extends ISeq, Sequential{ 16 | 17 | IChunk chunkedFirst() ; 18 | 19 | ISeq chunkedNext() ; 20 | 21 | ISeq chunkedMore() ; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IDeref.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Feb 9, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IDeref{ 16 | Object deref() ; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IEditableCollection.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jul 17, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IEditableCollection{ 16 | ITransientCollection asTransient(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IFn.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 25, 2006 3:54:03 PM */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.concurrent.Callable; 16 | 17 | public interface IFn extends Callable, Runnable{ 18 | 19 | public Object invoke() ; 20 | 21 | public Object invoke(Object arg1) ; 22 | 23 | public Object invoke(Object arg1, Object arg2) ; 24 | 25 | public Object invoke(Object arg1, Object arg2, Object arg3) ; 26 | 27 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) ; 28 | 29 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) ; 30 | 31 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) ; 32 | 33 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) 34 | ; 35 | 36 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 37 | Object arg8) ; 38 | 39 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 40 | Object arg8, Object arg9) ; 41 | 42 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 43 | Object arg8, Object arg9, Object arg10) ; 44 | 45 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 46 | Object arg8, Object arg9, Object arg10, Object arg11) ; 47 | 48 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 49 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) ; 50 | 51 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 52 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13) ; 53 | 54 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 55 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14) 56 | ; 57 | 58 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 59 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 60 | Object arg15) ; 61 | 62 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 63 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 64 | Object arg15, Object arg16) ; 65 | 66 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 67 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 68 | Object arg15, Object arg16, Object arg17) ; 69 | 70 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 71 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 72 | Object arg15, Object arg16, Object arg17, Object arg18) ; 73 | 74 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 75 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 76 | Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) ; 77 | 78 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 79 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 80 | Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20) 81 | ; 82 | 83 | public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 84 | Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 85 | Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, 86 | Object... args) 87 | ; 88 | 89 | public Object applyTo(ISeq arglist) ; 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IHashEq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich 10/23/11 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IHashEq{ 16 | int hasheq(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ILookup.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Aug 2, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface ILookup{ 16 | V valAt(K key); 17 | 18 | V valAt(K key, V notFound); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IMapEntry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | */ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.util.Map; 14 | 15 | public interface IMapEntry extends Map.Entry{ 16 | K key(); 17 | 18 | V val(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IMeta.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Dec 31, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IMeta { 16 | IPersistentMap meta(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IObj.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | 14 | public interface IObj extends IMeta { 15 | 16 | public IObj withMeta(IPersistentMap meta); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPending.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | public interface IPending{ 14 | boolean isRealized(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPersistentCollection.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | /** 4 | * Copyright (c) Rich Hickey. All rights reserved. 5 | * The use and distribution terms for this software are covered by the 6 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 7 | * which can be found in the file epl-v10.html at the root of this distribution. 8 | * By using this software in any fashion, you are agreeing to be bound by 9 | * the terms of this license. 10 | * You must not remove this notice, or any other, from this software. 11 | */ 12 | 13 | 14 | public interface IPersistentCollection extends Seqable { 15 | 16 | int count(); 17 | 18 | IPersistentCollection cons(T o); 19 | 20 | IPersistentCollection empty(); 21 | 22 | boolean equiv(Object o); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPersistentList.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | */ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | 14 | public interface IPersistentList extends Sequential, IPersistentStack{ 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPersistentMap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | */ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.util.Iterator; 14 | import java.util.Map; 15 | 16 | 17 | public interface IPersistentMap extends Iterable>, Associative, Counted{ 18 | 19 | 20 | IPersistentMap assoc(K key, V val); 21 | 22 | IPersistentMap assocEx(K key, V val); 23 | 24 | IPersistentMap without(K key); 25 | 26 | Iterator> iteratorFrom(K key); 27 | 28 | Iterator> reverseIterator(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPersistentSet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IPersistentSet extends IPersistentCollection, Counted{ 16 | public IPersistentSet disjoin(T key); 17 | public boolean contains(T key); 18 | public Boolean get(T key); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPersistentStack.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Sep 19, 2007 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IPersistentStack extends IPersistentCollection{ 16 | T peek(); 17 | 18 | IPersistentStack pop(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPersistentTrie.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | /** 4 | * Copyright (c) Karl Krukow. All rights reserved. 5 | * The use and distribution terms for this software are covered by the 6 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 7 | * which can be found in the file epl-v10.html at the root of this distribution. 8 | * By using this software in any fashion, you are agreeing to be bound by 9 | * the terms of this license. 10 | * You must not remove this notice, or any other, from this software. 11 | */ 12 | 13 | 14 | public interface IPersistentTrie /*extends IPersistentSet, Seqable*/ { 15 | public T getMember(String s); 16 | public IPersistentTrie addMember(String s, T t); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IPersistentVector.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | /** 4 | * Copyright (c) Rich Hickey. All rights reserved. 5 | * The use and distribution terms for this software are covered by the 6 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 7 | * which can be found in the file epl-v10.html at the root of this distribution. 8 | * By using this software in any fashion, you are agreeing to be bound by 9 | * the terms of this license. 10 | * You must not remove this notice, or any other, from this software. 11 | */ 12 | 13 | public interface IPersistentVector extends Sequential, IPersistentStack, Reversible, Indexed{ 14 | int length(); 15 | 16 | IPersistentVector assocN(int i, T val); 17 | 18 | IPersistentVector cons(T o); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IReduce.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jun 11, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface IReduce{ 16 | Object reduce(IFn f) ; 17 | 18 | Object reduce(IFn f, Object start) ; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ISeq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | */ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | /** 14 | * A persistent, functional, sequence interface 15 | *

16 | * ISeqs are immutable values, i.e. neither first(), nor rest() changes 17 | * or invalidates the ISeq 18 | */ 19 | public interface ISeq extends IPersistentCollection { 20 | 21 | T first(); 22 | 23 | ISeq next(); 24 | 25 | ISeq more(); 26 | 27 | ISeq cons(T o); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ITransientAssociative.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jul 17, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.Map; 16 | 17 | public interface ITransientAssociative extends ITransientCollection>, ILookup{ 18 | 19 | ITransientAssociative assoc(K key, V val); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ITransientCollection.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jul 17, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface ITransientCollection{ 16 | 17 | ITransientCollection conj(T val); 18 | 19 | IPersistentCollection persistent(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ITransientMap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jul 17, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | 16 | public interface ITransientMap extends ITransientAssociative, Counted{ 17 | 18 | ITransientMap assoc(K key, V val); 19 | 20 | ITransientMap without(K key); 21 | 22 | IPersistentMap persistentMap(); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ITransientSet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface ITransientSet extends ITransientCollection, Counted{ 16 | public ITransientSet disjoin(T key) ; 17 | public boolean contains(T key); 18 | public Boolean get(T key); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/ITransientVector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jul 17, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface ITransientVector extends ITransientAssociative, Indexed{ 16 | 17 | ITransientVector assocN(int i, T val); 18 | 19 | ITransientVector pop(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Indexed.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich May 24, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface Indexed extends Counted{ 16 | T nth(int i); 17 | 18 | T nth(int i, T notFound); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IndexedSeq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | */ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | public interface IndexedSeq extends ISeq, Sequential, Counted{ 14 | 15 | public int index(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/IteratorSeq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.io.IOException; 14 | import java.io.NotSerializableException; 15 | import java.util.Iterator; 16 | 17 | public class IteratorSeq extends ASeq{ 18 | final Iterator iter; 19 | final State state; 20 | 21 | static class State{ 22 | volatile Object val; 23 | volatile Object _rest; 24 | } 25 | 26 | public static IteratorSeq create(Iterator iter){ 27 | if(iter.hasNext()) 28 | return new IteratorSeq(iter); 29 | return null; 30 | } 31 | 32 | IteratorSeq(Iterator iter){ 33 | this.iter = iter; 34 | state = new State(); 35 | this.state.val = state; 36 | this.state._rest = state; 37 | } 38 | 39 | IteratorSeq(IPersistentMap meta, Iterator iter, State state){ 40 | super(meta); 41 | this.iter = iter; 42 | this.state = state; 43 | } 44 | 45 | public Object first(){ 46 | if(state.val == state) 47 | synchronized(state) 48 | { 49 | if(state.val == state) 50 | state.val = iter.next(); 51 | } 52 | return state.val; 53 | } 54 | 55 | public ISeq next(){ 56 | if(state._rest == state) 57 | synchronized(state) 58 | { 59 | if(state._rest == state) 60 | { 61 | first(); 62 | state._rest = create(iter); 63 | } 64 | } 65 | return (ISeq) state._rest; 66 | } 67 | 68 | public IteratorSeq withMeta(IPersistentMap meta){ 69 | return new IteratorSeq(meta, iter, state); 70 | } 71 | 72 | private void writeObject (java.io.ObjectOutputStream out) throws IOException { 73 | throw new NotSerializableException(getClass().getName()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/LazilyPersistentVector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich May 14, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.Collection; 16 | 17 | public class LazilyPersistentVector{ 18 | 19 | 20 | static public IPersistentVector createOwning(Object... items){ 21 | if(items.length == 0) 22 | return PersistentVector.EMPTY; 23 | else if(items.length <= 32) 24 | return new PersistentVector(items.length, 5, PersistentVector.EMPTY_NODE,items); 25 | return PersistentVector.create(items); 26 | } 27 | 28 | static public IPersistentVector create(Collection coll){ 29 | if(!(coll instanceof ISeq) && coll.size() <= 32) 30 | return createOwning(coll.toArray()); 31 | return PersistentVector.create(RT.seq(coll)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/LazySeq.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jan 31, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.*; 16 | 17 | public final class LazySeq extends Obj implements ISeq, Sequential, List, IPending, IHashEq{ 18 | 19 | private IFn fn; 20 | private Object sv; 21 | private ISeq s; 22 | 23 | public LazySeq(IFn fn){ 24 | this.fn = fn; 25 | } 26 | 27 | private LazySeq(IPersistentMap meta, ISeq s){ 28 | super(meta); 29 | this.fn = null; 30 | this.s = s; 31 | } 32 | 33 | public Obj withMeta(IPersistentMap meta){ 34 | return new LazySeq(meta, seq()); 35 | } 36 | 37 | final synchronized Object sval(){ 38 | if(fn != null) 39 | { 40 | try 41 | { 42 | sv = fn.invoke(); 43 | fn = null; 44 | } 45 | catch(RuntimeException e) 46 | { 47 | throw e; 48 | } 49 | catch(Exception e) 50 | { 51 | throw Util.sneakyThrow(e); 52 | } 53 | } 54 | if(sv != null) 55 | return sv; 56 | return s; 57 | } 58 | 59 | final synchronized public ISeq seq(){ 60 | sval(); 61 | if(sv != null) 62 | { 63 | Object ls = sv; 64 | sv = null; 65 | while(ls instanceof LazySeq) 66 | { 67 | ls = ((LazySeq)ls).sval(); 68 | } 69 | s = RT.seq(ls); 70 | } 71 | return s; 72 | } 73 | 74 | public int count(){ 75 | int c = 0; 76 | for(ISeq s = seq(); s != null; s = s.next()) 77 | ++c; 78 | return c; 79 | } 80 | 81 | public Object first(){ 82 | seq(); 83 | if(s == null) 84 | return null; 85 | return s.first(); 86 | } 87 | 88 | public ISeq next(){ 89 | seq(); 90 | if(s == null) 91 | return null; 92 | return s.next(); 93 | } 94 | 95 | public ISeq more(){ 96 | seq(); 97 | if(s == null) 98 | return PersistentList.EMPTY; 99 | return s.more(); 100 | } 101 | 102 | public ISeq cons(Object o){ 103 | return RT.cons(o, seq()); 104 | } 105 | 106 | public IPersistentCollection empty(){ 107 | return PersistentList.EMPTY; 108 | } 109 | 110 | public boolean equiv(Object o){ 111 | return equals(o); 112 | } 113 | 114 | public int hashCode(){ 115 | ISeq s = seq(); 116 | if(s == null) 117 | return 1; 118 | return Util.hash(seq()); 119 | } 120 | 121 | public int hasheq(){ 122 | ISeq s = seq(); 123 | if(s == null) 124 | return 1; 125 | return Util.hasheq(seq()); 126 | } 127 | 128 | public boolean equals(Object o){ 129 | ISeq s = seq(); 130 | if(s != null) 131 | return s.equiv(o); 132 | else 133 | return (o instanceof Sequential || o instanceof List) && RT.seq(o) == null; 134 | } 135 | 136 | 137 | // java.util.Collection implementation 138 | 139 | public Object[] toArray(){ 140 | return RT.seqToArray(seq()); 141 | } 142 | 143 | public boolean add(Object o){ 144 | throw new UnsupportedOperationException(); 145 | } 146 | 147 | public boolean remove(Object o){ 148 | throw new UnsupportedOperationException(); 149 | } 150 | 151 | public boolean addAll(Collection c){ 152 | throw new UnsupportedOperationException(); 153 | } 154 | 155 | public void clear(){ 156 | throw new UnsupportedOperationException(); 157 | } 158 | 159 | public boolean retainAll(Collection c){ 160 | throw new UnsupportedOperationException(); 161 | } 162 | 163 | public boolean removeAll(Collection c){ 164 | throw new UnsupportedOperationException(); 165 | } 166 | 167 | public boolean containsAll(Collection c){ 168 | for(Object o : c) 169 | { 170 | if(!contains(o)) 171 | return false; 172 | } 173 | return true; 174 | } 175 | 176 | public Object[] toArray(Object[] a){ 177 | return RT.seqToPassedArray(seq(), a); 178 | } 179 | 180 | public int size(){ 181 | return count(); 182 | } 183 | 184 | public boolean isEmpty(){ 185 | return seq() == null; 186 | } 187 | 188 | public boolean contains(Object o){ 189 | for(ISeq s = seq(); s != null; s = s.next()) 190 | { 191 | if(Util.equiv(s.first(), o)) 192 | return true; 193 | } 194 | return false; 195 | } 196 | 197 | public Iterator iterator(){ 198 | return new SeqIterator(seq()); 199 | } 200 | 201 | //////////// List stuff ///////////////// 202 | private List reify(){ 203 | return new ArrayList(this); 204 | } 205 | 206 | public List subList(int fromIndex, int toIndex){ 207 | return reify().subList(fromIndex, toIndex); 208 | } 209 | 210 | public Object set(int index, Object element){ 211 | throw new UnsupportedOperationException(); 212 | } 213 | 214 | public Object remove(int index){ 215 | throw new UnsupportedOperationException(); 216 | } 217 | 218 | public int indexOf(Object o){ 219 | ISeq s = seq(); 220 | for(int i = 0; s != null; s = s.next(), i++) 221 | { 222 | if(Util.equiv(s.first(), o)) 223 | return i; 224 | } 225 | return -1; 226 | } 227 | 228 | public int lastIndexOf(Object o){ 229 | return reify().lastIndexOf(o); 230 | } 231 | 232 | public ListIterator listIterator(){ 233 | return reify().listIterator(); 234 | } 235 | 236 | public ListIterator listIterator(int index){ 237 | return reify().listIterator(index); 238 | } 239 | 240 | public Object get(int index){ 241 | return RT.nth(this, index); 242 | } 243 | 244 | public void add(int index, Object element){ 245 | throw new UnsupportedOperationException(); 246 | } 247 | 248 | public boolean addAll(int index, Collection c){ 249 | throw new UnsupportedOperationException(); 250 | } 251 | 252 | synchronized public boolean isRealized(){ 253 | return fn == null; 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/MapEntry.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | 14 | public class MapEntry extends AMapEntry{ 15 | final K _key; 16 | final V _val; 17 | 18 | public MapEntry(K key, V val){ 19 | this._key = key; 20 | this._val = val; 21 | } 22 | 23 | public K key(){ 24 | return _key; 25 | } 26 | 27 | public V val(){ 28 | return _val; 29 | } 30 | 31 | public K getKey(){ 32 | return key(); 33 | } 34 | 35 | public V getValue(){ 36 | return val(); 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Obj.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 25, 2006 3:44:58 PM */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.io.Serializable; 16 | 17 | public abstract class Obj implements IObj, Serializable { 18 | 19 | final IPersistentMap _meta; 20 | 21 | public Obj(IPersistentMap meta){ 22 | this._meta = meta; 23 | } 24 | 25 | public Obj(){ 26 | _meta = null; 27 | } 28 | 29 | final public IPersistentMap meta(){ 30 | return _meta; 31 | } 32 | 33 | abstract public Obj withMeta(IPersistentMap meta); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/PersistentHATTrie.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Karl Krukow. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.util.Collection; 14 | import java.util.Iterator; 15 | import java.util.Map; 16 | import java.util.Map.Entry; 17 | 18 | /* 19 | A persistent rendition of Nikolas Askitis' HAT Trie 20 | Uses path copying for persistence 21 | Any errors are my own 22 | */ 23 | @SuppressWarnings({"rawtypes","unchecked"}) 24 | public class PersistentHATTrie extends APersistentTrie implements IObj { 25 | private static final long serialVersionUID = -7068824281866890730L; 26 | final IPersistentMap meta; 27 | final HATTrieNode root; 28 | final int count; 29 | 30 | public static final PersistentHATTrie EMPTY = new PersistentHATTrie(null, null, 0); 31 | 32 | public PersistentHATTrie(HATTrieNode root, IPersistentMap meta, int count) { 33 | this.root = root; 34 | this.meta = meta; 35 | this.count = count; 36 | } 37 | 38 | public IPersistentMap meta() { 39 | return meta; 40 | } 41 | 42 | private static interface HATTrieNode { 43 | HATTrieNode add(String s, int i, T t); 44 | T get(String s, int j); 45 | Iterator> nodeIt(String prefix); 46 | } 47 | private static interface ToStringWithPrefix { 48 | String toStringWithPrefix(String prefix); 49 | } 50 | 51 | private static final class AccessNode implements HATTrieNode,ToStringWithPrefix { 52 | private final HATTrieNode children[]; 53 | private final T emptyPtr; 54 | 55 | public AccessNode(HATTrieNode[] children, T emptyPtr) { 56 | this.children = children; 57 | this.emptyPtr = emptyPtr; 58 | } 59 | 60 | public String toString() { 61 | return toStringWithPrefix(""); 62 | } 63 | 64 | public String toStringWithPrefix(String prefix) { 65 | StringBuilder sb = new StringBuilder(); 66 | String nestedPrefix = prefix+" "; 67 | sb.append(prefix); 68 | sb.append("(access-node\n").append(nestedPrefix); 69 | for (int i=0;i ").append(((ToStringWithPrefix) node) 73 | .toStringWithPrefix(nestedPrefix)).append(";\n").append(nestedPrefix); 74 | } 75 | } 76 | if (emptyPtr != null) { 77 | sb.append("\n").append(prefix).append("**"); 78 | } 79 | sb.append(prefix).append(")"); 80 | return sb.toString(); 81 | } 82 | 83 | 84 | public HATTrieNode add(String s, int i, T t) { 85 | int length = s.length(); 86 | if (i < length) { 87 | char ichar = s.charAt(i); 88 | HATTrieNode hatTrieNode = children[ichar]; 89 | if (hatTrieNode != null) { 90 | HATTrieNode newNode = hatTrieNode.add(s, i+1, t); 91 | if (newNode == hatTrieNode) { 92 | return this; 93 | } 94 | HATTrieNode[] newArr = new HATTrieNode[children.length]; 95 | System.arraycopy(children, 0, newArr, 0, children.length); 96 | newArr[ichar] = newNode; 97 | return new AccessNode(newArr, emptyPtr); 98 | } 99 | ContainerNode c = new ContainerNode(PersistentTreeMap.EMPTY.assoc(s.substring(i+1), t)); 100 | HATTrieNode[] newArr = new HATTrieNode[children.length]; 101 | System.arraycopy(children, 0, newArr, 0, children.length); 102 | newArr[ichar] = c; 103 | return new AccessNode(newArr, emptyPtr); 104 | } 105 | if (i == length && emptyPtr == null) { 106 | return new AccessNode(children, s); 107 | } 108 | return this; 109 | } 110 | 111 | public T get(String s, int i) { 112 | if (i == s.length()) { 113 | return emptyPtr; 114 | } 115 | HATTrieNode c = children[s.charAt(i)]; 116 | if (c == null) { 117 | return null; 118 | } 119 | return c.get(s, i+1); 120 | } 121 | 122 | private static final class AccessNodeIterator implements Iterator> { 123 | private final HATTrieNode children[]; 124 | private final T emptyPtr; 125 | private int index = -1; 126 | private final String prefix; 127 | Iterator> current = null; 128 | 129 | AccessNodeIterator(AccessNode node, String prefix) { 130 | children = node.children; 131 | emptyPtr = node.emptyPtr; 132 | this.prefix = prefix; 133 | moveCurIfNeeded(); 134 | } 135 | 136 | private void moveCurIfNeeded() { 137 | if (index == -1){ 138 | if (emptyPtr == null) { 139 | index = 0; 140 | } else { 141 | return; 142 | } 143 | } 144 | 145 | if (current != null && current.hasNext()) return; 146 | while (index < children.length && children[index] == null) {index += 1;}; 147 | if (index == children.length) { current = null;} 148 | else { 149 | String prefix = new StringBuilder(this.prefix).append((char) index).toString(); 150 | current = children[index++].nodeIt(prefix); 151 | } 152 | 153 | } 154 | 155 | public boolean hasNext() { 156 | if (index == -1 && emptyPtr != null) { 157 | return true; 158 | } 159 | while (current != null && !current.hasNext()) { 160 | moveCurIfNeeded(); 161 | } 162 | return current != null && current.hasNext(); 163 | } 164 | 165 | @Override 166 | public MapEntry next() { 167 | if (index == -1 && emptyPtr != null) { 168 | index = 0; 169 | moveCurIfNeeded(); 170 | return new MapEntry(prefix, emptyPtr); 171 | } 172 | return current.next(); 173 | } 174 | 175 | @Override 176 | public void remove() { 177 | throw new UnsupportedOperationException(); 178 | } 179 | 180 | } 181 | 182 | @Override 183 | public Iterator> nodeIt(String prefix) { 184 | return new AccessNodeIterator(this,prefix); 185 | } 186 | 187 | } 188 | 189 | private static final class ContainerNode implements HATTrieNode,ToStringWithPrefix { 190 | private PersistentTreeMap strings; 191 | 192 | public ContainerNode(PersistentTreeMap strings) { 193 | this.strings = strings; 194 | } 195 | 196 | public String toString() { 197 | return strings.toString(); 198 | } 199 | 200 | public HATTrieNode add(String s, int i, T t) { 201 | String ss = s.substring(i); 202 | T et = strings.get(ss); 203 | if (Util.equiv(et, t)) { 204 | return this; 205 | } 206 | if (shouldBurst()) { 207 | return burst(s,i,t); 208 | } 209 | return new ContainerNode(this.strings.assoc(s.substring(i),t)); 210 | } 211 | 212 | public T get(String s, int i) { 213 | return strings.get(s.substring(i)); 214 | } 215 | 216 | private HATTrieNode burst(String s, int i, T t) { 217 | HATTrieNode[] children = new HATTrieNode[256]; 218 | T empty = s.length() == i ? t : null; 219 | for (Iterator> iterator = strings.iterator(); iterator.hasNext();) { 220 | Entry next = iterator.next(); 221 | String old = next.getKey(); 222 | T value = next.getValue(); 223 | if (empty == null && "".equals(old)) {//can only happen once 224 | empty = value; 225 | } else { 226 | char f = old.charAt(0); 227 | children[f] = addToNode(children[f],old,value,1); 228 | } 229 | } 230 | if (empty != t) {//i < s.length() 231 | char f = s.charAt(i); 232 | children[f] = addToNode(children[f],s,t,i+1); 233 | } 234 | return new AccessNode(children, empty); 235 | } 236 | 237 | private static final HATTrieNode addToNode(HATTrieNode hatTrieNode, String s, T v, int i) { 238 | if (hatTrieNode == null) { 239 | return new ContainerNode(PersistentTreeMap.EMPTY.assoc(s.substring(i),v)); 240 | } else { 241 | return hatTrieNode.add(s, i,v); 242 | } 243 | 244 | } 245 | 246 | private boolean shouldBurst() { 247 | return strings.count() == 4; 248 | } 249 | 250 | @Override 251 | public Iterator> nodeIt(final String prefix) { 252 | return new Iterator>() { 253 | Iterator> it = strings.iterator(); 254 | @Override 255 | public boolean hasNext() { 256 | return it.hasNext(); 257 | } 258 | 259 | @Override 260 | public Map.Entry next() { 261 | Entry next = it.next(); 262 | return new MapEntry(prefix+next.getKey(), next.getValue()); 263 | } 264 | 265 | @Override 266 | public void remove() { 267 | throw new UnsupportedOperationException(); 268 | } 269 | }; 270 | } 271 | 272 | @Override 273 | public String toStringWithPrefix(String prefix) { 274 | return prefix+toString(); 275 | 276 | } 277 | 278 | } 279 | 280 | @Override 281 | public T getMember(String s) { 282 | if (root == null || s == null) return null; 283 | return root.get(s,0); 284 | } 285 | 286 | @Override 287 | public IPersistentTrie addMember(String s, T t) { 288 | if (root == null) { 289 | return new PersistentHATTrie(new ContainerNode(PersistentTreeMap.EMPTY.assoc(s, t)),null,1); 290 | } 291 | HATTrieNode newRoot = root.add(s, 0,t); 292 | if (root == newRoot) { 293 | return this; 294 | } 295 | return new PersistentHATTrie(newRoot,meta,count+1); 296 | } 297 | 298 | @Override 299 | public IPersistentSet disjoin(Object key) { 300 | throw new UnsupportedOperationException(); 301 | } 302 | 303 | @Override 304 | public boolean contains(Object key) { 305 | return (key instanceof String) && getMember((String) key) != null; 306 | } 307 | 308 | @Override 309 | public Boolean get(Object key) { 310 | return contains(key); 311 | } 312 | 313 | @Override 314 | public int count() { 315 | return count; 316 | } 317 | 318 | @Override 319 | public IPersistentCollection cons(Object o) { 320 | if (!(o instanceof Map.Entry)) { 321 | throw new IllegalArgumentException("Only adding strings is supported"); 322 | } 323 | Map.Entry e = (Entry) o; 324 | return (IPersistentCollection) this.addMember(e.getKey(),e.getValue()); 325 | } 326 | 327 | @Override 328 | public IPersistentCollection empty() { 329 | return EMPTY; 330 | } 331 | 332 | @Override 333 | public Iterator> iterator() { 334 | return root != null ? root.nodeIt("") : new EmptyIterator(); 335 | } 336 | 337 | @Override 338 | public ISeq seq() { 339 | throw new UnsupportedOperationException(); 340 | } 341 | 342 | 343 | 344 | 345 | @Override 346 | public boolean remove(Object o) { 347 | throw new UnsupportedOperationException(); 348 | } 349 | 350 | @Override 351 | public boolean containsAll(Collection c) { 352 | for (Object o : c) { 353 | if (!contains(o)) { 354 | return false; 355 | } 356 | } 357 | return true; 358 | } 359 | 360 | @Override 361 | public boolean removeAll(Collection c) { 362 | throw new UnsupportedOperationException(); 363 | } 364 | 365 | @Override 366 | public boolean retainAll(Collection c) { 367 | throw new UnsupportedOperationException(); 368 | } 369 | 370 | @Override 371 | public void clear() { 372 | throw new UnsupportedOperationException(); 373 | } 374 | 375 | @Override 376 | public IObj withMeta(IPersistentMap meta) { 377 | return new PersistentHATTrie(root,meta,count); 378 | } 379 | 380 | @Override 381 | public String toString() { 382 | if (root == null) {return "{}";} 383 | return root.toString(); 384 | } 385 | 386 | 387 | @Override 388 | public boolean add(Entry e) { 389 | throw new UnsupportedOperationException(); 390 | } 391 | 392 | @Override 393 | public boolean addAll(Collection> c) { 394 | throw new UnsupportedOperationException(); 395 | } 396 | 397 | } -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/PersistentHashSet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.Iterator; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | import com.github.krukow.clj_ds.PersistentSet; 20 | import com.github.krukow.clj_ds.TransientSet; 21 | 22 | public class PersistentHashSet extends APersistentSet implements IObj, IEditableCollection, PersistentSet { 23 | 24 | static public final PersistentHashSet EMPTY = new PersistentHashSet(null, PersistentHashMap.EMPTY); 25 | 26 | @SuppressWarnings("unchecked") 27 | static public final PersistentHashSet emptySet() { 28 | return EMPTY; 29 | } 30 | final IPersistentMap _meta; 31 | 32 | public static PersistentHashSet create(T... init){ 33 | PersistentHashSet ret = EMPTY; 34 | for(int i = 0; i < init.length; i++) 35 | { 36 | ret = (PersistentHashSet) ret.cons(init[i]); 37 | } 38 | return ret; 39 | } 40 | 41 | public static PersistentHashSet create(Iterable init){ 42 | PersistentHashSet ret = EMPTY; 43 | for(T key : init) 44 | { 45 | ret = (PersistentHashSet) ret.cons(key); 46 | } 47 | return ret; 48 | } 49 | 50 | static public PersistentHashSet create(ISeq items){ 51 | PersistentHashSet ret = EMPTY; 52 | for(; items != null; items = items.next()) 53 | { 54 | ret = (PersistentHashSet) ret.cons(items.first()); 55 | } 56 | return ret; 57 | } 58 | 59 | public static PersistentHashSet createWithCheck(T ... init){ 60 | PersistentHashSet ret = EMPTY; 61 | for(int i = 0; i < init.length; i++) 62 | { 63 | ret = (PersistentHashSet) ret.cons(init[i]); 64 | if(ret.count() != i + 1) 65 | throw new IllegalArgumentException("Duplicate key: " + init[i]); 66 | } 67 | return ret; 68 | } 69 | 70 | public static PersistentHashSet createWithCheck(List init){ 71 | PersistentHashSet ret = EMPTY; 72 | int i=0; 73 | for(T key : init) 74 | { 75 | ret = (PersistentHashSet) ret.cons(key); 76 | if(ret.count() != i + 1) 77 | throw new IllegalArgumentException("Duplicate key: " + key); 78 | ++i; 79 | } 80 | return ret; 81 | } 82 | 83 | static public PersistentHashSet createWithCheck(ISeq items){ 84 | PersistentHashSet ret = EMPTY; 85 | for(int i=0; items != null; items = items.next(), ++i) 86 | { 87 | ret = (PersistentHashSet) ret.cons(items.first()); 88 | if(ret.count() != i + 1) 89 | throw new IllegalArgumentException("Duplicate key: " + items.first()); 90 | } 91 | return ret; 92 | } 93 | 94 | PersistentHashSet(IPersistentMap meta, IPersistentMap impl){ 95 | super(impl); 96 | this._meta = meta; 97 | } 98 | 99 | public Iterator iterator(){ 100 | return new Iterator() { 101 | final Iterator iterator = impl.iterator(); 102 | 103 | public boolean hasNext() { 104 | return iterator.hasNext(); 105 | } 106 | 107 | public T next() { 108 | Map.Entry n = iterator.next(); 109 | return (T) n.getKey(); 110 | } 111 | 112 | @Override 113 | public void remove() { 114 | throw new UnsupportedOperationException(); 115 | } 116 | 117 | }; 118 | } 119 | 120 | 121 | public PersistentHashSet disjoin(T key) { 122 | if(contains(key)) 123 | return new PersistentHashSet(meta(),impl.without(key)); 124 | return this; 125 | } 126 | 127 | public PersistentHashSet cons(T o){ 128 | if(contains(o)) 129 | return this; 130 | return new PersistentHashSet(meta(),impl.assoc(o,o)); 131 | } 132 | 133 | public IPersistentSet empty(){ 134 | return EMPTY.withMeta(meta()); 135 | } 136 | 137 | public PersistentHashSet withMeta(IPersistentMap meta){ 138 | return new PersistentHashSet(meta, impl); 139 | } 140 | 141 | public TransientHashSet asTransient() { 142 | return new TransientHashSet(((PersistentHashMap) impl).asTransient()); 143 | } 144 | 145 | public IPersistentMap meta(){ 146 | return _meta; 147 | } 148 | 149 | static final class TransientHashSet extends ATransientSet implements TransientSet { 150 | TransientHashSet(ITransientMap impl) { 151 | super(impl); 152 | } 153 | 154 | public PersistentHashSet persistent() { 155 | return new PersistentHashSet(null, impl.persistentMap()); 156 | } 157 | 158 | @Override 159 | public PersistentSet persist() { 160 | return persistent(); 161 | } 162 | 163 | @Override 164 | public TransientSet plus(T val) { 165 | return (TransientSet) conj(val); 166 | } 167 | 168 | @Override 169 | public TransientSet minus(T val) { 170 | return (TransientSet) disjoin(val); 171 | } 172 | } 173 | 174 | @Override 175 | public PersistentSet zero() { 176 | return (PersistentSet) empty(); 177 | } 178 | 179 | @Override 180 | public PersistentSet plus(T val) { 181 | return cons(val); 182 | } 183 | 184 | @Override 185 | public PersistentSet minus(T val) { 186 | return disjoin(val); 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/PersistentList.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Collection; 15 | import java.util.Collections; 16 | import java.util.Iterator; 17 | import java.util.List; 18 | import java.util.ListIterator; 19 | import java.util.NoSuchElementException; 20 | 21 | public class PersistentList extends ASeq implements IPersistentList, IReduce, List, Counted, com.github.krukow.clj_ds.PersistentList { 22 | 23 | private final T _first; 24 | private final PersistentList _rest; 25 | private final int _count; 26 | 27 | final public static EmptyList EMPTY = new EmptyList(null); 28 | 29 | public static final EmptyList emptyList() { 30 | return EMPTY; 31 | } 32 | 33 | public PersistentList(T first){ 34 | this._first = first; 35 | this._rest = null; 36 | 37 | this._count = 1; 38 | } 39 | 40 | PersistentList(IPersistentMap meta, T _first, PersistentList _rest, int _count){ 41 | super(meta); 42 | this._first = _first; 43 | this._rest = _rest; 44 | this._count = _count; 45 | } 46 | 47 | public static com.github.krukow.clj_ds.PersistentList create(T... init){ 48 | IPersistentList ret = emptyList(); 49 | for(int i = init.length-1; i>=0; i--) 50 | { 51 | ret = (IPersistentList) ret.cons(init[i]); 52 | } 53 | return (com.github.krukow.clj_ds.PersistentList) ret; 54 | } 55 | 56 | public static com.github.krukow.clj_ds.PersistentList create(Iterable init) { 57 | PersistentVector initVector = PersistentVector.create(init); 58 | return (com.github.krukow.clj_ds.PersistentList) create(initVector); 59 | } 60 | 61 | public static IPersistentList create(List init){ 62 | IPersistentList ret = emptyList(); 63 | for(ListIterator i = init.listIterator(init.size()); i.hasPrevious();) 64 | { 65 | ret = (IPersistentList) ret.cons(i.previous()); 66 | } 67 | return ret; 68 | } 69 | 70 | public T first(){ 71 | return _first; 72 | } 73 | 74 | public ISeq next(){ 75 | if(_count == 1) 76 | return null; 77 | return (ISeq) _rest; 78 | } 79 | 80 | public T peek(){ 81 | return first(); 82 | } 83 | 84 | public IPersistentList pop(){ 85 | if(_rest == null) 86 | return EMPTY.withMeta(_meta); 87 | return _rest; 88 | } 89 | 90 | public int count(){ 91 | return _count; 92 | } 93 | 94 | public PersistentList cons(T o){ 95 | return new PersistentList(meta(), o, this, _count + 1); 96 | } 97 | 98 | 99 | public EmptyList empty(){ 100 | return EMPTY.withMeta(meta()); 101 | } 102 | 103 | public PersistentList withMeta(IPersistentMap meta){ 104 | if(meta != _meta) 105 | return new PersistentList(meta, _first, _rest, _count); 106 | return this; 107 | } 108 | 109 | public Object reduce(IFn f) { 110 | Object ret = first(); 111 | for(ISeq s = next(); s != null; s = s.next()) 112 | ret = f.invoke(ret, s.first()); 113 | return ret; 114 | } 115 | 116 | public Object reduce(IFn f, Object start) { 117 | Object ret = f.invoke(start, first()); 118 | for(ISeq s = next(); s != null; s = s.next()) 119 | ret = f.invoke(ret, s.first()); 120 | return ret; 121 | } 122 | 123 | 124 | static class EmptyList extends Obj implements IPersistentList, List, ISeq, Counted, com.github.krukow.clj_ds.PersistentList{ 125 | 126 | public int hashCode(){ 127 | return 1; 128 | } 129 | 130 | public boolean equals(Object o) { 131 | return (o instanceof Sequential || o instanceof List) && RT.seq(o) == null; 132 | } 133 | 134 | public boolean equiv(Object o){ 135 | return equals(o); 136 | } 137 | 138 | EmptyList(IPersistentMap meta){ 139 | super(meta); 140 | } 141 | 142 | public T first() { 143 | return null; 144 | } 145 | 146 | public ISeq next() { 147 | return null; 148 | } 149 | 150 | public ISeq more() { 151 | return this; 152 | } 153 | 154 | public PersistentList cons(T o){ 155 | return new PersistentList(meta(), o, null, 1); 156 | } 157 | 158 | public EmptyList empty(){ 159 | return this; 160 | } 161 | 162 | public EmptyList withMeta(IPersistentMap meta){ 163 | if(meta != meta()) 164 | return new EmptyList(meta); 165 | return this; 166 | } 167 | 168 | public T peek(){ 169 | return null; 170 | } 171 | 172 | public PersistentList pop(){ 173 | throw new IllegalStateException("Can't pop empty list"); 174 | } 175 | 176 | public int count(){ 177 | return 0; 178 | } 179 | 180 | public ISeq seq(){ 181 | return null; 182 | } 183 | 184 | 185 | public int size(){ 186 | return 0; 187 | } 188 | 189 | public boolean isEmpty(){ 190 | return true; 191 | } 192 | 193 | public boolean contains(Object o){ 194 | return false; 195 | } 196 | 197 | public Iterator iterator(){ 198 | return new Iterator(){ 199 | 200 | public boolean hasNext(){ 201 | return false; 202 | } 203 | 204 | public T next(){ 205 | throw new NoSuchElementException(); 206 | } 207 | 208 | public void remove(){ 209 | throw new UnsupportedOperationException(); 210 | } 211 | }; 212 | } 213 | 214 | public Object[] toArray(){ 215 | return RT.EMPTY_ARRAY; 216 | } 217 | 218 | public boolean add(T o){ 219 | throw new UnsupportedOperationException(); 220 | } 221 | 222 | public boolean remove(Object o){ 223 | throw new UnsupportedOperationException(); 224 | } 225 | 226 | public boolean addAll(Collection collection){ 227 | throw new UnsupportedOperationException(); 228 | } 229 | 230 | public void clear(){ 231 | throw new UnsupportedOperationException(); 232 | } 233 | 234 | public boolean retainAll(Collection collection){ 235 | throw new UnsupportedOperationException(); 236 | } 237 | 238 | public boolean removeAll(Collection collection){ 239 | throw new UnsupportedOperationException(); 240 | } 241 | 242 | public boolean containsAll(Collection collection){ 243 | return collection.isEmpty(); 244 | } 245 | 246 | public Object[] toArray(Object[] objects){ 247 | if(objects.length > 0) 248 | objects[0] = null; 249 | return objects; 250 | } 251 | 252 | //////////// List stuff ///////////////// 253 | private List reify(){ 254 | return Collections.unmodifiableList(new ArrayList(this)); 255 | } 256 | 257 | public List subList(int fromIndex, int toIndex){ 258 | return reify().subList(fromIndex, toIndex); 259 | } 260 | 261 | public T set(int index, T element){ 262 | throw new UnsupportedOperationException(); 263 | } 264 | 265 | public T remove(int index){ 266 | throw new UnsupportedOperationException(); 267 | } 268 | 269 | public int indexOf(Object o){ 270 | ISeq s = seq(); 271 | for(int i = 0; s != null; s = s.next(), i++) 272 | { 273 | if(Util.equiv(s.first(), o)) 274 | return i; 275 | } 276 | return -1; 277 | } 278 | 279 | public int lastIndexOf(Object o){ 280 | return reify().lastIndexOf(o); 281 | } 282 | 283 | public ListIterator listIterator(){ 284 | return reify().listIterator(); 285 | } 286 | 287 | public ListIterator listIterator(int index){ 288 | return reify().listIterator(index); 289 | } 290 | 291 | public T get(int index){ 292 | return (T) RT.nth(this, index); 293 | } 294 | 295 | public void add(int index, Object element){ 296 | throw new UnsupportedOperationException(); 297 | } 298 | 299 | public boolean addAll(int index, Collection c){ 300 | throw new UnsupportedOperationException(); 301 | } 302 | 303 | @Override 304 | public com.github.krukow.clj_ds.PersistentList zero() { 305 | return this; 306 | } 307 | 308 | @Override 309 | public com.github.krukow.clj_ds.PersistentList plus(T val) { 310 | return cons(val); 311 | } 312 | 313 | @Override 314 | public com.github.krukow.clj_ds.PersistentList minus() { 315 | return pop(); 316 | } 317 | 318 | } 319 | 320 | public static com.github.krukow.clj_ds.PersistentList consAll(com.github.krukow.clj_ds.PersistentList list, Iterable others) { 321 | for (T other : others) { 322 | list = list.plus(other); 323 | } 324 | return list; 325 | } 326 | 327 | @Override 328 | public com.github.krukow.clj_ds.PersistentList zero() { 329 | return empty(); 330 | } 331 | 332 | @Override 333 | public com.github.krukow.clj_ds.PersistentList plus(T val) { 334 | return cons(val); 335 | } 336 | 337 | @Override 338 | public com.github.krukow.clj_ds.PersistentList minus() { 339 | return (com.github.krukow.clj_ds.PersistentList) pop(); 340 | } 341 | 342 | } 343 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/PersistentQueue.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | import java.util.Collection; 14 | import java.util.Iterator; 15 | 16 | /** 17 | * conses onto rear, peeks/pops from front 18 | * See Okasaki's Batched Queues 19 | * This differs in that it uses a PersistentVector as the rear, which is in-order, 20 | * so no reversing or suspensions required for persistent use 21 | */ 22 | 23 | public class PersistentQueue extends Obj implements IPersistentList, Collection, Counted, IHashEq{ 24 | 25 | final public static PersistentQueue EMPTY = new PersistentQueue(null, 0, null, null); 26 | 27 | //* 28 | final int cnt; 29 | final ISeq f; 30 | final PersistentVector r; 31 | //static final int INITIAL_REAR_SIZE = 4; 32 | int _hash = -1; 33 | int _hasheq = -1; 34 | 35 | PersistentQueue(IPersistentMap meta, int cnt, ISeq f, PersistentVector r){ 36 | super(meta); 37 | this.cnt = cnt; 38 | this.f = f; 39 | this.r = r; 40 | } 41 | 42 | public boolean equiv(Object obj){ 43 | 44 | if(!(obj instanceof Sequential)) 45 | return false; 46 | ISeq ms = RT.seq(obj); 47 | for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next()) 48 | { 49 | if(ms == null || !Util.equiv(s.first(), ms.first())) 50 | return false; 51 | } 52 | return ms == null; 53 | 54 | } 55 | 56 | public boolean equals(Object obj){ 57 | 58 | if(!(obj instanceof Sequential)) 59 | return false; 60 | ISeq ms = RT.seq(obj); 61 | for(ISeq s = seq(); s != null; s = s.next(), ms = ms.next()) 62 | { 63 | if(ms == null || !Util.equals(s.first(), ms.first())) 64 | return false; 65 | } 66 | return ms == null; 67 | 68 | } 69 | 70 | public int hashCode(){ 71 | if(_hash == -1) 72 | { 73 | int hash = 1; 74 | for(ISeq s = seq(); s != null; s = s.next()) 75 | { 76 | hash = 31 * hash + (s.first() == null ? 0 : s.first().hashCode()); 77 | } 78 | this._hash = hash; 79 | } 80 | return _hash; 81 | } 82 | 83 | public int hasheq() { 84 | if(_hasheq == -1) 85 | { 86 | int hash = 1; 87 | for(ISeq s = seq(); s != null; s = s.next()) 88 | { 89 | hash = 31 * hash + Util.hasheq(s.first()); 90 | } 91 | this._hasheq = hash; 92 | } 93 | return _hasheq; 94 | } 95 | 96 | public T peek(){ 97 | return (T) RT.first(f); 98 | } 99 | 100 | public PersistentQueue pop(){ 101 | if(f == null) //hmmm... pop of empty queue -> empty queue? 102 | return this; 103 | //throw new IllegalStateException("popping empty queue"); 104 | ISeq f1 = f.next(); 105 | PersistentVector r1 = r; 106 | if(f1 == null) 107 | { 108 | f1 = RT.seq(r); 109 | r1 = null; 110 | } 111 | return new PersistentQueue(meta(), cnt - 1, f1, r1); 112 | } 113 | 114 | public int count(){ 115 | return cnt; 116 | } 117 | 118 | public ISeq seq(){ 119 | if(f == null) 120 | return null; 121 | return new Seq(f, RT.seq(r)); 122 | } 123 | 124 | public PersistentQueue cons(T o){ 125 | if(f == null) //empty 126 | return new PersistentQueue(meta(), cnt + 1, RT.list(o), null); 127 | else 128 | return new PersistentQueue(meta(), cnt + 1, f, (r != null ? r : PersistentVector.EMPTY).cons(o)); 129 | } 130 | 131 | public IPersistentCollection empty(){ 132 | return EMPTY.withMeta(meta()); 133 | } 134 | 135 | public PersistentQueue withMeta(IPersistentMap meta){ 136 | return new PersistentQueue(meta, cnt, f, r); 137 | } 138 | 139 | static class Seq extends ASeq{ 140 | final ISeq f; 141 | final ISeq rseq; 142 | 143 | Seq(ISeq f, ISeq rseq){ 144 | this.f = f; 145 | this.rseq = rseq; 146 | } 147 | 148 | Seq(IPersistentMap meta, ISeq f, ISeq rseq){ 149 | super(meta); 150 | this.f = f; 151 | this.rseq = rseq; 152 | } 153 | 154 | public T first(){ 155 | return f.first(); 156 | } 157 | 158 | public ISeq next(){ 159 | ISeq f1 = f.next(); 160 | ISeq r1 = rseq; 161 | if(f1 == null) 162 | { 163 | if(rseq == null) 164 | return null; 165 | f1 = rseq; 166 | r1 = null; 167 | } 168 | return new Seq(f1, r1); 169 | } 170 | 171 | public int count(){ 172 | return RT.count(f) + RT.count(rseq); 173 | } 174 | 175 | public Seq withMeta(IPersistentMap meta){ 176 | return new Seq(meta, f, rseq); 177 | } 178 | } 179 | 180 | // java.util.Collection implementation 181 | 182 | public Object[] toArray(){ 183 | return RT.seqToArray(seq()); 184 | } 185 | 186 | public boolean add(Object o){ 187 | throw new UnsupportedOperationException(); 188 | } 189 | 190 | public boolean remove(Object o){ 191 | throw new UnsupportedOperationException(); 192 | } 193 | 194 | public boolean addAll(Collection c){ 195 | throw new UnsupportedOperationException(); 196 | } 197 | 198 | public void clear(){ 199 | throw new UnsupportedOperationException(); 200 | } 201 | 202 | public boolean retainAll(Collection c){ 203 | throw new UnsupportedOperationException(); 204 | } 205 | 206 | public boolean removeAll(Collection c){ 207 | throw new UnsupportedOperationException(); 208 | } 209 | 210 | public boolean containsAll(Collection c){ 211 | for(Object o : c) 212 | { 213 | if(contains(o)) 214 | return true; 215 | } 216 | return false; 217 | } 218 | 219 | public Object[] toArray(Object[] a){ 220 | return RT.seqToPassedArray(seq(), a); 221 | } 222 | 223 | public int size(){ 224 | return count(); 225 | } 226 | 227 | public boolean isEmpty(){ 228 | return count() == 0; 229 | } 230 | 231 | public boolean contains(Object o){ 232 | for(ISeq s = seq(); s != null; s = s.next()) 233 | { 234 | if(Util.equiv(s.first(), o)) 235 | return true; 236 | } 237 | return false; 238 | } 239 | 240 | public Iterator iterator(){ 241 | return new SeqIterator(seq()); 242 | } 243 | 244 | /* 245 | public static void main(String[] args){ 246 | if(args.length != 1) 247 | { 248 | System.err.println("Usage: PersistentQueue n"); 249 | return; 250 | } 251 | int n = Integer.parseInt(args[0]); 252 | 253 | 254 | long startTime, estimatedTime; 255 | 256 | Queue list = new LinkedList(); 257 | //Queue list = new ConcurrentLinkedQueue(); 258 | System.out.println("Queue"); 259 | startTime = System.nanoTime(); 260 | for(int i = 0; i < n; i++) 261 | { 262 | list.add(i); 263 | list.add(i); 264 | list.remove(); 265 | } 266 | for(int i = 0; i < n - 10; i++) 267 | { 268 | list.remove(); 269 | } 270 | estimatedTime = System.nanoTime() - startTime; 271 | System.out.println("time: " + estimatedTime / 1000000); 272 | System.out.println("peek: " + list.peek()); 273 | 274 | 275 | PersistentQueue q = PersistentQueue.EMPTY; 276 | System.out.println("PersistentQueue"); 277 | startTime = System.nanoTime(); 278 | for(int i = 0; i < n; i++) 279 | { 280 | q = q.cons(i); 281 | q = q.cons(i); 282 | q = q.pop(); 283 | } 284 | // IPersistentList lastq = null; 285 | // IPersistentList lastq2; 286 | for(int i = 0; i < n - 10; i++) 287 | { 288 | //lastq2 = lastq; 289 | //lastq = q; 290 | q = q.pop(); 291 | } 292 | estimatedTime = System.nanoTime() - startTime; 293 | System.out.println("time: " + estimatedTime / 1000000); 294 | System.out.println("peek: " + q.peek()); 295 | 296 | IPersistentList q2 = q; 297 | for(int i = 0; i < 10; i++) 298 | { 299 | q2 = (IPersistentList) q2.cons(i); 300 | } 301 | // for(ISeq s = q.seq();s != null;s = s.rest()) 302 | // System.out.println("q: " + s.first().toString()); 303 | // for(ISeq s = q2.seq();s != null;s = s.rest()) 304 | // System.out.println("q2: " + s.first().toString()); 305 | } 306 | */ 307 | } 308 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/PersistentStructMap.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Dec 16, 2007 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.io.Serializable; 16 | import java.util.Iterator; 17 | import java.util.Map; 18 | 19 | public class PersistentStructMap extends APersistentMap implements IObj{ 20 | 21 | public static class Def implements Serializable{ 22 | final ISeq keys; 23 | final IPersistentMap keyslots; 24 | 25 | Def(ISeq keys, IPersistentMap keyslots){ 26 | this.keys = keys; 27 | this.keyslots = keyslots; 28 | } 29 | } 30 | 31 | final Def def; 32 | final Object[] vals; 33 | final IPersistentMap ext; 34 | final IPersistentMap _meta; 35 | 36 | 37 | static public Def createSlotMap(ISeq keys){ 38 | if(keys == null) 39 | throw new IllegalArgumentException("Must supply keys"); 40 | int c = RT.count(keys); 41 | Object[] v = new Object[2*c]; 42 | int i = 0; 43 | for(ISeq s = keys; s != null; s = s.next(), i++) 44 | { 45 | v[2*i] = s.first(); 46 | v[2*i+1] = i; 47 | } 48 | return new Def(keys, map(v)); 49 | } 50 | 51 | static public IPersistentMap map(Object... init){ 52 | if(init == null) 53 | return PersistentArrayMap.EMPTY; 54 | else if(init.length <= PersistentArrayMap.HASHTABLE_THRESHOLD) 55 | return PersistentArrayMap.createWithCheck(init); 56 | return PersistentHashMap.create(init); 57 | } 58 | 59 | 60 | static public PersistentStructMap create(Def def, ISeq keyvals){ 61 | Object[] vals = new Object[def.keyslots.count()]; 62 | IPersistentMap ext = PersistentHashMap.EMPTY; 63 | for(; keyvals != null; keyvals = keyvals.next().next()) 64 | { 65 | if(keyvals.next() == null) 66 | throw new IllegalArgumentException(String.format("No value supplied for key: %s", keyvals.first())); 67 | K k = (K) keyvals.first(); 68 | V v = (V) RT.second(keyvals); 69 | Map.Entry e = def.keyslots.entryAt(k); 70 | if(e != null) 71 | vals[e.getValue()] = v; 72 | else 73 | ext = ext.assoc(k, v); 74 | } 75 | return new PersistentStructMap(null, def, vals, ext); 76 | } 77 | 78 | static public PersistentStructMap construct(Def def, ISeq valseq){ 79 | Object[] vals = new Object[def.keyslots.count()]; 80 | IPersistentMap ext = PersistentHashMap.EMPTY; 81 | for(int i = 0; i < vals.length && valseq != null; valseq = valseq.next(), i++) 82 | { 83 | vals[i] = valseq.first(); 84 | } 85 | if(valseq != null) 86 | throw new IllegalArgumentException("Too many arguments to struct constructor"); 87 | return new PersistentStructMap(null, def, vals, ext); 88 | } 89 | 90 | static public IFn getAccessor(final Def def, K key){ 91 | Map.Entry e = def.keyslots.entryAt(key); 92 | if(e != null) 93 | { 94 | final int i = e.getValue(); 95 | return new AFn(){ 96 | public Object invoke(Object arg1) { 97 | PersistentStructMap m = (PersistentStructMap) arg1; 98 | if(m.def != def) 99 | throw Util.runtimeException("Accessor/struct mismatch"); 100 | return m.vals[i]; 101 | } 102 | }; 103 | } 104 | throw new IllegalArgumentException("Not a key of struct"); 105 | } 106 | 107 | protected PersistentStructMap(IPersistentMap meta, Def def, Object[] vals, IPersistentMap ext){ 108 | this._meta = meta; 109 | this.ext = ext; 110 | this.def = def; 111 | this.vals = vals; 112 | } 113 | 114 | /** 115 | * Returns a new instance of PersistentStructMap using the given parameters. 116 | * This function is used instead of the PersistentStructMap constructor by 117 | * all methods that return a new PersistentStructMap. This is done so as to 118 | * allow subclasses to return instances of their class from all 119 | * PersistentStructMap methods. 120 | */ 121 | protected PersistentStructMap makeNew(IPersistentMap meta, Def def, Object[] vals, IPersistentMap ext){ 122 | return new PersistentStructMap(meta, def, vals, ext); 123 | } 124 | 125 | public IObj withMeta(IPersistentMap meta){ 126 | if(meta == _meta) 127 | return this; 128 | return makeNew(meta, def, vals, ext); 129 | } 130 | 131 | public IPersistentMap meta(){ 132 | return _meta; 133 | } 134 | 135 | 136 | public boolean containsKey(Object key){ 137 | return def.keyslots.containsKey(key) || ((Map)ext).containsKey(key); 138 | } 139 | 140 | public IMapEntry entryAt(K key){ 141 | Map.Entry e = def.keyslots.entryAt(key); 142 | if(e != null) 143 | { 144 | return new MapEntry(e.getKey(), (V) vals[e.getValue()]); 145 | } 146 | return ext.entryAt(key); 147 | } 148 | 149 | public IPersistentMap assoc(K key, V val){ 150 | Map.Entry e = def.keyslots.entryAt(key); 151 | if(e != null) 152 | { 153 | int i = e.getValue(); 154 | Object[] newVals = vals.clone(); 155 | newVals[i] = val; 156 | return makeNew(_meta, def, newVals, ext); 157 | } 158 | return makeNew(_meta, def, vals, ext.assoc(key, val)); 159 | } 160 | 161 | public V valAt(K key){ 162 | Integer i = (Integer) def.keyslots.valAt(key); 163 | if(i != null) 164 | { 165 | return (V) vals[i]; 166 | } 167 | return ext.valAt(key); 168 | } 169 | 170 | public V valAt(K key, V notFound){ 171 | Integer i = (Integer) def.keyslots.valAt(key); 172 | if(i != null) 173 | { 174 | return (V) vals[i]; 175 | } 176 | return ext.valAt(key, notFound); 177 | } 178 | 179 | public IPersistentMap assocEx(K key, V val) { 180 | if(containsKey(key)) 181 | throw Util.runtimeException("Key already present"); 182 | return assoc(key, val); 183 | } 184 | 185 | public IPersistentMap without(K key) { 186 | Map.Entry e = def.keyslots.entryAt(key); 187 | if(e != null) 188 | throw Util.runtimeException("Can't remove struct key"); 189 | IPersistentMap newExt = ext.without(key); 190 | if(newExt == ext) 191 | return this; 192 | return makeNew(_meta, def, vals, newExt); 193 | } 194 | 195 | public Iterator> iterator(){ 196 | return new Iterator>() { 197 | 198 | ISeq> seq = seq(); 199 | 200 | public boolean hasNext() { 201 | return seq != null; 202 | } 203 | 204 | public java.util.Map.Entry next() { 205 | Entry first = seq.first(); 206 | seq = seq.next(); 207 | return first; 208 | } 209 | 210 | public void remove() { 211 | throw new UnsupportedOperationException(); 212 | } 213 | }; 214 | } 215 | 216 | public Iterator> reverseIterator(){ 217 | return new Iterator>() { 218 | 219 | Iterator> mapIter = ext.reverseIterator(); 220 | Object[] keys = RT.seqToArray(def.keys); 221 | int index = keys.length; 222 | 223 | public boolean hasNext() { 224 | return mapIter.hasNext() || index > 0; 225 | } 226 | 227 | public java.util.Map.Entry next() { 228 | if (mapIter.hasNext()) { 229 | return mapIter.next(); 230 | } 231 | index -= 1; 232 | return new MapEntry(keys[index],vals[index]); 233 | } 234 | 235 | public void remove() { 236 | throw new UnsupportedOperationException(); 237 | } 238 | }; 239 | } 240 | 241 | public Iterator> iteratorFrom(K key) { 242 | Map.Entry e = def.keyslots.entryAt(key); 243 | if(e != null) { 244 | final int start = e.getValue(); 245 | return new Iterator>() { 246 | int index = start; 247 | final Object[] keys = RT.seqToArray(def.keys); 248 | Iterator> extIt = ext.iterator(); 249 | 250 | public boolean hasNext() { 251 | return index < vals.length || extIt.hasNext(); 252 | } 253 | 254 | public java.util.Map.Entry next() { 255 | if (index < vals.length) { 256 | return new MapEntry(keys[index], vals[index++]); 257 | } 258 | return extIt.next(); 259 | } 260 | 261 | public void remove() { 262 | throw new UnsupportedOperationException(); 263 | } 264 | }; 265 | } else { 266 | return ext.iteratorFrom(key); 267 | } 268 | } 269 | 270 | public int count(){ 271 | return vals.length + RT.count(ext); 272 | } 273 | 274 | public ISeq> seq(){ 275 | return new Seq(null, def.keys, vals, 0, ext); 276 | } 277 | 278 | public IPersistentCollection empty(){ 279 | return construct(def, null); 280 | } 281 | 282 | static class Seq extends ASeq{ 283 | final int i; 284 | final ISeq keys; 285 | final Object[] vals; 286 | final IPersistentMap ext; 287 | 288 | 289 | public Seq(IPersistentMap meta, ISeq keys, Object[] vals, int i, IPersistentMap ext){ 290 | super(meta); 291 | this.i = i; 292 | this.keys = keys; 293 | this.vals = vals; 294 | this.ext = ext; 295 | } 296 | 297 | public Obj withMeta(IPersistentMap meta){ 298 | if(meta != _meta) 299 | return new Seq(meta, keys, vals, i, ext); 300 | return this; 301 | } 302 | 303 | public Object first(){ 304 | return new MapEntry(keys.first(), vals[i]); 305 | } 306 | 307 | public ISeq next(){ 308 | if(i + 1 < vals.length) 309 | return new Seq(_meta, keys.next(), vals, i + 1, ext); 310 | return ext.seq(); 311 | } 312 | } 313 | 314 | } 315 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/PersistentTreeSet.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.Comparator; 16 | 17 | import com.github.krukow.clj_ds.PersistentSortedSet; 18 | import com.github.krukow.clj_ds.TransientCollection; 19 | 20 | public class PersistentTreeSet extends APersistentSet implements IObj, Reversible, Sorted, PersistentSortedSet{ 21 | static public final PersistentTreeSet EMPTY = new PersistentTreeSet(null, PersistentTreeMap.EMPTY); 22 | final IPersistentMap _meta; 23 | 24 | 25 | static public PersistentTreeSet create(ISeq items){ 26 | PersistentTreeSet ret = EMPTY; 27 | for(; items != null; items = items.next()) 28 | { 29 | ret = (PersistentTreeSet) ret.cons(items.first()); 30 | } 31 | return ret; 32 | } 33 | 34 | static public PersistentTreeSet create(Comparator comp, ISeq items){ 35 | PersistentTreeSet ret = new PersistentTreeSet(null, new PersistentTreeMap(null, comp)); 36 | for(; items != null; items = items.next()) 37 | { 38 | ret = (PersistentTreeSet) ret.cons(items.first()); 39 | } 40 | return ret; 41 | } 42 | 43 | PersistentTreeSet(IPersistentMap meta, IPersistentMap impl){ 44 | super(impl); 45 | this._meta = meta; 46 | } 47 | 48 | public PersistentTreeSet disjoin(T key) { 49 | if(contains(key)) 50 | return new PersistentTreeSet(meta(),impl.without(key)); 51 | return this; 52 | } 53 | 54 | public PersistentTreeSet cons(T o){ 55 | if(contains(o)) 56 | return this; 57 | return new PersistentTreeSet(meta(),impl.assoc(o,o)); 58 | } 59 | 60 | public PersistentTreeSet empty(){ 61 | return new PersistentTreeSet(meta(),(PersistentTreeMap)impl.empty()); 62 | } 63 | 64 | public ISeq rseq() { 65 | return APersistentMap.KeySeq.create(((Reversible) impl).rseq()); 66 | } 67 | 68 | public PersistentTreeSet withMeta(IPersistentMap meta){ 69 | return new PersistentTreeSet(meta, impl); 70 | } 71 | 72 | public Comparator comparator(){ 73 | return ((Sorted)impl).comparator(); 74 | } 75 | 76 | public Object entryKey(Object entry){ 77 | return entry; 78 | } 79 | 80 | public ISeq seq(boolean ascending){ 81 | PersistentTreeMap m = (PersistentTreeMap) impl; 82 | return RT.keys(m.seq(ascending)); 83 | } 84 | 85 | public ISeq seqFrom(T key, boolean ascending){ 86 | PersistentTreeMap m = (PersistentTreeMap) impl; 87 | return RT.keys(m.seqFrom(key,ascending)); 88 | } 89 | 90 | public IPersistentMap meta(){ 91 | return _meta; 92 | } 93 | 94 | @Override 95 | public PersistentSortedSet zero() { 96 | return empty(); 97 | } 98 | 99 | @Override 100 | public PersistentSortedSet plus(T o) { 101 | return cons(o); 102 | } 103 | 104 | @Override 105 | public PersistentSortedSet minus(T key) { 106 | return disjoin(key); 107 | } 108 | 109 | @Override 110 | public TransientCollection asTransient() { 111 | throw new UnsupportedOperationException(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/RRBTree.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | import java.io.Serializable; 4 | import java.util.concurrent.atomic.AtomicReference; 5 | 6 | @SuppressWarnings({ "rawtypes", "serial" }) 7 | public abstract class RRBTree extends APersistentVector { 8 | /* 9 | static class Node implements Serializable { 10 | transient final AtomicReference edit; 11 | final int[] ranges; 12 | final Object[] array; 13 | 14 | Node(AtomicReference edit, Object[] array) { 15 | this.array = array; 16 | this.ranges = null; 17 | this.edit = edit; 18 | } 19 | 20 | Node(AtomicReference edit, Object[] array, int[] ranges) { 21 | this.edit = edit; 22 | this.array = array; 23 | this.ranges = ranges; 24 | } 25 | } 26 | 27 | final int cnt; 28 | final int shift; 29 | final Node root; 30 | final Object[] tail; 31 | final IPersistentMap _meta; 32 | 33 | final static AtomicReference NOEDIT = new AtomicReference(null); 34 | final static Node EMPTY_NODE = new Node(NOEDIT, new Object[0]); 35 | 36 | public final static RRBTree EMPTY = new RRBTree(0, 0, EMPTY_NODE, 37 | new Object[32]); 38 | 39 | RRBTree(int cnt, int shift, Node root, Object[] tail) { 40 | this._meta = null; 41 | this.cnt = cnt; 42 | this.shift = shift; 43 | this.root = root; 44 | this.tail = tail; 45 | } 46 | 47 | //put node's child where i is located in box 48 | //return the index of 'i' relative to the found child 49 | private static final int findNode(Node node, int i, int level, Box box) { 50 | int subidx = (i >>> level) & 0x01f; 51 | int leftCount = 0; 52 | if (node.ranges == null) { 53 | leftCount = subidx * (int) Math.pow(32, level / 5);//optimization possible 54 | } else { 55 | leftCount = node.ranges[subidx]; 56 | while (i >= leftCount) { 57 | subidx++; 58 | leftCount = node.ranges[subidx]; 59 | } 60 | } 61 | i -= leftCount; 62 | if (subidx < node.array.length) { 63 | box.val = node.array[subidx]; 64 | } else { 65 | box.val = null; 66 | } 67 | 68 | return i; 69 | } 70 | 71 | @SuppressWarnings("unchecked") 72 | public T nth(int i) { 73 | if (i >= 0 && i < cnt) { 74 | Node node = root; 75 | Box box = new Box(null); 76 | for (int level = shift; level > 0; level -= 5) { 77 | i = findNode(node, i, level, box); 78 | node = (Node) box.val; 79 | } 80 | return (T) node.array[i]; 81 | } 82 | throw new IndexOutOfBoundsException(); 83 | } 84 | 85 | public RRBTree assocN(int i, T val) { 86 | if (i >= 0 && i < cnt) { 87 | return new RRBTree(cnt, shift, 88 | doAssoc(new Box(null), shift, root, i, val), 89 | tail); 90 | } 91 | if (i == cnt) 92 | return cons(val); 93 | throw new IndexOutOfBoundsException(); 94 | } 95 | 96 | private static Node cloneNode(Node node) { 97 | return new Node(node.edit, node.array.clone(), 98 | (node.ranges == null) ? null : node.ranges.clone()); 99 | } 100 | 101 | private static int findDiff(Node node, int i, int idx) { 102 | if (node.ranges != null) { 103 | int cnt = node.ranges[idx]; 104 | while (i >= cnt) { 105 | idx += 1; 106 | cnt = node.ranges[idx]; 107 | return 1; 108 | } 109 | } 110 | return 0; 111 | } 112 | 113 | private static Node doAssoc(Box box, int level, Node parent, int i, Object val) { 114 | Node ret = cloneNode(parent); 115 | if (level == 0) { 116 | ret.array[i] = val; 117 | } else { 118 | int subidx = (i >>> level) & 0x01f; 119 | i = findNode(parent, i, level, box); 120 | ret.array[subidx] = doAssoc(box, level - 5, (Node) box.val, i, val); 121 | } 122 | return ret; 123 | } 124 | 125 | public RRBTree cons(T val) { 126 | //note there are optimizations possible here 127 | Node ret = doCons(new Box(null), root, shift, cnt-1, val); 128 | // overflow root? 129 | if (ret == null) {//optimization: this could be cached. 130 | Object[] rootChildren = new Object[2]; 131 | 132 | int newshift = shift + 5; 133 | rootChildren[0] = root; 134 | Node tailnode = new Node(root.edit, new Object[] {val}); 135 | rootChildren[1] = newPath(root.edit, shift, tailnode); 136 | Node newroot = new Node(root.edit, rootChildren, 137 | root.ranges == null ? null : new int[] { cnt }); 138 | 139 | return new RRBTree(cnt + 1, newshift, newroot, tail); 140 | } 141 | return new RRBTree(cnt + 1, shift, ret, tail); 142 | } 143 | 144 | private static Node newPath(AtomicReference edit, int level, 145 | Node node) { 146 | if (level == 0) 147 | return node; 148 | return new Node(edit, new Object[]{ newPath(edit, level - 5, node) }); 149 | } 150 | 151 | protected Node doCons(Box box, Node node, int level, int i, T val) { 152 | if (level == 0) { 153 | if (node.array.length == 32) { 154 | return null;// no room 155 | } else { 156 | Object[] newArr = new Object[node.array.length + 1]; 157 | System.arraycopy(node.array, 0,newArr , 0, node.array.length); 158 | newArr[node.array.length] = val; 159 | return new Node(node.edit, newArr, null); 160 | } 161 | } else { 162 | // warning code dup ahead 163 | int subidx = (i >>> level) & 0x01f; 164 | subidx += findDiff(node, i, subidx); 165 | i = findNode(node, i, level, box); 166 | 167 | Node ret = doCons(box, (Node)box.val, level - 5, i, val); 168 | if (ret == null) { 169 | if (node.array.length == 32) { 170 | return null;// no room 171 | } else { 172 | Object[] newArr = new Object[node.array.length + 1]; 173 | System.arraycopy(node.array, 0, newArr, 0, 174 | node.array.length); 175 | newArr[node.array.length] = newPath(node.edit, level - 5, 176 | new Node(root.edit, new Object[] { val })); 177 | int[] newRange = node.ranges; 178 | if (newArr.length < 32 && node.ranges != null) { 179 | newRange = new int[node.ranges.length + 1]; 180 | System.arraycopy(node.ranges, 0,newRange, 0, 181 | node.ranges.length); 182 | newRange[node.ranges.length] = node.ranges[node.ranges.length - 1] + 1; 183 | } 184 | return new Node(node.edit, newArr, newRange); 185 | } 186 | } 187 | Node newNode = cloneNode(node); 188 | newNode.array[subidx] = ret; 189 | return newNode; 190 | 191 | } 192 | } 193 | 194 | public IPersistentVector concatv(IPersistentVector other) { 195 | if (other instanceof RRBTree) { 196 | RRBTree t = (RRBTree) other; 197 | Box box = new Box(null); 198 | Node left = concatrec(box, ...); 199 | Node right = (Node)box.val;//left overs 200 | Node newroot = null; 201 | int newshift = this.shift; 202 | if (right == null){ 203 | newroot = left; 204 | } 205 | else if (root.array.length < 32) { 206 | Object[] newRoot = new Object[root.array.length+1]; 207 | System.arraycopy(left.array, 0, newRoot,0, left.array.length); 208 | newRoot[left.array.length] = right; 209 | newroot = new Node(root.edit,newRoot); 210 | } else { 211 | Object[] rootChildren = new Object[2]; 212 | 213 | int newshift = shift + 5; 214 | rootChildren[0] = root; 215 | Node tailnode = new Node(root.edit, new Object[] {val}); 216 | rootChildren[1] = newPath(root.edit, shift, tailnode); 217 | Node newroot = new Node(root.edit, rootChildren, 218 | root.ranges == null ? null : new int[] { cnt }); 219 | 220 | return new RRBTree(cnt + 1, newshift, newroot, tail); 221 | } 222 | return new RRBTree(this.cnt+other.count(),this.shift,left,tail); 223 | 224 | 225 | } 226 | throw new IllegalArgumentException(); 227 | 228 | } 229 | 230 | protected static RRBTree concatv(Node lroot, int lcnt, int llevel, Node rroot, int rcnt, int rlevel) { 231 | 232 | 233 | //move to bottom 234 | Node node = lroot; 235 | Box box = new Box(null); 236 | int i = lcnt-1; 237 | for (int level = llevel; level > 0; level -= 5) { 238 | i = findNode(node, i, level, box); 239 | node = (Node) box.val; 240 | } 241 | 242 | Node rnode = rroot; 243 | box = new Box(null); 244 | for (int level = rlevel; level > 0; level -= 5) { 245 | findNode(rnode, 0, level, box); 246 | rnode = (Node) box.val; 247 | } 248 | 249 | 250 | 251 | return r; 252 | 253 | } 254 | 255 | @Override 256 | public IPersistentStack pop() { 257 | throw new UnsupportedOperationException(); 258 | } 259 | 260 | public int count() { 261 | return cnt; 262 | } 263 | 264 | @SuppressWarnings("unchecked") 265 | @Override 266 | public IPersistentCollection empty() { 267 | return EMPTY; 268 | } 269 | 270 | public static void main(String[] args) { 271 | RRBTree t = RRBTree.EMPTY; 272 | for (int i=0;i<33;i++) {t = t.cons(i);} 273 | 274 | RRBTree s = RRBTree.EMPTY; 275 | for (int i=0;i<33;i++) {s = s.cons(-i);} 276 | 277 | System.out.println(t.concatv(s)); 278 | 279 | 280 | System.out.println(t); 281 | } 282 | */ 283 | } 284 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Range.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Apr 1, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public class Range extends ASeq implements IReduce, Counted{ 16 | final int end; 17 | final int n; 18 | 19 | public Range(int start, int end){ 20 | this.end = end; 21 | this.n = start; 22 | } 23 | 24 | public Range(IPersistentMap meta, int start, int end){ 25 | super(meta); 26 | this.end = end; 27 | this.n = start; 28 | } 29 | 30 | public Obj withMeta(IPersistentMap meta){ 31 | if(meta == meta()) 32 | return this; 33 | return new Range(meta(), end, n); 34 | } 35 | 36 | public Object first(){ 37 | return n; 38 | } 39 | 40 | public ISeq next(){ 41 | if(n < end-1) 42 | return new Range(_meta, n + 1, end); 43 | return null; 44 | } 45 | 46 | public Object reduce(IFn f) { 47 | Object ret = n; 48 | for(int x = n+1;x < end;x++) 49 | ret = f.invoke(ret, x); 50 | return ret; 51 | } 52 | 53 | public Object reduce(IFn f, Object start) { 54 | Object ret = f.invoke(start,n); 55 | for(int x = n+1;x < end;x++) 56 | ret = f.invoke(ret, x); 57 | return ret; 58 | } 59 | 60 | public int count() { 61 | return end - n; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Ratio.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 31, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.math.BigInteger; 16 | import java.math.BigDecimal; 17 | import java.math.MathContext; 18 | 19 | public class Ratio extends Number implements Comparable{ 20 | final public BigInteger numerator; 21 | final public BigInteger denominator; 22 | 23 | public Ratio(BigInteger numerator, BigInteger denominator){ 24 | this.numerator = numerator; 25 | this.denominator = denominator; 26 | } 27 | 28 | public boolean equals(Object arg0){ 29 | return arg0 != null 30 | && arg0 instanceof Ratio 31 | && ((Ratio) arg0).numerator.equals(numerator) 32 | && ((Ratio) arg0).denominator.equals(denominator); 33 | } 34 | 35 | public int hashCode(){ 36 | return numerator.hashCode() ^ denominator.hashCode(); 37 | } 38 | 39 | public String toString(){ 40 | return numerator.toString() + "/" + denominator.toString(); 41 | } 42 | 43 | public int intValue(){ 44 | return (int) doubleValue(); 45 | } 46 | 47 | public long longValue(){ 48 | return bigIntegerValue().longValue(); 49 | } 50 | 51 | public float floatValue(){ 52 | return (float)doubleValue(); 53 | } 54 | 55 | public double doubleValue(){ 56 | return decimalValue(MathContext.DECIMAL64).doubleValue(); 57 | } 58 | 59 | public BigDecimal decimalValue(){ 60 | return decimalValue(MathContext.UNLIMITED); 61 | } 62 | 63 | public BigDecimal decimalValue(MathContext mc){ 64 | BigDecimal numerator = new BigDecimal(this.numerator); 65 | BigDecimal denominator = new BigDecimal(this.denominator); 66 | 67 | return numerator.divide(denominator, mc); 68 | } 69 | 70 | public BigInteger bigIntegerValue(){ 71 | return numerator.divide(denominator); 72 | } 73 | 74 | public int compareTo(Object o){ 75 | Number other = (Number)o; 76 | return Numbers.compare(this, other); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Reduced.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | package com.github.krukow.clj_lang; 12 | 13 | public class Reduced implements IDeref{ 14 | Object val; 15 | 16 | public Reduced(Object val){ 17 | this.val = val; 18 | } 19 | 20 | public Object deref(){ 21 | return val; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Reflector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Apr 19, 2006 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public class Reflector { 16 | 17 | public static Object prepRet(Class c, Object x){ 18 | if (!(c.isPrimitive() || c == Boolean.class)) 19 | return x; 20 | if(x instanceof Boolean) 21 | return ((Boolean) x)?Boolean.TRUE:Boolean.FALSE; 22 | // else if(x instanceof Integer) 23 | // { 24 | // return ((Integer)x).longValue(); 25 | // } 26 | // else if(x instanceof Float) 27 | // return Double.valueOf(((Float) x).doubleValue()); 28 | return x; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Reversible.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jan 5, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface Reversible{ 16 | ISeq rseq() ; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/SeqEnumeration.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Mar 3, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.Enumeration; 16 | 17 | public class SeqEnumeration implements Enumeration{ 18 | ISeq seq; 19 | 20 | public SeqEnumeration(ISeq seq){ 21 | this.seq = seq; 22 | } 23 | 24 | public boolean hasMoreElements(){ 25 | return seq != null; 26 | } 27 | 28 | public Object nextElement(){ 29 | Object ret = RT.first(seq); 30 | seq = RT.next(seq); 31 | return ret; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/SeqIterator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jun 19, 2007 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.Iterator; 16 | import java.util.NoSuchElementException; 17 | 18 | public class SeqIterator implements Iterator{ 19 | 20 | ISeq seq; 21 | 22 | public SeqIterator(ISeq seq){ 23 | this.seq = seq; 24 | } 25 | 26 | 27 | public boolean hasNext(){ 28 | return seq != null; 29 | } 30 | 31 | public T next() throws NoSuchElementException { 32 | if(seq == null) 33 | throw new NoSuchElementException(); 34 | T ret = (T) RT.first(seq); 35 | seq = RT.next(seq); 36 | return ret; 37 | } 38 | 39 | public void remove(){ 40 | throw new UnsupportedOperationException(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Seqable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Jan 28, 2009 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | public interface Seqable { 16 | ISeq seq(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Sequential.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang; 2 | 3 | /** 4 | * Copyright (c) Rich Hickey. All rights reserved. 5 | * The use and distribution terms for this software are covered by the 6 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 7 | * which can be found in the file epl-v10.html at the root of this distribution. 8 | * By using this software in any fashion, you are agreeing to be bound by 9 | * the terms of this license. 10 | * You must not remove this notice, or any other, from this software. 11 | */ 12 | public interface Sequential { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Sorted.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Apr 15, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.util.Comparator; 16 | 17 | public interface Sorted{ 18 | Comparator comparator(); 19 | 20 | Object entryKey(Object entry); 21 | 22 | ISeq seq(boolean ascending); 23 | 24 | ISeq seqFrom(K key, boolean ascending); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/github/krukow/clj_lang/Util.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Rich Hickey. All rights reserved. 3 | * The use and distribution terms for this software are covered by the 4 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 5 | * which can be found in the file epl-v10.html at the root of this distribution. 6 | * By using this software in any fashion, you are agreeing to be bound by 7 | * the terms of this license. 8 | * You must not remove this notice, or any other, from this software. 9 | **/ 10 | 11 | /* rich Apr 19, 2008 */ 12 | 13 | package com.github.krukow.clj_lang; 14 | 15 | import java.lang.ref.Reference; 16 | import java.math.BigInteger; 17 | 18 | import com.github.krukow.clj_lang.PersistentVector.Node; 19 | 20 | import java.util.Collection; 21 | import java.util.Map; 22 | import java.util.concurrent.ConcurrentHashMap; 23 | import java.lang.ref.SoftReference; 24 | import java.lang.ref.ReferenceQueue; 25 | 26 | public class Util{ 27 | static public boolean equiv(Object k1, Object k2){ 28 | if(k1 == k2) 29 | return true; 30 | if(k1 != null) 31 | { 32 | if(k1 instanceof Number && k2 instanceof Number) 33 | return Numbers.equal((Number)k1, (Number)k2); 34 | else if(k1 instanceof IPersistentCollection || k2 instanceof IPersistentCollection) 35 | return pcequiv(k1,k2); 36 | return k1.equals(k2); 37 | } 38 | return false; 39 | } 40 | 41 | public interface EquivPred{ 42 | boolean equiv(Object k1, Object k2); 43 | } 44 | 45 | static EquivPred equivNull = new EquivPred() { 46 | public boolean equiv(Object k1, Object k2) { 47 | return k2 == null; 48 | } 49 | }; 50 | 51 | static EquivPred equivEquals = new EquivPred(){ 52 | public boolean equiv(Object k1, Object k2) { 53 | return k1.equals(k2); 54 | } 55 | }; 56 | 57 | static EquivPred equivNumber = new EquivPred(){ 58 | public boolean equiv(Object k1, Object k2) { 59 | if(k2 instanceof Number) 60 | return Numbers.equal((Number) k1, (Number) k2); 61 | return false; 62 | } 63 | }; 64 | 65 | static EquivPred equivColl = new EquivPred(){ 66 | public boolean equiv(Object k1, Object k2) { 67 | if(k1 instanceof IPersistentCollection || k2 instanceof IPersistentCollection) 68 | return pcequiv(k1, k2); 69 | return k1.equals(k2); 70 | } 71 | }; 72 | 73 | static public EquivPred equivPred(Object k1){ 74 | if(k1 == null) 75 | return equivNull; 76 | else if (k1 instanceof Number) 77 | return equivNumber; 78 | else if (k1 instanceof String) 79 | return equivEquals; 80 | else if (k1 instanceof Collection || k1 instanceof Map) 81 | return equivColl; 82 | return equivEquals; 83 | } 84 | 85 | static public boolean equiv(long k1, long k2){ 86 | return k1 == k2; 87 | } 88 | 89 | static public boolean equiv(Object k1, long k2){ 90 | return equiv(k1, (Object)k2); 91 | } 92 | 93 | static public boolean equiv(long k1, Object k2){ 94 | return equiv((Object)k1, k2); 95 | } 96 | 97 | static public boolean equiv(double k1, double k2){ 98 | return k1 == k2; 99 | } 100 | 101 | static public boolean equiv(Object k1, double k2){ 102 | return equiv(k1, (Object)k2); 103 | } 104 | 105 | static public boolean equiv(double k1, Object k2){ 106 | return equiv((Object)k1, k2); 107 | } 108 | 109 | static public boolean equiv(boolean k1, boolean k2){ 110 | return k1 == k2; 111 | } 112 | 113 | static public boolean equiv(Object k1, boolean k2){ 114 | return equiv(k1, (Object)k2); 115 | } 116 | 117 | static public boolean equiv(boolean k1, Object k2){ 118 | return equiv((Object)k1, k2); 119 | } 120 | 121 | static public boolean equiv(char c1, char c2) { 122 | return c1 == c2; 123 | } 124 | 125 | static public boolean pcequiv(Object k1, Object k2){ 126 | if(k1 instanceof IPersistentCollection) 127 | return ((IPersistentCollection)k1).equiv(k2); 128 | return ((IPersistentCollection)k2).equiv(k1); 129 | } 130 | 131 | static public boolean equals(Object k1, Object k2){ 132 | if(k1 == k2) 133 | return true; 134 | return k1 != null && k1.equals(k2); 135 | } 136 | 137 | static public boolean identical(Object k1, Object k2){ 138 | return k1 == k2; 139 | } 140 | 141 | static public Class classOf(Object x){ 142 | if(x != null) 143 | return x.getClass(); 144 | return null; 145 | } 146 | 147 | static public int compare(Object k1, Object k2){ 148 | if(k1 == k2) 149 | return 0; 150 | if(k1 != null) 151 | { 152 | if(k2 == null) 153 | return 1; 154 | if(k1 instanceof Number) 155 | return Numbers.compare((Number) k1, (Number) k2); 156 | return ((Comparable) k1).compareTo(k2); 157 | } 158 | return -1; 159 | } 160 | 161 | static public int hash(Object o){ 162 | if(o == null) 163 | return 0; 164 | return o.hashCode(); 165 | } 166 | 167 | public static int hasheq(Object o){ 168 | if(o == null) 169 | return 0; 170 | if(o instanceof IHashEq) 171 | return dohasheq((IHashEq) o); 172 | if(o instanceof Number) 173 | return Numbers.hasheq((Number)o); 174 | return o.hashCode(); 175 | } 176 | 177 | private static int dohasheq(IHashEq o) { 178 | return o.hasheq(); 179 | } 180 | 181 | static public int hashCombine(int seed, int hash){ 182 | //a la boost 183 | seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); 184 | return seed; 185 | } 186 | 187 | static public boolean isPrimitive(Class c){ 188 | return c != null && c.isPrimitive() && !(c == Void.TYPE); 189 | } 190 | 191 | static public boolean isInteger(Object x){ 192 | return x instanceof Integer 193 | || x instanceof Long 194 | || x instanceof BigInt 195 | || x instanceof BigInteger; 196 | } 197 | 198 | static public Object ret1(Object ret, Object nil){ 199 | return ret; 200 | } 201 | static public Node ret1(Node ret, Object nil){ 202 | return ret; 203 | } 204 | static public Object[] ret1(Object[] ret, Object nil){ 205 | return ret; 206 | } 207 | 208 | static public ISeq ret1(ISeq ret, Object nil){ 209 | return ret; 210 | } 211 | 212 | static public void clearCache(ReferenceQueue rq, ConcurrentHashMap> cache){ 213 | //cleanup any dead entries 214 | if(rq.poll() != null) 215 | { 216 | while(rq.poll() != null) 217 | ; 218 | for(Map.Entry> e : cache.entrySet()) 219 | { 220 | Reference val = e.getValue(); 221 | if(val != null && val.get() == null) 222 | cache.remove(e.getKey(), val); 223 | } 224 | } 225 | } 226 | 227 | static public RuntimeException runtimeException(String s){ 228 | return new RuntimeException(s); 229 | } 230 | 231 | static public RuntimeException runtimeException(String s, Throwable e){ 232 | return new RuntimeException(s, e); 233 | } 234 | 235 | /** 236 | * Throw even checked exceptions without being required 237 | * to declare them or catch them. Suggested idiom: 238 | *

239 | * throw sneakyThrow( some exception ); 240 | */ 241 | static public RuntimeException sneakyThrow(Throwable t) { 242 | // http://www.mail-archive.com/javaposse@googlegroups.com/msg05984.html 243 | if (t == null) 244 | throw new NullPointerException(); 245 | Util.sneakyThrow0(t); 246 | return null; 247 | } 248 | 249 | @SuppressWarnings("unchecked") 250 | static private void sneakyThrow0(Throwable t) throws T { 251 | throw (T) t; 252 | } 253 | 254 | } -------------------------------------------------------------------------------- /src/test/java/com/github/krukow/clj_lang/test/AllTests.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang.test; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.junit.runners.Suite; 5 | 6 | @RunWith(Suite.class) 7 | @Suite.SuiteClasses( { 8 | PersistentHashSetTest.class, 9 | PersistentVectorTest.class, 10 | PersistentHashMapTest.class }) 11 | public class AllTests {} 12 | -------------------------------------------------------------------------------- /src/test/java/com/github/krukow/clj_lang/test/PersistentHATTrieTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.github.krukow.clj_lang.test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertNull; 8 | 9 | import java.util.Map; 10 | 11 | import org.junit.Test; 12 | 13 | import com.github.krukow.clj_lang.PersistentHATTrie; 14 | 15 | /** 16 | * @author krukow 17 | * 18 | */ 19 | public class PersistentHATTrieTest { 20 | 21 | 22 | PersistentHATTrie createTrie() { 23 | PersistentHATTrie trie = (PersistentHATTrie) PersistentHATTrie.EMPTY.addMember("we",0); 24 | trie = (PersistentHATTrie) trie.addMember("were",1); 25 | trie = (PersistentHATTrie) trie.addMember("went",2); 26 | trie = (PersistentHATTrie) trie.addMember("west",3); 27 | trie = (PersistentHATTrie) trie.addMember("water",4); 28 | trie = (PersistentHATTrie) trie.addMember("western",5); 29 | trie = (PersistentHATTrie) trie.addMember("tri",6); 30 | trie = (PersistentHATTrie) trie.addMember("fork",7); 31 | trie = (PersistentHATTrie) trie.addMember("trifork",8); 32 | trie = (PersistentHATTrie) trie.addMember("forks",9); 33 | return trie; 34 | } 35 | @Test 36 | public final void testSmallTrie() { 37 | PersistentHATTrie trie = createTrie(); 38 | assertEquals(10, trie.count()); 39 | 40 | assertEquals(0, trie.getMember("we")); 41 | assertEquals(1, trie.getMember("were")); 42 | assertEquals(2, trie.getMember("went")); 43 | assertEquals(3, trie.getMember("west")); 44 | assertEquals(4, trie.getMember("water")); 45 | assertEquals(5, trie.getMember("western")); 46 | assertEquals(6, trie.getMember("tri")); 47 | assertEquals(7, trie.getMember("fork")); 48 | assertEquals(8, trie.getMember("trifork")); 49 | assertEquals(9, trie.getMember("forks")); 50 | } 51 | 52 | @Test 53 | public final void doesNotContainNotAdded() { 54 | PersistentHATTrie trie = createTrie(); 55 | assertNull(trie.getMember("wes")); 56 | assertNull(trie.getMember("w")); 57 | assertNull(trie.getMember("wents")); 58 | assertNull(trie.getMember("westee")); 59 | assertNull(trie.getMember("tris")); 60 | assertNull(trie.getMember("sfork")); 61 | assertNull(trie.getMember("tri2fork")); 62 | assertNull(trie.getMember("forksa")); 63 | } 64 | 65 | @Test 66 | public final void testIterator() { 67 | PersistentHATTrie trie = createTrie(); 68 | int count =0; 69 | System.out.println(trie.toString()); 70 | for (Map.Entry s:trie) { 71 | System.out.println(s); 72 | count++; 73 | } 74 | assertEquals(10,count); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/com/github/krukow/clj_lang/test/PersistentHashMapTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.github.krukow.clj_lang.test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | import static org.junit.Assert.assertTrue; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.HashSet; 12 | import java.util.Iterator; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.TreeMap; 16 | import java.util.Map.Entry; 17 | 18 | import org.junit.Test; 19 | 20 | import com.github.krukow.clj_lang.IPersistentMap; 21 | import com.github.krukow.clj_lang.PersistentHashMap; 22 | 23 | /** 24 | * @author krukow 25 | * 26 | */ 27 | public class PersistentHashMapTest { 28 | 29 | 30 | /** 31 | * Test method for {@link com.github.krukow.clj_lang.PersistentHashMap#emptyMap()}. 32 | */ 33 | @Test 34 | public final void testEmptyMap() { 35 | PersistentHashMap genMap = PersistentHashMap.emptyMap(); 36 | assertEquals(0, genMap.count()); 37 | PersistentHashMap genMap2 = PersistentHashMap.emptyMap(); 38 | assertEquals(0, genMap2.count()); 39 | assert(genMap == (PersistentHashMap) genMap2); 40 | } 41 | 42 | 43 | @Test 44 | public final void testNullMap() { 45 | PersistentHashMap genMap = PersistentHashMap.emptyMap(); 46 | genMap = (PersistentHashMap) genMap.assoc(null, 42); 47 | genMap = (PersistentHashMap) genMap.assoc("43", 43); 48 | Iterator> iterator = genMap.iterator(); 49 | assertTrue(iterator.hasNext()); 50 | assertEquals(42, (int) genMap.get(null)); 51 | int count=0; 52 | boolean nullKey = false; 53 | for (Map.Entry e:genMap) { 54 | count+=1; 55 | if (e.getKey()==null) { 56 | nullKey = true; 57 | assertEquals(42, (int)e.getValue()); 58 | } else { 59 | assertEquals(43, (int)e.getValue()); 60 | } 61 | 62 | } 63 | assertEquals(2, count); 64 | assertTrue(nullKey); 65 | } 66 | 67 | 68 | @Test 69 | public final void testIteratorFrom() { 70 | final int N = 20; 71 | IPersistentMap genMap = PersistentHashMap.emptyMap(); 72 | for (int i=0;i l = new ArrayList(20); 82 | for (Map.Entry e: genMap) { 83 | l.add(e.getKey()); 84 | } 85 | 86 | assertEquals(20, l.size()); 87 | 88 | 89 | int index = 10; 90 | int count = 0; 91 | for (Iterator> iterator = genMap.iteratorFrom(l.get(index)); iterator.hasNext();) { 92 | Entry next = iterator.next(); 93 | assertEquals(l.get(index), next.getKey()); 94 | index++; 95 | count++; 96 | } 97 | assertEquals(10, count); 98 | 99 | 100 | } 101 | 102 | /** 103 | * Test method for {@link com.github.krukow.clj_lang.PersistentHashMap#create(java.util.Map)}. 104 | */ 105 | @Test 106 | public final void testCreateMapOfQextendsKQextendsV() { 107 | Map input = new TreeMap(); 108 | int N = 10; 109 | for (int i=0;i output = PersistentHashMap.create(input); 113 | 114 | for (int i=0;i ib = PersistentHashMap.create(1,false,2,true,3,false); 131 | assertEquals(false, ib.get(1)); 132 | assertEquals(true, ib.get(2)); 133 | assertEquals(false, ib.get(3)); 134 | 135 | } 136 | 137 | /** 138 | * Test method for {@link com.github.krukow.clj_lang.PersistentHashMap#create(java.lang.Object[])}. 139 | */ 140 | @Test(expected=ClassCastException.class) 141 | public final void testBadInvocCreateObjectArray() { 142 | PersistentHashMap bad = PersistentHashMap.create(1,false,2,"true",3,false); 143 | Boolean b = bad.get(2); 144 | } 145 | 146 | 147 | /** 148 | * NB: this methods takes a long time to run. Be patient. 149 | * Test method for {@link com.github.krukow.clj_lang.PersistentHashMap#iterator()}. 150 | */ 151 | @Test 152 | public final void testIterator() { 153 | IPersistentMap dsMap = PersistentHashMap.emptyMap(); 154 | HashSet hs = null; 155 | for (int i = 0; i < 33000; i++) { 156 | hs = new HashSet(); 157 | for (Map.Entry o : dsMap) { 158 | hs.add(o.getKey()); 159 | assertEquals(o.getKey(), o.getValue()); 160 | } 161 | assertEquals(i, hs.size()); 162 | Integer o = new Integer(i); 163 | dsMap = dsMap.assoc(o, o); 164 | } 165 | 166 | } 167 | 168 | @Test 169 | public final void testRandomIterator() { 170 | final int N = 33000; 171 | IPersistentMap genMap = PersistentHashMap.emptyMap(); 172 | for (int i=0;i hs = new HashSet(); 178 | for (Map.Entry e: genMap) { 179 | hs.add(e.getKey()); 180 | } 181 | assertEquals(N, hs.size()); 182 | 183 | } 184 | 185 | @Test 186 | public final void testRandomReverseIterator() { 187 | final int N = 33000; 188 | IPersistentMap genMap = PersistentHashMap.emptyMap(); 189 | for (int i=0;i e: genMap) { 196 | lst.add(e.getKey()); 197 | } 198 | for (Iterator> it = ((PersistentHashMap) genMap).reverseIterator();it.hasNext();) { 199 | Map.Entry e= it.next(); 200 | Double removed = (Double) lst.remove(lst.size()-1); 201 | assertEquals(removed, e.getKey()); 202 | assertEquals(removed+"", e.getValue()); 203 | } 204 | assertEquals(0, lst.size()); 205 | 206 | } 207 | 208 | 209 | } 210 | -------------------------------------------------------------------------------- /src/test/java/com/github/krukow/clj_lang/test/PersistentHashSetTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.github.krukow.clj_lang.test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | import java.util.HashSet; 9 | 10 | import org.junit.Test; 11 | 12 | import com.github.krukow.clj_lang.IPersistentCollection; 13 | import com.github.krukow.clj_lang.PersistentHashSet; 14 | import com.github.krukow.clj_lang.PersistentVector; 15 | import com.github.krukow.clj_lang.RT; 16 | 17 | /** 18 | * @author krukow 19 | * 20 | */ 21 | public class PersistentHashSetTest { 22 | 23 | 24 | @Test 25 | public final void testEmptyVector() { 26 | PersistentHashSet vecI = PersistentHashSet.emptySet(); 27 | assertEquals(0, vecI.size()); 28 | PersistentHashSet vecS = PersistentHashSet.emptySet(); 29 | assertEquals(0, vecS.size()); 30 | assert(vecI == (PersistentHashSet) vecS); 31 | } 32 | 33 | /** 34 | * * NB: this methods takes a long time to run. Be patient. 35 | */ 36 | @Test 37 | public final void testIterator() { 38 | PersistentHashSet dsSet = PersistentHashSet.emptySet(); 39 | HashSet hs = null; 40 | for (int i = 0; i < 20000; i++) { 41 | hs = new HashSet(); 42 | for (Integer o : dsSet) { 43 | hs.add(o); 44 | } 45 | assertEquals(i,hs.size()); 46 | Integer o = new Integer(i); 47 | dsSet = (PersistentHashSet) dsSet.cons(o); 48 | 49 | } 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/github/krukow/clj_lang/test/PersistentNonHashMapsTest.java: -------------------------------------------------------------------------------- 1 | package com.github.krukow.clj_lang.test; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Map.Entry; 10 | 11 | import org.junit.Test; 12 | 13 | import com.github.krukow.clj_lang.Cons; 14 | import com.github.krukow.clj_lang.MapEntry; 15 | import com.github.krukow.clj_lang.PersistentArrayMap; 16 | import com.github.krukow.clj_lang.PersistentStructMap; 17 | import com.github.krukow.clj_lang.PersistentStructMap.Def; 18 | 19 | public class PersistentNonHashMapsTest { 20 | 21 | /* 22 | 23 | PersistentArrayMap.java 24 | PersistentStructMap.java 25 | PersistentTreeMap.java 26 | 27 | */ 28 | @Test 29 | public final void testArrayMap() { 30 | PersistentArrayMap am = PersistentArrayMap.createWithCheck(new Object[]{ 31 | "1",1,"2",2,"3",3,"4",4,"5",5}); 32 | List> l = new ArrayList>(); 33 | int i=1; 34 | for (Map.Entry e:am) { 35 | l.add(e); 36 | assertEquals(i, (int) e.getValue()); 37 | assertEquals(i+"", e.getKey()); 38 | i += 1; 39 | } 40 | 41 | i=3; 42 | for (Iterator> it = am.iteratorFrom("3");it.hasNext();) { 43 | System.out.println(l.get(i)); 44 | assertEquals(l.get(i++), it.next()); 45 | } 46 | assertEquals(5, i); 47 | 48 | for(Iterator> rit = am.reverseIterator();rit.hasNext();) { 49 | assertEquals(l.get(--i), rit.next()); 50 | } 51 | assertEquals(0,i); 52 | 53 | } 54 | 55 | @Test 56 | public final void testStructMap() { 57 | Def def = PersistentStructMap.createSlotMap( 58 | new Cons("1", new Cons("2", new Cons("3",null)))); 59 | PersistentStructMap sm = PersistentStructMap.construct(def, 60 | new Cons(1,new Cons(2,new Cons(3,null)))); 61 | 62 | for (int i=4;i<10000;i++) { 63 | sm = (PersistentStructMap) sm.assoc(i+"", i); 64 | } 65 | List> l = new ArrayList>(); 66 | for (Map.Entry e: sm) {l.add(e);} 67 | assertEquals(new MapEntry("1",1),l.get(0)); 68 | assertEquals(new MapEntry("2",2),l.get(1)); 69 | assertEquals(new MapEntry("3",3),l.get(2)); 70 | 71 | assertEquals(9999,l.size()); 72 | 73 | int i=9999; 74 | for (Iterator> rit = sm.reverseIterator();rit.hasNext();) { 75 | assertEquals(l.get(--i),rit.next()); 76 | } 77 | assertEquals(0,i); 78 | 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/com/github/krukow/clj_lang/test/PersistentVectorTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.github.krukow.clj_lang.test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | import java.util.HashSet; 9 | 10 | import org.junit.Test; 11 | 12 | import com.github.krukow.clj_lang.AFn; 13 | import com.github.krukow.clj_lang.IFn; 14 | import com.github.krukow.clj_lang.IPersistentVector; 15 | import com.github.krukow.clj_lang.ISeq; 16 | import com.github.krukow.clj_lang.PersistentVector; 17 | import com.github.krukow.clj_lang.Util; 18 | 19 | /** 20 | * @author krukow 21 | * 22 | */ 23 | public class PersistentVectorTest { 24 | 25 | @Test 26 | public final void testEmptyVector() { 27 | PersistentVector vecI = PersistentVector.emptyVector(); 28 | assertEquals(0, vecI.size()); 29 | PersistentVector vecS = PersistentVector.emptyVector(); 30 | assertEquals(0, vecS.size()); 31 | assert(vecI == (PersistentVector) vecS); 32 | } 33 | 34 | /** 35 | * * NB: this methods takes a long time to run. Be patient. 36 | */ 37 | @Test 38 | public final void testIterator() { 39 | PersistentVector vec = PersistentVector.emptyVector(); 40 | HashSet hs = null; 41 | int N = 32*32*32+33; 42 | //Checking all states up to: N 43 | for (int i = 0; i < N; i++) { 44 | hs = new HashSet(); 45 | int expected = 0; 46 | for (Integer o : vec) { 47 | assert(expected == o); 48 | expected += 1; 49 | hs.add(o); 50 | } 51 | assertEquals(i,hs.size()); 52 | Integer o = new Integer(i); 53 | vec = vec.cons(o); 54 | } 55 | } 56 | 57 | 58 | /** 59 | * * NB: this methods takes a long time to run. Be patient. 60 | */ 61 | @Test 62 | public final void testVectorMap() { 63 | PersistentVector vec = PersistentVector.emptyVector(); 64 | HashSet hs = null; 65 | int N = 32*32*32+33; 66 | //Checking all states up to: N 67 | for (int i = 0; i < N; i++) { 68 | vec = vec.cons(i); 69 | 70 | } 71 | IPersistentVector vector = PersistentVector.vectormap(new AFn() { 72 | @Override 73 | public Object invoke(Object arg1) { 74 | Integer s = (Integer )arg1; 75 | return s.intValue()*2; 76 | } 77 | }, vec); 78 | assertEquals(vec.length(), vector.length()); 79 | for (int i = 0; i < N; i++) { 80 | assertEquals(i*2, vector.nth(i)); 81 | 82 | } 83 | } 84 | 85 | } 86 | --------------------------------------------------------------------------------