I've been playing around with nim for a while, and the thing that trips me up constantly is templates. I want them - at the signature level at least - to work like procs, but they miss certain features (like optional / default parameters - which really threw me a curve ball yesterday)
Anyway, I have what I think is a simple enough pattern for using templates, so here's some code:
template Kitten*(name: string, age, body: untyped) {.dirty.} =
var kitty_name = name # my {.dirty.} exposes this
echo("Hi, " & name)
if age != 0: echo("wow, " & $age & " years old already!")
body
echo("Bye, " & name)
template Kitten*(name: string, body: untyped) {.dirty.} =
Kitten(name, 0, body)
Kitten("Jimmy"):
echo("It's really nice to meet you, " & kitty_name)
## Ralph and Jimmy cannot co-exist - it's fine, I understand the issue here
# Kitten("Ralph", 5):
# echo("Great that you joined us, " & kitty_name)
That compiles correctly, and works fine. Because my template is dirty, kitty_name
is available from within body
. Uncomment Ralph and comment out Jimmy, and this works correctly too.
Then, I realise that age
does not have a type associated. I certainly don't want that - how silly of me! So I fix it:
template Kitten*(name: string, age:int, body: untyped) {.dirty.}=
Suddenly, Jimmy does not compile. Ralph is fine - Ralph uses the template directly, but because Jimmy uses the overridden (if that term even applies to templates?) method, suddenly it's like the main Kitten has closed its borders? It's not dirty enough?
So the question is, why was it working, why is it failing, and is it a bug or a misunderstood feature? Or am I just misusing templates?
(p.s. tried this on 0.17.0 and latest devel branch)