Enums

Notice! This page contains advanced material. If you are a beginner LipiScript programmer, we recommend you become familiar with other, more accessible LipiScript features before you venture here.

Introduction

LipiScript Enums, also referred to as enumerations, enumerated types, or enum types, are unique data types where all possible values (members) are explicitly defined by the programmer. They provide a human-readable and expressive way to declare distinct sets of predefined values that variables, conditional expressions, and collections can accept, allowing for stricter control over the values used in a script’s logic.

Declaring an Enum

To declare an enum, use the enum keyword with the following syntax:

[export ]enum <enumName>
    <field_1>[ = <title_1>]
    <field_2>[ = <title_2>]
    ...
    <field_N>[ = <title_N>]

Each field in the enum represents a unique, named member (value) of the enum type. Users can specify optional const string titles for enum fields to provide additional context regarding what their values represent. If a programmer does not specify a field’s title, its title defaults to the string representation of its name. Enum inputs display these titles within their dropdown menus in a script’s Settings/Inputs tab. Scripts can also retrieve enum field titles using the str.tostring() function, allowing for their use in further calculations. Refer to the section below for more information.

While the syntax above may resemble that for declaring user-defined types (UDTs), it is crucial to recognize that enum types and UDTs serve different purposes. Scripts utilize UDTs to create objects with series fields that can hold values of any specified type. In contrast, enums consist of distinct groups of simple fields representing specific, predefined values of the same unique type that variables, expressions, and collections can accept.

For example, this code block declares a Signal enum with three fields: buy, sell, and neutral. Each field represents a distinct member (possible value) of the Signal enum type:

//@enum           An enumeration of named values representing buy, sell, and neutral signal states.
//@field buy      Represents a "Buy signal" state.
//@field sell     Represents a "Sell signal" state.
//@field neutral  Represents a "neutral" state.
enum Signal
    buy     = "Buy signal"
    sell    = "Sell signal"
    neutral

Note that:

  • The Signal identifier represents the name of the enum, signifying the unique type to which the fields belong.
  • We used the //@enum and //@field annotations to document the meanings of the enum and its fields.
  • Unlike the buy and sell fields, the neutral field does not include a specified title. Therefore, its title defaults to the string representation of its name (“neutral”).
  • To retrieve a member of an enum, reference its field name using dot notation syntax, i.e:
enumName.fieldName;

As with other types, scripts can assign enum members to variables, function parameters, and UDT fields, providing strict control over their allowed values.

For instance, this line of code declares a mySignal variable whose value is the neutral member of the Signal enum. Any value assigned to this variable later must also be of the same enum type:

mySignal = Signal.neutral;

Note that the above line does not require declaring the variable’s type as Signal because the compiler can automatically infer that information from the assigned value. If we use na as the initial value instead, we must explicitly use Signal as the type keyword to specify that mySignal will accept a Signal member:

Signal mySignal = na

Shadowing

To avoid potential conflicts where namespaces added to Lipi Script in the future might clash with the names of enums in existing scripts, enum names can shadow some of Lipi’s namespaces.

For example, one can declare an enum like the following, whose name shadows the syminfo.* namespace:

indicator("Shadowing demo")
 
enum syminfo
    abcd
 
log.info(str.tostring(syminfo.abcd))

However, using such a name for an enum is only permitted if the enum’s fields do not have names that match any of the namespace’s built-ins. If they do, Lipi will be unable to determine which value the script is supposed to use, resulting in a compilation error:

indicator("Name conflict demo")
 
enum syminfo
    abcd
    tickerid // This matches the built-in `syminfo.tickerid` variable, causing a compilation error.
 
log.info(str.tostring(syminfo.tickerid))

Additionally, one cannot use any of Lipi’s built-in type names as the name of an enum.

Notice! While it is possible for some enum names to shadow language namespaces, as shown above, we recommend choosing unique names for enums wherever possible for more readable code that’s easier to maintain.