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

Error handling #53

Open
jdpage opened this issue Aug 10, 2018 · 3 comments
Open

Error handling #53

jdpage opened this issue Aug 10, 2018 · 3 comments

Comments

@jdpage
Copy link
Collaborator

jdpage commented Aug 10, 2018

We should probably think about our story for this at some point.

We could add generics/templates and discriminated unions and go for a Result type, but that's... a lot.

We could do multiple return. Maybe say that you return your error first, then your value, and provide a syntax...

fun foo(a: u8) -> err, u8
  -- do something
endfun

fun bar() -> err, u8
  let x = try foo(7)    -- causes early-return on error
  return x + 7          -- returns ok as the error
endfun

-- bar desugars to this, where e is some kind of gensym
fun bar() -> err, u8
  let e, x = foo(7)
  if e != ok do  return e  end
  return ok, x + 7
end

EDIT: Of course, err is a new type... it's one byte wide, has the special value literal ok, and allows 1-255 as literals. You can't do arithmetic with it or assign u8s to it. If a conditional expression has type err, ok is considered truthy.

@jdpage
Copy link
Collaborator Author

jdpage commented Aug 10, 2018

Incidentally, I kind of like what lua does with multiple returns, but I don't like the "error last" convention, which makes it easy to discard errors. Hence putting it first. If you really, really want to discard an error, maybe provide an ignore! syntax, which, given an expression returning n values where n > 0, returns n - 1 values, dropping the first one, i.e.

-- might bind x to garbage
let x: u8 = ignore! foo(7)

Similarly, if we enforce the (sensible) rule that functions which return err have to have SOMETHING done with the result

-- just do it and hope for the best
ignore! foo(7)

@jdpage
Copy link
Collaborator Author

jdpage commented Aug 10, 2018

Additionally, it would be cool to have a nice way to express the common idiom "call a function and branch on success, binding a value if successful". Maybe just a straight syntactic sugar:

-- if-let tests against the first bound value
if let e, x = foo(7) do
  -- success
else
  -- failure
end

desugars to the following pseudocode:

do
  let e, x = foo(7)
  if e == ok do
    -- success
  else
    -- failure
  end
end

Of course, we should be able to do further branches on the error

if let e, x = foo(7) do
  -- success
elseif e == some-error
  -- failure case 1
else
  -- catchall
end

Or none at all

if let e, x = foo(7) do
  -- success
end

Though this last one is awkward because e would often be bound to a known (and therefore useless) value.

@jdpage jdpage added the syntax label Aug 10, 2018
@jdpage
Copy link
Collaborator Author

jdpage commented Aug 10, 2018

An alternative for if you seriously don't care about the error code:

if try x = foo(7) do
  -- success
end

-- desugared
do
  let e, x = foo(7)
  if e == ok do
    -- success
  end
end

Not to be confused with

if let x = try foo(7) do
  -- stuff
end

-- desugared
do
  let e, x = foo(7)
  if e != ok do  return e  end
  if x do
    -- stuff
  end
end

... maybe make the expression form be try! and the let modifier be try -- or alternatively, make the let modifier be try? and the expression form try. I like the idea of ! meaning "stay on your toes". (By that rubric, maybe not-equals shouldn't be != -- maybe <> or =/= ?)

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

No branches or pull requests

1 participant