GLBasic forum

Other languages => GLBasic - de => Topic started by: Markus on 2012-Apr-24

Title: (Erledigt) Sowas wie ByRef als Funktionsrückgabe
Post by: Markus on 2012-Apr-24
Sowas brauche ich damit nicht jedes mal eine neue Struktur erzeugt wird.
Vieleicht geht sowas auch schon und ich weiß es noch nicht.

Code (glbasic) Select

FUNCTION >>>ByRef<<< FindPlayer AS TPlayer:Nr

FOREACH P IN Players[]
IF P.Nr=Nr THEN RETURN P
NEXT

ENDFUNCTION


Tatsache ist das ich hier den echten Inhalt vom Array bekomme
Code (glbasic) Select

LOCAL P AS TPlayer
FOREACH P IN Players[]
P.Draw()
IF P.Nr=1 THEN P.Update() //das geht
NEXT


Plan B geht nicht  (das Byref ist bei PR wohl schon automatisch bei)
Code (glbasic) Select

FUNCTION FindPlayer:Nr, PR AS TPlayer

FOREACH PR IN Players[]
IF PR.Nr=Nr 
BREAK
ENDIF
NEXT

ENDFUNCTION


Sowas macht eine Kopie
Code (glbasic) Select

FUNCTION FindPlayer:Nr, PR AS TPlayer

FOREACH P IN Players[]
IF P.Nr=Nr 
PR=P
BREAK
ENDIF
NEXT

ENDFUNCTION



Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: backslider on 2012-Apr-24
Geht nicht
Code (glbasic) Select

FUNCTION FindPlayer: Nr, BYREF p AS TPlayer
    FOREACH P IN Players[]
        IF P.Nr=Nr THEN p = P
    NEXT
ENDFUNCTION

?
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Quentin on 2012-Apr-24
Meinst du sowas, dass die Funktion den Typen zurückliefert? Doch das geht schon. musst nur die Funktion entsprechend deklarieren:

Code (glbasic) Select

TYPE TPlayer
text$
ENDTYPE

GLOBAL players[] AS TPlayer
DIM players[3]

players[0].text$ = "Erster"
players[1].text$ = "Zweiter"
players[2].text$ = "Dritter"

LOCAL test AS TPlayer

test = get_player("Zweiter")
STDOUT test.text$
KEYWAIT


FUNCTION get_player AS TPlayer: text$
FOREACH p IN players[]
IF p.text$ = text$
RETURN p
ENDIF
NEXT
ENDFUNCTION
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: backslider on 2012-Apr-24
Dein Beispiel hat er doch als erste Funktion genannt, nur das er da irgendwie nen BYREF haben will.  :P
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Kitty Hello on 2012-Apr-24
Byref geht nicht. Aber Du kannst ja byref als argument übergeben.
Wenn Du BYREF returnen willst - worauf soll der Rückgabewert zeigen!?
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: backslider on 2012-Apr-24
QuoteByref geht nicht. Aber Du kannst ja byref als argument übergeben.
Damit meinst Du doch meine Idee, oder nicht?
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Kitty Hello on 2012-Apr-24
ja. genau.
...warum red ich überhaupt...
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: kanonet on 2012-Apr-24
Quote from: Kitty Hello on 2012-Apr-24...warum red ich überhaupt...
:nana:
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Markus on 2012-Apr-24
byref bei einem Parameter mit Struktur gibt mir ein Syntax Error.
ich gehe aber davon aus das der Parameter eh schon als Pointer übergeben wird weil das nur ein paar Bytes sind und so üblich ist.
Oben mein Beispiel ging aber nicht wie ich das erwartet hatte.

Bei A=B habt ihr mir erklärt das dort die Struktur B nach A kopiert wird,ich will aber B haben original :-)

@Quentin
ich möchte keine kopie als Rückgabe

@Kitty Hello
ich will quasi Pointer tauschen bzw. weiter geben und Variable A durch B ersetzen vom gleichem Typ.
Das was im Array ist möchte ich mit einer Funktion raus suchen ohne eine kopie zu erstellen, dann mit .MachIrgendwas() ändern.
Ansonsten muß ich bei einer Kopie das ja auch wieder zurück kopieren in mein Array.
Und wenn man mit kopien arbeitet dann haben andere Funktionen wieder nicht das aktuelle.
Kopien kosten zu dem unnötig Zeit.

Was zum experimentieren:
Code (glbasic) Select


TYPE TPlayer
Nr
Name$
x
y
Money

