something has to parse it. This is AdventOfParsing after all. if you know all the input strings at compile time one way could be: import macros const validCard: set[char] = {'A','J','Q','K','0'..'9'} type Hand = distinct string macro validate(s: static string) = if (s.len!=5): error "length must be 5" for i in s: if (not (i in validCard)): error "invalid card: " & i proc toHand(s:static string):Hand = static: validate(s) Hand(s) proc `$`(x:Hand):string = "Hand: " & string(x) echo toHand("A3QJ4") static: assert not compiles(toHand("ABCDE")) Run
to do your enum solution you might: import std/[enumutils,sequtils] macro generateEnum(validCards:static set[char]):type = result = nnkEnumTy.newNimNode().add(newEmptyNode()) for c in validCards: result.add nnkEnumFieldDef.newNimNode().add(ident ("C" & c), newLit(c)) #echo result.treeRepr type Card = generateEnum({'A','J','Q','K','T','2'..'9'}) Hand2 = array[5,Card] #still need to validate the input string, proc toHand2(s:static string):Hand2 = static: validate(s) for i,c in s: result[i] = Card(c)#warning: conversion to enum with holes is unsafe echo toHand2("A3QJ4") # [CA, C3, CQ, CJ, C4] Run