Enhanced iterator
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
These declarations are "shallow" in the sense that they are not really compiled, only the type-checker uses them
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface class ReadOnlyArray<out T> : ISized {
|
||||||
|
[operator] fun get(index : Int) : T
|
||||||
|
}
|
||||||
|
|
||||||
|
interface class WriteOnlyArray<in T> : ISized { // This is needed to keep IIterator's <T> covariant
|
||||||
|
[operator] fun set(index : Int, value : T)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutableArray<T> : ReadOnlyArray<T>, WriteOnlyArray<T> {...}
|
||||||
@@ -1,4 +1,25 @@
|
|||||||
interface class IIterator<out T> {
|
interface class IIterator<out T> {
|
||||||
fun next() : T
|
fun next() : T
|
||||||
val hasNext : Boolean
|
val hasNext : Boolean
|
||||||
|
|
||||||
|
fun toArray(buffer : WriteOnlyArray<T>) : Int { // T is still an in-parameter
|
||||||
|
return fillBuffer(buffer, 0, buffer.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toArray(buffer : WriteOnlyArray<T>, from : Int, length : Int) : Int { // T is still an in-parameter
|
||||||
|
if (from < 0 || from > buffer.lastIndex || length < 0 || length > buffer.size - from) {
|
||||||
|
throw IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) return 0;
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
for (i in [from .. from + length - 1]) {
|
||||||
|
if (!hasNext)
|
||||||
|
return count
|
||||||
|
buffer[i] = next()
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
interface class IList<out T> : IIterable<T>, ISizable {
|
interface class IList<out T> : IIterable<T>, ISized {
|
||||||
[operator] fun get(index : Int) : T
|
[operator] fun get(index : Int) : T
|
||||||
val isEmpty : Boolean
|
val isEmpty : Boolean
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,13 @@
|
|||||||
interface class IMutableIterator<out T> : IIterator<T> {
|
interface class IMutableIterator<out T> : IIterator<T> {
|
||||||
fun remove() : T
|
fun remove() : T
|
||||||
|
|
||||||
|
/*
|
||||||
|
Considerations:
|
||||||
|
pro: why not + non iteration breaking
|
||||||
|
con: counter-intuitive for, e.g., TreeSet
|
||||||
|
|
||||||
|
|
||||||
|
fun addBefore(item : T) : Boolean
|
||||||
|
fun addAfter(item : T) : Boolean
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
@@ -15,14 +15,14 @@ class LinkedList<T> : IMutableList<T> {
|
|||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
newItem.next = head
|
newItem.next = head
|
||||||
head = newItem
|
head = newItem
|
||||||
if (tail == null) {
|
if (tail === null) {
|
||||||
tail = head
|
tail = head
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var insertAfter = itemAt(index)
|
var insertAfter = itemAt(index)
|
||||||
newItem.next = insertAfter.next
|
newItem.next = insertAfter.next
|
||||||
insertAfter.next = newItem
|
insertAfter.next = newItem
|
||||||
if (tail == insertAfter) {
|
if (tail === insertAfter) {
|
||||||
tail = newItem
|
tail = newItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,13 +37,13 @@ class LinkedList<T> : IMutableList<T> {
|
|||||||
override fun remove(index : Int) : T {
|
override fun remove(index : Int) : T {
|
||||||
checkIndex(index)
|
checkIndex(index)
|
||||||
val item = itemAt(index)
|
val item = itemAt(index)
|
||||||
if (item == head) {
|
if (item === head) {
|
||||||
head = item.next
|
head = item.next
|
||||||
if (head == null)
|
if (head === null)
|
||||||
tail= null
|
tail= null
|
||||||
} else {
|
} else {
|
||||||
item.previous.next = item.next
|
item.previous.next = item.next
|
||||||
if (item.next == null) {
|
if (item.next === null) {
|
||||||
item.next.previous = item.previous
|
item.next.previous = item.previous
|
||||||
} else {
|
} else {
|
||||||
tail = tail.previous
|
tail = tail.previous
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
interface class IAdder<in T> {
|
||||||
|
fun add(item : T) : Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface class ICloseable {
|
||||||
|
fun close()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class JavaCloseableWrapper(closeable : java.io.Closeable) : ICloseable(closeable)
|
||||||
|
|
||||||
|
fun streamCopy<T>(from : IIterable<T>, to : IAdder<T>) {
|
||||||
|
for (item in from) t.add(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileInput : IIterator<Byte>, JavaCloseableWrapper {
|
||||||
|
private val stream : InputStream
|
||||||
|
private var next : Int
|
||||||
|
private var nextUsed = false
|
||||||
|
|
||||||
|
this(file : File) : JavaCloseableWrapper(stream) { // implicitly throws IOException
|
||||||
|
stream = FileInputStream(file) // throws IOException
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun next() {
|
||||||
|
if (!nextUsed) {
|
||||||
|
nextUsed = true
|
||||||
|
return next.as<Byte>
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
override val hasNext {
|
||||||
|
get() { // implicitly throws IOException
|
||||||
|
if (nextUsed && next != -1) {
|
||||||
|
nextUsed = false
|
||||||
|
next = stream.read() // throws IOException
|
||||||
|
}
|
||||||
|
return next != -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileOutput throws IOException : IAdder<Byte>, JavaCloseableWrapper {
|
||||||
|
private val stream : OutputStream
|
||||||
|
|
||||||
|
this(file : File) : JavaCloseableWrapper(stream) {
|
||||||
|
stream = FileOutputStream(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun add(item : Byte) {
|
||||||
|
stream.write(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun example() { // this does not rethrow, no appropriate parameters given
|
||||||
|
|
||||||
|
val f1 : File = ...
|
||||||
|
val f2 : File = ...
|
||||||
|
|
||||||
|
streamCopy(FileInput(f1), f2) // throws IOException, you must catch or rethrow explicitly
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
interface class IIterable<T> throws <E> {
|
||||||
|
fun next() : T // implicitly throws <E>
|
||||||
|
val hasNext : Boolean // implicitly throws <E>, but actually may NOT!!!
|
||||||
|
}
|
||||||
|
|
||||||
|
interface class IAdder<T> throws <E> {
|
||||||
|
fun add(item : T) : Boolean // implicitly throws <E>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface class ICloseable throws <E> {
|
||||||
|
fun close()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class JavaCloseableWrapper(closeable : java.io.Closeable) throws <IOException> : ICloseable { // Maybe we can delegate here
|
||||||
|
override fun close() {
|
||||||
|
closeable.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun streamCopy<T>(from : IIterable<T>, to : IAdder<T>) { // implicitly rethrows
|
||||||
|
for (item in from) t.add(item) // both implicitly throw <E>
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileInput throws <IOException> : IIterable<Byte>, JavaCloseableWrapper {
|
||||||
|
private val stream : InputStream
|
||||||
|
private var next : Int
|
||||||
|
private var nextUsed = false
|
||||||
|
|
||||||
|
this(file : File) : JavaCloseableWrapper(stream) { // implicitly throws IOException
|
||||||
|
stream = FileInputStream(file) // throws IOException
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun next() {
|
||||||
|
if (!nextUsed) {
|
||||||
|
nextUsed = true
|
||||||
|
return next.as<Byte>
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
override val hasNext {
|
||||||
|
get() { // implicitly throws IOException
|
||||||
|
if (nextUsed && next != -1) {
|
||||||
|
nextUsed = false
|
||||||
|
next = stream.read() // throws IOException
|
||||||
|
}
|
||||||
|
return next != -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileOutput throws IOException : IAdder<Byte>, JavaCloseableWrapper {
|
||||||
|
private val stream : OutputStream
|
||||||
|
|
||||||
|
this(file : File) : JavaCloseableWrapper(stream) {
|
||||||
|
stream = FileOutputStream(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun add(item : Byte) {
|
||||||
|
stream.write(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun example() { // this does not rethrow, no appropriate parameters given
|
||||||
|
|
||||||
|
val f1 : File = ...
|
||||||
|
val f2 : File = ...
|
||||||
|
|
||||||
|
streamCopy(FileInput(f1), f2) // throws IOException, you must catch or rethrow explicitly
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user