(This question is mostly about whether this approach makes sense or if there is 
a vastly easier way.)

For example, when working with 2-dimensional coordinates, I might define:

> type
>
>> X = distinct int
>> 
>> Y = distinct int

So that I can't mix up the types by accident, which could happen, if `X` and 
`Y` were just plain `int`.

So far, so good. But often I'd also like to conveniently do math with such 
types. So that these lines work:

> let
>
>> a : X = X(40)+X(2)
>> 
>> b : X = X(40)+2
> 
> assert a == X(42)
> 
> assert b == X(42)

(Side-note; should have been a comment in the previous code block, but it seems 
the forum interprets the leading # as instruction to print the comment as a 
LARGE TITLE): This must not compile: let c : X = 40 + 2

Currently I achieve this by creating overloads via template.

All the generated procs follow this pattern

  * convert parameters to base type if not of `distinctType`
  * pass converted parameters to `usedProc`
  * convert that result to `distinctType`



> template genImplicitUpconversion*(distinctType, usedProc) =
>
>> type
>>
>>> D = distinctType
>>> 
>>> T = D.distinctBase
>> 
>> proc usedProc (d0, d1: D): D = D(usedProc(T(d0), T(d1)))
>> 
>> proc usedProc (t: T; d: D): D = D(usedProc(t, T(d)))
>> 
>> proc usedProc (d: D; t: T): D = D(usedProc(T(d), t))

(Side-note; inside the template usedProc should be `usedProc`. But that causes 
an error about "Message needs to be valid RST! Error: input(49, 38) Error: '`' 
expected", so I left them out.)

This template is used again in another template that overloads all appropriate 
symbols (like +,-,*,div or /, ...), so that finally all that is required is:

> X.enableImplicitDistinctUpconversion()

My current implementation works but is less flexible than I would like. Before 
I dig in and make a proper macro out of all this, I wanted to make sure I'm not 
missing a relevant language mechanism or feature.

Does this approach makes sense or is there an easier way? 

Reply via email to