softwaremill / softwaremill/quicklens

Surprising behaviour on Stream using "modify", "each" and "using"

Open
#291 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
852
Forks
53
PR merge metrics
No merged PRs in 30d

Description

When I use "modify", "each" and "using" with a side-effectful function on a Stream, the result is surprising.

Consider this minimal example:

import com.softwaremill.quicklens.{modify, QuicklensEach}

import scala.collection.immutable.Stream.Empty
import scala.collection.mutable

case class A(x: Int)

val regularSeq = Seq(A(1), A(3))
val lazySeq1   = Seq(A(1), A(3)).groupBy(_.x).mapValues(_.head).values.toSeq
val lazySeq2   = Stream.cons(A(1), Stream.cons(A(3), Empty))

def test(s: Seq[A]): Unit = {
  val buffer = mutable.ArrayBuffer[Int]()
  val modifier1 = modify(_: Seq[A])(_.each.x).using { e =>
    buffer += e
    e
  }
  val modifier2 = modify(_: Seq[A])(_.each.x).using(_ + 1)

  modifier1(s)
  println(buffer)
  println(modifier2(s))
}

test(regularSeq) // output: ArrayBuffer(1, 3)
                 //         List(A(2), A(4))
test(lazySeq1).  // output: ArrayBuffer(1)
                 //         Stream(A(2), ?)
test(lazySeq2).  // output: ArrayBuffer(1)
                 //         Stream(A(2), ?)

The surprising part is that the buffer which is filled as a side-effect only contains the first element, and - in contrast to the resulting Stream - there is no indication that this may not be the complete result.

I understand that this side-effectful usage is not optimal, but since it is possible, I would appreciate more feedback from the library that I may be missing some elements here.

P.S.: Quicklens is a great tool, thank you very much for your efforts!

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no source file or test; start at the modify(...).each...using entry point and reproduce the supplied examples with regularSeq, lazySeq1, and lazySeq2. Compare the side-effect output and resulting Stream, then add coverage for the agreed behavior or feedback when lazy elements are not fully evaluated.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.