REDUCE ABAP750 FOR x = u IN n = 1 THEN brainf*ck

Hoijoijoi. Ich gebe zu, ich tue mich echt schwer mit den neuen Befehlen im ABAP-Sprachschatz. Besonders die ganz neuen Features im ABAP Release 7.50 (oder 7.40 – ich blick da nicht mehr durch) fordern mich ziemlich (REDUCE, COND, FILTER etc).

Angeregt durch den Artikel von Jerry Wang im neuen SCN über REDUCE habe ich mich mit dem Befehl-REDUCE näher beschäftigt. Über die ABAP-Doku bin ich dann auf die Demoprogramme DEMO_REDUCE* gestolpert und beim DEMO_REDUCE_SIMPLE hängen geblieben.

Das Programm ermittelt mit Hilfe des REDUCE-Befehls die Summe von Werten in einer Tabelle. Das Programm DEMO_REDUCE_COND_ITERATION erzeugt mit Hilfe einer FOR-Schleife zusammengesetzte Texte (1 2 3 4 usw).

Ich wollte dann ein bisserl mit den Features herumspielen und hatte die Idee, einen HTML-Text zusammen zusetzen.

Aus der Tabelle

<HTML>
<BODY>
<P>

wollte ich die einzelnen Elemente plus einem separaten Text zu einem String zusammenfügen. Das funktionierte auch noch sehr einfach:

DATA(text) = REDUCE string(
               INIT html = ``
                FOR command IN html_commands 
                NEXT html = |{ html }{ command }| ) 
            && 'Hallo Welt'.

Eigentlich nur zum Spaß habe ich versucht, ob ich mit einem erneuten && auch ein erneutes REDUCE benutzen kann. Obwohl ich einigermaßen überrascht war, dass es anstandslos funktionierte, wäre ich auch maßlos enttäuscht gewesen, wenn es nicht geklappt hätte… 😉

Der nächste Schritt war dann etwas komplizierter: Ich wollte die einzelnen Tags auch wieder schließen. Natürlich in umgekehrter Reihenfolge. Und mit dem SLASH, der ein Ende-Tag anzeigt. Hier brauchte es dann etliche Versuche und verwirrte Blicke in die Doku um zu dem folgenden Ergebnis zu gelangen:

Und hier der Quelltext dazu:

REPORT zdemo_reduce_simple.

CLASS demo DEFINITION.
  PUBLIC SECTION.
  CLASS-METHODS main.
ENDCLASS.

CLASS demo IMPLEMENTATION.
  METHOD main.

  DATA(html_commands) = VALUE string_table(
                              ( `<html>` )
                              ( `<body>` )
                              ( `<p>` ) ).
  cl_demo_output=>write( html_commands ).


  DATA(text) = REDUCE string(
                INIT html = ``
                 FOR command IN html_commands NEXT html = |{ html }{ command }| )
             && 'Hallo Welt'
             && REDUCE string( INIT html = ``
                FOR n = lines( html_commands )
                THEN n - 1
                WHILE n > 0
                 NEXT html = html && COND #( LET command = html_commands[ n ]
                                              IN WHEN command IS NOT INITIAL
                                                 THEN command(1) && '/' && command+1 ) ).

   cl_demo_output=>write( text ).
   cl_demo_output=>display( ).
 ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
 demo=>main( ).

Ich lasse es einfach so unkommentiert stehen. Wenn man weiß, was der Ausdruck macht, ist es einigermaßen klar.

Hier der Beitrag von Horst Keller zum Thema ABAP-740 Features: https://blogs.sap.com/2014/09/30/abap-news-for-740-sp08-iteration-expressions/

Table Expressions

Sehr gewöhnungsbedürftig für mich ist der Zusatz um die einzelne Tabellenzeile (die Tabelle hat ja keine Struktur) anzusprechen:

COND #( LET command = html_commands[ n ]
         IN WHEN command IS NOT INITIAL
            THEN command(1) && '/' && command+1 )

Mein erster Ansatz war Folgendes (was aber nicht funktionierte):

html_commands[ n ]-TABLE_LINE

Also bin ich zum COND-Ausdruck gekommen. Hier finde ich verwirrend, dass anscheinend zwingend eine WHEN-Klausel angegeben werden muss. Vielleicht gibt es auch eine einfachere Alternative?! Bestimmt. Lasst es mich gerne wissen.

Link zur Horst Kellers Blog: https://blogs.sap.com/2013/05/29/abap-news-for-release-740-table-expressions/

 

Ein komisches Gefühl, auf ein mal wieder Anfänger zu sein…

Der guten alten Zeiten Willen noch mal das Coding mit ABAPvor740. Viel Länger ist es auch nicht. Und ob die Programmierung mit ABAP740 eleganter oder besser ist, wage ich zu bezweifeln.

