Seite 1 von 2

Integerübergabe ByRef

Verfasst: 29.07.2017 23:01
von Kurzer
Hallo zusammen,

nachdem ich seit ein paar Wochen in PHP eine Webanwendung programmiere, bin ich durch dessen Möglichkeiten etwas verwöhnt wie mir scheint. ;-)

"Nativ" werden in PureBasic ja nur Arrays, Listen und Maps als Referenz an Prozeduren übergeben.

In PHP kann jede Variable sehr einfach, nach Bedarf "byRef" übergeben (oder besser aus Sicht der Funktion "übernommen") werden, wenn man bei der Funktionsimplementation ein & vor die Variable schreibt.

Code: Alles auswählen

function Test($param1, &$param2) {
    $param2 = 22;
}

$a = 10;
echo test(1, $a);
echo a$;   // Wird 22 ausgeben
Param 2 wird dadurch automatisch "byRef" behandelt, also als Referenz auf die originale Variable außerhalb der Prozedur / Funktion.

Nun habe ich mir das in PureBasic wie folgt nachgebaut und frage mich, ob das die einzige Möglichkeit ist dies zu erreichen.

Code: Alles auswählen

Procedure test (*byref.integer)
			*byref\i = 22
EndProcedure
	
a.i = 10
test (@a)

Debug a ; gibt 22 aus.

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 07:36
von GPI
das einzige, was mir noch einfällt, wäre Macros zur Verschleierung zu Nutzen.

Code: Alles auswählen

Procedure __test (*byref.integer)
  *byref\i = 22
EndProcedure
Macro test(variable)
  __test(@variable)
EndMacro


a.i = 10
test (a)

Debug a ; gibt 22 aus.
Macht aber den Code etwas schlechter lesbar.

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 10:32
von mk-soft
Schwieriger wird es bei Strings als ByRef zu übergeben.
Es kann nicht eine einfache String-Variable übergeben werden weil dann der Pointer zum String übergeben wird und nicht der Pointer zur Variable der den Pointer zum String enthält.

Code: Alles auswählen

;-TOP
Procedure foo(*inout.String, *value.integer)
  *value\i + 100
  *inout\s + " " + Str(*value\i)
EndProcedure

Global t1.String
Global v1 = 100
t1\s = "hello world"
Debug "Address of String: " + PeekI(t1)
Debug t1\s
foo(t1, @v1)
Debug "Address of String: " + PeekI(t1)
Debug t1\s

; Invalid Pointer to String

t2.s = "hello world"
Debug "Address of String: " + PeekI(@t2)
foo(@t2, @v1)
Debug "Address of String: " + PeekI(@t2)
Debug t2

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 11:26
von uweb
Das ist ja mal eine nette Denksportaufgabe für den Sonntagmorgen.

*byref.integer kannte ich noch gar nicht.
Deswegen habe ich eine noch schlechter lesbare Lösung gebastelt.
Die ist zwar viel aufwendiger, aber wenn man schon von hinten durch die Brust ins Auge fasst sind Strings auch kein Problem mehr.
Ob das nun sinnvoll ist steht auf einem anderen Blatt.
:)

Code: Alles auswählen

Structure Param
  int.i
  strg .s
EndStructure

; Die Grundidee ist es von Anfang an Felder statt Variablen zu nutzen:
Dim parameters.Param(1)
Macro a_i : parameters(1)\int : EndMacro
Macro hi_s : parameters(1)\strg : EndMacro

Macro params : Array parameters.Param(1) : EndMacro ; nur verkürzte Schreibweise
Declare Test(params)

Macro TestParam1 : parameters(0)\int : EndMacro
Macro TestParam2 : parameters(1)\int : EndMacro
Macro TestParam3 : parameters(0)\strg : EndMacro
Macro TestParam4 : parameters(1)\strg : EndMacro

Macro _Test(_TestParam1, _TestParam2, _TestParam3, _TestParam4)
  ; da auch Konstanten übergeben werden können:
  parameters(0)\int=_TestParam1
  parameters(1)\int=_TestParam2
  parameters(0)\strg=_TestParam3
  parameters(1)\strg=_TestParam4
  Test(parameters())
EndMacro


Procedure Test (params)
  TestParam2 = 22;
  a_i = a_i + TestParam1 ; Das Macro für a_i ist global
  TestParam4 = TestParam4 + TestParam3
