Skip to content

Instantly share code, notes, and snippets.

@lancy
Created March 27, 2016 10:20
Show Gist options
  • Save lancy/7e644a8e50deb68a1aec to your computer and use it in GitHub Desktop.
Save lancy/7e644a8e50deb68a1aec to your computer and use it in GitHub Desktop.
Mutating Generic Enum Issue
enum List<Element> {
case End
indirect case Node(Element, next: List<Element>)
}
enum ListError: ErrorType {
case EndCannotAppendValue
}
extension List {
mutating func append(value: Element) throws -> List {
guard case .Node(let element) = self else { throw ListError.EndCannotAppendValue }
let next = List.Node(value, next: .End)
// Error: Cannot convert value of type 'List<Element>' to expected argument type 'List<_>'
self = List.Node(element, next: next)
return next
}
}
@lancy
Copy link
Author

lancy commented Mar 27, 2016

line 11 is wrong:
Type of element is infer to (Element, next: List<Element>), which make compiler infer self as List<(Element, next: List<Element>)>.

The correct code should be:

    mutating func append(value: Element) throws -> List {
        guard case let .Node(element, next: _) = self else { throw ListError.EndCannotAppendValue }
        let next = List.Node(value, next: .End)
        self = List.Node(element, next: next)
        return next
    }

@lancy
Copy link
Author

lancy commented Mar 27, 2016

Bad news: append function can only return a immutable value, which can't be call in chain.

var head = List.Node(1, next: .End)
// error: cannot use mutating member on immutable value: function call returns immutable value
try! head.append(2).append(2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment