Just had this thought on my mind and am curious what others think. quick note, even if this is actually a good idea it might be impossible to implement in a reasonable time frame. Both null and Error occur when we get a value we do not want and we have to choose how to handle it. Oftentimes the ways in which we handle it are extremely similar to each other in nature. Here is my proposal. Illustrated through the integer type.
func add_last_two(s: seq[int]): int? = \\the question mark indicates that this can either be a valid int or a error type\None type
result s[^-1]? + s[^-2]? \\ the question mark signifies that if we get a err/null we return that err/null instead of continuing our code
let x = @[1].add_last_two.d [ the d signifies that if we get a error type we instead use
the default value of the type, in this case it would be 0
let x = @[1].add_last_two.e.d #[ if we are running a non released version of nim .e crashes
the program if its a release version it returns its input so we handle it with .d this is for when
we don't expect to get a error and if we do there is a bug so if debugging version we want it to crash]#
let x = @[1].add_last_two.c # this always crashes the program if we get a error type and fold the value to int
let x = @[1].add_last_two.d(7) this defaults the value to seven if its a error.
let x = @[1].add_last_two.o(write a arbitrary block with result variable initialized to zero value but can be mutate within the block can access outer scope as well)
there are five main ways to handle error.
some further code examples
let x = [1, 2, 3, 4, 5, 6, 7]
var i = 1
while true:
echo x[i].o(break) # which means echo x unless x is a error or null in which case break
var t = 0
for i in 0 .. 30:
t += x[i].d # since zero value is 0 this would just add the items in x and then add zero the rest of the time
var r = 1
for i in 0 .. 30:
t *= x[i].d(1) this sets the error case to one
var b = 0
for i in 0 .. x.len:
b += x[i].e.d over here we want to crash the program in debug mode since there is a logic error so we do .e.d
See https://github.com/arnetheduck/nim-result/
Which allows
proc ex: Opt[int] =
let smth = ? anotherProcReturningAnOpt()
# smth is now unpacked
let smth2 = anotherProcReturningAnOpt().get(default)
let smth3 = anotherProcReturningAnOpt().tryGet()
# tryGet throw defect if value missing
https://github.com/status-im/questionable Adds operation chaining through ?., though it's not (yet) compatible with the nim-result opt
I don't think there is a need for language-level support.
You can already implement it as a library to showcase.