I'd like to hijack this thread to talk about what the TI Voyage 200 could
do as far as "type-safe calculations" go.
The calculator supports symbolic equations (for instance, `a * 1000 / 2`
results in `500a` when a isn't known). The interesting part is that you
could append units to numbers. For instance, you can write `500_m`, and
this means 500 meters. Numbers with a type can only be added/subtracted
with numbers of the same type, but they can be multiplied or divided by
pretty much anything. For instance, `500_m - 2_s` (500 meters minus 2
seconds) is an error, but `500_m / 2_s` is `250 (_m/_s)` (or _m * _s^-1).
I found this *extremely* useful for engineering calculations. For
instance, when you multiply quantities that should end up in Teslas, you
know that you've done something wrong if the unit displayed after the
number doesn't look like `V * s * m^-2`. It was also a lifesaver that you
could do something like `6_ft` and end up with 1.8288_m (because _ft is
defined as 0.3048_m).
I have no idea how you'd implement that with Swift though. I'm not a very
powerful template wizard, but I have no idea how you'd do it with C++
either.
Of course, it might be a few years before you're allowed to use the Swift
compiler during your physics exams, and I don't think that real-world
programs often need that much unit safety with numbers. But when I read
"epic typesafe calculations", that's what I think about.
Félix
Le 7 janv. 2016 à 01:42:07, Thorsten Seitz via swift-evolution < >> swift-evolution@swift.org> a écrit :
I think the name should be changed to NumberBox or something similar. A
box is something very generic and should not have number related associated
types.
-Thorsten
Am 06. Januar 2016 um 18:15 schrieb James Campbell <james@supmenow.com>:
I've managed to implement this already in the language with a few ugly
corners due to the lack of generic protocols.
I created a protocol based on Box (https://github.com/robrix/Box/\) which
works really well. I have extended this to handle certain special protocols
like Equatable so you can do SpecialType == SpecialType, and even
literalConversion.
There is however a lot of boilerplate:
- You have to declare all of your Convertible protocols for converting
from one type to another
- You have to define an empty init so the protocol extensions have
something to chain to.
- You need to write the value property with type.
Due to the lack of protocol generics, you also need to have a protocol
for every type you wish to box which sets the associated type. Of course I
could have done this with classes but I wanted to keep this as a value type
:).
With member-wise initializations and generic protocols this could be
achievable just by adding a Box protocol to the standard library.
Here is my implementation of Box as a protocol:
*protocol Box: CustomStringConvertible, CustomDebugStringConvertible {*
* typealias FloatLiteralType = Double*
* typealias IntegerLiteralType = Int*
* typealias BoxType = Any*
* var value: BoxType { get set }*
* init()*
* init(_ value: BoxType)*
*}*
*extension Box where BoxType: CustomStringConvertible {*
* var description: String {*
* return self.value.description*
* }*
* var debugDescription: String {*
* return "\(self.value.description)㎭"*
* }*
*}*
*//MARK: FloatingPointBox*
*protocol FloatingPointBox: Box, FloatLiteralConvertible,
IntegerLiteralConvertible {*
* typealias BoxType = Double*
* typealias FloatLiteralConvertible = Double*
* typealias IntegerLiteralConvertible = Int*
*}*
*extension Box where Self.BoxType == Double {*
* init(_ value: Double) {*
* self.init()*
* self.value = value*
* }*
* init(_ value: Int) {*
* self.init()*
* self.value = Double(value)*
* }*
*}*
*extension FloatLiteralType {*
* init<T: Box where T.BoxType == Double >(_ box: T) {*
* self.init(box.value)*
* }*
* init<T: Box where T.BoxType == Int >(_ box: T) {*
* self.init(box.value)*
* }*
*}*
*extension CGFloat {*
* init<T: Box where T.BoxType == Double >(_ box: T) {*
* self.init(box.value)*
* }*
* init<T: Box where T.BoxType == Int >(_ box: T) {*
* self.init(box.value)*
* }*
*}*
*//Adding FloatLiteralConvertible, IntegerLiteralConvertible*
*extension FloatingPointBox where Self.BoxType == Double,
Self.FloatLiteralConvertible == Double {*
* init(floatLiteral value: Double) {*
* self.init(value)*
* }*
* init(integerLiteral value: Int) {*
* self.init(value)*
* }*
* init<T: IntegerType>(_ value: T) {*
* self.init(value)*
* }*
*}*
Here is my example of using the Box protocol:
*struct Degree: FloatingPointBox {*
* var value: Double = 0*
* init()*
* {*
* }*
*}*
*protocol DegreeConvertiable {*
* init(degreeLiteral value: Degree)*
*}*
*extension Degree: RadianConvertiable {*
* init(radianLiteral value: Radian) {*
* self.value = Double(value) * 180.0 / M_PI*
* }*
* init(_ value: Radian) {*
* self.init(radianLiteral: value)*
* }*
*}*
On Tue, Jan 5, 2016 at 5:24 PM, Matthew Johnson via swift-evolution < >> swift-evolution@swift.org> wrote:
> On Jan 5, 2016, at 11:16 AM, Thorsten Seitz via swift-evolution < >>> swift-evolution@swift.org> wrote:
>
>
>> Am 05.01.2016 um 17:11 schrieb Grzegorz Adam Hankiewicz via >>> swift-evolution <swift-evolution@swift.org>:
>>
>> The ideal would be for the compiler to pretend Euros or RefTablePk
are different types, yet use their parent type at the binary level. This
needs a specific syntax to teach the compiler which existing
methods/operations are allowed on the new fake types and which aren’t.
These new distinct types would *borrow* previous implementations.
>
> What about citing the relevant protocols in the newtype definition?
This should include the ability to use my own protocols to which I have
made the underlying type conform to by an extension.
This is how my forwarding proposal works. The newtype syntax I
suggested as a possible extension looks like this:
newtype Euro = Double forwarding Addable, Subtractable
The keyword could be different, but I think `forwarding` is not bad.
When I complete the second draft I think it will make even more sense. The
forwarding facility has features to handle non-trivial cases (Self and
associated type requirements, etc).
>
> Throwing some syntax into the discussion:
>
> newtype Euro = Double : Addable, Subtractable
>
> where I have defined the protocols Addable and Subtractable somewhere
and made Double conform to them if all this is not provided by the standard
library.
> The implementation of Euro then borrows the implementation of Double
for these protocols.
>
> -Thorsten
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
--
Wizard
james@supmenow.com
+44 7523 279 698
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution