Result
An Optional says that there is no answer. Often the caller
also needs to know why, and that is outcome.Result( of T, E ): a T on
success, or an E that explains the failure.
#import "std/outcome"
'' A port number, or the reason the text is not one.
type PortResult as outcome.Result( of int32, ustring )
function ParsePort( byref text as ustring ) as PortResult
if len( text ) = 0 then
return outcome.Fail( of int32, ustring )( "the port is empty" )
end if
if str( valint( text ) ) <> text then
var why = "'" & text & "' is not a number"
return outcome.Fail( of int32, ustring )( why )
end if
var port = valint( text )
if port < 1 orelse port > 65535 then
var why = text & " is outside 1 to 65535"
return outcome.Fail( of int32, ustring )( why )
end if
return outcome.Ok( of int32, ustring )( port )
end function
dim inputs( 0 to 3 ) as ustring = { "8080", "http", "70000", "" }
for each text in inputs
var r = ParsePort( text )
if r.IsOk( ) then
print "port"; r.Value( )
else
print "refused: "; r.Failure( )
end if
next
'' ValueOr picks a default; a new Result is a failure.
print "or the default:"; ParsePort( "x" ).ValueOr( 80 )
dim unset as PortResult
print "a new Result is ok: "; unset.IsOk( )
Output
port 8080
refused: 'http' is not a number
refused: 70000 is outside 1 to 65535
refused: the port is empty
or the default: 80
a new Result is ok: false
| Procedure or member | Does |
|---|---|
outcome.Ok( of T, E )( v ) | a success holding v |
outcome.Fail( of T, E )( why ) | a failure holding why |
r.IsOk( ) | whether it succeeded |
r.Value( ) | the value; a runtime error if it failed |
r.Failure( ) | the reason; a runtime error if it succeeded |
r.ValueOr( d ) | the value, or d on failure |
Ok and Fail each take only one of T and E as a parameter, so the
compiler cannot infer the other, and both type arguments are always
written. That is why the result type is named once, with
type PortResult as outcome.Result( of int32, ustring ), and the long
spelling appears only where a value is built.
A new Result is a failure. dim unset as PortResult reports
IsOk( ) false. Code that forgets to set a Result cannot claim success by
accident. Because both slots always exist, T and E must each be a type
that can be created with no arguments.
Within that rule E can be any type. A ustring is enough to tell a person what went wrong;
a type with a code field lets a program branch on the reason.
Activities
- Give
ParsePorta fourth failure: a port below 1024 is "reserved". - Replace the
ustringfailure with atype PortErrorholding anenumcode and a message, and print a different line for each code.