get last error in error handling
try in risor is very different from Python, w/o the error provided or methods to get the last error it is inconvenient during error handling since we often need to get it for logging or acting on different errors (see code below).
is it possible? am i missing something?
func main() {
code := `
func utilsFunc() {
error("error from utilsFunc")
}
func () {
try(
utilFunc,
func() {
// logging the error from utilsFunc
}) // `)` must be on the same line
}()
`
_, err := risor.Eval(context.Background(), code)
if err != nil {
fmt.Println(err)
}
}
Hi @runsisi, I agree this can be improved. I started a branch that has a small but perhaps meaningful improvement: https://github.com/risor-io/risor/tree/adjust-try
There are two main changes there:
- An error raised in a handler is available as a parameter in the next handler
- If the final handler in the
tryraises an error, then the try raises that error
This makes it more equivalent to try-except in languages like Python.
Example 1:
try(func() {
error("kaboom 1") // this error is passed to the next handler
}, func(e) {
print("caught error:", e)
// this handler doesn't raise an error, so the try returns `nil`
})
Example 2:
try(func() {
error("kaboom 2")
}, func(e) {
// e.error() is "kaboom 2"
error("raising different error from: %s", e.error()) // this causes the try call to raise this modified error
})
What do you think about this?
i will try it, thanks!
package main
import (
"context"
"fmt"
"github.com/risor-io/risor"
)
func main() {
code := `
const error1 = error("errno == 1")
try(func() {
error1
}, func(e) {
if e == error1 {
print("error1 occurred")
}
})
`
_, err := risor.Eval(context.Background(), code)
if err != nil {
fmt.Println(err)
}
}
code above exits on the definition of error1 , but i think defining const errors should be allowed?
Hi @runsisi and sorry for the delay.
I updated the adjust-try branch with some more improvements. Want to give it a try?
Here's a slightly adjusted form of your example that works with the branch:
const error1 = errors.new("errno == 1")
try(func() {
error(error1)
}, func(e) {
if e == error1 {
print("error1 occurred")
} else {
print("error1 not occurred")
}
})
The key things to point out:
error(msg)actually raises an error (rather than returning an error value)errors.new(msg)now is available and it returns an error value, likeerrors.New(msg)in Go.- error comparison works, and is based off of the error message only
@myzie I've been testing the branch, found the behavior of this snippet surprising:
const error1 = errors.new("errno == 1")
try(func() {
me := fetch("https://api.github.com", {})
print(me.status_code)
error(error1)
}, func(e) {
if e == error1 {
print("error1 occurred")
} else {
print("error1 not occurred")
}
})
$ risor test.risor
200
{}
Why's that not raising the error?
Why's that not raising the error?
It seems when I provide a second argument to fetch, that second argument ends up being the second argument to try?
const error1 = errors.new("errno == 1")
try(func() {
me := fetch("https://api.github.com")
print(me.status_code)
error(error1)
}, func(e) {
if e == error1 {
print("error1 occurred")
} else {
print("error1 not occurred")
}
})
❯ risor tests/github.risor
200
error1 occurred
const error1 = errors.new("errno == 1")
try(func() {
me := fetch("https://api.github.com", {method: "GET"})
print(me.status_code)
error(error1)
}, func(e) {
if e == error1 {
print("error1 occurred")
} else {
print("error1 not occurred")
}
})
❯ risor tests/github.risor
200
{
"method": "GET"
}
@myzie will try it later :) thanks!
@rubiojr that does sound weird. I'll try to take a look tomorrow.
@myzie I've been testing with the recent changes, seems to be working great so far. I've been using it successfully to write a small test suite and some tests in https://github.com/rubiojr/risor-libs/blob/main/tests/github.risor. Quite convenient! 🚀
Awesome, thank you for the extra eyes on it @rubiojr. Hopefully I can get it merged soon.
Thanks for the link to your risor-libs... I'm enjoying perusing what you have in there 😄