Reputation: 4723
I am trying to use a property root
as default parameter in add
function as below and it is giving me an error:
Cannot use instance member 'root' as a default parameter .
However, when I am using root
in a nested function search
it is working fine.
class Trie {
var root = TrieNode()
func add(value: String, node: TrieNode? = root) { // error
var myNode = node
if myNode == nil {
myNode = root
}
if value.count == 0 {
node?.setEnd()
return
} else if myNode!.keys[String(value.first!)] == nil {
myNode!.keys[String(value.first!)] = TrieNode()
return add(value: String(value.dropFirst()), node: myNode!.keys[String(value.first!)])
} else {
return add(value: String(value.dropFirst()), node: myNode!.keys[String(value.first!)])
}
}
func allWords() -> [String] {
var words = [String]()
func search(node: TrieNode = root, string: String) { // Here it is working fine.
if node.keys.count != 0 {
for key in node.keys.keys {
search(node: node.keys[key]!, string: string+key)
}
if node.isEnd {
words.append(string)
}
} else {
if string.count > 0 {
words.append(string)
}
}
}
search(node: self.root, string: "")
return words
}
}
Can someone tell me why I am not able to use a property as the default parameter?
Upvotes: 5
Views: 4482
Reputation: 114975
Other answers have explained why you can't do it.
I suggest that the simplest way to achieve what you want is via the nil coalescing operator
func add(value: String, node: TrieNode? = nil) { // error
var myNode = node ?? root
guard let key = value.first, keyStr = String(key) else {
myNode.setEnd()
return
}
let updateNode = myNode.keys[keyStr, default: TrieNode()]
return add(value: String(value.dropFirst(), node: updateNode)
}
Upvotes: 4
Reputation: 258117
The reason is in different context visibility, the arguments context of interface function is external in relation to class declaration, so members are not visible, but nested function is declared inside class context, as other function body, so members are visible.
So the solution might be static, as already proposed, but it might have drawbacks (eg. for reference default members), so I recommend to use it only for constants.
The other possible solutions is below
func add(value: String, node: TrieNode?) { // no error
func _add(value: String, node: TrieNode? = root) { // in-context
var myNode = node
if myNode == nil {
myNode = root
}
if value.count == 0 {
node?.setEnd()
return
} else if myNode!.keys[String(value.first!)] == nil {
myNode!.keys[String(value.first!)] = TrieNode()
return add(value: String(value.dropFirst()), node: myNode!.keys[String(value.first!)])
} else {
return add(value: String(value.dropFirst()), node: myNode!.keys[String(value.first!)])
}
}
_add(value: value, node: node)
}
Upvotes: 6