Custom Errors in Crystal
# A custom error type usually has the suffix "Error".
class ArgError < Exception
getter arg : Int32
getter message : String
def initialize(@arg : Int32, @message : String)
end
# Adding this to_s method makes ArgError implement
# the Exception interface.
def to_s(io : IO) : Nil
io << "#{@arg} - #{@message}"
end
end
def f(arg : Int32) : {Int32, Exception?}
if arg == 42
# Return our custom error.
return {-1, ArgError.new(arg, "can't work with it")}
end
{arg + 3, nil}
end
# Crystal doesn't have a direct equivalent to Go's errors.As,
# but we can achieve similar functionality using is_a?
_, err = f(42)
if err.is_a?(ArgError)
puts err.arg
puts err.message
else
puts "err doesn't match ArgError"
endThis Crystal code demonstrates how to create and use custom error types. Here’s a breakdown of the translation:
We define a custom
ArgErrorclass that inherits fromException. This is equivalent to implementing theerrorinterface in the original code.The
ArgErrorclass hasargandmessageproperties, similar to the struct in the original code.We implement a
to_smethod, which is Crystal’s equivalent of theError()method in the original code.The
ffunction is translated almost directly, but we use Crystal’s tuple syntax to return multiple values.In the
mainfunction equivalent, we use Crystal’sis_a?method to check if the error is an instance ofArgError. This is similar to theerrors.Asfunctionality in the original code.
To run this program:
$ crystal run custom_errors.cr
42
can't work with itCrystal’s error handling is somewhat different from Go’s. It uses exceptions rather than returning error values. However, this example demonstrates how to create a custom error type and use it in a way that’s similar to the Go code.
Crystal doesn’t have a direct equivalent to Go’s errors.As function, but the is_a? method provides similar functionality for type checking and casting.