PB4 + LinkedLists + Proceduren

Fragen und Bugreports zur PureBasic 4.0-Beta.
Benutzeravatar
Hyper
Beiträge: 194
Registriert: 19.04.2005 19:14

PB4 + LinkedLists + Proceduren

Beitrag von Hyper »

Hallo Gefährten,

ich habe mir Beta5 von PB 4.0 angeschaut und bin ja begeistert! Viele bislang sehnlichst vermisste Dinge (readOnly beim Editor Gadget etc...)

Was mich aber besonders freut, ist das man nun LinkedLists lokal definieren und in Proceduren übergeben kann.

Hierzu habe ich 2 Fragen:
1. Kann man diese auch aus Proceduren wieder zurückgeben?
2. Kann man Listen ohne Loop kopieren?

Etwa so (schnell mal ohne Editor):

Code: Alles auswählen

NewList Liste.Typ()                             ; Deklaration

Procedure List_aufraeumen(Input_Liste.Typ())     ; Übergabe an Proc

  Protected NewList Lokale_Liste.Typ()
  
  Lokale_Liste() = Input_Liste()  ; Geht so etwas = Frage 1?

  ; Liste bearbeiten
  ; ......

  ProcedureReturn ;Lokale_Liste() als Liste zurück, aber ... Wie = Frage 2??

Endprocedure

; -----------------
; Hauptprogramm

List_aufraeumen(Liste())

Zuletzt geändert von Hyper am 12.03.2006 01:53, insgesamt 1-mal geändert.
PB 5.72
technicorn
Beiträge: 11
Registriert: 11.03.2006 22:07

Beitrag von technicorn »

Hi,

das mit dem zurückgeben kann nie gehen, da die lokale Liste beim beenden
der Procedure, wie auch alle anderen lokalen Variablen, vom Stapel entfernt werden.

Willst Du ein Liste in der Procedure verändern, einfach als Parameter übergeben,
die Proc. arbeitet dann mit der übergenen Liste und alle Änderungen sind
auch nach dem Ende noch da.

Kopieren kann nur mit einer Schleife gehen, da jedes Element der Liste
irgendwo im Speicher liegt und nicht wie bei Arrays hintereinander.

Z.z. giebt es meines Wissens in PB keinen Befehl dafür.

Gruß
technicorn
Benutzeravatar
Hyper
Beiträge: 194
Registriert: 19.04.2005 19:14

Beitrag von Hyper »

@technicorn: Danke Dir für die Bestätigung!

@all:

zum Thema Listen an Procedures übergeben habe ich weiter getestet:

1. Linked Lists als optionale Funktionsparameter nicht möglich
Zu PB4 wurden für Proceduren a) optionale Parameter eingeführt und b) die Möglichkeit, LinkedLists als Parameter zu übergeben. Offenbar aber mit XOR, d.h. nicht beides gleichzeitig.

2. Uneinheitliche Behandlung von übergebenen LinkedLists und sonstigen Parametern
Übergibt man in einem Procedure-Aufruf eine Variable, dann ist dies unidirektional, sollte die Variable in der Procedure geändert werden, wird sie nicht im aufrufenden Hauptprogramm geändert. Bei Listen verhält es sich hier anders. Dort wird direkt in der übergebenen Liste geändert.

3. Listen können nicht ProcedurereReturn sein
Beispiel: Man möchte das Erzeugen einer Liste in einer Proc. kapseln
(Generell wäre es auch schön, wenn der ProcedurereReturn zumindest eine Struktur sein könnte, da bräuchte man nicht zu "pointern")

Insbesondere Punkt 1 ist meines Erachtens nicht gut, da nicht konsequent. Wie seht Ihr das und die anderen Punkte?
PB 5.72
technicorn
Beiträge: 11
Registriert: 11.03.2006 22:07

Beitrag von technicorn »

Zu 1.
Das würde meines Erachtens auch wenig Sinn machen, da Du in der Procedure keine Möglichkeit hättest, zu prüfen ob die Liste da ist oder nicht.
Und was willst Du optional für die List übergeben?

Zu 2.
Das hängt mit dem Programmaufbau zusammen ->
Parameter ist eine einfache Variable -> Du arbeitest in der Proc. mit einer
Kopie der Daten.

Parameter ist ein Array/Liste -> Nur ein Zeiger auf das Array/ die List
wird übergeben, die Proc. arbeitet direkt mit den Daten,
ist das Gleiche als wenn Du einen Zeiger auf eine Variable übergibts!

