Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-29 Thread Rod Brown via swift-evolution

> On 30 Dec 2016, at 10:50 am, Freak Show  wrote:
> 
> 
>> On Dec 29, 2016, at 13:28, Rod Brown via swift-evolution 
>>  wrote:
>> 
>> I’m in agreement that ‘dynamic’ is probably not what you want without a 
>> declaration.
> 
> I hold a completely opposite viewpoint.  Dynamic is always what I want and 
> table based is premature optimization.  Late binding is important.  I found 
> far too often when working in C++ (yes I am really flipping old) I would come 
> across code where a developer hadn't chosen to make a method virtual and I 
> found myself just up a creek with regards to extending that code.  Ditto 
> people declaring stuff final in Java for no good reason.
> 
> The important thing to consider is that the future is generally unknowable 
> and if you don't know the future you cannot make good choices about what 
> should and should not be dynamic.  So the conservative thing is to make 
> everything dynamic until you cannot afford it - which...is usually never.

Then that’s great. If you’d prefer to work with a more open, overridable and 
intercetable platform which is dynamic by default, Apple has your back: Obj-C. 
It’s not deprecated. It’s actually the language they’re still writing iOS, OS 
X, tvOS and watchOS higher level frameworks in still, so you’re covered. Who is 
forcing you to use Swift, a language where compiler optimisations like this a 
stated goal?

> 
>> The only difference between table and method dispatch is the Objective-C 
>> message dispatch system. Unless users want to work around things by manually 
>> handling with some of the complex machinery in Obj-C, which is rare, then 
>> there is no reason behind doing so, and all it comes down to is a relatively 
>> large performance hit for nothing. And to be honest, with very few 
>> exceptions, if you’re using that ultra-dynamic machinery, you’re probably 
>> Doing It Wrong in the first place.
> 
> I do this sort of thing routinely and I assure you I am not Doing It Wrong.

Ok, so you do it a lot. That means definitively it’s the best way?

Obj-C was designed to constantly be interfering with method dispatch? You can 
do it, it’s there, message forwarding, those types of mechanisms, but if you’re 
relying on that for your day-to-day work, you’re in for a load of trouble, and 
you’re hacking around frameworks using the language rather than working with 
the frameworks. Apple don’t design their frameworks first and foremost for us 
to get in there and start using method swizzling or the like - in fact they 
specifically discourage it. Just because you do it and you think you’re smart 
doesn’t make it good design.

There are rare instances where frameworks and implementations use some of the 
really dynamic stuff, like CoreData, or KVO. That’s great. I’m not arguing 
there isn’t a use for it. I’m saying you pay a massive hit, 90% of the time for 
no reason.

> 
> I don't get why there is so much emphasis on performance in this day and age. 
>  I haven't run into a performance problem I could trace to speed of 
> ObjectiveC's method dispatching since the early 90’s.

Do a time profile of a modern Obj-C application. You’ll find that 15% of the 
time the application is running, it’s stuck in the middle of objc_msgSend. 
That’s a massive overhead in anyone’s books. Why is this important?

1. More CPU use equals more battery drain. Considering the vast majority of 
Apple’s platforms and the direction of computing as a whole is dependent on 
batteries rather than plugs in walls, this is important.

2. Moore’s Law won’t continue. We’re getting to the end of the road in what CPU 
advances have given us, and all those core multiplications just ends in more 
locks - we need to be more efficient because in 40 years of computing, we 
haven’t worried about making our software better, we just waited for CPU’s to 
catch up. News Flash: They won’t. Time for us to stop justifying ourselves and 
do something about making ourselves better at using the processing power we 
have.

3. Swift wasn’t designed just to replace Obj-C, a relatively high level 
language. It was designed to scale from system programming to the higher levels 
as well. Obj-C is good for basic UI development because you rarely tax the 
limits and are rarely worried about getting performance out of it.

4. Because performance in the language and its frameworks benefits everyone by 
giving more flexibility to their users.

> 
> Second - I have quite a lot of code that relies on this sort of dynamism. 
> I've been a very serious C++ developer and a very serious Smalltalk 
> programmer at various times in my career and I value the flexibility of late 
> binding far above performance.
> 
>> If you need this functionality, dynamic still exists. But Swift is Table 
>> Dispatch by default for a reason: you’re paying a massive penalty for 
>> something you’ll rarely if ever use, and it should be opt in.
> 
> Strongly disagree.  
>> 
>> 
>>> 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-29 Thread Dave Abrahams via swift-evolution

on Thu Dec 29 2016, Freak Show  wrote:

>> On Dec 29, 2016, at 13:28, Rod Brown via swift-evolution 
>>  wrote:
>> 
>> I’m in agreement that ‘dynamic’ is probably not what you want without a 
>> declaration.
>
> I hold a completely opposite viewpoint.  Dynamic is always what I want
> and table based is premature optimization.  Late binding is important.
> I found far too often when working in C++ (yes I am really flipping
> old) I would come across code where a developer hadn't chosen to make
> a method virtual and I found myself just up a creek with regards to
> extending that code.  Ditto people declaring stuff final in Java for
> no good reason.
>
> The important thing to consider is that the future is generally
> unknowable and if you don't know the future you cannot make good
> choices about what should and should not be dynamic.  So the
> conservative thing is to make everything dynamic until you cannot
> afford it - which...is usually never.

By that measure there should be no encapsulation; we should make
everything public, because somebody might need it someday.

Cheers,

-- 
-Dave

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


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-29 Thread Freak Show via swift-evolution

> On Dec 29, 2016, at 13:28, Rod Brown via swift-evolution 
>  wrote:
> 
> I’m in agreement that ‘dynamic’ is probably not what you want without a 
> declaration.

I hold a completely opposite viewpoint.  Dynamic is always what I want and 
table based is premature optimization.  Late binding is important.  I found far 
too often when working in C++ (yes I am really flipping old) I would come 
across code where a developer hadn't chosen to make a method virtual and I 
found myself just up a creek with regards to extending that code.  Ditto people 
declaring stuff final in Java for no good reason.

The important thing to consider is that the future is generally unknowable and 
if you don't know the future you cannot make good choices about what should and 
should not be dynamic.  So the conservative thing is to make everything dynamic 
until you cannot afford it - which...is usually never.

> The only difference between table and method dispatch is the Objective-C 
> message dispatch system. Unless users want to work around things by manually 
> handling with some of the complex machinery in Obj-C, which is rare, then 
> there is no reason behind doing so, and all it comes down to is a relatively 
> large performance hit for nothing. And to be honest, with very few 
> exceptions, if you’re using that ultra-dynamic machinery, you’re probably 
> Doing It Wrong in the first place.

I do this sort of thing routinely and I assure you I am not Doing It Wrong.

I don't get why there is so much emphasis on performance in this day and age.  
I haven't run into a performance problem I could trace to speed of ObjectiveC's 
method dispatching since the early 90's.

Second - I have quite a lot of code that relies on this sort of dynamism. I've 
been a very serious C++ developer and a very serious Smalltalk programmer at 
various times in my career and I value the flexibility of late binding far 
above performance.

> If you need this functionality, dynamic still exists. But Swift is Table 
> Dispatch by default for a reason: you’re paying a massive penalty for 
> something you’ll rarely if ever use, and it should be opt in.

Strongly disagree.  
> 
> 
>> On 15 Dec 2016, at 10:15 am, Brian King via swift-evolution 
>>  wrote:
>> 
>> I wanted to follow up to a blog post I wrote about Message Dispatch in
>> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
>> mentioned some changes to NSObject that didn’t result in any
>> objections, so I thought it was time to see what the SE mailing list
>> thought.
>> 
>> I’ve read a few conversations on SE mailing list that have morphed
>> into abstract conversations about dynamic vs static dispatch. I want
>> to focus specifically on how Swift NSObject subclasses behave.
>> 
>> I think that there are 2 changes that will result in fewer bugs and
>> will not have a substantial impact on performance:
>> 
>> 
>> ## Remove Table Dispatch from NSObject
>> 
>> NSObject subclasses use table dispatch for the initial class
>> declaration block. I think that using message dispatch for NSObject
>> subclasses everywhere will result in a much more consistent developer
>> experience.
>> 
>> ## Block NSObject Visibility Optimizations
>> 
>> Swift upgrades method dispatch to final when the compiler can prove
>> that the method is not subclassed. I would like to see Swift be more
>> careful about the impact of these optimizations on message dispatch,
>> and consider message dispatch non-upgradable.
>> 
>> 
>> I thought it would help to frame this choice as a trade-off between
>> Swift’s goals of safe, fast, and expressive.
>> 
>> ## Safe
>> 
>> Always using message dispatch for NSObject subclasses will fix a class
>> of runtime errors in framework features that are designed around
>> message passing (e.g. KVO). Arguments against using dynamic features
>> like this are valid, but Cocoa frameworks still use dynamic features
>> and the above behaviors result in actual bugs. As a bonus, this will
>> resolve SR-584, where a table-dispatched method that is overridden by
>> a message dispatch method doesn’t behave correctly.
>> 
>> ## Fast
>> 
>> The above changes will result in slower dispatch in NSObject
>> subclasses. However, I don't think that these dispatch changes
>> actually have a tangible impact on performance. Most NSObject
>> subclasses sit on top of a lot of `objc_msgSend`, and if there is a
>> specific hot spot, it would still be optimizable via the final
>> keyword.
>> 
>> ## Expressive
>> 
>> Using table dispatch for NSObject without any source indication or
>> library documentation is not very expressive. I think it’s important
>> to weigh table dispatch behavior against all of the framework
>> documentation and developer experience that assume message dispatch.
>> This will also eliminate the need for a lot of `@objc` and `dynamic`
>> annotations that are often inconsistently applied depending on if they
>> are needed 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-29 Thread Rod Brown via swift-evolution
I’m in agreement that ‘dynamic’ is probably not what you want without a 
declaration.

There are currently some bugs in how dispatch works for overrides in Swift 
extensions, and I’d like to see any methods that conform to an @objc protocol 
being given an implicit @objc, but true dynamic? No.

The only difference between table and method dispatch is the Objective-C 
message dispatch system. Unless users want to work around things by manually 
handling with some of the complex machinery in Obj-C, which is rare, then there 
is no reason behind doing so, and all it comes down to is a relatively large 
performance hit for nothing. And to be honest, with very few exceptions, if 
you’re using that ultra-dynamic machinery, you’re probably Doing It Wrong in 
the first place. If you need this functionality, dynamic still exists. But 
Swift is Table Dispatch by default for a reason: you’re paying a massive 
penalty for something you’ll rarely if ever use, and it should be opt in.


> On 15 Dec 2016, at 10:15 am, Brian King via swift-evolution 
>  wrote:
> 
> I wanted to follow up to a blog post I wrote about Message Dispatch in
> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
> mentioned some changes to NSObject that didn’t result in any
> objections, so I thought it was time to see what the SE mailing list
> thought.
> 
> I’ve read a few conversations on SE mailing list that have morphed
> into abstract conversations about dynamic vs static dispatch. I want
> to focus specifically on how Swift NSObject subclasses behave.
> 
> I think that there are 2 changes that will result in fewer bugs and
> will not have a substantial impact on performance:
> 
> 
> ## Remove Table Dispatch from NSObject
> 
> NSObject subclasses use table dispatch for the initial class
> declaration block. I think that using message dispatch for NSObject
> subclasses everywhere will result in a much more consistent developer
> experience.
> 
> ## Block NSObject Visibility Optimizations
> 
> Swift upgrades method dispatch to final when the compiler can prove
> that the method is not subclassed. I would like to see Swift be more
> careful about the impact of these optimizations on message dispatch,
> and consider message dispatch non-upgradable.
> 
> 
> I thought it would help to frame this choice as a trade-off between
> Swift’s goals of safe, fast, and expressive.
> 
> ## Safe
> 
> Always using message dispatch for NSObject subclasses will fix a class
> of runtime errors in framework features that are designed around
> message passing (e.g. KVO). Arguments against using dynamic features
> like this are valid, but Cocoa frameworks still use dynamic features
> and the above behaviors result in actual bugs. As a bonus, this will
> resolve SR-584, where a table-dispatched method that is overridden by
> a message dispatch method doesn’t behave correctly.
> 
> ## Fast
> 
> The above changes will result in slower dispatch in NSObject
> subclasses. However, I don't think that these dispatch changes
> actually have a tangible impact on performance. Most NSObject
> subclasses sit on top of a lot of `objc_msgSend`, and if there is a
> specific hot spot, it would still be optimizable via the final
> keyword.
> 
> ## Expressive
> 
> Using table dispatch for NSObject without any source indication or
> library documentation is not very expressive. I think it’s important
> to weigh table dispatch behavior against all of the framework
> documentation and developer experience that assume message dispatch.
> This will also eliminate the need for a lot of `@objc` and `dynamic`
> annotations that are often inconsistently applied depending on if they
> are needed in the scope they are defined in (e.g. class vs extension).
> 
> 
> If this idea shows promise, I’d be glad to formalize a Swift Evolution
> Proposal and explore syntactic details. I think being able to flag a
> class with `dynamic` and applying this flag to `NSObject` may be the
> only syntactic change needed. However, it would be good to debate the
> merit of the behavior change before the syntax.
> 
> 
> Thanks!
> 
> 
> Brian King
> ___
> 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] Changing NSObject dispatch behavior

2016-12-19 Thread Charles Srstka via swift-evolution
> On Dec 19, 2016, at 1:57 PM, Kevin Ballard  wrote:
> 
> On Fri, Dec 16, 2016, at 06:30 AM, Charles Srstka wrote:
>>> On Dec 16, 2016, at 12:36 AM, Kevin Ballard >> > wrote:
>>> 
>>> On Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
> On Dec 15, 2016, at 4:33 PM, Kevin Ballard  > wrote:
> 
> The problem with that code isn't that `dynamic` doesn't work for computed 
> properties. It does; if you mutate the `foo` property, you'll get the KVO 
> notifications. The problem is you have one property that depends on 
> another and you didn't set up the KVO machinery properly using 
> automaticallyNotifiesObservers(forKey:) or 
> automaticallyNotifiesObserversOf() (incidentally in Swift you can 
> write the latter as a `static let`, since that becomes a class method in 
> Obj-C).
 
 You’ll only get the notifications if you mutate ‘foo’ directly. This, 
 however, is fairly useless, because if you are watching ‘foo’, you want to 
 be notified every time the value changes, not just when someone hits one 
 particular accessor. Code relying on observation of ‘foo’ in the example I 
 provided would be prone to breaking in mysterious and possibly horrible 
 ways.
>>> 
>>> No, if you implement keyPathsForValuesAffecting() then you get "foo" 
>>> KVO notifications when "bar" is mutated.  That's the whole point of that 
>>> method, and this is exactly what you have to do in Obj-C as well.
>> 
>> Right… the sentence I was quoting was talking about code which uses 
>> ‘dynamic’ but *doesn’t* use keyPathsForValuesAffecting. You’ll get 
>> notifications if someone calls that one particular accessor, but otherwise 
>> you won’t.
> 
> You can always write buggy code. If you're using `dynamic` for KVO purposes, 
> then not implementing keyPathsForValuesAffecting in this case is 
> strictly a bug. If you're using `dynamic` for something other than KVO, and 
> your property won't end up supporting KVO properly by default, then you 
> should document it as such, given that the natural assumption for a `dynamic` 
> property is that it supports KVO.

If you’re using ‘dynamic’ for KVO purposes, you should document it as such. If 
you are using it for something else, not implementing KVO is not in any way a 
bug. Relying on KVO for properties that are not documented to be compliant, 
though, *is.*

Documentation is the only reliable way to check for KVO conformance. I have a 
class with 28 KVO-compliant methods on it. Of those, exactly 4 are marked as 
‘dynamic’. The presence of the ‘dynamic’ keyword is not a good thing to rely on 
for this (and the lack of a good built-in mechanism is part of why, IMO, we 
need something new to replace KVO).

> So yes, `dynamic` by itself doesn't mean that the property supports KVO. 
> But there are very few reasons to use `dynamic` outside of supporting 
> KVO, so it's a pretty good signal that the property does support it. And 
> conversely, not having `dynamic` doesn't mean that it doesn't support 
> KVO, though if it does have manual KVO support using 
> will/didChangeValue(forKey:) then it should be documented as such.
 Use of the ‘dynamic’ keyword enables all manner of runtime hackery which 
 someone may be employing. The trick to automatically add KVO conformance 
 to accessors is probably the most common, but it’s hardly the only one. 
 One also might want to declare things ‘dynamic’ when working with 
 Objective-C frameworks not under one’s control which might assume the 
 ability to do metaprogramming on your classes
