Tuesday 30 September 2014

AVAudioPlayerNode Audio Loop

Well, I think I've finally concluded that AVAudioPlayerNode can't really be used for any sensible audio synthesis or effects in Swift. It's a shame as Swift certainly seems to be up to the job and the processing isn't really even touching the CPU at 3% but despite the seeming promise of the application descriptions given in the WWDC notes, playback in all the modes I've tried seems glitchy even when using extremely long buffers, so it seems that the ScheduleBuffer function is really not useful for anything more than basic trivial sound generation.

So, following the previous posts my last little test to ensure that my generation code itself was not just the problem was to try a loop-back and see how this worked. To do this I created a simple test case which has the default input going into a mixer with it's volume set to zero and then a player also going into the other mixer that is connecting to the output. I have then installed a tap on the input and used that buffer to pump straight into ScheduleBuffer of the player.

Here's the example code:

import Cocoa
import AVFoundation

// Setup engine and node instances
var engine = AVAudioEngine()
var mixer = engine.mainMixerNode

var inputstub = AVAudioMixerNode()
var player = AVAudioPlayerNode()
var input = engine.inputNode
var output = engine.outputNode
var format = input.inputFormatForBus(0)
var error:NSError?

engine.attachNode(inputstub)
engine.attachNode(player)

// Connect nodes
engine.connect(player,to:mixer, format:format)

// Start engine
engine.startAndReturnError(&error)

player.play()

engine.connect(input, to: inputstub, format: format)
engine.connect(inputstub, to: mixer, format: format)
engine.connect(mixer, to: output, format: format)

inputstub.outputVolume = 1.0
mixer.outputVolume = 1.0

let length = 24256

var audioBuffer = AVAudioPCMBuffer(PCMFormat: player.outputFormatForBus(0), 
                                   frameCapacity: UInt32(length))
audioBuffer.frameLength = UInt32(length)

input.installTapOnBus(0, bufferSize:UInt32(length), format: input.outputFormatForBus(0))
{
        (buffer, time) in
        
        var sum:Float = 0
        
        // fill up the buffer with some samples
        for (var i=0; i<length; i++)
        {
            audioBuffer.floatChannelData.memory[i] = 1.0 * buffer.floatChannelData.memory[i]
        }
                          
        player.scheduleBuffer(audioBuffer,atTime:nil,options:.InterruptsAtLoop,
                              completionHandler:nil)        
}


while (true)
{
    NSThread.sleepForTimeInterval(1)
}

You'll want to put headphones on to test this and have the input take an external feed and put this into the headphones so that it does not create an oscillating feedback loop.

Testing this, there is a sense that the loop must be working ok to fill the buffer without too much trouble and the CPU is barely hitting 3% but the audio playback is glitching which becomes more pronounced as the buffer size is reduced (try playing around with length) until values below 1000 or so become too choppy for anything sensible.

I tried scheduleBuffer with various different options, nil and InterruptsAtLoop, neither made much difference. This is a shame as it means that the scheduleBuffer function is just a bit too simplistic in implementation and is not implementing some fairly basic double buffering to transition between two buffers. Hmmm.... will have to look at another way of doing this then and get back to basics.

For information, I'm using two separate buffers as if the buffer in the tap closure is used the memory is not freed and just increases.


AVFoundation audio monitoring - Installing a Tap on a Bus in Swift

Having had disappointing results with the AVAudioPlayerNode so far in Swift I haven't had a chance to return and continue bashing my head against a wall yet to try to get an answer, but today I had a quick chance to try something else that I'd been wanting to do and should certainly be in the scope of what Apple communicated in the WWDC info on the new AVFoundation classes.

If I can't quite work out how to synthesise audio just yet, it will be interesting to see if Swift has the real-timeness to do some audio monitoring and processing, so I wanted to quickly knock up a few lines of code to see if I could read the audio input and see what the rough, averaged 'energy'/volume was as a quick test.

