expr icon indicating copy to clipboard operation
expr copied to clipboard

[Feature Request] Allow dots in injected Expr function names

Open polds opened this issue 1 year ago • 5 comments

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 avatar Jan 26 '24 22:01 polds

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))
}

antonmedv avatar Jan 26 '24 23:01 antonmedv

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.

polds avatar Jan 26 '24 23:01 polds

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

antonmedv avatar Jan 27 '24 07:01 antonmedv

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.

PranavPeshwe avatar Jan 27 '24 08:01 PranavPeshwe

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{}))
}

antonmedv avatar Jan 27 '24 15:01 antonmedv