PDA

View Full Version : Rückgabe von 2 Werten aus einer Prozedur



BUG
18-10-04, 10:58
Hallo,

ich habe da eine Prozedur die zwei Parameter mitbekommt. Diese beiden sollen innerhalb der Prozedur verarbeitet werden und dann zurückgegeben werden. Die beiden Parameter sind global gültige Variablen. Ich will also eine Wertzuweisung an die eigentlichen Variablen nicht in der Funktion vornehmen, in der die Verarbeitung vorgenommen wird (Stichwort Kapselung). Das habe ich mir sagen lassen würde über Input/Output-Variablen möglich sein.

Nun habe ich mit der Umsetzung dieser Idee so meine Schwierigkeiten.

Erstens kann man aus einer Prozedur doch nur einen Wert zurückliefern, oder (Return XXX gibt den Wert raus und die Prozedur wird verlassen)?

Zweitens, selbst wenn ich zwei Werte zurückliefern könnte wie wäre dann eine Zuweisung in einem Funktionsaufruf zu gestalten?

Ein bisschen plastischer:



P Hauptfunktion B
D Hauptfunktion PI
/Free

// Wertzuweisungen auf globale Variablen sollen nur hier in dieser Prozedur stattfinden
globVar1 = Wert1 aus Unterfunktion(globVar1:globVar2);
globVar2 = Wert2 aus Unterfunktion(globVar1:globVar2);

/End-Free
P Hauptfunktion E






P Unterfunktion B
D Unterfunktion PI
D Parm1 Like(globVar1)
D Parm2 Like(globVar2)
**----
D intVar1 S
D intVar2 S
/Free

intVar1 = Parm1;
intVar2 = Parm2;

//Verarbeitung der Variablen...

Return inVar1; // ???
Return inVar2; // ???

/End-Free

P Unterfunktion E



So ungefähr soll der Ablauf des Ganzen vonstatten gehen, aber ich hab nicht so wirklich eine gute Idee, wie das zu machen wäre. Ich könnte mir ein "schönes" Konstrukt mir Pointern auf die Werte vorstellen, aber das wäre ja letztendlich auch nur innerhalb der Unterprozedur zu machen und so der Kapselungsgedanke verletzt. Oder ich könnte je eine Prozedur für je einen Wert erstellen. Aber gäbe es nicht auch eine Möglichkeit das Ganze zu lösen wie oben angedeutet? Kann mit jemand sagen, wie ich eine I/O Variable nutzen kann?

Herlichen Dank für Anregungen, Björn

Fuerchau
18-10-04, 11:09
Ein Return von mehr als 1 Wert ist nun mal nicht zulässig.

Es ist deshalb durchaus erlaubt (bei entsprechender) Dokumentation, die Übergebenen Variablen zu verändern ! Der Return gibt dann z.B. nur zurück, ob die Funktion Korrekt ist.

Viele C-Funktionen arbeiten genau so. Und es ist trotzdem als Kapselung zu verstehen.

jo400
18-10-04, 11:27
Hallo Björn,

ich hätte noch zwei Vorschläge bzw. Anregungen.

1. Du könntest ja noch einen dritten Parameter an die Unterfunktion mitgeben, mit dem entschieden wird, welcher der beiden Parameter zurückgegeben werden soll. (Voraussetzung ist natürlich, dass die beiden Rückgabewerte gleich bzw. ähnlich definiert sind.)

2. Kannst du nicht eine Datenstruktur als Rückgabeparameter verwenden, die beide Werte beinhaltet?

Jo

BUG
18-10-04, 11:54
2. Kannst du nicht eine Datenstruktur als Rückgabeparameter verwenden, die beide Werte beinhaltet?

Jo
Das gefällt mir, ich werd's mal probieren!

Aber vielleicht nochmal ganz kurz zu meiner anderen Frage:
Könnt ihr mir vielleicht sagen, wie ich mir eine I/O-Variable vorzustellen habe? Ich mag mich hier blamieren weil ich eine Riesenlücke in meinem Basiswissen rausposaune, aber ich finde partout nirgends eine konkrete Definition finde oder eine Anleitung zur Implementierung... Was wie genau geh ich damit um?

Ich meine, der Name sagt natürlich schon einiges. Geht's dabei dann einfach nur darum, einen Parameter zu übergeben, zu verarbeiten und zurückzugeben?