Zu 3.
Programmtechnisch wegen der Stapelsache nicht möglich.
Alles was in der Procedur mit Protected erzeugt wird ist nur solange
auf dem Stapel, bis die Procedure endet.
Was mit Static erzeugt wird, bleibt zwar zwichen den Aufrufen erhalten, ist aber nur innerhalb der Procedur sichtbar.
Eine dynamische Erzeugung von Arrays/Listen ist in PB (noch) nicht vorgesehen.

Es ist ja auch noch nicht möglich, Listen zu erstellen die Listen enthalten, wäre aber extrem sinnvoll, weil damit auf einfache Weise eine Baumstruktur erzeugt werden könnte.
Lösche ich dann ein Listenelement, das eine andere Liste enthält, würde die (Sub)List dann automatisch gelöscht.

Bei Listen, die Strings enhalten ist es ja auch so, in der Liste selbst ist
nur ein Zeiger auf den String, der irgendwo im Speicher liegt und ausserdem
bei jeder neuen Zuweisung an einen anderen Platzt verlegt wird.
Wird jetzt ein Listenelement gelöscht, das einen String enhält, wird automatisch der Zusäztliche
Speicher des Strings mit freigegeben.

Noch Fragen? :twisted: :wink:

cu
technicorn
Benutzeravatar
Hyper
Beiträge: 194
Registriert: 19.04.2005 19:14

Beitrag von Hyper »

Nun, Du erklärst, warum es nicht (so einfach) geht. Ist ja auch ok. Ich blicke aber aus Sicht des Anwenders der Programmiersprache und da bin ich halt bspw. von ABAB/4 relativ verwöhnt.

Als Nutzer der Sprache halte ich es für meine Aufgabe, zu sagen was sinnvoll wäre, was dann wie umzusetzen ist, müssen dann die Macher der Sprache sagen. Und da bleibt es bspw. nicht logisch, wenn es optionale Parameter gibt, dass Listen nicht optional sein können. Mit CounList kann man in der Procedure ja sehr einfach ermitteln, ob eine Liste reinkam oder nicht.
PB 5.72
technicorn
Beiträge: 11
Registriert: 11.03.2006 22:07

Beitrag von technicorn »

Hallo Hyper,

ich vermisse bei PB auch so einige Sachen, insbesondere rund um Arrays/Listen.
In XBasic, was leider schon seit Jahren nicht Weiterentwickelt wird,
gibt es sogar die Möglichkeit, unregelmäßige Arrays zu erzeugen, bzw.
man kann einzelne Teile aus dem Array ausklinken und an andere wieder
anhängen.

Ich weiß auch nicht so genau, wieviele nun tatsächlich an der Entwicklung von PB arbeiten,
es sieht aber so aus, daß es ein Einmann Job ist, und dafür ist gegenüber PB3.94 einiges (sehr gutes) passiert.

Was ich jetzt noch nicht verstehe, wieso willst Du eine Proc. aufrufen,
die mit Listen arbeiten soll, und dann keine Übergibts?

Hab's mahl kurz probiert, was viel problematischer ist, finde ich,
daß es bei Proc. nicht möglich ist verschieden Typen von Listen zu übergeben,
um dann z.B. je nach Typ die Daten zu bearbeiten.
Aber das geht wohl schon in Richtung Funktionsüberladung, wie in C++, Java, und ist für die meisten eher nicht einzusetzen.
Muß dann halt eine Proc. für jeden Typ schreiben,
was auf der anderen Seite auch schnelleren Code bringt,
keine Abfrage von Typen usw.
Benutzeravatar
Hyper
Beiträge: 194
Registriert: 19.04.2005 19:14

Beitrag von Hyper »

Hallo technicorn,
...und dafür ist gegenüber PB3.94 einiges (sehr gutes) passiert.
Das sehe ich ganz genau so! Ich bin wirklich ein großer Fan von PB und deshalb war ich auch begeistert, dass PB4 rauskam. Um so mehr habe ich natürlich Interesse am weiteren Ausbau der Sprache.
Was ich jetzt noch nicht verstehe, wieso willst Du eine Proc. aufrufen,
die mit Listen arbeiten soll, und dann keine Übergibts?
Wenn es Gründe gibt, normale Variablen als optional zu kennzeichnen, gibt es auch welche, um das für Arrays und Listen zu tun. Um so mehr wir mit optionalen Parametern arbeiten werden, desto häufiger werden uns hier Fälle begegnen, denke ich.
PB 5.72
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Hyper hat geschrieben: Wenn es Gründe gibt, normale Variablen als optional zu kennzeichnen, gibt es auch welche, um das für Arrays und Listen zu tun. Um so mehr wir mit optionalen Parametern arbeiten werden, desto häufiger werden uns hier Fälle begegnen, denke ich.
Für Listen oder Arrays kann ich mir keinen Grund für Optionalität vorstellen
:mrgreen:
Wenn Du dafür ein sinnvolles Beispiel hättest, würde mich aber wundern :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
In_Go
Beiträge: 20
Registriert: 06.02.2006 23:46
Wohnort: Eschau, Spessart

