a troublesome way to return "different types" in nim16.11.2023
Recently, 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
strVal if the kind is
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
element. To me, a function that does something like this has overlapping concerns.
Is this worth doing for a kata? …hard no.