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

Thorsten Seitz tseitz42 at icloud.com
Sat Sep 3 11:19:01 CDT 2016



> Am 15.08.2016 um 19:05 schrieb Justin Jia via swift-evolution <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 

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


More information about the swift-evolution mailing list