>>> 
>>> That is exceedingly rare. I can't even remember the last time I used such a 
>>> thing.
>> 
>> You used such a thing the last time you used KVO. ;-)
> 
> We were talking about metaprogramming other than KVO.

We were talking about libraries and/or frameworks that have the ability to do 
metaprogramming, which when you come down to it is all KVO is. KVO is the most 
popular of these, but keep in mind that all Objective-C code written before 
2014 is assuming that *every* method is *always* going to be dynamically 
dispatched, and as a result may act on those assumptions. For example, consider 
the following contrived example:

import Foundation

class Foo: NSObject {
@objc func sayHello() {
print("Hello World")
}
}

class Bar: NSObject {
@objc func doSomething(with foo: Foo) 
foo.sayHello()
}
}

let foo = Foo()
let bar = Bar()

SomeLegacyObjectiveCAPI().doSomething(with: foo, andSendItBackTo: bar, 
selector: #selector(Bar.doSomething(with:)))

Is this safe? On the surface, it looks like it. However, for all we know, the 
Objective-C API may send us back an NSProxy pretending to be our Foo object, 
rather than the Foo object itself. This is perfectly legal by Objective-C 
conventions, the proxy will look like a Foo due to 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-19 Thread Kevin Ballard via swift-evolution
On Fri, Dec 16, 2016, at 06:30 AM, Charles Srstka wrote:
>> On Dec 16, 2016, at 12:36 AM, Kevin Ballard  wrote:
>> 

>> On Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
 On Dec 15, 2016, at 4:33 PM, Kevin Ballard  wrote:
 

 The problem with that code isn't that `dynamic` doesn't work for
 computed properties. It does; if you mutate the `foo` property,
 you'll get the KVO notifications. The problem is you have one
 property that depends on another and you didn't set up the KVO
 machinery properly using automaticallyNotifiesObservers(forKey:) or
 automaticallyNotifiesObserversOf() (incidentally in Swift you
 can write the latter as a `static let`, since that becomes a class
 method in Obj-C).
>>> 

>>> You’ll only get the notifications if you mutate ‘foo’ directly.
>>> This, however, is fairly useless, because if you are watching ‘foo’,
>>> you want to be notified every time the value changes, not just when
>>> someone hits one particular accessor. Code relying on observation of
>>> ‘foo’ in the example I provided would be prone to breaking in
>>> mysterious and possibly horrible ways.
>> 

>> No, if you implement keyPathsForValuesAffecting()  then you get
>> "foo" KVO notifications when "bar" is mutated.  That's the whole
>> point of that method, and this is exactly what you have to do in Obj-
>> C as well.
> 

> Right… the sentence I was quoting was talking about code which uses
> ‘dynamic’ but *doesn’t* use keyPathsForValuesAffecting. You’ll
> get notifications if someone calls that one particular accessor, but
> otherwise you won’t.


You can always write buggy code. If you're using `dynamic` for KVO
purposes, then not implementing keyPathsForValuesAffecting in this
case is strictly a bug. If you're using `dynamic` for something other
than KVO, and your property won't end up supporting KVO properly by
default, then you should document it as such, given that the natural
assumption for a `dynamic` property is that it supports KVO.


 So yes, `dynamic` by itself doesn't mean that the property supports
 KVO. But there are very few reasons to use `dynamic` outside of
 supporting KVO, so it's a pretty good signal that the property does
 support it. And conversely, not having `dynamic` doesn't mean that
 it doesn't support KVO, though if it does have manual KVO support
 using will/didChangeValue(forKey:) then it should be documented as
 such.
>>> Use of the ‘dynamic’ keyword enables all manner of runtime hackery
>>> which someone may be employing. The trick to automatically add KVO
>>> conformance to accessors is probably the most common, but it’s
>>> hardly the only one. One also might want to declare things ‘dynamic’
>>> when working with Objective-C frameworks not under one’s control
>>> which might assume the ability to do metaprogramming on your classes
>> 

>> That is exceedingly rare. I can't even remember the last time I used
>> such a thing.
> 

> You used such a thing the last time you used KVO. ;-)



We were talking about metaprogramming other than KVO.



>>> I know it’s commonplace to use ‘dynamic’ all over the place wherever
>>> Core Data is involved.
>> 

>> It is? Why? Maybe you're confusing this with Obj-C's @dynamic
>> keyword, which is completely unrelated to Swift's `dynamic`. When
>> writing Swift NSManagedObject subclasses, you use the @NSManaged
>> property attribute, not the `dynamic` keyword (@NSManaged does
>> effectively the same thing that Obj-C's @dynamic, except it's
>> reserved for integration with CoreData instead of being as generic as
>> Obj-C's @dynamic is).
> 

> @NSManaged implies dynamic, though. Core Data is entirely built on the
> dynamic runtime, and is using it pretty much everywhere.


@NSManaged could easily be implemented by codegenning static-dispatch
methods that invoke the primitive accessors and will/didChange KVO
broadcasts. Presumably it doesn't (presumably it does literally the same
thing @dynamic does in Obj-C, which is that it makes the assumption that
the methods exist at runtime even though they're unknown at compile-
time), but there's nothing about @NSManaged that requires it to always
use dynamic dispatch. Core Data leverages the dynamic runtime for method
generation, but it doesn't actually require it (you can completely
ignore dynamicism and implement your properties in terms of
primitiveValue(forKey:) and setPrimitiveValue(_:forKey:), though the 
dynamically-
synthesized primitive accessors are supposed to be more efficient).


>>> Long story short, ‘dynamic’ does not guarantee KVO conformance in
>>> any way, shape, or form.
>> 

>> And declaring that your property returns a String doesn't guarantee
>> that it actually does either. You can always write broken code. But
>> `dynamic` is required for automatic KVO conformance, and it's
>> extremely rare to have a reason to use `dynamic` outside of KVO, so
>> it's a really really strong signal that 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-16 Thread Charles Srstka via swift-evolution
> On Dec 16, 2016, at 12:36 AM, Kevin Ballard  wrote:
> 
> On Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
>>> On Dec 15, 2016, at 4:33 PM, Kevin Ballard >> > wrote:
>>> 
>>> The problem with that code isn't that `dynamic` doesn't work for computed 
>>> properties. It does; if you mutate the `foo` property, you'll get the KVO 
>>> notifications. The problem is you have one property that depends on another 
>>> and you didn't set up the KVO machinery properly using 
>>> automaticallyNotifiesObservers(forKey:) or 
>>> automaticallyNotifiesObserversOf() (incidentally in Swift you can 
>>> write the latter as a `static let`, since that becomes a class method in 
>>> Obj-C).
>> 
>> You’ll only get the notifications if you mutate ‘foo’ directly. This, 
>> however, is fairly useless, because if you are watching ‘foo’, you want to 
>> be notified every time the value changes, not just when someone hits one 
>> particular accessor. Code relying on observation of ‘foo’ in the example I 
>> provided would be prone to breaking in mysterious and possibly horrible ways.
> 
> No, if you implement keyPathsForValuesAffecting() then you get "foo" KVO 
> notifications when "bar" is mutated.  That's the whole point of that method, 
> and this is exactly what you have to do in Obj-C as well.

Right… the sentence I was quoting was talking about code which uses ‘dynamic’ 
but *doesn’t* use keyPathsForValuesAffecting. You’ll get notifications if 
someone calls that one particular accessor, but otherwise you won’t.

>>> So yes, `dynamic` by itself doesn't mean that the property supports KVO. 
>>> But there are very few reasons to use `dynamic` outside of supporting KVO, 
>>> so it's a pretty good signal that the property does support it. And 
>>> conversely, not having `dynamic` doesn't mean that it doesn't support KVO, 
>>> though if it does have manual KVO support using 
>>> will/didChangeValue(forKey:) then it should be documented as such.
>> Use of the ‘dynamic’ keyword enables all manner of runtime hackery which 
>> someone may be employing. The trick to automatically add KVO conformance to 
>> accessors is probably the most common, but it’s hardly the only one. One 
>> also might want to declare things ‘dynamic’ when working with Objective-C 
>> frameworks not under one’s control which might assume the ability to do 
>> metaprogramming on your classes
> 
> That is exceedingly rare. I can't even remember the last time I used such a 
> thing.

You used such a thing the last time you used KVO. ;-)

