In a script, if a “condition” step evaluates to “false”, then the script exits early rather than continue execution.
If it’s too complex to implement “if/elsif/else” logic, perhaps a new step called “Condition-Continue” or somesuch.
Example of when this matters:
I have a script that turns on my receiver, TV, and Playstation. But if house mode is set to “Quiet”, I want the receiver to mute itself immediately after it turns on to avoid waking people up.
But I can’t do that immediately, since that would require a conditional at the top of the script. If it’s not set to Quiet, then nothing else gets turned on.
In addition, I can’t then do multiple conditionals like “If Quiet, mute the receiver, and if nighttime, apply ‘Theater’ scene”
Have a look at the choose feature introduced in 0.113. Effectively it implements a chain of if-elif statements (case is the term used in other languages). If the first condition evaluate to false it proceeds to the next condition and so on and so on until a condition evaluates to true or ends at the optional default section.
The example below is from the documentation for script syntax. If the first condition isn’t met (you can have many more) it proceeds to execute the default: section.
Yes, I use choose in some of my scripts, and it’s a fantastic addition to automations and scripts.
But in my “turn on playstation” example above, wouldn’t I then have to duplicate all the subsequent steps (turn on tv, turn on playstation, etc) in both the true block, and the default block?
Also, am I able to implement my second example of multiple, unrelated conditionals? That is:
Right. And that’s the kind of thing I’ve had to do. My “WTH” suggestion is to make that possible without having to use workarounds like adding more scripts.
Which it sounds like I can do using choose without a default as per @pnbruckner’s suggestion (though… that’s still in the “workaround” category for me, since it’s not an obvious way to use switch/case/choose statements).
Ah! That makes sense. Thanks for pointing that out – I’ll definitely start using that trick.
I still consider it something of a “WTH”, though. A programmer wouldn’t normally think to use “choose” in that way, so it would be nice to have a construct that’s more intentional and clear for that purpose.
Neither is switch/case to a someone who’s never used it before. Scripts are not a “workaround” any more than a subroutine or function is a “workaround” in other languages.
Anyway, if you believe you know of an easier way it should be done, please present an example of the syntax you would prefer to see for, say, a choice of three possible options. You can modify the following example to show how it could be simplified with different syntax:
FWIW, I believe pnbruckner is also working on a simplification of how conditions are presented when using the template platform. I’ve seen an example and it’s more streamlined than how it’s currently done.
BTW, I did use the adjective “optional” when describing default. Maybe you missed it.
You can use multiple choose in your script sequence or automation action
So
- service: #whatever you use to turn receiver on
- choose:
- conditions:
#Your condition to check quiet mode
sequence:
# your actions to set volume
- service: # service to turn TV on
- service: # service to turn playstation on
- choose:
- conditions:
#check if it's night- time
sequence:
# apply your theme
The choose action was a compromise. It was discussed at length in an architecture issue. A more straightforward if - elif - else construct would have been preferable, but YAML constraints made it difficult. So, yeah, I agree, choose is neither optimal nor intuitive, but it was the best that could be suggested at the time.
Maybe it is because I have a little programming experience, but I think it would still be clearer (easier to understand) to just call it ‘if/else if’ instead of 'choose" and ‘else’ instead of ‘default’.
Nothing inherently wrong with the term choose. Other languages use different names, for example, this is from VB:
Select [ Case ] testexpression
[ Case expressionlist
[ statements ] ]
[ Case Else
[ elsestatements ] ]
End Select
It uses the word ‘select’ instead of choose, each selection begins with the word ‘case’ and the equivalent of ‘default’ is ‘case else’.
In C++, switch is the equivalent word for choose, each choice begins with case and it uses the word default in the same way VB uses case else.
In perl 5, it’s given, when, and default, respectively. Prior to version 5 it was switch case.
When learning python, it was surprising to discover there’s no equivalent statement for switch/choose/select/given (or, for that matter, do while). Nevertheless, an old-school chain of if-elif's can achieve the same thing (it just looks kind of lame when you’re accustomed to using switch or select).
I’m beginning to believe that the choose construct was a mistake. It seems to confuse everyone.
I think this would be better (and now that I’ve had a chance to think about it more, it wouldn’t really be any more difficult to implement than choose was):
That was another option, but then it would quickly lead to ridiculous indentation with nested if’s. I prefer something with elif to keep things reasonable.
Unless I’m mistaken, I believe choose was suggested in the Architecture discussion and inspired by XSL. However, what was lost in translation is that XSL’s choose includes other key words to clarify its usage:
<xsl:choose>
<xsl:when test="expression">
... some output ...
</xsl:when>
<xsl:otherwise>
... some output ....
</xsl:otherwise>
</xsl:choose>
The key word otherwise became default and when effectively disappeared and simply inferred by condition.
I don’t have a problem with understanding the new choose option’s structure. Frankly, I dislike the if-then-elif-then-else example (shown above) because it contains more key words to achieve what can already be done with less.
While all the suggestions are valid here and I appreciate @pnbruckner’s continued contributions to make this easier still, I feel like the author’s original point is still valid - why doesn’t execution continue after a conditional? I feel like whether or not to continue execution after should be a decision users can make regardless of the conditional construct or whether or not a default is present.
To give an example, when someone arrives home at my house I conditionally turn lights on downstairs based on current light levels in those rooms. Then I always turn the outlets on regardless of which lights turned on since those are for two devices with screens, light level doesn’t matter to them. Today I would need to do the following to make that work:
Remember to do the outlets first since those are always and once conditionals start the script ends
Move all but one of the conditionals into a separate script since logic cannot proceed within this script past a conditional
Move that one remaining conditional to the end (or just put them all in separate scripts because this is kind of a hassle)
I don’t mind that its possible for script execution to end after a conditional but I do feel like that should be an option rather then a requirement.
There are two different action types being discussed: condition and choose. The former’s whole purpose in life is to provide a conditional “exit” type statement. The latter allows a “do something only if something else is true” type statement. So basically, don’t use the first when the second is more appropriate. I believe that was the suggestion in the first reply.
The discussion, though, has lately turned into “WTH is an exit statement called condition, and why is an if statement called choose”.