a troublesome way to return "different types" in nim
16.11.2023 2 min readRecently, I came across a kata. It went something like this:
Given a string, return the first character that is repeated. If there are no repeating characters, return -1.
So, a few issues here. Nim doesn’t allow union return types - it seems like return types have to be known at compile time So, what can we do instead? How close can we get?
Here are the results of my research:
type IntOrStr = enum
Int, String
type Result = ref object
case kind: IntOrStr
of Int: intVal: int
of String: strVal: string
proc findSomething(s: seq[string], t: string): Result =
let idx = s.find(t)
if idx == -1:
return Result(kind: Int, intVal: idx)
else:
return Result(kind: String, strVal: s[idx])
let res = findSomething(@["a", "b", "z"], "z")
case res.kind:
of Int: echo res.intVal
of String: echo res.strVal
First, we define an enum. The enum will contain the possible types that our custom variant type can hold.
Next, we define an variant object type. All objects will have a kind, the kind being any one of our enum values. Depending on what we pass to the object constructor, different object fields will be initialized - intVal
if the kind is Int
, and strVal
if the kind is String
.
So, it’s like… fancy objects.
Is it nice that you’re able to do this? I suppose.
Am I happy that I learnt how to use this? Yes.
Do I think it is appropriate for a function to return an index or an element? Not really. If a function returns -1 where an element was not found, it should probably also return an index when an element was found. Alternatively, we can return nil
or element
. To me, a function that does something like this has overlapping concerns.
Is this worth doing for a kata? …hard no.