Re: [swift-evolution] [pitch] Implementation composition

2016-11-25 Thread Matthew Johnson via swift-evolution

> On Nov 25, 2016, at 12:06 PM, Nevin Brackett-Rozinsky via swift-evolution 
>  wrote:
> 
> Protocol forwarding was discussed on-list near the end of 2015 in the thread 
> “[swift-evolution] [Proposal Draft] automatic protocol forwarding”. Feedback 
> was generally positive, though there were disagreements about whether the 
> forwarder and/or forwardee should have to conform to the protocol. Also, 
> complications regarding Self requirements were brought up.

I was the author of the draft proposal discussed in that thread.  I’m sitting 
on a second draft which is about 2/3 complete.  I will finish the draft and 
bring it back up when the core team is ready to consider proposals along these 
lines again.

The ideas I have run in a different and more general direction than what you 
suggest below.  But let’s wait until the time is right to dive into the details.

> 
> For simplicity, if we are going to do this, I propose the following:
> 
> Direct forwarding
> • Both the forwarder and the forwardee must conform to the protocol being 
> forwarded.
> • The forwarder’s associated types are inferred to (and must) match the 
> forwardee’s.
> • Requirements the forwarder implements take precedence and are not forwarded.
> 
> Self requirements
> • A return type of Self cannot be forwarded.
> • A return type of, eg. Self.Element, *can* be forwarded, since the 
> associated types match.
> • A parameter type of Self is forwarded in the natural way, by calling the 
> forwardee’s implementation with the argument’s forwardee.
> 
> Example of that last point:
> 
> protocol P { func f(_: Self) }
> struct Q: P { func f(_: Q){ } }
> class C: P {
>   var q: Q implements P
>   
>   // synthesized:
>   func f(_ a: C) {
> q.f(a.q)
>   }
> }
> 
> Some of these restrictions could potentially be lifted in the future, however 
> for the time being I think they serve an important purpose.
> 
> All that said, I am not yet entirely convinced that protocol forwarding 
> carries sufficient benefits to justify its addition to the language.
> 
> Nevin
> 
> ___
> 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


Re: [swift-evolution] [pitch] Implementation composition

2016-11-25 Thread Nevin Brackett-Rozinsky via swift-evolution
Protocol forwarding was discussed on-list near the end of 2015 in the
thread “[swift-evolution] [Proposal Draft] automatic protocol forwarding”.
Feedback was generally positive, though there were disagreements about
whether the forwarder and/or forwardee should have to conform to the
protocol. Also, complications regarding Self requirements were brought up.

For simplicity, if we are going to do this, I propose the following:

*Direct forwarding*
• Both the forwarder and the forwardee must conform to the protocol being
forwarded.
• The forwarder’s associated types are inferred to (and must) match the
forwardee’s.
• Requirements the forwarder implements take precedence and are not
forwarded.

*Self requirements*
• A return type of Self cannot be forwarded.
• A return type of, eg. Self.Element, *can* be forwarded, since the
associated types match.
• A parameter type of Self is forwarded in the natural way, by calling the
forwardee’s implementation with the argument’s forwardee.

Example of that last point:

protocol P { func f(_: Self) }
struct Q: P { func f(_: Q){ } }
class C: P {
  var q: Q implements P

  // synthesized:
  func f(_ a: C) {
q.f(a.q)
  }
}

Some of these restrictions could potentially be lifted in the future,
however for the time being I think they serve an important purpose.

All that said, I am not yet entirely convinced that protocol forwarding
carries sufficient benefits to justify its addition to the language.

Nevin
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [pitch] Implementation composition

2016-11-25 Thread Tino Heth via swift-evolution

