I have a ternary expression with multiple conditions, where I would like to perform an assertion on one case:
var result = (
"bananas" if input == "yellow"
else "oranges" if input == "orange"
else {
assert(false, "Unsupported fruit color %s detected!" % input)
"bananas" # fallback to default
}
This is not, in fact, valid GDScript and does not compile because this is not valid syntax:
{
someStatement
anExpression
}
But does GDScript provide a way to do such a thing, executing a statement for its side effects and then returning an expression?
GDScript does not support statements inside of expressions (ternary expression or otherwise).
You can, of course, use and statements (such as if
). Although statements do not return. But you can do this:
var result = "bananas" #default
if input == "yellow":
result = "bananas"
elif input == "orange":
result = "oranges"
else:
assert(false, "Unsupported fruit color %s detected!" % input)
Or using a match
statement:
var result = "bananas" #default
match input:
"yellow":
result = "bananas"
"orange":
result = "oranges"
_:
assert(false, "Unsupported fruit color %s detected!" % input)
Which I believe to be easier to read.
Anyway, to answer the question, what comes to mind is to use a method. Since a method can have statements and return.
var result = (
"bananas" if input == "yellow"
else "oranges" if input == "orange"
else fail(input)
)
Where fail
is a method that looks like this:
func fail(input) -> String:
assert(false, "Unsupported fruit color %s detected!" % input)
return "bananas" # fallback to default
You didn't tell me which version of Godot you are using. What I said above should work in either Godot 3 or Godot 4.
With that said, starting form Godot 4, you can use inline anonymous methods ("lambda"), so you might do something like this:
var result = value if condition else (func():
assert(false, "HELLO")
return false).call()
I'm showing this simple example to highlight that the indentation gets awkward because the inline anonymous method requires and indention level, but we also need to wrap it and parenthesis and call it.
Now, for your case, it would be like this:
var result = (
"bananas" if input == "yellow"
else "oranges" if input == "orange"
else (func (input) -> String:
assert(false, "Unsupported fruit color %s detected!" % input)
return "bananas").call(input)
)
I'll reiterate that I believe the match
version is easier to read, but you do you.