/core/src/main/scala/scalaz/ImmutableArray.scala

http://github.com/scalaz/scalaz · Scala · 323 lines · 247 code · 58 blank · 18 comment · 14 complexity · c8dd6f6fa28bac4ada2cc652f275513e MD5 · raw file

  1. package scalaz
  2. import reflect.ClassTag
  3. import scala.collection.immutable.IndexedSeq
  4. import scala.collection.mutable.{ArrayBuilder, Builder}
  5. import syntax.Ops
  6. /**
  7. * An immutable wrapper for arrays
  8. *
  9. * @tparam A type of the elements of the array
  10. */
  11. sealed abstract class ImmutableArray[+A] {
  12. protected[this] def elemTag: ClassTag[A]
  13. // these methods are not total
  14. private[scalaz] def apply(index: Int): A
  15. private[scalaz] def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit
  16. def length: Int
  17. def isEmpty: Boolean = length == 0
  18. def toArray[B >: A : ClassTag]: Array[B]
  19. def slice(from: Int, until: Int): ImmutableArray[A]
  20. def ++[B >: A: ClassTag](other: ImmutableArray[B]): ImmutableArray[B]
  21. }
  22. sealed abstract class ImmutableArrayInstances {
  23. implicit def immutableArrayEqual[A](implicit A: Equal[A]): Equal[ImmutableArray[A]] =
  24. Equal.equal{ (a, b) =>
  25. (a.length == b.length) && (0 until a.length).forall(i => A.equal(a(i), b(i)))
  26. }
  27. implicit val immutableArrayInstance: Foldable[ImmutableArray] with Zip[ImmutableArray] =
  28. new Foldable[ImmutableArray] with Zip[ImmutableArray] {
  29. override def foldLeft[A, B](fa: ImmutableArray[A], z: B)(f: (B, A) => B) =
  30. fa.foldLeft(z)(f)
  31. def foldMap[A, B](fa: ImmutableArray[A])(f: A => B)(implicit F: Monoid[B]): B = {
  32. var i = 0
  33. var b = F.zero
  34. while(i < fa.length){
  35. b = F.append(b, f(fa(i)))
  36. i += 1
  37. }
  38. b
  39. }
  40. def foldRight[A, B](fa: ImmutableArray[A], z: => B)(f: (A, => B) => B) =
  41. fa.foldRight(z)((a, b) => f(a, b))
  42. def zip[A, B](a: => ImmutableArray[A], b: => ImmutableArray[B]) = {
  43. val _a = a
  44. if(_a.isEmpty) new ImmutableArray.ofRef(Array[(A, B)]())
  45. else new ImmutableArray.ofRef((_a.iterator zip b.iterator).toArray)
  46. }
  47. override def index[A](fa: ImmutableArray[A], i: Int) =
  48. if(0 <= i && i < fa.length) Some(fa(i)) else None
  49. override def length[A](fa: ImmutableArray[A]) =
  50. fa.length
  51. override def empty[A](fa: ImmutableArray[A]) =
  52. fa.isEmpty
  53. override def all[A](fa: ImmutableArray[A])(f: A => Boolean) = {
  54. val len = fa.length
  55. @annotation.tailrec
  56. def loop(i: Int): Boolean = {
  57. if(i < len) f(fa(i)) && loop(i + 1)
  58. else true
  59. }
  60. loop(0)
  61. }
  62. override def any[A](fa: ImmutableArray[A])(f: A => Boolean) = {
  63. val len = fa.length
  64. @annotation.tailrec
  65. def loop(i: Int): Boolean = {
  66. if(i < len) f(fa(i)) || loop(i + 1)
  67. else false
  68. }
  69. loop(0)
  70. }
  71. }
  72. }
  73. object ImmutableArray extends ImmutableArrayInstances {
  74. def make[A](x: AnyRef): ImmutableArray[A] = {
  75. val y = x match {
  76. case null => null
  77. case x: Array[Byte] => new ofByte(x)
  78. case x: Array[Short] => new ofShort(x)
  79. case x: Array[Char] => new ofChar(x)
  80. case x: Array[Int] => new ofInt(x)
  81. case x: Array[Long] => new ofLong(x)
  82. case x: Array[Float] => new ofFloat(x)
  83. case x: Array[Double] => new ofDouble(x)
  84. case x: Array[Boolean] => new ofBoolean(x)
  85. case x: Array[Unit] => new ofUnit(x)
  86. case x: Array[AnyRef] => new ofRef(x)
  87. case x: String => new StringArray(x)
  88. }
  89. y.asInstanceOf[ImmutableArray[A]]
  90. }
  91. /**
  92. * Wrap `x` in an `ImmutableArray`.
  93. *
  94. * Provides better type inference than `make[A]`
  95. */
  96. def fromArray[A](x: Array[A]): ImmutableArray[A] = {
  97. val y = x.asInstanceOf[AnyRef] match {
  98. case null => null
  99. case x: Array[Byte] => new ofByte(x)
  100. case x: Array[Short] => new ofShort(x)
  101. case x: Array[Char] => new ofChar(x)
  102. case x: Array[Int] => new ofInt(x)
  103. case x: Array[Long] => new ofLong(x)
  104. case x: Array[Float] => new ofFloat(x)
  105. case x: Array[Double] => new ofDouble(x)
  106. case x: Array[Boolean] => new ofBoolean(x)
  107. case x: Array[Unit] => new ofUnit(x)
  108. case _: Array[AnyRef] => new ofRef(x.asInstanceOf[Array[AnyRef]])
  109. }
  110. y.asInstanceOf[ImmutableArray[A]]
  111. }
  112. /** Wrap the characters in `str` in an `ImmutableArray` */
  113. def fromString(str: String): ImmutableArray[Char] = new StringArray(str)
  114. def newBuilder[A](implicit elemTag: ClassTag[A]): Builder[A, ImmutableArray[A]] =
  115. ArrayBuilder.make[A].mapResult(make(_))
  116. def newStringArrayBuilder: Builder[Char, ImmutableArray[Char]] =
  117. (new StringBuilder).mapResult(fromString(_))
  118. sealed abstract class ImmutableArray1[+A](array: Array[A]) extends ImmutableArray[A] {
  119. private[this] val arr = array.clone
  120. // override def stringPrefix = "ImmutableArray"
  121. // override protected[this] def newBuilder = ImmutableArray.newBuilder[A](elemTag)
  122. def componentType: Class[_] = arr.getClass().getComponentType
  123. def apply(idx: Int) = arr(idx)
  124. def length = arr.length
  125. def toArray[B >: A : ClassTag] = arr.clone.asInstanceOf[Array[B]]
  126. def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = { arr.copyToArray(xs, start, len) }
  127. def slice(from: Int, until: Int) = fromArray(arr.slice(from, until))
  128. // TODO can do O(1) for primitives
  129. override def ++[B >: A: ClassTag](other: ImmutableArray[B]) = {
  130. val newArr = new Array(length + other.length)
  131. this.copyToArray(newArr, 0, length)
  132. other.copyToArray(newArr, length, other.length)
  133. fromArray(newArr)
  134. }
  135. }
  136. final class ofRef[A <: AnyRef](array: Array[A]) extends ImmutableArray1[A](array) {
  137. protected[this] lazy val elemTag = ClassTag[A](componentType)
  138. }
  139. final class ofByte(array: Array[Byte]) extends ImmutableArray1[Byte](array) {
  140. protected[this] def elemTag = ClassTag.Byte
  141. }
  142. final class ofShort(array: Array[Short]) extends ImmutableArray1[Short](array) {
  143. protected[this] def elemTag = ClassTag.Short
  144. }
  145. final class ofChar(array: Array[Char]) extends ImmutableArray1[Char](array) {
  146. protected[this] def elemTag = ClassTag.Char
  147. // def mkString = new String(arr)
  148. // TODO why can elemTag be protected, but arr can't?
  149. }
  150. final class ofInt(array: Array[Int]) extends ImmutableArray1[Int](array) {
  151. protected[this] def elemTag = ClassTag.Int
  152. }
  153. final class ofLong(array: Array[Long]) extends ImmutableArray1[Long](array) {
  154. protected[this] def elemTag = ClassTag.Long
  155. }
  156. final class ofFloat(array: Array[Float]) extends ImmutableArray1[Float](array) {
  157. protected[this] def elemTag = ClassTag.Float
  158. }
  159. final class ofDouble(array: Array[Double]) extends ImmutableArray1[Double](array) {
  160. protected[this] def elemTag = ClassTag.Double
  161. }
  162. final class ofBoolean(array: Array[Boolean]) extends ImmutableArray1[Boolean](array) {
  163. protected[this] def elemTag = ClassTag.Boolean
  164. }
  165. final class ofUnit(array: Array[Unit]) extends ImmutableArray1[Unit](array) {
  166. protected[this] def elemTag = ClassTag.Unit
  167. }
  168. final class StringArray(val str: String) extends ImmutableArray[Char] {
  169. protected[this] def elemTag = ClassTag.Char
  170. // override protected[this] def newBuilder = (new StringBuilder).mapResult(new StringArray(_))
  171. def apply(idx: Int) = str(idx)
  172. def length = str.length
  173. def toArray[B >: Char : ClassTag] = str.toArray
  174. def copyToArray[B >: Char](xs: Array[B], start: Int, len: Int): Unit = {
  175. xs match {
  176. case xs0: Array[Char] =>
  177. str.copyToArray(xs0, start, len)
  178. case _ =>
  179. str.toCharArray.copyToArray(xs, start, len)
  180. }
  181. }
  182. def slice(from: Int, until: Int) = new StringArray(str.slice(from, until))
  183. def ++[B >: Char: ClassTag](other: ImmutableArray[B]) =
  184. other match {
  185. case other: StringArray => new StringArray(str + other.str)
  186. case _ => {
  187. val newArr = new Array[B](length + other.length)
  188. this.copyToArray(newArr, 0, length)
  189. other.copyToArray(newArr, length, other.length)
  190. fromArray(newArr)
  191. }
  192. }
  193. }
  194. implicit def wrapArray[A](immArray: ImmutableArray[A]): WrappedImmutableArray[A] = {
  195. import ImmutableArray.{WrappedImmutableArray => IAO}
  196. immArray match {
  197. case a: StringArray => new IAO.ofStringArray(a)
  198. case a: ofRef[_] => new IAO.ofRef(a)
  199. case a: ofByte => new IAO.ofByte(a)
  200. case a: ofShort => new IAO.ofShort(a)
  201. case a: ofChar => new IAO.ofChar(a)
  202. case a: ofInt => new IAO.ofInt(a)
  203. case a: ofLong => new IAO.ofLong(a)
  204. case a: ofFloat => new IAO.ofFloat(a)
  205. case a: ofDouble => new IAO.ofDouble(a)
  206. case a: ofBoolean => new IAO.ofBoolean(a)
  207. case a: ofUnit => new IAO.ofUnit(a)
  208. }
  209. }
  210. implicit def unwrapArray[A](immArrayOps: WrappedImmutableArray[A]): ImmutableArray[A] = immArrayOps.value
  211. abstract class WrappedImmutableArray[+A](val value: ImmutableArray[A]) extends
  212. IndexedSeq[A] {
  213. def apply(index: Int) = value(index)
  214. def length = value.length
  215. protected[this] def arrayBuilder: Builder[A, ImmutableArray[A]]
  216. }
  217. object WrappedImmutableArray {
  218. import scalaz.{ImmutableArray => IA}
  219. class ofStringArray(val strArray: StringArray) extends WrappedImmutableArray[Char](strArray) {
  220. override protected[this] def arrayBuilder = (new StringBuilder).mapResult(str => new StringArray(str.toString))
  221. }
  222. abstract class ofImmutableArray1[+A](val immArray: ImmutableArray1[A]) extends WrappedImmutableArray[A](immArray) {
  223. protected[this] def elemTag: ClassTag[A]
  224. override protected[this] def arrayBuilder = ImmutableArray.newBuilder[A](elemTag)
  225. }
  226. final class ofRef[+A <: AnyRef](array: IA.ofRef[A]) extends ofImmutableArray1[A](array) {
  227. protected[this] lazy val elemTag = ClassTag[A](array.componentType)
  228. }
  229. final class ofByte(array: IA.ofByte) extends ofImmutableArray1[Byte](array) {
  230. protected[this] def elemTag = ClassTag.Byte
  231. }
  232. final class ofShort(array: IA.ofShort) extends ofImmutableArray1[Short](array) {
  233. protected[this] def elemTag = ClassTag.Short
  234. }
  235. final class ofChar(array: IA.ofChar) extends ofImmutableArray1[Char](array) {
  236. protected[this] def elemTag = ClassTag.Char
  237. }
  238. final class ofInt(array: IA.ofInt) extends ofImmutableArray1[Int](array) {
  239. protected[this] def elemTag = ClassTag.Int
  240. }
  241. final class ofLong(array: IA.ofLong) extends ofImmutableArray1[Long](array) {
  242. protected[this] def elemTag = ClassTag.Long
  243. }
  244. final class ofFloat(array: IA.ofFloat) extends ofImmutableArray1[Float](array) {
  245. protected[this] def elemTag = ClassTag.Float
  246. }
  247. final class ofDouble(array: IA.ofDouble) extends ofImmutableArray1[Double](array) {
  248. protected[this] def elemTag = ClassTag.Double
  249. }
  250. final class ofBoolean(array: IA.ofBoolean) extends ofImmutableArray1[Boolean](array) {
  251. protected[this] def elemTag = ClassTag.Boolean
  252. }
  253. final class ofUnit(array: IA.ofUnit) extends ofImmutableArray1[Unit](array) {
  254. protected[this] def elemTag = ClassTag.Unit
  255. }
  256. }
  257. sealed class ImmutableArrayCharW(val self: ImmutableArray[Char]) extends Ops[ImmutableArray[Char]] {
  258. def asString: String = self match {
  259. case a: StringArray => a.str
  260. case a: ofChar => wrapArray(a).mkString
  261. case _ => sys.error("Unknown subtype of ImmutableArray[Char]")
  262. }
  263. }
  264. implicit def wrapRopeChar(array: ImmutableArray[Char]): ImmutableArrayCharW = new ImmutableArrayCharW(array)
  265. }