Skip to content
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

Introduce Gen.zipWith multi-arity method #1062

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

satorg
Copy link
Contributor

@satorg satorg commented Jul 14, 2024

Adds a code generator for Gen.zipWith functions.

Example:

case class Foo(pos: Int, ascii: String, hex: String)

Gen.zipWith(Gen.posNum[Int], Gen.asciiStr, Gen.hexStr)(Foo.apply)

Without Gen.zipWith the same was possible to accomplish with Gen.zip, however it would required an additional map over an intermediary tuple instance:

Gen.zip(Gen.posNum[Int], Gen.asciiStr, Gen.hexStr)
  .map { case (pos, ascii, hex) => Foo(pos, ascii, hex)) }

Therefore Gen.zipWith allows to avoid the intermediate conversion which can come in handy in come cases.

Note that Gen.zipWith starts with arity 2 whereas Gen.zip starts with arity 1.
However, I think the latter was an oversight – Gen.zip for arity 1 is a no-op function.

@rossabaker
Copy link
Member

Is this intended to behave similarly to mapN, but without the Cats dependency?

@satorg
Copy link
Contributor Author

satorg commented Aug 13, 2024

Is this intended to behave similarly to mapN, but without the Cats dependency?

Pretty much. To be more accurate, it is supposed to resemble functions map2 through map22 of the Apply typeclass, because mapN requires a tuple to be created first, check this out:

case class Foo(pos: Int, ascii: String, hex: String)

val gen1 = (Gen.posNum[Int], Gen.asciiStr, Gen.hexStr).mapN { Foo.apply }

val gen2 = Apply[Gen].map3(Gen.posNum[Int], Gen.asciiStr, Gen.hexStr) { Foo.apply }

val gen3 = Gen.zipWith(Gen.posNum[Int], Gen.asciiStr, Gen.hexStr) { Foo.apply }

However, there's one catch with the Cats functions: they both use a chain of Functor.product under the hood, which in turn calls to Gen.zip with arity 2. I.e. the Cats functions incur a bunch of intermediary tuples on every evaluation to be created.

@satorg satorg force-pushed the gen-zip-with branch 2 times, most recently from e206580 to cad9980 Compare September 1, 2024 01:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants