On Tue, Sep 10, 2024, at 10:00, Mike Schinkel wrote:
>> On Sep 9, 2024, at 5:35 PM, Rowan Tommins [IMSoP] <imsop....@rwec.co.uk> 
>> wrote:
>> 
>> On 09/09/2024 19:41, Mike Schinkel wrote:
>>> In Go you cannot add or subtract on a typedef without casting to the 
>>> underlying type.  I would definitely prefer that to be relaxed, but only
>>>  if it is relaxed via an explicit opt-in, e.g. something maybe like 
>>> this:
>>> 
>>> typedef UserId: int operations: +, -, *, /;
>>> typedef UserName: string operations: .;
>> I think this would stray into some of the same complexity as operator 
>> overloads on objects, in terms of the types and values allowed. For instance:
>> 
> I tend to agree that allowing operations may be too much for an initial scope 
> given that it is unlike anything else in the current language and with no 
> other languages offering an equivalent AFAIK.
> 
> I would however make the distinction that it is unlike operator overloading 
> because the big concern was what constituted an operation for any given type 
> could be too subjective.  In your example of `Metres` it is pretty obvious, 
> but not at all obvious for a `User`, for example.  (BTW, thank you for not 
> calling out my nonsensical example of operations on a `UserId`; when I wrote 
> that I clear was not thinking about if they were relevant, doh!)
> 
> However give the suggestion regarding operations with a typedef, the only 
> operations that I suggested would be valid would be the ones already defined 
> on the underlying type, (when I mentioned other operations I was thinking of 
> methods — see my the following example with round — not operators so that is 
> not the same as operator overload.) For example:
> 
> /**
>  * Currency is an int so for example in USD 1 
>  * unit of currency not a dollar but a cent.
>  */
> typedef Currency: int operations: +,-,*,/,round;
> function CalcTotal(Currency $subTotal, Currency $shipping, float 
> $tax):Currency {
>    return round($subTotal*(1+$tax/100),0) + $shipping;
> }

This is very similar (behaviorally) to what I wanted to do with GMP. 
Overloading GMP would have given you int-like powers in your type. The biggest 
negative feedback I got was that people would abuse it still; so we need some 
way to prevent abuse. If you read Jordon's operator overloads RFC, and my GMP 
overloading RFC, you can see that users basically need a way to define how to 
operate over even just an integer.

For example, Dollar(1) + Euro(3) is what? Or even Dollar(1) + 1? How does a 
developer prevent someone from doing something nonsensical? The language needs 
to enforce some rules and/or the developer needs to be able to define them. 
These rules need to be intuitive and well reasoned, IMHO.

>> typedef Metres: int;
>> 
>> assert( Metres(2) +  Metres(1) === Metres(3) ); // most obvious
>> assert( Metres(2) + 1 === Metres(3) ); // seems pretty clear
> 
> Both of those are in line with what I was suggesting.
>> 
>> 
>> $_GET['input'] = '1';
>> assert( Metres(2) + $_GET['input'] === Metres(3) ); // might be more 
>> controversial
>> 
>> 
> I would not consider this appropriate as it has two levels of conversion and 
> could thus end up with unintended edge cases. To do the above I think you 
> would have to either convert or typecast:
> 
> assert( Metres(2) + intval($_GET['input']) === Metres(3) ); 
> assert( Metres(2) + (int)$_GET['input'] === Metres(3) ); 
>> 
>> 
>> typedef Feet: int;
>> assert( Metres(2) + Feet(1) === Metres(3) ); // almost certainly a bad idea
>> 
>> 
> This would be operator overloading where knowledge of the conversion between 
> meters and feet would be required, and that is not in any way in scope with 
> what I was suggesting.  
> 
> As an aside, I am against userland operator overloading as I have seen in 
> other languages that operator overloading gets abused and results in code 
> that is a nightmare to maintain. OTOH, I would support operator overloading 
> in specific cases, e.g. a `Measurement` class in PHP core could allow adding 
> meters to feet, assuming such a proposal were made and all other aspects of 
> the RFC were of the nature to be voted in.
> 
> To reiterate on typedefs, what I was suggesting was that if an operation was 
> explicitly allowed — e.g. + — then anything that would work with the 
> underlying type — such as adding an int 1 would work without typecasting and 
> yet still result in the typedef type, e.g. Meters(2) + 1 results in a value 
> of type Meters. (note that I corrected your spelling of 'Meters' here. ;-) 
> 
> But I agree, this is probably a bridge too far for a first RFC for typedefs. 
> 
>>> type MyNewType: Foo
>>> type MyAlias = Foo
>> I know this was only an example, but as a general point, I think we should 
>> avoid concise but cryptic differences like this. PHP is generally 
>> keyword-heavy, rather than punctuation-heavy, and I think that's a valid 
>> style which we should keep to.
>> 
> Here, I also tend to agree WRT PHP.  Was just pointing out for sake of laying 
> out other options that were implied not to exist.
> 
> -Mike

In other news, I'm highly considering refactoring the records RFC to be a 
typedef RFC; the infrastructure is there; we just need more restrictions.

— Rob

Reply via email to