<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't work, although it should. Compiler Error: Binary operator '+' cannot be applied to operands of type 'Double' and 'Distance'</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'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'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't!</p><div><br></div></div><div>Also just still issue of Double space polluted with both Distance and Weight extensions, but don'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"><<a href="mailto:svabox@gmail.com" target="_blank">svabox@gmail.com</a>></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'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't re-use ".m",<br>
".km", etc. and have to use ".inMeters()", 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) -> Distance {<br></span>
return Distance(m: lhs.m + rhs.m)<span class=""><br>
}<br>
<br>
static func -(lhs: Distance, rhs: Distance) -> 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<Distance>.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's<br>
a limitation of Swift not supporting this "Typed Numerics" 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'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>
"default" 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> <<a href="http://125.km" rel="noreferrer" target="_blank">http://125.km</a>>, dist is converted at compile time to 125000.m.<span class=""><br>
<br>
4) Agree that this "feature" 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> <<a href="http://100.mm" rel="noreferrer" target="_blank">http://100.mm</a>>) //or<br>
circle(radius: <a href="http://10.cm" rel="noreferrer" target="_blank">10.cm</a> <<a href="http://10.cm" rel="noreferrer" target="_blank">http://10.cm</a>>)<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 <<a href="mailto:svabox@gmail.com" target="_blank">svabox@gmail.com</a><br></span><span class="">
<mailto:<a href="mailto:svabox@gmail.com" target="_blank">svabox@gmail.com</a>>> 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> <<a href="http://10.km" rel="noreferrer" target="_blank">http://10.km</a>><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'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() -> Double {<br>
return inMeters() / 1000.0<br>
}<br>
<br>
func inMeters() -> 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() -> Double {<br>
return inMeters() * 1000.0<br>
}<br>
<br>
static func +(lhs: Distance, rhs: Distance) -> Distance {<br>
return .m(lhs.inMeters() + rhs.inMeters())<br>
}<br>
<br>
static func -(lhs: Distance, rhs: Distance) -> 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> <<a href="http://10.km" rel="noreferrer" target="_blank">http://10.km</a>> + 5.m + <a href="http://5.mm" rel="noreferrer" target="_blank">5.mm</a> <<a href="http://5.mm" rel="noreferrer" target="_blank">http://5.mm</a>><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'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> <tel:22.08.2016%2017>:54, Nur Ismail via<span class=""><br>
swift-evolution wrote:<br>
<br>
Hi,<br>
<br>
I'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> <<a href="http://5.kg" rel="noreferrer" target="_blank">http://5.kg</a>> <<a href="http://5.kg/" rel="noreferrer" target="_blank">http://5.kg/</a>> + 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> <<a href="http://7.km" rel="noreferrer" target="_blank">http://7.km</a>> <<a href="http://7.km/" rel="noreferrer" target="_blank">http://7.km/</a>> + 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'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>
>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> <<a href="http://42.km" rel="noreferrer" target="_blank">http://42.km</a>> <<a href="http://42.km/" rel="noreferrer" target="_blank">http://42.km/</a>> + 195.m<span class=""><br>
print("A marathon is \(aMarathon) meters long")<br>
// Prints "A marathon is 42195.0 meters long"<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> <<a href="http://42.km" rel="noreferrer" target="_blank">http://42.km</a>> <<a href="http://42.km/" rel="noreferrer" target="_blank">http://42.km/</a>> + 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>
<<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>
<<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>
<<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>
<br>
"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."<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> <mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.<wbr>org</a>><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>
<<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>><br>
<br>
<br>
</blockquote>
</blockquote></div><br></div>