In order to check whether all entries of an internal table lt_itab
meet a condition COND, I would like to use REDUCE statement. The loop of course needs to terminate once a line violating COND occurs. The second code block further down seems to work but appears to me like a slight abuse of the iteration index. Are you aware of a better/more transparent solution within the REDUCE syntax? Is it possible to work with a structure (integer, boolean) for the iteration variable? The INDEX INTO
option seems not to work with REDUCE. Compatibility to kernel-release 753 (or lower) would be nice.
Here is my Minimal Reproducible Example (MRE) which passes syntax check only if lvr_flag_allowed = abap_false OR
is commented out (viz -> "lvr_flag_allowed = abap_false OR
):
DATA: lt_itab TYPE TABLE OF i,
rv_flag_allowed TYPE boole_d.
lt_itab = VALUE #( ( 2 ) ( 1 ) ( -1 ) ( 5 ) ).
IF lt_itab IS NOT INITIAL.
rv_flag_allowed = REDUCE #( INIT lvr_flag_allowed = abap_true
FOR lvf_idx = 1 UNTIL lvr_flag_allowed = abap_false OR
lvf_idx > lines( lt_itab )
NEXT lvr_flag_allowed = xsdbool( lt_itab[ lvf_idx ] < 0 ) ).
ENDIF.
RETURN.
Currently it gives this syntax check message (its ID is MESSAGEG[M
):
The variable "LVR_FLAG_ALLOWED" cannot be used here.
Do you know the technical reason why this does not work? The SAP documentation on REDUCE - Reduction Operator only states
Usually the expression expr (after THEN) and the termination condition log_exp (after UNTIL or WHILE) depend on the iteration variable var.
Hence a workaround MRE came to my mind while writing this down:
DATA: lt_itab TYPE TABLE OF i,
* rv_flag_allowed TYPE boole_d,
rv_last_index TYPE i.
lt_itab = VALUE #( ( 2 ) ( 1 ) ( -22 ) ( 5 ) ( 7 ) ( 4 ) ).
IF lt_itab IS NOT INITIAL.
rv_last_index = REDUCE #( INIT lvr_last_index = 0
FOR lvf_idx = 1 THEN COND #( WHEN lt_itab[ lvf_idx ] < 0
THEN 0
ELSE lvf_idx + 1 )
UNTIL lvf_idx = 0 OR
lvf_idx > lines( lt_itab )
NEXT lvr_last_index = lvr_last_index + 1 ).
ENDIF.
RETURN.
It makes "double" use of the iteration index and returns rv_last_index = 3
. I'm returning an integer now rather than a boolean in order to check the correct abort result. Does this seem correct to you?
Many thanks in advance for your feedback and improvement suggestions (beyond the classical while/until loops ;-)) !