<div dir="ltr">Hi Vladimir,<div><br></div><div>Your latest code is even nicer :) and works for most part, however found the following issues below:</div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">let</span> dist : <span style="color:rgb(79,129,135)">Distance</span> = <span style="color:rgb(39,42,216)">10</span>.<span style="color:rgb(79,129,135)">km</span> <span style="color:rgb(49,89,93)">+</span> <span style="color:rgb(39,42,216)">5</span>.<span style="color:rgb(79,129,135)">m</span> <span style="color:rgb(49,89,93)">+</span> <span style="color:rgb(39,42,216)">5</span>.<span style="color:rgb(79,129,135)">mm</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">let</span> dist2 : <span style="color:rgb(79,129,135)">Distance</span> = <span style="color:rgb(39,42,216)">100</span>.<span style="color:rgb(79,129,135)">km</span> <span style="color:rgb(49,89,93)">+</span> <span style="color:rgb(39,42,216)">5</span>.<span style="color:rgb(79,129,135)">m</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">let</span> weight : <span style="color:rgb(79,129,135)">Weight</span> = <span style="color:rgb(39,42,216)">10</span>.<span style="color:rgb(79,129,135)">pounds</span> <span style="color:rgb(49,89,93)">+</span> <span style="color:rgb(39,42,216)">5</span>.<span style="color:rgb(79,129,135)">kg</span> <span style="color:rgb(49,89,93)">+</span> <span style="color:rgb(39,42,216)">5</span>.<span style="color:rgb(79,129,135)">g  // Assume we have Weight type defined also</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span style="color:rgb(0,132,0)">//let num = <a href="http://100.km">100.km</a> + 10.pounds  </span><span style="color:rgb(0,132,0)">// Not allowed, as different types. Compiler error as expected!</span><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">let</span> distSum = <span style="color:rgb(79,129,135)">dist</span> <span style="color:rgb(49,89,93)">+</span> <span style="color:rgb(79,129,135)">dist2  // Okay</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)">print</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(79,129,135)">dist</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">m</span><span style="color:rgb(0,0,0)">) </span>// Okay</p></div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)"><br></span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)">print</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(79,129,135)">dist</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">km</span><span style="color:rgb(79,129,135)"> + <a href="http://10.km">10.km</a></span><span style="color:rgb(0,0,0)">) </span>// Doesn&#39;t work, although it should. Compiler Error: Binary operator &#39;+&#39; cannot be applied to operands of type &#39;Double&#39; and &#39;Distance&#39;</p></div><div><br></div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)">print</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(79,129,135)">dist</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">km</span><span style="color:rgb(79,129,135)"> + 10</span><span style="color:rgb(0,0,0)">)   </span>// 20.005005 // This works although it shouldn&#39;t!</p></div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)">print</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(79,129,135)">dist</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">km</span><span style="color:rgb(79,129,135)"> * 200</span><span style="color:rgb(0,0,0)">)  </span>// 2001.001  // This works although it shouldn&#39;t!</p></div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)"><br></span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(61,29,129)">print</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(79,129,135)">dist</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">km</span><span style="color:rgb(0,0,0)"> + </span><span style="color:rgb(79,129,135)">weight</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(79,129,135)">kg</span><span style="color:rgb(0,0,0)">) </span>// 18.9470128740157<span style="color:rgb(0,0,0)">  </span>// This also works although it shouldn&#39;t!</p><div><br></div></div><div>Also just still issue of Double space polluted with both Distance and Weight extensions, but don&#39;t think we can get around that, unless we get some compiler support :)</div><div><br></div><div>Regards,</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Aug 23, 2016 at 6:00 PM, Vladimir.S <span dir="ltr">&lt;<a href="mailto:svabox@gmail.com" target="_blank">svabox@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 23.08.2016 12:42, Nur Ismail wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Vladimir,<br>
<br>
Thanks for your code, it&#39;s actually quite close to what I want :)<br>
<br>
Some comments:<br>
1) The main downside is that to read back the value, one can&#39;t re-use &quot;.m&quot;,<br>
&quot;.km&quot;, etc. and have to use &quot;.inMeters()&quot;, etc. Would have been nice to be<br>
able read and write using the same suffixes.<br>
</blockquote>
<br></span>
I agree with all of your points. And about this first.. Yes, I think this variant is better:<br>
<br>
struct Distance  {<br>
<br>
    var km : Double { return self.m / 1000.0 }<br>
    var m: Double<br>
    var mm : Double { return self.m * 1000.0 }<br>
<br>
    init(m: Double) {<br>
        self.m = m<br>
    }<br>
<br>
    init(km: Double) {<br>
        self.m = km * 1000.0<br>
    }<br>
<br>
    init(mm: Double) {<br>
        self.m = mm / 1000.0<span class=""><br>
    }<br>
<br>
    static func +(lhs: Distance, rhs: Distance) -&gt; Distance {<br></span>
        return Distance(m: lhs.m + rhs.m)<span class=""><br>
    }<br>
<br>
    static func -(lhs: Distance, rhs: Distance) -&gt; Distance {<br></span>
        return Distance(m: lhs.m - rhs.m)<br>
    }<br>
}<br>
<br>
extension Double {<br>
    var km : Distance { return Distance(km: self) }<br>
    var m : Distance { return Distance(m: self) }<br>
    var mm : Distance { return Distance(mm: self) }<span class=""><br>
}<br>
<br>
<br>
let dist : Distance = <a href="http://10.km" rel="noreferrer" target="_blank">10.km</a> + 5.m + <a href="http://5.mm" rel="noreferrer" target="_blank">5.mm</a><br>
<br></span>
print(dist.m) // 10005.005<br>
print(<a href="http://dist.km" rel="noreferrer" target="_blank">dist.km</a>) // 10.005005<br>
print(MemoryLayout&lt;Distance&gt;.s<wbr>ize) // 8<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
2) Works quite well on assigning values, and works as expected with a lot<br>
of control of allowed operations, etc. However can make things verbose as<br>
you also mentioned when needing to define many different types, but that&#39;s<br>
a limitation of Swift not supporting this &quot;Typed Numerics&quot; natively rather<br>
than your code :)<br>
<br>
3) Requires an extra byte to store the enumeration value internally, so<br>
whereas Double is 8 bytes, Distance would be 9 bytes. Sometimes it might be<br>
desirable to store the original type the value was assigned with, for<br>
example .km, and only convert to appropriate type when reading, whereas<br>
other times it&#39;s best to convert immediately to the preferred type on<br>
assignment which would be .m (or meters) in this case, perhaps use the<br>
&quot;default&quot; keyword next to the type?. Also compiler support would be<br>
advantageous here also, so that constant expressions can be evaluated at<br>
compile time with no overhead, so that if I put... let dist : Distance =<br>
</span><a href="http://125.km" rel="noreferrer" target="_blank">125.km</a> &lt;<a href="http://125.km" rel="noreferrer" target="_blank">http://125.km</a>&gt;, dist is converted at compile time to 125000.m.<span class=""><br>
<br>
4) Agree that this &quot;feature&quot; should rather be a type alias, as we dealing<br>
with types rather than a structure.<br>
<br>
5) If Swift could support the shortened typed numeric syntax natively, and<br>
with the efficiency that can only happen in the compiler itself so that it<br>
works as fast and efficiently as normal untyped numbers that would be<br>
awesome :)<br>
<br>
6) I think a feature like this could make Swift even more useful in<br>
scientific and other critical applications where they deal with many<br>
different types of numbers, such as velocity, acceleration, gravity, power,<br>
watts, distance, etc. etc.<br>
<br>
Also normal everyday code, for example,<br>
    func circle(radius: Double) ... //Is that radius in pixels, meters,<br>
millimetres or something else? But if radius was defined as our fancy<br>
Distance (assuming we add pixels (px) too :), then they could call it with:<br>
    circle(radius: 150.px) //or<br></span>
    circle(radius: <a href="http://100.mm" rel="noreferrer" target="_blank">100.mm</a> &lt;<a href="http://100.mm" rel="noreferrer" target="_blank">http://100.mm</a>&gt;) //or<br>
    circle(radius: <a href="http://10.cm" rel="noreferrer" target="_blank">10.cm</a> &lt;<a href="http://10.cm" rel="noreferrer" target="_blank">http://10.cm</a>&gt;)<span class=""><br>
    //etc.<br>
<br>
This would help make the code clearer, and lead to better quality code and<br>
hopefully less bugs.<br>
<br>
Regards,<br>
Nur<br>
<br>
On Mon, Aug 22, 2016 at 6:07 PM, Vladimir.S &lt;<a href="mailto:svabox@gmail.com" target="_blank">svabox@gmail.com</a><br></span><span class="">
&lt;mailto:<a href="mailto:svabox@gmail.com" target="_blank">svabox@gmail.com</a>&gt;&gt; wrote:<br>
<br>
    The first question is what the meaning of , for example, a<br>
    multiplication of Distance ? I.e.<br>
    let x1 : Distance = 10.m<br></span>
    let x2 : Distance = <a href="http://10.km" rel="noreferrer" target="_blank">10.km</a> &lt;<a href="http://10.km" rel="noreferrer" target="_blank">http://10.km</a>&gt;<div><div class="h5"><br>
    let x3 = x1 * x2  // ???<br>
<br>
    I.e. as soon as your Distance is Double, you allows all kind of<br>
    floating point operations on instances of this type. And some such<br>
    operations has no meaning for Distance. So, in your proposal, you need<br>
    to somehow control allowed operations.<br>
<br>
    And I believe you can get what you want right now with enums(If I&#39;m not<br>
    missing something):<br>
<br>
    enum Distance  {<br>
        case km(Double)<br>
        case m(Double)<br>
        case mm(Double)<br>
<br>
        func inKilometers() -&gt; Double {<br>
            return inMeters() / 1000.0<br>
        }<br>
<br>
        func inMeters() -&gt; Double {<br>
            switch self {<br>
                case .km(let value) : return value * 1000.0<br>
                case .m(let value) : return value<br>
                case .mm(let value) : return value / 1000.0<br>
            }<br>
        }<br>
<br>
        func inMillimeters() -&gt; Double {<br>
            return inMeters() * 1000.0<br>
        }<br>
<br>
        static func +(lhs: Distance, rhs: Distance) -&gt; Distance {<br>
            return .m(lhs.inMeters() + rhs.inMeters())<br>
        }<br>
<br>
        static func -(lhs: Distance, rhs: Distance) -&gt; Distance {<br>
            return .m(lhs.inMeters() - rhs.inMeters())<br>
        }<br>
<br>
        // implement needed operations here..<br>
    }<br>
<br>
    extension Double {<br>
        var km : Distance { return Distance.km(self) }<br>
        var m : Distance { return Distance.m(self) }<br>
        var mm : Distance { return Distance.mm(self) }<br>
    }<br>
<br></div></div>
    let dist : Distance = <a href="http://10.km" rel="noreferrer" target="_blank">10.km</a> &lt;<a href="http://10.km" rel="noreferrer" target="_blank">http://10.km</a>&gt; + 5.m + <a href="http://5.mm" rel="noreferrer" target="_blank">5.mm</a> &lt;<a href="http://5.mm" rel="noreferrer" target="_blank">http://5.mm</a>&gt;<span class=""><br>
<br>
    print(dist.inMeters()) // 10005.005<br>
    print(dist.inKilometers()) // 10.005005<br>
<br>
    More verbose, but more control. From other point of view, currently<br>
    you&#39;ll need a lot of code for each such type(like Distance).<br>
<br>
    But I do think that such ability to create custom domain-specific types<br>
    based on standard value types is a useful feature which can improve a<br>
    quality of code and can reduce the number of bugs.<br>
<br>
    The syntax to declare such type should be simple and clear, to be able<br>
    to declare a number of such types without a lot of boilerplate code.<br>
    Something like this:<br>
<br>
    typealias Distance : Double {<br>
        var km : Distance { return self * 1000.0 }<br>
        var m : Distance { return self  }<br>
        var mm : Distance { return self / 1000.0 }<br>
        inherit [+,-,/]<br>
    }<br>
<br>
    IMO such type is more a type alias than new structure<br>
<br></span>
    On <a href="tel:22.08.2016%2017" value="+12208201617" target="_blank">22.08.2016 17</a> &lt;tel:22.08.2016%2017&gt;:54, Nur Ismail via<span class=""><br>
    swift-evolution wrote:<br>
<br>
        Hi,<br>
<br>
        I&#39;m new to the list, but have an idea for Typed Numerics.<br>
        Basically numeric values (such as Double, Int, etc.) that are strongly<br>
        typed to a specific use case, for example Distance, Weight, etc.<br>
        and cannot<br>
        be intermixed with untyped values.<br>
<br>
        So if I have (the syntax is made up, but perhaps something like this):<br>
        =====<br>
        //Distance<br>
        struct fixedtype Distance : Double {<br>
        var km: …<br>
        var m: …<br>
        typealias meters: m<br>
        var feet: ...<br>
        ...<br>
        }<br>
<br>
        //Weight<br>
        struct fixedtype Weight : Double {<br>
        var kg: …<br>
        var g: …<br>
        typealias grams : g<br>
        var pound: ...<br>
        }<br>
<br>
        …<br></span>
        var weight : Weight = <a href="http://5.kg" rel="noreferrer" target="_blank">5.kg</a> &lt;<a href="http://5.kg" rel="noreferrer" target="_blank">http://5.kg</a>&gt; &lt;<a href="http://5.kg/" rel="noreferrer" target="_blank">http://5.kg/</a>&gt; + 5.g + 7.m<span class=""><br>
        ………………………………………..^ Compiler Error: Can’t add Distance to Weight...<br></span>
        var distance: Distance = <a href="http://7.km" rel="noreferrer" target="_blank">7.km</a> &lt;<a href="http://7.km" rel="noreferrer" target="_blank">http://7.km</a>&gt; &lt;<a href="http://7.km/" rel="noreferrer" target="_blank">http://7.km/</a>&gt; + 12.5.m<span class=""><br>
        + 5.0 + 3<br>
        ………………………………………………...^ Compiler Error: can’t add untyped number to<br>
        Distance...<br>
        ===<br>
<br>
        The main restriction this syntax should do is disallow intermixing of<br>
        numeric types (even if they all descend from Double, Int, etc.) and not<br>
        allow adding untyped numerics (i.e. those without a type suffix),<br>
        unless<br>
        explicitly asked for in the code.<br>
<br>
        Any of these can be converted to it&#39;s raw untyped value, for example:<br>
        =====<br>
        let number : Double = distance.rawValue + 5.0   //This is allowed<br>
        distance += number.m   //number is converted to m (meters)<br>
        =====<br>
<br>
        &gt;From the Swift 3 Language guide, we are for example given the following<br>
        example:<br>
        =====<br>
        extension Double {<br>
          var km: Double { return self * 1_000.0 }<br>
          var m: Double { return self }<br>
          var cm: Double { return self / 100.0 }<br>
          var mm: Double { return self / 1_000.0 }<br>
          var ft: Double { return self / 3.28084 }<br>
        }<br>
<br></span>
        let aMarathon = <a href="http://42.km" rel="noreferrer" target="_blank">42.km</a> &lt;<a href="http://42.km" rel="noreferrer" target="_blank">http://42.km</a>&gt; &lt;<a href="http://42.km/" rel="noreferrer" target="_blank">http://42.km/</a>&gt; + 195.m<span class=""><br>
        print(&quot;A marathon is \(aMarathon) meters long&quot;)<br>
        // Prints &quot;A marathon is 42195.0 meters long&quot;<br>
        =====<br>
<br>
        This is quite nice to suffix a conversion method after the value,<br>
        but if I<br>
        had another extension that converts the values to pounds and kilograms,<br>
        then one can illegally do this:<br></span>
             let aValue = <a href="http://42.km" rel="noreferrer" target="_blank">42.km</a> &lt;<a href="http://42.km" rel="noreferrer" target="_blank">http://42.km</a>&gt; &lt;<a href="http://42.km/" rel="noreferrer" target="_blank">http://42.km/</a>&gt; + 195.m +<div><div class="h5"><br>
        17.pounds + 5.0<br>
        and then the code would still compile and run, but not work as<br>
        intended.<br>
<br>
        Extra reading, and inspiration for a feature like the above:<br>
        Mars Probe Lost Due to Simple Math Error<br>
        <a href="http://articles.latimes.com/1999/oct/01/news/mn-17288" rel="noreferrer" target="_blank">http://articles.latimes.com/19<wbr>99/oct/01/news/mn-17288</a><br>
        &lt;<a href="http://articles.latimes.com/1999/oct/01/news/mn-17288" rel="noreferrer" target="_blank">http://articles.latimes.com/1<wbr>999/oct/01/news/mn-17288</a>&gt;<br>
        &lt;<a href="http://articles.latimes.com/1999/oct/01/news/mn-17288" rel="noreferrer" target="_blank">http://articles.latimes.com/1<wbr>999/oct/01/news/mn-17288</a><br>
        &lt;<a href="http://articles.latimes.com/1999/oct/01/news/mn-17288" rel="noreferrer" target="_blank">http://articles.latimes.com/1<wbr>999/oct/01/news/mn-17288</a>&gt;&gt;<br>
<br>
        &quot;NASA lost its $125-million Mars Climate Orbiter because spacecraft<br>
        engineers failed to convert from English to metric measurements when<br>
        exchanging vital data before the craft was launched, space agency<br>
        officials<br>
        said Thursday.<br>
<br>
        A navigation team at the Jet Propulsion Laboratory used the metric<br>
        system<br>
        of millimeters and meters in its calculations, while Lockheed Martin<br>
        Astronautics in Denver, which designed and built the spacecraft,<br>
        provided<br>
        crucial acceleration data in the English system of inches, feet and<br>
        pounds.<br>
<br>
        As a result, JPL engineers mistook acceleration readings measured in<br>
        English units of pound-seconds for a metric measure of force called<br>
        newton-seconds.&quot;<br>
<br>
<br>
        ______________________________<wbr>_________________<br>
        swift-evolution mailing list<br></div></div>
        <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.<wbr>org</a>&gt;<br>
        <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br>
        &lt;<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailm<wbr>an/listinfo/swift-evolution</a>&gt;<br>
<br>
<br>
</blockquote>
</blockquote></div><br></div>