>> I know it’s commonplace to use ‘dynamic’ all over the place wherever Core 
>> Data is involved.
> 
> It is? Why? Maybe you're confusing this with Obj-C's @dynamic keyword, which 
> is completely unrelated to Swift's `dynamic`. When writing Swift 
> NSManagedObject subclasses, you use the @NSManaged property attribute, not 
> the `dynamic` keyword (@NSManaged does effectively the same thing that 
> Obj-C's @dynamic, except it's reserved for integration with CoreData instead 
> of being as generic as Obj-C's @dynamic is).

@NSManaged implies dynamic, though. Core Data is entirely built on the dynamic 
runtime, and is using it pretty much everywhere.

>> Long story short, ‘dynamic’ does not guarantee KVO conformance in any way, 
>> shape, or form.
> 
> And declaring that your property returns a String doesn't guarantee that it 
> actually does either. You can always write broken code. But `dynamic` is 
> required for automatic KVO conformance, and it's extremely rare to have a 
> reason to use `dynamic` outside of KVO, so it's a really really strong signal 
> that the property supports KVO. If you're using `dynamic` on a property but 
> don't support KVO correctly, as you showed in your code example, that's a bug 
> with your code.

Correlation does not imply causation. Dynamic properties often support KVO, but 
the developer may have just declared it dynamic in order to use Objective-C’s 
dynamism to solve some other problem. You don’t know, and thus I certainly 
wouldn’t call it a bug in the code.

Charles

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


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
>> On Dec 15, 2016, at 4:33 PM, Kevin Ballard  wrote:
>> 

>> The problem with that code isn't that `dynamic` doesn't work for
>> computed properties. It does; if you mutate the `foo` property,
>> you'll get the KVO notifications. The problem is you have one
>> property that depends on another and you didn't set up the KVO
>> machinery properly using automaticallyNotifiesObservers(forKey:) or
>> automaticallyNotifiesObserversOf() (incidentally in Swift you
>> can write the latter as a `static let`, since that becomes a class
>> method in Obj-C).
> 

> You’ll only get the notifications if you mutate ‘foo’ directly. This,
> however, is fairly useless, because if you are watching ‘foo’, you
> want to be notified every time the value changes, not just when
> someone hits one particular accessor. Code relying on observation of
> ‘foo’ in the example I provided would be prone to breaking in
> mysterious and possibly horrible ways.


No, if you implement keyPathsForValuesAffecting()  then you get
"foo" KVO notifications when "bar" is mutated.  That's the whole
point of that method, and this is exactly what you have to do in Obj-
C as well.


>> So yes, `dynamic` by itself doesn't mean that the property supports
>> KVO. But there are very few reasons to use `dynamic` outside of
>> supporting KVO, so it's a pretty good signal that the property does
>> support it. And conversely, not having `dynamic` doesn't mean that it
>> doesn't support KVO, though if it does have manual KVO support using
>> will/didChangeValue(forKey:) then it should be documented as such.
> Use of the ‘dynamic’ keyword enables all manner of runtime hackery
> which someone may be employing. The trick to automatically add KVO
> conformance to accessors is probably the most common, but it’s hardly
> the only one. One also might want to declare things ‘dynamic’ when
> working with Objective-C frameworks not under one’s control which
> might assume the ability to do metaprogramming on your classes


That is exceedingly rare. I can't even remember the last time I used
such a thing.


> I know it’s commonplace to use ‘dynamic’ all over the place wherever
> Core Data is involved.


It is? Why? Maybe you're confusing this with Obj-C's @dynamic keyword,
which is completely unrelated to Swift's `dynamic`. When writing Swift
NSManagedObject subclasses, you use the @NSManaged property attribute,
not the `dynamic` keyword (@NSManaged does effectively the same thing
that Obj-C's @dynamic, except it's reserved for integration with
CoreData instead of being as generic as Obj-C's @dynamic is).


> Long story short, ‘dynamic’ does not guarantee KVO conformance in any
> way, shape, or form.


And declaring that your property returns a String doesn't guarantee that
it actually does either. You can always write broken code. But `dynamic`
is required for automatic KVO conformance, and it's extremely rare to
have a reason to use `dynamic` outside of KVO, so it's a really really
strong signal that the property supports KVO. If you're using `dynamic`
on a property but don't support KVO correctly, as you showed in your
code example, that's a bug with your code.


-Kevin Ballard



> On Dec 15, 2016, at 4:35 PM, Kevin Ballard  wrote:

> 

>> 

>> Oops, I mean keyPathsForValuesAffectingValue(forKey:) and
>> keyPathsForValuesAffecting().
>> 

>> That said, your code as written actually sends 2 KVO change notices
>> for "bar", and you do still need to implement
>> automaticallyNotifiesObservers… to disable the automatic KVO notice
>> for "bar".
> 

> Only when the accessor is called from Objective-C, in which the message-
> send is *always* dynamic and the presence of the ‘dynamic’ keyword is
> fairly academic. The example, which was simplified for the purpose of
> clarity, was to illustrate how things work with respect to Swift’s
> vtable dispatch system. A real-world example could shut off the
> automatic notifications, or declare the property as @nonobjc, or
> similar.


What? No. You marked the property as `dynamic`, which means it'll always
go through message send, which means it'll invoke automatic KVO
conformance and trigger 2 KVO notifications. And you can't mark a
property both `@nonobjc` and `dynamic` as the latter implies the former.


-Kevin Ballard


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


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Brian King via swift-evolution
OK, this is great, a little detail just clicked that I had not fully
thought through. My suggestion of using message dispatch only for NSObject
isn't really possible since `dynamic` doesn't support Swift types yet. So
any form of consistency argument is out the window.

But what is clear from the general tone is that dynamic behavior is to be
opted into, and that's not changing. I can PR `commonly_proposed.md`, to
save future runtime happy developers from treading into these waters if
interested. I am interested in ways to make dynamic easier to use, but I'm
not sure flagging a declaration is helpful enough to warrant the syntax.

Thanks all, I have a blog post to update, and I'm going to get back to
playing around with SR-584 -- the bug that began it all.

Brian

On Thu, Dec 15, 2016 at 10:00 PM, Joe Groff  wrote:

>
> > On Dec 15, 2016, at 6:48 PM, Brian King  wrote:
> >
> > Thanks Joe, that makes a lot of sense. But is the only metric for "the
> best possible strategy" performance? The best possible metric for NSObject
> could be to use message dispatch, because consistency with the frameworks
> and with it's legacy.
>
> The performance cost of objc_msgSend isn't that high, but it only supports
> dispatching ObjC-compatible methods. We'll need something similar to
> objc_msgSend for Swift method dispatch in its full generality, but vtables
> are easier to implement (and do have a much lower startup and dirty memory
> cost, and slightly lower per-method-call cost, so there are good reasons to
> use vtables when possible). The dispatch mechanism is orthogonal to the
> language semantics, and is an implementation detail. We don't want methods
> to be arbitrarily overridable at runtime by default, for reasons Kevin
> articulated well, and when the method implementation is bound at compile
> time, it shouldn't really matter how it's dispatched.
>
> -Joe
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Brian King via swift-evolution
On Thu, Dec 15, 2016 at 3:51 PM, Michael Ilseman  wrote:

> You would want a class-level `dynamic` that would also implicitly apply to
> any subclasses? This feels a little different than how Swift normally
> chooses defaults, could you elaborate more on why or if there’s anything
> else in the language analogous to this?
>

I'm not entirely sure how it should behave to be honest. Having the
`dynamic` version of `final` would be a nice feature though. Since final
stops inheritance as well, it could be considered as influencing the entire
class hierarchy! I think this could be a large lever and effect the entire
hierarchy, or a smaller lever and just effect the declaration. I was
thinking that it would influence all the subclasses as well.


> I’m not familiar enough with these kinds of bugs. Kevin, do you think the
> existing behavior aligns with or runs counter to safe-by-default?
>

It's interesting hearing this called 'safe by default'. To me it's unsafe
by default since you can use KVO and it can compile and not work, and only
1 paragraph in the Swift book, or experience will teach you this.


> That’s a very thoughtful and informative post, thank you for writing it! I
> haven’t read the whole thing, but relevant to this, here are a couple
> tweaks:
>

Thanks for the feedback! I'm going to update the post soon and will add
that to the list.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Brian King via swift-evolution
First off, I'm still learning out how to debate at this speed, sorry for
the slow replies!

On Wed, Dec 14, 2016 at 9:32 PM, Kevin Ballard  wrote:

> On Wed, Dec 14, 2016, at 05:54 PM, Brian King wrote:
>
> Obj-C compatibility certainly is one reason to use NSObject, but perhaps a
> bigger reason is because you're subclassing some framework-provided class,
> like UIView or UIViewController. Just because I'm subclassing
> UIViewController doesn't mean I want my controller's API to be subject to
> Obj-C method dispatch unnecessarily.
>
> And even in the cases where I'm subclassing NSObject for Obj-C
> compatibility, that doesn't mean that most of the calls to my object are
> coming from Obj-C. All that means is that at least one place my object is
> used is Obj-C, and 99% of the uses might be Swift. Or if I'm writing a
> library, it might mean that I simply want to preserve Obj-C compatibility
> in case a client wants it, even though I expect my clients to be primarily
> Swift (For example, this is how postmates/PMHTTP is written;
> Obj-C–compatible, but the expectation is most clients will probably be
> Swift).
>

It's interesting, your library has very few non-final methods, because most
of your classes are `final`. it's great to have this option, and as a
result, it is very easy to write performant code. It is very wordy to write
runtime friendly code. I think I value these optimizations less than you,
to me it feels like it's pre-mature optimization, especially given how easy
it is to opt into Static dispatch.


>
> > > Interaction with Obj-C runtime machinery stuff like KVO should be
> opt-in. In Obj-C it's ad-hoc, many classes support it for properties but
> many also don't, and very few properties have their KVO conformance
> documented. I don't view having to mark my properties as `dynamic` to
> participate in KVO to be a problem with Swift but rather a feature. It
> tells the reader that this property supports KVO.
> >
> > This is an interesting point, and it would be an interesting semantic.
> > However in practice, the majority of NSObject code is imported from
> > obj-c, and it's generated interface does not follow this convention.
>
> Just because framework classes don't follow this convention doesn't mean
> it's not a valuable convention to have in code written in Swift. There's a
> lot of things that Swift does better than Obj-C, and that you don't get
> when using an API imported from Obj-C, but that's not a reason to not do
> those things.
>
> > Also, it's strange to conflate how something was dispatched and if it
> > supported KVO. I think property delegates will be the future here and
> > enable some exciting contracts if adopted.
> >
> > Another approach is to just make it easier to opt into the full obj-c
> > machinery. The addition of a class or extension level `dynamic`
> > keyword would be great. If we could get buy in on this, then the
> > debate becomes if NSObject should default to `dynamic` or not.
>
> I don't think we should ever make it possible to mark an entire class as
> `dynamic`. This just reintroduces the Obj-C problem, where many properties
> support KVO, but not all, and there's no indication on the property itself
> as to whether it supports it.
>

This would just be short hand for adding the `dynamic` keyword in front of
every variable and method, so shy of the already existing computed property
getter case, all of the properties should just work.


> -Kevin Ballard
>
> > Brian
> >
> > >
> > > -Kevin Ballard
> > >
> > > On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution
> wrote:
> > >> I wanted to follow up to a blog post I wrote about Message Dispatch in
> > >> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
> > >> mentioned some changes to NSObject that didn’t result in any
> > >> objections, so I thought it was time to see what the SE mailing list
> > >> thought.
> > >>
> > >> I’ve read a few conversations on SE mailing list that have morphed
> > >> into abstract conversations about dynamic vs static dispatch. I want
> > >> to focus specifically on how Swift NSObject subclasses behave.
> > >>
> > >> I think that there are 2 changes that will result in fewer bugs and
> > >> will not have a substantial impact on performance:
> > >>
> > >>
> > >> ## Remove Table Dispatch from NSObject
> > >>
> > >> NSObject subclasses use table dispatch for the initial class
> > >> declaration block. I think that using message dispatch for NSObject
> > >> subclasses everywhere will result in a much more consistent developer
> > >> experience.
> > >>
> > >> ## Block NSObject Visibility Optimizations
> > >>
> > >> Swift upgrades method dispatch to final when the compiler can prove
> > >> that the method is not subclassed. I would like to see Swift be more
> > >> careful about the impact of these optimizations on message dispatch,
> > >> and consider message dispatch non-upgradable.
> > >>
> > >>
> > >> I thought it would help to frame 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Charles Srstka via swift-evolution
> On Dec 15, 2016, at 4:33 PM, Kevin Ballard  wrote:
> 
> The problem with that code isn't that `dynamic` doesn't work for computed 
> properties. It does; if you mutate the `foo` property, you'll get the KVO 
> notifications. The problem is you have one property that depends on another 
> and you didn't set up the KVO machinery properly using 
> automaticallyNotifiesObservers(forKey:) or 
> automaticallyNotifiesObserversOf() (incidentally in Swift you can write 
> the latter as a `static let`, since that becomes a class method in Obj-C).

You’ll only get the notifications if you mutate ‘foo’ directly. This, however, 
is fairly useless, because if you are watching ‘foo’, you want to be notified 
every time the value changes, not just when someone hits one particular 
accessor. Code relying on observation of ‘foo’ in the example I provided would 
be prone to breaking in mysterious and possibly horrible ways.

> So yes, `dynamic` by itself doesn't mean that the property supports KVO. But 
> there are very few reasons to use `dynamic` outside of supporting KVO, so 
> it's a pretty good signal that the property does support it. And conversely, 
> not having `dynamic` doesn't mean that it doesn't support KVO, though if it 
> does have manual KVO support using will/didChangeValue(forKey:) then it 
> should be documented as such.

Use of the ‘dynamic’ keyword enables all manner of runtime hackery which 
someone may be employing. The trick to automatically add KVO conformance to 
accessors is probably the most common, but it’s hardly the only one. One also 
might want to declare things ‘dynamic’ when working with Objective-C frameworks 
not under one’s control which might assume the ability to do metaprogramming on 
your classes—I know it’s commonplace to use ‘dynamic’ all over the place 
wherever Core Data is involved. Long story short, ‘dynamic’ does not guarantee 
KVO conformance in any way, shape, or form.

On Dec 15, 2016, at 4:35 PM, Kevin Ballard  wrote:
> 
> Oops, I mean keyPathsForValuesAffectingValue(forKey:) and 
> keyPathsForValuesAffecting().
> 
> That said, your code as written actually sends 2 KVO change notices for 
> "bar", and you do still need to implement automaticallyNotifiesObservers… to 
> disable the automatic KVO notice for "bar".

Only when the accessor is called from Objective-C, in which the message-send is 
*always* dynamic and the presence of the ‘dynamic’ keyword is fairly academic. 
The example, which was simplified for the purpose of clarity, was to illustrate 
how things work with respect to Swift’s vtable dispatch system. A real-world 
example could shut off the automatic notifications, or declare the property as 
@nonobjc, or similar.

Charles

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


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 02:33 PM, Kevin Ballard wrote:
> On Thu, Dec 15, 2016, at 02:29 PM, Charles Srstka wrote:
> > > On Dec 15, 2016, at 2:51 PM, Michael Ilseman via swift-evolution 
> > >  wrote:
> > > 
> > >> I don't think we should ever make it possible to mark an entire class as 
> > >> `dynamic`. This just reintroduces the Obj-C problem, where many 
> > >> properties support KVO, but not all, and there's no indication on the 
> > >> property itself as to whether it supports it.
> > >> 
> > > 
> > > I’m not familiar enough with these kinds of bugs. Kevin, do you think the 
> > > existing behavior aligns with or runs counter to safe-by-default?
> > 
> > The problem Kevin describes is still here; ‘dynamic’ itself is quite 
> > orthogonal to KVO as a concept. A method being declared ‘dynamic’ is no 
> > guarantee that it actually supports KVO, and likewise, a method does not 
> > need to be marked ‘dynamic’ in order to support KVO. You can, for example, 
> > either call willChangeValue() and didChangeValue() in your willSet and 
> > didSet accessors for a stored property, or for a computed property you can 
> > simply implement the proper accessor methods to describe the dependencies, 
> > as in the example below.
> > 
> > import Foundation
> > 
> > class Watcher: NSObject {
> > var kvoContext = 0
> > 
> > init(watched: Watched) {
> > super.init()
> > watched.addObserver(self, forKeyPath: "foo", options: [], 
> > context: )
> > }
> > 
> > override func observeValue(forKeyPath keyPath: String?, of object: 
> > Any?, change: [NSKeyValueChangeKey : Any]?, context: 
> > UnsafeMutableRawPointer?) {
> > if context ==  {
> > print("foo changed; now it's \((object as! 
> > Watched).foo)")
> > } else {
> > super.observeValue(forKeyPath: keyPath, of: object, 
> > change: change, context: context)
> > }
> > }
> > }
> > 
> > class Watched: NSObject {
> > // not a single ‘dynamic’ member in here:
> > 
> > class func keyPathsForValuesAffectingFoo() -> Set { return 
> > ["bar"] }
> > var foo: Int {
> > get { return self.bar }
> > set(foo) { self.bar = foo }
> > }
> > 
> > var bar: Int = 0 {
> > willSet { self.willChangeValue(forKey: "bar") }
> > didSet { self.didChangeValue(forKey: "bar") }
> > }
> > }
> > 
> > let watched = Watched()
> > let watcher = Watcher(watched: watched)
> > 
> > watched.bar = 5 // outputs: "foo changed; now it's 5”
> > 
> > - - - - - -
> > 
> > All ‘dynamic’ does for you vis a vis KVO conformance is to automatically 
> > add the willChangeValue() and didChangeValue() calls, *for a stored 
> > property.* For a computed property, that doesn’t help you, if the 
> > dependencies aren’t properly set up. For example, if we replace the Watched 
> > class with:
> > 
> > class Watched: NSObject {
> > dynamic var foo: Int {
> > get { return self.bar }
> > set(foo) { self.bar = foo }
> > }
> > 
> > dynamic var bar: Int = 0 {
> > willSet { self.willChangeValue(forKey: "bar") }
> > didSet { self.didChangeValue(forKey: "bar") }
> > }
> > }
> > 
> > - - - - - -
> > 
> > and then change the “bar” property, no notifications will be fired, even 
> > though the value of ‘foo’ has indeed changed. So to a client of the class 
> > who can only see its interface and not the source code, ‘dynamic’ is 
> > useless on its own for determining KVO conformance.
> 
> The problem with that code isn't that `dynamic` doesn't work for computed 
> properties. It does; if you mutate the `foo` property, you'll get the KVO 
> notifications. The problem is you have one property that depends on another 
> and you didn't set up the KVO machinery properly using 
> automaticallyNotifiesObservers(forKey:) or 
> automaticallyNotifiesObserversOf() (incidentally in Swift you can write 
> the latter as a `static let`, since that becomes a class method in Obj-C).

Oops, I mean keyPathsForValuesAffectingValue(forKey:) and 
keyPathsForValuesAffecting().

That said, your code as written actually sends 2 KVO change notices for "bar", 
and you do still need to implement automaticallyNotifiesObservers… to disable 
the automatic KVO notice for "bar".

-Kevin Ballard

> So yes, `dynamic` by itself doesn't mean that the property supports KVO. But 
> there are very few reasons to use `dynamic` outside of supporting KVO, so 
> it's a pretty good signal that the property does support it. And conversely, 
> not having `dynamic` doesn't mean that it doesn't support KVO, though if it 
> does have manual KVO support using will/didChangeValue(forKey:) then it 
> should be documented as such.
> 
> > Bottom line: we really do need a new KVO-replacement system for Swift, one 
> > that could actually advertise itself as part of the interface instead of 
> > relying 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 02:29 PM, Charles Srstka wrote:
> > On Dec 15, 2016, at 2:51 PM, Michael Ilseman via swift-evolution 
> >  wrote:
> > 
> >> I don't think we should ever make it possible to mark an entire class as 
> >> `dynamic`. This just reintroduces the Obj-C problem, where many properties 
> >> support KVO, but not all, and there's no indication on the property itself 
> >> as to whether it supports it.
> >> 
> > 
> > I’m not familiar enough with these kinds of bugs. Kevin, do you think the 
> > existing behavior aligns with or runs counter to safe-by-default?
> 
> The problem Kevin describes is still here; ‘dynamic’ itself is quite 
> orthogonal to KVO as a concept. A method being declared ‘dynamic’ is no 
> guarantee that it actually supports KVO, and likewise, a method does not need 
> to be marked ‘dynamic’ in order to support KVO. You can, for example, either 
> call willChangeValue() and didChangeValue() in your willSet and didSet 
> accessors for a stored property, or for a computed property you can simply 
> implement the proper accessor methods to describe the dependencies, as in the 
> example below.
> 
> import Foundation
> 
> class Watcher: NSObject {
>   var kvoContext = 0
>   
>   init(watched: Watched) {
>   super.init()
>   watched.addObserver(self, forKeyPath: "foo", options: [], 
> context: )
>   }
>   
>   override func observeValue(forKeyPath keyPath: String?, of object: 
> Any?, change: [NSKeyValueChangeKey : Any]?, context: 
> UnsafeMutableRawPointer?) {
>   if context ==  {
>   print("foo changed; now it's \((object as! 
> Watched).foo)")
>   } else {
>   super.observeValue(forKeyPath: keyPath, of: object, 
> change: change, context: context)
>   }
>   }
> }
> 
> class Watched: NSObject {
>   // not a single ‘dynamic’ member in here:
> 
>   class func keyPathsForValuesAffectingFoo() -> Set { return 
> ["bar"] }
>   var foo: Int {
>   get { return self.bar }
>   set(foo) { self.bar = foo }
>   }
>   
>   var bar: Int = 0 {
>   willSet { self.willChangeValue(forKey: "bar") }
>   didSet { self.didChangeValue(forKey: "bar") }
>   }
> }
> 
> let watched = Watched()
> let watcher = Watcher(watched: watched)
> 
> watched.bar = 5 // outputs: "foo changed; now it's 5”
> 
> - - - - - -
> 
> All ‘dynamic’ does for you vis a vis KVO conformance is to automatically add 
> the willChangeValue() and didChangeValue() calls, *for a stored property.* 
> For a computed property, that doesn’t help you, if the dependencies aren’t 
> properly set up. For example, if we replace the Watched class with:
> 
> class Watched: NSObject {
>   dynamic var foo: Int {
>   get { return self.bar }
>   set(foo) { self.bar = foo }
>   }
>   
>   dynamic var bar: Int = 0 {
>   willSet { self.willChangeValue(forKey: "bar") }
>   didSet { self.didChangeValue(forKey: "bar") }
>   }
> }
> 
> - - - - - -
> 
> and then change the “bar” property, no notifications will be fired, even 
> though the value of ‘foo’ has indeed changed. So to a client of the class who 
> can only see its interface and not the source code, ‘dynamic’ is useless on 
> its own for determining KVO conformance.

