The ternary operator is a handy syntax for creating a result based on a (scalar) condition that is evaluated for truth. For example, I frequently use it to set a default value for an input variable, like the following that uses a default value of 5.0 if x is not present:

_x = n_elements(x) eq 0L ? 5.0 : x

Without the syntax, you would need an if statement:

if (n_elements(x) eq 0L) then _x = 5.0 else _x = x

(Or, in this case, a special purpose routine like default.) But, besides being a bit longer, the if statement hides the possibility that you might not assign to _x in both cases of the if statement, whereas it is clear in the ternary statement that _x is going to receive a value in any case.

The ternary statement is even more useful because it can be chained with other statements. For example,

results[f] = day + (year eq currentYear $
                      ? string(time, format='(A6)') $
                      : string(year, format='(I6)'))

Without the ternary operator, this would require a new local variable and would be twice as long:

if (year eq currentYear) then begin
  yeartime = string(time, format='(A6)')
endif else begin
  yeartime = string(year, format='(I6)')
endelse
result[f] = day + yeartime

One of the main limitations to the ternary operator is that, like an if statement, the condition must be evaluated to a scalar truth value. I would like to extend the ternary operator to arrays. Let’s see how it would work.

First, let’s create some arrays to use in the examples:

IDL> x = findgen(5)
IDL> y = 2 * findgen(5)
IDL> z = lindgen(5) mod 2
IDL> print, x
      0.00000      1.00000      2.00000      3.00000      4.00000
IDL> print, y
      0.00000      2.00000      4.00000      6.00000      8.00000
IDL> print, z
           0           1           0           1           0

Then, my proposal would be for the following lines to work:

IDL> print, z ? x : y
      0.00000      1.00000      4.00000      3.00000      8.00000

One, or both, of the operators could be a scalar:

IDL> print, z ? 1.0 : y
      0.00000      1.00000      4.00000      1.00000      8.00000
IDL> print, z ? 1.0 : 2.0
      2.00000      1.00000      2.00000      1.00000      2.00000

Now, of course, this can be done already, but it takes a lot more code. For example, the first case expands from one line to:

IDL> result = fltarr(5)
IDL> ind = where(z, count, complement=not_ind, ncomplement=not_count)
IDL> if (count gt 0L) then result[ind] = x[ind]
IDL> if (not_count gt 0L) then result[not_ind] = y[not_ind]
IDL> print, result
      0.00000      1.00000      4.00000      3.00000      8.00000

IDL already has rules for type promotion if an operation has operands of two differing types; those could be used here to determine the type of the result since the elements of both value operands would be intermixed in a single array.