{"id":336,"date":"2014-07-04T08:28:19","date_gmt":"2014-07-04T14:28:19","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=336"},"modified":"2014-07-04T08:28:19","modified_gmt":"2014-07-04T14:28:19","slug":"using-swift-as-a-scripting-language","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/using-swift-as-a-scripting-language\/","title":{"rendered":"Using Swift As a Scripting Language"},"content":{"rendered":"<p>Much fanfare accompanied the &#8220;playground&#8221; feature of Xcode 6 that allows developers to write some code and see the effect in realtime.  If you have any experience with scripting languages such as Ruby or Python, you recognize this as nothing more than running the interactive language interpreter.  With Ruby you type <code>irb<\/code> at the command line; for Python try <code>python<\/code>.<\/p>\n<p><code><br \/>\n$ irb<br \/>\n1.9.3-p448 :001 > fruit = ['apples', 'pears', 'bananas']<br \/>\n => [\"apples\", \"pears\", \"bananas\"]<br \/>\n<\/code><\/p>\n<p><code><br \/>\n$ python<br \/>\nPython 2.7.6 (default, May 30 2014, 22:21:15)<br \/>\n[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.34.2)] on darwin<br \/>\nType \"help\", \"copyright\", \"credits\" or \"license\" for more information.<br \/>\n>>> fruit = ['apples', 'pears', 'bananas']<br \/>\n<\/code><\/p>\n<p>For some reason Swift employs the more technical name of an interpreter, the <b>REPL<\/b>, or <b>Read-Eval-Print-Loop<\/b>.  The interpreter reads what you entered, evaluates it, prints it, and then loops back to read.  The <b>REPL<\/b> isn&#8217;t magic, and its not anything new, it&#8217;s just new to those whose only experience with iOS and Mac development is Objective-C.  Objective-C (and it&#8217;s C and C++ brethren) use the <b>ECLR<\/b> paradigm:  <b>Edit-Compile-Link-Run<\/b>.<\/p>\n<p>It stands to reason that if you can run a Swift interpreter in Xcode, you can run it from the commandline.  And sure enough you can you just have to dig down into the Xcode 6 package contents and find the binary to run.  So open up a Terminal or <a href=\"http:\/\/www.iterm2.com\/\">iTerm 2<\/a> and type into your shell:<\/p>\n<p><code><br \/>\nexport PATH=\"\/Applications\/Xcode6-Beta.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/bin\/\":$PATH<br \/>\n<\/code><\/p>\n<p>Now, this assumes that the Xcode6-Beta application was installed into <code>\/Applications<\/code>.  If you are running it off of your desktop or some other location, adjust the path accordingly.  For those unfamiliar with the Unix <code>PATH<\/code> environment variable, check out <a href=\"http:\/\/en.wikipedia.org\/wiki\/PATH_(variable)\">Wikipedia<\/a>.  Let&#8217;s fire up the interactive Swift interpreter!<\/p>\n<p><code><br \/>\n$ swift -repl<br \/>\nWelcome to Swift!  Type :help for assistance.<br \/>\n  1><br \/>\n<\/code><\/p>\n<p>Create an array similar to the examples above:<\/p>\n<p><code><br \/>\n  1> fruit = [\"apples\", \"pears\", \"bananas\"]<br \/>\n<REPL>:1:1: error: use of unresolved identifier 'fruit'<br \/>\nfruit = [\"apples\", \"pears\", \"bananas\"]<br \/>\n^<br \/>\n<\/code><\/p>\n<p>Okay, so we know that we still have to use the Swift syntax for declaring variables.  We can cope.<\/p>\n<p><code><br \/>\n  1> var fruit = [\"apples\", \"pears\", \"bananas\"]<br \/>\nfruit: String[] = size=3 {<br \/>\n  [0] = \"apples\"<br \/>\n  [1] = \"pears\"<br \/>\n  [2] = \"bananas\"<br \/>\n}<br \/>\n<\/code><\/p>\n<p>Note that similar to Ruby&#8217;s interpreter, Swift echoed back what we declared.  That&#8217;s the <b>Print<\/b> part of the <b>REPL<\/b>.<\/p>\n<p>Now iterate over the <code>fruit<\/code>:<\/p>\n<p><code><br \/>\n  2> for f in fruit<br \/>\n<REPL>:3:3: error: expected '{' to start the body of for-each loop<br \/>\n  }<br \/>\n  ^<br \/>\n<\/code><\/p>\n<p>Oops&#8230; we didn&#8217;t end the line with an opening brace.  Swift <i>clearly<\/i> prefers that the <a href=\"https:\/\/www.google.com\/#q=opening+brace+on+same+line\">opening brace be on the same line<\/a> as the <code>for<\/code> keyword, and we happen to prefer that style as well.<\/p>\n<p><code><br \/>\n  5> for f in fruit {<br \/>\n  6.     println(\"One type of fruit is \\(f)\")<br \/>\n  7. }<br \/>\nOne type of fruit is apples<br \/>\nOne type of fruit is pears<br \/>\nOne type of fruit is bananas<br \/>\n<\/code><\/p>\n<p>To quit out of the interpreter you can type <b>CTRL-D<\/b> or just type <code>:q<\/code> and hit Return.<\/p>\n<p>Cool indeed.  But what we&#8217;d really like is to treat Swift as <i>scripting<\/i> language, not just another language we can play with in an interpreter.  We&#8217;ll give that a try by writing a simple Swift script that accepts a list of filenames and then performs the Unix <code>wc<\/code> function.  Those that have dabbled in system administration or report generation know that <code>wc<\/code> prints the number of lines, words, and characters in each of its input files.  <\/p>\n<p>With the use of the <code>-i<\/code> flag to the <code>swift<\/code> executable we can do exactly that.  Along the way we&#8217;ll continue to drive home the point that adopting Swift <i>does not<\/i> mean you have to abandon everything you know about iOS and OS X application development.<\/p>\n<p>To make a point, we won&#8217;t be using the Xcode editor to edit the file <code>wc.swift<\/code>, but rather our favorite Mac version of Emacs known as <a href=\"http:\/\/aquamacs.org\/\">Aquamacs<\/a>.  If you are familiar with Emacs editing modes, there&#8217;s even one for <a href=\"https:\/\/github.com\/chrisbarrett\/swift-mode\">swift<\/a> that we like to use.<\/p>\n<p>The first line of <code>wc.swift<\/code> should be<\/p>\n<p>[objc]<br \/>\nimport Foundation<br \/>\n[\/objc]<\/p>\n<p><i>This<\/i> is the real reason why developing in Swift already feels so robust;  it doesn&#8217;t require abandonment of the core iOS and Mac OS X frameworks.  Bringing in the <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/cocoa\/reference\/foundation\/ObjC_classic\/_index.html\">Foundation Framework<\/a> links in all manner of classes ranging from <code>NSCalendar<\/code> to <code>NSXMLParser<\/code>.  You will certainly almost always want to start your Swift files with <code>import Foundation<\/code>, and it&#8217;s so fundamental that Xcode puts the line in for you when creating a new Swift file.<\/p>\n<p>The next line of code sets up the array of filenames that were (or will be) passed into our application.  <\/p>\n<p>[objc]<br \/>\nlet filenames = Process.arguments<br \/>\n[\/objc]<\/p>\n<p>Now that we have our filenames we&#8217;ll iterate on them and use the fact that Swift <code>String<\/code> gives us access to <code>NSString<\/code> methods to load a string with the contents of that file.  <\/p>\n<p>[objc]<br \/>\nfor filename in filenames {<br \/>\n  var fileContents:String? = String.stringWithContentsOfFile(filename)<br \/>\n[\/objc]<\/p>\n<p>Before we continue let&#8217;s again look at why we had to declare <code>fileContents<\/code> as a <code>String?<\/code>.  The reason is straightforward:  imagine if the <code>stringWithContentsOfFile<\/code> method failed for some reason, then what would <code>fileContents<\/code> hold?  <b>Nothing.<\/b>  <i>That&#8217;s<\/i> why the variable is declared as an optional:  it can either be a <code>String<\/code> or it can be nothing at all.<\/p>\n<p>Since <code>fileContents<\/code> is an optional, any further methods called on it would have to accompanied with an exclamation mark <i>or<\/i> we would have to assign the contents to an unwrapped variable or constant.  Trying to access methods using the optional results in:<\/p>\n<p><code><br \/>\nwc.swift:16:23: error: 'String?' does not have a member named 'componentsSeparatedByCharactersInSet'<br \/>\n    var lines:Array = fileContents.componentsSeparatedByCharactersInSet(newline)<br \/>\n                      ^            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br \/>\n<\/code><\/p>\n<p>So, we have to use exclamation mark:<\/p>\n<p><code><br \/>\n  var lines:Array = fileContents!.componentsSeparatedByCharactersInSet(newline)<br \/>\n<\/code><\/p>\n<p>This is, however, poor form.  If reading the file contents of the string did fail (for example, there was no file there to begin with), accessing it in this manner will crash with a likely <code>fatal error: Can't unwrap Optional.None<\/code>.  Instead we should use <i>optional binding<\/i> to encapsulate our <code>wc<\/code> routine:<\/p>\n<p>[objc]<br \/>\nif let contents = fileContents {<br \/>\n[\/objc]<\/p>\n<p>This line basically says, &#8220;If <code>fileContents<\/code> is a <code>String<\/code> and not the <code>None<\/code> type then assign that string to the constant <code>contents<\/code> and provide that constant to the <i>true branch<\/i> of the <code>if<\/code> statement.&#8221;  That&#8217;s a mouthful.  What this does is allows use to use <code>contents<\/code> without the exclamation mark, because it is already unwrapped and we know that it is a <code>String<\/code>.  <\/p>\n<p>The remaining code is straightforward and illustrates once more that Swift provides access to the Foundation Framework.  Using <code>NSCharacterSet<\/code> and the <code>NSString componentsSeparatedByCharactersInSet<\/code> method we are able to quickly pull apart how many lines and words are in our string.  Tying it all together we get:<\/p>\n<p>[objc]<br \/>\nimport Foundation<\/p>\n<p>let filenames = Process.arguments<\/p>\n<p>for filename in filenames {<\/p>\n<p>    var fileContents:String? = String.stringWithContentsOfFile(filename)<\/p>\n<p>    if let contents = fileContents {<\/p>\n<p>        var whitespace = NSCharacterSet.whitespaceAndNewlineCharacterSet() as NSCharacterSet<br \/>\n        var newline    = NSCharacterSet.newlineCharacterSet() as NSCharacterSet<\/p>\n<p>        var lines:Array = contents.componentsSeparatedByCharactersInSet(newline)<br \/>\n        var words:Array = contents.componentsSeparatedByCharactersInSet(whitespace)<\/p>\n<p>        var numChars = countElements(contents)<br \/>\n        var numLines = lines.count &#8211; 1<br \/>\n        var numWords = words.count &#8211; 1<\/p>\n<p>        println(&quot;\\t\\(numLines)\\t\\(numWords)\\t\\(numChars)\\t\\(filename)&quot;)<br \/>\n    } else {<br \/>\n        println(&quot;wc.swift: \\(filename):  No such file&quot;)<br \/>\n    }<\/p>\n<p>}<br \/>\n[\/objc]<\/p>\n<p>Finally, how to run this!  The <code>swift<\/code> binary provides the <code>-i<\/code> switch for running in <b>immediate mode<\/b>, which is what we want.  So we type <code>swift -i wc.swift<\/code> to run our code and&#8230;<\/p>\n<p><code><br \/>\n$ swift -i wc.swift<br \/>\nwc.swift:5:8: error: cannot load underlying module for 'Foundation'<br \/>\nimport Foundation<br \/>\n       ^<br \/>\n<unknown>:0: note: did you forget to set an SDK using -sdk or SDKROOT?<br \/>\n<unknown>:0: note: use \"-sdk $(xcrun --show-sdk-path --sdk macosx)\" to select the default OS X SDK installed with Xcode<br \/>\n<\/code><\/p>\n<p>Oops.  Remember that your Xcode development environment is capable of compiling applications for all manner of iOS versions as well as Mac OS X.  There <i>are<\/i> differences between the operating systems and versions, so you need to tell <code>swift<\/code> which SDK you&#8217;re going to use (similar to setting your iOS SDK in Xcode).  Thankfully <code>swift<\/code> gives a nice little hint:  <code>\"use -sdk $(xcrun --show-sdk-path --sdk macosx)\" to select the default OS X SDK<\/code>.  We&#8217;ll try that.<\/p>\n<p><code><br \/>\n$ swift -i -sdk $(xcrun --show-sdk-path --sdk macosx) wc.swift<br \/>\nwc.swift: -i:  No such file<br \/>\n\t31\t184\t831\twc.swift<br \/>\nwc.swift: -enable-objc-attr-requires-objc-module:  No such file<br \/>\nwc.swift: -target:  No such file<br \/>\nwc.swift: x86_64-apple-darwin14.0.0:  No such file<br \/>\nwc.swift: -module-name:  No such file<br \/>\nwc.swift: wc:  No such file<br \/>\n<\/code><\/p>\n<p>What the&#8230;  What&#8217;s happening here is the default behavior of <code>Process.arguments<\/code>.  If there are no options presented to the application <code>Process.arguments<\/code> will contain the commandline for <code>swift<\/code>, which is <i>not<\/i> what we want (obviously).  In our example, <code>Process.arguments<\/code> contained <code>[-i, wc.swift, -enable-objc-attr-requires-objc-module, -target, x86_64-apple-darwin14.0.0, -module-name, wc, -sdk, \/Applications\/Xcode.app\/Contents\/Developer\/Platforms\/MacOSX.platform\/Developer\/SDKs\/MacOSX10.9.sdk, -color-diagnostics]<\/code>.<\/p>\n<p>To invoke the script in the intended manner we use the &#8220;dash-dash&#8221; option and <i>then<\/i> provide the filename.  <code>$ swift -i -sdk $(xcrun --show-sdk-path --sdk macosx) wc.swift -- declaration.txt<\/code>:<\/p>\n<pre>\r\n\t6\t35\t210\tdeclaration.txt\r\n<\/pre>\n<p><code>declaration.txt<\/code> contains:<\/p>\n<pre>\r\nWe hold these truths to be self-evident,\r\nthat all men are created equal,\r\nthat they are endowed by their Creator\r\nwith certain unalienable Rights,\r\nthat among these are Life, Liberty\r\nand the pursuit of Happiness.\r\n<\/pre>\n<p>Was writing and executing this as straightforward as Ruby or Python?  No.  But it does illustrate you <i>can<\/i> use Swift as a scripting language on your Mac and iteratively run bits of code without going through the <b>Edit-Compile-Link-Run<\/b> cycle.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Much fanfare accompanied the &#8220;playground&#8221; feature of Xcode 6 that allows developers to write some code and see the effect in realtime. If you have any experience with scripting languages such as Ruby or Python, you recognize this as nothing more than running the interactive language interpreter. With Ruby you type irb at the command [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-336","post","type-post","status-publish","format-standard","hentry","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/336"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=336"}],"version-history":[{"count":14,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/336\/revisions"}],"predecessor-version":[{"id":350,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/336\/revisions\/350"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=336"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=336"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=336"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}