The problem with that code isn't that `dynamic` doesn't work for computed 
properties. It does; if you mutate the `foo` property, you'll get the KVO 
notifications. The problem is you have one property that depends on another and 
you didn't set up the KVO machinery properly using 
automaticallyNotifiesObservers(forKey:) or 
automaticallyNotifiesObserversOf() (incidentally in Swift you can write 
the latter as a `static let`, since that becomes a class method in Obj-C).

So yes, `dynamic` by itself doesn't mean that the property supports KVO. But 
there are very few reasons to use `dynamic` outside of supporting KVO, so it's 
a pretty good signal that the property does support it. And conversely, not 
having `dynamic` doesn't mean that it doesn't support KVO, though if it does 
have manual KVO support using will/didChangeValue(forKey:) then it should be 
documented as such.

> Bottom line: we really do need a new KVO-replacement system for Swift, one 
> that could actually advertise itself as part of the interface instead of 
> relying on documentation (especially since Apple isn’t interested in writing 
> it anymore; the number of classes and methods that just say “No overview 
> available.” in the documentation viewer in Sierra is really quite 
> astounding). Unfortunately, this is probably additive, and thus probably 
> won’t be heard until the next phase of swift-evolution.
> 
> Charles
> 
___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 12:51 PM, Michael Ilseman wrote:

