Re: [swift-evolution] [Proposal] Allow scoped properties from within computed properties

2017-01-14 Thread Xiaodi Wu via swift-evolution
On Sat, Jan 14, 2017 at 9:36 AM, Joseph Newton  wrote:

> Thank you for your responses Xiaodi and David,
>
> I believe you can do this using didSet without the `_bar`:
>> class Foo {
>> public var bar: String? {
>
> didSet {
>> if (bar?.characters.count ?? 0) < 100 {
>> bar = nil
>> }
>> }
>> }
>> }
>
>
> Yes, although this is a perfectly valid way of implementing this, I'm not
> a big fan of implementing this functionality in this way. Particularly, I
> don't like the concept of validating data after setting it, and then
> re-setting the property if the validation failed. I would much rather
> implement it in a manner where it's conditionally set depending on
> validation.
>
> It's an interesting idea, for sure. Because of the persistent storage
>> required for `_bar`, I *think* one way to look at what you're proposing
>> is essentially as a way to allow for a variable to be declared publicly
>> as one type, be implemented as another (anonymous, in this case) type under
>> the hood, and to specify a mechanism for automatically converting between
>> the two types.
>
>
> Essentially, yes. The programmer would have the option of using these
> nested properties to be able to add custom storage or functionality to any
> computed property that they please.
>
> (That said, there is a recurrent theme on this list where people ask for
>> new support for encapsulating members from visibility in ever smaller
>> scopes. I continue to be not in favor of the new `private`, but even
>> allowing its existence, providing all the permutations of
>> type/file/extension visibility is (afaict) and should continue to be (imo)
>> a non-goal. The distinction between public and internal not only avoids
>> pollution in your autocomplete list but also provides important safety
>> wins, and I think those gains are increasingly limited the finer we dice
>> these access levels.)
>
>
> I'm not sure that I quite understand what you mean by this. Would you mind
> elaborating?
>

See below.


>  I get that your proposal allows you to write one fewer declaration in
>> the case of an ad-hoc behavior than SE-0030 would. That is, in the case of
>> SE-0030, you'd have to declare both a behavior and a member that uses it;
>> in your case, you could declare just the member and implement the behavior
>> there. However, I think I'd want to see some concrete use cases that are
>> better served by this proposal than by SE-0030, which is the more general
>> solution as far as I can tell. In the two use cases you've mentioned, one
>> is served by `didSet`, and the other (`synchronized`) is a reusable
>> behavior for which SE-0030 offers the more elegant solution.
>
>
> Here are some additional uses cases for this proposal:
>
> *Implementing Objective-C's "__null_resettable"*
>
> class Foo {
> var bar: UIColor! {
> var _bar: UIColor = .clear
>
> get { _return _bar }
> set { _bar = newValue ?? .clear }
> }
> }
>

In this use case, your proposal differs from what's currently possible only
in that `_bar` (presumably, after you write `private` in front of it, for
consistency with current rules about default access levels) would be
invisible even inside `Foo`. As I wrote to you above, avoiding "pollution"
within ever smaller scopes [in this case, the scope inside `Foo`] is
(AFAICT) and should be (IMO) a non-goal. To convince me that this use case
is worth the engineering effort and complexity of a new syntax, you'd also
have to convince me that having `_bar` visible within the entire scope of
`Foo` has practical and not merely theoretical footgun potential or some
other negative impact beyond the fact that autocomplete will show a member
you'd rather not see.

_Even if_ I were to buy that argument, I think there is a more general
solution that covers your use case. A few months earlier on this list,
several people discussed the possibility of same-module extensions allowing
stored properties, to very positive reception. There are numerous use cases
for that feature, but such a feature would also allow you to isolate `_bar`
and `bar` in its own extension, a common Swift idiom. It would also allow
you to group this implementation in the same extension with arbitrary
functions that need to see `_bar` (such as your `init(_:)` example below)
without exposing `_bar` to other initializer and methods that don't need to
manipulate it. This would be both more flexible and more fine-grained than
possible with your own proposal, and if I were to buy your argument that
`_bar` being visible where it's not needed is suboptimal, this would be the
optimal solution.

