Swift is Open Source

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Picking up from my previous Swift posts; I was wondering if there would be any interest in exploring a few posts around the building of GPU shaders that use Core Image kernels written in GLSL (Open GL Shader Language). The builds will typically involve 2 primary languages: Swift for the Core Image Aspects and C++ for the OpenGL Shader coding. However the GLSL portion of the code will be compatible with both Windows and Linux builds using frameworks like DirectX, OpenCV, ...

A lot of the code (GLSL bits) or principles should however directly translate to Xamarin for iOS and with a bit of work to Android using either Java or Xamarin.

We could for example explore both colour & coordinate manipulation shaders, for example:
  • Color Manipulation : Parallel dithering compatible algorithm with colour downscaling.
  • Color Manipulation : Tint, Solarization, etc.
  • Coordinate: Bulging eyes
  • Coordinate: Picture warp and swirl.

I am however open to anything other requests. Practical uses within your apps for this type of technology is quite diverse, for example: picture modification, view transition, animation, game effects, ...
 
Last edited:

BlindMelonChitlin

Expert Member
Joined
Nov 3, 2015
Messages
1,334
[)roi(];16665183 said:
Some updates since Swift's open sourcing:

It's now the top developed language on Github, ahead of 26 other languages:
Ruby, D, Julia, Rust, Java, Scala, Elixir, Objective-C, C, LiveScript, Haskell, Scheme, CoffeeScript, Nimrod, F#, JavaScript, Racket, Erlang, Go, Dylan, Frege, Dart, Chapel, C#, Red, and C++.

Very surprising considering Microsoft has a big stable of open source project on Github, to name a few: .NET (in 2014), Visual F#, and more recently Visual Studio Code (Cross platform IDE).

Alternative IDEs to Apple's Xcode:
1. http://www.elementscompiler.com/elements/silver/
2. https://www.jetbrains.com/objc/download/

Eclipse support is work in progress.

As for Linux IDE support, it's a toss up between who will be first Jetbrains or Eclipse (both have current Linux IDEs)
Until then your probably better off coding on either OS X or Windows or using something like Gedit or VIM on Linux; a few swift plugins for vim are available for download from Github.

Languages? Frameworks? Same diffs?
As for being the 'top developed language' on GITHub... what is that based on?
http://githut.info/

Untitled.jpg
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
[)roi(] are you using Xamarin for iOS?

On the occasion (depends on the client); it's not my first goto; that used to be Objective-C for iOS, today it's mostly Swift.

That being said I'm quite comfortable coding in C# and Xamarin.
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Belated status update on Swift 2.2 and the roadmap for Swift 3.0

Swift 2.2 is a minor language release that is mostly source-compatible with Swift 2.1.
It contains the following language changes that went through the Swift’s evolution process:
  • SE-0001: Allow (most) keywords as argument labels
  • SE-0015: Tuple comparison operators
  • SE-0014: Constraining AnySequence.init
  • SE-0011: Replace typealias keyword with associatedtype for associated type declarations
  • SE-0021: Naming Functions with Argument Labels
  • SE-0022: Referencing the Objective-C selector of a method
  • SE-0020: Swift Language Version Build Configuration
https://swift.org/blog/swift-2-2-released/
https://swift.org/blog/swift-2-2-new-features/

Swift 3.0 Goals
The primary goal of 3.0 is to stabilize the binary interface of the language and standard library. The focus is to refine the language to provide better overall consistency in feel and implementation. Swift 3.0 will contain a lot source-breaking changes from Swift 2.x; a source code update tool is planned to assist in migrating 2.x code to 3.0.
https://github.com/apple/swift-evolution/blob/master/README.md

Full list of evolution proposals (current, future and in discussion): https://github.com/apple/swift-evolution/tree/master/proposals

Project Website: https://swift.org
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Google, Facebook and Uber - possible adoption of Swift

About the time Swift was going open source, representatives for three major brands — Google, Facebook and Uber — were at a meeting in London discussing the new language. Sources tell The Next Web that Google is considering making Swift a “first class” language for Android, while Facebook and Uber are also looking to make Swift more central to their operations.
http://thenextweb.com/dd/2016/04/07/google-facebook-uber-swift/
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Swift Port to Android has been merged
The huge github PR porting Swift to Android has been finally merged. Most of the work was done by Brian Gesiak from Facebook, his twitter handle is @modocache if you want to keep abreast of the PR, or to ask questions, etc.