> In what way is this “hiding” protocol conformance? In the examples, MyClass 
> is declaring conformance to A and B via the Useful protocol composition. 
> Perhaps I should have made it clearer which bits are new/proposed: Only the 
> implements word is new here, the protocol composition syntax (A & B) already 
> exists.
> 
My fault — but imho this "sub-protocol" situation isn't that common, and it 
would make the proposal simpler if it starts with just forwarding:
class MyClass : A {
private let a = ImplementsA() implements A
...

In this case, there is (small) repetition (which imho isn't that bad — but 
Kotlin has a nicer syntax for it).___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Add code to super methods.

2016-11-25 Thread Kevin Nattinger via swift-evolution
I agree. An NS_REQUIRES_SUPER equivalent was on my list of things to propose 
during stage 2, and I don't see a reason to enforce order. 


> On Nov 25, 2016, at 04:42, Tino Heth via swift-evolution 
>  wrote:
> 
> 
>> What are your thoughts on this?
>> 
>> Just to throw out a strawman:
>> 
>> // Warn if override doesn’t begin with “super.foo()”
>> __attribute(swift_requires_super_call_at_begin) 
>> 
>>  // Warn if override doesn’t end with “super.foo()”
>> __attribute(swift_requires_super_call_at_end)
> 
> I myself would already be happy if Swift had an equivalent to 
> NS_REQUIRES_SUPER (preferably with a different name ;-).
> The ability to indicate that super shouldn't be called when overriding would 
> be nice as well ― both situations happen in Cocoa, and it isn't enforced, but 
> only documented.
> 
> I don't have any examples where the position of the call to super matters, 
> and my personal opinion is that this feature wouldn't pay off:
> Of course, there are situations where order is important ― but as with 
> willSet/didSet, it might only be important for the overriding class, not for 
> super.
> 
> - Tino
> ___
> 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


Re: [swift-evolution] [pitch] Implementation composition

2016-11-25 Thread Jay Abbott via swift-evolution
Tino,

In what way is this “hiding” protocol conformance? In the examples, MyClass
is declaring conformance to A and B via the Useful protocol composition.
Perhaps I should have made it clearer which bits are new/proposed: Only the
implements word is new here, the protocol composition syntax (A & B)
already exists.

You’re probably right that this is an additive (4.1) thing. But personally
I see no harm in building up a backlog of useful proposals to be reviewed
next year. The knowledge of what’s to come may also help influence thinking
on what’s to come next. Should such discussions be flagged as additive in
the subject somehow? I think I asked this before but forgot or missed if
there was a response.
On Fri, 25 Nov 2016 at 16:21 Tino Heth <2...@gmx.de> wrote:

Kotlin has a imho really nice solution for this: Because constructor
parameters appear right after the class declaration, you can refer to them
in the inheritance-clause.

Protocol conformance is a quite important aspect of a type, so I'm not sure
if it wise to allow "hiding" it — and I hope the promised macro-system will
allow forwarding, so that there is no special syntax needed.

Bottom line:
Imho it's not the right time for serious discussion (serious means: with
the goal of a accepted proposal ;-)

​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [pitch] Implementation composition

2016-11-25 Thread Tino Heth via swift-evolution
Kotlin has a imho really nice solution for this: Because constructor parameters 
appear right after the class declaration, you can refer to them in the 
inheritance-clause.

Protocol conformance is a quite important aspect of a type, so I'm not sure if 
it wise to allow "hiding" it — and I hope the promised macro-system will allow 
forwarding, so that there is no special syntax needed.

Bottom line:
Imho it's not the right time for serious discussion (serious means: with the 
goal of a accepted proposal ;-)
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [pitch] Implementation composition

2016-11-25 Thread Rien via swift-evolution
I like that.

Have you considered the following?

protocol foobar {
func foo() …
func bar() ...
}

class A: foobar { …}

class B: foobar {
let a = A() implements foobar.foo
let b = A() implements foobar.bar
}

Regards,
Rien

Site: http://balancingrock.nl
Blog: http://swiftrien.blogspot.com
Github: http://github.com/Swiftrien
Project: http://swiftfire.nl




