> ## Documentation Index
> Fetch the complete documentation index at: https://gocharting.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Control flow, functions and collections across languages

> How Lipi maps to MQL4, MQL5, NinjaScript, Pine Script and thinkScript for control flow, functions and collections: conditional block, choose by value, inline condition, counted loop, loop over a collection, conditional loop and more, with the differences that matter when converting.

Branches, loops, your own functions and types, operators and arrays. Each row maps one concept from Lipi to the other languages; the word in a cell is the relation, explained in the [language map overview](https://gocharting.com/docs/scripting/reference/language-map.md#relations).

| Concept | Lipi | MQL4 | MQL5 | NinjaScript | Pine Script | thinkScript |
| - | - | - | - | - | - | - |
| [Conditional block](#flow-if) | `if`, `else` | Caveat | Caveat | Exact | Caveat | Caveat |
| [Choose by value](#flow-switch) | `switch`, `case`, `default` | Differs | Differs | Caveat | Caveat | Caveat |
| [Inline condition](#flow-ternary) | Syntax | Caveat | Exact | Exact | Exact | Caveat |
| [Counted loop](#flow-for-count) | `for to`, `step` | Differs | Differs | Caveat | Differs | Differs |
| [Loop over a collection](#flow-for-each) | `for in` | Absent | Absent | Caveat | Caveat | Absent |
| [Conditional loop](#flow-while) | `while` | Exact | Caveat | Caveat | Exact | Differs |
| [Leave or skip a loop pass](#flow-break-continue) | `break`, `continue` | Caveat | Caveat | Exact | Exact | Absent |
| [Your own function](#func-user-function) | `func`, `return` | Caveat | Caveat | Caveat | Caveat | Caveat |
| [Method on a type](#func-method) | `def` | Caveat | Caveat | Caveat | Caveat | Absent |
| [Arithmetic operators](#op-arithmetic) | `+`, `-`, `*`, `/`, `%` | Differs | Differs | Differs | Caveat | Exact |
| [Comparison operators](#op-comparison) | `==`, `!=`, `>`, `<`, `>=`, `<=` | Caveat | Caveat | Exact | Caveat | Caveat |
| [Logical operators](#op-logical) | `and`, `or`, `not` | Differs | Differs | Differs | Differs | Caveat |
| [Update in place](#op-compound-assign) | Syntax | Caveat | Caveat | Caveat | Caveat | Absent |
| [Key-value collection](#coll-map) | None | Absent | Not in Lipi | Not in Lipi | Not in Lipi | Absent |
| [Two-dimensional collection](#coll-matrix) | None | Not in Lipi | Not in Lipi | Not in Lipi | Not in Lipi | Absent |
| [Reuse code from another file](#mod-import) | None | Not in Lipi | Not in Lipi | Not in Lipi | Not in Lipi | Absent |
| [Stop with an error](#err-runtime-error) | None | Not in Lipi | Not in Lipi | Not in Lipi | Not in Lipi | Not in Lipi |

Each section below gives the Lipi construct first, then the construct in each language, with a note wherever behaviour differs. The language name links to the documentation the row was checked against.

## Conditional block

Running a block only when a condition holds, with optional alternative branches.

In Lipi: `if`, `else`. `if` has no value (`x = if ...` is a syntax error). Nonzero numbers are true, na is false; a string is rejected.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operators/if) | if (cond) \{...} else \{...} | Equivalent, with a caveat | C-style: condition in parentheses, braces optional for one statement, else if chains. |
| [MQL5](https://www.mql5.com/en/docs/basis/operators/if) | `if / else` | Equivalent, with a caveat | Condition sits in parentheses and chains as else if; any non-zero number counts as true. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/branching_commands.htm) | `if / else if / else` | Exact | |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/conditional-structures/#if-structure) | `if / else if / else` | Equivalent, with a caveat | Pine if returns a value (x = if c ...) and nests by indentation; Lipi's if is a statement with braces and returns nothing. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/if) | if / else (statement); if ... then ... else (expression) | Equivalent, with a caveat | Statement branches assign to plot or def variables rather than run imperative code; the expression form needs both branches and computes both. |

## Choose by value

Running one of several blocks depending on the value of an expression.

In Lipi: `switch`, `case`, `default`. No fall-through; one value per case. A switch inside a function body fails on Add to chart (Not Implemented): use if/else there.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("Switch")
float v = 0.0
switch bar_index % 2 {
    case 0: v := close
    default: v := open
}
plot(v, title="Alternating")
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operators/switch) | switch (expr) \{ case const: ... break; default: } | Looks alike, behaves differently | Control falls through to following cases until break; the expression must be an integer type and case labels constants. |
| [MQL5](https://www.mql5.com/en/docs/basis/operators/switch) | `switch / case / default` | Looks alike, behaves differently | Without break, execution falls into the next case; case labels are constants and the switched value must be an integer. State and side effects: A forgotten break silently runs several branches. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/branching_commands.htm) | `switch / case / break` | Equivalent, with a caveat | Each C# case block ends with break; Lipi cases take exactly one value each and use case and default labels. |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/conditional-structures/#switch-structure) | `switch` | Equivalent, with a caveat | Pine switch returns a value, may omit the subject to test conditions, and uses value => block with a bare => default. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/switch) | `switch / case / default` | Equivalent, with a caveat | Switches only on an enum input or enum def, not on arbitrary values; default is needed unless every enum value has a case. |

## Inline condition

An expression that gives one of two values depending on a condition.

In Lipi this is written with the language's own syntax. Only the chosen branch runs; an na condition takes the else branch. The branches need compatible types.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("Up or down", overlay=true)
shade = close >= open ? color.green : color.red
plot(close, title="Close", color=shade, linewidth=2)
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operators/ternary) | `cond ? a : b` | Equivalent, with a caveat | Both branches must share a type (the wider type wins); there is no na branch, EMPTY\_VALUE is the usual stand-in. |
| [MQL5](https://www.mql5.com/en/docs/basis/operators/ternary) | `?:` | Exact | |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm) | `condition ? a : b` | Exact | |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/operators/#-ternary-operator) | `condition ? a : b` | Exact | |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/If) | if \<cond> then \<a> else \<b>; If(cond, a, b) | Equivalent, with a caveat | Written as if-then-else; the If() function accepts only numeric double arguments, so use the expression form for colours or text. |

## Counted loop

Repeating a block with a counter that runs from a start value to an end value.

In Lipi: `for to`, `step`. The end is inclusive and a start above the end counts down, but equal bounds run zero times. `by` is not a keyword; use `step`.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("Sum of five closes")
total = 0.0
for i = 0 to 4 {
    total += close[i]
}
plot(total, title="Sum")
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operators/for) | for (init; cond; step) | Looks alike, behaves differently | C-style loop that ends when the condition fails; no inclusive end or automatic direction, so descending loops need i-- and a matching comparison. |
| [MQL5](https://www.mql5.com/en/docs/basis/operators/for) | `for` | Looks alike, behaves differently | Start, test and step are free expressions; there is no to/step form, so inclusive end and step direction are written by hand. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm) | for (initializer; condition; iterator) | Equivalent, with a caveat | Start, bound and step are written by hand in three clauses; Lipi 'for i = a to b' infers direction without a step. |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/loops/#for-loops) | for i = a to b by step | Looks alike, behaves differently | Pine's end value is inclusive, so equal bounds run once (Lipi runs zero times). The step keyword is by, not step. State and side effects: Pine re-evaluates the end bound before every pass; Lipi evaluates start, end and step once. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/fold) | `fold` | Looks alike, behaves differently | fold is a reduction expression, not a statement loop: the end bound is excluded, the step is fixed at 1, one accumulated result. |

## Loop over a collection

Repeating a block once for each element of a collection.

In Lipi: `for in`. Iterates only an array held in a variable: no expression after `in`, no index form. Assigning the loop variable does not change the array.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("For each")
a = array.from(1.0, 2.0, 3.0)
total = 0.0
for x in a {
    total += x
}
plot(total, title="Total")
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operators/for) | | Not in MQL4 | No for-in or range loop; the operator list has for, while and do-while. Loop over indexes up to ArraySize instead. |
| [MQL5](https://www.mql5.com/en/docs/basis/operators) | | Not in MQL5 | The operators section lists no foreach or range loop; index through the array with a for loop. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm) | `foreach (type item in collection)` | Equivalent, with a caveat | Keyword is foreach with an explicit element type; Lipi writes 'for item in collection'. |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/loops/#forin-loops) | for item in collection; for \[index, item] in collection | Equivalent, with a caveat | Pine also offers the \[index, item] form and loops over matrices and maps; Lipi has only the single-item form over an array variable. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types) | | Not in thinkScript | No arrays or collections exist, so there is nothing to iterate over; fold only counts an index. |

## Conditional loop

Repeating a block while a condition holds.

In Lipi: `while`. No iteration limit, but a history run is cancelled after 45 seconds.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("While")
x = close
while x > 100 {
    x := x / 2
}
plot(x, title="Halved")
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operators/while) | while (cond) \{...} | Exact | |
| [MQL5](https://www.mql5.com/en/docs/basis/operators/while) | while; do while | Equivalent, with a caveat | MQL5 construct includes do-while, which runs its body once before testing; Lipi has only while and rejects do/while, so rewrite with while and break. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm) | while (condition) \{ }; do \{ } while (condition) | Equivalent, with a caveat | C# do-while runs its body once before testing the condition; Lipi has no do-while (rejected), so rewrite with while true and break. |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/loops/#while-loops) | `while` | Exact | |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/while) | `while (inside fold)` | Looks alike, behaves differently | while only adds an early-exit test inside fold; it is not a standalone loop, and a failed test keeps the last accumulated value. |

## Leave or skip a loop pass

Ending a loop early, or skipping to its next pass.

In Lipi: `break`, `continue`.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operators/break) | break; continue; | Equivalent, with a caveat | break also ends a switch case; Lipi's break works only inside a loop. continue goes to the next loop iteration in both. |
| [MQL5](https://www.mql5.com/en/docs/basis/operators/break) | break; continue | Equivalent, with a caveat | break also ends a switch case; Lipi's break works only inside a loop. continue goes to the next loop iteration in both. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/looping_commands.htm) | break; continue; | Exact | |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/loops/) | `break, continue` | Exact | |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/fold) | | Not in thinkScript | No break or continue; a while condition inside fold is the only documented way to stop early, and nothing skips a pass. |

## Your own function

A named, reusable calculation declared by the script, with parameters and a result.

In Lipi: `func`, `return`. Declare before use; no recursion; every parameter is typed. A function cannot rebind a global, and plot-family calls are not allowed inside one.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("Typical price", overlay=true)
func typical(float h, float l, float c) => (h + l + c) / 3
plot(typical(high, low, close), title="Typical")
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/function/parameterpass) | type name(params) \{ return value; } | Equivalent, with a caveat | Return and parameter types are declared; plain-type parameters pass by value, & passes by reference; arrays and structs are always by reference. |
| [MQL5](https://www.mql5.com/en/docs/basis/function) | return\_type name(params) \{ return value; } | Equivalent, with a caveat | Return type is declared before the name; parameters may have defaults and may be passed by reference; arrays and class objects cannot be returned. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/functions_and_methods_explaine.htm) | \[access] returnType Name(params) \{ return ...; } | Equivalent, with a caveat | A method needs an access modifier plus explicit parameter and return types, or void; Lipi func infers them. State and side effects: A method may assign class fields; Lipi functions cannot assign global variables. |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/user-defined-functions/#structure-and-syntax) | `name(params) => body` | Equivalent, with a caveat | Pine declares name(args) => with parameter types optional and returns the last expression; there is no func or return keyword. Neither language allows recursion. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Reserved-Words/script) | `script` | Equivalent, with a caveat | A script block is a mini-study: parameters are declared as inputs and results come back as plots, read by name. |

## Method on a type

A function attached to a type and called on an object of that type.

In Lipi: `def`. `def` needs at least one parameter, the receiver. Call it as `value.name(...)` or `name(value, ...)`; a `func` cannot use dot syntax.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("Method")
def doubled(float x) => x * 2
plot(close.doubled(), title="Twice the close")
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/types/classes) | `member functions of struct or class` | Equivalent, with a caveat | Methods are declared inside a struct or class, may be defined outside with the :: operator, and are called with a dot on an object. |
| [MQL5](https://www.mql5.com/en/docs/basis/oop/staticmembers) | `member function of struct or class` | Equivalent, with a caveat | Methods are declared inside a struct or class (or defined outside with ::); there is no def keyword attaching a function to an existing type. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/functions_and_methods_explaine.htm) | instance method of the script class (or of your own class) | Equivalent, with a caveat | Methods you declare belong to the script class; attaching one to your own type needs a separate C# class. Lipi 'def' extends a type. |
| [Pine Script](https://www.tradingview.com/pine-script-reference/v6/#kw_method) | `method` | Equivalent, with a caveat | Pine uses the method keyword with an explicitly typed first parameter; Lipi uses def. Both call it as value.name(...). |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types) | | Not in thinkScript | No methods on user types exist; only built-in plot methods such as SetDefaultColor() are available. |

## Arithmetic operators

Adding, subtracting, multiplying, dividing and taking remainders.

In Lipi: `+`, `-`, `*`, `/`, `%`. `/` always returns float, even for two ints; division and modulo by zero give na. There is no `^`: use math.pow.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/types/casting) | `+ - * / %` | Looks alike, behaves differently | Two integer operands divide as integers (1/2 gives 0) while Lipi / always returns a decimal; % keeps the sign of the dividend. Numbers and types: Integer division truncates; make an operand double to get a fraction. |
| [MQL5](https://www.mql5.com/en/docs/runtime/errors) | `+ - * / %` | Looks alike, behaves differently | Division by zero is a critical runtime error that stops the program, whereas Lipi returns na. State and side effects: The program is terminated on division by zero; guard every divisor yourself. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm) | `+, -, *, /, %` | Looks alike, behaves differently | The page lists + - \* /; % is the standard C# remainder operator and is not shown there. Numbers and types: Two int operands divide as integers in C#; Lipi '/' always returns a float. |
| [Pine Script](https://www.tradingview.com/pine-script-reference/v6/) | +  -  \*  /  % | Equivalent, with a caveat | Pine's own docs disagree on % with negative operands: the reference keeps the dividend's sign (like Lipi), the Operators page computes with floor. Numbers and types: Pine docs give both truncated and floored results for % with a negative operand; Lipi takes the sign of the left operand. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Arithmetic) | `+ - * / %` | Exact | |

## Comparison operators

Testing whether values are equal, different, greater or smaller.

In Lipi: `==`, `!=`, `>`, `<`, `>=`, `<=`. Comparisons do not chain: write `a < b and b < c`. Test na with na(x); `x == na` compiles with a warning.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operations/relation) | `== != > < >= <=` | Equivalent, with a caveat | MQL4 comparisons yield integer 0 or 1 usable in arithmetic; Lipi comparisons yield bool, and arithmetic or int() on a bool is rejected. |
| [MQL5](https://www.mql5.com/en/docs/basis/operations/relation) | `== != > < >= <=` | Equivalent, with a caveat | Same operators; for reals the docs advise comparing a normalised difference to zero instead of using ==. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm) | `==, !=, >, <, >=, <=` | Exact | |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/operators/#comparison-operators) | ==  !=  >  \<  >=  \<= | Equivalent, with a caveat | Pine rounds floats to nine decimals for ==/!= and never yields na; Lipi compares exactly and yields na with an na operand. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Comparison) | == != \<> \< > \<= >= between crosses | Equivalent, with a caveat | Also word forms (equals, is greater than), \<> and between; crosses above/below are operators here, so use ta.crossover and ta.crossunder in Lipi. |

## Logical operators

Combining or negating true/false values.

In Lipi: `and`, `or`, `not`. No short-circuit: both operands are always evaluated. `not` binds tighter than comparison, so `not 1 > 2` is a type error.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operations/bool) | `&& \|\| !` | Looks alike, behaves differently | Written with symbols, not and/or/not. MQL4 stops evaluating once the result is known; Lipi always evaluates both operands. State and side effects: Short-circuit: a right operand with side effects may not run in MQL4 but always runs in Lipi. |
| [MQL5](https://www.mql5.com/en/docs/basis/operations/bool) | `&& \|\| !` | Looks alike, behaves differently | MQL5 stops once the result is known; Lipi evaluates both operands, so a guard such as i \< n does not protect the right side. State and side effects: A right-hand call or array access is skipped in MQL5 when the left side decides; in Lipi it always runs. |
| [NinjaScript](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators#conditional-logical-and-operator-) | `&&, \|\|, !` | Looks alike, behaves differently | Written && \|\| !. C# skips the right side once the left decides; Lipi evaluates both, so a guard such as i \< n fails. |
| [Pine Script](https://www.tradingview.com/pine-script-reference/v6/) | `and, or, not` | Looks alike, behaves differently | Pine v6 and/or are lazy: the right side is skipped once the left decides. Lipi evaluates both, so guards like i \< n fail. State and side effects: Pine skips the right operand when the left decides; Lipi always evaluates it. Warm-up and missing values: Pine v6 bools are never na; in Lipi na and false gives na. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Operators/Logical) | and, &&, or, !, is true, is false | Equivalent, with a caveat | Works on numbers: 0 is false and anything else true; also has word forms such as is true and is false. |

## Update in place

Changing a variable by an amount in one step, such as adding to a running total.

In Lipi this is written with the language's own syntax. `+=` also joins strings. `/=` on an int variable is rejected because `/` returns float.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("Running volume")
static float total = 0.0
total += volume
plot(total, title="Volume so far")
```

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/operations/assign) | `+= -= *= /= %=` | Equivalent, with a caveat | %= keeps the sign of the dividend. Integer operands follow integer arithmetic, so /= on an int is allowed, where Lipi rejects it. Numbers and types: Integer operands keep integer arithmetic under /= and %=. |
| [MQL5](https://www.mql5.com/en/docs/basis/operations/assign) | += -= \*= /= %= \<\<= >>= &= \|= ^= | Equivalent, with a caveat | Same operators. Lipi refuses /= on an int variable, because dividing two ints gives a float; declare the variable float. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/basic_syntax.htm) | `+=, -=, *=, /=` | Equivalent, with a caveat | Same operators. Lipi refuses /= on an int variable, because dividing two ints gives a float; declare the variable float. |
| [Pine Script](https://www.tradingview.com/pine-script-docs/language/operators/#compound-assignment-operators) | +=  -=  \*=  /=  %= | Equivalent, with a caveat | Same operators. Lipi refuses /= on an int variable, because dividing two ints gives a float; declare the variable float. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Operators) | | Not in thinkScript | Only plain = exists; accumulate with a self-referencing def such as def total = total\[1] + x. |

## Key-value collection

A collection that stores values under keys.

Lipi has no construct for this. Lipi has no key-value collection type; use two arrays kept in step, or a user type.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/types) | | Not in MQL4 | The Data Types list has numeric, string, struct, class, dynamic array and pointer entries but no key-value collection. Use parallel arrays or your own class. |
| [MQL5](https://www.mql5.com/en/docs/standardlibrary/generic/chashmap) | `CHashMap<TKey,TValue>` | No Lipi equivalent | A standard-library generic class of key/value pairs; the Lipi workaround is two arrays kept in step. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/c_method_functions_reference.htm) | `Dictionary<TKey, TValue> (.NET)` | No Lipi equivalent | Standard .NET class; the NinjaTrader page only points to the .NET class library. In Lipi use two parallel arrays or a user type. |
| [Pine Script](https://www.tradingview.com/pine-script-reference/v6/) | `map<K, V>, map.new<K, V>()` | No Lipi equivalent | Use two arrays kept in step, or an array of a user type. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types) | | Not in thinkScript | No key-value type; the data types list contains no collections at all. |

## Two-dimensional collection

A collection with rows and columns.

Lipi has no construct for this. Lipi has no matrix type; use an array with computed indexes.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/variables) | `multi-dimensional array, e.g. double a[][4]` | No Lipi equivalent | Arrays may have up to four dimensions; in Lipi use one array with computed indexes. |
| [MQL5](https://www.mql5.com/en/docs/basis/types/matrix_vector) | matrix; matrixf; matrixc | No Lipi equivalent | Built-in two-dimensional types holding double, float or complex elements; the Lipi workaround is a flat array with computed indexes. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/c_method_functions_reference.htm) | `double[,] or jagged arrays (.NET)` | No Lipi equivalent | C# arrays are linked from the same page. Lipi has no matrix type; use one array with computed indexes. |
| [Pine Script](https://www.tradingview.com/pine-script-reference/v6/) | `matrix<T>, matrix.new<T>()` | No Lipi equivalent | Use one array and compute the index as row \* columns + column. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Data-Types) | | Not in thinkScript | No two-dimensional type; the data types list contains no collections at all. |

## Reuse code from another file

Bringing in functions or types published in a separate file or library.

Lipi has no construct for this. A Lipi script is one file; copy the functions you need into it.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/basis/preprosessor/include) | #include, #import | No Lipi equivalent | #include pulls in source files and #import calls functions from compiled libraries; a Lipi script is a single file. |
| [MQL5](https://www.mql5.com/en/docs/basis/preprosessor/import) | #import; #include | No Lipi equivalent | Imports functions from compiled .ex5 or .dll modules; Lipi scripts are single files, so copy the code in. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/considerations_for_compiled_assemblies.htm) | C# using directives, namespaces and compiled assemblies | No Lipi equivalent | Scripts can reference other types by namespace or through compiled DLLs. Lipi is single-file: copy the functions you need into the script. |
| [Pine Script](https://www.tradingview.com/pine-script-reference/v6/) | import user/library/version as alias; library(); export | No Lipi equivalent | Copy the functions you need into the single Lipi file. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-13---Referencing-Other-Data) | | Not in thinkScript | Scripts cannot import user code: reference only pulls built-in studies, and script blocks stay inside one file. |

## Stop with an error

Ending the script on purpose with a message when a condition is not met.

Lipi has no construct for this. Lipi has no function that raises a runtime error; guard the calculation and skip it instead.

| Language | Construct | Relation | Note |
| - | - | - | - |
| [MQL4](https://docs.mql4.com/common/expertremove) | Print or Alert then return; ExpertRemove() | No Lipi equivalent | No raise statement: report with Alert or Print and return, or call ExpertRemove to unload an Expert Advisor. Lipi: guard the calculation. |
| [MQL5](https://www.mql5.com/en/docs/basis/function/events) | return INIT\_FAILED from OnInit; ExpertRemove() | No Lipi equivalent | No call raises a custom error: INIT\_FAILED leaves an indicator inoperative, ExpertRemove unloads an Expert Advisor only; in Lipi, guard and skip. |
| [NinjaScript](https://ninjatrader.com/support/helpGuides/nt8/log.htm) | `Log(message, LogLevel.Error)` | No Lipi equivalent | Log() writes to the Control Center Log tab and the log file; it is logging, not an exit. Lipi has no raise; guard and skip. |
| [Pine Script](https://www.tradingview.com/pine-script-reference/v6/#fun_runtime.error) | `runtime.error()` | No Lipi equivalent | Guard the calculation and skip it; Lipi cannot halt the script on purpose. |
| [thinkScript](https://toslc.thinkorswim.com/center/reference/thinkScript/Functions/Others/Assert) | `Assert` | No Lipi equivalent | Assert stops the plots and shows an error flag when the condition is false; in Lipi guard the calculation and skip it. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.