swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.62k stars 10.37k forks source link

[SR-2062] Optionals do not conform to CustomStringConvertible #44671

Open swift-ci opened 8 years ago

swift-ci commented 8 years ago
Previous ID SR-2062
Radar None
Original Reporter erica (JIRA User)
Type Bug
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Standard Library | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 983c4522a7cfa08be3464f79fc4e1593

relates to:

Issue Description:

Optionals do not currently conform to CustomStringConvertible so their representations do not use the preferred representation of the wrapped value:

let amount: Float? = 3.8
print(amount) // prints Optional(3.79999995)
print(amount!) // prints 3.8

Conforming Optional to CustomStringConvertible pricks up the value's preferred output style:

extension Optional : CustomStringConvertible {
    /// A textual representation of this instance, suitable for printing.
    public var description: String {
        switch self {
        case .some(let value):
            var result = "Optional("
            print(value, terminator: "", to: &result)
            result += ")"
            return result
        case .none:
            return "nil"
        }
    }
}

When added, the output is

let amount: Float? = 3.8
print(amount) // prints Optional(3.8)
print(amount!) // prints 3.8
belkadan commented 8 years ago

In order to do this properly we would need conditional conformances. But in most cases you don't really want to print an Optional directly anyway. I'll admit playgrounds are an exception.

jckarter commented 8 years ago

This behavior is intentional. Optional does conform to CustomDebugStringConvertible. We wanted to make it clear you're printing a wrapped Optional so that in playgrounds or printf-debugging scenarios, it's clear the value is wrapped.

swift-ci commented 8 years ago

Comment by Shai Mishali (JIRA)

I'm not exactly sure how printing out an adjusted/wrong value gives clarity on the fact it's wrapped ?

The issue is getting Optional(3.79999995) instead of the expected Optional(3.8) eventually

jckarter commented 8 years ago

I think that's because debugDescription and description print floats at different precisions, and Optional uses the debugDescription. The former ought to give you enough digits to uniquely identify the float value.

swift-ci commented 8 years ago

Comment by Shai Mishali (JIRA)

That's very interesting, thanks for elaborating on the possible cause šŸ™‚

I would still think this is more of a bug/side-effect then actual intended behaviour...

When I got around to just printing a result of some request returning an optional Float, i was sure something was wrong until unwrapping that value. I do agree most users would print an already-unwrapped value, but it still seems kinda odd and somewhat confusing to leave it this way.

Is there anything preventing using `description` over `debugDescription` in that scenario ?

belkadan commented 8 years ago

Strings in particular don't compose well with other context. Is Optional(nil) a doubly-nested optional, or an optional containing the string "nil"?

jckarter commented 8 years ago

We generally use debugDescription in nested positions. The alternative is worse for things like String, since description doesn't include the punctuation or escaping. .some("(1, 2)") would print as Optional((1, 2)) if we accepted this, for instance. Arrays, dictionaries, and other containers also use the debugDescription for similar reasons.

swift-ci commented 8 years ago

Comment by Shai Mishali (JIRA)

Understood šŸ™‚ Thanks again for the explanation.

Jordan, that's actually a great point as well.

Dante-Broggi commented 6 years ago

Is this actually a bug? It seems just a natural consequence of `Optional` using it's wrapped value's `debugDescription` as part of it's `description`.