DATA text TYPE string.
LOOP AT html_commands INTO DATA(command).
  text = text && command.
ENDLOOP.
text = text && 'Hallo Welt'.

DATA line TYPE i.
line = lines( html_commands ).
DO lines( html_commands ) TIMES.
  DATA(cmd) = html_commands[ line ].
  text = text && cmd(1) && '/' && cmd+1.
  SUBTRACT 1 FROM line.
ENDDO.
Enno Wulff
Letzte Artikel von Enno Wulff (Alle anzeigen)

COMMENTS

  • <cite class="fn">laurin</cite>

    Hi Enno,
    ich glaube, dass du einen kleinen Denkfehler machst. Diese neuen Features sollen nicht das “alte” ABAP ersetzen – sie sollen lediglich da eingesetzt werden, wo sie auch wirklich Sinn machen. Ich habe auf StackOverflow schon einige Fragen gesehen, in denen krampfhaft versucht wurde, ausschließlich den neuen Schreibstil unterzubringen. Fürchterlich!

    CONV zum Beispiel ist wunderbar um die strengen Typchecks bei Funktionsbausteinen zu umgehen. CORRESPONDING erweitert MOVE-CORRESPONDING endlich um eine Möglichkeit, Felder zu mappen, welche nicht gleich benannt sind. Es gibt schon einige Vorteile.

    COND ist an der Stelle, an welcher du ihn benutzt, auch etwas unpassend. Du kannst doch einfach LET command ... IN NEXT html = html ... verwenden – völlig ohne COND.

    BTW: auch das hier ist Pflichtlektüre 😉

    • <cite class="fn">Enno Wulff</cite>

      Du hast natürlich Recht, es geht nicht darum auf Teufel komm raus das alte durch Neues zu ersetzen. Aber es wird immer mehr Leute geben, die bei neuen Programmierungen Probleme mit neuen Sprachfeatures zu lösen. Und ohne, dass man wirklich verstanden hat, wie sie funktionieren, kommt halt sowas wie bei mir raus.
      Danke für den Blogbeitrag! Testing wird immer wichtiger. Gerade bei solchen kompakten Sprachausdrücken.

  • <cite class="fn">abapkadabra</cite>

    Gerade bei der schon fachlich hohen Komplexität von SAP-Systemen finde ich es sehr wichtig, dass das Coding gut lesbar und somit langfristig gut wartbar bleibt. Idealerweise soll nicht nur der Hardcore-Programmierer sondern auch der SAP-Berater mit grundsätzlichen ABAP-Kenntnissen im Debugger noch verstehen können, was gerade passiert.

    Noch hatte ich keine Situationen in der Entwicklung, in welchen die neuen Befehle und Schreibweisen wirklich erforderlich gewesen wären, aber das mag in Spezialgebieten anders sein. Andererseits kann ich auch meistens die Neuerungen gar nicht verwenden, da wir unsere Entwicklung in Kundensysteme unterschiedlichster Releasestände ausliefern.

    Ganz klar muss man sich als SAP-Entwickler aber mit den neuen Möglichkeiten auseinandersetzen und diese zumindest verstehen – mögen muss man sie deswegen noch lange nicht 😉

  • <cite class="fn">ralfwenzel</cite>

    Wenn man ABAP so schreiben will, dass ein Berater es versteht, schränkt man sich sehr stark ein, weil die zumeist schon mit OO-Konzepten überfordert sind.

    Viel wichtiger ist, dass man so komplexes Coding in eine eigene Methode schreibt und diese durch sprechenden Namen, eine ebensolche Beschreibung und ggf. per Dokumentation erklärt.

    Den wichtigsten Vorteil aber hat hier keiner genannt: Ähnlich einer funktionalen Methode können solche Operationen an Operandenpositionen eingesetzt werden, was unglaublich viele Hilfsvariablen erspart.

    Ich kenne Methoden, die erstmal 20 Zeilen Deklarationsblock haben, ehe das Coding überhaupt anfängt…..

    Ralf

    • <cite class="fn">Enno Wulff</cite>

      Ein Programmierer will in der Regel nicht so programmieren, dass es ein Berater versteht. Ein Programmierer programmiert so, wie er kann und so, dass es läuft.

      Gerade mit diesen verkettet-geschachtelten Aufrufen ist es m. E. nicht mehr nötig, eine neue Methode zu machen (Ja: Test-Units, Ja, Clean-Code, aber finde mal einen passenden Namen für eine Methode, die alle mit RÜCK oder TRÜK zurück gemeldeten Vorgänge aus den Aufträgen ermittelt, die kein Löschkennzeichen haben…)
      Aber das ist ein anderes Thema…

      Hier geht es ja darum, aufzuzeigen, was wie möglich ist.

Comments are closed.