[Returned for revision] SE-0089: Renaming String.init<T>(_: T)


(Chris Lattner) #1

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0089-rename-string-reflection-init.md

The review of "SE-0089: Renaming String.init<T>(_: T)" ran from May 17…23, 2016. The proposal has been *returned for revision* and another round of discussion - the core team would love to see the revised proposal make it into Swift 3.

The community and core team both want to remove this “footgun” from the standard library, where someone could write "String(x)” with the intention of getting a value-preserving conversion to String, but may instead get a potentially lossy and potentially expensive reflection-based conversion to a String. After extensive discussion, the core team recommends that the community consider a somewhat more elaborate design:

- Rename the existing reflection-based "String.init<T>(_: T)” initializer to "String.init<T>(describing: T)” as recommend by the community. This initializer would rarely be invoked in user code directly.

- Introduce a new protocol (for sake of discussion, call it “ValuePreservingStringConvertible") that refines CustomStringConvertible but that adds no new requirements. Conformance to this protocol indicates that the “description” requirement produces a value-preserving representation in String form.

- Introduce a new unlabeled initializer on String: "init<T: ValuePreservingStringConvertible>(_ v: T) { return v.description }". This permits the “String(x)” syntax to be used on all values of types that can be converted to string in a value-preserving way.

- Audit important standard library types (e.g. the integer and floating point types), and make them explicitly conform to ValuePreservingStringConvertible with an explicitly implemented “description” property.

- As a performance optimization, change the implementation of the string literal interpolation syntax to prefer the unlabeled initializer when interpolating a type that is ValuePreservingStringConvertible or that has otherwise has an unlabeled String initializer, but use the "String.init<T>(describing: T)” initializer if not.

The expected advantages of this design are:

- Swift encourages the T(x) syntax for value preserving conversions, and this design ensures that String(x) continues to work for the value preserving cases.

- This ensures that the String(x) syntax does not accidentally fall off a performance cliff by using the extremely-dynamic reflection mechanism unintentionally.

- The preferred “I don’t care how you do it, just convert this value to a string somehow” syntax remains string interpolation syntax. This syntax is efficient in the cases where the String(x) syntax is allowed, but fully general to the other cases where custom convert-to-string code has not been provided.

Some remaining open questions:

- Exactly what types should conform to ValuePreservingStringConvertible. It seems clear that integer, floating point types, and Character can and should conform. What other types should?

- Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough? We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

Thank you to Austin Zheng for driving this proposal forward!

-Chris Lattner
Review Manager


(Brent Royal-Gordon) #2

- Rename the existing reflection-based "String.init<T>(_: T)” initializer to "String.init<T>(describing: T)” as recommend by the community. This initializer would rarely be invoked in user code directly.

Yes.

- Introduce a new protocol (for sake of discussion, call it “ValuePreservingStringConvertible") that refines CustomStringConvertible but that adds no new requirements. Conformance to this protocol indicates that the “description” requirement produces a value-preserving representation in String form.

Yes!

- Introduce a new unlabeled initializer on String: "init<T: ValuePreservingStringConvertible>(_ v: T) { return v.description }". This permits the “String(x)” syntax to be used on all values of types that can be converted to string in a value-preserving way.

YES!

- Audit important standard library types (e.g. the integer and floating point types), and make them explicitly conform to ValuePreservingStringConvertible with an explicitly implemented “description” property.

HELL YES!

- As a performance optimization, change the implementation of the string literal interpolation syntax to prefer the unlabeled initializer when interpolating a type that is ValuePreservingStringConvertible or that has otherwise has an unlabeled String initializer, but use the "String.init<T>(describing: T)” initializer if not.

...huh. Well, if you insist.

(I would favor a design which somehow differentiated between strings intended for debugging or logging, which would permit any interpolation, and strings intended for paths, user display, and other such purposes, which would only permit ValuePreservingStringConvertible interpolations. But short of introducing a separate DebugString type, I'm not sure how we might actually accomplish that.)

···

--
Brent Royal-Gordon
Architechies


(Patrick Smith) #3

These are some great points. I like the sound of ValuePreservingStringConvertible. A few questions to add:

- If its conformers produce a value-preserving representation, would it make sense for it to also have an initializer accepting the value? What specifically makes it value preserving otherwise?

- What is the difference between CustomStringConvertible and CustomDebugStringConvertible? Are most implementations of description and debugDescription identical? It says CustomStringConvertible is for writing to an output stream. Is a ‘value preserving string’ going to be a better fit for that all the time?

- To the question of ‘is CustomStringConvertible enough?’, what about replacing it with ValuePreservingStringConvertible? Then there are two very distinct protocols: ValuePreservingStringConvertible and CustomDebugStringConvertible, one obviously safely value preserving and one obviously just for inspecting.

- Could `.description` be renamed to something more specific and clear? For example, `preservedValue` or `.valuePreservingDescription`. If the recommended way is to use `init<T: ValuePreservingStringConvertible>(_ v: T)`, will anybody be using `.description` directly anyway? I always found NSObject’s seize of the ‘description’ property annoying, as on models it’s a perfect valid property to want as a member, so I was a little disappointed to see it in Swift too. If there’s an alternative, more clear name for this property then it won’t clash with anything else.

I like this clear separation of ‘value preserving’ and ‘just show me something’ representations.

Patrick

···

On 26 May 2016, at 3:08 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0089-rename-string-reflection-init.md

The review of "SE-0089: Renaming String.init<T>(_: T)" ran from May 17…23, 2016. The proposal has been *returned for revision* and another round of discussion - the core team would love to see the revised proposal make it into Swift 3.

The community and core team both want to remove this “footgun” from the standard library, where someone could write "String(x)” with the intention of getting a value-preserving conversion to String, but may instead get a potentially lossy and potentially expensive reflection-based conversion to a String. After extensive discussion, the core team recommends that the community consider a somewhat more elaborate design:

- Rename the existing reflection-based "String.init<T>(_: T)” initializer to "String.init<T>(describing: T)” as recommend by the community. This initializer would rarely be invoked in user code directly.

- Introduce a new protocol (for sake of discussion, call it “ValuePreservingStringConvertible") that refines CustomStringConvertible but that adds no new requirements. Conformance to this protocol indicates that the “description” requirement produces a value-preserving representation in String form.

- Introduce a new unlabeled initializer on String: "init<T: ValuePreservingStringConvertible>(_ v: T) { return v.description }". This permits the “String(x)” syntax to be used on all values of types that can be converted to string in a value-preserving way.

- Audit important standard library types (e.g. the integer and floating point types), and make them explicitly conform to ValuePreservingStringConvertible with an explicitly implemented “description” property.

- As a performance optimization, change the implementation of the string literal interpolation syntax to prefer the unlabeled initializer when interpolating a type that is ValuePreservingStringConvertible or that has otherwise has an unlabeled String initializer, but use the "String.init<T>(describing: T)” initializer if not.

The expected advantages of this design are:

- Swift encourages the T(x) syntax for value preserving conversions, and this design ensures that String(x) continues to work for the value preserving cases.

- This ensures that the String(x) syntax does not accidentally fall off a performance cliff by using the extremely-dynamic reflection mechanism unintentionally.

- The preferred “I don’t care how you do it, just convert this value to a string somehow” syntax remains string interpolation syntax. This syntax is efficient in the cases where the String(x) syntax is allowed, but fully general to the other cases where custom convert-to-string code has not been provided.

Some remaining open questions:

- Exactly what types should conform to ValuePreservingStringConvertible. It seems clear that integer, floating point types, and Character can and should conform. What other types should?

- Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough? We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

Thank you to Austin Zheng for driving this proposal forward!

-Chris Lattner
Review Manager

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


(Austin Zheng) #4

I think this is an incredible idea.

Should we eventually prepare an updated proposal? Given the need for further discussion I'd be happy to drive it forward, or if someone else wants they can take over too.

(inline)

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0089-rename-string-reflection-init.md

The review of "SE-0089: Renaming String.init<T>(_: T)" ran from May 17…23, 2016. The proposal has been *returned for revision* and another round of discussion - the core team would love to see the revised proposal make it into Swift 3.

The community and core team both want to remove this “footgun” from the standard library, where someone could write "String(x)” with the intention of getting a value-preserving conversion to String, but may instead get a potentially lossy and potentially expensive reflection-based conversion to a String. After extensive discussion, the core team recommends that the community consider a somewhat more elaborate design:

- Rename the existing reflection-based "String.init<T>(_: T)” initializer to "String.init<T>(describing: T)” as recommend by the community. This initializer would rarely be invoked in user code directly.

- Introduce a new protocol (for sake of discussion, call it “ValuePreservingStringConvertible") that refines CustomStringConvertible but that adds no new requirements. Conformance to this protocol indicates that the “description” requirement produces a value-preserving representation in String form.

- Introduce a new unlabeled initializer on String: "init<T: ValuePreservingStringConvertible>(_ v: T) { return v.description }". This permits the “String(x)” syntax to be used on all values of types that can be converted to string in a value-preserving way.

- Audit important standard library types (e.g. the integer and floating point types), and make them explicitly conform to ValuePreservingStringConvertible with an explicitly implemented “description” property.

Yes to all of this, as others have already said.

- As a performance optimization, change the implementation of the string literal interpolation syntax to prefer the unlabeled initializer when interpolating a type that is ValuePreservingStringConvertible or that has otherwise has an unlabeled String initializer, but use the "String.init<T>(describing: T)” initializer if not.

The expected advantages of this design are:

- Swift encourages the T(x) syntax for value preserving conversions, and this design ensures that String(x) continues to work for the value preserving cases.

Yes. I think doing a little more work to keep this convention is worthwhile.

- This ensures that the String(x) syntax does not accidentally fall off a performance cliff by using the extremely-dynamic reflection mechanism unintentionally.

- The preferred “I don’t care how you do it, just convert this value to a string somehow” syntax remains string interpolation syntax. This syntax is efficient in the cases where the String(x) syntax is allowed, but fully general to the other cases where custom convert-to-string code has not been provided.

Some remaining open questions:

- Exactly what types should conform to ValuePreservingStringConvertible. It seems clear that integer, floating point types, and Character can and should conform. What other types should?

Like Brent mentioned, there are some types that are natural candidates, including Foundation types whose conformance could go into the overlays. NSURL, NSUUID, NSIndexPath. NSData is a borderline candidate, and probably not a good fit in the end (what encoding to use? what happens if you get the .description of a 100 MB NSData? etc). Same with NSDate. Maybe some of the CGStructs, although maybe the fact that CGFloat differs between platforms will sink that idea.

Any of the NSObject subclass candidates may require their `description`s to be altered to meet the semantics, which may or may not be an acceptable breaking change.

- Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough? We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

This is a good question.

Since a ValuePreservingStringConvertible is, by definition, a type that can be represented as a string in a lossless and unambiguous manner, would it be worth requiring a reverse conversion in the form of a failable initializer taking a string? Some of the proposed ValuePreservingStringConvertible types already have such functionality today. It would give the protocol a little more of a reason to exist, as well as encouraging proper conformance.

Today, `description` is definitely used for both lossless and lossy string representations, and that's probably not going to change in the future.

···

On May 25, 2016, at 10:08 PM, Chris Lattner <clattner@apple.com> wrote:

Thank you to Austin Zheng for driving this proposal forward!

-Chris Lattner
Review Manager

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


(plx) #5

I like the design strategy, but I’m having a hard time seeing the value of `ValuePreservingStringConvertible`; it’d be easier to evaluate the need for it with some concrete examples of types with `description` implementations that:

- aren’t value-preserving
- would cause problems if mistakenly-classified as value-preserving

Relatedly, here are some concrete `description`/`debugDescription` pairs; would these `description`s be value-preserving or not?

- a `Wavelength` type
- description: “650.0 nm”
- debugDescription: “Wavelength(nanometers: 650.0)”

- an `Angle` type:
  - description: “90.0°”
  - debugDescription: “Angle(πUnits: 0.5)”

…(note that neither type has a corresponding `init?(_ string: String)` implementation, and I don’t plan to add one either).

I’m just having trouble coming up with realistic non-value-preserving descriptions that’d be *problematic* (as opposed to just, say, unhelpful).

···

On May 26, 2016, at 12:08 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0089-rename-string-reflection-init.md

The review of "SE-0089: Renaming String.init<T>(_: T)" ran from May 17…23, 2016. The proposal has been *returned for revision* and another round of discussion - the core team would love to see the revised proposal make it into Swift 3.

The community and core team both want to remove this “footgun” from the standard library, where someone could write "String(x)” with the intention of getting a value-preserving conversion to String, but may instead get a potentially lossy and potentially expensive reflection-based conversion to a String. After extensive discussion, the core team recommends that the community consider a somewhat more elaborate design:

- Rename the existing reflection-based "String.init<T>(_: T)” initializer to "String.init<T>(describing: T)” as recommend by the community. This initializer would rarely be invoked in user code directly.

- Introduce a new protocol (for sake of discussion, call it “ValuePreservingStringConvertible") that refines CustomStringConvertible but that adds no new requirements. Conformance to this protocol indicates that the “description” requirement produces a value-preserving representation in String form.

- Introduce a new unlabeled initializer on String: "init<T: ValuePreservingStringConvertible>(_ v: T) { return v.description }". This permits the “String(x)” syntax to be used on all values of types that can be converted to string in a value-preserving way.

- Audit important standard library types (e.g. the integer and floating point types), and make them explicitly conform to ValuePreservingStringConvertible with an explicitly implemented “description” property.

- As a performance optimization, change the implementation of the string literal interpolation syntax to prefer the unlabeled initializer when interpolating a type that is ValuePreservingStringConvertible or that has otherwise has an unlabeled String initializer, but use the "String.init<T>(describing: T)” initializer if not.

The expected advantages of this design are:

- Swift encourages the T(x) syntax for value preserving conversions, and this design ensures that String(x) continues to work for the value preserving cases.

- This ensures that the String(x) syntax does not accidentally fall off a performance cliff by using the extremely-dynamic reflection mechanism unintentionally.

- The preferred “I don’t care how you do it, just convert this value to a string somehow” syntax remains string interpolation syntax. This syntax is efficient in the cases where the String(x) syntax is allowed, but fully general to the other cases where custom convert-to-string code has not been provided.

Some remaining open questions:

- Exactly what types should conform to ValuePreservingStringConvertible. It seems clear that integer, floating point types, and Character can and should conform. What other types should?

- Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough? We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

Thank you to Austin Zheng for driving this proposal forward!

-Chris Lattner
Review Manager

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


(David Hart) #6

- If its conformers produce a value-preserving representation, would it make sense for it to also have an initializer accepting the value? What specifically makes it value preserving otherwise?

This makes sense to me. But we are getting dangerously close to a Serialization feature which could benefit a more complex and generic design.

- What is the difference between CustomStringConvertible and CustomDebugStringConvertible? Are most implementations of description and debugDescription identical? It says CustomStringConvertible is for writing to an output stream. Is a ‘value preserving string’ going to be a better fit for that all the time?

I’ve always found those two confusing. But I guess that CustomDebugStringConvertible could provide more information, like the actual type and pointer value. For example, imagine that we make UIColor ValuePreservingStringConvertible, one implementation could look like:

let a = UIColor(red: 0, green: 0, blue: 0)
a.description // #000000
a.debugDescription // <UIColor: 0xcodebeef - red: 0.0, green: 0.0, blue: 0.0>

···

- To the question of ‘is CustomStringConvertible enough?’, what about replacing it with ValuePreservingStringConvertible? Then there are two very distinct protocols: ValuePreservingStringConvertible and CustomDebugStringConvertible, one obviously safely value preserving and one obviously just for inspecting.

- Could `.description` be renamed to something more specific and clear? For example, `preservedValue` or `.valuePreservingDescription`. If the recommended way is to use `init<T: ValuePreservingStringConvertible>(_ v: T)`, will anybody be using `.description` directly anyway? I always found NSObject’s seize of the ‘description’ property annoying, as on models it’s a perfect valid property to want as a member, so I was a little disappointed to see it in Swift too. If there’s an alternative, more clear name for this property then it won’t clash with anything else.

I like this clear separation of ‘value preserving’ and ‘just show me something’ representations.

Patrick

On 26 May 2016, at 3:08 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0089-rename-string-reflection-init.md

The review of "SE-0089: Renaming String.init<T>(_: T)" ran from May 17…23, 2016. The proposal has been *returned for revision* and another round of discussion - the core team would love to see the revised proposal make it into Swift 3.

The community and core team both want to remove this “footgun” from the standard library, where someone could write "String(x)” with the intention of getting a value-preserving conversion to String, but may instead get a potentially lossy and potentially expensive reflection-based conversion to a String. After extensive discussion, the core team recommends that the community consider a somewhat more elaborate design:

- Rename the existing reflection-based "String.init<T>(_: T)” initializer to "String.init<T>(describing: T)” as recommend by the community. This initializer would rarely be invoked in user code directly.

- Introduce a new protocol (for sake of discussion, call it “ValuePreservingStringConvertible") that refines CustomStringConvertible but that adds no new requirements. Conformance to this protocol indicates that the “description” requirement produces a value-preserving representation in String form.

- Introduce a new unlabeled initializer on String: "init<T: ValuePreservingStringConvertible>(_ v: T) { return v.description }". This permits the “String(x)” syntax to be used on all values of types that can be converted to string in a value-preserving way.

- Audit important standard library types (e.g. the integer and floating point types), and make them explicitly conform to ValuePreservingStringConvertible with an explicitly implemented “description” property.

- As a performance optimization, change the implementation of the string literal interpolation syntax to prefer the unlabeled initializer when interpolating a type that is ValuePreservingStringConvertible or that has otherwise has an unlabeled String initializer, but use the "String.init<T>(describing: T)” initializer if not.

The expected advantages of this design are:

- Swift encourages the T(x) syntax for value preserving conversions, and this design ensures that String(x) continues to work for the value preserving cases.

- This ensures that the String(x) syntax does not accidentally fall off a performance cliff by using the extremely-dynamic reflection mechanism unintentionally.

- The preferred “I don’t care how you do it, just convert this value to a string somehow” syntax remains string interpolation syntax. This syntax is efficient in the cases where the String(x) syntax is allowed, but fully general to the other cases where custom convert-to-string code has not been provided.

Some remaining open questions:

- Exactly what types should conform to ValuePreservingStringConvertible. It seems clear that integer, floating point types, and Character can and should conform. What other types should?

- Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough? We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

Thank you to Austin Zheng for driving this proposal forward!

-Chris Lattner
Review Manager

_______________________________________________
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


(Dave Abrahams) #7

I think this is an incredible idea.

Should we eventually prepare an updated proposal?

I think that's what “returned for revision” implies :wink:

Given the need for further discussion I'd be happy to drive it
forward, or if someone else wants they can take over too.

(inline)

Proposal Link: https://github.com/apple/swift-evolution/blob/master/proposals/0089-rename-string-reflection-init.md

The review of "SE-0089: Renaming String.init<T>(_: T)" ran from May
17…23, 2016. The proposal has been *returned for revision* and
another round of discussion - the core team would love to see the
revised proposal make it into Swift 3.

The community and core team both want to remove this “footgun” from
the standard library, where someone could write "String(x)” with the
intention of getting a value-preserving conversion to String, but
may instead get a potentially lossy and potentially expensive
reflection-based conversion to a String. After extensive
discussion, the core team recommends that the community consider a
somewhat more elaborate design:

- Rename the existing reflection-based "String.init<T>(_: T)”
initializer to "String.init<T>(describing: T)” as recommend by the
community. This initializer would rarely be invoked in user code
directly.

- Introduce a new protocol (for sake of discussion, call it
“ValuePreservingStringConvertible") that refines
CustomStringConvertible but that adds no new requirements.
Conformance to this protocol indicates that the “description”
requirement produces a value-preserving representation in String
form.

- Introduce a new unlabeled initializer on String: "init<T:
>(_ v: T) { return v.description }".
This permits the “String(x)” syntax to be used on all values of
types that can be converted to string in a value-preserving way.

- Audit important standard library types (e.g. the integer and
floating point types), and make them explicitly conform to
ValuePreservingStringConvertible with an explicitly implemented
“description” property.

Yes to all of this, as others have already said.

- As a performance optimization, change the implementation of the
string literal interpolation syntax to prefer the unlabeled
initializer when interpolating a type that is
ValuePreservingStringConvertible or that has otherwise has an
unlabeled String initializer, but use the
"String.init<T>(describing: T)” initializer if not.

The expected advantages of this design are:

- Swift encourages the T(x) syntax for value preserving conversions, and this design ensures that String(x) continues to work for the value preserving cases.

Yes. I think doing a little more work to keep this convention is worthwhile.

- This ensures that the String(x) syntax does not accidentally fall
off a performance cliff by using the extremely-dynamic reflection
mechanism unintentionally.

- The preferred “I don’t care how you do it, just convert this value
to a string somehow” syntax remains string interpolation syntax.
This syntax is efficient in the cases where the String(x) syntax is
allowed, but fully general to the other cases where custom
convert-to-string code has not been provided.

Some remaining open questions:

- Exactly what types should conform to
ValuePreservingStringConvertible. It seems clear that integer,
floating point types, and Character can and should conform. What
other types should?

Like Brent mentioned, there are some types that are natural
candidates, including Foundation types whose conformance could go into
the overlays. NSURL, NSUUID, NSIndexPath. NSData is a borderline
candidate, and probably not a good fit in the end (what encoding to
use? what happens if you get the .description of a 100 MB NSData?
etc). Same with NSDate. Maybe some of the CGStructs, although maybe
the fact that CGFloat differs between platforms will sink that idea.

Any of the NSObject subclass candidates may require their
`description`s to be altered to meet the semantics, which may or may
not be an acceptable breaking change.

- Do we need the ValuePreservingStringConvertible at all, or is the
existing CustomStringConvertible enough? We already have a few
protocols for handling string convertibility, it would be great to
avoid adding another one.

This is a good question.

Since a ValuePreservingStringConvertible is, by definition, a type
that can be represented as a string in a lossless and unambiguous
manner, would it be worth requiring a reverse conversion in the form
of a failable initializer taking a string?

Yes. It would also be worth requiring that round-trip conversion works
and produces an equivalent value.

···

on Thu May 26 2016, Austin Zheng <swift-evolution@swift.org> wrote:

On May 25, 2016, at 10:08 PM, Chris Lattner <clattner@apple.com> wrote:

Some of the proposed ValuePreservingStringConvertible types already
have such functionality today. It would give the protocol a little
more of a reason to exist, as well as encouraging proper conformance.

Today, `description` is definitely used for both lossless and lossy
string representations, and that's probably not going to change in the
future.

Thank you to Austin Zheng for driving this proposal forward!

-Chris Lattner
Review Manager

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

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

--
Dave


(Patrick Smith) #8

This distinction seems a little arbitrary to me. However, something like `preservedString` would make more sense to me:

let a = UIColor(red: 0, green: 0, blue: 0)
a.preservedString // #000000 — or perhaps more accurate: rgba(0.0,0.0,0.0,1.0)
a.debugDescription // <UIColor: 0xcodebeef - red: 0.0, green: 0.0, blue: 0.0>

This why I think it makes sense to really differentiate `description` from `debugDescription`, so it’s no long ‘confusing’ as you say.

···

On 26 May 2016, at 5:40 PM, David Hart <david@hartbit.com> wrote:

I’ve always found those two confusing. But I guess that CustomDebugStringConvertible could provide more information, like the actual type and pointer value. For example, imagine that we make UIColor ValuePreservingStringConvertible, one implementation could look like:

let a = UIColor(red: 0, green: 0, blue: 0)
a.description // #000000
a.debugDescription // <UIColor: 0xcodebeef - red: 0.0, green: 0.0, blue: 0.0>


(Patrick Smith) #9

Do you think it might be worth changing `description` to be named something else? Something more clear, less likely to conflict with ‘real’ properties — ‘description’ doesn’t seem to portray something that is value-preserving. What is the reason for calling it ‘description’?

Especially if NSObject subclasses won’t fit, then why not have a different method that can be strictly value preserving? (Then `description` can stay being an NSObject thing.)

···

On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

Any of the NSObject subclass candidates may require their `description`s to be altered to meet the semantics, which may or may not be an acceptable breaking change.


(Chris Lattner) #10

Some remaining open questions:

- Exactly what types should conform to ValuePreservingStringConvertible. It seems clear that integer, floating point types, and Character can and should conform. What other types should?

Like Brent mentioned, there are some types that are natural candidates, including Foundation types whose conformance could go into the overlays. NSURL, NSUUID, NSIndexPath. NSData is a borderline candidate, and probably not a good fit in the end (what encoding to use? what happens if you get the .description of a 100 MB NSData? etc). Same with NSDate. Maybe some of the CGStructs, although maybe the fact that CGFloat differs between platforms will sink that idea.

Yes, there definitely are Foundation types that could adopt this. However, we don’t have a swift-evolution process at the moment to propose Foundation API extensions, so these would have to go through bugreporter.apple.com.

- Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough? We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

This is a good question.

Since a ValuePreservingStringConvertible is, by definition, a type that can be represented as a string in a lossless and unambiguous manner, would it be worth requiring a reverse conversion in the form of a failable initializer taking a string? Some of the proposed ValuePreservingStringConvertible types already have such functionality today. It would give the protocol a little more of a reason to exist, as well as encouraging proper conformance.

Yes, this would be really great. Perhaps obvious, but this could/should be expressed an initializer requirement in ValuePreservingStringConvertible.

-Chris

···

On May 26, 2016, at 9:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:


(Austin Zheng) #11

I think I agree. "description" to me implies something meant for humans to read, whatever the exact form. Something like "stringRepresentation" would be a more precise name for the property.

···

On May 26, 2016, at 11:58 PM, Daniel Vollmer via swift-evolution <swift-evolution@swift.org> wrote:

On 27 May 2016, at 07:14, Patrick Smith via swift-evolution <swift-evolution@swift.org> wrote:

On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

Any of the NSObject subclass candidates may require their `description`s to be altered to meet the semantics, which may or may not be an acceptable breaking change.

Do you think it might be worth changing `description` to be named something else? Something more clear, less likely to conflict with ‘real’ properties — ‘description’ doesn’t seem to portray something that is value-preserving. What is the reason for calling it ‘description’?

I’m also not quite sure (from the suggested names) whether the intended use is to be “a string *description* that happens to be value-preserving” (for which the name description might be ok), or “a value-preserving version of the instance as string *with no intent of that string ever being descriptive or helpful when presented to anything other than the matching initialiser of the same type*” (which rather be one form of serialisation).

  Daniel.

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


(Daniel Vollmer) #12

I’m also not quite sure (from the suggested names) whether the intended use is to be “a string *description* that happens to be value-preserving” (for which the name description might be ok), or “a value-preserving version of the instance as string *with no intent of that string ever being descriptive or helpful when presented to anything other than the matching initialiser of the same type*” (which rather be one form of serialisation).

  Daniel.

···

On 27 May 2016, at 07:14, Patrick Smith via swift-evolution <swift-evolution@swift.org> wrote:

On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

Any of the NSObject subclass candidates may require their `description`s to be altered to meet the semantics, which may or may not be an acceptable breaking change.

Do you think it might be worth changing `description` to be named something else? Something more clear, less likely to conflict with ‘real’ properties — ‘description’ doesn’t seem to portray something that is value-preserving. What is the reason for calling it ‘description’?


(L Mihalkovic) #13

Any of the NSObject subclass candidates may require their `description`s to be altered to meet the semantics, which may or may not be an acceptable breaking change.

Do you think it might be worth changing `description` to be named something else? Something more clear, less likely to conflict with ‘real’ properties — ‘description’ doesn’t seem to portray something that is value-preserving. What is the reason for calling it ‘description’?

I’m also not quite sure (from the suggested names) whether the intended use is to be “a string *description* that happens to be value-preserving” (for which the name description might be ok), or “a value-preserving version of the instance as string *with no intent of that string ever being descriptive or helpful when presented to anything other than the matching initialiser of the same type*” (which rather be one form of serialisation).

   Daniel.

If you want to pursue this line of thinking, there is already precedent in the language for denoting 'an equivalent representation to', it is the "as" keyword. So perhaps to denote that the string is an equivalent representation of the value of this object, something like the following might be closer:

asStringValue
asString

but not the following as they convey the notion of a convertion rather than an equivalence:
toString
toStringValue

But frankly, I don't know that is it worth touching description (as the merrit of avoiding the ensuing debate of camel casing).

···

On May 27, 2016, at 8:58 AM, Daniel Vollmer via swift-evolution <swift-evolution@swift.org> wrote:

On 27 May 2016, at 07:14, Patrick Smith via swift-evolution <swift-evolution@swift.org> wrote:

On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

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


(Dave Abrahams) #14

Any of the NSObject subclass candidates may require their
`description`s to be altered to meet the semantics, which may or may
not be an acceptable breaking change.

Do you think it might be worth changing `description` to be named
something else? Something more clear, less likely to conflict with
‘real’ properties — ‘description’ doesn’t seem to portray something
that is value-preserving. What is the reason for calling it
‘description’?

The main reason was backward compatibility with Cocoa, which already has
a “description” property.

···

on Thu May 26 2016, Patrick Smith <swift-evolution@swift.org> wrote:

On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

Especially if NSObject subclasses won’t fit, then why not have a
different method that can be strictly value preserving? (Then
`description` can stay being an NSObject thing.)

--
Dave


(Patrick Smith) #15

Is there any possibility we can break from this? Especially as:

1. ValuePreservingStringConvertible expects its description to be value preserving, but current Cocoa implementations are not.
2. ‘Description’ doesn’t really convey the meaning of ‘value preserving’ in my mind, but is a valuable name for many other use cases.
3. Swift 3 has a wide range of breaking changes for the better.
4. With the presence of ValuePreservingStringConvertible, CustomStringConvertible doesn’t seem to provide much value over CustomDebugStringConvertible?

For string interpolation, I imagine the standard library could fall back to a ‘description’ method for NSObject subclasses.

Thanks,

Patrick

···

On 28 May 2016, at 7:49 AM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Thu May 26 2016, Patrick Smith <swift-evolution@swift.org> wrote:

On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org> wrote:

Any of the NSObject subclass candidates may require their
`description`s to be altered to meet the semantics, which may or may
not be an acceptable breaking change.

Do you think it might be worth changing `description` to be named
something else? Something more clear, less likely to conflict with
‘real’ properties — ‘description’ doesn’t seem to portray something
that is value-preserving. What is the reason for calling it
‘description’?

The main reason was backward compatibility with Cocoa, which already has
a “description” property.

Especially if NSObject subclasses won’t fit, then why not have a
different method that can be strictly value preserving? (Then
`description` can stay being an NSObject thing.)

--
Dave

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


(Austin Zheng) #16

I've submitted a swift-evolution PR with a modified version of the proposal that takes into account the feedback from the discussion participants.

If anyone is curious, the revised proposal can be found here: https://github.com/austinzheng/swift-evolution/blob/2b31df6163f5c5d1975a37e72c6996b82d61a5c6/proposals/0089-rename-string-reflection-init.md

Best,
Austin

···

On May 28, 2016, at 1:08 PM, Chris Lattner <clattner@apple.com> wrote:

On May 26, 2016, at 9:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Some remaining open questions:

- Exactly what types should conform to ValuePreservingStringConvertible. It seems clear that integer, floating point types, and Character can and should conform. What other types should?

Like Brent mentioned, there are some types that are natural candidates, including Foundation types whose conformance could go into the overlays. NSURL, NSUUID, NSIndexPath. NSData is a borderline candidate, and probably not a good fit in the end (what encoding to use? what happens if you get the .description of a 100 MB NSData? etc). Same with NSDate. Maybe some of the CGStructs, although maybe the fact that CGFloat differs between platforms will sink that idea.

Yes, there definitely are Foundation types that could adopt this. However, we don’t have a swift-evolution process at the moment to propose Foundation API extensions, so these would have to go through bugreporter.apple.com <http://bugreporter.apple.com/>.

- Do we need the ValuePreservingStringConvertible at all, or is the existing CustomStringConvertible enough? We already have a few protocols for handling string convertibility, it would be great to avoid adding another one.

This is a good question.

Since a ValuePreservingStringConvertible is, by definition, a type that can be represented as a string in a lossless and unambiguous manner, would it be worth requiring a reverse conversion in the form of a failable initializer taking a string? Some of the proposed ValuePreservingStringConvertible types already have such functionality today. It would give the protocol a little more of a reason to exist, as well as encouraging proper conformance.

Yes, this would be really great. Perhaps obvious, but this could/should be expressed an initializer requirement in ValuePreservingStringConvertible.

-Chris


(Austin Zheng) #17

Hello swift-evolution,

I've put together a preliminary v2 of the proposal, taking into account
feedback expressed on this thread. I would appreciate any comments,
suggestions, or criticisms.

https://github.com/austinzheng/swift-evolution/blob/az-edit-89/proposals/0089-rename-string-reflection-init.md

If any objections can be worked out quickly, I hope to resubmit this
proposal for review early next week.

Best,
Austin

···

On Fri, May 27, 2016 at 7:50 PM, Patrick Smith via swift-evolution < swift-evolution@swift.org> wrote:

Is there any possibility we can break from this? Especially as:

1. ValuePreservingStringConvertible expects its description to be value
preserving, but current Cocoa implementations are not.
2. ‘Description’ doesn’t really convey the meaning of ‘value preserving’
in my mind, but is a valuable name for many other use cases.
3. Swift 3 has a wide range of breaking changes for the better.
4. With the presence of ValuePreservingStringConvertible,
CustomStringConvertible doesn’t seem to provide much value over
CustomDebugStringConvertible?

For string interpolation, I imagine the standard library could fall back
to a ‘description’ method for NSObject subclasses.

Thanks,

Patrick

> On 28 May 2016, at 7:49 AM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote:
>
>
> on Thu May 26 2016, Patrick Smith <swift-evolution@swift.org> wrote:
>
>>> On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution < > swift-evolution@swift.org> wrote:
>>>
>>> Any of the NSObject subclass candidates may require their
>>> `description`s to be altered to meet the semantics, which may or may
>>> not be an acceptable breaking change.
>>
>> Do you think it might be worth changing `description` to be named
>> something else? Something more clear, less likely to conflict with
>> ‘real’ properties — ‘description’ doesn’t seem to portray something
>> that is value-preserving. What is the reason for calling it
>> ‘description’?
>
> The main reason was backward compatibility with Cocoa, which already has
> a “description” property.
>
>> Especially if NSObject subclasses won’t fit, then why not have a
>> different method that can be strictly value preserving? (Then
>> `description` can stay being an NSObject thing.)
>
> --
> Dave
>
> _______________________________________________
> 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


(Austin Zheng) #18

Thanks, I like "Lossless" too. Further suggestions on naming would be appreciated from anyone.

Austin

···

On May 27, 2016, at 9:03 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This looks good. I like your use of the term "lossless"; perhaps we can use it consistently, i.e. LosslessStringConvertible. The implication by comparison would be that CustomStringConvertible makes no guarantee of losslessness.
On Fri, May 27, 2016 at 23:52 Austin Zheng via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello swift-evolution,

I've put together a preliminary v2 of the proposal, taking into account feedback expressed on this thread. I would appreciate any comments, suggestions, or criticisms.

https://github.com/austinzheng/swift-evolution/blob/az-edit-89/proposals/0089-rename-string-reflection-init.md

If any objections can be worked out quickly, I hope to resubmit this proposal for review early next week.

Best,
Austin

On Fri, May 27, 2016 at 7:50 PM, Patrick Smith via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Is there any possibility we can break from this? Especially as:

1. ValuePreservingStringConvertible expects its description to be value preserving, but current Cocoa implementations are not.
2. ‘Description’ doesn’t really convey the meaning of ‘value preserving’ in my mind, but is a valuable name for many other use cases.
3. Swift 3 has a wide range of breaking changes for the better.
4. With the presence of ValuePreservingStringConvertible, CustomStringConvertible doesn’t seem to provide much value over CustomDebugStringConvertible?

For string interpolation, I imagine the standard library could fall back to a ‘description’ method for NSObject subclasses.

Thanks,

Patrick

> On 28 May 2016, at 7:49 AM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
>
> on Thu May 26 2016, Patrick Smith <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>
>>> On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>
>>> Any of the NSObject subclass candidates may require their
>>> `description`s to be altered to meet the semantics, which may or may
>>> not be an acceptable breaking change.
>>
>> Do you think it might be worth changing `description` to be named
>> something else? Something more clear, less likely to conflict with
>> ‘real’ properties — ‘description’ doesn’t seem to portray something
>> that is value-preserving. What is the reason for calling it
>> ‘description’?
>
> The main reason was backward compatibility with Cocoa, which already has
> a “description” property.
>
>> Especially if NSObject subclasses won’t fit, then why not have a
>> different method that can be strictly value preserving? (Then
>> `description` can stay being an NSObject thing.)
>
> --
> Dave
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution

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

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


(Brent Royal-Gordon) #19

https://github.com/austinzheng/swift-evolution/blob/az-edit-89/proposals/0089-rename-string-reflection-init.md

I prefer the more conservative and backwards-compatible option of using `description` and conforming `ValuePreservingStringConvertible` to `CustomStringConvertible`.

This is for three reasons:

* ValuePreservingStringConvertible really is a refinement of CustomStringConvertible's semantic; a value-preserving `description` should always be acceptable as an ordinary `description`.

* You should not call `description` directly anyway; you should call `String.init(_:)`. That makes the arguably non-descriptive name a lot less important.

* Changing the name of this property now will not actually make `description` available for the uses you want to put it to in most code. No amount of monkeying with the Swift standard library in 2016 can change the fact that the OpenStep specification took that name in 1994, and we need to interoperate with that heritage. You might free up the name `description` in value types and Linux-only code, but only at the cost of interoperability headaches. I don't think that's worth it.

I also think that, if we're serious about ValuePreservingStringConvertible's initializer restoring the full state of the instance, then it is a full-width conversion and doesn't need a label.

So, here's what I suggest:

  protocol CustomStringConvertible {
    var description: String { get }
  }
  protocol ValuePreservingStringConvertible: CustomStringConvertible {
    init?(_ description: String)
  }
  extension String {
    init<Value: ValuePreservingStringConvertible>(_ value: Value) { ... }
    init<Value>(describing value: Value) { ... }
  }

Actually, I'd *like* to see `String.init(describing:)` constrained to CustomStringConvertible, but I've lost that argument before.

("Lossless" instead of "ValuePreserving" is fine too, perhaps even slightly better.)

···

--
Brent Royal-Gordon
Architechies


(Xiaodi Wu) #20

This looks good. I like your use of the term "lossless"; perhaps we can use
it consistently, i.e. LosslessStringConvertible. The implication by
comparison would be that CustomStringConvertible makes no guarantee of
losslessness.

···

On Fri, May 27, 2016 at 23:52 Austin Zheng via swift-evolution < swift-evolution@swift.org> wrote:

Hello swift-evolution,

I've put together a preliminary v2 of the proposal, taking into account
feedback expressed on this thread. I would appreciate any comments,
suggestions, or criticisms.

https://github.com/austinzheng/swift-evolution/blob/az-edit-89/proposals/0089-rename-string-reflection-init.md

If any objections can be worked out quickly, I hope to resubmit this
proposal for review early next week.

Best,
Austin

On Fri, May 27, 2016 at 7:50 PM, Patrick Smith via swift-evolution < > swift-evolution@swift.org> wrote:

Is there any possibility we can break from this? Especially as:

1. ValuePreservingStringConvertible expects its description to be value
preserving, but current Cocoa implementations are not.
2. ‘Description’ doesn’t really convey the meaning of ‘value preserving’
in my mind, but is a valuable name for many other use cases.
3. Swift 3 has a wide range of breaking changes for the better.
4. With the presence of ValuePreservingStringConvertible,
CustomStringConvertible doesn’t seem to provide much value over
CustomDebugStringConvertible?

For string interpolation, I imagine the standard library could fall back
to a ‘description’ method for NSObject subclasses.

Thanks,

Patrick

> On 28 May 2016, at 7:49 AM, Dave Abrahams via swift-evolution < >> swift-evolution@swift.org> wrote:
>
>
> on Thu May 26 2016, Patrick Smith <swift-evolution@swift.org> wrote:
>
>>> On 27 May 2016, at 2:40 PM, Austin Zheng via swift-evolution < >> swift-evolution@swift.org> wrote:
>>>
>>> Any of the NSObject subclass candidates may require their
>>> `description`s to be altered to meet the semantics, which may or may
>>> not be an acceptable breaking change.
>>
>> Do you think it might be worth changing `description` to be named
>> something else? Something more clear, less likely to conflict with
>> ‘real’ properties — ‘description’ doesn’t seem to portray something
>> that is value-preserving. What is the reason for calling it
>> ‘description’?
>
> The main reason was backward compatibility with Cocoa, which already has
> a “description” property.
>
>> Especially if NSObject subclasses won’t fit, then why not have a
>> different method that can be strictly value preserving? (Then
>> `description` can stay being an NSObject thing.)
>
> --
> Dave
>
> _______________________________________________
> 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