Beitrag von In_Go »

Hallo!

Ihr habt viel über unmögliches (?) geschrieben habt aber den Kern der
Sache aus den Augen verloren!

Dabei ists ganz einfach!
Man definiert eine linkedList und übergibt Sie an die Procedure
Innerhalb der Procedure wird die linkedListe Verändert
Die Änderung ists nach der Rückkehr immer noch da!
Die Liste mus dazu nicht mal Global sein!

Also:

Code: Alles auswählen

;Beispiel für Parameterübergabe von Listen an Unterprogramme
;Beispiel für Errechnung der Indizes im Scrollgadget
;Beispiel für With und Endwith
;DIES SOLLTE ALLE DEINE FRAGEN BEANTWORTEN
;UND IST EIN GUTES BEISPIEL FÜR DIE NEUERUNGEN VON PB$
; DANKE FRED! 
Structure TableLine 
  index.l 
  y.l 
  yl.l 
EndStructure 

Structure TableColumn 
  x.l 
  y.l 
  xl.l 
  yl.l 
  name.s 
  id.l 
EndStructure 
Structure Gad
  x.l
  y.l
  b.l
  h.l
  Gadgetart.l 
  Spalte.l
  Zeile.l
  Nummer.l
EndStructure
Enumeration 
  #Window_0 
EndEnumeration
Global GGAD.l
Global GWB.l
Global GWH.l

Procedure PlusGadget(gadgetnummer.l,x.l,y.l,h.l,b.l,zeile.l,spalte.l,G.gad())
  GGAD.l + 1
  SetGadgetData(gadgetnummer.l,GGAD.l)
  AddElement(G())
  With G()  
  \Nummer=gadgetnummer.l :\x=x.l : \y=y.l :\h=h.l : \b=b.l :\Gadgetart=GadgetType(gadgetnummer) 
  \zeile=zeile.l : \spalte=spalte.l
  EndWith
