Skip to content

Commit 06e1add

Browse files
committed
Redesign NonEmptyLazyList to be maximally lazy
This commit does not include docs or tests.
1 parent 60bb1fe commit 06e1add

File tree

1 file changed

+79
-27
lines changed

1 file changed

+79
-27
lines changed

core/src/main/scala-2.13+/cats/data/NonEmptyLazyList.scala

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,47 @@ object NonEmptyLazyList extends NonEmptyLazyListInstances {
6262
def fromSeq[A](as: Seq[A]): Option[NonEmptyLazyList[A]] =
6363
if (as.nonEmpty) Option(create(LazyList.from(as))) else None
6464

65-
def fromLazyListPrepend[A](a: A, ca: LazyList[A]): NonEmptyLazyList[A] =
66-
create(a +: ca)
65+
def fromLazyListPrepend[A](a: => A, ll: => LazyList[A]): NonEmptyLazyList[A] =
66+
create(a #:: ll)
6767

68-
def fromLazyListAppend[A](ca: LazyList[A], a: A): NonEmptyLazyList[A] =
69-
create(ca :+ a)
68+
def fromLazyListAppend[A](ll: => LazyList[A], a: => A): NonEmptyLazyList[A] =
69+
create(ll #::: a #:: LazyList.empty)
7070

7171
def apply[A](a: => A, as: A*): NonEmptyLazyList[A] =
7272
create(a #:: LazyList.from(as))
7373

74+
// allows the creation of fully lazy `NonEmptyLazyList`s by prepending to this
75+
def maybe[A](ll: => LazyList[A]): Maybe[A] = new Maybe(() => ll)
76+
77+
final class Maybe[A] private[NonEmptyLazyList] (private[this] var mkLL: () => LazyList[A]) {
78+
// because instances of this class are created explicitly, they might be
79+
// reused, and we don't want to re-evaluate `mkLL`
80+
private[this] lazy val ll = {
81+
val res = mkLL()
82+
mkLL = null // allow GC
83+
res
84+
}
85+
86+
def #::[B >: A](elem: => B): NonEmptyLazyList[B] =
87+
create(elem #:: ll)
88+
def #:::[B >: A](prefix: => NonEmptyLazyList[B]): NonEmptyLazyList[B] =
89+
create(prefix.toLazyList #::: ll)
90+
def #:::[B >: A](prefix: => LazyList[B]): Maybe[B] =
91+
new Maybe(() => prefix #::: ll)
92+
}
93+
94+
final class Deferrer[A] private[NonEmptyLazyList] (private val nell: () => NonEmptyLazyList[A]) extends AnyVal {
95+
def #::[B >: A](elem: => B): NonEmptyLazyList[B] =
96+
create(elem #:: nell().toLazyList)
97+
def #:::[B >: A](prefix: => NonEmptyLazyList[B]): NonEmptyLazyList[B] =
98+
create(prefix.toLazyList #::: nell().toLazyList)
99+
def #:::[B >: A](prefix: => LazyList[B]): NonEmptyLazyList[B] =
100+
create(prefix #::: nell().toLazyList)
101+
}
102+
103+
implicit def toDeferrer[A](nell: => NonEmptyLazyList[A]): Deferrer[A] =
104+
new Deferrer(() => nell)
105+
74106
implicit def catsNonEmptyLazyListOps[A](value: NonEmptyLazyList[A]): NonEmptyLazyListOps[A] =
75107
new NonEmptyLazyListOps(value)
76108
}
@@ -118,11 +150,7 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
118150
final def +:[AA >: A](a: AA): NonEmptyLazyList[AA] =
119151
prepend(a)
120152

121-
/**
122-
* Alias for [[prepend]].
123-
*/
124-
// TODO: `a` should be by-name and this method should not be listed as an
125-
// alias for `prepend`, but it's too late to change that in this version
153+
@deprecated("use Deferrer construction instead")
126154
final def #::[AA >: A](a: AA): NonEmptyLazyList[AA] =
127155
prepend(a)
128156

@@ -139,52 +167,76 @@ class NonEmptyLazyListOps[A](private val value: NonEmptyLazyList[A])
139167
append(a)
140168

141169
/**
142-
* concatenates this with `ll`
170+
* Concatenates this with `ll`; equivalent to `appendLazyList`
171+
*/
172+
final def concat[AA >: A](ll: => LazyList[AA]): NonEmptyLazyList[AA] =
173+
appendLazyList(ll)
174+
175+
/**
176+
* Alias for `concat`
143177
*/
144-
final def concat[AA >: A](ll: LazyList[AA]): NonEmptyLazyList[AA] =
145-
create(toLazyList ++ ll)
178+
final def ++[AA >: A](ll: => LazyList[AA]): NonEmptyLazyList[AA] =
179+
concat(ll)
146180

147181
/**
148-
* Concatenates this with `nell`
182+
* Concatenates this with `nell`; equivalent to `appendNell`
149183
*/
150-
final def concatNell[AA >: A](nell: NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
151-
create(toLazyList ++ nell.toLazyList)
184+
final def concatNell[AA >: A](nell: => NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
185+
appendNell(nell)
152186

153187
/**
154-
* Alias for concatNell
188+
* Alias for `concatNell`
155189
*/
156-
final def ++[AA >: A](nell: NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
190+
final def ++[AA >: A](nell: => NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
157191
concatNell(nell)
158192

159193
/**
160194
* Appends the given LazyList
161195
*/
162-
final def appendLazyList[AA >: A](nell: LazyList[AA]): NonEmptyLazyList[AA] =
163-
create(toLazyList ++ nell)
196+
final def appendLazyList[AA >: A](ll: => LazyList[AA]): NonEmptyLazyList[AA] =
197+
create(toLazyList #::: ll)
164198

165199
/**
166200
* Alias for `appendLazyList`
167201
*/
168-
final def :++[AA >: A](c: LazyList[AA]): NonEmptyLazyList[AA] =
169-
appendLazyList(c)
202+
final def :++[AA >: A](ll: => LazyList[AA]): NonEmptyLazyList[AA] =
203+
appendLazyList(ll)
204+
205+
/**
206+
* Prepends the given NonEmptyLazyList
207+
*/
208+
final def appendNell[AA >: A](nell: => NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
209+
create(toLazyList #::: nell.toLazyList)
210+
211+
/**
212+
* Alias for `appendNell`
213+
*/
214+
final def :++[AA >: A](nell: => NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
215+
appendNell(nell)
170216

171217
/**
172218
* Prepends the given LazyList
173219
*/
174-
final def prependLazyList[AA >: A](c: LazyList[AA]): NonEmptyLazyList[AA] =
175-
create(c ++ toLazyList)
220+
final def prependLazyList[AA >: A](ll: => LazyList[AA]): NonEmptyLazyList[AA] =
221+
create(ll #::: toLazyList)
222+
223+
/**
224+
* Alias for `prependLazyList`
225+
*/
226+
final def ++:[AA >: A](ll: => LazyList[AA]): NonEmptyLazyList[AA] =
227+
prependLazyList(ll)
176228

177229
/**
178230
* Prepends the given NonEmptyLazyList
179231
*/
180-
final def prependNell[AA >: A](c: NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
181-
create(c.toLazyList ++ toLazyList)
232+
final def prependNell[AA >: A](nell: => NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
233+
create(nell.toLazyList #::: toLazyList)
182234

183235
/**
184236
* Alias for `prependNell`
185237
*/
186-
final def ++:[AA >: A](c: NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
187-
prependNell(c)
238+
final def ++:[AA >: A](nell: => NonEmptyLazyList[AA]): NonEmptyLazyList[AA] =
239+
prependNell(nell)
188240

189241
/**
190242
* Converts this NonEmptyLazyList to a `NonEmptyList`.

0 commit comments

Comments
 (0)