EndProcedure


a_i = 10
hi_s = "Hello World!"
_Test(1, a_i," Nice to meet you.",hi_s)
Debug a_i
Debug hi_s

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 12:31
von Nino
Kurzer hat geschrieben:"Nativ" werden in PureBasic ja nur Arrays, Listen und Maps als Referenz an Prozeduren übergeben.
uweb hat geschrieben:

Code: Alles auswählen

; Die Grundidee ist es von Anfang an Felder statt Variablen zu nutzen:
Also Arrays (bzw. Listen oder Maps) nur deshalb benutzen, weil sie als Prozedurparameter als Referenz übergeben werden, auch wenn man sie sonst gar nicht braucht?
uweb hat geschrieben:Ob das nun sinnvoll ist steht auf einem anderen Blatt.
:)
Jo. :-) Da würde ich doch lieber Zeiger nehmen, so wie hier im 1. Posting gezeigt.

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 13:43
von GPI
Nino hat geschrieben:Also Arrays (bzw. Listen oder Maps) nur deshalb benutzen, weil sie als Prozedurparameter als Referenz übergeben werden, auch wenn man sie sonst gar nicht braucht?
Structuren gehen auch wunderbar

Code: Alles auswählen

Structure para
  opt1.i
  opt2.s
  opt3.d
EndStructure

v.para
v\opt1=10
v\opt2="test"
v\opt3=4.5

Procedure test(*para.para)
  Debug "test:"+*para\opt1+" "+*para\opt2+" "+*para\opt3
  *para\opt1=33
  *para\opt2="neo"
  *para\opt3=9.9
EndProcedure

Debug "outside:"+v\opt1+" "+v\opt2+" "+v\opt3

test(v)

Debug "outside:"+v\opt1+" "+v\opt2+" "+v\opt3

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 13:51
von Nino
GPI hat geschrieben:
Nino hat geschrieben:Also Arrays (bzw. Listen oder Maps) nur deshalb benutzen, weil sie als Prozedurparameter als Referenz übergeben werden, auch wenn man sie sonst gar nicht braucht?
Structuren gehen auch wunderbar
Ja klar, die hat Kurzer ja von Anfang an verwendet. :-)

Code: Alles auswählen

.integer
bezeichnet nichts anderes als eine in PB bereis eingebaute Struktur. Natürlich bietet es sich je nach Situation an, ggf. best. "by Reference-Variablen" in einer selbstdefinierten Struktur zusammenzufassen.

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 14:08
von Kurzer
Ich versuche die PHP Syntax gerade mit Macros zu imitieren, es scheitert aber daran, dass das Verkettungs-Zeichen # in Macros nicht mit einem * zusammen funktioniert.

http://www.purebasic.fr/english/viewtop ... 13&t=68850

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 18:33
von uweb

Code: Alles auswählen

a_i = 10
hi_s = "Hello World!"
_Test(1, a_i," Nice to meet you.",hi_s)
Nach reichlichem Herumprobieren bin ich auf noch keine bessere Lösung für ByRef und Konstanten gekommen.
Mir ist schon klar, dass die Array-Lösung umständlich ist und nur fuktioniert weil sie die Konstantenwerte in ein Feld kopiert - also die Konstanten nicht wirklich ByRef behandelt.
Aber was wäre denn der bessere Weg ohne die Syntax zu vergewaltigen bzw um sie ggf. über Makros wiederherzustellen?

PS
Ich habe gerade beim Aufräumen noch etwas witziges wiedergefunden:

Code: Alles auswählen

Procedure _test (*byref1.integer, *byref2.integer)
  *byref2\i = 22
EndProcedure

Macro test(variable1, variable2)
  _test(@variable1, @variable2)
EndMacro

a.i = 10
test (1, a)
Debug a

Re: Integerübergabe ByRef

Verfasst: 30.07.2017 20:24
von Josh
Gerade zu Beginn meiner Pb-Zeiten war ich von der Parameterübergabe 'ByRef' in Pb auch nicht gerade begeistert.

Trotzdem halte ich nicht viel davon, wenn per Macro syntaktischer Zucker verstreut wird. Das macht es nur mühsamer, wenn nach ein paar Jahren ein Code angepasst werden muss oder gar der Code von anderen gelesen werden muss.