Skip to Content

With Release 7.40 constructor expressions NEW, VALUE and CORRESPONDING were introduced, that allow you to construct complex data objects in operand positions. Some of you might have noticed, that something was missing there.

Look at the following examples:

DATA:
  BEGIN OF struct1,
    col1 TYPE i VALUE 11,
    col2 TYPE i VALUE 12,
  END OF struct1.

DATA:
  BEGIN OF struct2,
    col2 TYPE i VALUE 22,
    col3 TYPE i VALUE 23,
  END OF struct2.

struct2 = CORRESPONDING #( struct1 ).

This is not the same as

MOVE-CORRESPONDING struct2 TO struct1.

Since the RHS does not know anything of the LHS, component col3 of struct2 does not keep its former value but is initialized.

Same for:

DATA itab TYPE TABLE OF i.

itab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).

itab = VALUE #( ( 4 ) ( 5 ) ( 6 ) ).

This is not the same as

APPEND 1 TO itab.

APPEND 2 TO itab.

APPEND 3 TO itab.

APPEND 4 TO itab.

APPEND 5 TO itab.

APPEND 6 TO itab.

Again, the RHS does not know the LHS and the result of the second assignment is three lines containing 4, 5, 6.

Of course, it is a common use case to add new values to existing values. Therefore, with Release 740, SP08 there is a new addition BASE for constructor expressions NEW, VALUE and CORRESPONDING that allows you to give the expressions a start value.  Very often, this means to make the LHS known to a RHS. For the examples shown above, this simply will look as follows:

struct2 = CORRESPONDING #( BASE ( struct2 ) struct1 ).

The result of the expression is initialized with struct2 and then the evaluation takes place. Now it works like MOVE-CORRESPONDING, col3 of struct2 keeps its former value.

And

itab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).

itab = VALUE #( BASE itab ( 4 ) ( 5 ) ( 6 ) ).

The result of the second expression is initialized with itab and then the other lines are added. After the second assignment, itab contains 1, 2, 3, 4, 5, 6.

You can als construct structures using BASE:

struct2 = VALUE #( BASE struct1  col3 = 33 ).

First, all components are taken over from struct1, then the columns specified are overwritten.

Of course, the usage of BASE is not restricted to constructor expressions in RHS-positions.