Fuerchau
18-10-04, 12:07
Also Datenstrukturen als Returnwert geht zwar schon (ist dann vom Typ Zeichen) aber nicht unbedingt sinnvoll, da die Schnittstelle dann nicht eindeutig ist.

IO/O-Parameter sind Parameter die "by reference", also mit Adresse übergeben werden und die Definitionen CONST und VALUE nicht enthalten. Also alle Parameter, die keine Extradefinitionen enthalten.
Ein Problem ist noch die Definition STRING, da diese CONST mit einschließt.

BenderD
18-10-04, 12:17
Hallo,

was dahinter steckt ist CALL by reference und call bei value.
CALL BY REFERENCE: es wird die Adresse des Parameters übergeben
- Veränderungen werden im aufrufenden Programm direkt sichtbar
- auf der AS400 grundsätzlich default
- auf der AS400 keinerlei Typprüfung
- Risiko: falsche Definition im aufgerufenen Programm erzeugt Probleme bis zum Absturz im aufrufenden Programm
mein Resumee: Finger weg, wenn möglich immer (in Worten: immer) VALUE nehmen. (Sclüsselwort VALUE bei gebundenen Calls, CONST bei dynamischen Calls wirkt ähnlich)

CALL BY VALUE: Übergabe eines Wertes
- Veränderungen des Parameters im aufgerufenen Programm werden nicht sichtbar im aufrufenden
- genaue Kontrolle des Rückgabeflusses
- Rückgabe über return, bei mehreren Werten Verbundtypen nehmen (DS im RPG)
- (fast) vollständige Typprüfung auch in ILE RPG (über Prototyp) möglich.

Weitergabe von Referenzen (CALL BY REFERENCE, oder Pointer) nur in klar definierten Ausnahmefällen, wofür ein positiver Grund vorliegen muss.

mfg

Dieter Bender

@Baldur: wo der C Vergleich hinkt: C weiss üblicherweise auf was ein Pointer zeigt (Ausnahme Pointer auf Pointer), RPG weiss nie auf was ein Pointer zeigt!!!


Das gefällt mir, ich werd's mal probieren!

Aber vielleicht nochmal ganz kurz zu meiner anderen Frage:
Könnt ihr mir vielleicht sagen, wie ich mir eine I/O-Variable vorzustellen habe? Ich mag mich hier blamieren weil ich eine Riesenlücke in meinem Basiswissen rausposaune, aber ich finde partout nirgends eine konkrete Definition finde oder eine Anleitung zur Implementierung... Was wie genau geh ich damit um?

Ich meine, der Name sagt natürlich schon einiges. Geht's dabei dann einfach nur darum, einen Parameter zu übergeben, zu verarbeiten und zurückzugeben?

BUG
18-10-04, 12:50
Also, wenn ich euch beide richtig verstehe, werden laut Fuerchau I/O-Parameter generell per Referenz uebergeben? Dann würde ich also eine Adresse übergeben, mir daher den Wert besorgen, eine Verarbeitung vornehmen und dann das Ergebnis (direkt) auf die Speicheradresse schreiben, so gesehen also keinen Rückgabewert im eigentlichen Sinne (Return) haben?

Und nach Dieter geht beides, sowohl per Adresse als auch per Wert, mit Tendenz zu call by value?
Außerdem gehst du bem Thema Sichtbarkeit auch wirklich von externen Programmen aus, oder?


@Fuerchau, wie ist das gemeint mit der Eindeutigkeit? Wenn ich einen numerischen Wert als teil der DS hätte, würde ich trotzdem einen String zurückbekommen -> weitere Verarbeitung erst nach erneuter Umwandlung in ursprünglichen Datentyp? Ich bin da vielleicht etwas nachlässig, aber ich finde die Vorstellung nicht so schlimm! Ich mein, so BI-Functions wie %Char gibt's ja auch nicht ohne Grund, oder?

B.Hauser
18-10-04, 13:05
Also Datenstrukturen als Returnwert geht zwar schon (ist dann vom Typ Zeichen) aber nicht unbedingt sinnvoll, da die Schnittstelle dann nicht eindeutig ist.


Wenn eine Datenstruktur als Rückgabe-Wert definiert ist, kann sie auch als Datenstruktur empfangen werden.
In diesem Fall eine Dummy Datenstruktur an und versteckt diese in der Copy-Strecke für den Prototyp.
Der Rückgabe-Wert kann dann mit LIKEDS definiert und verwendet werden.

Beispiel:


