[swift-evolution] Request for Discussion: Setup closures

Joe Groff jgroff at apple.com
Fri Dec 4 15:27:05 CST 2015


> On Dec 4, 2015, at 1:24 PM, Erica Sadun <erica at ericasadun.com> wrote:
> 
> PROBLEM: With many Apple-supplied classes, typical initializers fail to fully set up an instance for use.  Here's one example:
> 
> let task = NSTask()
> task.launchPath = "/usr/bin/mdfind"
> task.arguments = ["kMDItemDisplayName == *.playground"]
> task.standardOutput = pipe
> 
> Here's another:
> 
> let questionLabel = UILabel()
> questionLabel.textAlignment = .Center
> questionLabel.font =  UIFont(name:"DnealianManuscript", size: 72)
> questionLabel.text = currentQuestion.questionText
> questionLabel.numberOfLines = 0
> 
> You end up with stodgy repetitive code that turns into a blocky hard-to-follow clump. Here are some of my complaints:
> This code feels unnecessarily redundant 
> This code visually stacks. The task/task/task and questionLabel/questionLabel/questionLabel blocks draw attention away from the actual set-up these lines of code are intended to do. 
> The extra symbol verbiage goes against common Swift style. For example, when the context is clear, prefer .whitespaceAndNewlineCharacterSet to NSCharacterSet.whitespaceAndNewlineCharacterSet.
> Further, if you have many instances to set up there's no clear way to differentiate unrelated set-up groups other than inserting whitespace gaps or building custom factory functions.
> 
> PROPOSED SOLUTION: What do you think about creating setup closures  that modify initializers and automatically introduce self-references. For example the NSTask() initialization might look something like this instead:
> 
> let task = NSTask()>>{
>     launchPath = "/usr/bin/mdfind"
>     arguments = ["kMDItemDisplayName == *.playground"]
>     standardOutput = pipe
> }
> 
> In this example, the braces are scoped to the instance as self, enabling the properties to entirely drop their prefixes and be grouped together for set-up.

In Smalltalk and Dart, you can do this with method cascades, which apply multiple methods to the same 'self'. In Dart they use '..' for this:

let task = NSTask()
  ..launchPath = "..."
  ..arguments = [...]
  ..standardOutput = pipe

The nice thing about that is that it's a bit more generally applicable than just initialization.

-Joe

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151204/0ec325b3/attachment-0001.html>


More information about the swift-evolution mailing list