[swift-evolution] Proposal: Deprecate optionals in string interpolation

Charlie Monroe charlie at charliemonroe.net
Sun Jun 19 04:13:04 CDT 2016


> On Jun 19, 2016, at 6:59 AM, Chris Lattner <clattner at apple.com> wrote:
> 
> 
>> On Jun 16, 2016, at 12:44 PM, Charlie Monroe via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> Sorry, didn't have time to actually submit the proposal, but it at least gave me some time to think it through a few more times.
>> 
>> After reconsiderations, I suggest the following:
>> 
>> - deprecation of interpolation of optionals.
>> - extending the Optional type by:
>> 	- var detailedDescription: String - which will return the same value as until now: "nil" for nil and "Optional(value)" for .some(_). This is due to .description and .debugDescription's documentation discouraging direct invocation.
>> 
>> 	- func descriptionWithDefaultValue(_ defaultValue: String = "nil") -> String - which would return either the description of the value, or `defaultValue`.
>> 
>> So, when the compiler runs into interpolation of an Optional, it issues a warning with a fix-it, that by default calls .descriptionWithDefaultValue() on the optional.
> 
> I think that this is overcomplicating the issue.  I’d suggest that someone just implement a simple compiler patch (which doesn’t need an evolution proposal):
> 
> 1. Produce a warning when a string interpolation includes a non-redundantly-parenthesized optional, saying that this is probably a bug.
> 2. Attach two notes (with fixits) to the warning:
> 2a. a note that adds redundant parens around the parameter, silencing the warning.
> 2b. a note that fixits the issue with a “!” or "?? <#placeholder#>"

The "?? <#placeholder#>" fix-it suffers from a slight drawback:

enum MyEnum {
    case value1
    case value2
}

let someObj: MyEnum? = nil
let obj = someObj ?? "Hello" // Error: Binary operator '??' cannot be applied to operands of type 'MyEnum?' and 'String'

(tested in Xcode 8)

I'm not sure whether to consider this a bug in the compiler - what should be the correct behavior? Should "obj" be of kind "Any" with the compiler finding the lowest common type in all cases? Won't this introduce a new kind of confusing bugs where the inferred types would be wrong?

I've deprecated the interpolation of Optionals in my projects (~200KLOC) using an extension on String and the only way to satisfy the compiler in all cases is to use something like 

"someObj is \((someObj as Any?) ?? "Hello")"

And it can get a bit nastier, which is why I've proposed a more universal and better readable fix:

"someObj is \(someObj.descriptionWithDefaultValue("Hello"))"

and

"\(item.valueForPrintableField(.DocumentType, withContext: nil).optionaDescription) \(item.year) - \(item.itemID).pdf"

I'm personally not a big fan of the extra parentheses around the optional for silencing the warning either, mostly since it will look like this:

"\((item.valueForPrintableField(.DocumentType, withContext: nil))) \(item.year) - \(item.itemID).pdf"

which is IMHO hard to read and understand why there are so many parentheses.

But if you insist on this being the way to go, I'll try to take a look at the compiler, though it's been a while since I've done anything in Clang.

> 
> I agree that this should be fixed.
> 
> -Chris
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160619/9da29d43/attachment.html>


More information about the swift-evolution mailing list