-
Notifications
You must be signed in to change notification settings - Fork 21
Very lazy LazyList creation #11105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@NthPortal just some stuff off the top of my head. I can delete it if it is utter nonsense 😁 Reasoning for a Lazy Fetching this data is very expensive,and so you want to cache the results of the data in the users session. The api from the clients perspective is to ask for a given index within the date range supplied. For convenience you may have some kind of Session that looks like the following.
Implementing the same thing with a mutable data structure
Reasoning not to have it: you can always use the current unfold and map to achieve the same result
Not sure if this is too contrived though 👌 Sorry for the dodgy pseudo Scala and formatting, I did it on my phone. |
@javax-swing if you have a fixed date range, you can use |
I think actually a very compelling usecase is testing the laziness of private[this] val heads = new Array[Boolean](count)
private[this] val states = new Array[Boolean](count)
private[this] def gen(index: Int): LazyList[Int] = {
def f(): Int = {
heads(index) = true
index
}
LazyList.unfold(0) { _ => { states(index) = true; None } } #::: f() #:: LazyList.empty[Int]
}
private[this] def genList(): LazyList[Int] = {
def doGen(n: Int): LazyList[Int] =
if (n < count) gen(n) #::: doGen(n + 1)
else LazyList.unfold(0)(_ => None)
doGen(0)
} If we think about adding a method to simplify the implementation, we might try something like this: def unfoldLazy[A, S](init: S)(f: S => Option[(() => A, S)]): LazyList[A] = ??? This allows us to rewrite the testing implementation as follows: private[this] val heads = new Array[Boolean](count)
private[this] val states = new Array[Boolean](count)
private[this] def genList(): LazyList[Int] = LazyList.unfoldLazy(0) { index =>
if (index >= count) None
else {
states(index) = true
Some(() => { heads(index) = true; index }, index + 1)
}
} In fact, at this point, the definition of
|
@NthPortal Even if the state part is lazy, you could still replicate both with https://scastie.scala-lang.org/S44MPq47R0eTDGxvpo4Q5A If people were so inclined to delay the computation of |
I'm wondering if there is value in having def unfoldLazy[A, S](init: S)(f: S => Option[(() => A, S)]): LazyList[A] = ??? in order to reduce allocation over @javax-swing's suggestion. Internally, For comparison: // taken from @javax-swing's scastie
val lazyList1: LazyList[A] = LazyList.unfold(1) {
s => Some(() => s * s, s + 1)
}.map(_.apply())
val lazyList2: LazyList[A] = LazyList.unfoldLazy(1) {
s => Some(() => s * s, s + 1)
} |
Rejected by #11307 |
Uh oh!
There was an error while loading. Please reload this page.
Currently,
LazyList
has two forms of laziness:head
ortail
of theLazyList
does not cause the evaluation of previoushead
s.Of
LazyList
's factory methods, none support both kinds of laziness.unfold
andfrom
(when called with anIterator
orView
) support the first kind, but have to evaluate previous elements in order to know if the collection contains subsequent elements.tabulate
,fill
andcontinually
support the second kind of laziness, but their sizes are known at construction (infinity in the case ofcontinually
). The lazy#::
method can only be used to create non-emptyLazyList
s as well.In theory,
#:::
can be used to combineLazyList
s of 0 or 1 elements which are lazy in the first way, thus making the elements independently lazy; however, this seems to have poor usability both from API and performance perspectives (also it may not be stack-safe).What factory method (or other strategy) can we use to create a
LazyList
with both kinds of laziness? Is this even a useful feature? I do not personally have a motivating example, but that doesn't mean that none exists.The text was updated successfully, but these errors were encountered: