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

[Feature Request] Allow dots in injected Expr function names #539

Open
polds opened this issue Jan 26, 2024 · 5 comments
Open

[Feature Request] Allow dots in injected Expr function names #539

polds opened this issue Jan 26, 2024 · 5 comments
Labels

Comments

@polds
Copy link

polds commented Jan 26, 2024

We'd like to inject effectively an entire package into our Expr environment with a dozen or so methods. We were hoping to be able to effectively treat it like Go's package syntax and do something like:

expr.Function("pkg.NewThing", func(p ...any) (any, error) { }

But pkg. seems disallowed as the Compile step throws an error like:

unknown name pkg (1:9)
| let x = pkg.NewThing([1, 2, 3]); x.String()
| ........^
@polds polds changed the title [Feature Request] Allow dots in injected expr Function names [Feature Request] Allow dots in injected Expr function names Jan 26, 2024
@antonmedv
Copy link
Member

What about adding a variable containing a struct with all needed methods?

type Pkg struct{}

func (p Pkg) NewThing(a, b int) int {
	return a + b
}

func main() {
	env := map[string]interface{}{
		"pkg": Pkg{},
	}

	program, err := expr.Compile(`pkg.NewThing(1, 2)`, expr.Env(env))
}

@polds
Copy link
Author

polds commented Jan 26, 2024

I was hoping to avoid touching the passed in Env where sometimes we're passing around concrete types and not just a map[string]any, but that would work.

@antonmedv
Copy link
Member

I see. This is actually a good point. in case you’re passing extract as it’s not possible always to add additional methods

Let me think for an api of declaring namespaces four functions

@PranavPeshwe
Copy link
Contributor

I think the method that @antonmedv suggested is elegant & straightforward. I use the same.
@polds , the expr.compile/run functions could be fronted by another function which (as needed) wraps the incoming object (based on its type) and adds requisite functions (in your case a library) to a [say] wrapper.utils member which could be an array/map.

@antonmedv
Copy link
Member

Yes, this is a good suggestion. Even if you are using a struct as an environment, it is possible to embed the struct in another struct.

type Wrapper struct {
 	MyEnv
	Pkg Pkg `expr:"pkg"`
}

type Pkg struct{}

func (p Pkg) NewThing(a, b int) int {
	return a + b
}

func main() {
	program, err := expr.Compile(`pkg.NewThing(1, 2)`, expr.Env(Wrapper{}))
}

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

No branches or pull requests

3 participants