Skip to content

Instantly share code, notes, and snippets.

@benlings
Created May 30, 2015 22:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benlings/b52843a85633044a4411 to your computer and use it in GitHub Desktop.
Save benlings/b52843a85633044a4411 to your computer and use it in GitHub Desktop.
Object-Oriented Programming in Functional Programming in Swift - now with Open Recursion
// Based on http://www.sicpers.info/2015/05/object-oriented-programming-in-functional-programming-in-swift/
// Each method now has an extra `self` parameter
struct List<T> {
let count: List<T> -> () -> Int
let at: List<T> -> Int -> T?
}
// Helper functions to pass self to the self parameter
func lCount<T>(l: List<T>) -> Int {
return l.count(l)()
}
func lAt<T>(l: List<T>)(_ idx: Int) -> T? {
return l.at(l)(idx)
}
func EmptyList<T>() -> List<T>
{
return List(
count: { s in { 0 } },
at: { s in { _ in nil } }
)
}
func LinkedList<T>(head:T, tail:List<T>) -> List<T>
{
return List(
count: { s in { 1 + lCount(tail) } },
at: { s in { index in (index == 0) ? head : lAt(tail)(index - 1) } }
)
}
// Step Six: Inherit from objects
// Changed references to super's methods to be super's type because otherwise
// we can't call super's methods on ourself
struct ListWithDescription<T> {
let list: List<T>
let describe: ListWithDescription<T> -> () -> String
}
// Overrides of helper functions for the subclass
func lAt<T>(l: ListWithDescription<T>) -> Int -> T? {
return lAt(l.list)
}
func lCount<T>(l: ListWithDescription<T>) -> Int {
return lCount(l.list)
}
// Helper function for new subclass method
func lDescribe<T>(l: ListWithDescription<T>) -> String {
return l.describe(l)()
}
func ListOfStringsWithDescription(proto: List<String>) ->
ListWithDescription<String>
{
let describe: ListWithDescription<String> -> () -> String = { s in
{
var output = ""
for i in 0..<lCount(s) {
output = output.stringByAppendingString(lAt(s)(i)!)
output = output.stringByAppendingString(" ")
}
return
output.stringByTrimmingCharactersInSet(
NSCharacterSet.whitespaceCharacterSet()
)
}
}
// I've in-lined SubtypeListByAddingDescription
return ListWithDescription<String>(
list: proto,
describe: describe
)
}
let awesomeGreeting =
ListOfStringsWithDescription(LinkedList("Hello,",
LinkedList("World",
EmptyList())))
lAt(awesomeGreeting) //"World"
lDescribe(awesomeGreeting) //"Hello, World"
// Step 7 override base class method that subclass uses
// Override `at` method
func ListOfStringWithDescriptionWithPrefix(proto: ListWithDescription<String>, prefix: String) -> ListWithDescription<String>
{
return ListWithDescription<String>(
list: List<String>(
count: proto.list.count,
at: { s in
{ idx in lAt(proto)(idx).map { "\(prefix) \($0)" } }
}
),
describe: proto.describe
)
}
// `describe` method uses overriden `at` method
let superAwesomeGreeting = ListOfStringWithDescriptionWithPrefix(awesomeGreeting, "yo")
lDescribe(superAwesomeGreeting) // "yo Hello, yo World"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment