Conditional statements let you control your capsule's execution by testing conditions, such as the values of concepts or expressions, and taking different actions based on the result of the test. An example of a conditional is "if the time is before 8:00 a.m., then set the default meal choice to 'breakfast'." Bixby provides several conditionals for use in your code, as well as a looping construct to repeat the same set of actions with each element in an array.
result-view {
match {
Shoe (this)
}
render {
if ("size(this) > 1") {
list-of (this) {
where-each (shoe) {
macro (shoe-summary-macro) {
param (shoe) {
expression (shoe)
}
}
}
}
} else-if ("size(this) == 1") {
layout {
macro (shoe-details-macro) {
param (shoe) {
expression (this)
}
}
}
}
}
}
The chain is evaluated from top to bottom and executes the first code block whose conditional expression evaluates to true:
if (expression)
and else-if (expression)
execute their blocks if their expression
evaluates to true. There can be multiple else-if
blocks, but only the first true if
or else-if
block will be executed.else
always executes if it is reached (that is, none of the if
or else-if
blocks evaluate to true).Conditionals can use Expression Language to perform a wide range of tests. In the example above, size()
tests how many results have been returned. Any value that can be accessed in EL can be tested in a conditional:
sum
property on the RollResult
in the dice-rolling capsule. The value of a property could be another concept (primitive or structure), or could be a symbol of an enum.Here's another example of an if/else-if/else
construction from a transactional capsule:
activity-support {
match {
Receipt (this)
}
time (statusRefreshTime)
states {
if (orderState == 'Ordered') {
state (Scheduled) {
expires(statusRefreshTime)
summary-view {
message {
template ("#{value(orderState)} #{value(order)}")
}
title {
template ("#{value(order)}")
}
details {
template ("#{value(orderState)}")
}
}
detail-view {
render {
layout-match (this) {
mode (Details)
}
}
}
}
} else-if (orderState == 'Shipped') {
state (Relevant) {
expires(statusRefreshTime)
summary-view {
message {
template ("#{value(orderState)} #{value(order)}")
}
title {
template ("#{value(order)}")
}
details {
template ("#{value(orderState)}")
}
}
detail-view {
render {
layout-match (this) {
mode (Details)
}
}
}
}
} else { //orderState == 'Delivered' || orderState == 'Cancelled'
state (Recent) {
summary-view {
message {
template ("#{value(orderState)} #{value(order)}")
}
title {
template ("#{value(order)}")
}
details {
template ("#{value(orderState)}")
}
}
detail-view {
render {
layout-match (this) {
mode (Details)
}
}
}
}
}
}
}
A switch
block is similar to an if/else-if
block, but only performs a single conditional test at the start of the block, providing case
blocks that handle cases for the conditional expression's returned value.
dialog (Value) {
match: ProductType(this)
switch (this) {
case (FlowerArrangement) {
template("Flower Arrangement")
}
case (Bouquet) {
template("Bouquet")
}
case (Plantable) {
template("Plantable")
}
}
}
The expression in switch (expression)
defines the test (in this case, simply the value of this
). Then, case
statements test the value of the expression. The first case
that matches the result of the switch
expression will be executed.
Just like the if/else-if
block has an optional else
block to be executed if no tests match, a switch
block has an optional default
block that will be executed if no case
values match:
dialog (Concept) {
match {
Shoe (this)
}
switch (plural(this)) {
case (One) {
template (shoe)
}
default {
template (shoes)
}
}
}
By default, Bixby will select the first occurrence of whatever it is looking for (such as a selection strategy or a dialog template), while respecting the control flows. You can modify this behavior for a code block by wrapping it with a choose
.
choose (%order%) {
...
}
The %order%
can be either:
First
: Select the first valid occurrence.Random
: Find all valid occurrences and randomly select one.This control flow is particularly useful when adding dialog variations, like in the Dialog Affirmations Sample Capsule:
// Pick a random affirmation from a bag of words
macro-def (AFFIRMATION) {
content {
choose (Random) {
template (Okay)
template (Alright)
}
}
}
If you are testing your capsule in the Simulator, disable the Deterministic Mode checkbox to make sure that choose (Random)
behaves as expected.
A for-each
block loops through an array of values, such as a list of results in a result view, and executes its code block on each individual element within the array. In Bixby, this is used most often for rendering elements within their own view components.
compound-card {
content {
for-each (items) {
as (item) {
// do something with the the item
}
}
}
}
This creates a partitioned
area in your layout, with separated rows that iterate through a list of hotel amenities, rendering them in single-line
containers.
result-view {
match: Hotel (hotel) {
from-output: ShowHotelPartitioned
}
message {
template ("Here are partitioned hotel amenities:")
}
render {
layout {
section {
content {
partitioned {
content {
for-each (hotel.amenities) {
as (amenity) {
single-line {
text {
value ("#{value(amenity)}")
style (Detail_L)
}
}
}
}
}
}
}
}
}
}
}
The as
block also provides a loop index, a counter that starts at 0
and increments with each loop iteration. For the first item, the index will be 0
; for the second, it will be 1
; and so on. You can use this for conditional logic within your loop. By default, the loop index counter is bound to the i
variable. You can only have a single as
block per for-each
loop.
for-each (this.instructions) {
as (instruction) {
divider
single-line {
text {
style (Detail_M_Soft)
value ("Step #{i + 1}") // i is the default index variable and starts at 0
}
}
paragraph {
value ("#{raw(instruction)}")
style (Detail_M)
}
divider
}
}
If you want to use another variable name, you can use the index-var
key to specify another variable to bind to the loop counter.
for-each (this.items) {
as (item) {
index-var (j)
if (j == 0) {
// first item
} else {
// second through last item
}
}
}