Skip to content

[Request/Question] Support proxies for expr.Env #777

Open
@x1unix

Description

@x1unix

Greetings.

I've a question - does expr support having proxies as expr.Env (something similar to Proxy feature in JS)?

I have a situation where I've to deal with a chain of objects as env that have prototype inheritance (also like in JS).

As env itself is dynamic (might depend on context, environment vars, etc), in order to build expr.Env each time I need to run an expression - it's necessary to traverse a whole prototype chain and create a new map.

Feature Benefits

This feature will allow to handle complex cases such as:

  • Cases when value have to be pulled dynamically in runtime.
  • To abstract away env when it has a complex structure, such as prototype chain.
  • Avoid allocating additional maps or structs for env.

Proposed solutions

Global & Nested Proxy

Ideally, to handle such cases, expr.Env could consume a ProxyEnv interface that will be called to get a variable:

// feel free to provide a better name
type ProxyEnv interface {
   GetValue(path string) (bool, any)
}

If returned value implements ProxyEnv, it also should be treated as proxy:

func example() {
    // Let's assume expression is `foo.bar[keyName]`
    keyName, _ := getValue(env, "keyName")

    foo, _ := getValue(env, "foo")
    bar, _ := getValue(bar, "bar")

    result, _ := getValue(bar, keyName)
}

func getValue(env any, key string) (any, bool) {
  switch t := env.(type) {
    case ProxyEnv:
        return t.GetValue(key)
    case map[string]any:
        v, ok := t[key]
        return v, ok
    default:
        // use reflection
        return getUsingReflect(env, key)
  }
}

Pros

  • Easier to implement

Cons

  • Additional type casting

Alternative Solutions

Please feel free to provide a better more efficient solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions