Notes from Swift core team 2016-04-20 design discussion


(Alex Martini) #1

To help keep proposals moving forward, the Swift core team has set aside some time specifically for design discussions of upcoming proposals. Below are some rough notes from the yesterday's discussion.

These are informal comments, intended to guide the proposals in directions that draw constructive feedback. You are welcome to ignore the feedback, agree with it, or disagree with it. As always, the formal decision doesn't happen until after the review period ends.

SE-0068: Expanding Swift Self to class members and value types <file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2016-04-20.html#se-0068-expanding-swift-self-to-class-members-and-value-types>
https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md
We have one keyword left in the language, dynamicType, which is camel cased. This proposal renames it to Self instead.

In a static function today, self.dynamicType will give you a metatype but the non-member Self will not. The most useful reason to reference it is to call an initializer. It makes accessing the metatype weirder. It’s not Self.Type; that’s a type — you have to spell it Self.type.

Quiz time! What do each of the permutations mean?

Self.self
self.Self
Self.Self
self.self
The number of capital letters gives you the level of meta-ness. This is very subtle, which is probably not a good thing.

Another approach would be to introduce a new dynamictype keyword that doesn’t need to be accessed as a member of self, and keep Self the way it is. Self should work in structs as a type alias.

Why don’t we turn this into a standard library function? It’s not something you need so often that the member access is very valuable. Putting it in the standard library as dynamicType(_:slight_smile: does still allow for that function to be implemented using compiler magic.

func dynamicType<T>(_: T) -> T.Type { }
We have a proposal to remove .self on types. One reason .self exists is to avoid the mistake of writing let x = Int — the compiler will give you a weird type error later on in code if the value of x is what we today call Int.self but you meant to call the Int() initializer. Creating a metatype is not a common operation, so doing it explicitly is a good thing.

It’s weird that you can use the metatype directly to construct something or to do member access, but you can’t access it as a bare value.

Coming back to this proposal, if we removed .self why would we want to add .Self?

If you have a variable whose value is a metatype, you also keep its name in lower case. So Self makes a little less sense from that aspect too.

Another perspective is that .dynamicType is just an implicitly synthesized property on all type.

We do have other keywords that follow the dot on types, Int.Type and Fooable.Protocol, so this isn’t the only thing. Those things are magic nested types.

Subjectively, having dynamicType as a member feels weird.

If .self goes away, the four-self example above is simplified, and .Self doesn’t make sense anymore. There’s also the difference that .Self would be a runtime thing.

What to do about optional requirements <file:///Users/alexmartini/DevPubs%20Git%20Repositories/Swift%20Language%20Review/_build/html/LR_MeetingNotes/2016-04-20.html#what-to-do-about-optional-requirements>
http://thread.gmane.org/gmane.comp.lang.swift.evolution/14046
People commonly ask why optional only works on Objective-C protocols, and the responses they get are usually that in Swift code you should reshape your protocols. As a starting assumption, we’re not making optionl work in Swift. So what do we do about this as part of the interoperability code?

People do write these, but it’s often because they’re writing a delegate protocol and they’re following the example of Cocoa frameworks.

Roughly three things we can do:

Rename it to make it clearly an Objective-C interop feature. We could also forbid you actually spelling it in Swift code. That doesn’t work well because it breaks your ability to write code in Swift that has Objective-C clients — those clients won’t get the default implementation from the extensions like you would use with Swift clients instead of creating optional requirements.
Modeling optional requirements as a function of optional type such as ((A, B) -> C)? doesn’t work well. For example, properties can have optional type and they can be optional requirements, so you would end up having to deal with a lot of extra complexity due to double-optionals and likely want better code completion so you could type it all out.
You force the default implementation to be visible from all callers, and you do the dispatch at the call site. The only advantage of this is that it takes optional requirements out of the language entirely. If you wanted to implement the (somewhat common) pattern of checking whether a type implements an optional requirement, you would have to use a respondsToSelector check.
The best pattern we’ve seen for checking conformance and using different code paths based on that is to use finer-grained protocols. (But there are still issues with organizing your code that way.)

The caller default (#3) is really the only way to get optional requirements out of the type system. The weird code path in the compiler here is the same as the weird code path as we have in AnyObject. But it doesn’t look like we’re going to be able to do that.

We can rename this as objcoptional or possibly demote it to an attribute.


(David Waite) #2

Calling an optional method on a delegate protocol and using the result to judge whether you should have some default behavior to me does seem a bit flimsy in retrospect (I originally proposed things like importing optional methods with throws and having an unimplemented method error raised by default, etc). You aren’t really trying to judge that the behavior ‘currently’ is the default, but that there is no behavior defined thus you can reliably *always* use the default.

To that end, you need some way to detect static features of a type at runtime. Today we have respondsToSelector for objc types, and checking for conformance to different protocols.

I don’t think supporting optional protocols in swift could work unless there was also a respondsToSelector equivalent for native swift types.

-DW

···

On Apr 21, 2016, at 9:58 AM, Alex Martini via swift-evolution <swift-evolution@swift.org> wrote:

What to do about optional requirements

http://thread.gmane.org/gmane.comp.lang.swift.evolution/14046
Rename it to make it clearly an Objective-C interop feature. We could also forbid you actually spelling it in Swift code. That doesn’t work well because it breaks your ability to write code in Swift that has Objective-C clients — those clients won’t get the default implementation from the extensions like you would use with Swift clients instead of creating optional requirements.
Modeling optional requirements as a function of optional type such as ((A, B) -> C)? doesn’t work well. For example, properties can have optional type and they can be optional requirements, so you would end up having to deal with a lot of extra complexity due to double-optionals and likely want better code completion so you could type it all out.
You force the default implementation to be visible from all callers, and you do the dispatch at the call site. The only advantage of this is that it takes optional requirements out of the language entirely. If you wanted to implement the (somewhat common) pattern of checking whether a type implements an optional requirement, you would have to use a respondsToSelector check.


(Vladimir) #3

"Another approach would be to introduce a new dynamictype keyword that doesn’t need to be accessed as a member of self, and keep Self the way it is. Self should work in structs as a type alias."

So, could you clarify, do you suggest to introduce dynamictype keyword instead of "self.dynamicType" ? (In addition to remove .self on type and .Self for instance)

And to leave Self just as placeholder for current type i.e. "the class there this is declared" ?

Just want to clarify. Let's review this code:

protocol Proto {
     func z() -> Self
     func z(s: Self)
}

class X: Proto {
     required init () {}
     func x() -> Self { return self.dynamicType.init() }
     func z() -> Self { return self }
     func z(s: X) {}
}

How should it looks like in Swift 3.0 ? :

protocol AP {
     func z() -> dynamictype
     func z(s: Self)
}

class X: AP {
     required init () {}
     func x() -> dynamictype { return dynamicType.init() }
     func z() -> dynamictype { return self }
     func z(s: X) {} // ? Don't we want to have Self here ?
}

Do you support to extend Self to be used in class methods declarations to behave just like in protocol i.e. as "placeholder for defined class" ?

So we can have in class:
     func z(s: Self) {}

Do you support to rename Self -> #Self ?

Thank you for answers.

···

On 21.04.2016 18:58, Alex Martini via swift-evolution wrote:

To help keep proposals moving forward, the Swift core team has set aside
some time specifically for design discussions of upcoming proposals. Below
are some rough notes from the yesterday's discussion.

These are informal comments, intended to guide the proposals in directions
that draw constructive feedback. You are welcome to ignore the
feedback, agree with it, or disagree with it. As always, the formal
decision doesn't happen until after the review period ends.

      SE-0068: Expanding Swift Self to class members and value types

https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md

We have one keyword left in the language, dynamicType, which is camel
cased. This proposal renames it to Self instead.

In a static function today, self.dynamicType will give you a metatype but
the non-member Self will not. The most useful reason to reference it is to
call an initializer. It makes accessing the metatype weirder. It’s
not Self.Type; that’s a type — you have to spell it Self.type.

Quiz time! What do each of the permutations mean?

Self.self
self.Self
Self.Self
self.self

The number of capital letters gives you the level of meta-ness. This is
very subtle, which is probably not a good thing.

Another approach would be to introduce a new dynamictype keyword that
doesn’t need to be accessed as a member of self, and keep Self the way it
is. Self should work in structs as a type alias.

Why don’t we turn this into a standard library function? It’s not something
you need so often that the member access is very valuable. Putting it in
the standard library as dynamicType(_:slight_smile: does still allow for that function
to be implemented using compiler magic.

func dynamicType<T>(_: T) -> T.Type { }

We have a proposal to remove .self on types. One reason .self exists is to
avoid the mistake of writing let x = Int — the compiler will give you a
weird type error later on in code if the value of x is what we today
call Int.self but you meant to call the Int() initializer. Creating a
metatype is not a common operation, so doing it explicitly is a good thing.

It’s weird that you can use the metatype directly to construct something or
to do member access, but you can’t access it as a bare value.

Coming back to this proposal, if we removed .self why would we want to
add .Self?

If you have a variable whose value is a metatype, you also keep its name in
lower case. So Self makes a little less sense from that aspect too.

Another perspective is that .dynamicType is just an implicitly synthesized
property on all type.

We do have other keywords that follow the dot on
types, Int.Type and Fooable.Protocol, so this isn’t the only thing. Those
things are magic nested types.

Subjectively, having dynamicType as a member feels weird.

If .self goes away, the four-self example above is simplified,
and .Self doesn’t make sense anymore. There’s also the difference
that .Self would be a runtime thing.

      What to do about optional requirements

http://thread.gmane.org/gmane.comp.lang.swift.evolution/14046

People commonly ask why optional only works on Objective-C protocols, and
the responses they get are usually that in Swift code you should reshape
your protocols. As a starting assumption, we’re not making optionl work in
Swift. So what do we do about this as part of the interoperability code?

People do write these, but it’s often because they’re writing a delegate
protocol and they’re following the example of Cocoa frameworks.

Roughly three things we can do:

1. Rename it to make it clearly an Objective-C interop feature. We could
    also forbid you actually spelling it in Swift code. That doesn’t work
    well because it breaks your ability to write code in Swift that has
    Objective-C clients — those clients won’t get the default
    implementation from the extensions like you would use with Swift
    clients instead of creating optional requirements.
2. Modeling optional requirements as a function of optional type such
    as ((A, B) -> C)? doesn’t work well. For example, properties can have
    optional type and they can be optional requirements, so you would end
    up having to deal with a lot of extra complexity due to
    double-optionals and likely want better code completion so you could
    type it all out.
3. You force the default implementation to be visible from all callers,
    and you do the dispatch at the call site. The only advantage of this is
    that it takes optional requirements out of the language entirely. If
    you wanted to implement the (somewhat common) pattern of checking
    whether a type implements an optional requirement, you would have to
    use a respondsToSelector check.

The best pattern we’ve seen for checking conformance and using different
code paths based on that is to use finer-grained protocols. (But there are
still issues with organizing your code that way.)

The caller default (#3) is really the only way to get optional requirements
out of the type system. The weird code path in the compiler here is the
same as the weird code path as we have in AnyObject. But it doesn’t look
like we’re going to be able to do that.

We can rename this as objcoptional or possibly demote it to an attribute.

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


(Vladimir) #4

https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md
>
> I'm not totally clear what's being proposed here.
>
> Is this valid?
> ...

Yes, I'm also confused if it is a final proposal or some additions/changes are expected here? As we were also discussing #Self (in meaning "placeholder for name of current defining type", resolving at compilation time)

Also, there were notes regarding this proposal by @Alex Martini<amartini@apple.com> 21.04.2016 18:58 (quoted below), with suggestion for "dynamictype" keyword / "dynamicType" standard library function.

@Brent, your questions could be(in general) answered by replacing "Self" to "dynamicType", but actually there are more questions on this proposal, which I suggest to discuss.

We have some mess *right now* with all these dynamicType/self/Self :

* "self" in meaning of current instance reference (OK), dynamicType is dynamic type of the instance :
class A { func f() { self.something() } }
self.dynamicType is A

* "self" in meaning of current type object in static/class methods, dynamicType is meta type
class A { static func f() { self.something() } }
self.dynamicType is A.Type

* "Self" in meaning "placeholder to concrete defining class name" :
protocol AProtocol { func assignFrom(a: Self) }
class A : AProtocol { func assignFrom(a: A) {..} } // "A" here,not "Self"

* "Self" in meaning of dynamic type in runtime:
class A { func f() -> Self { return self } }

I'd like to discuss how the following current code should looks in Swift 3.0 :

···

On 25.04.2016 4:57, Brent Royal-Gordon via swift-evolution wrote:

----------------------------
protocol Proto {
     func z() -> Self
     func z(s: Self) // I propose the #Self here
}

class X: Proto {
     required init () {}
     func x() -> Self { return self.dynamicType.init() }
     func z() -> Self { return self }
     func z(s: X) {} // propose z(s: #Self) here

     static func staticF() -> Self {..} // shouldn't be #Self here?
     class func classF() -> Self {..}
}
----------------------------

"Notes from Swift core team 2016-04-20 design discussion" :

On 21.04.2016 18:58, Alex Martini via swift-evolution wrote:

      SE-0068: Expanding Swift Self to class members and value types

https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md

We have one keyword left in the language, dynamicType, which is camel
cased. This proposal renames it to Self instead.

In a static function today, self.dynamicType will give you a metatype but
the non-member Self will not. The most useful reason to reference it is to
call an initializer. It makes accessing the metatype weirder. It’s
not Self.Type; that’s a type — you have to spell it Self.type.

Quiz time! What do each of the permutations mean?

Self.self
self.Self
Self.Self
self.self

The number of capital letters gives you the level of meta-ness. This is
very subtle, which is probably not a good thing.

Another approach would be to introduce a new dynamictype keyword that
doesn’t need to be accessed as a member of self, and keep Self the way it
is. Self should work in structs as a type alias.

Why don’t we turn this into a standard library function? It’s not something
you need so often that the member access is very valuable. Putting it in
the standard library as dynamicType(_:slight_smile: does still allow for that function
to be implemented using compiler magic.

func dynamicType<T>(_: T) -> T.Type { }

We have a proposal to remove .self on types. One reason .self exists is to
avoid the mistake of writing let x = Int — the compiler will give you a
weird type error later on in code if the value of x is what we today
call Int.self but you meant to call the Int() initializer. Creating a
metatype is not a common operation, so doing it explicitly is a good thing.

It’s weird that you can use the metatype directly to construct something or
to do member access, but you can’t access it as a bare value.

Coming back to this proposal, if we removed .self why would we want to
add .Self?

If you have a variable whose value is a metatype, you also keep its name in
lower case. So Self makes a little less sense from that aspect too.

Another perspective is that .dynamicType is just an implicitly synthesized
property on all type.

We do have other keywords that follow the dot on
types, Int.Type and Fooable.Protocol, so this isn’t the only thing. Those
things are magic nested types.

Subjectively, having dynamicType as a member feels weird.

If .self goes away, the four-self example above is simplified,
and .Self doesn’t make sense anymore. There’s also the difference
that .Self would be a runtime thing.


(Thorsten Seitz) #5

We could require optional methods which would return T to instead return OptionalResult<T> which is essentially an enum with values 'unimplemented' and 'implemented(T)', i.e. essentially the same as Optional but as a separate type to avoid confusion when the real result would be 'T?'.

Default implementations would answer 'unimplemented'.

This would require the caller to handle the unimplemented default case explicitly.

-Thorsten

···

Am 22.04.2016 um 02:58 schrieb David Waite via swift-evolution <swift-evolution@swift.org>:

On Apr 21, 2016, at 9:58 AM, Alex Martini via swift-evolution <swift-evolution@swift.org> wrote:

What to do about optional requirements

http://thread.gmane.org/gmane.comp.lang.swift.evolution/14046
Rename it to make it clearly an Objective-C interop feature. We could also forbid you actually spelling it in Swift code. That doesn’t work well because it breaks your ability to write code in Swift that has Objective-C clients — those clients won’t get the default implementation from the extensions like you would use with Swift clients instead of creating optional requirements.
Modeling optional requirements as a function of optional type such as ((A, B) -> C)? doesn’t work well. For example, properties can have optional type and they can be optional requirements, so you would end up having to deal with a lot of extra complexity due to double-optionals and likely want better code completion so you could type it all out.
You force the default implementation to be visible from all callers, and you do the dispatch at the call site. The only advantage of this is that it takes optional requirements out of the language entirely. If you wanted to implement the (somewhat common) pattern of checking whether a type implements an optional requirement, you would have to use a respondsToSelector check.

Calling an optional method on a delegate protocol and using the result to judge whether you should have some default behavior to me does seem a bit flimsy in retrospect (I originally proposed things like importing optional methods with throws and having an unimplemented method error raised by default, etc). You aren’t really trying to judge that the behavior ‘currently’ is the default, but that there is no behavior defined thus you can reliably *always* use the default.

To that end, you need some way to detect static features of a type at runtime. Today we have respondsToSelector for objc types, and checking for conformance to different protocols.

I don’t think supporting optional protocols in swift could work unless there was also a respondsToSelector equivalent for native swift types.

-DW

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


(Michael Peternell) #6

Is "Self" dynamically dispatched? What would the following program print?

class A: NSObject {
    static func myClassName() -> String {
        return "A"
    }
    func hello() -> String {
        return "I am a \(Self.myClassName())"
    }
}

class B: A {
    static func myClassName() -> String {
        return "B"
    }
}

print(B.init().hello())

Because I think "Self" would only cause confusion if it is statically dispatched. assert(B.init().hello() == "I am a B")

-Michael

···

Am 25.04.2016 um 13:33 schrieb Vladimir.S via swift-evolution <swift-evolution@swift.org>:

On 25.04.2016 4:57, Brent Royal-Gordon via swift-evolution wrote:
>> https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md
>
> I'm not totally clear what's being proposed here.
>
> Is this valid?
> ...

Yes, I'm also confused if it is a final proposal or some additions/changes are expected here? As we were also discussing #Self (in meaning "placeholder for name of current defining type", resolving at compilation time)

Also, there were notes regarding this proposal by @Alex Martini<amartini@apple.com> 21.04.2016 18:58 (quoted below), with suggestion for "dynamictype" keyword / "dynamicType" standard library function.

@Brent, your questions could be(in general) answered by replacing "Self" to "dynamicType", but actually there are more questions on this proposal, which I suggest to discuss.

We have some mess *right now* with all these dynamicType/self/Self :

* "self" in meaning of current instance reference (OK), dynamicType is dynamic type of the instance :
class A { func f() { self.something() } }
self.dynamicType is A

* "self" in meaning of current type object in static/class methods, dynamicType is meta type
class A { static func f() { self.something() } }
self.dynamicType is A.Type

* "Self" in meaning "placeholder to concrete defining class name" :
protocol AProtocol { func assignFrom(a: Self) }
class A : AProtocol { func assignFrom(a: A) {..} } // "A" here,not "Self"

* "Self" in meaning of dynamic type in runtime:
class A { func f() -> Self { return self } }

I'd like to discuss how the following current code should looks in Swift 3.0 :

----------------------------
protocol Proto {
   func z() -> Self
   func z(s: Self) // I propose the #Self here
}

class X: Proto {
   required init () {}
   func x() -> Self { return self.dynamicType.init() }
   func z() -> Self { return self }
   func z(s: X) {} // propose z(s: #Self) here

   static func staticF() -> Self {..} // shouldn't be #Self here?
   class func classF() -> Self {..}
}
----------------------------

"Notes from Swift core team 2016-04-20 design discussion" :

On 21.04.2016 18:58, Alex Martini via swift-evolution wrote:

     SE-0068: Expanding Swift Self to class members and value types

https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md

We have one keyword left in the language, dynamicType, which is camel
cased. This proposal renames it to Self instead.

In a static function today, self.dynamicType will give you a metatype but
the non-member Self will not. The most useful reason to reference it is to
call an initializer. It makes accessing the metatype weirder. It’s
not Self.Type; that’s a type — you have to spell it Self.type.

Quiz time! What do each of the permutations mean?

Self.self
self.Self
Self.Self
self.self

The number of capital letters gives you the level of meta-ness. This is
very subtle, which is probably not a good thing.

Another approach would be to introduce a new dynamictype keyword that
doesn’t need to be accessed as a member of self, and keep Self the way it
is. Self should work in structs as a type alias.

Why don’t we turn this into a standard library function? It’s not something
you need so often that the member access is very valuable. Putting it in
the standard library as dynamicType(_:slight_smile: does still allow for that function
to be implemented using compiler magic.

func dynamicType<T>(_: T) -> T.Type { }

We have a proposal to remove .self on types. One reason .self exists is to
avoid the mistake of writing let x = Int — the compiler will give you a
weird type error later on in code if the value of x is what we today
call Int.self but you meant to call the Int() initializer. Creating a
metatype is not a common operation, so doing it explicitly is a good thing.

It’s weird that you can use the metatype directly to construct something or
to do member access, but you can’t access it as a bare value.

Coming back to this proposal, if we removed .self why would we want to
add .Self?

If you have a variable whose value is a metatype, you also keep its name in
lower case. So Self makes a little less sense from that aspect too.

Another perspective is that .dynamicType is just an implicitly synthesized
property on all type.

We do have other keywords that follow the dot on
types, Int.Type and Fooable.Protocol, so this isn’t the only thing. Those
things are magic nested types.

Subjectively, having dynamicType as a member feels weird.

If .self goes away, the four-self example above is simplified,
and .Self doesn’t make sense anymore. There’s also the difference
that .Self would be a runtime thing.

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


(David Waite) #7

Sure, but I personally want to configure delegates early, when the delegate is set.

It may be inappropriate to send a synthetic message through (e.g. give me the table row height for arbitrary index -1 so I can detect if you have overridden behavior)

A default implementation may help the caller, but some API do consider a non-default implementation to be a flag in itself.

I don’t think you can meet current objective-c usage and meaning of optional protocols by collapsing the flag into default method behavior. This would cause problems when porting the objective-c caller of the delegate interface to swift.

-DW

···

On Apr 22, 2016, at 10:01 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

We could require optional methods which would return T to instead return OptionalResult<T> which is essentially an enum with values 'unimplemented' and 'implemented(T)', i.e. essentially the same as Optional but as a separate type to avoid confusion when the real result would be 'T?'.

Default implementations would answer 'unimplemented'.

This would require the caller to handle the unimplemented default case explicitly.

-Thorsten


(Shawn Erickson) #8

I have the same thoughts and also have code that configures itself on
delegate setting.

···

On Fri, Apr 22, 2016 at 10:04 AM David Waite via swift-evolution < swift-evolution@swift.org> wrote:

Sure, but I personally want to configure delegates early, when the
delegate is set.

It may be inappropriate to send a synthetic message through (e.g. give me
the table row height for arbitrary index -1 so I can detect if you have
overridden behavior)

A default implementation may help the caller, but some API do consider a
non-default implementation to be a flag in itself.

I don’t think you can meet current objective-c usage and meaning of
optional protocols by collapsing the flag into default method behavior.
This would cause problems when porting the objective-c caller of the
delegate interface to swift.

-DW

On Apr 22, 2016, at 10:01 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

We could require optional methods which would return T to instead return
OptionalResult<T> which is essentially an enum with values 'unimplemented'
and 'implemented(T)', i.e. essentially the same as Optional but as a
separate type to avoid confusion when the real result would be 'T?'.

Default implementations would answer 'unimplemented'.

This would require the caller to handle the unimplemented default case
explicitly.

-Thorsten

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


(Thorsten Seitz) #9

Ah, yes, you are right, I didn’t think of configuring delegates when the delegate ist set.

-Thorsten

···

Am 22.04.2016 um 19:04 schrieb David Waite <david@alkaline-solutions.com>:

Sure, but I personally want to configure delegates early, when the delegate is set.

It may be inappropriate to send a synthetic message through (e.g. give me the table row height for arbitrary index -1 so I can detect if you have overridden behavior)

A default implementation may help the caller, but some API do consider a non-default implementation to be a flag in itself.

I don’t think you can meet current objective-c usage and meaning of optional protocols by collapsing the flag into default method behavior. This would cause problems when porting the objective-c caller of the delegate interface to swift.

-DW

On Apr 22, 2016, at 10:01 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

We could require optional methods which would return T to instead return OptionalResult<T> which is essentially an enum with values 'unimplemented' and 'implemented(T)', i.e. essentially the same as Optional but as a separate type to avoid confusion when the real result would be 'T?'.

Default implementations would answer 'unimplemented'.

This would require the caller to handle the unimplemented default case explicitly.

-Thorsten


(Erica Sadun) #10

The current Swift will not allow your second example to compile.

-- E

···

On Apr 25, 2016, at 11:18 AM, Michael Peternell via swift-evolution <swift-evolution@swift.org> wrote:

Is "Self" dynamically dispatched? What would the following program print?

class A: NSObject {
   static func myClassName() -> String {
       return "A"
   }
   func hello() -> String {
       return "I am a \(Self.myClassName())"
   }
}

class B: A {
   static func myClassName() -> String {
       return "B"
   }
}

print(B.init().hello())

Because I think "Self" would only cause confusion if it is statically dispatched. assert(B.init().hello() == "I am a B")

-Michael


(Vladimir) #11

Is "Self" dynamically dispatched? What would the following program print?

In your example you can just replace "Self" to "self.dynamicType", the more questions appear if "Self" is used in protocol as result type and as parameter type

···

On 25.04.2016 20:18, Michael Peternell via swift-evolution wrote:

class A: NSObject {
    static func myClassName() -> String {
        return "A"
    }
    func hello() -> String {
        return "I am a \(Self.myClassName())"
    }
}

class B: A {
    static func myClassName() -> String {
        return "B"
    }
}

print(B.init().hello())

Because I think "Self" would only cause confusion if it is statically dispatched. assert(B.init().hello() == "I am a B")

-Michael

Am 25.04.2016 um 13:33 schrieb Vladimir.S via swift-evolution <swift-evolution@swift.org>:

On 25.04.2016 4:57, Brent Royal-Gordon via swift-evolution wrote:

https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md

I'm not totally clear what's being proposed here.

Is this valid?
...

Yes, I'm also confused if it is a final proposal or some additions/changes are expected here? As we were also discussing #Self (in meaning "placeholder for name of current defining type", resolving at compilation time)

Also, there were notes regarding this proposal by @Alex Martini<amartini@apple.com> 21.04.2016 18:58 (quoted below), with suggestion for "dynamictype" keyword / "dynamicType" standard library function.

@Brent, your questions could be(in general) answered by replacing "Self" to "dynamicType", but actually there are more questions on this proposal, which I suggest to discuss.

We have some mess *right now* with all these dynamicType/self/Self :

* "self" in meaning of current instance reference (OK), dynamicType is dynamic type of the instance :
class A { func f() { self.something() } }
self.dynamicType is A

* "self" in meaning of current type object in static/class methods, dynamicType is meta type
class A { static func f() { self.something() } }
self.dynamicType is A.Type

* "Self" in meaning "placeholder to concrete defining class name" :
protocol AProtocol { func assignFrom(a: Self) }
class A : AProtocol { func assignFrom(a: A) {..} } // "A" here,not "Self"

* "Self" in meaning of dynamic type in runtime:
class A { func f() -> Self { return self } }

I'd like to discuss how the following current code should looks in Swift 3.0 :

----------------------------
protocol Proto {
   func z() -> Self
   func z(s: Self) // I propose the #Self here
}

class X: Proto {
   required init () {}
   func x() -> Self { return self.dynamicType.init() }
   func z() -> Self { return self }
   func z(s: X) {} // propose z(s: #Self) here

   static func staticF() -> Self {..} // shouldn't be #Self here?
   class func classF() -> Self {..}
}
----------------------------

"Notes from Swift core team 2016-04-20 design discussion" :

On 21.04.2016 18:58, Alex Martini via swift-evolution wrote:

     SE-0068: Expanding Swift Self to class members and value types

https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md

We have one keyword left in the language, dynamicType, which is camel
cased. This proposal renames it to Self instead.

In a static function today, self.dynamicType will give you a metatype but
the non-member Self will not. The most useful reason to reference it is to
call an initializer. It makes accessing the metatype weirder. It’s
not Self.Type; that’s a type — you have to spell it Self.type.

Quiz time! What do each of the permutations mean?

Self.self
self.Self
Self.Self
self.self

The number of capital letters gives you the level of meta-ness. This is
very subtle, which is probably not a good thing.

Another approach would be to introduce a new dynamictype keyword that
doesn’t need to be accessed as a member of self, and keep Self the way it
is. Self should work in structs as a type alias.

Why don’t we turn this into a standard library function? It’s not something
you need so often that the member access is very valuable. Putting it in
the standard library as dynamicType(_:slight_smile: does still allow for that function
to be implemented using compiler magic.

func dynamicType<T>(_: T) -> T.Type { }

We have a proposal to remove .self on types. One reason .self exists is to
avoid the mistake of writing let x = Int — the compiler will give you a
weird type error later on in code if the value of x is what we today
call Int.self but you meant to call the Int() initializer. Creating a
metatype is not a common operation, so doing it explicitly is a good thing.

It’s weird that you can use the metatype directly to construct something or
to do member access, but you can’t access it as a bare value.

Coming back to this proposal, if we removed .self why would we want to
add .Self?

If you have a variable whose value is a metatype, you also keep its name in
lower case. So Self makes a little less sense from that aspect too.

Another perspective is that .dynamicType is just an implicitly synthesized
property on all type.

We do have other keywords that follow the dot on
types, Int.Type and Fooable.Protocol, so this isn’t the only thing. Those
things are magic nested types.

Subjectively, having dynamicType as a member feels weird.

If .self goes away, the four-self example above is simplified,
and .Self doesn’t make sense anymore. There’s also the difference
that .Self would be a runtime thing.

_______________________________________________
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