It seemed pretty simple and the code worked without too much trouble, so here it is....

WARNING - turn your speaker off before doing this!!

I've just linked the input through a delay to the output to generate a signal to monitor.

import AVFoundation

// Setup engine and node instances
var engine = AVAudioEngine()
var delay = AVAudioUnitDelay()
var input = engine.inputNode
var output = engine.outputNode
var format = input.inputFormatForBus(0)
var error:NSError?

// Attach FX nodes to engine
engine.attachNode(delay)

// Connect nodes
engine.connect(input, to: delay, format: format)
engine.connect(delay, to: output, format: format)

// Start engine
engine.startAndReturnError(&error)

let length = 256
var audioBuffer = AVAudioPCMBuffer(PCMFormat: input.outputFormatForBus(0), frameCapacity: UInt32(length))
audioBuffer.frameLength = UInt32(length)

input.installTapOnBus(0, bufferSize:UInt32(length), format: input.outputFormatForBus(0), block:
    {
        (buffer, time) in
        
        var sum:Float = 0
        
        // do a quick calc from the buffer values
        for (var i=0; i<length; i++)
        {
            sum += Float(buffer.floatChannelData.memory[i]) * 10_000
        }
        
        println(NSString(format:"%.0f",sum/Float(length)))
})


while (true)
{
    NSThread.sleepForTimeInterval(1)
}

Remember, if you do this in a playground the looping in the playground is not going to work real-time.

hmmm, maybe there is just something really simple that is not working with the generation and I need to go back to it....


Update.... as I just bashed this together this morning, it got the needed result, but I didn't really like that I needed to link the audio to a delay and then the output to get this working. With a  bit more time looking at this it's easy to connect this just with the input as follows.... just use an input connected to a mixer, which is enough as follows:

var mixer = engine.mainMixerNode
var input = engine.inputNode
var format = input.inputFormatForBus(0)
var error:NSError?

// Connect nodes

engine.connect(input, to: mixer, format: format)

mixer.outputVolume = 0

And the rest of the code is the same. The important part here is that the mixer output needs to be zero otherwise it's creating another feedback loop like before.

Friday 26 September 2014

Thom Yorke Bittorrent album (and Stanley Donwood artwork)

Well, not to be outdone and hot on the heels of U2 forced installation into everyone's iTune's library Thom Yorke has released his latest work on Bittorrent to bypass the 'gatekeepers'. Expect this to generate further blog-o-sphere discussion (isn't he one of the gatekeepers?) on from the In-Rainbows 'choose-your-own-pricing'. Looks like we're being treated to a range of new economic approaches, or should I really say 'marketing' by major brand stars as they transition from their 40s into their 50s.....



Here's the accompanying propaganda, erm, 'marketing' statement:

"As an experiment we are using a new version of BitTorrent to distribute a new Thom Yorke record. The new Torrent files have a pay gate to access a bundle of files.. The files can be anything, but in this case is an ‘album’.
"It’s an experiment to see if the mechanics of the system are something that the general public can get its head around … If it works well it could be an effective way of handing some control of internet commerce back to people who are creating the work.
"Enabling those people who make either music, video or any other kind of digital content to sell it themselves. Bypassing the self elected gate-keepers. If it works anyone can do this exactly as we have done. The torrent mechanism does not require any server uploading or hosting costs or ‘cloud’ malarkey. It’s a self-contained embeddable shop front… The network not only carries the traffic, it also hosts the file. The file is in the network. Oh yes and it’s called Tomorrow’s Modern Boxes. Thom Yorke & Nigel Godrich"
Anyway, hype and marketing aside, it's about the music and I'm looking forward to getting my ears onto this.

It's also good to see that Thom is keeping his collaboration with Stanley Donwood going, so this is a music/art project as well. I loved the work on The Eraser as this was classic linocut, which is one of my favourite formats to work with. They've been enigmatically twittering related artwork for some months now...










Wednesday 24 September 2014

Swift ?? ! ? (an excalmation explanation question)

Yesterday's exploration using Swift to access the Pinterest API was interesting and instructive. I glossed over some interesting details to focus on looking at the functional objectives of getting an end result rather than some of the Swift constructs. Today I thought it would be good to just walk through some of the syntax and concepts that were used and I haven't had a chance to note down cohesively.

This is really an opportunity to make a little reference review for myself of some Swift syntax features around Optionals.

So, kicking off, writing anything in Swift using the Cocoa APIs seems to require quite a bit of using quotation and exclamation marks. What's that all about? These are called Optionals and provide a language facility for describing types and handling variables that can have either a value or are 'unset'.  This idea has been around for a long time as 'tri-state' logic in digital circuits. C-sharp has the concept of nullable types built into the language which allow variables to hold a value or null and are represented by a type defintion T? The variable then can be checked against null before using. Swift brings this into the language along with a bunch of other useful features.

One of the usual ways of coming across this concept is with pointers in C++, where an object pointer is typically assumed (or set) to be null until the class is instantiated and set to the object pointer. In this case the pointer can be considered to point to null or the value of an object. Code then checks for null before using the object. Obviously this can only be used with objects in C++, Swift and C-sharp extend the concept of having a null/nil value to any type.  In Swift, these are called optionals and are written as follows:

var myOptional:Int?

This will be implicitly assumed to be the value nil until it is assigned to. Also, when using the variable, it must be checked against to ensure it is non-nil before using. In Swift-speak this is known as unwrapping. There are a few ways of doing this, we'll step thorugh them. Firstly, the obvious way is to check to see if the value is nil or not before using:

if myOptional != nil
{
   // use myOptional
}

Now that we're assured that the optional does indeed contain a value (e.g. it's not nil) the value can be 'unwrapped' using an exclamation mark as follows

// use myOptional
println("the value = \(myOptional!)")

In this case we're using the Swift string interpolation features to put the variable into the string. The syntax of 'implicitly unwrapping' an optional by adding an exclamation mark can be used where we're certain that the variable is non-nil and can safely use it e.g.

var myValue:Int = myOptional!

Another way of doing this is also to define a type that once it has been set will never be given a nil value, it's sort of like defining a const. In this case the exclamation mark is used in the type definition:

let anotherValue:Int! = 2_000

Swift also provides a short-hand way of doing this without explicitly putting an exclamation mark in if and while clauses as follows:

if let myValue = myOptional
{
}

Another way of unwrapping an optional (that I didn't use yesterday) is to use the 'Nil Coalescing Operator' which allows setting either the unwrapped value or an alternative value in the case that the optional value is nil. The Nil Coalescing Operator is written as a double quotation mark and can be used as follows:

var newValue:Int = myOptional ?? 404

In this case if myOptional is nil, then newValue will be set to 404. The Nil Coalescing Operator can be written in terms of the ternary conditional operator as follows:

a ?? b         is equivalent to        a != nil ? a! : b 

So, that explains the ! and ?s, but I think they were used a bit more than that, right? Well spotted, yes! Swift puts this concept in pretty deep. Most of the examples in the JSON code previously were using the concept of Optional Chaining. This is the idea of being able to call and query prorperties, methods and subscripts on optionals that might be nil. Optional Chaining is achieved by placing a question mark after the method, property or subscript, similar to how the exclamation mark is used to implicitly unwrap an optional value.

I haven't got time just now to go through this, but wanted to make sure that I'd referenced it to explain some of the usage of ? in the examples yesterday.

Lastly, the other concept uses extensively yesterday was the optional form of the downcast operator as?. In this case what is happening is that we know the type that the object needs to be downcast to, but we're not sure if the variable is nil or not and want to preserve that typing.





Tuesday 23 September 2014

Pinteresting playing around with Swift and JSON

So after the rather disappointing dead-end using the Pinterest API to download my boards and pinned images I decided to not waste the experience and as the code was relatively simple use this as a springboard to get into using Swift for HTTP requests and see how easy it would be parsing JSON.

I'd had a play around with making some basic GET requests previously and tried out NSURLConnection (Shephertz has a good intro), then noticed the general advice that Apple has switched from using this in Mavericks to the newer NSURLSession API. There are some good online examples of this as well (see Stackoverflow). The Playgrounds feature is yet again proving it's worth in prototyping that these new ideas can easily be explored and the various trial workings put into Playgrounds to reference, explore and come back to.

I did a bit of googling the other day around JSON processing in Swift and was surprised at the number of posts dealing with this and describing it in various shades of 'chewing glass'. There were a lot of 'simple-support' classes, a lot of really clever ideas overloading various operators and using the new Swift features for 'roll-your-own' operators. Given one of the ideas of Swift was for readability to aid understanding I was less than happy with these approaches as it looked like adding a whole new set of custom semantics. So, in my books, maybe a few more lines of code, but if this is easier to understand then all the better. Writing code is easy, it's the reading and understanding bit that takes time.

So, I plunged for the boring, long winded route to just see how easy it would be to walk through the JSON response for asking for the pins from a particular board. See my previous post to take a look at this description.

After navigating through the !s and ?s this turned out to not be too much trouble.

First of all let's get the HTTP request in the bag and take it onwards from there:

import Cocoa

//  allow the asynchronous task to continue, set timeout in console
import XCPlayground
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely:true)

