Skip to Content

ABAP: Unexpected behaviour of reduce expression

Today I stumbled across an unexpected behaviour in a reduce table expression and couldn't find any hint in the documentation.

Consider these two reduce operations.

    TYPES: BEGIN OF ty_output,
             head     TYPE string,
             position TYPE string,
           END OF ty_output.


    SELECT FROM t100
           FIELDS *
           WHERE sprsl = @sy-langu
           ORDER BY PRIMARY KEY
           INTO TABLE @DATA(t100_tab)
           UP TO 10 ROWS.


    DATA(output) = REDUCE ty_output( INIT result = VALUE ty_output( )
                                     FOR GROUPS group OF ls_t100 IN t100_tab
                                     INDEX INTO index
                                     GROUP BY ( arbgb = ls_t100-arbgb
                                                msgnr = ls_t100-msgnr )
                                     FOR <ls_t100> IN GROUP group
                                     NEXT result = VALUE #( position = result-position && |\n{ <ls_t100>-text }| ) ). " <=== difference here


    DATA(output2) = REDUCE ty_output( INIT result = VALUE ty_output( )
                                      FOR GROUPS group OF ls_t100 IN t100_tab
                                      INDEX INTO index
                                      GROUP BY ( arbgb = ls_t100-arbgb
                                                 msgnr = ls_t100-msgnr )
                                      FOR <ls_t100> IN GROUP group
                                      NEXT result-position = result-position && |\n{ <ls_t100>-text }| ). " <=== difference here


    " fails:
*    ASSERT output = output2.

    cl_demo_output=>write( output-position ).
    cl_demo_output=>write( output2-position ).
    cl_demo_output=>display( ).

I expected that both return the same value. They don't.

Can anybody explain that? Is that documented somewhere?

Maybe Horst Keller is around ;-)

Thanks.

Christian

P.s. You can also find the code in this abapGit repo.

Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

3 Answers

  • Best Answer
    Nov 24, 2017 at 01:42 PM

    Hi Christian

    This is just a semi-educated guess but I think that OUTPUT only gets the last message in the internal table due to the VALUE #( ) operator in the last line of the first REDUCE statement.

    NEXT result = VALUE #( position = result-position && |\n{ <ls_t100>-text }| ) )

    My understanding of the VALUE operator is that it initialises the left hand side (in your case, the RESULT structure) *before* it constructs the right hand side. So RESULT-POSITION is always empty when it concatenates the next message.

    The second REDUCE doesn not use the VALUE operator and so doesn't clear the RESULT structure in each iteration... resulting in a longer string.

    Of course, I could be wrong. :-)

    Regards
    Glen

    Add comment
    10|10000 characters needed characters exceeded

  • Nov 24, 2017 at 02:59 PM
    Add comment
    10|10000 characters needed characters exceeded

  • Nov 27, 2017 at 07:29 AM

    Thanks to Glens and Horsts answers I was able to solve my issue with the base addition of the value constructor expression. I updated the repo if anybody is interested.

        DATA(output) = REDUCE ty_output( INIT result = VALUE ty_output( )
                                         FOR GROUPS group OF ls_t100 IN t100_tab
                                         INDEX INTO index
                                         GROUP BY ( arbgb = ls_t100-arbgb
                                                    msgnr = ls_t100-msgnr )
                                         FOR <ls_t100> IN GROUP group
                                         NEXT result = VALUE #( BASE result
                                                                position = result-position && |\n{ <ls_t100>-text }| ) ). " <=== solution with base
    *                                     NEXT result = VALUE #( position = result-position && |\n{ <ls_t100>-text }| ) ). " <=== difference here
    Add comment
    10|10000 characters needed characters exceeded