Skip to Content
Author's profile photo Horst Keller

ABAP News for Release 7.40 – Inline Declarations

Inline declarations are a new way of declaring variables and field symbols at operand positions.

Data Declarations

In ABAP you have many operand positions, where the value of the operand is changed by the statement. The most typical of these “write positions” is the left hand side lhs of an assignment.

lhs = rhs.

But of course there are more. The data objects you can use at these write positions are either writable formal parameters of the procedure you are working in or variables declared with DATA in front of the statement.

In many cases the variables filled by a statement are helper variables that you only need close to the statement. For each of  these helper variables you had to write a data declaration with the DATA statement and of course it was your task to give the variable an adequate type.

Well, the operand type of most write positions is statically fixed and well known to the compiler. And this is why ABAP can offer inline data declarations with Release 7.40. The ingredients are so called declaration positions (write positions with fully known operand type)  and the new declaration operator DATA(…).

Let’s look at some examples.

Declaration of a lhs-variable for a simple assignment

Before 7.40

DATA text TYPE string.
text = `…`.

With 7.40

DATA(text) = `…`.

Declaration of table work areas

Before 7.40

DATA wa like LINE OF itab.
LOOP AT itab INTO wa.  
  ...
ENDLOOP.

With 7.40

LOOP AT itab INTO DATA(wa).  
  ...
ENDLOOP
.

Declaration of a helper variable

Before 7.40

DATA cnt TYPE i.
FIND … IN … MATCH COUNT cnt.

With 7.40

FIND … IN … MATCH COUNT DATA(cnt).

Declaration of a result

Before 7.40

DATA xml TYPE xstring.
CALL TRANSFORMATION … RESULT XML xml.

With 7.40

CALL TRANSFORMATION … RESULT XML DATA(xml).

Declaration of actual parameters

Before 7.40

DATA a1 TYPE …

DATA a2 TYPE …

oref->meth( IMPORTING p1 = a1

            IMPORTING p2 = a2

            … )

With 7.40

oref->meth( IMPORTING p1 = DATA(a1)

            IMPORTING p2 = DATA(a2)

            … ).

Declaration of reference variables for factory methods

Before 7.40

DATA ixml           TYPE REF TO if_ixml.
DATA stream_factory TYPE REF TO if_ixml_stream_factory.
DATA document       TYPE REF TO if_ixml_document.

ixml           = cl_ixml=>create( ).
stream_factory = ixml->create_stream_factory( ).
document       = ixml->create_document( ).

With 7.40

DATA(ixml)           = cl_ixml=>create( ).
DATA(stream_factory) = ixml->create_stream_factory( ).
DATA(document)       = ixml->create_document( ).

This example is my favorite. When working with class libraries as the iXML-Library you don’t have to care about the data type of the reference variables too much any more. You simply create them inline and use them. As you will see in the 7.40 version of the ABAP Example Library, this feature has facilitated my writings of example programs considerably.

 

Field Symbols

For field symbols there is the new declaration operator FIELD-SYMBOL(…) that you can use at exactly three declaration positions.

ASSIGN … TO FIELD-SYMBOL(<fs>).

LOOP AT itab ASSIGNING FIELD-SYMBOL(<line>).

ENDLOOP.

READ TABLE itab ASSIGNING FIELD-SYMBOL(<line>) …

I guess it is clear to you what happens here.

Outlook

In my upcoming blogs I will make use of inline declarations when introducing other new features. Be prepared for code like this:

TYPES t_itab TYPE TABLE OF i WITH EMPTY KEY.

DATA(itab) = VALUE t_itab( ( 1 ) ( 2 ) ( 3 ) ).

Yes, this is ABAP 7.40 …

Assigned tags

      147 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      Great news, Horst! Looking forward to 7.40 being shipped.

      What I find even more annoying in present-day ABAP than the necessity of type declarations for lvalues, is the necessity of declaring auxiliary variables and to move data to them only for being able to pass these data to a method (or function module).

      One example: Suppose I have a field in a STRING variable iv_name. Just because some other developer didn't use the general type 'CSEQUENCE'  for his API import parameter, I have to add a data declaration for it and to move the STRING content to it before calling his API:

      data: lv_bname type BNAME.

      lv_bname = iv_name.  " (... supposing iv_name is a STRING field )

      lo_api->method( exporting iv_bname = lv_bname ). " Doesn't accept the iv_name, bc. it's a STRING.

      Will there be a simplification for this kind of call too?

      Actually, the local variable lv_bname is needed only for the call. The compiler knows itself what type is expected (at least for non-generic types, for which we have this kind of problem). So the compiler could generate a data object on the fly and perform an implicit MOVE. Syntax could be

      lo_api->method( exporting iv_bname ?= iv_name ).

      or

      lo_api->method( exporting iv_bname = (?) iv_name ),

      (since for a one-parameter or preferred-parameter method the formal parameter name may not be specified, the simplified syntax would then be possible:

      lo_api->method( (?) iv_name )

      or even implicit (no special annotation at all - but this variant would bring the backward compatibility issue):

      lo_api->method( exporting iv_bname = iv_name ).

      to indicate that a move should be performed to an ad-hoc data object of the appropriate data type.

      Regards,

      Rüdiger

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Will there be a simplification for this kind of call too?

      Yes.

      lo_api->method( exporting iv_bname = CONV #( lv_bname ) ).

      CONV is one of the new constructor operators, that I will introduce in an upcoming blog.

      Best

      Horst

      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      Great! Looking forward to it (the blog and the new ABAP runtime)!  🙂

      Thx

      Rüdiger

      Author's profile photo Volodymyr Shcheglov
      Volodymyr Shcheglov

      Rüdiger Plantiko wrote:

                             

      Great news, Horst! Looking forward to 7.40 being shipped.

      ...<skipped>

      One example: Suppose I have a field in a STRING variable iv_name. Just because some other developer didn't use the general type 'CSEQUENCE'  for his API import parameter, I have to add a data declaration for it and to move the STRING content to it before calling his API:

      data: lv_bname type BNAME.

      lv_bname = iv_name.  " (... supposing iv_name is a STRING field )

      lo_api->method( exporting iv_bname = lv_bname ). " Doesn't accept the iv_name, bc. it's a STRING.

      Will there be a simplification for this kind of call too?

      ...<skipped>

      Regards,

      Rüdiger

                         

      This example is slightly irrelevant because you can use string templates. Since ABAP version 7.02 one is able to write the code such as:

      data: lv_str type string value 'initial'.

      lo_api->method( iv_bname = |{ lv_str }| ).

      This is applicable only to methods. Unfortunately, you can't do the same for function or procedures calls.

      By the way, question to Horst: why isn't that feature implemented for older constructions such as CALL FUNCTION or PERFORM, or macro calls? Was it too difficult, or it was just assumed there was no demand for such things?

      As for Rüdiger's example, the real problem is with other convertible types, say, P or N. For example, we have a method's parameter is defined as IV_PAR(8) TYPE P DECIMALS 4, and an actual parameter, as LV_VAL(6) TYPE P DECIMALS 2. It's obvious that this variable can be easily converted to the formal parameter's type but right now you will get a syntax error trying to call this method as:

      LO_OBJ->METHOD( IV_PAR = LV_VAL ).

      So,

      CONV #( lv_bname ) would be handy.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      lo_api->method( iv_bname = |{ lv_str }| ).

      works, yes, but more "by chance" (string expression is handled like a string literal here).

      Better to use the new CONV operator that wors explicitly and for any type.

      why isn't that feature implemented for older constructions such as CALL FUNCTION

      http://help.sap.com/abapdocu_740/en/abennews-740-operand_positions.htm

      But PERFORM is too outdated to be supported with the nice things ...

      Author's profile photo Custodio de Oliveira
      Custodio de Oliveira

      Hi Horst,

      In your very first example you have:

      Before 7.40

      DATA text TYPE string.
      text = `...`.

      With 7.40

      DATA(text) = `...`.

      But currently we can have in one line already:

      DATA text TYPE string VALUE '...'.

      Still a nice improvement.

      Cheers,

      Custodio

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Hi Custodio,

      so let me rewrite my first example:

      data(var) = rhs.

      Where rhs is

      • any data object
      • a functional method call
      • a call of a built-in function
      • an arithmetic expression
      • a string expression
      • a bit expression
      • a constuctor expression
      • a table expression

      Now it's your turn again 😉

      Author's profile photo Custodio de Oliveira
      Custodio de Oliveira

      Can't stop loving ABAP 7.40!

      Author's profile photo Volodymyr Shcheglov
      Volodymyr Shcheglov

      Horst Keller wrote:

                             

      Hi Custodio,

      so let me rewrite my first example:

      data(var) = rhs.

      Where rhs is

      • any data object
      • a functional method call
      • a call of a built-in function
      • an arithmetic expression
      • a string expression
      • a bit expression
      • a constuctor expression
      • a table expression

      Now it's your turn again 😉

                         

      Dear Horst, will there be an ability to make a call like this:

      CALL FUNCTION 'MY_FUNC'

        EXPORTING

          IV_PAR = lo_object->method( )

      ? This is really a demanding feature. Otherwise we need to declare a variable just to store a returning parameter and then pass it to a function call. Moreover, this feature is fully supported in method calls.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author
      Author's profile photo SHEKHAR SAHA
      SHEKHAR SAHA

      Hi Horst,

      Does the LHS variable is always converted to Cstring type?..

      as the RHS variable I am having is of type c(10), so while converting, the type mismatch is occuring.

       

      Eg below:

      im_opp_id type C(10).


      SPAN {
      font-family: "Courier New";
      font-size: 10pt;
      color: #000000;
      background: #FFFFFF;
      }
      .L0S52 {
      color: #0000FF;
      }
      .L0S55 {
      color: #800080;
      }
      DATA(lv_opp_id) |{ im_opp_id ALPHA IN }|.

       

      Regards,

      Shekhar

      Author's profile photo Former Member
      Former Member

      Release 740 is perhaps the most revolutionary change i've seen in 7.5yrs as an ABAPer!

      I think the ABAP code will look more like Java in days to come. Any insider tip when will 740 be shipped to custom developers? 😏

      BR,

      Suhas

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      I think the ABAP code will look more like Java in days to come.

      Yep, and I'm sure not erverybody will like that. For me, the only spoiler is that you can mix very old and quaint stuff with very modern features inside one program unit now. You can create quite queer effects by this. I'm a great fan of a version flag for ABAP programs that would allow new stuff in new programs only, where obsolete stuff would be prohibited then. But alas, no majority for this.

      Any insider tip when will 740 be shipped to custom developers?

      Uh, oh, I'm not insider enough to answer such a question, better ask one of the PM guys blogging about 7.40 ...

      Best

      Horst

      Author's profile photo Brian O'Neill
      Brian O'Neill

      Horst Keller wrote:

                             

      I'm a great fan of a version flag for ABAP programs that would allow new stuff in new programs only, where obsolete stuff would be prohibited then. But alas, no majority for this.

                         

      Wow! That's too bad!

      I could see where the version flag could just be set lower for people that are still stuck in the past. The problem is that some people writing outdated code may not know that they are doing anything wrong or even obsolete.

      I think there is a hidden cost to not adopting modern ABAP that is not really promoted. There are good developers graduating right now who may have the potential to be great ABAP developers. You can do a lot without utilizing modern ABAP, but outdated techniques will not inspire a typical millennial developer.

      It's hard enough to find experienced ABAP developers as is. By not utilizing modern ABAP, it's going to be hard to inspire the next generation of ABAP developers.

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      If you setup your ATC (ABAP Test Cockpit) the right way, you can prevent depreciated ABAP code from beeing transported.

      (just one way to force your devs to use modern code)

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      Hi Suhas,

      the standalone AS ABAP 7.40 is already general available (and running on my server 🙂 ). See http://bgoerke.wordpress.com/2013/05/10/sap-netweaver-7-4-now-generally-available-ga/

      Author's profile photo Oliver Russinger
      Oliver Russinger

      Very cool innovations.

      specially

      lo_api->method( exporting iv_bname = CONV #( lv_bname ) ).

      would be something long awaited ;-).

      is there a complete reference in the snd anywhere as it will time time 'till we will geht 740 i guess.

      best regards oliver

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      is there a complete reference in the snd anywhere

      I'm planning to introduce all innovations step by step in blogs (always when I find some time to write one) and to produce one TOC in the end. Furthermore, I will try to get the offline version of the 7.40 keyword documentation into the sap help portal this year ...

      Author's profile photo Uwe Fetzer
      Uwe Fetzer
      Author's profile photo B. Meijs
      B. Meijs

      First the changes in WAS702, now this. Surely an improvement to the language. Can't wait to get my hands on a was740 server (and some customers to upgrade to a was740 based system)

      One question: Is there an backward compatibility check option available to check if my was702/703/740 abap code will run in older versions like was700?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Is there an backward compatibility check option available to check if my was702/703/740 abap code will run in older versions like was700

      Don't know of any but trying to compile the code in 7.00.

      Author's profile photo Nigel James
      Nigel James

      You raise a good point Ben Meijs . If I was a partner delivering custom code and I was targeting several systems, would I have to write to the LCD or could I do checking to see if my new code could run, in a similar way to javascript testing for browser features.

      Nigel

      Author's profile photo B. Meijs
      B. Meijs

      Horst Keller wrote:

                             

      Is there an backward compatibility check option available to check if my was702/703/740 abap code will run in older versions like was700

      Don't nkow of any but trying to compile the code in 7.00.

                         

      Well, actually we run the code inspector on older releases, because we also ran into problems with functions missing specific formal parameters.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Ohkay, so I say,

      Don't know of anything but trying to check the code in 7.00 ...

      Author's profile photo Paul Hardy
      Paul Hardy

      All jokes and songs aside, this is wonderful stuff. I only had access to a 7.02 system this time last year, and it will be five years at least before I can start programming in version 7.40, but already I can't wait....

      Going back to header lines, I reckon one of the reasons a lot of people kept using them, was because people includign me are lazy, and you had to explictly define a work area and it was far easier just to say LOOP AT ITAB. In 7.40 there is no excuse whatsoever you neatly solve the problem of not having two data objecst with the same name, coupled with not having to explicitly define the work area.

      Declaring the variables whilst receiving it is brilliant as well.

      Well done. As I said, I can't wait.

      Cue Ray Davies: - "Yeah, you really got be going, you got me so I can;t sleep at night, you really got me, you really got me..."

      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      Applause to the solution to declare the field symbol at the point where it is actually needed - and not some miles above (for those of us who like large methods)...

      The most robust way would be to have the scope limited to the loop itself, throwing the dreaded GETWA_NOT_ASSIGNED as soon as one tries to access the field-symbol outside of the loop.

      I don't know, however, whether limited scope is planned in ABAP.

      We would then be very similar to the range-based for in C++11 (http://www.stroustrup.com/C++11FAQ.html#for ). In

      for (auto entry : addressBook ) {

         ...

          }

      not only the type of the variable "entry" will be automatically (type "auto") be inferred from the addressBook, but also the scope of the symbol "entry" is limited to the for {} loop (which is nothing new). This way it is made sure that "entry" cannot be mis-used later on.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Rubbing salt into the wound eh?

      In fact:

      LOOP AT  ASSIGNING FIELD-SYMBOL(<fs>).

      ...

      ENDLOOP.

      ...

      LOOP AT  ASSIGNING FIELD-SYMBOL(<fs>).

      ...

      ENDLOOP.

      gives a syntax error 😥

      Author's profile photo Former Member
      Former Member

      LOOP AT itab1  ASSIGNING FIELD-SYMBOL(<fs1>).

      ...

      ENDLOOP.

      LOOP AT itab2  ASSIGNING FIELD-SYMBOL(<fs2>).

      ...

      ENDLOOP.

      So this is the correct syntax then? I think the visibility remains the same as in previous releases.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      'xactly ...

      (had to adjust the programming guidelines a bit)

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      First of all: you know I like ABAP 7.40 !!!!!

      But in this case the declaration of SFLIGHT_LH should result in a table (with all 'LH' entries) and not a flat structure (with just the first entry):

      DATA sflight_all  TYPE SORTED TABLE OF sflight WITH UNIQUE KEY carrid connid fldate.

      SELECT * FROM sflight

        INTO TABLE sflight_all

        ORDER BY PRIMARY KEY.

      DATA(sflight_lh) = sflight_all[ carrid = 'LH' ].

      And it would be great if this inline declaration would work also in the next release:

      SELECT * FROM sflight

        INTO TABLE DATA(sflight_all)

        ORDER BY PRIMARY KEY.

      Maybe ABAP 7.50/8.00?

      Author's profile photo Oliver Russinger
      Oliver Russinger

      i guess this is  DATA(sflight_lh) = sflight_all[ carrid = 'LH' ]. a read table not a loop...endloop construct.

      but they (sap) have a lot to do to meet users expectations.

      remember r/3 3.1 , there was no alv at all, only write statements and you have to do your sorting by yourself 😉

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Ten points for the right answer.

      All table expressions that we have up to now are shortcuts for READ and return a table line. I'll ask the creator of those, if he will think about LOOP-expressions.

      SELECT is already under consideration.

      Author's profile photo Suresh Subramanian
      Suresh Subramanian

      Thank you so much for bringing up the features in 7.40.

      Your post is pretty useful !

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      ... a kind of LOOP-Expression (working title FILTER) is in the making ...

      Author's profile photo Former Member
      Former Member

      This is good news. SELECT on itabs could replace many loops. I think it is more readable too. I would also like a MAP functionality on itabs similar to the map function in functional languages like Haskell or Scala.

      Thanks for inline declarations.
      It will make my ABAP code less verbose. I think it will remove "noise" from my programs helping me to concentrate on the business logic.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      SELECT on itabs could replace many loops

      No, it was about SELECT FROM dbtab INTO TABLE DATA(itab).

      But from 7.40 SP05, we will have Table Comprehensions!

      E.g.:

      DATA(itab) = VALUE itab(

            FOR x IN array INDEX INTO idx

               LET off = factor * idx IN

              ( col1 = x col2 = x * x col3 = x + off ) ).

      I would also like a MAP functionality on itabs

      Again 7.40, SP05:

      itab2 = CORRESPONDING #( itab1 MAPPING ... = ...  ... = ... ).

      Author's profile photo Paul Hardy
      Paul Hardy

      Hooray!

      In 7.02 in about 2011 you let ABAP have expressions ike A = ( B + C)  a construct BASIC could do in 1981, so if someone had jumped forward 30 years in a "Back to the Future" car they would have been comfortable with the language.

      Now in 2013 we have the good old FOR NEXT LET  LOOPS which again look just like the ZX81 syntax when I started to program when I was 14. I'm 45 now.

      I'm not complaining - this is a good thing, I loved programming the ZX81 even if it only had 1K of memory. It was better than the VIC20 even if that had much more memory the programming language onthe VIC20 had lots of holes in it, and workarounds e.g. PEEK / POKE.

      Programming languages must be like the fashion industry. Don't throw anything out of your wardrobe, in thirty years it will be fashionable again.

      Cheersy Cheers

      Paul

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author
      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      [START DIGRESSION]

      >It was better than the VIC20 even if that had much more memory

      Disagree. The VIC20 had the better CPU: MOS Technology's 6502 was by far the best CPU available in the market in those days - better then the 8080, and much better than the Z80 anyway. It's a pity that the x8... family won the race, although its concepts are worse. BTW - see here an impressive page of a 6502 fan, emulating the currents inside the processor during execution! http://www.visual6502.org/JSSim/

      [END DIGRESSION]

      Author's profile photo Ronaldo Aparecido
      Ronaldo Aparecido

      Congratulations Mrs Keller.

      I did try install the 7.4 version ,but the message that was not released in Brazil.

      It´s important for studies.

      what date to come in Brazil?

      THanks ,useful Post.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Hi Ronaldo,

      I'm sorry but I don't have information about the the release policy of the trial versions.

      Please visit the acording pages, e.g., http://scn.sap.com/docs/DOC-41566 , to learn more.

      Kind regards

      Horst

      Author's profile photo solen dogan
      solen dogan

      THats great Horst

      Abap gets more eloguent as each release is shipped

      I am so excited to try the new release

      look forward to try the new release

      Author's profile photo Kamal el Marzgioui
      Kamal el Marzgioui

      I was already very charmed by the new features of the new ABAP Workbench and Debugger (in 7.00 and 7.02)!

      This...this is just great stuff!! Can't wait 🙂

      @Horst, thank you for the post. Please keep sharing!

      Regards,
      Kamal.

      Author's profile photo Shakeeluddin Khaja
      Shakeeluddin Khaja

      Useful Information. Thanks for sharing.

      Regards.

      Author's profile photo Adi Sieker
      Adi Sieker

      Curently doing my first project on a 7.4 AS ABAP and inline declarations are just so nice. Been waiting for that for ages.

      Also method chaining and being able to directly access fields of a structure when calling functional methods are just awesome.

      Thank you ever so much, for the work in tht respect. Makes working with ABAP just so much more fun.

      Author's profile photo Christian Drumm
      Christian Drumm

      Hi Horst,

      is there any way to use inline declaration together with field-symbols where the field-symbol is itself an itab?

      What I'm trying to do is the following. I've got a structure example_order which has a component example_order_items. Now I want to access this data using only field symbols and inline declarations. What I tried is the following:

      ASSIGN COMPONENT 'ITEMS' OF STRUCTURE <example_order> TO FIELD-SYMBOL(<items>).

      LOOP AT <items> ASSIGNING FIELD-SYMBOL(<item>).

      This doesn't seem to work. At least I could't figure out how. If I use an explicitly declared field symbol instead everything works fine:

      FIELD-SYMBOLS <items> TYPE ANY TABLE.

      ASSIGN COMPONENT 'ITEMS' OF STRUCTURE <example_order> TO <items>

      LOOP AT <items> ASSIGNING FIELD-SYMBOL(<item>).

      However, I'd like to use the inline declarations even in this case. Is this possible?

      Best,

      Christian

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Hi Christian,

      Since you are using the dynamic ASSIGN COMPONENT, the field symbol declared inline has the generic type ANY (how should the compiler know the type of the assigned component). A field symbol (or formal parameter) that is not typed as an internal table cannot be used at operand positions for internal tables.

      Your example would work with a static ASSIGN:

      ASSIGN COMPONENT <example_order>-items TO FIELD-SYMBOL(<items>).

      LOOP AT <items> ASSIGNING FIELD-SYMBOL(<item>).

      If this is not possible, you have to declare and type the field symbol explicitly with TYPE ANY TABLE as you've shown it. An inline declaration is not possible then.

      Best,

      Horst

      Author's profile photo Christian Drumm
      Christian Drumm

      Hi Horst,

      Thanks. That's what I was expecting. I'll have to use the explicit declaration in my case then.

      Christian

      Author's profile photo Former Member
      Former Member

      Hello Horst,

      I recently started exploring 7.4 features and its fascinating.

      This works well

      PARAMETERS: p_from   TYPE /sapapo/locno.

      DATA(g_from) = p_from

      DATA(g_from1) = g_from.

      But, when I try this, I get an error.

      PARAMETERS: p_from   TYPE /sapapo/locno.

      DATA(g_from1) = DATA(g_from) = p_from.

      Also one more question,

      Though Inline declarations can be used always, what is its effect on the global variables in Data declaration Includes?. The reason for this question is all the clients have coding standards and most of them will go for 1 Data declaration include and 1 Subroutine includes.

      Lokesh

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Hi Lokesch,

      But, when I try this, I get an error.

      PARAMETERS: p_from   TYPE /sapapo/locno.

      DATA(g_from1) = DATA(g_from) = p_from.

      Yes, inline declarations are forbidden in multiple assignments.

      what is its effect on the global variables in Data declaration Includes

      Global variables shouldn't be declared at all ... 😛

      But seriously:

      Inline declarations influenced the way we looked at those things and we tackled that as follows

      Programming Guideline for Inline Declarations

      Horst

      Author's profile photo Adi Sieker
      Adi Sieker

      Horst Keller wrote:

      Inline declarations influenced the way we looked at those things and we tackled that as follows

      Programming Guideline for Inline Declarations

      ideally the scope of inline declarations would be the block they were defined for. 🙂

      That was the first question most colleagues asked me when I showed them inline declarations.

      i.e.the following would cause a syntax error on the last line, stating that ls_struc is unknown:

      LOOP AT lt_table into DATA(ls_struc).

           "Do something with ls_struc.

      ENDLOOP.

      add 1 to ls_struc-counter.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      I know, I know, I know, ...  sigh

      Author's profile photo Adi Sieker
      Adi Sieker

      Horst Keller wrote:

      I know, I know, I know, ...  sigh

      sounds like that discussion as been had before. 🙂

      But since it's not in there now and because people will start relying on it being the way it is now, it will never happen. 🙁

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      The backward compatibility trap. Building new features in old ABAP. There is no local context in old ABAP and it seems to be impossible to enable it without breaking existing code.

      Author's profile photo SAP ITR ENTWICKLUNG
      SAP ITR ENTWICKLUNG

      Maybe with a new syntax element for scoping blocks like {... scoping block } as we know it from Java, C++...

      Additionally there could be a scoping version of other block building statements like

      If x = Y {  ... }

      loop at lt_a into ls_a {  ... }

      case y { when a. ... }

      replacing the end[something] with the block closing sign. This would at the same time make the code leaner and more readable.

      Author's profile photo Paul Hardy
      Paul Hardy

      I agree there is a big bonus with making code shorter (leaner)

      In Java and so forth everyone is sed to the good old { }.

      However for good or for bad ABAP programmers are used to things like ENDIF, and I wonder if } is more readable e.g.

      is

            ENDIF.

          ENDCASE.

        ENDMETHOD.

      better than

         }

        }

      }

      When it comes to the readability stakes?

      I presume in Eclipse when you hover over a "}" sign it tells you in a hover text the start of the code block the sign is closing? In ABAP the official recommendation used to be to add a comment such as

      ENDIF."Is the fish blue?

      Cheersy Cheers

      Paul

      Author's profile photo Adi Sieker
      Adi Sieker

      Paul Hardy wrote:

      In ABAP the official recommendation used to be to add a comment such as

      ENDIF."Is the fish blue?

      I think, if that is necessary to make the scope (method/function/form) readable then it's too complicated/long and should be split up.

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      ADT always marks the current context of your writing position (IF/ELSE/ENDIF in this example):

      adt.PNG

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      In ABAP the official recommendation used to be to add a comment such as

      ENDIF."Is the fish blue?

      Used to be, but is it still?

      See Comments.

      Author's profile photo Adi Sieker
      Adi Sieker

                                  Horst Keller wrote:

      In ABAP the official recommendation used to be to add a comment such as

      ENDIF."Is the fish blue?

      Used to be, but is it still?

      See Comments.

      Quote from "Arrangement in source Code" page:

      "...

      End of line comments are suitable for the following situations:

      • ...
      • To indicate block ends (separate from indentations) in larger control structures

      ..."

      and the "Good Example" is formatted as follows:

        ENDIF. "item_ref IS BOUND AND...
      ENDLOOP.
      ...
      ENDMETHOD. "main
      *----------------------------------------------------------*
      ENDCLASS. "application


      it does imply to use the endcomments.


      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Arrrrrgh 😳

      Author's profile photo Adi Sieker
      Adi Sieker

      Horst Keller wrote:

      Arrrrrgh 😳

      Can I like that twice. 😀

      oh, and btw space is getting pretty thin down this deep in a thread.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Can I like that twice

      Give me five!

      Author's profile photo Franz Seidl
      Franz Seidl

      Good posting! Thank you! 🙂

      Author's profile photo Saurabh Kumbhare
      Saurabh Kumbhare

      Thanks!! 🙂

      Author's profile photo Former Member
      Former Member

      Hi,

      My system is on Release 7.40 SP006. Inline declaration is giving syntax error.

      My Code:

      REPORT zr_opensql_01_aggregation.

      SELECT bp_id,
              company_name,
              so~currency_code,
              SUM( so~gross_amount ) AS total_gross_amount
         FROM snwd_so AS so
         INNER JOIN snwd_bpa AS bpa
                 ON so~buyer_guid = bpa~node_key
         INTO TABLE @DATA(lt_result)
         GROUP BY bp_id, company_name, so~currency_code.

      cl_demo_output=>display_data( value = lt_result ).


      Syntax Error: The inline declaration "DATA(lt_result)" is not possible in this position.


      Any inputs on why this is happening will help a lot.


      Regards,

      Sayantika.

      Author's profile photo Uwe Fetzer
      Uwe Fetzer

      Inline declaration within open SQL comes in SP8.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author
      Author's profile photo Former Member
      Former Member

      Thanks for this Blog post Horst. I haven't started playing around with 7.4 yet but sure looks interesting.

      One thing scares me though is this.

      Rule

      Only use inline declarations locally

      Only make inline declarations in processing blocks that support local data. Use them as if they were local declarations in the current statement block.

      Details

      If used correctly, inline declarations are an excellent way of making programs leaner and easier to understand.

      ------

      The IF used correctly part in the Details.

      --------

      Don't you feel the code would be much difficult to maintain if the program is a 1000 lines code and some where way up in the top there is an inline declared variable ( defined globally -- by mistake I may add) and you have to debug this chunk of code to figure out where exactly is this variable defined.

      With the usual declaration statement you know that the declaration is made with the TYPE statement.

      -- Well one argument would be with inline code you would not have 1000 lines of code anyway.  😛

      Comments.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Well one argument would be with inline code you would not have 1000 lines of code anyway

      'xactly, see Procedure Volume 😈 .

      Author's profile photo Adi Sieker
      Adi Sieker

      Horst Keller wrote:

      'xactly, see Procedure Volume

      😈

      .

      In my opinion this is the number one thing that should be hammered into every developers head. I also think that 150 executable statements is to much. I think it should be around 50-70.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      I also think that 150 executable statements is to much. I think it should be around 50-70.

      Yes, that's the factor you can gain by using expression enabled ABAP 😉 .

      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      My rule of thumb is: The implementation part of a method should be visible completely on my screen, with the signature part expanded => max. at about 30-40 lines of code per method, including blank lines and comments.

      Author's profile photo Amol Vakhare
      Amol Vakhare

      Hi Horst,

      Wondering how can I declare a packed variable or any other type variable using the Data() operator.

      Data(lv_var1) = 1.  "Integer"
      Data(lv_var2) = '1.10'. "Declared as character...

      How to declare lv_var2 as packed type?

      Author's profile photo Adi Sieker
      Adi Sieker

      Hi Amol,

      DATA(lv_var2) = VALUE packed_type('1.10').

      Where packed_type is any type in the ABAP dictionary and whatever else VALUE allows.

      Cheers

         Adi

      Author's profile photo Amol Vakhare
      Amol Vakhare

      Thanks Adi! Understood the use of VALUE too 🙂

      Author's profile photo Amol Vakhare
      Amol Vakhare

      Hi Adi,Though I understood the use of VALUE.. still wondering why following gives compile time error>

      Data(lv_var) = value p('123.10').

      Error: Value of generic type "P" cannot be constructed..

      The documentation says for generic type, additional attributes need to be specified.. so stuck again? Probable alternate is to define a type with a packed component in it and use it to declare.. Thoughts?

      Author's profile photo Adi Sieker
      Adi Sieker

      Hi,

      I would use a type from the data dictionary.

      Cheers

         Adi

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      The problem is, it wouldn't work too. Syntax error in:

      TYPES pack TYPE p DECIMALS 3.

      DATA(val) = VALUE pack( '1.1' ).

      Why? Operator VALUE is not possible for elementary types except for the initial value.

      Therefore, either initial value:

      TYPES pack TYPE p DECIMALS 3.

      DATA(val) = VALUE pack( ).

      or the conversion operator:

      TYPES pack TYPE p DECIMALS 3.

      DATA(val) = CONV pack( '1.1' ).

      But in fact the question remains, why you want to do this at all?

      If you want to declare a packed number, simply do so by using statement DATA or TYPES. The DATA operator for inline delcarations is designed for being used at declaration positions where the operand type is completely known and not for declaring variables of any types before using them. So if you have e.g. a method retrurning a packed number, of course you write

      DATA(val) = get_packed( ... ).

      This is a use case. Constructs as above are possible but more as side effects ...

      Author's profile photo Amol Vakhare
      Amol Vakhare

      I see your point now.. With it I am more clearer on its usage. Thank you so much!

      The DATA operator for inline delcarations is designed for being used at declaration positions where the operand type is completely known and not for declaring variables of any types before using them. So if you have e.g. a method retrurning a packed number, of course you write

      DATA(val) = get_packed( ... ).

      This is a use case. Constructs as above are possible but more as side effects ...

      Author's profile photo Michael Fritz
      Michael Fritz

      Hi,

      how would one re-write this existing coding using inline declarations?

      DATA: o_reference  TYPE REF TO zcl_customer_service_base.

      IF NOT notif_no IS INITIAL.

      "Create new reference

           CREATE OBJECT o_reference   

                EXPORTING     

                     i_order_number        = ''     

                     i_notif_number         = l_notif_no     

                     i_use_notification     = abap_true     

                     i_no_notif_buffer      = abap_false     

                     i_no_partner_init      = abap_true     

                     i_remove_deleted_items = abap_true.

      ELSE. 

      "Use existing reference 

           o_reference = me.

      ENDIF.

      The following will not work because of error "o_reference is already declared" when using the second inline declaration in the ELSE branch.

      IF NOT l_notif_no IS INITIAL   .

           DATA(o_reference) = NEW zcl_customer_service_base(                           i_order_number        = ''    

                i_notif_number         = l_notif_no    

                i_use_notification     = abap_true    

                i_no_notif_buffer      = abap_false    

                i_no_partner_init      = abap_true    

                i_remove_deleted_items = abap_true    

                ).

      ELSE.

           DATA(o_reference) = me.  "<<-- ERROR here

      ENDIF.

      Michael

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Well that's simple

      IF NOT l_notif_no IS INITIAL   .

           DATA(o_reference) = NEW zcl_customer_service_base(                           i_order_number        = ''   

                i_notif_number         = l_notif_no   

                i_use_notification     = abap_true   

                i_no_notif_buffer      = abap_false   

                i_no_partner_init      = abap_true   

                i_remove_deleted_items = abap_true   

                ).

      ELSE.

           o_reference = me.  "<<-- ERROR here

      ENDIF.

      Note that

      DATA(o_reference) = NEW zcl_customer_service_base(  ...

      can be seen as a short cut for:

      DATA o_reference TYPE REF TO zcl_customer_service_base.

      CREATE OBJECT o_reference EXPORTING ...

      Therefore, the data declaration is valid for the current context.

      Author's profile photo Michael Fritz
      Michael Fritz

      Horst,

      thanks again for your reply.

      That means it does not matter if the IF condition is met or not and the program execution immediately jumps into the ELSE branch?

      That's cool indeed!

      I've just checked this and it works perfectly! Never thought of this! At the very end no short dumps or similar when accessing the reference from the ELSE branch.

      Thanks,
      Michael

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      That means it does not matter if the IF condition is met or not and the program
      execution immediately jumps into the ELSE branch?

      Yes, but that's also kind of dangerous. Because there is no local context for data in control structures, the declared objects are statically visible everywhere behind the declaration and dynamically (ASSIGN (name ) ...) even everywhere in front of the declaration. Therefore, it needs some discipline when working with that, see the guideline.

      Author's profile photo Michael Fritz
      Michael Fritz

      You see I'm still learning those new inline declarations since we recently upgraded our ERP to 7.40 (SP08) 😉

      I wonder how to create an internal table without using any default values.

      Previously I would have written a statement like this:

      data: lt_w3head type STANDARD TABLE OF w3head.

      Now I tried to get the same result using inline declaration, to no avail so far.

      I need this internal table as a result table for a function module, hence I don't have any rows available so far. The function module will return them instead.

      Would it be possible to use those inline declarations for this purpose, too?

      Michael

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      TYPES: tt_w3head type STANDARD TABLE OF w3head WITH ... KEY ...

      DATA(data: lt_w3head) = VALUE #( ).

      but see above,

      ... the question remains, why you want to do this at all? ... The DATA operator for inline delcarations is designed for being used at declaration positions where the operand type is completely known and not for declaring variables of any types before using them.

      See Declaration positions

      Author's profile photo Damandeep Thakur
      Damandeep Thakur

      Hello Horst,

      The new features of ABAP are exciting. Is the performance same or better compared to old ones?

      Thanks!

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Same, because the same kernel modules are called. It's mainly the syntax that is different.

      But be aware of performance traps if you use expressions repeatedly in statements or even in loops. The new syntax can be seductive to write things you never wrote with fully blown statements. That can easlily lead to performing the same operations multiply.

      Author's profile photo Dominik Krämer
      Dominik Krämer

      Hi Horst,

      great blog! However I have an question on the following part:

      TYPES: t_scarr   TYPE SORTED TABLE OF scarr
                   WITH UNIQUE KEY carrid.

      TYPES:
         BEGIN OF t_flights,
           scarr TYPE t_scarr,
         END OF t_flights.
      DATA: flights TYPE t_flights.

      SELECT * FROM scarr INTO TABLE flights-scarr.

      ASSIGN COMPONENT 'SCARR' OF STRUCTURE flights TO FIELD-SYMBOL(<fs_dt_data>).


      Basically the above code works like a charm and in the end the fs_dt_data contains a sorted table with the values from scarr. However when I then want to do a loop over this table I cannot get the code to be activated:

      LOOP AT <fs_dt_data> ASSIGNING FIELD-SYMBOL(<fs_data>).
         ...
      ENDLOOP.


      I always receive the following error: "." expected after "<FS_DT_DATA>"


      Is this a bug or am I doing something wrong?


      Regards,

      Dominik

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      The error message is nonsense (I forward it) but you are trying to loop over something that can't be statically recognized as table. For that you still need a explicit declaration:

      FIELD-SYMBOLS <fs_dt_data> type STANDARD TABLE.
      ASSIGN COMPONENT 'SCARR' OF STRUCTURE flights TO <fs_dt_data>.

      LOOP AT <fs_dt_data> ASSIGNING FIELD-SYMBOL(<fs_data>).
         ...
      ENDLOOP.

      Author's profile photo Dominik Krämer
      Dominik Krämer

      Yes that's my workaround for the moment. Is this something which is planned for a later release, or are there any technical restrictions which prevent this?

      Regards,

      Dominik

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      If no type can be deduced, the field symbol declared inline is typed with ANY. You never could/can use fully generic field field symbols at operand positions of internal tables. That's the rule.

      Author's profile photo Dominik Krämer
      Dominik Krämer

      Hi Horst,

      not sure if I fully understood your point.

      Untitled.png

      In the debugger the type is correctly deduced as Sorted Table, only in the ABAP editor this is not recognised / throws the error message: "." expected after "<FS_DT_DATA>"


      Regards,

      Dominik

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Debugger is runtime. A DESCRIBE FIELD or RTTI would also find the internal table.

      But syntax check happens at compile time and the internal table cannot be deduced statically.

      https://ldcialx.wdf.sap.corp:44318/sap/public/bc/abap/docu?sap-language=EN&sap-client=000&format=STANDARD&object=ABENTYP…

      "The formal parameter or field symbol can be used as operands anywhere that is
      not excluded by this typing. However, operands that expect particular internal
      tables are an exception to this rule. Here, only formal parameters or field
      symbols typed as internal tables with the appropriate table category are allowed."

      Author's profile photo Dominik Krämer
      Dominik Krämer

      Thanks for the explanation.

      However it's a shame that the runtime would give me the expected result and then have the limitation in the compiler, as I would had a use case for this which would have saved me a ton of additional declaration.

      Regards,

      Dominik

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      The nonsense is independent from expressions

      FIELD-SYMBOLS <fs_dt_data> TYPE any.

      DATA wa.
      LOOP AT <fs_dt_data> INTO wa.
       
      ...
      ENDLOOP.

      Author's profile photo Sougata Chatterjee
      Sougata Chatterjee

      Hi Horst,

      Why the following is not supported? I'm in 7.4 SP05 on HDB - is it supported in later SPs?

      CALL FUNCTION 'function_module'

           EXPORTING

                i_param     = DATA(lv_data)


      Regards,

      Sougata.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Since that operand position is a read and not a write position. Declaration positions are always write positions (L-values, not R-values).

      Author's profile photo Rüdiger Plantiko
      Rüdiger Plantiko

      Hi Sougata,

      you want to pass a data object to the called function module, where it will not be changed (since you are EXPORTING it).

      The only case where this makes sense in my eyes would be that the inventor of the function module declared an import parameter to be obligatory although not strictly needed in the code (i.e. although being optional in fact), and you want to pass an initial value to it, just to satisfy the interface.

      You can't do that with a DATA operator, but you could do it with VALUE:

      call function 'Z_IMPORT_PAR_OBLIGATORY'

         exporting

           is_vbap       = value vbap( ).


      Here, IS_VBAP is an obligatory import parameter of Z_IMPORT_PAR_OBLIGATORY of type VBAP. You can't use # here, because for function modules - as opposed to methods - the compiler doesn't re-read the parameter types.


      Regards,

      Rüdiger

      Author's profile photo Sougata Chatterjee
      Sougata Chatterjee

      Thanks but it will not work for me as I'm on SP05.

      Author's profile photo Sougata Chatterjee
      Sougata Chatterjee

      Sorry, I take that back - it does work for exporting params. Thanks!

      Author's profile photo Nishant Bansal
      Nishant Bansal

      Dear Horst Keller,

      First of all thanks for sharing this blog.

      I have one question regarding this. Below i am taking one simple example.

      DATA wa like LINE OF itab.
      LOOP AT itab INTO wa.  
        ...
      ENDLOOP.

      With 7.40

      LOOP AT itab INTO DATA(wa).  
        ...
      ENDLOOP
      .



      After defining the WA using DATA(WA).

      Can i define the same name WA variable again in the current session?

      Actually i don't have system to test it.



      Thanks and Regards,

      Nishant

      Author's profile photo Michael Fritz
      Michael Fritz

      Hi,

      no you can't use DATA(wa) again.

      However after writing this inline declaration above, you can now use

      LOOP AT itab INTO wa.

      ...

      ENDLOOP.

      anywhere in your coding. No need to declare wa again.

      Michael

      Author's profile photo Raphael Pacheco
      Raphael Pacheco

      Horst,

      I have a basic question of this inline declarations.

      How could I create a counter using the inline declarations? It would be possible to make, for example ADD 1 to DATA(i)?


      Warn regards,


      Raphael Pacheco.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Would it be possible to write, for example, ADD 1 to DATA(i)?

      No, for two reasons:

      • The statement ADD is not expression enabled.
      • DATA(num) = num + 1 doesn't work either because you cannot declare a variable inline at LHS that is used at RHS.

      Best

      Horst

      Author's profile photo Former Member
      Former Member

      Thanks for the article and for introducing us to new ABAP.

      I am sorry if this question was already asked and answered in the 5 pages of Q&A, but how does the double-click navigation work with this type of inline declarations? If the variable is a structure, would I be able to eventually navigate (just by double-clicking a few times) to DDIC and see the structure components?

      When I first started programming, many languages were sneered at because they did not require explicit data declarations. Agreed, inline declaration is different, but still the trend is unsettling.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Works as before, eg.,

      DATA struct1 TYPE scarr.

      DATA(struct2) = VALUE scarr( ).

      ... struct1 ...

      ... struct2 ...

      Double clicking struct1, struct2 leads to the respective declaration, where you can double click the type.

      Author's profile photo Former Member
      Former Member

      I am full of happiness. Functional programming at last 🙂

      Author's profile photo Dionisio Ambrona
      Dionisio Ambrona

      Dear Horst Keller,

         in a first place, thanks a lot for your blog. I'm just starting to learn about new ABAP 7.40 capabilities, so I find it quite usefull and interesting.

         Regarding your first example in this post,

      Before 7.40

      DATA text TYPE string.
      text = `...`.

      With 7.40

      DATA(text) = `...`.


         I have the following question: what is the data type in the second dclaration with 7.40, is it a type string variable or is it a type c variable? Is there any rule so the system determines this?

         I know by reading the blog that online declarations are specially meant to be used for calling methods avoding extra code lines to declare help variables, but I'm just curious.

         Thank you and best regards!

         Dionisio

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Is there any rule so the system determines this?

      Sure, see the ABAP Keyword Documentation ...

      In the above example you have a string literal on the RHS and therefore the result is string.

      Best,

      Horst

      Author's profile photo Marc Cawood
      Marc Cawood

      Any way to dynamically cast inbound parameters of FUNCTION modules?

      DATA: lv_s TYPE STRING VALUE '0000'.

      CALL FUNCTION SOMETHING

      EXPORTING vkorg = lv_s. " Dumps here expecting CHAR4

      or even better:

      CALL FUNCTION SOMETHING

      EXPORTING vkorg = myStringMethod( ). " Function returning string

      Currently the compiler says "No type can be derived from the context for the operator "CONV"."

      Author's profile photo Former Member
      Former Member

      Do you mean CONV (ABAP News for Release 7.40 - Constructor Operators CONV and CAST)?

      You must set the expected type explicitly though.

      Author's profile photo Marc Cawood
      Marc Cawood

      OK, gottit:

      CALL FUNCTION 'LOAD_SOMETHING'

                 EXPORTING

                   customer  = CONV kunnr( get( 'customer' ) )


      Pretty cool - ABAP arrivoing in the 21st century at last!

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      See EXPORTING:

      a1, a2, ... are general expression positions. In other words, functions and expressions can be passed as actual parameters, alongside data objects.

      -> You can pass your myStringMethod( ).

      Unlike in method calls, types cannot be specified generically (#) when a constructor expression is specified. This is because the typing of the parameters is not determined until runtime.

      -> That's why you have to specify type string explicitly (or call a method).

      Author's profile photo Marc Cawood
      Marc Cawood

      How do you mean "constructor"?

      Theoretically, if the parameters of a Function Module are strongly typed then the compiler can know the type...

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      How do you mean "constructor"?

      I mean constructor expression.

      Theoretically, if the parameters of a Function Module are strongly typed then the compiler can know the type...

      Problem is that calling a function module other than calling a method is always a dynamic call. You specify the function module as a field and never directly. The compiler doesn't know the function module.Specifying it with a literal is pseudo static so to say. Then, some test tools (extended program check) evaluate the name, but not the compiler.

      Author's profile photo Former Member
      Former Member

      Problem is that calling a function module other than calling a method is always a dynamic call. You specify the function module as a field and never directly.

      Wow!!! Made my day 😎

      Is this somewhere specified in the ABAP documentation? I mean although this (You specify the function module as a field) is quite obvious, but still most of the ABAPers wouldn't have thought about it 🙂

      Author's profile photo Paul Hardy
      Paul Hardy

      I suppose that is why, when you pass the wrong type of variable into a function module, the normal syntax check doesn't say boo, but you get a short dump when you run the program.

      And if a function module has three compulsory IMPORTING parameters and I only specify two, no syntax error either.

      I know function modules are obsolete now, and we should not be using them, but I have always thought this (lack of syntax check warnings) was a bug as opposed to anything else i.e. too difficult for SAP to fix so document it, and then pretend it is not a bug. To be fair Microsoft do this sort of thing all the time.

      It is rather like the FOR ALL ENTRIES with a blank table doing a full table scan as opposed to not bringing back anything. That is an obvious bug as well, but will never be fixed, just more and more code inspector warnings.

      I am sure I will now be told millions of reasons why the code inspector / extended syntax check can do this, but not the standard syntax check, that's impossible, to which I will reply "it's a bug, bug, bug, bug, bug"

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      I suppose that is why, when you pass the wrong type of variable into a function module, the normal syntax check doesn't say boo, but you get a short dump when you run the program.

      And if a function module has three compulsory IMPORTING parameters and I only specify two, no syntax error either.

      Yes,, sure ...

      I will now be told millions of reasons

      One important reason is, its too old to be changed. There are miilions lines of code lying around worldwide that call FMs wrongly but are never executed (dead, dead, dead), Now you go and make syntax errors out of that and have some fun.


      In fact, there are also fans of the lax checking. The reason is that you do not break a system if you change an interface in an incompatible way as you do with methods. A true story that happened to me: I changed the interface of a method of CL_ABAP_DOCU and forgot to adjust its callers before activating. As result callers became syntactically incorrect and since CL_ABAP_DOCU is called far deeper in the system than I ever expected, you could not logon to the system any more due to syntax errors in central modules. Unfortunately, there was a customer presentation running on that system in SAP Arena, Mannheim that afternoon - no lie! The presenter wasn't amused. And correcting the error also wasn't to simple (remember, no logon  possible). Admin had to import the old version of the class. Wouldn't have happened with a function module.  I am not a fan of lax checking but had to learn to be more careful the hard way.





      Author's profile photo Marc Cawood
      Marc Cawood

      In theory you (ABAP Product Management) could make a new keyword (or syntax variant) to call FMs "strongly".

      EXEC FUNCTION 'MYFUNC'.

      or

      CALL FUNCTION MYFUNC. " Instead of 'MYFUNC'

      It's always been a weaknes of FMs that they compile when they're definitely gonna dump.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      In theory, yes. But good ol' function modules are "different".

      Remember, there's no ABAP syntax for defining a function module's interface as it is for methods.

      Author's profile photo Paul Hardy
      Paul Hardy

      I understand that SAP tries to be 100% downward compatible i.e. an upgrade will cause very few syntax errors to existing code. I have usually found if custom code passes the extended syntax check then you are very safe indeed,

      However in the past I have found that after an upgrade some custom code shows a yellow warning in the standard syntax check, where it did not on the old version of ABAP.

      As a fine example, the most annoying thing in the world "work area has more fields than selected".

      Show me a bus queue of programmers who thought that was a wonderful innovation.

      If SAP were to add a yellow warning "your function module is going to dump, and here is why" it would not cause syntax errors in any old code, which would continue to behave as before (dump) and not cause any grief being being transported or whatever.

      In fact you can add this new syntax check warning and ditch the "work area has more fields" one if you want.

      Oh yes, and in regard to the current situation ... it's a bug, bug, bug, bug, bug.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      In fact you can add this new syntax check warning and ditch the "work area has more fields" one if you want.


      Unfortunately (or maybe fortunately) I can't 😉



      Author's profile photo Former Member
      Former Member

      A true story that happened to me: I changed the interface of a method of CL_ABAP_DOCU and forgot to adjust its callers before activating.

      Good to know Horst Keller also makes mistakes 😏

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      way more than you think ...

      Author's profile photo Former Member
      Former Member

      I suppose that is why, when you pass the wrong type of variable into a function module, the normal syntax check doesn't say boo, but you get a short dump when you run the program.

      I always wondered, why do FMs get such love from the syntax checker? 😕 Now i know

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Is this somewhere specified in the ABAP documentation?


      See CALL FUNCTION ...


      (And the the last  point here, hehe)


      Author's profile photo Mike Pokraka
      Mike Pokraka

      Small annoyance: Why are multiple inline declarations not permitted in the same block? Would it not make sense to just ignore something that's already declared and reuse it?

      My main use case is an inline declaration that can be conditional and/or inside a loop.

      if some condition.

         read table x into data(wa) index 1.

      endif.

      ...

      if some other condition.

        read table x into data(wa) where ...

      endif.

      It just seems awkward to have to use wa1 and wa2 here.

      Regards,

      Mike

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      I'd rather say big annoyance. An inline declaration is like a DATA statement at this position with all well known drawbacks. But as already discussed here from time to time, ABAP does not support local data contexts in control structures and I'm afraid it will never do.

      Author's profile photo Mike Pokraka
      Mike Pokraka

      Understood, and that is exactly how an old-style DATA statement works.

      But, since 'it will never do', can/should an inline DATA not be made more tolerant and just be local to the method all the time?

      If a global element of the same name already exists, it will be overshadowed (current behaviour).

      If a local declaration (method, function module) already exists, the same element will be reused - as if the data() statement were not there.

      Just an idea that, to me at least, makes more sense than ever with inline declarations.

      Author's profile photo Mike Pokraka
      Mike Pokraka

      Actually I've just thought about it some more and it could be a risk if one isn't careful:

      loop at itab into data(wa).

      ...

          if some condition.

              read table things into data(wa).

              ==> oops!

      ...

      endloop.

      But then again this is down to the developer to manage. The same mistake is possible with a regular DATA declaration up front.

      Author's profile photo Former Member
      Former Member

      Great Horst, Amazing features!!!

      Awaited for such facility for a very long time..

      Feeling excited 🙂

      Author's profile photo Former Member
      Former Member

      Any idea why this doesn't work?

      /ui2/cl_json=>deserialize(

         EXPORTING json = request->get_cdata( )

         CHANGING data = CONV zmy_data_tt( lt_data )

      ).

      Instead of declaring DATA lt_data TYPE zmy_data_tt.

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      There are several reasons, CONV is not an inline declaration, CHANGING is neither a declaration position nor  general expression position. How should that work at a read/write position?

      Author's profile photo Former Member
      Former Member

      OK, I get the CHANGING argument - not the inline one since I use CONV successfully for EXPORTING parameters.

      One more for you - should this not work?

      DATA ls_ret TYPE zmytype.

      APPEND ls_ret TO data( lt_ret ).

      Is lt_ret not implicitly TYPE STANDARD TABLE OF zmytype?


      It seems to me this is corollary of LOOP AT itab INTO DATA(wa)

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Check out the places where DATA(...) is possible here.

      Author's profile photo Jacques Nomssi
      Jacques Nomssi

      Hello Horst,

      given a method declaration

      get_selected_rows EXPORTING et_rows TYPE lvc_t_row

      RETURNING VALUE(rv_flag) TYPE flag,

      I can write either

      get_selected_rows( IMPORTING et_rows = DATA(lt_rows) ).

      or

      CHECK get_selected_rows( IMPORTING et_rows = lt_rows ).

      but I cannot combine those like this

      CHECK get_selected_rows( IMPORTING et_rows = DATA(lt_rows)).


      Why not? Is the method call then considered part of an expression ?

      JNN

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Is the method call then considered part of an expression ?

      Yes,

      A method call at an operand position is treated like an expression.

      See functional method call:

      Inline declarations are not possible for actual parameters.

      Best

      Horst

      Author's profile photo Suman Pradhan
      Suman Pradhan

      Great article and interesting Q&A pages .

      Thanks Horst

      Author's profile photo saslove sap
      saslove sap

      Well this is wrong 🙂 !! Sorry to say that !!

      Before 7.40

      DATA text TYPE string.
      text `…`.

      With 7.40

      DATA(text) `…`.

      This text will only stores 3 characters. it cant be string, if you add text = '...1234' I am afriad it reads only first 3 characters, Let me know how to define a string please, thanks.

       

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Sorry, but you are wrong …

      DATA(text) `…`.

      Is the same as

      DATA text TYPE string VALUE  `…`.

      Author's profile photo saslove sap
      saslove sap

      What a Fun?? Lol! last time when I executed it came as said above, its getting truncated, but later when I apply today its working as you said, not sure where the mistake 🙂 but thank you very much, then how do we define if we need only char3 using data ?

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      Trivial, try yourself...

      Author's profile photo Marcelo M Bovo
      Marcelo M Bovo

      Hi Horst,

       

      When I use a method like this one bellow, it works perfectly well

      open_attachment( IMPORTING ex_docname = DATA(lv_docname) ).

       

      But if the method has a Returning value like the one bellow, then its impossible to use the inline declaration on the importing parameter

      data(lt_attachemnt) = open_attachment( importing ex_docname = data(lv_docname) ).

       

      Disclosure: the parameter ex_docname is optional, most of the time I use this method it's only with the returning parameter

       

      Author's profile photo Horst Keller
      Horst Keller
      Blog Post Author

      https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/index.htm?file=abendata_inline.htm

       

      • An inline declaration cannot occur on the right-hand side of an assignment or within an expression.
      Author's profile photo Padmaja Vasan
      Padmaja Vasan

      Hi. I've a select query with inline declared table inside a routine. How to read it in another routine. When I try to read, it says that that table is not defined by DATA statement.

      Author's profile photo Volodymyr Shcheglov
      Volodymyr Shcheglov

      Hi Horst Keller ,

      I know it's ABAP 7.53 already, but I couldn't find how to make this possible:

      loop at idoc_data assigning field-symbol(<data>).
        case <data>-segnam.
          when 'SomeSegmentName'.
            if ref some_segment_type( <data> )->some_field is initial.
              "Do/Skip processing or change IDoc's status
            endif.
        endcase.
      endloop.

      Even simple casting of SDATA (char1000) to a static structure type isn't possible with inline declarations, e.g., in the previous example, if we choose to declare a helper variable, this won't be possible:

      loop at idoc_data assigning field-symbol(<data>).
        case <data>-segnam.
          when 'SomeSegmentName'.
            data(header) = ref some_segment_type( <data> ).
      *...
        endcase.
      endloop.

      The code above gives error:

      However, segment types are by definition compatible with the SDATA field of type CHAR1000. I know that I can use static declarations, but it's not as handy as, say,

      check ref my_structure_type( char1000_field )-field_1 > 0.

      or even this, where declaration occurs near consumption:

      data(header) = ref header_segment( idoc_data-sdata ).

      Similar question regards to field symbols. If I declare a generic field-symbol, I can't refer to structure type fields DESPITE static type casting:

      field-symbols <fs> type simple.
      *...
      assign idoc_data-sdata to <fs> CASTING TYPE my_structure type. "note the type is know at design time
      check <fs>-field_5 > 0.  "error: 'The data object "<FS>" does not have a structure and therefore does not have a component called ...'

      I understand that the same CASTING TYPE can use a type handler which allows dynamic typing, but, at least, can structure recognition be implemented in case of statically defined type casts?

       

      Kind regards,

      Vlad.