Skip to Content
Technical Articles
Author's profile photo Stoyko Stoev

Declaring variables in a loop in ABAP: remember that ABAP is not block-scoped!

A few weeks back, I was debugging a seemingly very weird error. Without getting into too much details, what turned out to be the cause for my issue is that I had a variable declared in a loop. Then, in an if block, the variable was assigned some value (given that the if condition evaluated to true, obviously). Later in the loop, some operations were performed using this variable. And this is what turned out to be the problem.

I found out that the value from the previous loop is retained when the if block is not entered in. When I did think about it, it wasn’t so weird anymore. In ABAP, variable declarations are method-scoped, not block-scoped (as in, for example, Java). This means that the following code does not work in Java (we get an error: cannot find symbol a):

public class MyDemoClass {
     public static void main(String []args){
        if (false) {
            int a = 5;
        }
        a = 7;
        System.out.println(a);
     }
}

But the same logic is completely valid in ABAP (although a bad practice):

class zcl_my_demo_class definition public final create public.
  public section.
    interfaces:
      if_oo_adt_classrun.
endclass.


class zcl_my_demo_class implementation.
  method if_oo_adt_classrun~main.
    if abap_true = abap_false.
      data(a) = 5.
    endif.
    a = 7.
    out->write( a ).
  endmethod.
endclass.

Therefore, because of this, if we initialize variables in a loop, they are only given an initial value the first time, and every next iteration, the value from the previous iteration is kept. Again, when you do think about it, this is not strange, but, in general, information on the internet about ABAP is unfortunately not plentiful. So, I figured this may save some frustration for a developer somewhere in the future, if they land here after a Google search 😊 (and, on the overall, making information about ABAP more accessible, and thus helping to develop its ecosystem is something I am trying to do!).

So, based on the above, the following logic:

class zcl_my_demo_class definition public final create public.
  public section.
    interfaces:
      if_oo_adt_classrun.
endclass.


class zcl_my_demo_class implementation.
  method if_oo_adt_classrun~main.
    data(i) = 0.
    while i <> 3.
      data my_var type i.

      if i = 1.
        my_var = 7.
      endif.

      if my_var is initial.
        out->write( |we have an initial variable!| ).
      else.
        out->write( |we have { my_var } as value for the variable!| ).
      endif.

      i = i + 1.
    endwhile.
  endmethod.
endclass.

Will lead to the following output:

We have an initial variable!
We have 7 as value for the variable!
We have 7 as value for the variable!

I.e., in the first iteration (i = 0), we create the new variable my_var. It is currently initial. Nothing is assigned to it even after the if block, because as mentioned at this point i is 0. In the second iteration (i = 1), the variable my_var is already there, but it is still initial, because nothing was assigned to it during the last iteration. However, this time, we do enter the if block, and assign 7 to my_var. In the third and last iteration (i = 2), the variable my_var is already there, and it has already been assigned a value in the last iteration, so currently my_var is 7, even though the if block is not executed.

If you would like to get around this, one suggestion from my side is to do the following:

data(my_var) = value i(  ).

As opposed to:

data my_var type i.

This retains the benefit of not having to assign a literal of the initial value (i.e. 0 in this case) and, what is different, is that now, the initial value is re-assigned every loop. Now, we have the following output:

We have an initial variable!
We have 7 as value for the variable!
We have an initial variable!

To conclude, and to also repeat, this may seem obvious for most ABAP developers when being seen like this, but it can be the source of seemingly weird issues, especially in an old code, written before inline declarations were a thing in ABAP. So hopefully, this saves a bit of time in the future for at least some developers… and also spreads some ABAP knowledge to non-ABAP developers in the process 😊

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jacques Nomssi Nzali
      Jacques Nomssi Nzali

      Also check:

      https://github.com/SAP/styleguides/blob/master/clean-abap/CleanABAP.md#dont-declare-inline-in-optional-branches

       

      Author's profile photo Stoyko Stoev
      Stoyko Stoev
      Blog Post Author

      Hey, Jacques,

      Thanks for linking that!

      Indeed, I fully agree that declarations in an if block are a bad practice. They are still technically valid ABAP though, so it is important to know this when debugging other people's code.

      Best,

      Stoyko

      Author's profile photo Suhas Saha
      Suhas Saha

      I am assuming you are using ADT (aka ABAP in Eclipse) as the IDE. If yes, then just use the quick-fix (Ctrl+1) to define the variable MY_VAR 😉

      Saves the typing time and declares the variable at the top as it should be.

      Author's profile photo Stoyko Stoev
      Stoyko Stoev
      Blog Post Author

      Hey Suhas,

      very neat trick, I was not actually aware of it!

      It does also deal away with the problem in the sense that once the variable is declared outside of the loop, it will be immediately clear that it will retain its value from the previous iteration.

      Perhaps I could have made it more clear in the post that I was speaking of the use-case where the variable is used only inside the loop, so it makes sense to declare it there. BUT, this can lead to the confusion I mentioned (at least it temporary did for me - may be it won't for more clever developers 😉) where you'd expect the variable to be re-initialized in every iteration. Hence, for this specific use case, my proposed solution with:

      data(my_var) = value i(  ).

      Which does indeed re-initializes on every iteration, to achieve this behavior:

      We have an initial variable!
      We have 7 as value for the variable!
      We have an initial variable!

      If, however, the desired behavior is this:

      We have an initial variable!
      We have 7 as value for the variable!
      We have 7 as value for the variable!

      What you are proposing is obviously by far the best solution (declare outside of the loop).

      And one more thanks for showing the trick!

      Best,

      Stoyko