Description
Salute to everyone here, for the pass few weeks, I've read through all error handling proposal and I know most of them is likely to be rejected at the moment however I would like to put my idea here to help shape up the future if possible.
This proposal aiming to keep old syntax relevant and maintain compatibility.
This proposal utilize 2 new symbols ?
and =>
with an existing symbol !
to improve error handling and various part of the language.
- Use exclamation mark "
!
" symbol if we want to panic application - Use question mark "
?
" symbol if we want to return from the function - Use "
=>
" symbol to provide custom error or wrapped error
Acceptant Syntax
- Symbol
!
and?
is allow to use with the last variable in assign or define statement only. - The last variable must be a
bool
or anerror
type where bool would only work withmap
,channel
andcasting
err? := firstPatient()
patient, ok! := dictPatient["boob"]
number, ok? := it.(int)
patient, ok? := <- patientQueue
- Symbol
?
is allow to use in function or closure where return signature contain error type however it's not required when using withchannel
,casting
ormap
- Symbol
!
is not allow to use with channel - Both symbol is not allow to use in for loop (
Range
) and if initial statement.
Syntax pattern: var1, var2(?|!) := val1, val2 [=> error]
Note: To distinguish with a different opertor "
!=
", it required to have a whitespace after either?
or!
which mean statementerr?:= firstPatient()
is invalid.
patient, err? := findPatient(name)
// equivalent to
patient, err := findPatient(name)
if err != nil {
return err
}
id := "mly123"
patient, ok! := dictPatient[id] =>
fmt.Errorf("Patient id %s not found", id)
// equivalent to
id := "mly123"
patient, ok := dictPatient[id]
if !ok {
panic(fmt.Errorf("Patient id %s not found", id))
}
Compiler accepted
// channel usage
ch := make(chan bool)
// return as soon as channel close
b, ok? := <- ch
select {
// return as soon as channel close
case b, ok? := <- ch:
}
// suppose findPatient return a patient and an error
// return as soon as err is not nil
patient, err? := findPatient(name)
patient, err? := findPatient(name) => fmt.Errorf("cannot find patient name %s: %w", name, err)
patient, err! := findPatient(name)
// panic as soon as patient name "boob" is not exist in map "dictPatient"
patient, ok! := dictPatient["boob"]
// return as soon as patient name "boob" is not exist
patient, ok? := dictPatient["boob"] => &MyError{ Name: "boob", Message: "not existed" }
name, ok? := iPatient.(string)
// we can use error message generated by compiler instead.
name, ok! := iPatient.(string) => fmt.Errorf("iPatient is not a string")
// only ! can be use outside of function or closure
package foo
var patient, err! = findPatient("some name")
// ! can be use with error type in "init" function
package foo
func init() {
config, err! := parseConfiguration("path to file")
number, ok? := s.(int)
number, ok! := s.(int)
}
Compiler rejected
// channel do not accept ! mark nor custom error or wrapped error
b, ok! := <- ch
b, ok? := <- ch => fmt.Errorf("error message")
// wrong type and need to be use with last variable
patient?, err = findPatient(name)
// allow one usage only
patient?, err! = findPatient(name)
// suppose getPatient return a patient and a bool
// ***
// *** it's possible to make this statement valid if we treat
// *** this statement the same as type casting statement.
patient, existed? = getPatient(id)
// ? only allow to use within function or closure
package foo
var patient, err? = findPatient("some name")
// ? is not allow to use with error type in init function or function that
// does not have error type as part of return signature
package foo
func init() {
config, err? := parseConfiguration("path to file")
}
Thought
I've experimented with this syntax and my thought is, the syntax is short however it probably add a bit complexity to the compilation as the transformation or code generation must be done after a full type check is completed.