> 

>> On Dec 14, 2016, at 6:32 PM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:
>> 

>> I don't think we should ever make it possible to mark an entire class
>> as `dynamic`. This just reintroduces the Obj-C problem, where many
>> properties support KVO, but not all, and there's no indication on the
>> property itself as to whether it supports it.
> 

> I’m not familiar enough with these kinds of bugs. Kevin, do you think
> the existing behavior aligns with or runs counter to safe-by-default?


The existing behavior is safe-by-default. You have to opt-in to a
property supporting KVO, and the opt-in nature of this means that the
property is self-documenting as to whether it supports KVO. Of course,
it's possible to write a `dynamic` property that actually doesn't do KVO
properly (e.g. because it's a computed property that uses another
backing property, and you modify the backing property directly), but
since 99.9% of `dynamic` properties are only dynamic in order to support
KVO, I have no concerns about someone writing a `dynamic` property that
doesn't actually do KVO properly.


-Kevin Ballard


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


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Michael Ilseman via swift-evolution

> On Dec 14, 2016, at 6:32 PM, Kevin Ballard via swift-evolution 
>  wrote:
> 
> On Wed, Dec 14, 2016, at 05:54 PM, Brian King wrote:
>>> Please no. Just because I have to subclass NSObject doesn't mean I want to 
>>> discard the performance benefits of static dispatch, and it especially 
>>> doesn't mean I want to actually change the semantics of method resolution. 
>>> Taking an existing Swift class and changing its base class to NSObject 
>>> should not change how its methods are dispatched.
>> 
>> Subclassing NSObject already changes how dispatch happens. NSObject
>> extensions will use message dispatch for instance. I really don't
>> think that table -> message dispatch will result in a real life
>> performance impact, but I agree that consistency is valuable.
>> 
>> The static dispatch upgrade loss is disappointing. In practice
>> however, I don't think that this has ever had an impact on my code. If
>> performance is a consideration, most people just drop NSObject. If you
>> are using NSObject, you are probably using it because of a large
>> objective-c code base, in which case, I don't think the profiler is
>> really going to notice the few statically dispatched functions.
> 
> Obj-C compatibility certainly is one reason to use NSObject, but perhaps a 
> bigger reason is because you're subclassing some framework-provided class, 
> like UIView or UIViewController. Just because I'm subclassing 
> UIViewController doesn't mean I want my controller's API to be subject to 
> Obj-C method dispatch unnecessarily.
> 