For details of the C++ changes, here's the full PR:
https://github.com/apple/swift/pull/1442
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Swift London talks are being live streamed ATM

Swift London talks are being live streamed ATM (guess better later the never). You've missed Green Knight's talk, but honestly you'll thank me for that (that was the boring part)

TALKS

TALK #1: Autolayout, with Green Knight
The trials and travails of Autolayout in Swift; a story of struggle and redemption, retold for your edification.
Green Knight is a freelance developer and Swift London regular.We’ve benefitted from her travails before, and we’re very glad to welcome her back! Twitter: @green_knight

LIGHTNING TALK: Writing Swifty APIs, live coding with Daniel Tomlinson
Daniel hails from England, but is currently embracing jet lag as a way of life. They co-organize NSLondon and ran Fruitconf. They have been building things for Apple platforms for 8 years and currently works at Ride, as well as on a variety of open source libraries and tools. Twitter: @dantoml

If you’d like to give a lightning talk, please get in touch: [masked]

TALK #2: Introduction to Swift Intermediate Language, with Alex Blewitt
Alex will present the Swift Intermediate Language (SIL), and show how source code is compiled through SIL into machine executables. He’ll look at some of the optimisations that can occur with the Swift compiler, and what effect they have on the generated output. This will be demonstrated using Swift 2 and the SIL Inspector, a small utility that wraps the output of the standard Swift command line tools.

Dr Alex Blewitt cut his teeth programming object-oriented systems using NeXTstep and Objective-C over 20 years ago. He migrated to OS X with the release of 10.0 and has been using it ever since. More recently, he has published the second edition of Swift Essentials, which updates the book from its original release in 2014 to the latest version of Swift. He can be found on Twitter @albue, and if the weather’s nice, you may spot him in the sky, flying near Cranfield airport.

From Twitter, here are the approximate times for talks:
8:45pm Building APIs in Swift
8pm Swift Intermediate Language (SIL) -- FYI this the LLVM bridging language i.e. Swift gets turned into SIL and SIL get turned in the executable. If you're looking for reasons why SIL exist in the first place the I suggest watching the presentation done at the LLVM developer's meeting in San Francisco late last year.

Ps. appears they're running a bit late with the 8:45 API talk.
API talk just about to begin: 8:53pm

Here's Daniel github covering this quick talk about building Rest APIs in Swift:
Swift SIL talk is up underway (9:14pm)... will post links to this talks at the end. Here's some links that cover most of Dr Alex Blewitt talk:

Swift London has just tweeted that videos of all the talks will be published on youtube, you can look for those here: https://www.youtube.com/channel/UC5ypB3f_gdQm2qJ4gmjYkJg
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Swift 3.0 Release Process

Swift 3.0 is a major release that is not source-compatible with Swift 2.2. It contains fundamental changes to the language and Swift Standard Library. A comprehensive list of implemented changes for Swift 3.0 can be found on the Swift evolution site.

Swift 3.0 is also the first release to include the Swift Package Manager. While the Swift Package Manager is still early in its development, it supports the development and distribution of cross-platform Swift packages. The Swift Package Manager will be available on both Darwin and Linux.

For Linux, Swift 3 will also be the first release to contain the Swift Core Libraries.

Swift 3.0 is expected to be released sometime in late 2016. In addition to its Swift.org release, Swift 3.0 will ship in a future version of Xcode.

Schedule
The first developer preview branch swift-3.0-preview-1-branch will be created from master on May 12. It will be released 4-6 weeks later.

The date for creating the last developer preview branch — swift-3.0-branch — has not yet been established. When that date is determined the plan will be communicated both on swift-dev and by updating this post.

https://swift.org/blog/swift-3-0-release-process/
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Binary Trees

Binary Trees

In the following thread "Whiteboardcoding in software developer interviews" the subject of binary trees came up when quoting the example of WB interviews as it had related to Max Howell, more specifically related to these two tweets:

