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