Help with deprecation warning

I asked this question on gitter but I think the answer is too involved for that forum.

I’m trying to convert some 2.12 code to 2.13 and I don’t understand how the code ever worked in the first place.

I get the following compilation warning:

method foreach in class IterableOnceExtensionMethods is deprecated (since 2.13.0): Use .iterator.foreach(...) instead
      minterm <- genDnfFromBitMask(n,m, 5000, _=>true)

The code is here def of genDnfFromBitMask

There are a few suggested ways of fixing this. The one that works most easily is to just insert a .iterator on the offending line

minterm <- genDnfFromBitMask(n,m, 5000, _=>true).iterator

However, I don’t understand why it doesn’t also work to change the return type of the function. And in fact, I don’t understand why the current function definition even works in the first place. The function, genDnfFromBitMask, is defined with return type IterableOnce[List[Int]] . However, the value in tail position within the function has parametrised type List[A]. Where is IterableOnce coming from?

Also If I try to change IterableOnce to Iterator, then the code no longer compiles, giving the error

missing parameter type

Inheritance. A List implements LinearSeqOps which implements IterableOps which extends IterableOnce.

Look at the scaladoc and expand the “Linear Supertypes” accordion item: List

A List is not an Iterator. So you cannot simply return a List where an Iterator is expected. In your example, this leads to the unfortunate type parameter missing error, since the compiler cannot infer the type for A when calling withCollector. You could fix that by specifying List[Int] directly, which will give you:

   withCollector[List[Int]] { collect =>

| type mismatch;
| found   : List[List[Int]]
| required: Iterator[List[Int]]

To make it work, you could do:

    withCollector[List[Int]] { collect =>
      (0 to Math.min(1 << n, maxNumTerms)).foreach { truthTableRow =>
        if (f(truthTableRow))
          collect(minTerm(n, truthTableRow))
      }
    }.iterator
2 Likes

Thanks. I think the original purpose was to prevent the entire sequence from being generated in one fell swoop, but rather have part generated as needed. I’m not sure if that ever worked, but simply adding .iterator to the end won’t make the sequence lazily generated. Will it?

No, Scala is strict by default. So it will first generate the List and then create an Iterator for it.

With Scala 2.13 you could use a LazyList instead.

1 Like

so I think my old code never worked anyway. So there’s no reason to try to make this bizarre change. Just make it a list?

Sure, it’s a List - so make it a List.

1 Like

right! got it. The code should/could be optimized. But that is not necessary to convert the code that exists to be used in 2.13 and satisfy all the migration issues.