"Google: 90% of our engineers use the software you wrote (Homebrew), but you can't invert a binary tree on a whiteboard so **** off."

cguy posted the following in this thread:
cguy said:
I looked up the problem statement for "inverting a binary tree" - it seems as though this means: reflect the tree such that it is the mirror image (i.e., for each level the nodes read left to right should read right to left). If this is indeed the problem statement (and please, correct me if I'm wrong!), and someone got this wrong or regards this as special knowledge/"a trick", especially during an interactive interview, I would also disqualify them - it shows a total inability to think about algorithms.
This statement bugged me a little, primarily because it sounded far too easy (which I'll demonstrate in code later). Would a seasoned programmer really struggle to swap left/right node values; doubtful, hence I filed it away as something that needed clarification. First thought I'd have to PM Max to ask for clarification, but apparently it was easier than that: it has already been asked and answered.

When Max was asked to clarify what this implied, he answered as follows:
"@rogerdai16 to min-max the tree, ascending to descending."

Unfortunately that's still not very clear, the confusion is related to these three parts: "invert a binary tree", "min-max the tree" and finally "ascending to descending"; the first one seems to imply we are talking about turning something around e.g. flipping it horizontally or vertically, whereas "min-max the tree" seems to imply a more specialized use of binary trees e.g. double ended priority queues (deques), and finally "ascending to descending" is a common term for sort order e.g. largest to smallest.

Min-max double ended queues doesn't quite gel well with then invert bit; whereas sorting data as one would implement in a standard binary search tree model with or without tree balancing appears to be closer match? ¯\_(ツ)_/¯

Unfortunately its still not 100% clear, so for this article, I'm going demonstrate code for the following:
  1. Standard Binary Tree structure and populate it with some test data
  2. Create output routines to help with representation of binary tree, because without an easy to comprehend representation, you might not easily see what happened / changed.
  3. Create a function to horizontally flip the data (and hopefully get you to agree that this was probably far too simplistic to have been what Google had asked in Max's WB interview)
I have built code examples for points 1 to 3, both as an object and as a value type:
  • Object type structures are the domain of Object Oriented Programming (OOP).
  • Value types are the domain of Functional Programming (FP).
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Binary Trees - Basic Structure

Overview
A binary tree is a tree data structure in which each node has a maximum of two children.
192px-Binary_tree.svg.png

HOW IT WORKS
A binary tree is comprised of a value and two indicators. The value represents the data you would like to store, such as a string or scalar value (i.e. comparable values). Typically represented with pointers, the indicators store the location (also called the address) of its two children.

Now for the code:
Object code:
Code:
public class Node<T: Comparable>
{
  let value: T
  var left: Node?
  var right: Node?
  
  init(left: Node?, value: T, right: Node?)
  {
    self.left = left
    self.value = value
    self.right = right
  }
}

Functional code:
Code:
public indirect enum Tree<T: Comparable> {
  case Node(left: Tree<T>, value: T, right: Tree<T>)
  case Empty
}

In both cases we've defined two children properties, as the left and right Node, and also a value property.
  • In the case of the Object Class, both the left & right Node(s) end with a ? meaning these are optional properties i.e. both of these can either contain values or be nil (without this the values would be required).
  • The functional definition is defined as two enum cases; 1 is a Node containing a tuple of 3 values: left node, value and right node. The Empty case is the equivalent of the nil in the Object type.
Note: The key difference between these two types is mutability:
  • Object type is mutable
  • Value type is immutable. Although enums in Swift are not like other languages; they are quite full featured: initialisers(constructors), functions, etc...
What this means in general terms is not that much, however the value types are far simpler when it comes t, for example: multi-threading, because the values cannot be mutated, i.e. we avoid the complexity of synchronisation, locking, etc. re value types are inherently thread safe. Anyway the subject of Functional versus OOP is a far too wide subject to cover here, for more information I suggest you start with these basic tutorials:
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Binary Trees - Loading data and Representation

Here's an example of loading data, using this data sample
Screen Shot 2016-05-11 at 10.32.07 AM.png

Object code:
Code:
let referenceTree = Node(
  left: Node(
    left: Node(
      left: Node(left: nil, value: 19, right: nil),
      value: 44,
      right: Node(left: nil, value: 76, right: nil)),
    value: 9,
    right: Node(
      left: Node(left: nil, value: 13, right: nil),
      value: 86,
      right: Node(left: nil, value: 100, right: nil))),
  value: 3,
  right: Node(
    left: Node(left: nil, value: 15, right: nil),
    value: 20,
    right: Node(left: nil, value: 7, right: nil))
)

Value code:
Code:
let valueTree = Tree.Node(
  left: .Node(
    left: .Node(
      left: .Node(left: .Empty, value: 19, right: .Empty),
      value: 44,
      right: .Node(left: .Empty, value: 76, right: .Empty)),
    value: 9,
    right: .Node(
      left: .Node(left: .Empty, value: 13, right: .Empty),
      value: 86,
      right: .Node(left: .Empty, value: 100, right: .Empty))
  ),
  value: 3,
  right: .Node(
    left: .Node(left: .Empty, value: 15, right: .Empty),
    value: 20,
    right: .Node(left: .Empty, value: 7, right: .Empty))
)

Representation
Representing dynamic abstract data can be a challenge, quite often we represent data in structure formats similar to JSON, XML, etc. but as I will show a flat format is not always the best way to visualise tree data, here's the code for the flat representation:
Object code:
Code:
extension Node: CustomStringConvertible
{
  public var description: String
  {
    return left != nil && right != nil ?
      "\(value) => (left: \(left!), right: \(right!))" :
      left != nil && right == nil ?
        "\(value) => (left: \(left!), right:)" :
      left == nil && right != nil ?
        "\(value) => (left:, right: \(right!))" :
      "\(value)"
  }
}
Value code:
Code:
extension Tree: CustomStringConvertible {
  public var description: String {
    switch self {
    case let .Node(left, value, right):
      return "\(value)" + (left.count > 0 || right.count > 0 ?
        " => (" : "") + (left.count > 0 ?
          "left: " + left.description + (right.count > 0 ?
            ", " : ")") : "") + (right.count > 0 ?
              "right: " + right.description + ")" : "")
    case .Empty:
      return ""
    }
  }
}
Here is an example of the output from these functions (different code, same output):
Screen Shot 2016-05-11 at 10.37.36 AM.png
I didn't think this was good enough so I decided to see if I could textually create something that more closely visualised a tree, so staying in the console I threw together this code:
Object code:
Code:
extension Node
{
  private var spread: Int { return 5 }
  private var filler: String { return " "}
  private var vertical: String { return filler + "|" + filler.dup(spread - 2) }
  private var horizontal: String { return filler.dup(2) + filler.dup(spread - 2) }
  private var link: String { return filler + "●" + "─".dup(spread - 1) }
  
  public func draw()
  {
    right?.draw("", horizontal, vertical)
    print("\u{001b}[38;5;15m\(value)\u{001b}[0m")
    left?.draw("", vertical, horizontal)
  }
  
  private func draw(fill: String, _ fillLeft: String, _ fillRight: String)
  {
    right?.draw(fillLeft, fillLeft + horizontal, fillLeft + vertical)
    print("\u{001b}[38;5;236m" + fill + link + "\u{001b}[38;5;15m\(value)\u{001b}[0m")
    left?.draw(fillRight, fillRight + vertical, fillRight + horizontal)
  }
}
Value code:
Code:
extension Tree
{
  private var spread: Int { return 5 }
  private var filler: String { return " "}
  private var vertical: String { return filler + "|" + filler.dup(spread - 2) }
  private var horizontal: String { return filler.dup(2) + filler.dup(spread - 2) }
  private var link: String { return filler + "●" + "─".dup(spread - 1) }
  
  public func draw()
  {
    switch self
    {
    case let .Node(left, value, right):
      right.draw("", horizontal, vertical)
      print("\u{001b}[38;5;15m\(value)\u{001b}[0m")
      left.draw("", vertical, horizontal)
    case .Empty:
      print("", terminator: "")
    }
  }
  
  private func draw(fill: String, _ fillLeft: String, _ fillRight: String)
  {
    switch self
    {
    case let .Node(left, value, right):
      right.draw(fillLeft, fillLeft + horizontal, fillLeft + vertical)
      print("\u{001b}[38;5;236m" + fill + link + "\u{001b}[38;5;15m\(value)\u{001b}[0m")
      left.draw(fillRight, fillRight + vertical, fillRight + horizontal)
    case .Empty:
      print("", terminator: "")
    }
  }
}
Here's the output from this; which even though it's represented on it's side is still I think far easier to visualise than the flat version:
Screen Shot 2016-05-11 at 10.44.04 AM.png
 

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Binary Trees - Flipping Nodes

Horizontal Flipping of Nodes
As explained in the introduction, I thought the notion that WB implied flipping left/right nodes was improbable because it's just too simple; well... let me show you how this is done in code, so you can decide for yourself.
Object code:
Code:
extension Node
{
  public func deepCopyFlipNodes() -> Node<T>
  {
    return Node(
      left: right?.deepCopyFlipNodes(),
      value: value,
      right: left?.deepCopyFlipNodes())
  }
}
Value code:
Code:
extension Tree
{
  public func deepCopyFlipNodes() -> Tree<T>
  {
    switch self
    {
    case let .Node(left, value, right):
      return Tree.Node(
        left: right.deepCopyFlipNodes(),
        value: value,
        right: left.deepCopyFlipNodes())
    case .Empty:
      return .Empty
    }
  }
}
Printing:
Here's how we ask Swift to print the normal representation, and then how we ask it to flip horizontally and print.
Object code:
Code:
referenceTree.draw() // Normal
referenceTree.deepCopyFlipNodes().draw() // Left/ Right nodes are flipped horizontally
Value code:
Code:
valueTree.draw() // Normal
valueTree.deepCopyFlipNodes().draw() // Left/ Right nodes are flipped horizontally
As you can see the function is quite simple, plus to avoid any unintended mutation I decided to perform a deep copy and deliver a new Object in the case of the OOP code; with value code there is no option for mutability.
Before / After:
Hopefully you agree it does flip the left/right nodes.
Screen Shot 2016-05-11 at 10.57.58 AM.png

Closing
Anyway that's the end of this article. I am still considering whether to do a slightly more advanced follow on to cover some of the more useful implementations of Binary Trees:
1. Binary Search Trees.
2. Tree Balancing.
3. Min-Max Double Ended Priority Queues (Deques) using a binary tree.
In the mean time you can read up about these by clicking on the links tied to the above points.
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Dynamic vs. Static

In the last few week Swift discussions have centered around arguing the tenets of Dynamic (Objective-C) languages vs. Static(Swift) languages. whilst its been an ongoing topic, it pretty much started up again after Uncle Bob's recent article titled: "Type Wars", in which he argues that dynamic languages will win in the long run and that we don't need a language to enforce type "safety" when you can easily ensure full test coverage.

It's not a new topic; the dynamic supporters have been arguing for more dynamic functionality in Swift since it's inception, arguing that like Java and C#, the lack of dynamic support will result in a lot of tedious boilerplate code or the need to build elaborate harnesses for dynamic functionality like: observer pattern / KVOs around UI IDE design.

Not everyone is naturally convinced and many argue that the current integration between the Cocoa frameworks, and Objective-C mean that we don't have to rush to tag on Dynamicism functionality, moreover that we shouldn't as those needing it can always resort to using NSObject types in Swift and/or linking Objective-C dynamic code to Swift.

Here's a more detailed summary of the overall discussions.

Apple's Swift Language designers have stated that whilst Swift has a strong leaning towards functional style programming, it isn't a strict FP language like Haskell, and is a bit of a hybrid -- to demonstrate they shared the following code today:
Code:
prefix operator * {}

/// Force-cast an Any to the type demanded by static context.
prefix func *<T>(x: Any) -> T {
  return x as! T
}

var x: Any = 2
1 + *x             // returns 3
x = "world"
"hello " + *x    // returns "hello world"

infix operator => {}

func =><T, U, V>(myself: Any, method: T -> U -> V) -> U -> V {
  return method(myself as! T)
}

(x=>String.hasPrefix)("wor")  // returns true
In summary the Swift Any type is being used like Id in Objective-C to avoid static assignment of a fixed type to the variable x; then the custom asterisk(*) operator is used to "dynamically" specify or in this case infer the type, firstly as an Integer and then as String. Finally another custom operator (=>) is used with generic type currying to demonstrate dynamic method dispatch on Any type (Id equivalent).

For those familiar with Swift, you've probably picked up on the forced casts "as! T"; and like Objective-C it's par for the course with Dynamicism.

This is only a small example, and much still needs to be done to bridge the gap, but at least it opens up possibilities.
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Server Side Swift vs. The Other Guys — 1: Input

What makes Swift different than the other popular web frameworks that exist today? Does Swift work well as a server-side language? That’s what this series will attempt to answer. We’ll compare Vapor, a web framework written in Swift, to popular frameworks written in other languages.
This first post will cover input, i.e. request data. Fetching input from a request, ensuring it is the correct type, and most importantly, not crashing. These are common tasks that most web developers deal with daily. All of the frameworks have their own unique way of doing these tasks–Let’s see how they contrast.
The Frameworks
  • Vapor (Swift)
  • Ruby on Rails (Ruby)
  • Laravel (PHP)
  • Express (JavaScript)
  • Django (Python)
  • Spring (Java)

The Test
The test consists of parsing the following JSON input and fetching the 2nd user’s identifier as an integer.
Code:
{
    "name": "Test",
    "users": [
        { "id": 1337, "email": "foo@gmail.com" },
        { "id": 42, "email": "bar@gmail.com" },
        { "id": 500, "email": "baz@gmail.com" },
    ]
}
The integer should then be returned as the following JSON response.
Code:
{
    "second_user_id": 42
}
If the data is invalid, a 400 response should be returned.

Aside
I have only developed server-side software using Swift, JavaScript, and PHP before this test. For the rest of the frameworks, it was my first attempt, and it took a lot of Googling around.

Conclusion
It’s clear that something simple like reading and responding JSON could be made better in a lot of the popular web frameworks out there. The ability to access nested request data easily and without worrying about crashes is essential to every day web development. Swift makes some of these basic, repetitive tasks more concise, expressive, and safe. It’s also a lot faster.
image.png

The full article can be fouhd here:

Check out Vapor’s website, GitHub, and Twitter.

Note:
  • This is part 1 in a series on this topic. The next “Server Side Swift vs. The Other Guys” will cover installation and setup times.
  • Vapor is currently supported on iOS, OSX and Ubuntu.
  • Review the comments; covers discrepancies and suggested improvements with code & testing methodology.
  • IBM has also released a Swift Web Framework and HTTP Server called Kitura on OSX and Ubuntu, details on this can be found here: https://github.com/IBM-Swift/Kitura
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Waiting to see what happens at wwdc
Same here. Unfortunately wasn't lucky to win the WWDC ticket lotto, hopefully next year. Doubt too many surprises re Swift though -- I'm hoping for a lot around Xcode.

What specifically are you hoping for?

As to the Swift's future.
Swift version 3 target is now clear; ABI and Generics had to be cut, both topics were just too large and important to be rush into V3 + most of this year was needed to stabilise Swift's overall syntax incl. syntactically simplify tie-ins to Foundation and Cocoa. ABI is probably the biggest disappointment re it still either hinders adoption or at the very least make's it difficult for projects utilising many frameworks.

Generics were just too large a topic to be wrapped up this year + it's needed for ABI. Not sure if you seen the overall target for generics? Really interesting stuff, for example:
Also recently seen:
  • A git commit related to supporting Window PE/COFF (i.e. Windows EXEs), so native Swift on Windows shouldn't be too far off, & hopefully MS link it up with their WinObjc work.
  • Swift built Android apps + games running on device.
 
Last edited:

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Perfect example of an ineffective use of code

During one of the interactions around WWDC related to Swift Performance, an example was put forward as an good example of ineffective use of Swift code.

The article's title was inaptly named:
The article was related to solving the 4th Euler problem, the one about:
  • Finding the largest palindrome made from the product of two 3-digit numbers
The conclusion reached in this article was that Swift was a lot slower than Python & Typescript, because his results were as follows:
  • Python - 0.33 seconds
  • Typescript - 0.85 seconds
  • Swift - 22 seconds
Problem is like anything, the deliverable is only as good as the skill of the artisan and/or their understanding.

Here's his Python code for this:
Code:
answer = 0
for i in xrange(999, 100, -1):
  for j in xrange(i, 100, -1):
    k = i * j
    s = str(k)
    if s == s[::-1] and k > answer:      
      answer = k

print answer
This based on his measurements, took 0.33 seconds to complete.

... and here's his Swift code for this:
Code:
var answer = 0
var k = 0
var s = ""
for i in (100...999).reverse() {
  for j in (100...i).reverse() {
    k = i * j
    s = String(k)
    if s == String(s.characters.reverse()) && k > answer {
      answer = k
    }
  }
}

print(answer)
The Swift version above, again based on his measurements, took 22 seconds to complete. OMG :sick:

So what's the problem with the Swift code?
Well quite a few things weren't even code related.
  • Firstly he used Xcode's Swift Playground to run this "Performance Test"
  • Secondly he didn't apply any compiler optimisation (see picture below for the settings that should have been applied)
Screen Shot 2016-06-20 at 8.28.23 AM.png

Not changing anything, exception applying the compiler optimisations, dropped the result from 22 seconds to ~3.8 seconds.

Let's now review the code:
Ok, biggest issue is that he chose to use Swift Strings inside a loop to do a simple reverse comparison. We should ask why he chose to use such a complex type for such a simple task. Swift Strings are very powerful, but with that comes a very costly setup and teardown -- re its by design strongly tied to the heap.

He should rather have considered alternatives that stayed on the stack, specifically avoiding the heap if performance was the ultimate goal. Any of the following examples would have minimised or avoided the heap entirely:
  • Convert to UTF8
  • Use C Strings (far closer to the behaviour of python & its performance)
  • Use modulus and Integer Array
  • Use arithmetic routines
I chose the 4th approach i.e. believing the entire problem could be solved with some simple arithmetic. Success!:
  • To find the largest palindrome made from the product of two 3-digit numbers: 0.5ms
  • To find the largest palindrome made from the product of two 4-digit numbers: 63ms

UPDATE:
I decided to include an example that shows an approach with Swift String that is faster than his version, and to hopefully better highlight the problem with his code.
Code:
func isPalindrome(v: Int) -> Bool
{
  let utf8 = String(v).utf8.map {$0.hashValue}
  let mid = utf8.count / 2
  for i in 0..<mid
  {
    if utf8[i] != utf8[utf8.count - 1 - i]
    {
      return false
    }
  }
  return true
}

var answer = 0
var k = 0
var s = ""
for i in (100...999).reverse()
{
  for j in (100...i).reverse()
  {
    k = i * j
    if isPalindrome(k) && k > answer
    {
      answer = k
    }
  }
}
  
print(answer)
As you should hopefully see the major change is that I've created an isPalindrome function, which works by comparing the UTF8 hash values of characters at the start and end, progressively moving inwards until the midpoint.
Just this simple change has dropped the result from ~3.8 seconds to ~270ms i.e. faster than the Python and we're using String is a far more similar way to the Python code..

If you're still confused as to why his code was so much worse? Here's a few pointers to help:
  • He uses String(...) initialisation twice, i.e. memory is malloc'd and released twice to perform a single number check.
  • He also does a costly conversion from String to Character (+1 malloc), reverses (+1 malloc) and then back to String.
In conclusion:
I'm not advising you to specifically avoid Swift Strings, but rather to reason about when a particular type is most appropriate for the job at hand. Clearly for something as simple as this Euler problem, you should be looking elsewhere, especially if speed of execution is your goal.
Lastly, his conclusion that Swift was slow, was due to a simple lack of understanding.

If you're interested in understanding of how to optimise your Swift code, then I suggest you start with some of the WWDC videos covering this:

Ps.
I've specifically chosen not to share my code, in the event you wanted to attempt this problem for yourself.
If however you'd like a copy of my code, just send me a PM.
 
Last edited:
Top