mirror of
https://github.com/hanzoai/expr.git
synced 2026-09-24 16:58:58 +00:00
90 lines
2.1 KiB
Markdown
90 lines
2.1 KiB
Markdown
# Functions
|
|
|
|
Expr comes with a set of [builtin](language-definition.md) functions, but you can also define your own functions.
|
|
|
|
The easiest way to define a custom function is to add it to the environment.
|
|
|
|
```go
|
|
env := map[string]any{
|
|
"add": func(a, b int) int {
|
|
return a + b
|
|
},
|
|
}
|
|
```
|
|
|
|
Or you can use functions defined on a struct:
|
|
|
|
```go
|
|
type Env struct{}
|
|
|
|
func (Env) Add(a, b int) int {
|
|
return a + b
|
|
}
|
|
```
|
|
|
|
:::info
|
|
If functions are marked with [`ConstExpr`](./configuration.md#constexpr) option, they will be evaluated at compile time.
|
|
:::
|
|
|
|
The best way to define a function from a performance perspective is to use a [`Function`](https://pkg.go.dev/github.com/expr-lang/expr#Function) option.
|
|
|
|
```go
|
|
atoi := expr.Function(
|
|
"atoi",
|
|
func(params ...any) (any, error) {
|
|
return strconv.Atoi(params[0].(string))
|
|
},
|
|
)
|
|
|
|
program, err := expr.Compile(`atoi("42")`, atoi)
|
|
```
|
|
|
|
Type checker sees the `atoi` function as a function with a variadic number of arguments of type `any`, and returns
|
|
a value of type `any`. But, we can specify the types of arguments and the return value by adding the correct function
|
|
signature or multiple signatures.
|
|
|
|
```go
|
|
atoi := expr.Function(
|
|
"atoi",
|
|
func(params ...any) (any, error) {
|
|
return strconv.Atoi(params[0].(string))
|
|
},
|
|
// highlight-next-line
|
|
new(func(string) int),
|
|
)
|
|
```
|
|
|
|
Or we can simply reuse the strconv.Atoi function as a type:
|
|
|
|
```go
|
|
atoi := expr.Function(
|
|
"atoi",
|
|
func(params ...any) (any, error) {
|
|
return strconv.Atoi(params[0].(string))
|
|
},
|
|
// highlight-next-line
|
|
strconv.Atoi,
|
|
)
|
|
```
|
|
|
|
It is possible to define multiple signatures for a function:
|
|
|
|
```go
|
|
toInt := expr.Function(
|
|
"toInt",
|
|
func(params ...any) (any, error) {
|
|
switch params[0].(type) {
|
|
case float64:
|
|
return int(params[0].(float64)), nil
|
|
case string:
|
|
return strconv.Atoi(params[0].(string))
|
|
}
|
|
return nil, fmt.Errorf("invalid type")
|
|
},
|
|
// highlight-start
|
|
new(func(float64) int),
|
|
new(func(string) int),
|
|
// highlight-end
|
|
)
|
|
```
|