risor icon indicating copy to clipboard operation
risor copied to clipboard

get last error in error handling

Open runsisi opened this issue 1 year ago • 3 comments

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)
	}
}

runsisi avatar Apr 28 '24 02:04 runsisi

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?

myzie avatar May 01 '24 02:05 myzie

i will try it, thanks!

runsisi avatar May 07 '24 08:05 runsisi

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?

runsisi avatar May 07 '24 15:05 runsisi

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, like errors.New(msg) in Go.
  • error comparison works, and is based off of the error message only

myzie avatar Sep 11 '24 21:09 myzie

@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?

rubiojr avatar Sep 19 '24 10:09 rubiojr

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"
}

rubiojr avatar Sep 19 '24 11:09 rubiojr

@myzie will try it later :) thanks!

runsisi avatar Sep 19 '24 23:09 runsisi

@rubiojr that does sound weird. I'll try to take a look tomorrow.

myzie avatar Sep 19 '24 23:09 myzie

@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! 🚀

rubiojr avatar Sep 26 '24 23:09 rubiojr

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 😄

myzie avatar Sep 27 '24 02:09 myzie