risor-io / risor

Fast and flexible scripting for Go developers and DevOps.
https://risor.io
Apache License 2.0
576 stars 24 forks source link

get last error in error handling #237

Open runsisi opened 2 months ago

runsisi commented 2 months ago

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)
    }
}
myzie commented 2 months ago

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:

  1. An error raised in a handler is available as a parameter in the next handler
  2. If the final handler in the try raises 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?

runsisi commented 2 months ago

i will try it, thanks!

runsisi commented 2 months ago
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?