[swift-dev] Optional to String conversion
Andrew Trick
atrick at apple.com
Sat Dec 5 02:33:51 CST 2015
> On Dec 4, 2015, at 10:26 PM, Dmitri Gribenko <gribozavr at gmail.com> wrote:
>
> On Fri, Dec 4, 2015 at 10:21 PM, Andrew Trick <atrick at apple.com <mailto:atrick at apple.com>> wrote:
>>
>>> On Dec 4, 2015, at 10:05 PM, Dmitri Gribenko <gribozavr at gmail.com> wrote:
>>>
>>> On Fri, Dec 4, 2015 at 10:00 PM, Andrew Trick <atrick at apple.com> wrote:
>>>> I’m adding runtime functionality to support optional casts and ran into some Optional to String conversion behavior that is currently somewhat accidental—it will break when I add functionality. I want to understand the desired behavior before doing extra work to fix it.
>>>>
>>>> Currently swift does this:
>>>>
>>>>> print(Int?(3))
>>>> Optional(3)
>>>>> print(String?("meow"))
>>>> Optional("meow")
>>>>
>>>> I think swift should do this:
>>>>
>>>>> print(Int?(3))
>>>> 3
>>>>> print(String?("meow"))
>>>> "meow"
>>>>> debugPrint(Int?(3))
>>>> Optional(3)
>>>>> debugPrint(String?("meow"))
>>>> Optional("meow")
>>>>
>>>> When a value already knows how to represent itself as a string, I don't think that the string "Optional" belongs in the textual representation.
>>>>
>>>> When debugging data structures, it makes sense to include the "Optional" indicator.
>>>>
>>>> What was the intention here and what do people think is the desired behavior?
>>>
>>> This behavior was not accidental. Here's the rationale:
>>>
>>> If an Optional is nil, it should somehow indicate that. Whatever the
>>> representation is, it would be engineer-oriented and not suitable for
>>> end users. Thus, Optional should never be printed to users, it would
>>> only ever be presented to engineers, and thus its print() and
>>> debugPrint() representations should be the same.
>>>
>>> Dmitri
>>
>> I think you're saying that it's the programmer's responsibility not to construct a user-visible String from an Optional.
>
> No, the responsibility is not to display it to users. It is OK to e.g., log it.
>
>> By accidental, I mean that Optional does not conform to CustomStringConvertible. If we want "Optional" to be part of the string conversion, then this conformance needs to exist, or I need to add some special handling of Optional. Do you see any problem with me adding that conformance?
>
> Yes, the same behavior should also apply to any user-defined type: if
> there is only CustomDebugStringConvertible conformance, it should be
> used for String(x) initialization.
>
>> Incidentally, when *do* we want debug string conversion to deviate? Or is it just a customization point we anticipate to be useful?
>
> For example, in String: the user-presentable representation is the
> string itself, the engineer-oriented representation shows all special
> characters as escape sequences.
>
> Dmitri
I understand, thanks for the explanation. But Optionals are not like
other user-defined types in this respect. Let me clarify with an
example...
class A : CustomStringConvertible, CustomDebugStringConvertible {
init() {}
var description: String { get { return "Apple" } }
var debugDescription: String { get { return "Swift" } }
}
print(A?(A()) is CustomStringConvertible)
// true
// Now, Optional does not conform to CustomStringConvertible, but as
// you can see above it is convertible to CustomStringConvertible.
// As print_unlocked is currently written, the behavior should be:
print(String(A?(A())))
Apple
// But as you explained, that is not the behavior we want. We could fix
// it by making Optional counter-intuitively conform to
// CustomStringConvertible. This prevents down conversion to the wrapped
// type, instead printing "Optional" and the payload's debug string.
extension Optional : CustomStringConvertible {
/// A textual representation of `self`, suitable for debugging.
///
/// Optional has no representation suitable for an output
/// stream. Consequently, String conversion should always produce a
/// debug string indicating the Optional type and including the
/// debug representation of the wrapped type.
///
/// Optional must conform to CustomStringConvertible to avoid
/// automatic conversion to its wrapped type during String
/// conversion.
public var description: String {
return debugDescription
}
}
print(String(A?(A())))
Optional(Swift)
I think this is the way to go.
Andy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20151205/029ee5e5/attachment-0001.html>
More information about the swift-dev
mailing list