I have an option type
type Option*[A] = object
case isDefined*: Bool
of True:
value*: A
of False:
Nil
proc some*[A](value: A): Option[A] =
Option[A](isDefined: True, value: value)
proc none*[A](): Option[A] =
Option[A](isDefined: False)
and implemented a map function (I did it only with a template because Nimrods function literals are cumbersome):
template map(option, operation: expr): expr =
var result {.gensym.}: type(option)
var it {.inject.}: type(option.value)
if option.isDefined:
it = option.value
result = some(operation)
else:
result = option
result
It works fine, I can do
let x = some(5)
let y = x.map(it+5)
It works even with the none case:
let x = none[Int]()
let y = x.map(it+5)
However I'm interested why it works because I declared it as type(option.value) and none does not have a value. The type ascription never seems to be a problem because the value it is not used in case a none is passed. Though, is there a way to access the type parameter of the option in the template to mark it with that type?
One thing that does not yet work is the usage of multiple map calls in one scope. I get the error message that it already exists. Is there a way to tell the template to remove the variable from scope after it is used?
I assume when it is already defined as identifier by the user there is no way to work around that?
However I'm interested why it works because I declared it as type(option.value) and none does not have a value.
It's invalid to access the value at runtime but nevertheless it has a type; Int in your case.
One thing that does not yet work is the usage of multiple map calls in one scope. I get the error message that it already exists. Is there a way to tell the template to remove the variable from scope after it is used?
No, you can't remove it, but you can do when not definedInScope(it).