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
Quote
Byref 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
...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
@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
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.