> Am 03.09.2016 um 18:45 schrieb Justin Jia <[email protected]>: > > >> On Sep 4, 2016, at 12:19 AM, Thorsten Seitz <[email protected]> wrote: >> >> >> >> Am 15.08.2016 um 19:05 schrieb Justin Jia via swift-evolution >> <[email protected]>: >> >>> 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) >> } >> ``` >
I agree. The proposal effectively does just that, though: turn every function into a function accepting optionals (returning nil if any argument is nil). I would prefer to do this explicitly in cases where it makes sense and use map or let-bindings elsewhere. -Thorsten
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