> On 25 Nov 2016, at 16:33, Jay Abbott via swift-evolution 
>  wrote:
> 
> We already have a great way to compose APIs using protocol composition, and 
> we can supply default implementations for protocol methods, but what if we 
> want to compose implementations from existing types?
> 
> Say I have two disparate protocols:
> 
> protocol A 
> {
> 
> func methodA1()
> 
> 
> func methodA2()
> 
> }
> 
> protocol B 
> {
> 
> func methodB1()
> 
> 
> func methodB2()
> 
> }
> 
> And I also have a selection of classes that implement them, but let’s just 
> consider two:
> 
> class ImplementsA : A 
> {
> 
> func methodA1() 
> {
> 
> print("A1"
> )
> }
> 
> func methodA2() 
> {
> 
> print("A2"
> )
> }
> }
> 
> class ImplementsB : B 
> {
> 
> func methodB1() 
> {
> 
> print("B1"
> )
> }
> 
> func methodB2() 
> {
> 
> print("B2"
> )
> }
> }
> 
> And I have a composed interface:
> 
> typealias Useful = A & B
> Now I want to implement a Useful class by composing it from the two chosen 
> implementations of A and B:
> 
> class MyClass : Useful 
> {
> private 
> let a = ImplementsA
> ()
> private 
> let b = ImplementsB
> ()
> 
> public 
> func methodA1() 
> {
> a.methodA1()
> }
> public 
> func methodA2() 
> {
> a.methodA2()
> }
> public 
> func methodB1() 
> {
> b.methodB1()
> }
> public 
> func methodB2() 
> {
> b.methodB2()
> 
> // I want this to do what 'b' does, plus some
> 
> 
> // extra work in MyClass implementations of B
> 
> 
> print("Extra"
> )
> }
> }
> 
> Not too bad - but that could get pretty tedious if I had 5 protocols to 
> implement with 5 methods each. Much nicer would be:
> 
> class MyClass : Useful 
> {
> private 
> let a = ImplementsA() implements A
> 
> private 
> let b = ImplementsB() implements B
> 
> 
> public 
> func methodB2() 
> {
> b.methodB2()
> 
> // I want this to do whatever 'b' does, plus some
> 
> 
> // extra work in MyClass implementations of B
> 
> 
> print("Extra"
> )
> }
> }
> 
> The idea is that implements SomeProtocol after a member variable will 
> synthesize all the methods that aren’t explicitly implemented from 
> SomeProtcol by forwarding the call to that member. Or something more 
> efficient if possible.
> 
> You could also implement protocols using other classes that only partially 
> implement them:
> 
> class PartlyImplementsB 
> {
> 
> func methodB1() 
> {
> 
> print("B1"
> )
> }
> }
> 
> class MyClass : Useful 
> {
> private 
> let a = ImplementsA() implements A
> 
> private 
> let b = PartlyImplementsB() implements B
> 
> 
> public 
> func methodB2() 
> {
> 
> print("I have to implement this because `b` does not."
> )
> }
> }
> 
> The way this would work is find the intersection between all methods in the 
> protocol and all methods in the implementing member, then subtract all 
> methods already explicitly implemented in the class, and synthesize those. 
> That way if you had another class AlmostImplementsB that implements methodB2 
> you could simply do:
> 
> private let a = ImplementsA() implements A
> 
> private 
> let b1 = PartlyImplementsB() implements B
> 
> private 
> let b2 = AlmostImplementsB() implements B
> However, if the synthesis process finds that it’s synthesizing a method 
> twice, for example in this case…
> 
> protocol C 
> {
> 
> func methodC1()
> 
> 
> func methodC2()
> 
> 
> func methodC3()
> 
> }
> 
> class PartlyImplementsC 
> {
> 
> func methodC1() 
> {
> 
> print("C1(partly)"
> )
> }
> 
> func methodC2() 
> {
> 
> print("C2(partly)"
> )
> }
> }
> 
> class AlmostImplementsC 
> {
> 
> func methodC2() 
> {
> 
> print("C2(almost)"
> )
> }
> 
> func methodC3() 
> {
> 
> print("C3(almost)"
> )
> }
> }
> 
> class MyClass : C 
> {
> private 
> let cPartly = PartlyImplementsC() implements C
> 
> private 
> let cAlmost = AlmostImplementsC() implements C
> 
> }
> 
> …then the compiler would emit an error and you would have to explicitly 
> implement methodC2 to prevent it from being double-synthesized. You could of 
> course have your own custom implementation or choose which member to call as 
> your explicit implementation.
> 
> Regarding access: I think it would implement them as public, as this seems 
> obvious for a protocol, but I guess there’s a possibility you might want them 
> 

Re: [swift-evolution] Global init() functions

2016-11-25 Thread Jay Abbott via swift-evolution
Why not just say that this doesn't affect the removal of types (i.e. they
can still be discarded) and add something to prevent specific types being
discarded even if they're not statically used?

```swift
@nodiscard SomeType
```

This way, rather than a protocol opting in that anything implementing it is
automatically `@nodiscard` a program or library would declare some types as
non-discardable and could safely say "there will be at least 1
SomeProtocol" available" without saying what specific type it is in the
public interface/docs?