*Implementing a stack interface*
>
> class Foo {
> var currentItem: T? {
> var storage = [T]()
>
> get { return storage.last }
> set {
> if let newValue = newValue {
> storage.append(newValue)
> }
> else {
> storage.removeL

Re: [swift-evolution] [Proposal] Allow scoped properties from within computed properties

2017-01-14 Thread Joseph Newton via swift-evolution
Thank you for your responses Xiaodi and David,

I believe you can do this using didSet without the `_bar`:
> class Foo {
> public var bar: String? {

didSet {
> if (bar?.characters.count ?? 0) < 100 {
> bar = nil
> }
> }
> }
> }


Yes, although this is a perfectly valid way of implementing this, I'm not a
big fan of implementing this functionality in this way. Particularly, I
don't like the concept of validating data after setting it, and then
re-setting the property if the validation failed. I would much rather
implement it in a manner where it's conditionally set depending on
validation.

It's an interesting idea, for sure. Because of the persistent storage
> required for `_bar`, I *think* one way to look at what you're proposing
> is essentially as a way to allow for a variable to be declared publicly
> as one type, be implemented as another (anonymous, in this case) type under
> the hood, and to specify a mechanism for automatically converting between
> the two types.


Essentially, yes. The programmer would have the option of using these
nested properties to be able to add custom storage or functionality to any
computed property that they please.

(That said, there is a recurrent theme on this list where people ask for
> new support for encapsulating members from visibility in ever smaller
> scopes. I continue to be not in favor of the new `private`, but even
> allowing its existence, providing all the permutations of
> type/file/extension visibility is (afaict) and should continue to be (imo)
> a non-goal. The distinction between public and internal not only avoids
> pollution in your autocomplete list but also provides important safety
> wins, and I think those gains are increasingly limited the finer we dice
> these access levels.)


I'm not sure that I quite understand what you mean by this. Would you mind
elaborating?

 I get that your proposal allows you to write one fewer declaration in the
> case of an ad-hoc behavior than SE-0030 would. That is, in the case of
> SE-0030, you'd have to declare both a behavior and a member that uses it;
> in your case, you could declare just the member and implement the behavior
> there. However, I think I'd want to see some concrete use cases that are
> better served by this proposal than by SE-0030, which is the more general
> solution as far as I can tell. In the two use cases you've mentioned, one
> is served by `didSet`, and the other (`synchronized`) is a reusable
> behavior for which SE-0030 offers the more elegant solution.


Here are some additional uses cases for this proposal:

*Implementing Objective-C's "__null_resettable"*

class Foo {
var bar: UIColor! {
var _bar: UIColor = .clear

get { _return _bar }
set { _bar = newValue ?? .clear }
}
}

*Implementing a stack interface*

class Foo {
var currentItem: T? {
var storage = [T]()

get { return storage.last }
set {
if let newValue = newValue {
storage.append(newValue)
}
else {
storage.removeLast()
}
}
}
}

*Validation before changing (for performance)*

class SessionManager {
var session: Session {
var _session: Session

get { return _session }
set {
if newValue != _session {
// expensive teardown code for the old session

_session = newValue

// expensive setup code for the new session
}
}
}
}

Lastly, I've been doing some additional thinking and I think that it would
be beneficial to also setting values for these nested properties inside of
*init* methods. For example, I work with C APIs a great deal and create
Swift/ObjC wrappers for them a lot, I have a case where I provide an
implementation as follows:

class Wrapper {
private var _unmanaged: UnsafePointer
var text: String {
return String(cString: _unmanaged)
}

fileprivate init(_ unmanaged: UnsafePointer) {
_unamanged = unmanaged
}
}

It's implemented in this manner because the C APIs may change the
characters pointed to by *_unmanaged* before the *text* property is
accessed. With this proposal, this code could be implemented as follows:

class Wrapper {
var text: String {
private var unmanaged: UnsafePointer

get {
return String(cString: unmanaged)
}
}

fileprivate init(_ unmanaged: UnsafePointer) {
self.text.unmanaged = unmanaged
}
}

On Fri, Jan 13, 2017 at 4:01 PM, Xiaodi Wu  wrote:

> (Forward to the list if your early replied was intended to be sent there.)
>
>
> On Fri, Jan 13, 2017 at 1:58 PM, Joseph Newton  wrote:
>
>> I believe that you're referring to SE-0030 Property Behaviors
>> ,
>> correct?
>>
>> I have indeed read over this propos

Re: [swift-evolution] [Proposal] Allow scoped properties from within computed properties

2017-01-13 Thread David Sweeris via swift-evolution

> On Jan 13, 2017, at 11:27, Joseph Newton via swift-evolution 
>  wrote:
> 
> Hi,
> 
> I've done a lot of Objective-C and have been been a fan of Swift since it's 
> come out, however, there's a small feature of Objective-C that I would really 
> like to see implemented in Swift:
> 
> In Objective-C you have a few options implementation-wise when creating 
> properties for your class. You could use the @synthesize statement to have 
> the compiler create the backing ivar along with the appropriate accessor 
> methods or your could use the @dynamic statement to tell the compiler that 
> you're going to create your own accessor methods and backing ivar (if needed).
> 
> Additionally, one could use the @synthesize statement to have the compiler 
> create the backing ivar, and then they could create custom accessor methods 
> to supply custom functionality or validation. I use this third case 
> extensively in my Objecitve-C code but there's not a concise way of doing 
> this in Swift.
> 
> For example, I might have an Objective-C implementation that looks like this:
> 
> @interface Foo : NSObject
> @property (nullable, copy) NSString *bar;
> @end
> 
> @implementation Foo
> @synthesize bar = _bar; // Creates ivar '_bar'
> 
> - (void)setBar:(NSString *)bar {
> if (bar.length < 100)
> _bar = nil;
> else
> _bar = [bar copy];
> }
> 
> @end
> 
> Currently, the only way to implement this in Swift - AFAIK - is as follows:
> 
> class Foo {
> private var _bar: String?
> public var bar: String? {
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
> 
> Although this works, it isn't exactly glamorous. The main drawback of this 
> implementation (unless intended) is that you now have any additional '_bar' 
> variable accessible within the scope of your class. 

I believe you can do this using didSet without the `_bar`:
class Foo {
public var bar: String? {
didSet {
if (bar?.characters.count ?? 0) < 100 {
bar = nil
}
}
}
}


> My proposal is to allow stored properties in the declaration block of 
> computed properties. For this example, the '_bar' declaration would simply be 
> moved inside of the declaration block for 'bar':
> 
> class Foo {
> public var bar: String? {
> var _bar: String?
> 
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
> 
> Only the getter and setter methods of 'bar' are allowed to access and modify 
> the stored '_bar' property. My proposal would also allow for multiple stored 
> properties of varying types within the scope of a single computed property. 
> This would also simply atomic synchronization for single variables:
> 
> class Foo {
> static var synchronizedBar: String? {
> var queue = DispatchQueue(label: "Foo.synchronizedBar")
> var bar: String?
> 
> get { return queue.sync { return bar } }
> set { queue.sync { bar = newValue } }
> }
> }
> 
> Are there any suggestions or arguments, for or against, for this proposal?

It's an interesting idea, for sure. Because of the persistent storage required 
for `_bar`, I think one way to look at what you're proposing is essentially as 
a way to allow for a variable to be declared publicly as one type, be 
implemented as another (anonymous, in this case) type under the hood, and to 
specify a mechanism for automatically converting between the two types.

- Dave Sweeris

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


Re: [swift-evolution] [Proposal] Allow scoped properties from within computed properties

2017-01-13 Thread Xiaodi Wu via swift-evolution
There was a proposal for custom behaviors using `@`, which if I recall
would offer encapsulation along the lines of what you're proposing. It was
an extensively designed system which was deferred for consideration, but
which would be in scope again in phase 2. The proposal is in the
swift-evolution repository--does that address your use case?
On Fri, Jan 13, 2017 at 11:27 Joseph Newton via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi,
>
> I've done a lot of Objective-C and have been been a fan of Swift since
> it's come out, however, there's a small feature of Objective-C that I would
> really like to see implemented in Swift:
>
> In Objective-C you have a few options implementation-wise when creating
> properties for your class. You could use the *@synthesize *statement to
> have the compiler create the backing ivar along with the appropriate
> accessor methods or your could use the *@dynamic* statement to tell the
> compiler that you're going to create your own accessor methods and backing
> ivar (if needed).
>
> Additionally, one could use the *@synthesize* statement to have the
> compiler create the backing ivar, and then they could create custom
> accessor methods to supply custom functionality or validation. I use this
> third case extensively in my Objecitve-C code but there's not a concise way
> of doing this in Swift.
>
> For example, I might have an Objective-C implementation that looks like
> this:
>
> @interface Foo : NSObject
> @property (nullable, copy) NSString *bar;
> @end
>
> @implementation Foo
> @synthesize bar = _bar; // Creates ivar '_bar'
>
> - (void)setBar:(NSString *)bar {
> if (bar.length < 100)
> _bar = nil;
> else
> _bar = [bar copy];
> }
>
> @end
>
> Currently, the only way to implement this in Swift - AFAIK - is as follows:
>
> class Foo {
> private var _bar: String?
> public var bar: String? {
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Although this works, it isn't exactly glamorous. The main drawback of this
> implementation (unless intended) is that you now have any additional '_bar'
> variable accessible within the scope of your class.
>
> My proposal is to allow stored properties in the declaration block of
> computed properties. For this example, the '_bar' declaration would simply
> be moved inside of the declaration block for 'bar':
>
> class Foo {
> public var bar: String? {
> var _bar: String?
>
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Only the getter and setter methods of 'bar' are allowed to access and
> modify the stored '_bar' property. My proposal would also allow for
> multiple stored properties of varying types within the scope of a single
> computed property. This would also simply atomic synchronization for single
> variables:
>
> class Foo {
> static var synchronizedBar: String? {
> var queue = DispatchQueue(label: "Foo.synchronizedBar")
> var bar: String?
>
> get { return queue.sync { return bar } }
> set { queue.sync { bar = newValue } }
> }
> }
>
> Are there any suggestions or arguments, for or against, for this proposal?
>
> -- Joe Newton
> ___
> 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] [Proposal] Allow scoped properties from within computed properties

2017-01-13 Thread Joseph Newton via swift-evolution
Hi,

I've done a lot of Objective-C and have been been a fan of Swift since it's
come out, however, there's a small feature of Objective-C that I would
really like to see implemented in Swift:

In Objective-C you have a few options implementation-wise when creating
properties for your class. You could use the *@synthesize *statement to
have the compiler create the backing ivar along with the appropriate
accessor methods or your could use the *@dynamic* statement to tell the
compiler that you're going to create your own accessor methods and backing
ivar (if needed).

Additionally, one could use the *@synthesize* statement to have the
compiler create the backing ivar, and then they could create custom
accessor methods to supply custom functionality or validation. I use this
third case extensively in my Objecitve-C code but there's not a concise way
of doing this in Swift.

For example, I might have an Objective-C implementation that looks like
this:

@interface Foo : NSObject
@property (nullable, copy) NSString *bar;
@end

@implementation Foo
@synthesize bar = _bar; // Creates ivar '_bar'

- (void)setBar:(NSString *)bar {
if (bar.length < 100)
_bar = nil;
else
_bar = [bar copy];
}

@end

Currently, the only way to implement this in Swift - AFAIK - is as follows:

class Foo {
private var _bar: String?
public var bar: String? {
get { return _bar }
set {
if (newValue?.characters.count ?? 0) < 100 {
_bar = nil
}
else {
_bar = newValue.copy() as! String
}
}
}
}

Although this works, it isn't exactly glamorous. The main drawback of this
implementation (unless intended) is that you now have any additional '_bar'
variable accessible within the scope of your class.

My proposal is to allow stored properties in the declaration block of
computed properties. For this example, the '_bar' declaration would simply
be moved inside of the declaration block for 'bar':

class Foo {
public var bar: String? {
var _bar: String?

get { return _bar }
set {
if (newValue?.characters.count ?? 0) < 100 {
_bar = nil
}
else {
_bar = newValue.copy() as! String
}
}
}
}

Only the getter and setter methods of 'bar' are allowed to access and
modify the stored '_bar' property. My proposal would also allow for
multiple stored properties of varying types within the scope of a single
computed property. This would also simply atomic synchronization for single
variables:

class Foo {
static var synchronizedBar: String? {
var queue = DispatchQueue(label: "Foo.synchronizedBar")
var bar: String?

get { return queue.sync { return bar } }
set { queue.sync { bar = newValue } }
}
}

Are there any suggestions or arguments, for or against, for this proposal?

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