Uh oh! We couldn’t find any match.

Please try other search keywords.

Bixby Developer Center

Guides

Conditionals

Conditionals use logic to guide the runtime execution along a path appropriate for the current context. Here are the different control flow statements that are available:

if-else

if, else-if, else These keywords allow chaining choices in this order:

  • Start with a required if(%expression%)
  • Follow with any number of optional else-if(%expression%)
  • End with an optional else.

For example:

if(%expression%) {
  ...
} else-if(%expression%) {
  ...
} 
else {
  ...
}

The chain will be evaluated from top to bottom and execute the first qualifying code block:

  • if(%expression%) and else-if(%expression%) qualify if their %expression% evaluates to true. You can use Expression Language to write powerful %expression% choices.
  • else always qualifies when it is reached.

Example

The recipe.FindRecipes action uses relaxation to progressively drop the less meaningful inputs. As long as the action returns no results, this chain of conditionals will be evaluated to determine which input to drop next.

output (Recipe) {
on-empty {
if (exists(maxCalories)) {
drop (maxCalories)
} else-if (exists(servings)) {
drop (servings)
} else-if (exists(collection) && !relaxed(collection)) {
drop (collection)
} else-if (exists(flavorProfile)) {
drop (flavorProfile)
} else-if (exists(maxPreparationPeriod)) {
drop (maxPreparationPeriod)
} else-if (exists(theme)) {
drop (theme)
} else-if ("exists(course) && !contains(course,'Dessert')") {
drop (course)
} else-if (exists(cuisineAttribute) || exists(cuisine)) {
ordered-effects {
drop (cuisineAttribute)
drop (cuisine)
}
} else-if (exists(meal) && !relaxed(meal) && !relaxed(collection)) {
drop (meal)
} else-if (exists(ingredientToInclude)) {
drop (ingredientToInclude)
}
}
}

This is a strategy that conditions the time of day to the different meals.

instantiation-strategy {
id (recipes-default-meal)
match {
viv.food.MealName (meal) {
to-input: viv.recipe.FindRecipes(action)
}
}
if ("now().time.hour < 8") {
strategy {
intent {
goal: viv.food.MealName("Breakfast")
}
}
}
if ("8 <= now().time.hour && now().time.hour < 11") {
strategy {
intent {
goal: viv.food.MealName("Brunch")
}
}
}
if ("11 <= now().time.hour && now().time.hour < 14") {
strategy {
intent {
goal: viv.food.MealName("Lunch")
}
}
}
if ("14 <= now().time.hour && now().time.hour < 21") {
strategy {
intent {
goal: viv.food.MealName("Dinner")
}
}
}
if ("21 <= now().time.hour") {
strategy {
intent {
goal: viv.food.MealName("Snack")
}
}
}
}

switch

To define a switch, start with switch(%expression%){}. Then add one or more case(%value%) and a final optional default block.

switch (%expression%) {
case (%value%) {
...
}
case (%value%) {
...
}
default {
...
}
}

The switch will be evaluated from top to bottom by comparing the %expression% against each case. It will execute the code block for the first case that matches (otherwise it will fallback to the default block, if present).

Example

A very common use case is to adapt dialog to the quantity:

dialog (Concept) {
match {
viv.recipe.RecipeServings (this)
}
switch (plural(this)) {
case (One) {
template (serving)
}
default {
template (servings)
}
}
}

choose

By default, Bixby will select the first occurrence of whatever it is looking for (such as a 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%) {
...
}

Here are the possible values for %order%:

  • First: Select the first valid occurrence.
  • Random: Find all valid occurrences and randomly select one.

Example

This makes the Result Dialog for recipes more variable.

dialog (Result) {
match {
viv.recipe.Recipe (this)
}
switch (plural(this)) {
case (One) {
template ("Here is a #{concept(this)}")
}
default {
choose(Random) {
template ("Here are some #{concept(this)}")
template ("I found some #{concept(this)}")
template ("I found some yummy #{concept(this)}")
template ("Here are some tasty #{concept(this)}")
}
}
}
}

for-each

Enables you to loop by traversing through an array of structures. You can then render each element within this array into a separate component. The for-each loop also specifies an as key, which sets the variable name to be used in the for-each loop. For example, as(i). You can then refer to each item defined in the for-each by this variable further in your for-each block: text (“#{i.line}”).

Example:

This creates a partitioned area in your layout, with separated rows that iterate through a list of ingredients. Each hbox contains a line item and the quantity of that item in separate vbox containers.

partitioned {
for (this.ingredients) : as (i) {
hbox {
vbox {
align (Left)
text { text (“#{i.line}) style (Title2) }
}
vbox {
align (Right)
text { text (“#{i.quantity}) style (Title2) }
}
}
}
}

If you need to use conditional logic in your loop, you can use the index-var, which is the name of the variable you want to assign the iteration index to. For example, the first item will be given a value of 0, the second 1, etc.

if (i == 0) { do something} 
else { do something else}