Re: [swift-evolution] Proposal: Expose getter/setters in the same way as regular methods

2015-12-27 Thread Charles Srstka via swift-evolution
> On Dec 27, 2015, at 4:23 AM, Tino Heth <2...@gmx.de> wrote:
> 
>> 
>> Of course, if you’re worried about the performance costs associated with 
>> that extra method call, you might want to include a keyword, such as 
>> “observable”, and only generate the method call(s) if that keyword is on the 
>> property.
> I strongly agree that Swift should have/keep a possibility to create 
> properties with no performance penalty — but I guess comfort is more 
> important, so I'd rather make observable the default and offer a possibility 
> to disable it.
> 
> Tino

The problem, as I see it, is that KVO is not useful unless the author has 
specifically thought about it, and if “observable” is not the default, but 
something that the author of the class had to add, this demonstrates that the 
author *has* considered KVO compliance for the property.  Without some way to 
know that the property has deliberately been made KVO compliant, code that 
observes the property cannot be reliable. Therefore, I’d suggest *not* making 
observable the default, as it ultimately makes KVO a lot more useful.

Example:

class MyObject {
var foo: Int { get } // This is a computed property, possibly dependent 
on something else. Can I safely observe it and expect it to work?

var bar: Int   // This is a stored property—but do I know it 
won’t be changed to a computed property in the future? Can I observe this and 
trust my code won’t break in version 2.0?
}

vs.

class MyObject {
observable var foo: Int { get } // YES I can safely observe this.

observable var bar // YES I can safely observe this.
}

Observing things that aren’t observable is fraught with peril (in the current 
Objective-C implementation, it can often lead to crashes via exceptions being 
thrown). Knowing that it’s safe is valuable—I’d even say essential. Currently 
you have to look in the documentation, which as we all know isn’t always 
complete or up to date. Having the keyword there shows, right in the interface, 
that the author has committed to making this property compliant and keeping it 
that way in future releases.

The observable keyword could also allow one to set the KVO key string to 
something other than just the name of the property:

class MyObject {
observable(somethingElse) var something: Int
}

You’d also need an annotation to tell the system which other key paths the 
property is dependent upon, which I’d probably do something like this:

class MyObject {
observable var foo: Int
observable var bar: Int {
get { return self.foo }
set(bar) { self.foo = bar }
depends { return [“foo”] }
}
}

The compiler could automatically add a CollectionType property to the class 
corresponding to each property, and then rewrite the property setter something 
like this (pseudocode):

class MyObject {
private var observersOfFoo: [ObserverProtocol]?

observable var foo: Int {
set(newValue) {
let oldValue = _foo

_foo = newValue // or whatever the default setter 
usually does

self.observersOfFoo?.forEach { 
$0.notifyKeyValueChanged(self, key: “foo”, oldValue: oldValue) }
}
}
}

I made it optional so that for the common case where there aren’t actually any 
observers on the property, the only performance costs are the store of the old 
value and checking an optional. Since optionals are basically enums, which are 
represented as an 8-bit integer which in this case can have the values 0 or 1, 
I’d expect checking an optional to have similar performance characteristics to 
checking a boolean, and thus I’d expect it to perform better than checking 
whether an array is empty, and doing some quick tests seems to back that up.

Charles

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


Re: [swift-evolution] Proposal: Expose getter/setters in the same way as regular methods

2015-12-27 Thread Tino Heth via swift-evolution

> Of course, if you’re worried about the performance costs associated with that 
> extra method call, you might want to include a keyword, such as “observable”, 
> and only generate the method call(s) if that keyword is on the property.
I strongly agree that Swift should have/keep a possibility to create properties 
with no performance penalty — but I guess comfort is more important, so I'd 
rather make observable the default and offer a possibility to disable it.

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


Re: [swift-evolution] Proposal: Expose getter/setters in the same way as regular methods

2015-12-27 Thread Charles Srstka via swift-evolution
> On Dec 13, 2015, at 6:49 PM, Marc Knaup via swift-evolution 
>  wrote:
> 
> Also it's unlikely that all mutable properties will support observation 
> automatically. That would require the optimizer to keep using dynamic 
> dispatch for all of them which will hurt performance.

