Skip to content

Instantly share code, notes, and snippets.

@rnapier
Last active August 29, 2015 14:04
Show Gist options
  • Save rnapier/8eda179689d9d61c2bfb to your computer and use it in GitHub Desktop.
Save rnapier/8eda179689d9d61c2bfb to your computer and use it in GitHub Desktop.
And autoclosure saves(?) the day for generic recursive enums
// Creating a generic recursive data structure with autoclosure. (READ ALL NOTES; THIS MAY NOT DO WHAT YOU WANT.)
// Closures are reference types, so the size is known (? I think ?)
// Note that this is just because of unimplemented features in the compiler in Beta5
// There's no reason to think this is a long-term requirement.
// IMPORTANT: the closure will run every time you access this value, so if that has
// side effects, this won't work. It's only possible on pure value types.
// But the fact that this works as expected is actually kind of incredible.
// Think about what is required for it to work out the type for NestedList.Elem("first").
// Yet Xcode still has no idea where to put the }.
enum NestedList<A> {
case Elem(@autoclosure ()->A) // <--- The magic
case List([NestedList])
var description: String {
switch self {
case let Elem(x): return reflect(x()).summary
case let List(list): return "[" + join(", ", list.map{ $0.description }) + "]"
}
}
}
let first = NestedList.Elem("first")
let second = NestedList.Elem("second")
let list = NestedList.List([first, second])
let outerlist = NestedList.List([first, list])
println(first.description)
println(list.description)
println(outerlist.description)
// I (correctly) won't compile because of type mismatch
// let bad = NestedList.List([first, NestedList.Elem(2)])
// For more fun, we can replace the array with a varadic,
// but notice how it becomes a tuple of an array rather than an array (https://devforums.apple.com/thread/239744)
enum NestedList {
case Elem(String)
case List(NestedList...) // <===
var description: String {
switch self {
case let Elem(text): return text
case let List(list): return "[" + join(", ", list.0.map{ $0.description }) + "]"
}
}
}
let first = NestedList.Elem("first")
let second = NestedList.Elem("second")
let list = NestedList.List(first, second) // <=== no more []
let outerlist = NestedList.List(first, list)
first.description
list.description
outerlist.description
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment