如何使用 Scala 中的给定函数或属性定义无限惰性列表?

发布于 2025-01-16 08:59:05 字数 1146 浏览 1 评论 0原文

我最近在 Rock the JVM 中看到了一门高级 Scala 课程,在一节课中,Daniel 打算使用属性(从 A 到布尔值的函数)创建一个集合,该集合的实现 可以找到在这里

例如,他能够通过这样做创建一个“包含”所有自然数的集合:

val naturals = PBSet[Int](_ => true)

然后他可以通过执行 naturals.contains(input) 来验证输入是否包含在该集合内。

我的问题是,有没有办法使用惰性列表甚至更好的惰性向量或惰性映射来完成此任务?

例如,给定一个返回第 n 个斐波那契数的 fibonacci(n) 函数,包含该函数所有可能输出的惰性列表将如下所示:

val allFibonacciNumbers: LazyList[Long] = LazyList.generate(n => fibonacci(n))

我知道可以通过以下方式完成类似的操作这样做:

val allFibonacciNumbersV2: LazyList[Long] = LazyList.iterate(0L)(n => n + 1).map(n => fibonacci(n))

该实现的问题是迭代函数的起始值:它不会给出任何函数的所有可能输出,而只会给出之后的输出。

那么,如何使用基于 Porperty 的 Set 和 Lazy List 的组合来完成这样的任务呢?或者甚至更好,使用惰性向量或惰性映射?

我找不到类似的东西,我能找到的最接近的是基于属性的测试,但仅此而已。

感谢您的巨大帮助和阅读我的问题。祝你有美好的一天!

I recently was seeing an advanced Scala course in Rock the JVM and, in one lesson, Daniel purposed to create a set using propertys (functions going from A to Boolean), the implementation of this Set can be found here.

For example, he was able to create a set "containing" all the naturals by doing this:

val naturals = PBSet[Int](_ => true)

Then he could verify if an input was contained inside that set by doing naturals.contains(input).

My question is, is there any way to accomplish this using Lazy Lists or even better, Lazy Vectors or Lazy Maps?

For instance, given a fibonacci(n) function that returns the nth Fibonacci number, a lazy list containing all the posible outputs for that function would look like something like this:

val allFibonacciNumbers: LazyList[Long] = LazyList.generate(n => fibonacci(n))

I know something similiar could be done by doing this:

val allFibonacciNumbersV2: LazyList[Long] = LazyList.iterate(0L)(n => n + 1).map(n => fibonacci(n))

The problem of that implementation is the start value of the iterate function: It is not going to give all the possible outputs of any function, just the ones after that.

So, how could such a task be accomplished using a combination of the Porperty based Set and the Lazy List? Or even better, with a Lazy Vector or Lazy Map?

I couldn't find anything similar, the closest I could find was something called property based test but that's about it.

Thank you for the immense help and for reading my question. Have a great day!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情深缘浅 2025-01-23 08:59:05

好吧,没有开箱即用的“LazyMap”,但是自行推出是相当简单的。

您的评论听起来好像您已经知道如何使用 LazyList 计算斐波那契,从那里,您只需要记住结果:

object FF { 
   val fm = mutable.Map.empty[Int, BigInt] 
   val fib: LazyList[BigInt] = BigInt(0) #:: BigInt(1) #:: 
       fib.zip(fib.tail).map(p => p._1 + p._2)
   def apply(n: Int) = fm.getOrElseUpdate(n, fib(n))
}

现在,像 FF(100) 这样的东西第一次是线性的,并且时间恒定在那之后。
如果先执行 FF(100),然后执行 FF(99),则第二次调用第一次仍然是线性的。从技术上讲,它也可以优化为恒定时间,因为 fib(99) 已经可用,但我认为不值得这么麻烦……以及额外的存储空间。

Well, there is no "LazyMap" out of the box, but it is rather trivial to just roll your own.

Your comments sound like you already know how to compute Fibonacci with a LazyList, from there, you just need to memoize the result:

object FF { 
   val fm = mutable.Map.empty[Int, BigInt] 
   val fib: LazyList[BigInt] = BigInt(0) #:: BigInt(1) #:: 
       fib.zip(fib.tail).map(p => p._1 + p._2)
   def apply(n: Int) = fm.getOrElseUpdate(n, fib(n))
}

Now, things like FF(100) are linear the first time, and constant time after that.
If you do FF(100), and then FF(99), that second call is still linear for the first time though. Technically, it could be optimized to be constant time too, because fib(99) is already available, but I don't think it's worth the trouble ... and extra storage.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文