[swift-evolution] [Idea] Use optionals for non-optional parameters

Justin Jia justin.jia.developer at gmail.com
Sat Sep 3 11:45:42 CDT 2016


> On Sep 4, 2016, at 12:19 AM, Thorsten Seitz <tseitz42 at icloud.com> wrote:
> 
> 
> 
> Am 15.08.2016 um 19:05 schrieb Justin Jia via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>>:
> 
>> I agree that being explicit is nice and I also like to use `guard`.
>> 
>> But according to my observation, usually it is easier to make mistakes if we choose to use `guard`.
>> 
>> Let me give you a fake real world example.
>> 
>> With `guard`, you need to be really careful when you want to add new expression (people usually will add to the end of the function).
>> 
>> ```
>> func updateCell(cell: Cell, data: CellData) {
>>   cell.label.text = data.title
>>   guard let imageName = data.imageName else { return }
>>   cell.sublabel.text = cell.humanize(imageName)
>>   guard let image = UIImage(named: imageName) else { return }
>>   cell.addBackgroundImage(image)
>>   // Let's say we changed the design and added a new heading that depends on image name
>>   cell.heading = String(imageName.characters.first) // This won't be called if image is nil!
>> }
>> ```
>> 
>> With `if let`, it is really hard to read. This will become more complicated if we add more attributes to cell.
>> 
>> ```
>> func updateCell(cell: Cell, data: CellData) {
>>   cell.label.text = data.title
>>   if let imageName = data.imageName {
>>     cell.sublabel.text = cell.humanize(imageName)
>>     if let image = UIImage(name: imageName) {
>>       cell.addBackgroundImage(image)
>>     }
>>     cell.heading = String(imageName.characters.first)
>>   }
>> }
>> ```
>> 
>> With the proposed syntax:
>> 
>> ```
>> func updateCell(cell: Cell, data: CellData) {
>>   cell.label.text = data.title
>>   let imageName = data.imageName // imageName is optional
>>   cell.sublabel.text = cell.humanize(imageName?)
>>   let image = UIImage(named: imageName?) // image is optional
>>   cell.addBackgroundImage(image?)
>>   cell.heading = String(imageName.characters.first?)
>> }
>> ```
>> 
>> This is really easy to read. And everything works correctly.
> 
> It is even easier if you define the methods on Cell to take optional arguments. 
> Then you can write the code like in your last example and don't even need the proposed syntax:
> 
> class Cell {
>     let label = UILabel()
>     let sublabel = UILabel()
>     var heading: String?
>     func humanize(_ string: String?) -> String {...}    // optional argument
>     func addBackgroundImage(_ image: UIImage?)    // optional argument
> }
> 
> extension UIImage {
>     init?(named imageName: String?) {...}
> }
> 
> extension String {
>     init?(named imageName: Character?) {...}
> }
> 
> func updateCell(cell: Cell, data: CellData) {
>   cell.label.text = data.title
>   let imageName = data.imageName
>   cell.sublabel.text = cell.humanize(imageName)
>   let image = UIImage(named: imageName)
>   cell.addBackgroundImage(image)
>   cell.heading = String(imageName?.characters?.first)
> }
> 
> -Thorsten 


Quoting another email:

> Actually there is an easy fix: make all functions accept optionals. I think this is a really bad idea because sometimes functions are designed to accept non-optionals.
> 
> e.g.
> 
> ```
> func addSubview(_ view: UIView) { }
> ```
> 
> It doesn’t make sense if we want to add nil as the subview, so we choose to write code like this:
> 
> ```
> if let view = view {
>     addSubview(view)
> }
> ```

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


More information about the swift-evolution mailing list