In addition to UIView[Controller]s, pure Swift projects may also inherit from 
NSObject extensively in order to provide delegates, support NSCoding, etc. It 
would be counter-intuitive to me for methods on these otherwise pure Swift 
classes to not be vtable/de-virtualizable functions.

> And even in the cases where I'm subclassing NSObject for Obj-C compatibility, 
> that doesn't mean that most of the calls to my object are coming from Obj-C. 
> All that means is that at least one place my object is used is Obj-C, and 99% 
> of the uses might be Swift. Or if I'm writing a library, it might mean that I 
> simply want to preserve Obj-C compatibility in case a client wants it, even 
> though I expect my clients to be primarily Swift (For example, this is how 
> postmates/PMHTTP is written; Obj-C–compatible, but the expectation is most 
> clients will probably be Swift).
> 
>>> Interaction with Obj-C runtime machinery stuff like KVO should be opt-in. 
>>> In Obj-C it's ad-hoc, many classes support it for properties but many also 
>>> don't, and very few properties have their KVO conformance documented. I 
>>> don't view having to mark my properties as `dynamic` to participate in KVO 
>>> to be a problem with Swift but rather a feature. It tells the reader that 
>>> this property supports KVO.
>> 
>> This is an interesting point, and it would be an interesting semantic.
>> However in practice, the majority of NSObject code is imported from
>> obj-c, and it's generated interface does not follow this convention.
> 
> Just because framework classes don't follow this convention doesn't mean it's 
> not a valuable convention to have in code written in Swift. There's a lot of 
> things that Swift does better than Obj-C, and that you don't get when using 
> an API imported from Obj-C, but that's not a reason to not do those things.
> 
>> Also, it's strange to conflate how something was dispatched and if it
>> supported KVO. I think property delegates will be the future here and
>> enable some exciting contracts if adopted.
>> 
>> Another approach is to just make it easier to opt into the full obj-c
>> machinery. The addition of a class or extension level `dynamic`
>> keyword would be great. If we could get buy in on this, then the
>> debate becomes if NSObject should default to `dynamic` or not.
> 

You would want a class-level `dynamic` that would also implicitly apply to any 
subclasses? This feels a little different than how Swift normally chooses 
defaults, could you elaborate more on why or if there’s anything else in the 
language analogous to this?

> I don't think we should ever make it possible to mark an entire class as 
> `dynamic`. This just reintroduces the Obj-C problem, where many properties 
> support KVO, but not all, and there's no indication on the property itself as 
> to whether it supports it.
> 

I’m not familiar enough with these kinds of bugs. Kevin, do you think the 
existing behavior aligns with or runs counter to safe-by-default?

> -Kevin Ballard
> 
>> Brian
>> 
>>> 
>>> -Kevin Ballard
>>> 
>>> On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution wrote:
 I wanted to follow up to a blog post I wrote about Message Dispatch in
 Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
 mentioned some changes to NSObject that didn’t result in any
 objections, so I thought it was time to see what the SE mailing 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-14 Thread Kevin Ballard via swift-evolution
On Wed, Dec 14, 2016, at 05:54 PM, Brian King wrote:
> > Please no. Just because I have to subclass NSObject doesn't mean I want to 
> > discard the performance benefits of static dispatch, and it especially 
> > doesn't mean I want to actually change the semantics of method resolution. 
> > Taking an existing Swift class and changing its base class to NSObject 
> > should not change how its methods are dispatched.
> 
> Subclassing NSObject already changes how dispatch happens. NSObject
> extensions will use message dispatch for instance. I really don't
> think that table -> message dispatch will result in a real life
> performance impact, but I agree that consistency is valuable.
> 
> The static dispatch upgrade loss is disappointing. In practice
> however, I don't think that this has ever had an impact on my code. If
> performance is a consideration, most people just drop NSObject. If you
> are using NSObject, you are probably using it because of a large
> objective-c code base, in which case, I don't think the profiler is
> really going to notice the few statically dispatched functions.

Obj-C compatibility certainly is one reason to use NSObject, but perhaps a 
bigger reason is because you're subclassing some framework-provided class, like 
UIView or UIViewController. Just because I'm subclassing UIViewController 
doesn't mean I want my controller's API to be subject to Obj-C method dispatch 
unnecessarily.

And even in the cases where I'm subclassing NSObject for Obj-C compatibility, 
that doesn't mean that most of the calls to my object are coming from Obj-C. 
All that means is that at least one place my object is used is Obj-C, and 99% 
of the uses might be Swift. Or if I'm writing a library, it might mean that I 
simply want to preserve Obj-C compatibility in case a client wants it, even 
though I expect my clients to be primarily Swift (For example, this is how 
postmates/PMHTTP is written; Obj-C–compatible, but the expectation is most 
clients will probably be Swift).

> > Interaction with Obj-C runtime machinery stuff like KVO should be opt-in. 
> > In Obj-C it's ad-hoc, many classes support it for properties but many also 
> > don't, and very few properties have their KVO conformance documented. I 
> > don't view having to mark my properties as `dynamic` to participate in KVO 
> > to be a problem with Swift but rather a feature. It tells the reader that 
> > this property supports KVO.
> 
> This is an interesting point, and it would be an interesting semantic.
> However in practice, the majority of NSObject code is imported from
> obj-c, and it's generated interface does not follow this convention.

Just because framework classes don't follow this convention doesn't mean it's 
not a valuable convention to have in code written in Swift. There's a lot of 
things that Swift does better than Obj-C, and that you don't get when using an 
API imported from Obj-C, but that's not a reason to not do those things.

> Also, it's strange to conflate how something was dispatched and if it
> supported KVO. I think property delegates will be the future here and
> enable some exciting contracts if adopted.
> 
> Another approach is to just make it easier to opt into the full obj-c
> machinery. The addition of a class or extension level `dynamic`
> keyword would be great. If we could get buy in on this, then the
> debate becomes if NSObject should default to `dynamic` or not.

I don't think we should ever make it possible to mark an entire class as 
`dynamic`. This just reintroduces the Obj-C problem, where many properties 
support KVO, but not all, and there's no indication on the property itself as 
to whether it supports it.

-Kevin Ballard