On Mon, 21 Nov 2016 at 22:50 John McCall via swift-evolution <
swift-evolution@swift.org> wrote:

> On Nov 20, 2016, at 6:40 AM, Alan Cabrera  wrote:
>
> On Nov 19, 2016, at 8:57 PM, John McCall  wrote:
>
> On Nov 19, 2016, at 6:03 PM, Alan Cabrera  wrote:
>
> On Nov 19, 2016, at 4:02 PM, John McCall  wrote:
>
> On Nov 19, 2016, at 3:31 PM, Alan Cabrera  wrote:
>
> On Nov 19, 2016, at 1:21 PM, John McCall  wrote:
>
> On Nov 19, 2016, at 10:07 AM, Alan Cabrera via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Nov 19, 2016, at 9:27 AM, Jean-Daniel  wrote:
>
>
> Le 19 nov. 2016 à 15:58, Alan Cabrera via swift-evolution <
> swift-evolution@swift.org> a écrit :
>
> I’m not sure if this was proposed or not; or even if this is a Swift-ly
> way of doing things.  It would be pretty handy to be able to declare init()
> functions in my module to register handlers.  It’s a common pattern in
> enterprise software.
>
> Currently, I have to generate a lot of boilerplate code to emulate the
> behavior.  I think it would be cleaner to have these global init()
> functions.
>
>
> I’d rather like a swift attribute equivalent to : __attribute__((
> constructor))
>
> It will not force me to call my initializer init, and moreover it will let
> me declare multiple functions so I would be able to register multiples
> handlers from a single module without having to group all the register call
> into a single init() function.
>
>
> I’m not quite following what “__attribute__((constructor))” means; it
> looks like an LLVM implementation bit.  Do you mean defining a new Swift
> declaration attribute named “constructor”?  If so, I *really* like that
> idea.  I think that the specific attribute name “constructor” may be a bit
> confusing though, since it’s not really constructing anything specific.
> Maybe “startup” would be a more descriptive attribute name?
>
> @startup
> func registerHandlers() {
> }
>
> The attribute would also help the compiler and IDEs prevent direct calling
> of the startup functions, thus reinforcing/focusing the startup functions’
> role as global startup functions.  Maybe global teardown functions would be
> helpful as well.
>
> I’m going to try goofing around with the idea on my fork.
>
>
> Some sort of reflective discovery would be better, I think.  Eager global
> initialization is superficially attractive — what could be simpler than
> just running some code at program launch? —  but as a program scales up and
> gains library dependencies, it very quickly runs into problems.  What if an
> initializer depends on another already having been run?  What if an
> initializer needs to be sensitive to the arguments or environment?  What if
> an initializer need to spawn a thread?  What if an initializer needs to do
> I/O?  What if an initializer fails?  Global initialization also has a lot
> of the same engineering drawbacks as global state, in that once you've
> introduced a dependency on it, it's extremely hard to root that out because
> entire APIs get built around the assumption that there's no need for an
> explicit initialization/configuration/whatever step.  And it's also quite
> bad for launch performance — perhaps not important for a server, but
> important for pretty much every other kind of program — since every
> subsystem eagerly initializes itself whether it's going to be used or not,
> and that initialization generally has terrible locality.
>
>
> Very good points.  I recognize the dangers.  However.
>
> Don’t these problems already exist given that user code can still execute
> at program startup?  It cannot be denied that the pattern is used and is
> extremely useful though, as you point out above, it should be used
> carefully.  Thinking on it, there are always pros and cons to most language
> features and one relies on best practices to avoid shooting oneself in the
> foot.  For each of the specters listed above, there are simple accepted
> practices that can be adopted to avoid them; most of those practices are
> already being employed for other situations.
>
> And the pattern is not just useful in enterprise software.  Complex
> applications’ app-delegate did-finish-launching methods are chucked full of
> hand stitched roll calls to framework initialization code.  This needlessly
> places a brittle 

[swift-evolution] [pitch] Implementation composition

2016-11-25 Thread Jay Abbott via swift-evolution
We already have a great way to compose APIs using protocol composition, and
we can supply default implementations for protocol methods, but what if we
want to compose implementations from existing types?

Say I have two disparate protocols:

protocol A {
func methodA1()
func methodA2()
}protocol B {
func methodB1()
func methodB2()
}

And I also have a selection of classes that implement them, but let’s just
consider two:

class ImplementsA : A {
func methodA1() {
print("A1")
}
func methodA2() {
print("A2")
}
}class ImplementsB : B {
func methodB1() {
print("B1")
}
func methodB2() {
print("B2")
}
}

And I have a composed interface:

typealias Useful = A & B

Now I want to implement a Useful class by composing it from the two chosen
implementations of A and B:

class MyClass : Useful {
private let a = ImplementsA()
private let b = ImplementsB()

public func methodA1() {
a.methodA1()
}
public func methodA2() {
a.methodA2()
}
public func methodB1() {
b.methodB1()
}
public func methodB2() {
b.methodB2()
// I want this to do what 'b' does, plus some
// extra work in MyClass implementations of B
print("Extra")
}
}

Not too bad - but that could get pretty tedious if I had 5 protocols to
implement with 5 methods each. Much nicer would be:

class MyClass : Useful {
private let a = ImplementsA() implements A
private let b = ImplementsB() implements B

public func methodB2() {
b.methodB2()
// I want this to do whatever 'b' does, plus some
// extra work in MyClass implementations of B
print("Extra")
}
}

The idea is that implements SomeProtocol after a member variable will
synthesize all the methods that aren’t explicitly implemented from
SomeProtcol by forwarding the call to that member. Or something more
efficient if possible.

You could also implement protocols using other classes that only partially
implement them:

class PartlyImplementsB {
func methodB1() {
print("B1")
}
}class MyClass : Useful {
private let a = ImplementsA() implements A
private let b = PartlyImplementsB() implements B

public func methodB2() {
print("I have to implement this because `b` does not.")
}
}

The way this would work is find the intersection between all methods in the
protocol and all methods in the implementing member, then subtract all
methods already explicitly implemented in the class, and synthesize those.
That way if you had another class AlmostImplementsB that implements methodB2
you could simply do:

private let a = ImplementsA() implements A
private let b1 = PartlyImplementsB() implements B
private let b2 = AlmostImplementsB() implements B

However, if the synthesis process finds that it’s synthesizing a method
twice, for example in this case…

protocol C {
func methodC1()
func methodC2()
func methodC3()
}class PartlyImplementsC {
func methodC1() {
print("C1(partly)")
}
func methodC2() {
print("C2(partly)")
}
}class AlmostImplementsC {
func methodC2() {
print("C2(almost)")
}
func methodC3() {
print("C3(almost)")
}
}class MyClass : C {
private let cPartly = PartlyImplementsC() implements C
private let cAlmost = AlmostImplementsC() implements C
}

…then the compiler would emit an error and you would have to explicitly
implement methodC2 to prevent it from being double-synthesized. You could
of course have your own custom implementation or choose which member to
call as your explicit implementation.

Regarding access: I think it would implement them as public, as this seems
obvious for a protocol, but I guess there’s a possibility you might want
them to be internal, so perhaps implements(internal) or implements(public)
would be better. Or perhaps someone can think of a better word because in
the partial case it is a little confusing - is there a single word that
means use-to-implement ?

Regarding value-types: I haven’t thought deeply about this for non-class
types, but it can probably work the same for those too.

Anyway, this could be used to provide a variety of implementations for
protocols, composed of different combinations of partial implementations,
then use those complete implementations to compose your larger/complex
types with the minimum of boilerplate forwarding code.

Thoughts?
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Add code to super methods.

2016-11-25 Thread Tino Heth via swift-evolution

> What are your thoughts on this?
> 
> Just to throw out a strawman:
> 
> // Warn if override doesn’t begin with “super.foo()”
> __attribute(swift_requires_super_call_at_begin) 
> 
>  // Warn if override doesn’t end with “super.foo()”
> __attribute(swift_requires_super_call_at_end)

I myself would already be happy if Swift had an equivalent to NS_REQUIRES_SUPER 
(preferably with a different name ;-).
The ability to indicate that super shouldn't be called when overriding would be 
nice as well — both situations happen in Cocoa, and it isn't enforced, but only 
documented.

I don't have any examples where the position of the call to super matters, and 
my personal opinion is that this feature wouldn't pay off:
Of course, there are situations where order is important — but as with 
willSet/didSet, it might only be important for the overriding class, not for 
super.

- Tino___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution