millionchart
فارسی

Lazy operators

The right side of `and`, `or` and `??` and the arms of `if ... then ... else` run only when they are needed. What is safe to write there.

Edition 1 runs the right side of and, or and ??, and the arms of a one-line if ... then ... else, only when it is needed. That is why a call that keeps a state may not stand directly in them (E3302).

Lazy operators#

and, or and ?? run their right side only when needed; pure operands are fine.

Cuprel
// `and`, `or`, `??` and the two arms of `if ... then ... else` run their right side only when it is needed.
// Pure operands (plain arithmetic, comparisons, values already bound to a name) are always fine there.
indicator "Lazy operators"
    edition = 1
    display = price

let average = tech.sma(close, 20)
let above = close > average
let near = math.abs(close - average) < tech.atr(14)
let signal = above and near
let fallback = average ?? close
plot(if signal then fallback else na, name = "Near and above", style = circles)

Guarded read#

A size test on the left of and keeps a read on the right from failing; an arm of if-then-else that is not chosen is not read.

Cuprel
// The right side of "and" runs only when the left side is true, and so does an arm of "if ... then ... else" that is not chosen: neither is read at all.
// That lets a guard protect a read that would fail. The array holds the rises of the close; its tenth item does not exist until ten rises have been seen,
// and the size test on the left keeps the read on the right from ever failing.
indicator "Guarded read"
    edition = 1
    display = pane

state gains: array<float> = array<float>()
if close > close[1]
    gains.push(close - close[1])
let tenth_is_big = gains.size() > 9 and gains.at(9) > 2
let newest = if gains.size() > 0 then gains.last() else 0.0
let flag = if tenth_is_big then 1 else 0
plot(flag, name = "Tenth rise is big", style = histogram, color = color.green)
plot(newest, name = "Newest rise", color = color.blue)
plot(gains.size(), name = "Rises seen", display = none)

Read past the end of an array#

Without the size test the tenth item is read before it exists.

Cuprel · error E5602
// A mistake on purpose: without the size test on the left, the tenth item is read before it exists.
indicator "Guarded read"
    edition = 1
    display = pane

state gains: array<float> = array<float>()
if close > close[1]
    gains.push(close - close[1])
let tenth_is_big = gains.at(9) > 2
let newest = if gains.size() > 0 then gains.last() else 0.0
let flag = if tenth_is_big then 1 else 0
plot(flag, name = "Tenth rise is big", style = histogram, color = color.green)
plot(newest, name = "Newest rise", color = color.blue)
plot(gains.size(), name = "Rises seen", display = none)