I have a handful of procs that are called repeatedly. Each proc has two forms (as seen below). When the proc's argument is static, the compiler can perform better optimizations on the proc's body for significant performance gains. However, the argument cannot always be static, so the normal form is declared, too.
proc foo(a: static CustomType) =
echo "Value: static: ", a
proc foo(a: CustomType) =
echo "Value: ", a
My question is, does Nim offer something that would allow the definition of a single proc and the generation of two instances: an optimized version for when the arg is static and a normal version otherwise? Something like a static-if-possible modifier?
proc foo(a: [static] CustomType)
You can use generics for this:
proc foo(a: int | static int): string =
when a is static:
"static " & $a
else:
$a
const A = 123
var B = A
echo foo(A) # static 123
echo foo(B) # 123
# alternative syntax
proc altFoo(a: static[int] or int): string = discard
proc altFoo[T: static[int] | int](a: T): string = discard
when false:
# this won't compile because type is parsed as `static(int or int)`
proc wrongFoo[T: static int | int](a: T)
Strange, when I tried something like that, only the elif clause printed: playground link
type CustomType = uint32
type MaybeStaticCustomType = CustomType | static[CustomType]
proc bar[T: MaybeStaticCustomType](a: T) =
when T is static[CustomType]:
echo "bar: static: ", a
elif T is CustomType:
echo "bar: ", a
else:
echo "else: " & $typeof(T)
var c1 = CustomType(72)
bar(c1)
const c2 = CustomType(82)
bar(c2)
bar(CustomType(92))I am not sure why the argument is losing "static". My only guess is that it might be related to generic inference restrictions?
For example, if this is not allowed:
# also not allowed: explicit instantiation via 'var int'
g[var int](v, i)
Then I assume this is not allowed too:
proc foo[T](a: T) =
echo a
foo[static[int]](42)
But type classes like static[int] | int seems to work.