Skip to Content
4

ABAP: Unexpected behaviour of reduce expression

Nov 24, 2017 at 11:09 AM

185

avatar image

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.

10 |10000 characters needed characters left characters exceeded
* Please Login or Register to Answer, Follow or Comment.

3 Answers

Best Answer
Glen Simpson Nov 24, 2017 at 01:42 PM
5

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

Show 2 Share
10 |10000 characters needed characters left characters exceeded

Yes, that would be a reasonable explanation. But it came a bit as a surprise to me. Therefore I hoped to find something about in the documentation. But hadn't any luck yet.

0

Glen's answer is correct

2
Christian Guenter Nov 24, 2017 at 02:59 PM
3
Show 1 Share
10 |10000 characters needed characters left characters exceeded

Yep, that's it.

And we have the BASE or LET addition, to circumvent that.

There are examples in the documentation too.

https://help.sap.com/http.svc/rc/abapdocu_752_index_htm/7.52/en-US/index.htm?file=abenvalue_constructor_params_struc.htm

2
Christian Guenter Nov 27, 2017 at 07:29 AM
0

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
Share
10 |10000 characters needed characters left characters exceeded