A possibly novel construct for type-safe key/value pairs

Behrang Saeedzadeh behrangsa at gmail.com
Sun Jul 5 09:46:55 UTC 2020


I was reading [1] on Reddit and thought about the topic of syntax sugar for
maps that has been discussed many times before which would allow us write:

    User david = usersService.findBy("name" -> "David");

Instead of:

    User david = usersService.bind(1, "David").findBy("this.name = ?1");

Or if Java had symbols:

    User david = usersService.findBy(:name -> "David");
    // or
    User david = usersService.findBy(name: "David");


But what if we could make this typesafe?

Let's assume `User` is defined as:


    @Entity
    public class User {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;

        private String name;

        private String occupation;

        private LocalDateTime createdAt;

        private LocalDateTime updatedAt;

        public User() {
        }

        // Get/Set omitted by brevity
    }


If Java had:

* Symbols
* And syntax sugar for key-value pairs

And a "novel" [2] `Property<T>` (or `Getter<T>`) construct that we could
only assign properties (getters) of type `T` to its instances, for example:


    Getter<User> userId = User::getId;         // compiles -- getId is a
property of User
    Getter<User> userId = :id;                 // syntax sugar for
User::getId

    Getter<User> invalid = User::getFirstName; // does not compile -- getId
is not a property of User


Then we could write a query method like this:


    public List<User> find(Property<User>... params) {
        ...
    }


And call it like this:


    find(name: "David", occupation: "Programmer") // compiles -- name and
occupation are properties of `User`
    find(firstName: "David")                      // does not compile --
firstName is not a property of `User`

This can be expanded further to limit what properties can be assigned to a
`Getter<User>` instance. For example:

    public User findById(Getter<User, :id> id) {
        ...
    }

    findById(12);    // compiles -- id is is integer
    findById("foo"); // does not compile -- id is not String


Of course, if added to Java the final syntax and semantics could be very
different, but what do you think? Is there a language that already has a
similar construct?


[1]
https://www.reddit.com/r/java/comments/hlbw03/i_am_not_a_savage_for_stay_concatenating_jpql/
[2] Unless something similar already exists in another programming language

-- 
Best regards,
Behrang Saeedzadeh


More information about the discuss mailing list