EndProcedure
Procedure TableGadget(GadgetNr,x,y,width,height,name$,SpaltenBreite,TLL.TableLine(),TCL.TableColumn(),G.gad()) 
  If CreateGadgetList(WindowID(#Window_0)) 
    ScrollAreaGadget(GadgetNr, x, y, width, height, 80, 20,  15, #PB_ScrollArea_Single)
    plusgadget(Gadgetnr,x,y,width,height,-1,-1,G())
    AddElement(TLL()) ;Neue Zeile
    AddElement(TCL()) ;Neue Spalte
    With TCL()
    \x=30 : \y=0 : \xl=SpaltenBreite :\yl=20  :\name=name$ 
    \id=ButtonGadget(#PB_Any, \x, \y, \xl, \yl, \name, #PB_Button_MultiLine) 
    plusgadget(\id,\x,\y,\xl,\yl,0,1,G()) 
    EndWith
    CloseGadgetList() 
  EndIf 
EndProcedure 

Procedure AddTableColumn(GadgetNr,Position,name$,Breite,TCL.TableColumn(),G.Gad()) 
  OpenGadgetList(GadgetNr) 
  istbreite=GetGadgetAttribute(GadgetNr,#PB_ScrollArea_InnerWidth) 
  SetGadgetAttribute(GadgetNr,#PB_ScrollArea_InnerWidth,Breite+istbreite) 
  LastElement(TCL()) 
  With TCL()
  x = \x  : y = \y :xl= \xl : yl= \yl  
  AddElement(TCL()) 
  \x=x+xl : \y=y : \xl=Breite : \yl=yl : \name=name$ 
  \id=ButtonGadget(#PB_Any, \x, \y, \xl,\yl,\name, #PB_Button_MultiLine) 
  plusgadget(\id,\x,\y,\xl,\yl,0,CountList(TCL()),G())  
  EndWith
  CloseGadgetList() 
EndProcedure 
;Nun kann man Unterprogramme schreiben die allgemein gültig sind!
Procedure AddTableLine(GadgetNr,TLL.TableLine(),TCL.TableColumn(),G.gad()) 
  OpenGadgetList(GadgetNr) 
  isthoehe=GetGadgetAttribute(GadgetNr,#PB_ScrollArea_InnerHeight) 
  SetGadgetAttribute(GadgetNr,#PB_ScrollArea_InnerHeight,15+isthoehe) 
  Spaltenanzahl = CountList(TCL()) 
  LastElement(TLL()) 
  With TLL()
  index=\index : y=\y : yl=\yl 
  AddElement(TLL()) 
  \index=index+1 : \y=y+yl :\yl=15
  indextaste=ButtonGadget(#PB_Any,0,\y+20,30,15,Str(\index))
  plusgadget(indextaste,0,\y+20,30,15,  \index ,0,G()) 
  EndWith 
   ForEach TCL() 
    With TCL()
    x=\x :y=\yl+TLL()\y : xl=\xl  : yl=TLL()\yl
    EndWith
    mp=StringGadget(#PB_Any,x,y,xl-2,yl-1,"",#ES_MULTILINE|#PB_String_BorderLess) 
    plusgadget(mp,x,y , xl-2 , yl-1 , CountList(TLL())-1 , ListIndex(tcl())+1 , G() )
    ;#PB_String_MultiLine gibts nicht mehr, #ES_MULTILINE scheint identisch zu sein
  Next 
  CloseGadgetList() 
EndProcedure 

Procedure SaveTable()   
EndProcedure 

Procedure LoadTable()  
EndProcedure 

Procedure Open_Window_0(YTableLineList.TableLine(),XTableColumnList.TableColumn(),G.gad()) 
  GWB.l=459:GWH.l=285
  If OpenWindow(#Window_0, 74, 19, GWB.l, GWH.l,"TableGadget" , #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar)   
    TableGadget(1,5,5,300,200,"Index",50,YTableLineList(),XTableColumnList(),G()) 
    AddTableColumn(1,0,"Bemerkung",100,     XTableColumnList(),G())  
    AddTableColumn(1,0,"NotizAnweisung",100,XTableColumnList(),G()) 
    AddTableColumn(1,0,"Bemerkung",100,     XTableColumnList(),G()) 
    AddTableColumn(1,0,"Bemerkung2",100,    XTableColumnList(),G()) 
   ; CallDebugger
    For xxx= 1 To 50 
      AddTableLine(1,YTableLineList(),XTableColumnList(),G()) 
    Next 
  EndIf 
EndProcedure 
;Du siehst die Listen sind nicht global trotzdem werden sie in den Unterprogrammen verwendet! 
NewList TableColumnList.TableColumn() 
NewList TableLineList.TableLine() 
NewList gadgets.gad()
Open_Window_0(TableLineList(),TableColumnList(),gadgets()) 

Repeat 
  Event = WaitWindowEvent()  
  EventType = EventType() 
  Select event ;EventType
  Case #PB_Event_Gadget
    GadgetID = EventGadget() 
    D=GetGadgetData(gadgetid)   
    SelectElement(gadgets(),D-1)
    Debug "("+Str(gadgets()\zeile)+","+Str(gadgets()\spalte)+")"
  Case #PB_Event_Repaint
    If IsWindow(0) :UpdateWindow_(WindowID(0)) :EndIf
    Debug "Repaint"
  Case #WM_SIZE
    nwh.l=WindowHeight(0) :nwb.l=WindowWidth(0)
    If nwh.l<>GWH.l Or  nwb.l<>GWB.l
      ResizeGadget(1, 5*nwb.l/GWB.l  ,  5*nwh.l/GWH.l, 300*nwb.l/GWB.l , 200*nwh.l/GWH.l)
      ForEach gadgets()
        With gadgets()
        EndWith      
      Next
      Debug "Size"
    EndIf 
  EndSelect
Until Event = #PB_Event_CloseWindow 
End 
Shit happens: Let's try to make things better!
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

@in_go
Super beispiel :allright: :allright: :allright:

Darf nach man doch nutzen und weiterentwickeln?
Stelle gerade fest das ich mal die gesamte Befehles und Funktionsliste
mal durchschauen muss. Ist so viel GUTES dazugekommen, was man noch
gar nicht gesehen und ausprobiert hat.

FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Gesperrt