[swift-evolution] protocol based invocation forwarding

Alejandro Martinez alexito4 at gmail.com
Wed Dec 9 01:39:19 CST 2015


Hi,
Quick mail to check if I understood correctly ;)
Since swift introduction I've been trying to explore creating more domain specific types in order to avoid passing numbers and strings around (that can mean anything) and leverage the type checker to write safer code. (For context http://alejandromp.com/blog/2015/12/5/solving-the-strings-problem-in-swift/ )
You can quickly realize that it increases the safety a lot but at cost of s bunch of boilerplate. At the end you just want that your type behaves as the other (string, int) but that the type checker treats it as different types.
Seems like this proposal and making easier creating 'newtype' will be the solution for this right?
Thanks


Sent from my iPad

> On 08 Dec 2015, at 22:41, Matthew Johnson via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Yes, it should be pretty straightforward to handle the wrapping and unwrapping for the single member / newtype case.  Thanks bringing that up.  I will keep that in mind if I get around to writing this proposal before someone else does.
> 
> Is a forwarding mechanism like this something that might be considered in the Swift 3 timeframe?
> 
> Sent from my iPad
> 
>> On Dec 8, 2015, at 2:52 PM, Joe Groff <jgroff at apple.com> wrote:
>> 
>> 
>>> On Dec 8, 2015, at 10:09 AM, Matthew Johnson <matthew at anandabits.com> wrote:
>>> 
>>> Would it be acceptable to make forwarding of member with Self return types optional for the forwarder (i.e. If the initializer / factory function is not provided the member is not forwarded and must be implemented manually)?
>> 
>> That's definitely a reasonable answer.
>> 
>> In my mind, an ideal solution would make it easy to implement 'newtypes' that wrap a type while exposing selected parts of the original type's interface. For example, if you wanted to make strongly-typed units valued as Doubles that still support arithmetic:
>> 
>> protocol Addable { func + (_: Self, _: Self) -> Self }
>> 
>> struct Weight: Addable {
>>   var value: Double implements Addable
>> }
>> struct Distance: Addable {
>>   var value: Double implements Addable
>> }
>> 
>> it'd be nice if the unwrapping and wrapping defaulted to something sensible.
>> 
>> -Joe
>> 
>>> Sent from my iPad
>>> 
>>>> On Dec 8, 2015, at 11:53 AM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>>>> 
>>>> It'd definitely be awesome to support forwarding protocol conformances. One thing a forwarding design needs to consider is how to handle `Self` requirements in the forwarded protocol. If the protocol requirements consume `Self` types, you need a conversion operation to go from the forwarder to the forwardee type, such as the getter for the forwardee property.
>>>> If there are any requirements that return `Self` you'd need to additionally provide an initializer or factory function capable of building a new instance of the forwarder type from the forwardee.
>>>> 
>>>> -Joe
>>>> 
>>>>> On Dec 7, 2015, at 1:33 PM, David Owens II via swift-evolution <swift-evolution at swift.org> wrote:
>>>>> 
>>>>> Often it is the case where one might want to implement a type that provides an interface but has inner components that actually handle the implementation. In those cases, we end up with a lot of boiler-plate code that simply turns around and invokes the on the instance.
>>>>> 
>>>>> Let’s take the example of class clusters:
>>>>> 
>>>>> private protocol _Cluster {
>>>>>     func description() -> String
>>>>> }
>>>>> 
>>>>> class Cluster: _Cluster {
>>>>>     
>>>>>     private var _instance: _Cluster
>>>>>     
>>>>>     init(name: String) {
>>>>>         _instance = _ClusterString(name: name)
>>>>>     }
>>>>>     
>>>>>     init(value: Int) {
>>>>>         _instance = _ClusterValue(value: value)
>>>>>     }
>>>>>     
>>>>>     // this is pure boiler-plate
>>>>>     func description() -> String {
>>>>>         return _instance.description()
>>>>>     }
>>>>> }
>>>>> 
>>>>> private class _ClusterString: _Cluster {
>>>>>     private var name: String
>>>>>     init(name: String) { self.name = name }
>>>>>     func description() -> String {
>>>>>         return "_ClusterString: \(name)"
>>>>>     }
>>>>> }
>>>>> 
>>>>> private class _ClusterValue: _Cluster {
>>>>>     private var value: Int
>>>>>     init(value: Int) { self.value = value }
>>>>>     func description() -> String {
>>>>>         return "_ClusterValue: \(value)"
>>>>>     }
>>>>> }
>>>>> 
>>>>> let s = Cluster(name: "a string")
>>>>> s.description()
>>>>> 
>>>>> let v = Cluster(value: 12)
>>>>> v.description()
>>>>> 
>>>>> 
>>>>> Now, it would be nice to not have to have to implement the boiler-plate (this example only has a single method, so the savings seem minimal).
>>>>> 
>>>>> class Cluster: _Cluster {
>>>>>     @forward(_Cluster, _instance)
>>>>> 
>>>>>     private var _instance: _Cluster
>>>>>     
>>>>>     init(name: String) {
>>>>>         _instance = _ClusterString(name: name)
>>>>>     }
>>>>>     
>>>>>     init(value: Int) {
>>>>>         _instance = _ClusterValue(value: value)
>>>>>     }
>>>>> }
>>>>> 
>>>>> The @forward(protocol, instance) attribute lets the compiler know that the _Cluster protocol should be forwarded to the _instance value. The compiler would then generate all of the implementation stubs. Refactoring is also made simple as API changes to _Cluster do not need to be manually reflected on the type.
>>>>> 
>>>>> Another way to solve this problem is with a sufficiently advanced macro system. But that is out-of-scope for v3. However, this seems like it could be a straight-forward enough implementation to support in the mean-time, with an easy path for removal/update if it were to be replaced by a macro system.
>>>>> 
>>>>> -David
>>>>> 
>>>>> 
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151209/d51c4572/attachment.html>


More information about the swift-evolution mailing list