I defined a method treeNode
to create a node, and which can have children nodes. The simplified code is:
def treeNode(text:String) (children: => Any) {
val b = new TreeNode(text)
children
}
When I use this method, I have to write:
treeNode("aaa") {
treeNode("bbb") {}
treeNode("ccc") {}
}
You can see the leaf nodes they don't have children, but they have to have a empty block {}
.
Is there any way to give the parameter children: => Any
a default do-nothing value, that I can write the code as:
treeNode("aaa") {
treeNode("bbb")
treeNode("ccc")
}
Help~
The problem is not that you can't give it a do-nothing (default) value; the problem is that even if you do, functions with multiple parameter blocks have to at least have parentheses or braces for each block.
There is one exception: an implicit parameter block does not need to be referenced at all. Unfortunately, you're not allowed to have call-by-name implicit parameters, and even if you were, your signature would allow any random implicit to work in that spot!
Now, there is a way around this, which I will show for completeness, but I suggest that (assuming you don't just want another name, like
leafNode
) you just leave the trailing{}
there.You can get exactly the syntax that you want if you do the following. First, you need an implicit parameter, but you make it a wrapper class (could use
Function0
which already exists, but then the next step might have unintended consequences):Now you need two things--you need to be able to convert a by-name
Any
into your new trait, and you need to have an implicit do-nothing one available. So weAnd now we recover the behavior that you were after:
(in your example, you don't return anything; here I do, to show that it works.)
It's a lot of tooling just to avoid some
{}
s, though, which is why I'd suggest only doing this if you anticipate this to be a very heavily used DSL and that two names is unacceptable. (Also, if you expect it to be very heavily used,treeNode
is probably painfully long as a name; I'd suggest justnode
.)