2015-02-08

The Schwartzian Transform (from Perl) in Swift.

I realize that the "Schwartzian Transform" is not the name of algorithm itself but rather the name of the compact idiom in Perl for the expression of the algorithm. Since Swift has all of split(), join(), and map(), I will attempt to not only duplicate the algorithm, but the idiom itself.

As I write this, I am not certain I will succeed. I'm kind of excited. It is like a stage magic show.

I'm going off the 2006 article from Randal's web site.

Let's do the steps all broken down.

let data = "Bob 10\nSue 7\nJane 12\nBill 10\nJim 1\nNancy 8\n"
let lines = split(data, {$0 == "\n"})
let annotatedLines: Array = map(lines, {[$0, split($0, {$0 == " "})[1]]})
let sortedLines = sorted(annotatedLines, {$0[1] < $1[1]})
let cleanLines = map(sortedLines, {$0[0]})
let result: String = join("\n", cleanLines)
println(result)

Here is what it looks like with println() statements in a playground.


And here it is condensed properly to match the compact Perl idiom.

let data = "Bob 10\nSue 7\nJane 12\nBill 10\nJim 1\nNancy 8\n"
let result2 = join("\n",
    map(
        sorted(
            map(
                split(data, {$0 == "\n"}),
                {[$0, split($0, {$0 == " "})[1]]}),
            {$0[1] < $1[1]}),
        {$0[0]}))
println(result2)

And in the playground to prove it works.


Just so you know, as Xcode ran this code in the playground, my MacBook Pro (15-inch, Late 2011) CPU fans kicked in. I'm pretty sure Perl would not cause that to happen while processing the same data set.

Now, you may be thinking to yourself, "But it didn't work! Ten is not less than seven!" Yes, that is an obvious machine collating sequence problem because my version is doing string comparisons and not numeric.

This is where I think I've found a Swift defect. I can do this:


let stuff = "xxx 13"
let num:Int! = split(stuff, {$0==" "})[1].toInt()
println("num = \(num)")

But when I try to tack toInt() inside map() for annotatedLines, I get an error.


So the summary is that the Perl code is easier to read, it probably doesn't cause my CPU fans to engage, and its flexible scalar type is more convenient than the old integer vs string separation.

Up Next: the Orcish Maneuver.

No comments:

Post a Comment