//  this isn't my pinterest board, you'll need to change [hondrou] and [board]
let url = NSURL(string:"https://api.pinterest.com/v3/pidgets/boards/hondrou/board/pins/")
var session = NSURLSession.sharedSession()



var task:NSURLSessionDataTask = session.dataTaskWithURL(url)
{
    (data, response, error) in
    
    if let err = error
    {
        println("Error: \(err)")
    }
    else
    {
        // let's print out what we've got to check the look of the JSON response
        println(NSString(data:data,encoding: NSUTF8StringEncoding))


    }

    // do all the JSON response processing here
}



task.resume()

Nice! This is pretty short and succinct. If you want to see the console output easily, just open up the Assistant Editor.

Things that are worth noting here are that the dataTaskWithURL function has the following prototype:

func dataTaskWithURL(_ urlNSURL,
   completionHandler completionHandler: ((NSData!,
                              NSURLResponse!,
                              NSError!) -> Void)?) -> NSURLSessionDataTask


You'll notice that the second parameter of the function is a completionHandler. As I explored previously (and I'm very thankful to have got this now in my back-pocket) this can either be implemented as a more classic callback function or can be written as a Closure (as it is above). The way it is written above takes advantage of the Swift feature called Trailing Closures.

This is a bit of Swift syntactic simplification that where the last parameter can be expressed as a closure it's possible to write it without putting the expression into the function parameter brackets. So, in the about the completion handler is the part that is written as a closure like this:

{
    (data, response, error) in

    // this is the closure code
}

As this dataTaskWithURL calls out to the completionHandler to execute this please do not forget to include the last task.resume() and remember to keep the playground running indefinitely.

Now for the JSON processing, which looks like this:

    
    var jsonError:NSError?
    
    var json:NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &jsonError) as NSDictionary
        

    if let err = jsonError
    {
        println("Error parsing json: \(err)")
    }
    



    let status:String? = json["status"] as? String

Wow! where did all the questions come from! Just roll with me and we'll tackle this in another post another time. This picks out the status part of the first bit of the JSON response. We can now take a look at parsing through the structure in luddite fashion for the moment.

What I want to do is walk through the structure, collect the description, link url, image url and id for the pin. First of all we can work through the structures like this:

    let data:NSDictionary! = json["data"] as? NSDictionary!
    
    let board:NSDictionary! = data["board"] as? NSDictionary!
    
    let url:String? = board["image_thumbnail_url"] as? String
    
    let pins:NSArray! = data["pins"] as? NSArray!