* Copy-Strecke Prototyp
D DSQualName DS based(DummyPtr)
D Object 10A
D Library 10A

D GetQualName PR likeDS(DSQualName)
D ParmFile 10A
D ParmLib 10A




D MyFile S 10A inz('MYFILEP')
D MyLib S 10A
D DSQualFile DS likeDS(DSQualName)
*/-----------------------------------------------------
/Free
DSQualFile = GetQualName(MyFile: MyLib);
Dsply DSQualFile.Object;
Dsply DSQualFile.Library;
*inLR = *On;
/End-Free




P GetQualName B Export
D GetQualName PI likeDS(DSQualName)
D ParmObj 10A
D ParmLib 10A

D DSName DS likeDS(DSQualName)
*-------------------------------------------------------------
/Free
DSName.Object = ParmObj;
If ParmObj <> *Blanks;
If ParmLib <> *Blanks;
DSName.Library = ParmLib;
else;
DSName.Library = '*LIBL';
Endif;
EndIf;

Return DSName;

/End-Free
P GetQualName E


Ergänzung zu Dieter:
Es gibt auch noch die sogenannte Parameter-Übergabe by Constant Reference (Schlüssel-Wort CONST). Dabei wird geprüft, ob der übergebene Parameter der im Prototyp angegebenen Felddefinition entspricht. Bei Übereinstimmung wird die Adresse des Parameters an das rufende Programm oder Prozedur übergeben. Bei Abweichung wird ein temporäres Feld mit der erwarteten Definition erstellt und mit dem Paramete-Wert gefüllt. Anschliessend wird die Adresse diese neuen Feldes an das rufende Programm übergeben.

Die Parameter-Übergabe by VALUE kann zur für den Aufruf von Prozeduren verwendet werden. Für den Aufruf von Programmen ist nur eine Parameter-Übergabe by Reference möglich, auch Constant Reference.

Birgitta

BenderD
18-10-04, 13:12
Hallo,

irgendeine Auswahl hast du nur im ILE bei der verwendung von Prototypen, sagst du da beim Parameter VALUE, dann geht er nur hin und es wird ein call by value generiert. In allen anderen Fällen hast du immer einen call by reference vor dirmit allen bereits diskutierten Konsequenzen.
Rückgabe von Parametern kann beim return erfolgen und dann kommt man in einer Zuweisung an das Ergebnis; im (free) RPG:

ergebnis = machwas(....);

wenn du da mehr als einen Wert zurück haben willst, muss dann halt eine Datenstruktur verwendet werden. An die Einzelwerte kommt man dann per Unterfeld wieder dran (da braucht man keinen %irgendwas. Unschön ist hierbei, dass eine DS für RPG letztlich ein Alfastring ist, aber rpg ist halt eine Schmuddel Programmiersprache und ich finde das noch eine der kleineren Übel.
Sichtbar sind die einzelnen Parameter und Variablen in Abhängigkeit ihrer Definition, wobei bei der Übergabe von Referenzen Seiteneffekte entstehen (die man ja gerade für Parameter Rückgabe nutzt).

mfg

Dieter Bender


Also, wenn ich euch beide richtig verstehe, werden laut Fuerchau I/O-Parameter generell per Referenz uebergeben? Dann würde ich also eine Adresse übergeben, mir daher den Wert besorgen, eine Verarbeitung vornehmen und dann das Ergebnis (direkt) auf die Speicheradresse schreiben, so gesehen also keinen Rückgabewert im eigentlichen Sinne (Return) haben?

Und nach Dieter geht beides, sowohl per Adresse als auch per Wert, mit Tendenz zu call by value?
Außerdem gehst du bem Thema Sichtbarkeit auch wirklich von externen Programmen aus, oder?


@Fuerchau, wie ist das gemeint mit der Eindeutigkeit? Wenn ich einen numerischen Wert als teil der DS hätte, würde ich trotzdem einen String zurückbekommen -> weitere Verarbeitung erst nach erneuter Umwandlung in ursprünglichen Datentyp? Ich bin da vielleicht etwas nachlässig, aber ich finde die Vorstellung nicht so schlimm! Ich mein, so BI-Functions wie %Char gibt's ja auch nicht ohne Grund, oder?

BUG
18-10-04, 13:55
Klasse, alle Klarheiten beseitigt ;) Herzlichen Dank für diese Fülle an Info!

Ihr seid ne super Truppe hier,

Gruß Björn