Now accepting guest editorial from SAP, Oracle, Workday and ServiceNow practitioners.Pitch a guide
The Sign-Off Table

Lesson 3 of 6

Constructor expressions: VALUE, CORRESPONDING, REDUCE, FILTER, COND, SWITCH

11 min

Listen to this lesson

0:00 / 11:29

A constructor expression builds a value in one expression: OPERATOR type( ... ), where type is a type name or # for "the type the context expects". They replace sequences of CLEAR, APPEND, MOVE-CORRESPONDING, IF and CASE statements. SAP's constructor expressions cheat sheet lists them all; this lesson covers the ones Contoso's developers use daily, with the classic form each replaces.

OperatorBuildsReplacesContoso example
VALUEStructures and internal tablesCLEAR + field assignments + APPENDitems = VALUE #( ( product = 'CMC-ALT-100' qty = 12 ) ( product = 'CMC-ALT-240' qty = 2 ) ).
NEWObject or data referenceCREATE OBJECT / CREATE DATADATA(calc) = NEW zcl_cmc_core_deposit( ).
CONVA value of a given typeHelper variables for type conversionDATA(rate) = CONV decfloat34( 45 ).
CORRESPONDINGStructure or table from another, by nameMOVE-CORRESPONDINGout = CORRESPONDING #( agr MAPPING customer_id = customer ).
CONDOne value from conditionsIF / ELSEIF assigning one variableCOND #( WHEN qty > 100 THEN 'BULK' ELSE 'STD' )
SWITCHOne value from a case on one operandCASE assigning one variableSWITCH #( status WHEN 'OPEN' THEN 'Active' WHEN 'CLOSED' THEN 'Ended' )
REDUCEOne value from iteratingLOOP that accumulates a totalREDUCE #( INIT s = 0 FOR i IN items NEXT s = s + i-deposit )
FILTERA table of rows matching a keyLOOP + IF + APPENDFILTER #( agreements USING KEY by_status WHERE status = 'OPEN' )
REFA data referenceGET REFERENCE OF (rejected in ABAP Cloud)DATA(r) = REF #( total ).

The constructor operators covered in this lesson, with the classic statements they replace.

VALUE and CORRESPONDING

VALUE builds a structure or a table in one statement; each inner pair of parentheses is a row. BASE keeps the existing rows: items = VALUE #( BASE items ( product = ... ) ) appends, while leaving out BASE replaces the table. CORRESPONDING copies components with the same names; MAPPING maps different names and EXCEPT leaves components out. One trap: without BASE, components of the target that have no source are initialized, unlike MOVE-CORRESPONDING, which leaves them untouched.

CORRESPONDING copies by name and initializes target components with no source, unless BASE keeps the target's values.
The Sign-Off Table · thesignofftable.com/academy/sap-abp-206

NEW and CONV are the simplest operators and the ones classic developers adopt first. NEW zcl_cmc_core_deposit( ) replaces CREATE OBJECT and can be used directly as an argument. CONV converts a value to a named type in place, which removes the helper variables classic code declared only to change a type before a method call, for example calc->set_rate( CONV #( rate_text ) ). Use CONV deliberately: a conversion that can fail (text to number) still raises its exception, it just happens inside the expression.

REDUCE and FILTER

REDUCE iterates and accumulates: Contoso's total deposit for an agreement is REDUCE decfloat34( INIT sum = 0 FOR item IN items NEXT sum = sum + item-quantity * item-deposit_per_unit ). For 12 units of CMC-ALT-100 at 45.00 and 2 units at 25.00, it returns 590.00. FILTER returns the rows that match a condition on a key: the table needs a sorted or hashed key (primary or secondary) on the filtered components. FILTER ... EXCEPT returns the rows that do not match. For conditions that cannot use a key, use VALUE #( FOR ... WHERE ( ... ) ( ... ) ) instead.

  1. ClassicCLEAR lv_sum. LOOP AT lt_items INTO ls_item. lv_sum = lv_sum + ls_item-qty * ls_item-rate. ENDLOOP.
  2. Test firstPin the result: 590.00 for the two-item agreement; 0 for no items
  3. ModernDATA(sum) = REDUCE decfloat34( INIT s = 0 FOR i IN items NEXT s = s + i-qty * i-rate ).
  4. Check typeThe INIT type decides the result type; decfloat34 avoids integer truncation
  5. Re-runBoth tests green; review for readability
Refactoring Contoso's legacy total calculation step by step.
The Sign-Off Table · thesignofftable.com/academy/sap-abp-206

COND and SWITCH

COND returns a value from the first true WHEN; SWITCH compares one operand against constant values. Both may raise exceptions with THEN THROW. If no branch matches and there is no ELSE, the result is initial, which is a quiet source of defects: a status text that is blank for a new status nobody anticipated. Always write an ELSE, even if it throws.

  1. Building a structure or table from literals or fields?Yes → VALUE (with BASE to keep rows) · No → next question
  2. Copying fields between structures or tables?Yes → CORRESPONDING (MAPPING, EXCEPT, BASE) · No → next question
  3. Reducing many rows to one value?Yes → REDUCE with an explicit INIT type · No → next question
  4. Selecting rows by a key condition?Yes → FILTER (needs a sorted or hashed key) · No → VALUE #( FOR ... WHERE ... )
  5. Choosing one value by conditions?Yes → COND, or SWITCH for one operand; always with ELSE
Choosing the right constructor expression.
The Sign-Off Table · thesignofftable.com/academy/sap-abp-206

What goes wrong in testing

  • REDUCE with an integer INIT. INIT s = 0 with # can produce an integer sum and drop decimals. Name the type.
  • CORRESPONDING wipes fields. Target fields with no source are initialized. Tests that check only the copied fields miss it.
  • VALUE without BASE. Meant to append, but replaces the table.
  • FILTER on a table without a suitable key. A syntax error, so the developer switches to a loop; better to define a secondary key.
  • COND without ELSE. A new status value produces a blank text.
Every constructor-expression refactoring passes through a pinned, tested state; a red test sends it back.
The Sign-Off Table · thesignofftable.com/academy/sap-abp-206

What would you do?

After Kenji refactored a MOVE-CORRESPONDING into CORRESPONDING #( ), Dan notices that the total deposit field in a report output is now always 0.00. What happened?

Key points
  • Constructor expressions build values in one expression; # means the type the context expects.
  • VALUE replaces a table unless you use BASE; CORRESPONDING initializes target fields with no source.
  • REDUCE needs an explicit INIT type for amounts; FILTER needs a sorted or hashed key.
  • COND and SWITCH should always have an ELSE.

Check your understanding · not graded

Lesson check

  1. 1. What does # mean in VALUE #( ... )?

  2. 2. How do you append a row with VALUE without losing existing rows?

  3. 3. What does FILTER require of the internal table?

  4. 4. Why name the type in REDUCE decfloat34( INIT s = 0 ... )?

  5. 5. What does COND return when no WHEN matches and there is no ELSE?