Now, I want to iterate through the pins, but before doing that it's useful as we'll be in an iteration loop that is a bit more difficult to follow in the playground it's useful to see what the structure of the first element of the array (e.g. the first pin) is like so we can explore that in the playground. This line does the trick:

    let p = (data["pins"] as? NSArray)![0]

It also shows a little yellow warning triangle to tell you that the type is inferred to be AnyObject. We're ok with that as this is just exploratory.

So, using this I dabbled around a bit to make sure I could get the syntax right and then put the loop in.  There is very nice post here that gave me the neat syntax for describing this cleanly:

    for (index,pin) in enumerate(pins)
    {
        // iteration
    }

I really like this after being familiar with the C-sharp 'foreach' concept, this builds on the use of Tuples in Swift nicely (it's like the more clunky KeyValuePair iteration for Dictionary used in C-sharp).

Which I then finished off like this:

    for (index,pin) in enumerate(pins)
    {
        let description:String? = pin["description"] as? String
        let link:String? = pin["link"] as? String
        
        let images:NSDictionary! = pin["images"] as? NSDictionary
        
        let id:String? = pin["id"] as? String
        
        let image237x:String = (images["237x"] as? NSDictionary)!["url"] as String
        
        println("\(index): \(description!), \(id!) \(image237x)")



    }

Nice. I can now list each of my pins, give a description, get the id and show the url to the image (although only the 237x sized image as I explained previously).

I'm quite pleased with this. It was pretty straightforward and easy to explore in a Playground and allowed me to tinker with some more Swift syntax and get a meaningful result. I expect I'll be building on this quite a bit.

Before I hit the sack.... last but not least..... I wanted to actually download those images.

This took a bit longer than I thought, just as I was fighting through getting the correct path to write to, in the end I just let it put the files in the easiest place. I think this might be a Playground security thing that I need to work through another way or just my lack of understanding Mac file-system issues at the moment. Anyway, here it is:

This goes into the loop behind the other functions

        let imgURL: NSURL = NSURL(string: image237x)
        // Download an NSData representation of the image at the URL
        let imgData: NSData = NSData(contentsOfURL: imgURL)
        
        
        let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
        
        var error:NSError?
        imgData.writeToFile("\(documentsPath)/\(id!).jpg", options: .AtomicWrite , error: &error)

        
I'm downloading each of the images into a file that is written as a jpg image using the pin-id as the file name. Now, just would have been good to get them at a useful resolution :-(


Update!
I had a note from Reto Kuepfer on my previous post doing this with C-sharp and he found the answer to getting hold of the original resolution images.

Using the code above, what needs to be done is to swap out the 237x image url with 'originals' instead like this:

        let image237x:String = (images["237x"asNSDictionary)!["url"as String
        let imageO = image237x.stringByReplacingOccurrencesOfString("237x", withString: "originals", options: NSStringCompareOptions.LiteralSearch, range: nil)

Then use imageO in the creation of NSURL.

In revisiting this code, in the intermediate time I have updated to the latest version of xCode, which brings a couple of little changes as they harmonise the API. The following adjustments need to be made:



        let imgURL: NSURL! = NSURL(string: image237x)

and

        let imgData: NSData! = NSData(contentsOfURL: imgURL)

and in the earlier code, the following change:

        let p: AnyObject = (data["pins"asNSArray)![0]

Playing with the Pinterest 'sort-of' API

Yesterday's lunchtime coding gave me the desire to want to download the pins from some of my pinterest boards and be able to store the links and a high-quality version of the images. It's great collecting some of these inspirations - I'm particularly interested in lino-prints and watercolour journals and wanted to put them in a place where I could work with them for some of my own ideas.

So, I did a bit of googling and came across some informative posts. First was a good set of pointers from Ben Wong on StackOverflow which detailed the following openly available services:

https://api.pinterest.com/v3/pidgets/users/[username]/pins/

https://api.pinterest.com/v3/pidgets/boards/[username]/[board_name]/pins/

http://api.pinterest.com/v3/pidgets/pins/info/?pin_ids=521150988102375972

and another inferred one:

https://api.pinterest.com/v3/pidgets/boards/[username]/

which gives a list of a user's boards.

Bashing out a bit of code to call these URLs and get the results wasn't too much trouble. These all return JSON formatted data, so I used some of the code from my previous posting to walk through the responses. In the case of requesting the pins for a particular board the result looks something like this (this isn't actually my data):

The overall envelope details the board and list of pins.....


{
  "status": "success", 
  "code": 0, 
  "host": "ngapi2-485c0b18", 
  "generated_at": "Tue, 23 Sep 2014 13:07:44 +0000", 
  "message": "OK", 
  "data": 
  {
    "pins": 
    [

    ], 
    "user": 
    {
       "about": "", 
       "location": "", 
       "full_name": "hondrou", 
       "follower_count": 13, 
       "image_small_url": "http://passets-ec.pinterest.com/images/user/default_30.png", 
       "pin_count": 969, 
       "id": "482800159961391892", 
       "profile_url": "http://www.pinterest.com/hondrou/"}, 
       "board": 
       {
          "description": "", 
          "url": "/honrdrou/board/", 
          "follower_count": 8, 
          "image_thumbnail_url": "http://media-cache-ak0.pinimg.com/upload/482800091241943111_board_thumbnail_2014-09-13-20-51-23_20940_60.jpg", 
          "pin_count": 166, 
          "id": "482800091241943111",     
          "name": "board"
      }
   }
}

And then for each of the pins:

 {
"attribution": null, 
"description": "descriptive text", 
"pinner": 
 {
 "about": "", 
 "location": "", 
 "full_name": "hondrou", 
 "follower_count": 12, 
 "image_small_url": "http://passets-ec.pinterest.com/images/user/default_30.png",  
 "pin_count": 947, 
 "id": "482800159961391111", 
 "profile_url": "http://www.pinterest.com/hondrou/"}, 
 "repin_count": 0, 
 "dominant_color": "#5d5b36", 
 "like_count": 0, 
 "link": "http://bitacoradefrida.blogspot.com.ar/blahblahblah.html", 
 "images": 
 {
  "237x": 
  {
   "url": "http://media-cache-ak0.pinimg.com/237x/2e/7e/9f/2e7e9f14100b9acb832f047364a37111.jpg", 
   "width": 237, 
   "height": 201
  }
 }, 
 "embed": null, 
 "is_video": false, 
 "id": "48280002252727911"
}

Which is all good and pretty easy to parse using a fragment below:


string json = GetJSON(String.Format("https://api.pinterest.com/v3/pidgets/boards/hondrou/{0}/pins/",board));

JavaScriptSerializer jss = new JavaScriptSerializer();
jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });
DynamicJsonConverter.DynamicJsonObject j = jss.Deserialize(json, typeof(object)) as DynamicJsonConverter.DynamicJsonObject; //dynamic;

dynamic d = jss.Deserialize(json, typeof(object)) as dynamic;

foreach (dynamic b in d.data.pins)
{
    Pin pin = new Pin();
    pin.description = b.description;
    pin.link = b.link;

    dynamic c = b.images["237x"];
    pin.image = b.images["237x"].url;

This was all going very nicely until I took a look at the images that were downloaded. These appear only to reference the 237x size images which were too low quality for what I wanted. Hmmph, shame.

I did quite a bit more googling and didn't get anywhere. So, it's good that Pintrest sort of have some API, but a bit of a shame it is so lacking in functionality.

Unfortunately I couldn't go any further with this as the other bit of work I wanted to do was to download and reference a list of the pins from the pin that I had pinned.. eh? Well, take for example a particular pin I made for a person's journal. Typically they then pin a whole lot of pages and I wanted to follow that in full, but didn't want to pin each on of the individual images.

Unfortunately the API (even getting the information for a particular pin) just references the pinner details as my own details (I know them already, thank you!), not the pinner I pined from. Nor does there seem to be any way of getting the associated pins to that particular pin, so no way to find the other journal pages.

Seems like some of these functions are available via an API and were available previously with V2 of the API but have been blocked and now require an API key. It seems Pintrest are very reluctant to give these out and if my own experience of getting an early account (I was a very early Pinterest adopter) are anything to go by I can believe it. What a shame.

Bare Conductive


Finally after a long time waiting and multiple delays the BareConductive board has arrived. I saw this on Kickstarter just a little too late to get in and so had to be content with one of the first pre-order batches. The packaging and product looks great. Also, according to my eldest daughter it's the first day of Autumn today, so I think it might just be legitimate to start considering getting the soldering iron out again and start on the winter projects when the clocks go back.



And here are some more pictures of what arrived:


I've got a couple of ideas for this board, which I've been thinking about since I ordered it. It's got an Atmel ATMega32U4 is pin-compatible with Arduino boards and most notably as it has the VS1053B audio processing board that I have been playing around with previously integrated along with a MPR121 capacitive touch sensor which should allow some interesting applications. They've also made the battery faff a bit less faff with a LiPo recharging circuit built in and 5V supply.

I love some of the ideas on the BareConductive site, particularly the Boombox Kit.


















Vanta Black

Very interesting interview with Anish Kapoor this morning on Radio4 talking about his work with Vanta Black. Apparently it is the world's blackest material, absorbing all but 0.034% of light falling onto it. Vanta Black is made by a small UK company in Surrey and was only announced in July this year.


Just imagine some of the potential device and artistic applications. Coating the inside of cameras to reduce bouncing light or even possibly displays made from the material allowing increased HDR display.

Thursday 18 September 2014

Swift functions as parameters and getting Closure(s)

Previously I'd mentioned reading about closures helped me as a programmer more familiar with C-sharp to understand some of the design philosophies and put them into context. The function definition syntax in Swift is different from what I was familiar with in C-sharp/Java, but makes it's own logical sense. Continuing the journey this helps to understand what Swift closures are and how they fit into the language.

First of all, let's look at a basic function definition:

func myfunction(paramter1:String, parameter2:Int) -> (result:Int)

All, good. This boils down to the following prototype:

(String, Int) -> (Int)

Which means it is a function that takes a String and an Int and returns an Int.

Function prototypes as inputs
Now consider that this function definition itself can be a description of a parameter or return value as well:

func usingfunction( functionparameter: (String, Int) -> (Int)) -> Int

Which is saying that usingfunction is a function that takes a function as a parameter that has the prototype (String, Int) -> (Int) and returns an Int itself. It could be quite simply used by calling it:

{
  return functionparameter("parameter",1)
}

And calling using function is as simple as:

let result = usingfunction(myfunction)

Function prototypes as outputs
In the neat way in Swift that there is consistency in function input and output definitions the same can also be tried for returning a function from a function:

func returningfunction(Void) -> ( (String, Int) -> (Int) )

Great. We can now use that as follows in the implementation of returning function:

{
  return myfunction
}

And then using returningfunction:

let functionresult = returningfunction()

let result = functionresult("string",1)

Getting Closure
So, with the groundwork of passing and receiving functions and parameters we can now look at closures. Quite simply closures are the blocks of the function code above without naming the actual function. WTF? Let's take a look. In the usingfunction case let's say that rather than passing myfunction into the usingfunction we wanted to just write that code directly there as it might be a simple comparator or other operation. In that case, we define a closure. The syntax for this is as follows:

{ (inputs) -> (outputs) in statements }

Where the closure is everything in and including the curly braces. The tell here is the keyword 'in'. So we could write our previous example as:

let result = usingfunction( { ("some string", 1) -> Int in 
   // write some code here
   return 1 


Where this got a little confusing for me at first is where the syntax can be simplified in the case that some of these parts can be inferred, for example if it is obvious that the result should be returned.  We'll get onto more of that later.