meth( VALUE #( BASE … ( … ) ).

Didn’t you miss that?

And one mor goody for constructing internal tables:

… VALUE #( … ( LINES OF itab ) … ) …

To be freely combined with other line specifications and – of course – BASE.

To report this post you need to login first.

32 Comments

You must be Logged on to comment or reply to a post.

  1. Shai Sinai

    Quite impressive.

    However, I’m little worried about the readability of such monstrous statements.

    VALUE # ( … ( LINES OF ( VALUE ( FOR … ) )) ( CORRESPONDING # ( … ) ) … ), for example.

    (0) 
      1. Uwe Fetzer

        Hello Horst,

        you can still sleep without nightmares? 😈

        With the 2048 code I’m getting a syntax-error (I’m on NW 7.40 SP8). Is the sample already for an higher SP?

        abap.PNG

        (0) 
        1. Horst Keller Post author

          ‘xactly, I added the as_checkbox parameter with SP09. Same for an add_line-method (fortunately, I marked the class for internal use only …)

          Since the SP08 documentation was finished with SP09, it mentions in some few parts examples that are not yet available in SP08. In the above case, you can simply leave the parameter away and have to enter an X then.

          (0) 
  2. Uwe Fetzer

    Two questions:

    1.) Is there a difference between

    t2 = VALUE #( ( LINES OF t1 ) ( 4 ) ).

    and

    t2 = VALUE #( BASE t1 ( 4 ) ).

    T1 and T2 are both STANDARD TABLE OF i.

    2.) Is there a reason why we have BASE with and without brackets ?

    BASE ( struct2 )

    BASE itab


    (0) 
    1. Horst Keller Post author

      1.) Functionally it is the same, but using BASE should perform a little bit better.

      Translated to statements.

      t2 = VALUE #( ( LINES OF t1 ) ( 4 ) ).

      works as

      CLEAR t2.

      INSERT LINES OF t1 INTO TABLE t2.

      INSERT 4 INTO TABLE t2.

      while

      t2 = VALUE #( BASE t1 ( 4 ) ).

      works as

      CLEAR t2.

      t2 = t1.

      INSERT 4 INTO TABLE t2.

      2.) Yes. The parser needs a little help to recognize the tokens here. For the same reason you have to put brackets around the WHERE condition behind FOR in table iterations

      (0) 
      1. Amol Samte

        Hi Horst,

        Horst Keller wrote:

        1.) Functionally it is the same, but using BASE should perform a little bit better.

        Translated to statements.

        t2 = VALUE #( ( LINES OF t1 ) ( 4 ) ).

        works as

        CLEAR t2.

        INSERT LINES OF t1 INTO TABLE t2.

        INSERT 4 INTO TABLE t2.

        while

        t2 = VALUE #( BASE t1 ( 4 ) ).

        works as

        CLEAR t2.

        t2 = t1.

        INSERT 4 INTO TABLE t2.

        Where can we find the documentation how it works for all new stuff in 7.4 😐

        Regards,

        Amol

        (0) 
      2. Niall Brennan

        I wanted to use this kind of approach to append new lines to an already existing table whilst obviously retaining the existing entries – are there any options apart from doing the append first and using the field symbol (or copying the entries to another temporary internal and using that).

        This is what I wanted to achieve

        t1 = VALUE #( ( LINES OF t1 ) ( 4 ) ).

        This is h

        Append initial line to t1 assigning field-symbol(<fs>).

        <fs> = VALUE #(  4 ).

        (0) 
        1. Horst Keller Post author

          to append new lines to an already existing table whilst obviously retaining the existing entries


          But isn’t that solved with the BASE addition described above?


          t1 = VALUE #( BASE t1 ( 4 ) ).


          Or how should I understand your question?

          (0) 
  3. Robin Vleeschhouwer

    Hi Horst,

    Thanks for this informative blog and all the others blogs you wrote. You really rock!

    We can make the corresponding statement even more complete with an addition EXCLUDING.

    For example if you want to copy everything except the key.

    Example implementation:

    ls_mara2 = CORRESPONDING #( BASE ( ls_mara2 ) ls_mara EXCLUDING ( matnr ) ).

    Addition options:

    EXCLUDING ( field_names )

    EXCLUDING itab_field_names

    Best regards,

    Robin Vleeschhouwer

    (0) 
    1. Horst Keller Post author

      Hi Robin,

      The addition is there and it is called EXCEPT.

      I didn’t mention it above, since I only wanted to introduce the BASE addition, that is new with SP08, while EXECPT is available since SP05.

      Kind regards

      Horst

      PS: It’s not me, who rocks, but my colleagues who are implementing all this stuff 😉

      (0) 
      1. Oliver Jaegle

        Dear Horst (and rocking colleagues),

        please, please, please don’t add more funky features to the corresponding-stuff. I’ve been trying for years now to convince me fellows that explicitly moving named includes is the preferred style. The more convenient corresponding gets, the harder it’s for me to argue – and move-corresponding can cause really nasty effects.

        How about introducing an explicit mapping artifact (similar to the simple transformations, but more convenient to use 😉 )?

        Cheers,

        Oliver

        (0) 
        1. Horst Keller Post author

          How about introducing an explicit mapping artifact (similar to the simple transformations, but more convenient to use)

          Well, ‘xactly this we have in the 8.0 code line used SAP internally only – AMS (ABAP Mapping Script). Structures are regarded as trees and and AMS provides transformations between these trees. An AMS is passed as a string to a factory method of an AMS class and the resulting object can transform structures and internal tables. Quiet sophisticated stuff. I’ve even written an AMS studio for testing purposes.

          A simple AMS looks as follows:

          in(s)
          out(r)
          {
            $r.B1 := $s,
            $r.B2 :=  $s.A2,
            $r.B3 := C`x`
          }

          More sophisticated scripts contain conditions and loops and such.

          But, alas, AMS didn’t make its way to the 7.40 code line.

          move-corresponding can cause really nasty effects

          The majority of ABAP programmers simply love it and that’s why the efforts were put in the CORRESPONDING operator and not into AMS. At least, we have a mapping addition to the operator now.

          please don’t add more funky features to the corresponding-stuff

          Too late, in the next release you’ll see CL_ABAP_CORREPONDING that allows you to define a dynamic mapping between structure components. But as for all the CORRESPONDING stuff, components that are not listed in the mapping rule are  mapped by name …

          If you don’t want to map by name (well thats what CORRESPONDING literally stands for), you can use the VALUE operator (with table comprehensions) where you define the full mapping by your self.

          Cheers!

          Horst

          (0) 
          1. Peter Inotai

            I’m big fan of MOVE-CORRESPONDING, especially when it comes to the situation in Add-On development. It’s enough to use the same name in the customer include as the target fieldname in the customer projects and it works fine also with customer fields without any additional code.

            AMS and CL_ABAP_CORREPONDING sound interesting. It seems ABAP 8.0 is full of cool features 🙂 . I hope they will be downported soon.

            Cheers,

            Peter

            (0) 
  4. Nishant Bansal

    After watching all the new coding pattern in SAP, I would like to tell one thing. Only God help us to understand all the new concept…. 😉 😕 😐

    The ABAP will become ABAVA….. 😛 😛

    (0) 

Leave a Reply