> Brian
> 
> >
> > -Kevin Ballard
> >
> > On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution wrote:
> >> I wanted to follow up to a blog post I wrote about Message Dispatch in
> >> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
> >> mentioned some changes to NSObject that didn’t result in any
> >> objections, so I thought it was time to see what the SE mailing list
> >> thought.
> >>
> >> I’ve read a few conversations on SE mailing list that have morphed
> >> into abstract conversations about dynamic vs static dispatch. I want
> >> to focus specifically on how Swift NSObject subclasses behave.
> >>
> >> I think that there are 2 changes that will result in fewer bugs and
> >> will not have a substantial impact on performance:
> >>
> >>
> >> ## Remove Table Dispatch from NSObject
> >>
> >> NSObject subclasses use table dispatch for the initial class
> >> declaration block. I think that using message dispatch for NSObject
> >> subclasses everywhere will result in a much more consistent developer
> >> experience.
> >>
> >> ## Block NSObject Visibility Optimizations
> >>
> >> Swift upgrades method dispatch to final when the compiler can prove
> >> that the method is not subclassed. I would like to see Swift be more
> >> careful about the 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-14 Thread Brian King via swift-evolution
> Please no. Just because I have to subclass NSObject doesn't mean I want to 
> discard the performance benefits of static dispatch, and it especially 
> doesn't mean I want to actually change the semantics of method resolution. 
> Taking an existing Swift class and changing its base class to NSObject should 
> not change how its methods are dispatched.

Subclassing NSObject already changes how dispatch happens. NSObject
extensions will use message dispatch for instance. I really don't
think that table -> message dispatch will result in a real life
performance impact, but I agree that consistency is valuable.

The static dispatch upgrade loss is disappointing. In practice
however, I don't think that this has ever had an impact on my code. If
performance is a consideration, most people just drop NSObject. If you
are using NSObject, you are probably using it because of a large
objective-c code base, in which case, I don't think the profiler is
really going to notice the few statically dispatched functions.

> Interaction with Obj-C runtime machinery stuff like KVO should be opt-in. In 
> Obj-C it's ad-hoc, many classes support it for properties but many also 
> don't, and very few properties have their KVO conformance documented. I don't 
> view having to mark my properties as `dynamic` to participate in KVO to be a 
> problem with Swift but rather a feature. It tells the reader that this 
> property supports KVO.

This is an interesting point, and it would be an interesting semantic.
However in practice, the majority of NSObject code is imported from
obj-c, and it's generated interface does not follow this convention.
Also, it's strange to conflate how something was dispatched and if it
supported KVO. I think property delegates will be the future here and
enable some exciting contracts if adopted.

Another approach is to just make it easier to opt into the full obj-c
machinery. The addition of a class or extension level `dynamic`
keyword would be great. If we could get buy in on this, then the
debate becomes if NSObject should default to `dynamic` or not.


Brian

>
> -Kevin Ballard
>
> On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution wrote:
>> I wanted to follow up to a blog post I wrote about Message Dispatch in
>> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
>> mentioned some changes to NSObject that didn’t result in any
>> objections, so I thought it was time to see what the SE mailing list
>> thought.
>>
>> I’ve read a few conversations on SE mailing list that have morphed
>> into abstract conversations about dynamic vs static dispatch. I want
>> to focus specifically on how Swift NSObject subclasses behave.
>>
>> I think that there are 2 changes that will result in fewer bugs and
>> will not have a substantial impact on performance:
>>
>>
>> ## Remove Table Dispatch from NSObject
>>
>> NSObject subclasses use table dispatch for the initial class
>> declaration block. I think that using message dispatch for NSObject
>> subclasses everywhere will result in a much more consistent developer
>> experience.
>>
>> ## Block NSObject Visibility Optimizations
>>
>> Swift upgrades method dispatch to final when the compiler can prove
>> that the method is not subclassed. I would like to see Swift be more
>> careful about the impact of these optimizations on message dispatch,
>> and consider message dispatch non-upgradable.
>>
>>
>> I thought it would help to frame this choice as a trade-off between
>> Swift’s goals of safe, fast, and expressive.
>>
>> ## Safe
>>
>> Always using message dispatch for NSObject subclasses will fix a class
>> of runtime errors in framework features that are designed around
>> message passing (e.g. KVO). Arguments against using dynamic features
>> like this are valid, but Cocoa frameworks still use dynamic features
>> and the above behaviors result in actual bugs. As a bonus, this will
>> resolve SR-584, where a table-dispatched method that is overridden by
>> a message dispatch method doesn’t behave correctly.
>>
>> ## Fast
>>
>> The above changes will result in slower dispatch in NSObject
>> subclasses. However, I don't think that these dispatch changes
>> actually have a tangible impact on performance. Most NSObject
>> subclasses sit on top of a lot of `objc_msgSend`, and if there is a
>> specific hot spot, it would still be optimizable via the final
>> keyword.
>>
>> ## Expressive
>>
>> Using table dispatch for NSObject without any source indication or
>> library documentation is not very expressive. I think it’s important
>> to weigh table dispatch behavior against all of the framework
>> documentation and developer experience that assume message dispatch.
>> This will also eliminate the need for a lot of `@objc` and `dynamic`
>> annotations that are often inconsistently applied depending on if they
>> are needed in the scope they are defined in (e.g. class vs extension).
>>
>>
>> If this idea shows promise, I’d be glad to formalize a 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-14 Thread Kevin Ballard via swift-evolution
Please no. Just because I have to subclass NSObject doesn't mean I want to 
discard the performance benefits of static dispatch, and it especially doesn't 
mean I want to actually change the semantics of method resolution. Taking an 
existing Swift class and changing its base class to NSObject should not change 
how its methods are dispatched.

Interaction with Obj-C runtime machinery stuff like KVO should be opt-in. In 
Obj-C it's ad-hoc, many classes support it for properties but many also don't, 
and very few properties have their KVO conformance documented. I don't view 
having to mark my properties as `dynamic` to participate in KVO to be a problem 
with Swift but rather a feature. It tells the reader that this property 
supports KVO.

-Kevin Ballard

On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution wrote:
> I wanted to follow up to a blog post I wrote about Message Dispatch in
> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
> mentioned some changes to NSObject that didn’t result in any
> objections, so I thought it was time to see what the SE mailing list
> thought.
> 
> I’ve read a few conversations on SE mailing list that have morphed
> into abstract conversations about dynamic vs static dispatch. I want
> to focus specifically on how Swift NSObject subclasses behave.
> 
> I think that there are 2 changes that will result in fewer bugs and
> will not have a substantial impact on performance:
> 
> 
> ## Remove Table Dispatch from NSObject
> 
> NSObject subclasses use table dispatch for the initial class
> declaration block. I think that using message dispatch for NSObject
> subclasses everywhere will result in a much more consistent developer
> experience.
> 
> ## Block NSObject Visibility Optimizations
> 
> Swift upgrades method dispatch to final when the compiler can prove
> that the method is not subclassed. I would like to see Swift be more
> careful about the impact of these optimizations on message dispatch,
> and consider message dispatch non-upgradable.
> 
> 
> I thought it would help to frame this choice as a trade-off between
> Swift’s goals of safe, fast, and expressive.
> 
> ## Safe
> 
> Always using message dispatch for NSObject subclasses will fix a class
> of runtime errors in framework features that are designed around
> message passing (e.g. KVO). Arguments against using dynamic features
> like this are valid, but Cocoa frameworks still use dynamic features
> and the above behaviors result in actual bugs. As a bonus, this will
> resolve SR-584, where a table-dispatched method that is overridden by
> a message dispatch method doesn’t behave correctly.
> 
> ## Fast
> 
> The above changes will result in slower dispatch in NSObject
> subclasses. However, I don't think that these dispatch changes
> actually have a tangible impact on performance. Most NSObject
> subclasses sit on top of a lot of `objc_msgSend`, and if there is a
> specific hot spot, it would still be optimizable via the final
> keyword.
> 
> ## Expressive
> 
> Using table dispatch for NSObject without any source indication or
> library documentation is not very expressive. I think it’s important
> to weigh table dispatch behavior against all of the framework
> documentation and developer experience that assume message dispatch.
> This will also eliminate the need for a lot of `@objc` and `dynamic`
> annotations that are often inconsistently applied depending on if they
> are needed in the scope they are defined in (e.g. class vs extension).
> 
> 
> If this idea shows promise, I’d be glad to formalize a Swift Evolution
> Proposal and explore syntactic details. I think being able to flag a
> class with `dynamic` and applying this flag to `NSObject` may be the
> only syntactic change needed. However, it would be good to debate the
> merit of the behavior change before the syntax.
> 
> 
> Thanks!
> 
> 
> Brian King
> ___
> 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