2

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!

  • 1
    What's your goal? Having an easy way to know if a number belongs to the Fibonacci sequence? – Gaël J Mar 21 '22 at 20:38
  • @GaëlJ I would like to implement a form of memoization using Lazy Data Structures given any function. For instance, in the Fibonacci sequence example, just doing LazyList.generate(n => fibonacci(n)) would generate all Fibonacci numbers and if you need to access a certain result numerous times, you would only have to compute the result once and the rest would be accessed in O(n) (hence the question if that could be implemented in Lazy Vectors, so the access time would be reduced in O(Log32(n)). I hope I made myself clear :D – Gabriel Santana Paredes Mar 21 '22 at 21:32

1 Answers1

1

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.

Dima
  • 39,570
  • 6
  • 44
  • 70
  • Thank you! The problem with using mutable data structures is that the memoize function that you describe is only implemented for the Fibonacci sequence and also, is thread-unsafe. Anyway, thanks for replying! – Gabriel Santana Paredes Mar 30 '22 at 16:22
  • 1
    @GabrielSantanaParedes change it to `ConcurrentHashMap` if you need it to be thread safe. As for being specific to fibonacci, that was your question, so ... You can change `fib` method to do whatever you want it to do. Or change `object` to `class`, and take `compute` as an argument if you like. – Dima Mar 30 '22 at 17:09