Uh oh! We couldn’t find any match.

Please try other search keywords.

Bixby Developer Center

Guides

Using Expression Language

Overview

Bixby's Expression Language (EL) allows you to work with your capsule's concepts and actions in layouts, strategies, and dialogs by using simple expressions.

Here's an example of a simple layout including Expression Language:

layout {
mode (Summary)
match: Recipe (this)
content {
section {
title {
template ("#{value(name)}")
}
content {
if (exists(totalTime)) {
single-line {
text {
value ("Total Time: #{value(totalTime)} minutes")
}
}
}
if (exists(recipe.servings)) {
single-line {
text {
value ("Servings: #{value(servings)}")
}
}
}
}
}
}
}
  • The match pattern binds the value of Recipe to the variable this. Many EL functions that access slots (properties on a concept or inputs on an action) will look for them on this if no variable is specified.
  • Slots of this are accessed with the . operator, as we see in this.name.
  • The function exists(totalTime) is used to check whether the slot this.totalTime has a value. If the match expression had bound Recipe to a name other than this, it would need to be explicitly specified here. So, if the match pattern had been Recipe (r), we would have had to use˙ exists(r.totalTime).
  • EL is embedded in strings with the #{} notation: #{value(totalTime)} returns the value of this.totalTime.

Functions

Expression Language includes functions for testing node values, formatting them in a variety of ways in templates, working with geospatial information, and more. For a full list of EL functions, read the Expression Language Reference.

Operators

EL provides a set of typical operators you can use in expressions for comparisons, mathematics, and logic.

  • Arithmetic: +, -, *, /, % (modulo division), div, mod, unary -
  • Logic: and, &&, or, ||, not, !
  • Comparisons: ==, eq, !=, ne, <, lt, >, gt, <=, ge, >=, le.
  • Empty: The empty prefix operator can be used to determine whether a value is null or empty.
  • Ternary conditional: A ? B : C. Evaluate to B if A is true, otherwise evaluate to C. A shorthand equivalent to if (a) then return b else return c.

Comparisons can be made against other values or against Boolean, string, integer, or floating-point literals.

if (size(legs) == 1) {
template ("Nonstop")
} else {
template ("#{integer(size(legs) -1)} stops")
}

Here is a more complex example that uses logic, comparisons, and ternary conditionals:

template("#{value(info.Prop1)} #{(exists(info.Prop1Val) && info.Prop1Val > -1 ? info.Prop1Val : 'empty')}")

The ternary conditional in this example is specifically this statement: exists(info.Prop1Val) && info.Prop1Val > -1 ? info.Prop1Val : 'empty'. The entire template will print both the value of info.Prop1 and info.Prop1Val, if info.Prop1Val exists and has a value greater than -1. The template will print just info.Prop1 otherwise. This is a convenient way to have a template dynamically print information.

Accessors

A slot can be either:

  • A property of a concept, such as the sum property on the RollResult concept in the Dice sample capsule in the Quick Start Guide.
  • An input on an action.

Slots can be accessed in one of two ways:

  • The . operator: node.slot
  • The [ ] operator: node["slot"]
if (this.description == 'NoMatchedAlarm') {
// description slot on the node bound to "clock" is equal to 'NoMatchedAlarm'
}

EL in Bixby Language

Expression Language can be used with certain keys: match patterns, conditionals such as if blocks, and inside strings. In addition, the values returned by EL expressions can be bound using the $expr() construct.

In this example, moon.MoonPhase is bound to this, and the name property is accessed with the . operator:

match: moon.MoonPhase (this)
if (exists(this.name) && this.name == 'New Moon') {
...
}

In this example, #{} is used to inject an EL expression into advice:

match: time.DateTime (time)
advice ("#{isPast(time) ? 0.1 : 0.9}")
Note

You might see EL embedded in strings using either #{} or ${}. The first form is similar to Ruby's ERB and other template languages; the second form is the UEL standard. There is no difference in functionality between the two forms.

Lastly, this code example binds time.Date to date and the output of the moon.GetMoonPhaseDate action to action, and uses both of them in a template macro expression.

match: time.Date (date) {
from-output: moon.GetMoonPhaseDate(action)
}
...
expression("The next #{value(action.moonName)} is on #{value(date)}")

The $expr() construct takes an EL expression as an argument and returns its value. This can be used in a typed or untyped form. This example, from the sample transactional capsule, comes from the CreateItem constructor action:

action (CreateItem) {
type (Constructor)
collect {
input (searchTerm) {
type (SearchTerm)
min (Optional)
hidden
}
// continues with inputs for brand, style, gender, minPrice, maxPrice
computed-input (shirt) {
type (Shirt)
min (Required)

compute {
intent {
goal: FindShirt
value: $expr(searchTerm)
value: $expr(brand)
value: $expr(style)
value: $expr(gender)
value: $expr(minPrice)
value: $expr(maxPrice)
}
}
...
}
}
output (Item)
}

The typed expression form of $expr() lets you coerce the returned value to a specific concept. For instance, the following action outputs a Distance concept bound to the value of the calculateDistance() EL function:

action (GetCurrentDistance) {
type (Fetch)

collect {
input (point) {
type (GeoPoint)
min (Required)
plan-behavior (Always)
}
}

output (Distance) {
evaluate {
if (getLocale($user.locale).measurementSystem == 'USC') {
Distance$expr(calculateDistance($user.currentLocation, point, 'Miles'))
} else {
Distance$expr(calculateDistance($user.currentLocation, point, 'Kilometers'))
}
}
}
}

Special EL Variables

There are several variables available in EL that can be used to access contextual information about the user and device.

Suppose you wanted to set a concept's value to the user's current location. You could set a myLocation concept to that value by creating an action file that takes this computed-input block:

computed-input (myLocation) {
min (Required) max(One)
type (geo.CurrentLocation)

compute {
if (exists($user.currentLocation)) {
intent {
goal: geo.CurrentLocation
value-set: geo.CurrentLocation { $expr($user.currentLocation) }
}
}
}
}
Note

Your capsule will need to request the user-profile-access permission to be able to access the user's CurrentLocation. For more information, read Grant Capsule Permissions.

For a list of special EL variables, read the Expression Language Reference.