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

Ignoring arguments while pattern matching #73

Open
gneuvill opened this issue May 17, 2017 · 4 comments
Open

Ignoring arguments while pattern matching #73

gneuvill opened this issue May 17, 2017 · 4 comments

Comments

@gneuvill
Copy link
Contributor

It may happen that value constructors of an ADT take, say, five or more arguments. The pattern matching clause generated by derive4j can then become a bit ugly (necessitating a huge lambda expression) especially when you only need a few of all the arguments.

Would it be possible to generate "matchers" that would accept "tupled" lambdas ? (see the following example)

@Data(flavour = Flavour.FJ)
static abstract class Staff { // a dumb type
    Staff() {}

    interface Cases<R> {
        R Common(String name1, String name2, String name3, String name4, Integer age, String adress);
        R Admin(String name1, String name2, String name3, String name4, Integer age, String adress, String role);
    }

    abstract <R> R match(Cases<R> cases);
}

// current state of affairs
IO<Unit> test(Staff staff) {
    return Staffs.caseOf(staff)
        .Common((name1, name2, name3, name4, age, adress) -> IOFunctions.stdoutPrint(name3))
            
        .Admin((name1, name2, name3, name4, age, adress, role) -> IOFunctions.stdoutPrint(role));
}

// proposition
IO<Unit> tupledLambda(Staff staff) {
    return Staffs.caseOf(staff)
        // alternative name to preserve type inference (not sure it would be necessary)
        ._Common(__ -> IOFunctions.stdoutPrint(__._3())) // '__' would be of type P6<String, String, String, String, Integer, String>
            
        ._Admin(__ -> IOFunctions.stdoutPrint(__._7())); // '__' would be of type P7<...>
}

What do you think ?

@jbgi
Copy link
Member

jbgi commented May 17, 2017

Looks like String name1, String name2, String name3, String name4, Integer age, String adress should go into its own product type, no?

@gneuvill
Copy link
Contributor Author

Well in that case yes, but it was just an example ; creating yet another product type is not always possible or desirable. Anyway, my point is just one of syntactic convenience : sometimes having your type completely de-structured is what you want ; sometimes being able to pick just the data you need is handier.

I guess we could also see this "auto-tupling" feature as a kind of poor-man's as-pattern...

@jbgi
Copy link
Member

jbgi commented Mar 22, 2018

I think I got an idea for this:

@Data(flavour = Flavour.FJ)
public static abstract class Staff { // a dumb type
    Staff() {}

    interface Cases<R> {
        R Common(String name1, String name2, String name3, String name4, Integer age, String adress);
        R Admin(String name1, String name2, String name3, String name4, Integer age, String adress, String role);
    }

    public abstract <R> R match(Cases<R> cases);

    public abstract Staffs.Evaluated eval();
}

would generate in Staffs.java:

   // will use `sealed` semantic once supported by jdk:
  public static abstract class Evaluated extends Staff {
    Evaluated(){}
     // generated only when targetting jdk that do not support pattern matching:
    public abstract R match(F<Common, R> common, F<Admin, R> admin);
  }

 public static final class Common extends Evaluated {
  public final String name1;
  public final String name2;
  ....
   public R match(F<Common, R> common, F<Admin, R> admin) {
       return common.f(this);
   }
}
....

This should also ease support for built-in pattern matching when it comes, while preserving the lazy constructor functionality.

WDYT?

@gneuvill
Copy link
Contributor Author

Seems clever, as usual... Do you think having Staff 's subtypes public could mess with type inference (as I think was/is the case in scala ?) ?

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

2 participants