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 ;-)) !
 
     
    