expr icon indicating copy to clipboard operation
expr copied to clipboard

Option to disable short-circuiting

Open lvliangxiong opened this issue 3 months ago • 2 comments

package main

import (
	"fmt"

	"github.com/antonmedv/expr"
)

func main() {
	env := map[string]any{
		"a": func() bool { fmt.Println("a executed"); return true },
		"b": func() bool { fmt.Println("b executed"); return false },
	}

	program, _ := expr.Compile(`a() || b()`, expr.Env(env))

	_, _ = expr.Run(program, env)
	// Output:
	// a executed
}

Output of above code will be a executed. But I'm wondering if there's an option which I can pass to the expr, or something else I'can do to disable the shortcircuit effect. After disabling shortcircuit, output will be a executed and b executed.

lvliangxiong avatar Sep 12 '25 12:09 lvliangxiong

Lets add an option to disable short-circuiting expr.NoShortCircuiting().

In order for this to work compiler should procude different order of opcodes.

For now, as a workaround, you can use something like this:

let r1 = a();
let r2 = b();
r1 || r2

antonmedv avatar Sep 12 '25 12:09 antonmedv

I just find a trick which can achieve the same effect:

func ExampleDisableShortCircuit() {
	OR := func(a, b bool) bool {
		return a || b
	}

	env := map[string]any{
		"foo": func() bool {
			fmt.Println("foo")
			return false
		},
		"bar": func() bool {
			fmt.Println("bar")
			return false
		},
		"OR": OR,
	}

	program, _ := expr.Compile("true || foo() or bar()", expr.Env(env), expr.Operator("or", "OR"), expr.Operator("||", "OR"))
	got, _ := expr.Run(program, env)
	fmt.Println(got)

	// Output:
	// foo
	// bar
	// true
}

For sure, it would be better we have an Option to do this.

lvliangxiong avatar Sep 25 '25 06:09 lvliangxiong

Will be released with v1.17.7

antonmedv avatar Dec 14 '25 21:12 antonmedv