Not really. All that’s required for Objective-C KVO to work for a stored 
property is for the willChangeValueForKey() and didChangeValueForKey() methods 
to be called before and after the value is set. If you put those calls in 
willSet and didSet for a Swift stored property, you can get KVO compliance with 
no dynamic dispatch at all. The reason Objective-C typically requires dynamic 
dispatch for this is because KVO is purely a framework-level feature, and is 
not built into the library, so the framework code has to rewrite your class to 
add the needed methods. If you built a KVO-like system right into the language, 
the notification methods could be added right at compile time, and it’d work 
fine. Of course, if I were redesigning KVO, I’d probably eliminate 
willChangeValueForKey() and just include the old value as a parameter to 
didChangeValueForKey(), since if there’s only one method to call, you can set 
the property on a secondary thread, and then just call the observation method 
asynchronously on the main thread, which will avoid tying up the worker thread 
waiting for UI updates that result from the KVO update.

Of course, if you’re worried about the performance costs associated with that 
extra method call, you might want to include a keyword, such as “observable”, 
and only generate the method call(s) if that keyword is on the property. This 
would probably be a good thing *anyway*, since one of the weaknesses of the 
current KVO implementation is that there’s no way to know whether a property is 
KVO observable or not without reading the documentation for that method, since 
computed properties need to state their dependencies in order to property 
support KVO, and whether this has been done is not reflected in the interface 
at all.

Charles

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


Re: [swift-evolution] Proposal: Expose getter/setters in the same way as regular methods

2015-12-26 Thread Douglas Gregor via swift-evolution
FYI, I just sent a proposal draft titled “Generalized Naming for Any Function” 
that pulls these ideas together more formally. I went with a different syntax 
that I’d been kicking around for a while internally, and I’d love to hear 
everyone’s thoughts on this.

- Doug

> On Dec 14, 2015, at 12:25 AM, Pierre Monod-Broca via swift-evolution 
>  wrote:
> 
> +1
> 
> I like the #get, #set suffixes.
> 
> I’m afraid the following would be a bit ambiguous
>>  - example.init(argument:Int, another:String)
>>  - example.subscript(index:Int)
> 
> Maybe with ‘#’ too
>  - example.init#argument:Int#another:String
>  - example.init#argument#another
>  - example.init#(argument:Int, another:String)
>  - example.subscript#index:Int
>  - example.subscript#Int
> 
> Pierre
> 
>> Le 14 déc. 2015 à 08:57, ilya via swift-evolution > > a écrit :
>> 
>> > Being able to refer to getters and setters is a good idea and aligns with 
>> > being able to refer to initializers and methods.
>> > I would also add subscripts to the list if possible.
>> 
>> Great idea! Let's discuss syntax
>> 
>> How about 
>>  - example.get.member
>>  - example.set.member
>>  - example.init(argument:Int, another:String)
>>  - example.subscript(index:Int)
>> 
>> 
>> On Mon, Dec 14, 2015 at 3:49 AM, Marc Knaup via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> Wait, where is stated that KVO is a long-term goal for Swift? I might have 
>> missed that.
>> 
>> I find that one of Objective-C's most annoying features. It makes it really 
>> difficult to reason about code when things can happen unexpectedly left and 
>> right. It's the same issue with aspect-oriented programming.
>> 
>> I prefer explicit integration points like closures, delegates and alike.
>> Most times I used KVO in the past was to work around bugs or annoyances on 
>> iOS, like for example forcing a button stay enabled even when iOS disables 
>> it.
>> 
>> Also it's unlikely that all mutable properties will support observation 
>> automatically. That would require the optimizer to keep using dynamic 
>> dispatch for all of them which will hurt performance.
>> 
>> 
>> But I'm getting off-topic since your discussion is not about KVO nor about 
>> KVC.
>> 
>> Being able to refer to getters and setters is a good idea and aligns with 
>> being able to refer to initializers and methods.
>> I would also add subscripts to the list if possible.
>> 
>> On Mon, Dec 14, 2015 at 1:34 AM, Michael Henson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> Swift-like full KVO/KVC as in Objective-C is a stated long-term goal for 
>> Swift's evolution. The 90% solution might be more straightforward:
>> 
>> class Example {
>>   var member: String
>> 
>>   func print() {
>> print(self.member)
>>   }
>> }
>> 
>> var example = Example(member: "Hi!")
>> 
>> var example_print_method = example.print
>> example_print_method()
>> result:
>> Hi!
>> 
>> If there were a mechanism for referring to the getter and setter methods on 
>> the var member property as the same kind of self-capturing closures, it 
>> could make simple cases of data binding easier to implement:
>> 
>> var serializeFields = [
>>   "member": example.member#get,
>> ]
>> 
>> var deserializeFields = [
>>   "member": example.member#set,
>> ]
>> 
>> var broadcastValueTo = [
>>   "memberValues": [
>>  example.member#set,
>>  example2.member#set,
>>  example3.member#set,
>>   ]
>> ]
>> 
>> viewController.textField.onValueChanged(example.member#set)
>> 
>> Etc.
>> 
>> The "#" notation is just a placeholder for "whatever mechanism is decided 
>> upon", though it does seem to be available and using it postfix makes a 
>> first-glance sense to me in terms of the semantics of expressions.
>> 
>> Mike
>>  
>> ___
>> 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 
>> 
>> 
>> 
>>  ___
>> 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 
> 
___
swift-evolution mailing list
swift-evolution@s

Re: [swift-evolution] Proposal: Expose getter/setters in the same way as regular methods

2015-12-18 Thread Michael Henson via swift-evolution
Another option for handling this occurred to me - an "export list" in the
lexical block that usually declares getters, setters, and will/didSet:

class Thing {
  var property: String {
[get, set]
  }
}

It's somewhat like a "capture list" syntax but in the context of the
accessor declarations. The function is that it explicitly declares which of
the methods should be exposed to the outside world - much like the
auto-generated methods for properties in Objective-C. There would be a
defined naming scheme for generated methods, perhaps a way to override the
default name for special cases, etc. The generated/exported funcs are then
just like every other func declared on the type.

Is there a strong inclination on the internal team to add features like
this only if they can apply as broadly as possible, all at once?

Mike


> This is something I'm looking into. Providing the getter is valuable, but
> setters are not usually very useful by themselves. With value types, you
> need the full property interface to be able to drill further down into the
> value and update part of the value, since you potentially need recursive
> writeback. Furthermore, the get/set protocol is inefficient for
> copy-on-write types, since it forces a temporary copy when doing partial
> updates; Swift's property model provides a third implicit
> "materializeForSet" accessor that preserves in-place update when going
> through abstractions such as overrideable class properties, properties in
> generics, or properties across resilience boundaries. There are even more
> shenanigans we're planning to make mutations through array slices and the
> like efficient too. To that end, I think the two things you want of a
> property are:
> - its getter, since read-only access is definitely useful for things like
> `map`, and
> - what i'll call its "lens", notionally a function T -> inout U, which
> captures the full property interface. You can apply the function in mutable
> contexts without sacrificing efficiency or composability, and derive the
> getter/setter functions fairly straightforwardly.


On Wed, Dec 16, 2015 at 6:59 PM, Joe Groff  wrote:

> This is something I'm looking into. Providing the getter is valuable, but
> setters are not usually very useful by themselves. With value types, you
> need the full property interface to be able to drill further down into the
> value and update part of the value, since you potentially need recursive
> writeback. Furthermore, the get/set protocol is inefficient for
> copy-on-write types, since it forces a temporary copy when doing partial
> updates; Swift's property model provides a third implicit
> "materializeForSet" accessor that preserves in-place update when going
> through abstractions such as overrideable class properties, properties in
> generics, or properties across resilience boundaries. There are even more
> shenanigans we're planning to make mutations through array slices and the
> like efficient too. To that end, I think the two things you want of a
> property are:
>
> - its getter, since read-only access is definitely useful for things like
> `map`, and
> - what i'll call its "lens", notionally a function T -> inout U, which
> captures the full property interface. You can apply the function in mutable
> contexts without sacrificing efficiency or composability, and derive the
> getter/setter functions fairly straightforwardly.
>
> -Joe
>
> On Dec 13, 2015, at 4:34 PM, Michael Henson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Swift-like full KVO/KVC as in Objective-C is a stated long-term goal for
> Swift's evolution. The 90% solution might be more straightforward:
>
> class Example {
>   var member: String
>
>   func print() {
> print(self.member)
>   }
> }
>
> var example = Example(member: "Hi!")
>
> var example_print_method = example.print
> example_print_method()
> result:
> Hi!
>
> If there were a mechanism for referring to the getter and setter methods
> on the var member property as the same kind of self-capturing closures, it
> could make simple cases of data binding easier to implement:
>
> var serializeFields = [
>   "member": example.member#get,
> ]
>
> var deserializeFields = [
>   "member": example.member#set,
> ]
>
> var broadcastValueTo = [
>   "memberValues": [
>  example.member#set,
>  example2.member#set,
>  example3.member#set,
>   ]
> ]
>
> viewController.textField.onValueChanged(example.member#set)
>
> Etc.
>
> The "#" notation is just a placeholder for "whatever mechanism is decided
> upon", though it does seem to be available and using it postfix makes a
> first-glance sense to me in terms of the semantics of expressions.
>
> Mike
> ___
> 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/ma