Skip to content

ProxyValue / Implicit Getters, Setters, and Comparators in Polyglot #11226

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

Open
alexander-beaver opened this issue May 19, 2025 · 1 comment
Open
Assignees

Comments

@alexander-beaver
Copy link

alexander-beaver commented May 19, 2025

Feature request

An earlier version of this issue included references to comparators. I am looking into it, and think that the issue may have been caused by a bug internally. I still think that silent getter/setters would be valuable.

Please include the following information:

Is your feature request related to a problem? Please describe.

I am using Polyglot to define data models. The host process will then create instances to perform business logic. I want the fields to be properties of the class, rather than a ProxyObject passed as a parameter. Currently, as far as I can tell, there is no clean way to expose a single typed variable with a getter, setter, equal, and comparator.

class User:
    username = field.string({
        "primary_key": True
    })
    lifecycle = field.fsm({
        "options": {
            "UNKNOWN": {
                "value": 1,
            },
            "AWAITING_VERIFICATION": {
                "value": 2,
            },
            "VERIFIED": {
                "value": 3
            }
        }
    })

    def onVerify(self):
        if(self.status == 2)
            self.status.set("VERIFIED")
            # field.fsm() exposes a get() and set() method that will automatically convert Strings to values
      

Describe the solution you'd like.

I should be able to say that a class implements ProxyValue (or similar) and write getter/setter/comparator methods that will be exposed in a more "language-native" way. For the above code, I want the guest language code to be

def onVerify(self):
            if(self.status == "AWAITING_VERIFICATION"):
                self.status = "VERIFIED"

where self.status is a class FSMValue that contains

public boolean equals(Object o){}
public int compareTo(Object o){}
public Object get(){}
public void set(Object o){}

Describe who do you think will benefit the most.

This will most benefit users who write Polyglot scripts (especially those who aren't maintaining the host application). It will lower the barrier of entry for people who have not written scripts for polyglot before.

Describe alternatives you've considered.
I have considered exposing a proxy object as a parameter to a method, but I prefer to offer a more traditional object syntax. I am currently bridging this with explicit getter/setter calls. This approach while sufficient, is not ideal.

Additional context.
This may cause some ambiguity with the = operation, whether that should be a set operation or a replacement operation. I think it is reasonable to assume that if a member/variable implements this type, then the = syntax should be equal to .set(Object o). There may need to be a separate method to indicate an uncontrolled replacement.

Express whether you'd like to help contributing this feature
I don't think I have the skillset to contribute to this feature.

@chumer
Copy link
Member

chumer commented May 21, 2025

I agree generally with

public boolean equals(Object o){}
public int compareTo(Object o){}

However structural equality/comparison is very hard to specify well across languages. I tried a few times and failed.
In the meantime I would recommend to use a guest language specific proxy mechanism, if there is one.

public void set(Object o){}

Modifying the object underneath will violate all sorts of internal assumptions we make in the interop protocol. So it will become not feasible for languages to implement that protocol, if the object can be replaced at any point in time with set. For example we do make assumptions that if a object declares that it look is an array, that certain array methods are available afterwards. With this API you could swap out the implementation, with an object that no longer implements array between the call to hasArrayElements and the array read. That is just one example of many such cases. But maybe the solution below works for you here, if you don't need to swap types.

public Object get(){}

Can't you implement get() semantics by implementing all methods of ProxyObject querying an additional indirection? For example:

        class IndirectProxy implements ProxyExecutable {

        public Object execute(Value... t) {
            Object o = get();
            // execute o
        }
        
        protected abstract Object get();
    }

I think to some extend you could also implement a set(). Only limitation would be that you can't change the proxy type anymore dynamically, but that is required anyway to make our internal assumptions pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants