Trabalhando no Nim, minha intuição para templates é que, em tempo de compilação, eles são simplesmente expandidos em seu código (com as devidas substituições). Mas o seguinte código:
type
New_Type = ref object of RootObj
template Template_Procedure(T: untyped, vProc: bool = true) =
proc ProcedureA(self:var T, vInt: var int): int
when vProc == true:
proc ProcedureA(self:var T, vInt: var int): int =
var tReturn = vInt * vInt
return tReturn
proc ProcedureB(self: var T, vInt: var int): int =
var tI = ProcedureA(self, vInt)
return 2 * tI
Template_Procedure(New_Type, vProc = false)
proc ProcedureA(self:var New_Type, vInt: var int): int =
var tReturn = vInt * vInt * vInt
return tReturn
var tNew = new(New_Type)
var tInt = 5
echo $ProcedureB(tNew, tInt)
dá o erro:
test3.nim(9, 10) Error: implementation of 'test3.ProcedureA(self`gensym0: var New_Type, vInt`gensym0: var int)' expected
Se, no entanto, eu ligar
Template_Procedure(New_Type, vProc = true)
então não há erros.
Por outro lado, se eu substituir manualmente o texto do modelo no local onde ele é chamado, ocorre o oposto. Ou seja, o código é compilado se eu substituir false por vProc e receber o erro
Error: redefinition of 'ProcedureA'; previous declaration
se eu substituir true por vProc.
Alguém pode me explicar onde minha intuição está incorreta em relação aos modelos? (ou me dê referências apropriadas)
Além disso, existe uma maneira de escrever código que em tempo de compilação seja simplesmente expandido?
Especificamente, eu gostaria de poder chamar Template_Procedure(X, vProc = false) onde X é um tipo e então, para os tipos X apropriados, escrever manualmente
ProcedureA(self: var X, vInt var int): int
procedimentos. E para outro X basta chamar Template_Procedure(X) e não precisar definir manualmente o ProcedureA.
A declaração direta nunca é implementada porque os modelos são higiênicos. Embora ambos pareçam ter o mesmo nome,
ProcedureA
já que você está dentro do espaço do modelo, eles não têm o mesmo nome. Você provavelmente deve marcar o modelo{.dirty.}
ou usá-lo{.inject.}
nos procedimentos para injetar os nomes dos símbolos.Para a seguinte pergunta não sei o que você quer dizer, os modelos são simplesmente expandidos.