Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try-catch with custom function #65

Closed
wader opened this issue Jan 28, 2021 · 5 comments
Closed

Try-catch with custom function #65

wader opened this issue Jan 28, 2021 · 5 comments

Comments

@wader
Copy link
Contributor

wader commented Jan 28, 2021

Hi!

I was doing some custom functions that felt like good fit to be try:able on error. Did some quick experimentation by exporting gojq.exitCodeError as gojq.ExitCodeError that would enable a custom function to do this:

func customFn(c interface{}, a []interface{}) interface{} {
	return &gojq.ExitCodeError{
		Value: ...,
	}
}

Seems to work as expected.

Would that kind of functionality make sense? maybe should be done by checking if errors implement a tryable/catchable-interface somehow?

Another related question. I tried to understad what the significance of exitCodeError.code = 5 has, just a random constant for tests or something else?

@itchyny
Copy link
Owner

itchyny commented Jan 28, 2021

Throw any error, that will be caught by try. So exporting exitCodeError doesn't make sense.

package main

import (
	"errors"
	"fmt"
	"log"

	"github.com/itchyny/gojq"
)

func main() {
	query, err := gojq.Parse("try f catch .")
	if err != nil {
		log.Fatalln(err)
	}
	code, err := gojq.Compile(
		query,
		gojq.WithFunction("f", 0, 0,
			func(v interface{}, _ []interface{}) interface{} {
				return errors.New("error: custom error")
			},
		))
	if err != nil {
		log.Fatalln(err)
	}
	iter := code.Run(nil)
	for {
		v, ok := iter.Next()
		if !ok {
			break
		}
		if err, ok := v.(error); ok {
			log.Fatalln(err)
		}
		fmt.Printf("%#v\n", v)
	}
}

5 is not a random exit code. It follows the jq specification (exit codes 1 through 5 have each meaning in jq).

 % jq -n '"x" | error'; echo $?
jq: error (at <unknown>): x
5

@wader
Copy link
Contributor Author

wader commented Jan 29, 2021

Aha sorry I must have tested it wrongly somehow. But I was probably a bit unclear that I wanted to be able to throw any value, currently with error you catch the Error() string. So something like this:

$ jq -n 'try error({a: "some value"}) catch .'
{
  "a": "some value"
}

In my example the custom function would return &gojq.ExitCodeError{Value: map[string]interface{}{"a": "some value"} to get the same behaviour.

@itchyny
Copy link
Owner

itchyny commented Jan 29, 2021

Okay, let me think for a few days. Maybe interface{ ErrorValue() interface{} } would fit.

@itchyny
Copy link
Owner

itchyny commented Jan 30, 2021

I implemented the catch handler to use the error value when the error implements the following interface.

type ValueError interface {
	error
	Value() interface{}
}

@wader
Copy link
Contributor Author

wader commented Jan 30, 2021

Ok, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants