Builder Functions
Create type-safe functions with automatic type conversion using the Function Builder.
Basic Function
import "github.com/paularlott/scriptling/object"
func registerAddFunction(p *scriptling.Scriptling) {
fb := object.NewFunctionBuilder()
// Define function with automatic type conversion
fb.FunctionWithHelp(func(a, b int) int {
return a + b
}, "add(a, b) - Add two numbers together")
p.RegisterFunc("add", fb.Build())
}Function Signatures
The Builder API supports flexible function signatures:
func(args...) result- Positional arguments onlyfunc(ctx context.Context, args...) result- Context + positional argumentsfunc(kwargs object.Kwargs, args...) result- Kwargs + positional argumentsfunc(ctx context.Context, kwargs object.Kwargs, args...) result- All parametersfunc(kwargs object.Kwargs) result- Kwargs onlyfunc(ctx context.Context, kwargs object.Kwargs) result- Context + kwargs only
Parameter Order Rules (ALWAYS in this order):
- Context (optional) - comes first if present
- Kwargs (optional) - comes after context (or first if no context)
- Positional arguments - ALWAYS LAST
Examples
Simple Positional Arguments
fb := object.NewFunctionBuilder()
fb.Function(func(a, b int) int {
return a + b
})
p.RegisterFunc("add", fb.Build())
// Usage: add(3, 4) → 7Multiple Parameter Types
fb.FunctionWithHelp(func(name string, count int, ratio float64) string {
return fmt.Sprintf("%s: %d items at %.2f ratio", name, count, ratio)
}, "format(name, count, ratio) - Format data")With Context
fb.Function(func(ctx context.Context, timeout int) error {
select {
case <-time.After(time.Duration(timeout) * time.Second):
return nil
case <-ctx.Done():
return ctx.Err()
}
})
p.RegisterFunc("wait", fb.Build())With Kwargs
fb.Function(func(kwargs object.Kwargs) (string, error) {
host, err := kwargs.GetString("host", "localhost")
if err != nil {
return "", err
}
port, err := kwargs.GetInt("port", 8080)
if err != nil {
return "", err
}
return fmt.Sprintf("%s:%d", host, port), nil
})
p.RegisterFunc("connect", fb.Build())
// Usage: connect(host="example.com", port=443) → "example.com:443"Mixed Positional and Kwargs
fb.Function(func(kwargs object.Kwargs, name string, count int) string {
prefix, _ := kwargs.GetString("prefix", ">")
return fmt.Sprintf("%s %s: %d", prefix, name, count)
})
p.RegisterFunc("log", fb.Build())
// Usage: log("task", 5, prefix=">>>") → ">>> task: 5"With Error Handling
fb.Function(func(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
})
p.RegisterFunc("divide", fb.Build())With Complex Types
fb.Function(func(items []any) float64 {
sum := 0.0
for _, item := range items {
if v, ok := item.(float64); ok {
sum += v
}
}
return sum
})
fb.Function(func(config map[string]any) string {
if host, ok := config["host"].(string); ok {
return "Connected to " + host
}
return "No host"
})Adding Help Text
fb.FunctionWithHelp(func(x float64) float64 {
return math.Sqrt(x)
}, "sqrt(x) - Return the square root of x")
fb.FunctionWithHelp(func(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
}, "divide(a, b) - Divide two numbers (returns error if b is zero)")Variadic Functions
Accept variable number of arguments:
fb.FunctionFromVariadicWithHelp(func(args ...interface{}) []interface{} {
// Process all arguments
result := make([]interface{}, len(args))
for i, arg := range args {
result[i] = fmt.Sprintf("Item %d: %v", i, arg)
}
return result
}, "process_all(*args) - Process all arguments")
// Usage in script:
// result = process_all(1, "hello", True, [1, 2, 3])Builder Methods Reference
| Method | Description |
|---|---|
Function(fn) |
Register a typed Go function |
FunctionWithHelp(fn, help) |
Register with help text |
Build() |
Return the BuiltinFunction |
Choosing Between Native and Builder API
| Factor | Native API | Builder API |
|---|---|---|
| Performance | Faster (no reflection overhead) | Slight overhead |
| Code Clarity | More verbose | Cleaner |
| Type Safety | Manual checking | Automatic |
| Flexibility | Full control | Convention-based |
| Best For | Performance-critical, complex logic | Rapid development, simple functions |
See Also
- Builder Libraries - Type-safe library builder
- Builder Classes - Type-safe class builder
- Native Functions - Direct control with maximum performance