I have a procedure which should accept two units(absolute width and width relative to the parent widget). For this purpose I created two distinct types and a typeclass which contains both:
type
UIAbsLength = distinct float32
UIRelLength = distinct float32
UILength = UIAbsLength|UIRelLength
Then I created a procedure which accepts both types and has a default value(this is an Immediate Gui, were widgets are instatiated with a single call, so default values are really handy here):
proc button*(self: UISystem, buttonLabel = none(string), width, height: UILength = UIAbsLength(0)) =
when width is UIAbsLength:
discard
elif height is UIAbsLength:
discard
Now the problem arrives, that once I call the procedure with UIRelLength the compiler throws an error(Error: type mismatch: got (UIAbsLength) but expected 'UIRelLength = distinct float32')
Should this work at all? Or could this be done in some other way? Or is it maybe a compiler bug?
In fact, I consider it a bug in the compiler that the following doesn't work:
proc button*[W, H: UILength = UIAbsLength](self: UISystem,
buttonLabel = none(string),
width = W(0.0),
height = H(0.0)) =
when width is UIAbsLength:
echo "width is Abs!", cast[float32](width)
else:
echo "height is Abs!", cast[float32](width)
And here is why: UILength is a generic type consisting only of finite number of types. It means it's even entirely possible to check every time for compilability of W(0.0) and H(0.0). But still, Nim uses lazy instantiation and compile-time duck typing. Which means it should, as a rule, accept any constructors I give it unless I try to instantiate the proc and break it by trying to use constructors not in existence. And I think so because the following works as expected:
proc button*[W, H: UILength](self: UISystem,
buttonLabel = none(string),
width: W, height: H) =
let x = W(0.0)
let y = H(0.0)
So all in all: Nim makes some inconsistencies between declarations and definitions.
Btw. oh, how much I miss Rust's where... It's a true beautifier of generic signatures...
Thank you for responses, I created an issue on Github: https://github.com/nim-lang/Nim/issues/7000
Does somebody knows of a workaround to this issue? For now the only thing I can do is probably to just remove the default values.
Does somebody knows of a workaround to this issue? For now the only thing I can do is probably to just remove the default values.
You can do that and also provide overloads for respective number of arguments to achieve the same result at the call site.