Each Operator (∘.) on Empty Arrays: Undefined Behavior?
0 reputation · 05 May 2021, 14:08 UTC
What is the defined result of applying the each operator (∘.) to an empty array in APL, and how do different implementations handle this case?
0 reputation · 05 May 2021, 14:08 UTC
What is the defined result of applying the each operator (∘.) to an empty array in APL, and how do different implementations handle this case?
34775 reputation · 05 May 2021, 22:42 UTC
In APL the each operator (∘.) is a *reduction‑like* operator that applies a function to every element of an array. When the input array is empty (⍬), the language itself does not prescribe a single result. The ISO/IEC 13751 standard only specifies that *reduction* operators on empty arrays should use an identity element, but it does not extend that rule to the each operator. Consequently, the outcome is implementation‑defined.
∘.f¨ ⍬ returns an empty array with the prototype of the function’s output. The shape is ⍴⍬ (0 elements) and the type matches the function’s return type. No error is raised.f expects at least one argument, APL2 raises a DOMAIN ERROR when applied to ⍬. If f can be invoked with zero arguments (e.g., an identity function), it returns an empty array of the expected shape.⍬, but for a function returning a vector it may be ⍬⍬.When porting code that uses ∘. across dialects, assuming a consistent scalar, vector, or error result can lead to subtle bugs. For example, a function that relies on the identity element of a numeric array will work in Dyalog but fail in APL2 if the empty case is not handled explicitly.
f←{⍵+1}.
⍝ Dyalog or GNU APL
∘.f¨ ⍬
⍴⍬ ⍝ should be 0
⎕PW ⍝ prototype (type)
⎕FMT ⍝ format string for debugging
{⍵⍵} will error on ⍬).empty←⍬
result←∘.f¨ empty
⍝ If result is empty, use a default value
To give a more precise recommendation, it would help to know the function being applied (e.g., does it have side effects, does it require a non‑empty argument, does it return a scalar or vector?). If you can provide that, we can refine the guidance for your specific case.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 05 May 2021, 14:44 UTC
In standard APL the each operator is a map, so with an empty right argument there are no items for the left function to apply to. The result is an empty array whose rank and shape correspond to the right argument, not an error or undefined value.
That means an empty vector mapped by a monadic function returns an empty vector of the same rank, and an empty matrix mapped returns an empty matrix with the same number of dimensions. A practical check is to inspect the shape of the result after the each application.