diff --git a/05_Constructor_Expressions.md b/05_Constructor_Expressions.md
index 869c7bc..79bc003 100644
--- a/05_Constructor_Expressions.md
+++ b/05_Constructor_Expressions.md
@@ -14,9 +14,10 @@
- [COND](#cond)
- [SWITCH](#switch)
- [FILTER](#filter)
- - [REDUCE](#reduce)
- - [Iteration Expressions with FOR](#iteration-expressions-with-for)
- [LET Expressions](#let-expressions)
+ - [Iteration Expressions](#iteration-expressions)
+ - [Iteration Expressions Using FOR](#iteration-expressions-using-for)
+ - [REDUCE](#reduce)
- [Executable Example](#executable-example)
## Introduction
@@ -64,11 +65,12 @@
go: `DATA(dec) = VALUE decfloat34( '1.23' )`.
> **✔️ Hint**
-> The construction of a result, i. e. a target [data
+>- The construction of a result, i. e. a target [data
object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm "Glossary Entry"),
implies that the data object is initialized. However, for some
constructor operators, there is an addition with which the
initialization can be avoided.
+>- As is true for many of the following syntax options, you can do a lot with constructor expressions, often with fewer lines (than older syntax equivalents) of code in a very elegant way. However, keep in mind the readability, maintainability, and debuggability of your code.
⬆️ back to top
@@ -701,6 +703,7 @@ DATA(b) = SWITCH #( a
⬆️ back to top
+
## FILTER
- The
@@ -770,76 +773,138 @@ DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num =
⬆️ back to top
-## REDUCE
-- The
- [`REDUCE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_reduce.htm)
- operator creates a result of a specified or derived type from one or
- more [iteration
- expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry").
-- It basically reduces sets of data objects to a single data object.
- For example, the numeric values of a table column are summed up. As
- a result, the total number is constructed.
+## LET Expressions
-The following example calculates the total of the numbers from 1 to 10
-using the `REDUCE` operator:
-``` abap
-"sum: 55
-DATA(sum) = REDUCE i( INIT s = 0
- FOR i = 1 UNTIL i > 10
- NEXT s += i ) ).
+- Define one or more variables (field symbols are also possible) as local (i.e. local to the expression) helper fields and assigns values to them.
+- In the definition, the right-hand side value is declared as if an inline declaration is used. The data type is derived accordingly.
+- Only to be used in constructor expressions (see the syntax diagrams in the ABAP Keyword Documentation where exactly [`LET`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaplet.htm) expressions can be specified).
+
+See the following simple examples to get an idea about the use:
+
+```abap
+"Data type and object to work with in the example
+TYPES: BEGIN OF st_type,
+ comp1 TYPE c LENGTH 5,
+ comp2 TYPE i,
+ comp3 TYPE i,
+ END OF st_type.
+DATA it TYPE TABLE OF st_type WITH EMPTY KEY.
+it = VALUE #( ( comp1 = 'a' comp2 = 1 comp3 = 30 )
+ ( comp1 = 'bb' comp2 = 2 comp3 = 10 )
+ ( comp1 = 'ccc' comp2 = 3 comp3 = 20 ) ).
+
+"Constructing a data object with elementary data type using the CONV operator
+"One or more helper variables are possible specified after LET
+DATA(hi) = CONV string(
+ LET name = cl_abap_context_info=>get_user_technical_name( )
+ date = cl_abap_context_info=>get_system_date( )
+ IN |Hi { name }. Today's date is { date DATE = ISO }.| ).
+
+"Construction similar to the previous example
+"Depending on the time, a string is created. In the example, a LET expression
+"is specified for each constructor expression.
+DATA(time_of_day) = CONV string(
+ LET time = cl_abap_context_info=>get_system_time( ) IN
+ COND string( LET good = `Good` ending = `ing` IN
+ WHEN time BETWEEN '050001' AND '120000' THEN good && ` morn` && ending "Good morning
+ WHEN time BETWEEN '120001' AND '180000' THEN good && ` afternoon`
+ WHEN time BETWEEN '180001' AND '220000' THEN good && ` even` && ending
+ ELSE `night` ) ).
+
+
+"Getting a particular column name of an existing internal table using a RTTI
+"An internal table (it contains information on the table's structured type; the
+"component names, among others) is assigned to a data object that is declared
+"inline. This is an example of how powerful constructor expressions (and inline
+"declarations) are: You can make code more concise. Think of extra declarations
+"for the data objects, or using the older ?= operator for the casts. Many more
+"lines of code would be required.
+DATA(components) = CAST cl_abap_structdescr( CAST cl_abap_tabledescr(
+ cl_abap_typedescr=>describe_by_data( it ) )->get_table_line_type( ) )->components.
+DATA(comp2_a) = components[ 2 ]-name. "COMP2
+
+"Achieving the result from above even in one statement using LET
+DATA(comp2_b) = CONV abap_compname(
+ LET comps = CAST cl_abap_structdescr( CAST cl_abap_tabledescr(
+ cl_abap_typedescr=>describe_by_data( it ) )->get_table_line_type( ) )->components
+ IN comps[ 2 ]-name ).
+
+"Constructing a structure using local variables
+"The example uses the NEW operator to create an anonymous data object
+DATA(new_struc) = NEW st_type( LET num = 2 ch = 'AP' IN
+ comp1 = 'AB' && ch comp2 = 2 * num comp3 = 3 * num ).
+"Structure content:
+"COMP1 COMP2 COMP3
+"ABAP 4 6
+
+"Constructing an internal table using local variables
+"The example uses the VALUE operator.
+"Note the parentheses ( ... ) representing table lines.
+DATA(itab_value) = VALUE string_table( LET line = 1 IN
+ ( |Line { line }| )
+ ( |Line { line + 1 }| )
+ ( |Line { line + 2 }| ) ).
+"Table line content:
+"Line 1
+"Line 2
+"Line 3
+
+"Using a local field symbol in LET expressions
+"- The right-hand side value must be the result of a writable expression, i.e.
+" an operand that can be written to
+"- This value is then assigned to the local field symbol (as if ASSIGN is used)
+"- In the examples above, a specification such as ... LET = 1 IN ... is not
+" possible as they are not writable expressions.
+"- Writable expressions:
+" - Constructor expressions NEW class( ... )->attr and CAST type( ... )->dobj
+" - Table expressions itab[ ... ] and their chainings, e.g. itab[ 1 ]-comp
+"In the following example, an internal table is looped over. A string is created
+"from the table line content. In the constructor expression, a LET expression is
+"specified that uses a field symbol. It is assigned the line of the internal table.
+"The sy-index value represents the table index value.
+DATA str_tab TYPE string_table.
+DO lines( it ) TIMES.
+ DATA(concatenated_tab) = CONV string(
+ LET = it[ sy-index ]
+ comma = `, `
+ IN |{ -comp1 }{ comma }{ -comp2 }{ comma }{ -comp3 }| ).
+ str_tab = VALUE #( BASE str_tab ( concatenated_tab ) ).
+ENDDO.
+"Table line content:
+"a, 1, 30
+"bb, 2, 10
+"ccc, 3, 20
```
-> **💡 Note**
-> - `INIT ...`: A temporary variable is specified that sets an
- initial value for the result variable.
->- `FOR ...`: Represents a loop. The loop is carried out until
- the condition is met after `UNTIL`.
->- `NEXT ...`: Represents the assignment to the temporary
- variable after every iteration.
->- Once the loop has finished, the target variable is assigned the
- resulting value.
-
⬆️ back to top
-## Iteration Expressions with FOR
+## Iteration Expressions
-- Using [iteration
- expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry")
- with the language element
- [`FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor.htm),
- you can carry out [conditional
- iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor_conditional.htm)
+- Iteration expressions are expressions ...
+ - that perform an iteration and that are possible in specific constructor expressions (`NEW`, `VALUE`, `REDUCE`).
+ - that are introduced by the iteration operator `FOR`.
+ - that can optionally be used to create lines in internal tables.
+- `REDUCE` operator: Special reduction operator that is based on [iteration expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry"), i.e. it is mandatory to specify iteration expressions with `FOR` when using `REDUCE`.
+
+### Iteration Expressions Using FOR
+
+- Two flavors for iterations using [`FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor.htm):
+ - [Conditional iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor_conditional.htm)
(including the ABAP words `UNTIL` and `WHILE` which
have the semantics of ABAP statements
[`DO`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdo.htm)
and
- [`WHILE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhile.htm))
- or [table
- iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_iteration_glosry.htm "Glossary Entry")
- (having the semantics of [`LOOP AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_variants.htm);
- the expressions include the ABAP word `IN`).
-- Such expressions are possible in the following contexts:
- - `REDUCE`: The reduction result is created in the
- iteration steps.
- - `NEW` and `VALUE`: Used in the context of
+ [`WHILE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhile.htm))
+ - [Table iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_iteration_glosry.htm "Glossary Entry"):
+ Have the semantics of [`LOOP AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_variants.htm) and
+ include the addition `IN`.
+- Where possible:
+ - `REDUCE`: Mandatory `FOR` specification. The reduction result is created in the
+ iteration steps.
+ - `NEW` and `VALUE`: Optional `FOR` specification. Used in the context of
looping across internal tables. New table lines are created in
the iteration steps and inserted into a target table.
-
-`FOR ... WHILE`: The following example with `REDUCE`
-has the same effect as the example using `UNTIL` shown above.
-
-``` abap
-DATA(sum) = REDUCE i( INIT y = 0
- FOR n = 1 THEN n + 1 WHILE n < 11
- NEXT y += n ).
-```
-
-`FOR ... UNTIL`: See the example in the `REDUCE`
-section.
-
-`FOR ... IN`:
-
- The operand specified after `FOR` represents an iteration
variable, i. e. a [work
area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry")
@@ -856,77 +921,384 @@ section.
- In contrast to `LOOP` statements, the sequential processing
cannot be debugged.
-Some examples for looping across tables and storing values in target
-tables:
-``` abap
-"Looping across table and storing the whole line in a new table;
-"the target table must have the same table type as the source table itab;
-"without the WHERE condition, all lines are respected
+```abap
+"Data objects and types to work with in the examples
+TYPES: BEGIN OF s,
+ col1 TYPE c LENGTH 5,
+ col2 TYPE i,
+ col3 TYPE i,
+ END OF s.
+TYPES itab_type TYPE TABLE OF s WITH EMPTY KEY.
+DATA(itab) = VALUE itab_type( ( col1 = 'a' col2 = 1 col3 = 30 )
+ ( col1 = 'bb' col2 = 2 col3 = 10 )
+ ( col1 = 'ccc' col2 = 3 col3 = 20 ) ).
-TYPES t_type LIKE itab.
+"-------------- Table iterations --------------
-... = VALUE t_type( FOR wa IN itab
- "WHERE ( comp1 > 2 )
- ( wa ) ).
+DATA(it1) = VALUE itab_type( FOR wa IN itab ( col1 = wa-col1 && 'z'
+ col2 = wa-col2 + 1 ) ).
-"Storing specific components having different names by specifying the assignment
-"individually; assumption: the target type is not compatible to the type of itab;
-"a field mapping is provided; pay attention to potential type conversion
+"LOOP AT equivalent
+CLEAR it1.
+LOOP AT itab REFERENCE INTO DATA(ref).
+ APPEND VALUE #( col1 = ref->col1 && 'z'
+ col2 = ref->col2 + 1 ) TO it1.
+ENDLOOP.
-... = VALUE t_type( FOR wa IN itab
- "WHERE ( comp1 > 2 )
- ( compX = wa-comp1
- compY = wa-comp2 ) ).
+*COL1 COL2 COL3
+*az 2 0
+*bbz 3 0
+*cccz 4 0
-"Storing specific components having the same names;
-"assumption: Target type is not compatible to the type of itab;
-"if there are identically named components in the table types, you might
-"also use CORRESPONDING
+"The following example shows more syntax options
+"- Field symbol specifed after FOR
+"- LET expressions after FOR: Denotes that the LET
+" expressions is evaluated for each loop pass
+"- INDEX INTO addition (the variable that follows implicitly
+" has the type i): Storing the sy-tabix value for each
+" loop pass
+DATA(it2) = VALUE itab_type( FOR IN itab INDEX INTO idx
+ LET idxplus1 = idx + 1 IN
+ ( col1 = -col1 col2 = idx col3 = idxplus1 ) ).
-... = VALUE t_type( FOR wa IN itab
- "WHERE ( comp1 > 2 )
- ( CORRESPONDING #( wa ) ) ).
+*COL1 COL2 COL3
+*a 1 2
+*bb 2 3
+*ccc 3 4
-"Multiple iteration expressions
+"Similar to the example above, the following example uses the INDEX INTO
+"addition, as well as a LET expression with multiple local variables
+DATA(it3) = VALUE string_table( FOR IN itab INDEX INTO idx
+ LET col1 = |COL1: "{ -col1 }"|
+ col2 = |COL2: "{ -col2 }"|
+ col3 = |COL3: "{ -col3 }"|
+ str_to_be_added = |Table index { idx } -> { col1 } / { col2 } / { col3 }|
+ IN ( str_to_be_added ) ).
-... = VALUE t_type( FOR wa1 IN itab1 WHERE ( comp1 = 4 )
- FOR wa2 IN itab2 WHERE ( comp2 > 5 )
- FOR wa3 IN itab3 WHERE ( comp3 < 3 )
- ( compX = wa1-comp1
- compY = wa2-comp2
- compZ = wa3-comp3 ) ).
+*Table index 1 -> COL1: "a" / COL2: "1" / COL3: "30"
+*Table index 2 -> COL1: "bb" / COL2: "2" / COL3: "10"
+*Table index 3 -> COL1: "ccc" / COL2: "3" / COL3: "20"
+
+"---------- Excursions ----------
+
+"FOR expression are very handy, for example, in EML and other statements.
+"The following example commented out shows an EML statement in the implementation
+"of a handler method taken from an EML cheat sheet example.
+"'result' is an input parameter/internal table containing RAP BO instance data on whose
+"basis, an EML MODIFY statement is executed. A suitable internal table is constructed
+"in place and that is used as operand of the MODIFY ... UPDATE FIELDS ... WITH ...
+"statement.
+
+"MODIFY ENTITIES OF zdemo_abap_rap_ro_u IN LOCAL MODE
+" ENTITY root
+" UPDATE FIELDS ( field3 field4 ) WITH VALUE #( FOR key IN result ( %tky = key-%tky
+" field3 = key-field3 * 2
+" field4 = key-field4 * 2 ) ).
+
+"Merging tables
+"In the following example, the content of two existing internal tables is merged.
+"In the simple example, the index is used for the table index. You can also imagine
+"that you merge two internal tables, both having multiple columns. You could refer
+"to the specific component values, for example, using a free key in a table expression
+"such as ... VALUE #( some_itab[ comp_x = wa-comp_y ]-comp_z DEFAULT ... ) ...
+TYPES int_tab_type TYPE TABLE OF i WITH EMPTY KEY.
+DATA(inttab) = VALUE int_tab_type( ( 99 ) ( 100 ) ).
+
+DATA(it4) = VALUE itab_type( FOR wa IN itab INDEX INTO idx
+ ( col1 = wa-col1 col2 = VALUE #( inttab[ idx ] DEFAULT 0 ) ) ).
+
+*COL1 COL2 COL3
+*a 99 0
+*bb 100 0
+*ccc 0 0
+
+"Retaining non-specified column values using the BASE addition
+"In the example, the original value of col3 is retained.
+DATA(it5) = VALUE itab_type( FOR wa IN itab ( VALUE #( BASE wa col1 = wa-col1 && 'y'
+ col2 = wa-col2 + 3 ) ) ).
+
+*COL1 COL2 COL3
+*ay 4 30
+*bby 5 10
+*cccy 6 20
+
+"Using the CORRESPONDING operator to handle different types
+TYPES: BEGIN OF s2,
+ col1 TYPE c LENGTH 5,
+ col2 TYPE i,
+ str TYPE string,
+ END OF s2.
+TYPES itab_type_2 TYPE TABLE OF s2 WITH EMPTY KEY.
+
+DATA(it6) = VALUE itab_type_2( FOR wa IN itab ( CORRESPONDING #( wa ) ) ).
+
+*COL1 COL2 STR
+*a 1
+*bb 2
+*ccc 3
+
+"Multiple FOR expressions that work like nested loops
+DATA(it7) = VALUE string_table( FOR wa1 IN itab
+ FOR wa2 IN inttab
+ ( |Comp. 1st itab: "{ wa1-col1 }", comp. 2nd itab: "{ wa2 }"| ) ).
+
+*Comp. 1st itab: "a", comp. 2nd itab: "99"
+*Comp. 1st itab: "a", comp. 2nd itab: "100"
+*Comp. 1st itab: "bb", comp. 2nd itab: "99"
+*Comp. 1st itab: "bb", comp. 2nd itab: "100"
+*Comp. 1st itab: "ccc", comp. 2nd itab: "99"
+*Comp. 1st itab: "ccc", comp. 2nd itab: "100"
+
+"LOOP AT equivalent
+CLEAR it7.
+LOOP AT itab INTO DATA(wa3).
+ LOOP AT inttab INTO DATA(wa4).
+ it7 = VALUE #( BASE it7 ( |Comp. 1st itab: "{ wa3-col1 }", comp. 2nd itab: "{ wa4 }"| ) ).
+ ENDLOOP.
+ENDLOOP.
+
+"More additions can be specified such as WHERE, USING KEY, FROM/TO, STEP
+
+"WHERE condition
+"The WHERE condition must be placed in parentheses.
+DATA(it8) = VALUE itab_type( FOR wa IN itab WHERE ( col2 < 3 ) ( col1 = wa-col1 && 'w'
+ col2 = 5
+ col3 = wa-col2 ) ).
+*COL1 COL2 COL3
+*aw 5 1
+*bbw 5 2
+
+"FROM/TO additions
+DATA(it9) = VALUE itab_type( FOR wa IN itab FROM 2 TO 3 ( col1 = wa-col1 && 'v'
+ col2 = 6
+ col3 = wa-col2 + 5 ) ).
+
+*COL1 COL2 COL3
+*bbv 6 7
+*cccv 6 8
+
+"STEP addition
+DATA(it10) = VALUE itab_type( FOR wa IN itab STEP -1 ( col1 = wa-col1 && 'u'
+ col2 = 7
+ col3 = wa-col2 + 8 ) ).
+
+*COL1 COL2 COL3
+*cccu 7 11
+*bbu 7 10
+*au 7 9
+
+"USING KEY addition
+DATA(it11) = VALUE itab_type( FOR wa IN itab USING KEY primary_key ( col1 = wa-col1 && 't'
+ col2 = 9
+ col3 = wa-col2 + 10 ) ).
+*COL1 COL2 COL3
+*at 9 11
+*bbt 9 12
+*ccct 9 13
+
+"---------- Conditional iterations ----------
+
+"FOR ... WHILE ...
+DATA(it12) = VALUE itab_type( FOR x = 1 WHILE x < 4
+ ( col1 = x col2 = x + 1 col3 = x + 2 ) ).
+
+*COL1 COL2 COL3
+* 1 2 3
+* 2 3 4
+* 3 4 5
+
+"FOR ... UNTIL ...
+"The THEN addition is also possible for ... WHILE ...
+DATA(it13) = VALUE itab_type( FOR y = 31 THEN y - 10 UNTIL y < 10
+ ( col1 = y col2 = y + 1 col3 = y + 2 ) ).
+
+*COL1 COL2 COL3
+* 31 32 33
+* 21 22 23
+* 11 12 13
```
-⬆️ back to top
+### REDUCE
-## LET Expressions
+- The
+ [`REDUCE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_reduce.htm)
+ operator creates a result of a specified or derived type from one or
+ more [iteration expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry") with `FOR`.
+- As covered for `FOR`, conditional iterations (reducing sets of data objects to a single data object in custom iteration steps) and table iterations (evaluation of table lines, reducing the table content to summary value) are possible. For example, the numeric values of a table column are summed up. As a result, the total number is constructed.
+- Additions:
+ - Optional `LET` expressions (the following additions are mandatory)
+ - `INIT ...`: A temporary variable (or field symbol) to specify an initial value for the result variable. At least, one variable/field symbol must be specified. The first specified determines the result of the expression (any others that are additionally specified can be used after `NEXT`).
+ - `FOR ...`: Iteration expression as covered above.
+ - `NEXT ...`: Represents the assignment to the temporary variable after every iteration. Once the loop has finished, the target variable is assigned the resulting value.
-- [`LET`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaplet.htm)
- expressions allow you to declare local helper fields (variables or
- fields symbols) and assign values (the type is derived from the
- defined value) to be used in constructor expressions, for example,
- in iteration expressions using `FOR` or results specified in
- the conditional expressions of `COND` and `SWITCH`.
-- Note that the helper field is only valid in the context in which the
- `LET` expression is specified.
-Examples:
-``` abap
-"Creating a string table using a LET expression
+```abap
+"Data objects and types to work with in the examples
+TYPES: BEGIN OF s,
+ col1 TYPE c LENGTH 5,
+ col2 TYPE i,
+ col3 TYPE i,
+ END OF s.
+TYPES itab_type TYPE TABLE OF s WITH EMPTY KEY.
+DATA(itab) = VALUE itab_type( ( col1 = 'a' col2 = 1 col3 = 30 )
+ ( col1 = 'bb' col2 = 2 col3 = 10 )
+ ( col1 = 'ccc' col2 = 3 col3 = 20 ) ).
-DATA(str_tab) = VALUE string_table( LET it = `be` IN
- ( |To { it } is to do| )
- ( |To { it } or not to { it }| )
- ( |To do is to { it }| )
- ( |Do { it } do { it } do| ) ).
+"---------- Table iterations ----------
-"Conditional expressions
+"Calculating the sum of values in a table column
+"Result: 6
+DATA(sum_val) = REDUCE i( INIT len = 0
+ FOR IN itab
+ NEXT len = len + -col2 ).
-DATA(a) = COND #( LET b = c IN
- WHEN b > x THEN ...
- WHEN b < y THEN ...
- ...
- ELSE ... ).
+"Getting the longest string in a table column
+"Result: ccc
+DATA(long_str) = REDUCE s-col1( INIT str = VALUE #( )
+ FOR IN itab
+ NEXT str = COND #( WHEN strlen( -col1 ) > strlen( str )
+ THEN -col1
+ ELSE str ) ).
+
+"Getting the maximum value (other than using SORT)
+"Unlike above, a variable is used instead of a field symbol.
+"Result: 3
+DATA(max_val) = REDUCE i( INIT max = 0
+ FOR line IN itab
+ NEXT max = COND #( WHEN line-col2 > max
+ THEN line-col2
+ ELSE max ) ).
+
+"Creating a new internal table using REDUCE
+"In the example, the sum of two values is calculated.
+"A VALUE expression with the BASE addition is used to
+"add a line to a table (retaining the existing lines).
+DATA(itstr) = REDUCE string_table( INIT strtab = VALUE string_table( )
+ FOR wa IN itab
+ NEXT strtab = VALUE #( BASE strtab
+ ( |The sum of { wa-col2 } and { wa-col3 } is { wa-col2 + wa-col3 }.| ) ) ).
+
+*The sum of 1 and 30 is 31.
+*The sum of 2 and 10 is 12.
+*The sum of 3 and 20 is 23.
+
+"More additions are possible, such as specifying a WHERE condition (which
+"must be specified in parentheses). The following example creates a new
+"internal table based on a WHERE condition.
+TYPES: BEGIN OF s3,
+ num1 TYPE i,
+ num2 TYPE i,
+ sum TYPE i,
+ END OF s3.
+TYPES s3_tab_type TYPE TABLE OF s3 WITH EMPTY KEY.
+DATA(itred) = REDUCE s3_tab_type( INIT tab = VALUE s3_tab_type( )
+ FOR wa IN itab
+ WHERE ( col2 < 3 )
+ NEXT tab = VALUE #( BASE tab
+ ( num1 = wa-col2 num2 = wa-col3 sum = wa-col2 + wa-col3 ) ) ).
+
+*NUM1 NUM2 SUM
+*1 30 31
+*2 10 12
+
+"---------- Conditional iterations ----------
+
+"UNTIL addition
+"Iteratively calculating the sum from 1 to 10
+"Result: 55
+DATA(reduce_until) = REDUCE i( INIT sum = 0
+ FOR int = 1 UNTIL int > 10
+ NEXT sum += int ).
+
+"WHILE addition
+"The example corresponds to the previous one.
+DATA(reduce_while) = REDUCE i( INIT sum = 0
+ FOR int = 1 WHILE int <= 10
+ NEXT sum += int ).
+
+"THEN addition
+"The following example constructs a text string. The THEN addition is used
+"to decrement the iteration variable. Additionally, a LET expression is used
+"to specify a helper variable.
+"Result: Counting downwards starting with 10: 10 9 8 7 6 5 4 3 2 1
+DATA(count) = REDUCE string( LET start = 10 IN
+ INIT text = |Counting downwards starting with { start }:|
+ FOR n = start THEN n - 1 WHILE n > 0
+ NEXT text &&= | { n }| ).
+
+"Example similar to the previous one. Using UNTIL, a text string is enlarged until
+"it has reached a specific size.
+"Result: ab abap abapap abapapap abapapapap abapapapapap abapapapapapap
+DATA(abap_str) = REDUCE string( INIT text = ``
+ FOR t = `ab` THEN t && `ap` UNTIL strlen( t ) > 15
+ NEXT text &&= |{ t } | ).
+
+"---------- Excursion: Grouping lines in internal tables with VALUE/REDUCE ----------
+
+"The following examples show equivalents of LOOP AT GROUP ... GROUP BY ... statements.
+"Find more information and examples about grouping in the ABAP Keyword Documentation.
+
+"Internal table to work with in the examples
+DATA(itab4grp) = VALUE itab_type( ( col1 = 'a' col2 = 1 col3 = 2 )
+ ( col1 = 'a' col2 = 3 col3 = 4 )
+ ( col1 = 'a' col2 = 5 col3 = 6 )
+ ( col1 = 'b' col2 = 7 col3 = 8 )
+ ( col1 = 'b' col2 = 9 col3 = 10 )
+ ( col1 = 'c' col2 = 11 col3 = 12 ) ).
+
+
+"Constucting a result using VALUE
+"The following example returns the values of identified groups in an internal table
+"Table lines are evaluated by grouping all lines that meet the condition
+"specified in GROUP BY (group key binding). The group key is stored in the variable
+"after FOR GROUPS (gr). The constructed result just consists of the group keys in
+"the example. The content of the members is not relevant.
+DATA(it_val_1) = VALUE string_table( FOR GROUPS gr OF wa IN itab4grp
+ GROUP BY wa-col1 ASCENDING
+ WITHOUT MEMBERS
+ ( |{ gr }| ) ).
+
+*a
+*b
+*c
+
+"As above, the following example returns the values of identified groups in an internal table.
+"Additionally, a LET expression (that itself contains an iteration expression) is specified
+"to collect column values by group in an internal table. The lines of this (string) table
+"are concatenated and inserted in the target table.
+DATA(it_val_2) = VALUE string_table(
+ FOR GROUPS grp OF wa IN itab4grp
+ GROUP BY wa-col1 ASCENDING
+ LET members = VALUE string_table(
+ FOR grpd IN GROUP grp ( |{ grpd-col2 }, { grpd-col3 }| ) ) IN
+ ( |{ grp }: { concat_lines_of( table = members sep = ` / ` ) }| ) ).
+
+*a: 1, 2 / 3, 4 / 5, 6
+*b: 7, 8 / 9, 10
+*c: 11, 12
+
+"Constucting a result using REDUCE
+"The example is similar to the previous one by filling a string table.
+"The example uses a group key expression specified after GROUP BY.
+"In the group key expression, additional components of a structured
+"group key are specified which return specific information (group size,
+"group index).
+DATA(it_reduced) = REDUCE string_table(
+ INIT li = VALUE string_table( )
+ FOR GROUPS group OF grt IN itab4grp
+ GROUP BY ( grpkey = grt-col1
+ size = GROUP SIZE
+ index = GROUP INDEX ) ASCENDING
+ LET mem = VALUE string_table(
+ FOR grpr IN GROUP group ( |{ grpr-col2 }, { grpr-col3 }| ) ) IN
+ NEXT li = VALUE string_table( BASE li ( |Group key: "{ group-grpkey }" \| | &&
+ |group size: { group-size } \| | &&
+ |group index: { group-index } \| members: | &&
+ |{ concat_lines_of( table = mem sep = ` / ` ) }| ) ) ).
+
+*Group key: "a" | group size: 3 | group index: 1 | members: 1, 2 / 3, 4 / 5, 6
+*Group key: "b" | group size: 2 | group index: 2 | members: 7, 8 / 9, 10
+*Group key: "c" | group size: 1 | group index: 3 | members: 11, 12
```
⬆️ back to top