FUNCTION Draw:
SETPIXEL self.x,self.y,RGB(255,255,255)
ENDFUNCTION

FUNCTION Position: x,y
self.x=x
self.y=y
ENDFUNCTION

FUNCTION Update:

//<- 203 Cursors
//-> 205
//^  200
//V  208
//o   28 RETURN

LOCAL Name$=self.Name$ //for debug

IF KEY(205)
IF self.x<800 THEN self.x=self.x+1
ENDIF

ENDFUNCTION

ENDTYPE

GLOBAL Players[] AS TPlayer

ALLOWESCAPE TRUE

MainLoop()
END

FUNCTION MainLoop:

LOCAL A AS TPlayer
A.Nr=1
A.Name$="Markus"
A.Position(100,300)

LOCAL B AS TPlayer
B.Nr=2
B.Name$="Computer"
B.Position(800-100,300)

DIMPUSH Players[],A
DIMPUSH Players[],B

REPEAT

LOCAL P AS TPlayer
FOREACH P IN Players[]
P.Draw()
//IF P.Nr=1 THEN P.Update() //das geht
NEXT
FindPlayer(1,P)
P.Update() //das nicht weil das wohl eine Kopie der Struktur ist
//ReplacePlayer(1,P) //Workaround

SHOWSCREEN

UNTIL FALSE

ENDFUNCTION

// P als BYREF gibt Syntax Error
FUNCTION FindPlayer: Nr, P AS TPlayer
    FOREACH P IN Players[]
        IF P.Nr=Nr
        BREAK
        ENDIF
    NEXT
ENDFUNCTION

Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Kitty Hello on 2012-Apr-24
Keine Chance. Das Array ist ein echtes Array, keine Liste mit Pointern. Was in's Array soll, muss reinkopiert werden.
Bevor jetzt das Geheule über Geschwindigkeit losgeht, bitte erst ein konkretes Projekt machen und prüfen ob's wirklich "langsam" ist. Die GLB Arrays sind nämlich oft viel schneller als so linked-list Kram.
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Markus on 2012-Apr-24
@Kitty Hello
Ich will doch direkt im Array arbeiten und hier mit dem Beispiel geht es ja auch.
Dieses P ist doch ein Block der im Speicher (Array) steht, den möchte ich auch bearbeiten.
Ich bekomme aber das P nicht aus einer Funktion zurück ohne das es als Kopie angelegt wird.
Wie ich das verstehe ist das P in dem Beispiel unten ein Pointer auf einen Speicherbereich wo die Struktur in echt ist oder ?
Wenn ich bei Update() mit self.xy=x einen Wert zuweise ist das wieder im Array darum gehe ich davon aus das P ein Ausschnitt vom Array ist.
LOCAL P AS TPlayer
FOREACH P IN Players[]
   P.Draw()
   IF P.Nr=1 THEN P.Update() //das geht
NEXT
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Schranz0r on 2012-Apr-24
INLINE  :enc:
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Quentin on 2012-Apr-24
Quote from: Markus on 2012-Apr-24
@Quentin
ich möchte keine kopie als Rückgabe

ja sorry, hatte ich übersehen, hattest du ja schon probiert.

Was dein "P" hier angeht:
lt. Hilfe
"Man muss "ref" nicht als LOCAL definieren. Das passiert automatisch. Jedoch ist "ref" nach dem zugehörigem "NEXT" nicht mehr gültig."

Das beantwortet wohl, warum du nach der FOREACH-Schleife nicht mehr auf dein P zugreifen kannst. Und wenn du unbedingt direkt mit dem Array arbeiten willst, ohne irgendwelche Kopieraktionen, wieso arbeitest du dann nicht mit einem Index.

Anstatt FOREACH einfache FOR-Schleife:
Code (glbasic) Select

FOR i = 0 TO LEN(Players[]) - 1
    Players[i].draw()
NEXT

// damit kannst du dann auch außerhalb der Schleife gezielt über den Index zugreifen
// und deine gezeigte FindPlayer-Funktion wäre überflüssig

Players[5].update()


Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Schranz0r on 2012-Apr-24
Quote from: Quentin on 2012-Apr-24
Und wenn du unbedingt direkt mit dem Array arbeiten willst, ohne irgendwelche Kopieraktionen, wieso arbeitest du dann nicht mit einem Index.

Richtig, mach es nach dem GLB-Way, oder nutze einfach INLINE...
Ist ja das coole an GLB das du mixen kannst :)
Title: Re: Sowas wie ByRef als Funktionsrückgabe
Post by: Markus on 2012-Apr-24
@Quentin
ich wollte auch nicht nach der Schleife das P noch benutzen.
Das sieht jetzt nur in dem Beispiel so aus weil ich Experimente mache.
In der Funktion das P nach Außen geben .
Ich habe aber Explizite Deklaration an,warum nacht dann das ForEach
selber was ? Aber ich sehe grad dank dir wie das ForEach gemacht ist.
Da wird tatsächlich am Anfang und Ende alles kopiert, das muß ich ja dann
wohl auch so machen :-)

@Schranz0r
ihr habt mich grad auf die Idee gebracht das Array als Byref zu übergeben :-)

@Kitty Hello
hab dank Quentin ein Beispiel gefunden was das ForEach eigentlich macht.

Title: Re: (Erledigt) Sowas wie ByRef als Funktionsrückgabe
Post by: Kitty Hello on 2012-Apr-24
Also.

Einen Zeiger auf ein Element bekommst Du mit:
ALIAS zeiger AS feld[index]
zeiger.xx

Oder Du übergibst an eine Funktion. Types werden _immer_ BYREF übergeben. Arrays auch.
Title: Re: (Erledigt) Sowas wie ByRef als Funktionsrückgabe
Post by: Markus on 2012-Apr-24
@Kitty Hello  :enc:
danke, spiele ich mal mit rum  ;)

Wenn wie in der Hilfe dieses Each
Quote
FOREACH ref IN feld[]
...
NEXT

echt wie sowas ist
Quote
FOR i = 0 to BOUNDS(feld[],0)-1
   ref = feld
   ...
   feld = ref
NEXT
dann wäre nach Adam Riese ref schon eine Kopie.

Jede Sprache macht es anders , das Beispiel in der Hilfe war nützlich.

(mit "Objekten" die immer Byref übergeben werden kenne ich von MS,fände es aber logischer wenn es davor stehen würde weil die anderen wohl byval sind oder.)

:x
Title: Re: (Erledigt) Sowas wie ByRef als Funktionsrückgabe
Post by: Markus on 2012-Apr-25
@Alle
Danke

Und falls das jemand interessiert  :booze:
Code (glbasic) Select


TYPE TPlayer
Nr
Name$
x
y
Money

FUNCTION Draw:
SETPIXEL self.x,self.y,RGB(255,255,255)
ENDFUNCTION

FUNCTION Position: x,y
self.x=x
self.y=y
ENDFUNCTION

FUNCTION Update:

//<- 203 Cursors
//-> 205
//^  200
//V  208
//o   28 RETURN

LOCAL Name$=self.Name$ //for debug

IF KEY(205) // Taste nach rechts
IF self.x<800 THEN self.x=self.x+1
ENDIF

ENDFUNCTION

ENDTYPE

GLOBAL Players[] AS TPlayer

ALLOWESCAPE TRUE

MainLoop()
END

FUNCTION MainLoop:

LOCAL A AS TPlayer
A.Nr=1
A.Name$="Markus"
A.Position(100,300)

LOCAL B AS TPlayer
B.Nr=2
B.Name$="Computer"
B.Position(800-100,300)

DIMPUSH Players[],A
DIMPUSH Players[],B

REPEAT

FOREACH P IN Players[]
P.Draw()
NEXT

LOCAL i%
i=FindPlayer(1,Players[])
ALIAS P AS Players[i] //so vereinfacht die Schreibweise enorm und man arbeitet mit dem Original
P.Update() // Fragt nur die Rechts Taste ab

SHOWSCREEN

UNTIL FALSE

ENDFUNCTION

FUNCTION FindPlayer: Nr,List[] AS TPlayer //damit innen keine Globalen Variablen benutzt werden die Liste als Byref
LOCAL i%
FOR i = 0 TO BOUNDS(List[],0)-1
IF List[i].Nr=Nr
RETURN i
BREAK
ENDIF
NEXT
RETURN 0
ENDFUNCTION
Title: Re: (Erledigt) Sowas wie ByRef als Funktionsrückgabe
Post by: Kitty Hello on 2012-Apr-25
FOREACH j IN ar[] ist sowas wie:
FOR I%= 0 to LEN(ar[])-1
   ALIAS j AS as
   j...
NEXT
Title: Re: (Erledigt) Sowas wie ByRef als Funktionsrückgabe
Post by: Markus on 2012-Apr-25
@Kitty Hello
viel anders weiter geben konnte ich die Variable mit dem Alias nicht
aber das Alias hilft sehr damit es übersichtlicher bleibt.
Habe jetzt den dreh raus.