loopsfor-loopabapinternal-tables

Using REF within a FOR expression - unexpected behaviour


I have some example code below:

DATA(t_strings) = VALUE char10_t( ( 'S1' ) ( 'S2' ) ( 'S3' ) ).

TYPES : BEGIN OF gty_ref,
         string_ref TYPE REF TO data,
       END OF gty_ref,

       gty_t_ref TYPE STANDARD TABLE OF gty_ref.

DATA : t_string_ref1 TYPE gty_t_ref,
       t_string_ref2 TYPE gty_t_ref.

t_string_ref1 = VALUE #( FOR entry IN t_strings ( string_ref = REF #( entry ) ) ).

LOOP AT t_strings ASSIGNING FIELD-SYMBOL(<entry>).
  t_string_ref2 = VALUE #( BASE t_string_ref2 ( string_ref = REF #( <entry> ) ) ).
ENDLOOP.

I thought that using FOR or using a loop would provide the same result. But this is what happens:

enter image description here

Can someone explain why T_STRING_REF1 only contains references to S3 as opposed to S1, S2 and S3 as I expected?


Solution

  • entry in your example is a full-fledged variable. It's not scoped to the FOR-expression. You can still access it afterwards with whatever value it had after the expression.

    That means what happens in each loop of your FOR expression is:

    1. The value of the current line of t_string is copied into entry
    2. A new structure is initialized, where string_ref points to entry, not to the line of the table where it got its value from
    3. That structure is put into the resulting table t_string_ref1

    So the result is a table of references which all point to the entry variable with whatever value it has at the moment, not into the t_string table.

    OK, so how to we solve this problem?

    The actual crux here is that a FOR variable IN table expression behaves like LOOP AT table INTO variable. It creates a copy of each line. What you actually need here is to use the equivalent of a LOOP AT table ASSIGNING <field_symbol>. Fortunately, FOR can do that by simply declaring the line-variable in < and >.

    t_string_ref1 = VALUE #( FOR <entry> IN t_strings ( string_ref = REF #( <entry> ) ) ).
    

    Now <entry> is no longer a variable but a field-symbol. You can't reference a field symbol. So REF #( <entry> ) gets you a reference to the table line the field-symbol is currently assigned to.