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

Accessing ParametersSpec from a DefGen in a native function #17

Closed
oakash opened this issue Apr 4, 2021 · 4 comments
Closed

Accessing ParametersSpec from a DefGen in a native function #17

oakash opened this issue Apr 4, 2021 · 4 comments

Comments

@oakash
Copy link

oakash commented Apr 4, 2021

I'm trying to access the static components of a ParametersSpec from a native method exposed to the Starlark evaluator when the input into the method is a method. Example:

def function_name(a):
    return "Hello, higher order"
native_method(func=function_name)

The Value received is a struct of type DefGen which is private in eval:

DefGen { 
    parameters: ParametersSpec { 
        function_name: "wip.function_name", 
        names: [("a", Required)], 
        indices: SmallMap { state: Vec(VecMap { hashes: [SmallHashResult(2767251955), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0), SmallHashResult(0)],
        values: [("a", 0)] }) }, 
        positional: 1, 
        no_args: false, 
        args: None, 
        kwargs: None
    } ..rest omitted
}

Is there an approach to get access to the ParametersSpec for the passed in function that I am missing or another potential way to read it? If not, is that something that might be worth adding?

@ndmitchell
Copy link
Contributor

The idea of the function is that it is currently opaque - you can invoke it, but there's no way to get the and give it arguments, but you can't inspect what arguments it requires or what its name is. To change that we'd need to:

  • Make some of ParametersSpec transparent - currently all you can do is give it arguments. This would require careful design to expose the right information.
  • Make the FunctionInvoker you get back from .invoke give you a ParametersSpec back. This one isn't so hard.

What's the reason for wanting to understand the function arguments passed to a native function?

@oakash
Copy link
Author

oakash commented Apr 4, 2021

I'm seeing if it is feasible to use starklark-rust to define "callback" methods to events.

For example, a developer would pass a method to a native Rust function in that's exposed to Starklark, which would get evaluated when a particular event happens at a later time:

def handle_message(title, body):
    if title == "error":
        native.send_email("webmaster@example.com", body)

native.on_message(func=handle_message)

This program would get evaluated and a reference to the callbacks to on_message stored somewhere, for example in a database. When an event comes in, the program would get evaluated again in a different context, and handle_message evaluated with the incoming message.

I was toying with the idea of inspecting the parameters specified on the method to match the incoming event to parameter names to make it a bit easier to use.

There are various other ways this could be achieved. For instance by evaluating the program for each message and use the Context to determine which callbacks to trigger based on the incoming message. That's the approach I'll be trying out today.

@oakash
Copy link
Author

oakash commented Apr 4, 2021

As I sat down to look at this again today I realize I can get pretty far by introducing a level of indirection in starlark and use kwargs. I was bit too stuck in the Rust mindset and looking to solve it there.

Thanks for the library. I don't have a need to expose function details directly Rust integrators right now. Until that changes I'll go ahead and close this ticket.

@oakash oakash closed this as completed Apr 4, 2021
@ndmitchell
Copy link
Contributor

Glad you've figured out a way.

Note that you might want to update the code if you still have Context - the latest code has moved to use Evaluator as the name. As part of the preparation for a release (which we're planning tomorrow) we've renamed a bunch of names that hadn't been considered since the initial fork. Following our release tomorrow we expect things to be pretty stable.

There is also the function eval_function that might be useful for what you are doing - not sure if you've seen that or not.

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