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

Generator for type with more than 2 properties #39

Open
reedrosenbluth opened this issue Jan 19, 2018 · 3 comments
Open

Generator for type with more than 2 properties #39

reedrosenbluth opened this issue Jan 19, 2018 · 3 comments

Comments

@reedrosenbluth
Copy link

Is there a cleaner syntax for creating a Gen for a type with more than 2 properties than what I have below? This starts to get ugly for types with more properties...

private Gen<Cylinder> cylinders() {
    return radii().zip(heights(), (radius, height) -> {
        return colors().map(color -> new Cylinder(radius, height, color));
    }
}

private Gen<Integer> heights() {
    return integers().from(79).upToAndIncluding(1004856);
}

private Gen<Integer> radii() {
    return integers().allPositive();
}

private Gen<String> colors() {
    return Generate.pick(Arrays.asList("Red", "Green", "Blue"));
}
@hcoles
Copy link
Contributor

hcoles commented Jan 19, 2018

Zip is overloaded so you can combine up to three Gens, so your example can be written as.

Gen<Cylinder> cs = radii().zip(heights(), colours(), (r,h,c) -> new Cylinder(r,h,c));

So things currently start to get ugly at four.

This needs to be extended to support more values but it needs to stop somewhere (6?), at which point the best solution is probably to fix the modelling of the type being generated.

I'm open to suggestions of other ways the api could allow Gens to be combined.

hcoles pushed a commit that referenced this issue Jan 19, 2018
@danwallach
Copy link

You might consider having a generator for "tuples" of various arities, such that you might then write:

Gen<Cylinder> cs = tuples(radii(), heights(), colours()).map((r,h,c) -> new Cylinder(r,h,c));

This is approximately the same as your zip() method, but it seems somewhat cleaner to have all three components of a Cylinder represented at the same level, as arguments to a tuple-generator.

@danwallach
Copy link

danwallach commented Feb 15, 2018

Also, consider the following code snippet:

private static Gen<RGBColor> colors() {
  return doubles().between(0, 1).map((r, g, b) -> RGBColor.color(r, g, b));
}

It's super cool to be able to map a scalar onto a tuple-type like this. When you do this, however, IntelliJ helpfully highlights the lambda, saying "lambda can be replaced with a method reference". Unfortunately, because map is overloaded for lambdas of different arities, IntelliJ's helpful code rewriter generates this:

private static Gen<RGBColor> colors() {
  return doubles().between(0, 1).map((Function3<Double, Double, Double, RGBColor>) RGBColor::color);
}

Suggestion: how about having methods called map2, map3, and so forth, either in addition to or instead of the overloading of map? This would avoid the need for the verbose typecast.

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

No branches or pull requests

3 participants