Addcolumn() und codeblöcke

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Addcolumn() und codeblöcke

Beitrag von saul »

Hallo,

Code: Alles auswählen

ABrowse:AddColumn ( {|| aData[nRecno,1] } )
ABrowse:AddColumn ( {|| aData[nRecno,2] } )
funktioniert

Code: Alles auswählen

For i = 1 to 2
  ABrowse:AddColumn ( {|| aData[nRecno, i ] } )
next
Gibt eine Fehlermeldung. Ich schätze das liegt am Codeblock bzw. dem Zähler i.

Code: Alles auswählen

For i = 1 to 2
  ABrowse:AddColumn ( {|i| aData[nRecno, i ] } )
next
Gibt aber auch eine Fehlermeldung. Hat jemand eine Idee warum der codeblock in For next Problem bereitet?

mfg
Wolfgang
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2827
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 96 Mal
Danksagung erhalten: 13 Mal

Re: Addcolumn() und codeblöcke

Beitrag von georg »

Hallo, Wolfgang -


da wird jetzt wieder ein Glaubenskrieg losbrechen bezüglich der Frage, ob das Verhalten von Xbase++ in solchen Situationen sinnvoll ist oder nicht.

In solchen Situationen verwende ich eine Funktion die ich aufrufe, etwa in der Art:

Code: Alles auswählen

For i = 1 to 2
  ABrowse:AddColumn ( Blockify(aData, nRecno, nI )
next
...
FUNCTION Blockify(aArray, nPosition, nIndex)
   Local bBlock
   bBlock := {|| aArray[nPosition, nIndex]}
RETURN(bBlock)
In Deiner Schleife erhält i die Werte 1 bis 3 (!), denn nach der zweiten Schleife wird i auf 3 erhöht, die Endebedingung ist erreicht, und die Schleife wird verlassen, der Wert 3 verbleibt aber in der Variablen i.

Die Codeblöcke referenzieren die lokale Variable i, und die hat jetzt den Wert 3 und nicht den Wert, den sie zum Zeitpunkt hatte, als der Codeblock erzeugt wurde. Darum knallt es, denn der Codeblock verweist auf die aktuelle Variable (und damit den aktuellen Inhalt), und nicht auf den Inhalt zum Zeitpunkt der Codeblockerzeugung.

Verwendest Du eine Funktion, dann wird der Codeblock "anders" gebildet, da die Variable nIndex ausserhalb des Fokus ist, wird sie mit ihrem Wert und nicht ihrer Adresse festgehalten, und dann geht es.


Gruss,

Georg
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Re: Addcolumn() und codeblöcke

Beitrag von saul »

Hallo Georg,
danke für die Info. Ich habe den Code eingebaut. Funktioniert aber nicht.
Woher kommt die Variable nI bei Funktionsaufruf im For next?
Ich habe dort statt nI i eingesetzt.
Damit funktioniert es bedingt, denn es wird jetzt auf allen Zeilen der Tabelle immer der erste Datensatz angezeigt.

mfg
Wolfgang
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2827
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 96 Mal
Danksagung erhalten: 13 Mal

Re: Addcolumn() und codeblöcke

Beitrag von georg »

Hallo, Wolfgang -


da habe ich beim Tippen nicht genau hingeschaut, bezogen auf Deinen Code sollte es "i" und nicht "nI" gewesen sein.

Die ungarische Notation verwende ich grundsätzlich, weil man z.B. deutlich schneller die Verwendung von "nI" als von "i" findet.

Leider kenne ich den restlichen Code nicht ... eventuell könnte es so gehen:

Code: Alles auswählen

ABrowse:addColumn(Blockify(aData, i))

...

Function Blockify(aArray, nIndex)
   Local bBlock
   bBlock := {|| aArray[nRecno, nIndex]}
RETURN(bBlock)
Das setzt voraus, dass nRecno eine STATIC Variable ist, die .prg-weit sichtbar ist.


Gruss,

Georg
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Re: Addcolumn() und codeblöcke

Beitrag von saul »

Hi Georg,
funktioniert auch nicht.

Code: Alles auswählen

   ::ABrowse:AddColumn ( {|| ::aData[::nRecno,1] }  )
Funktioniert.

Code: Alles auswählen

For I = 1 to 2
  ::ABrowse:AddColumn ( {|| ::aData[::nRecno,i] }  )
endif
Funktioniert nicht.
Der eigentliche Code steckt in einer Methode. Die :: hatte ich weggelassen damit es nicht zu kompliziert wird. Aber vielleicht könnte das doch von Bedeutung sein.
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von UliTs »

saul hat geschrieben:

Code: Alles auswählen

For I = 1 to 2
  ::ABrowse:AddColumn ( {|| ::aData[::nRecno,i] }  )
endif
Funktioniert nicht.
Hallo Wolfgang,

das Problem liegt in der Variable I und darin, dass der Codeblock erst später vom Browser benutzt = berechnet wird.
Nach der Schleife hat I den Wert 3 (eigentlich undefiniert). Wenn dann der Browser den Codeblock berechnet, hat I vermutlich den Wert 3 und nicht wie gewünscht einmal 1 bzw. 2.
Abhilfe würden mit Hilfe des Macrooperators gebildete Codeblöcke (allerdings auf Kosten der Performance) liefern, da in diesem Fall I nicht innerhalb des Codeblocks verwendet wird:

Code: Alles auswählen

For I = 1 to 2
  cCodeBlock := "{||::aData[::nRecNo,"+str(i)+"}"
  ::ABrowse:AddColumn (  &cCodeBlock )
endif
Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9367
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von Tom »

Eben, Uli hat recht. Das ist keine "Glaubensfrage". Es gibt Slots/Codeblock-Zuweisungen, die werden im Moment der Zuweisung evaluiert, und andere (die meisten), die eben für die Laufzeit bestimmt sind, was bei Datalinks äußerst sinnvoll ist, aber auch bei ColorBlock und ähnlichen. Wenn dann innerhalb der Codeblöcke Variablen referenziert werden, die zu diesem Zeitpunkt ganz andere Werte haben, scheitert dieser lineare FOR - NEXT-Aufbau. Entweder baut man dann die Blöcke als Texte für den Makro-Expander, wie in Ulis Beispiel (Vorsicht: keine LOCALs referenzieren! "aData" muss in diesem Fall PRIVATE sein!), oder man erzeugt eine Funktion - oder man arbeitet mit echten "detached LOCALs".
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9367
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von Tom »

Vielleicht noch zum Verständnis.

Ein Codeblock ist verdichteter Code, repräsentiert durch einen eigenen Datentypen (ValType liefert "B"). An und für sich macht ein Codeblock erst einmal überhaupt nichts, etwa im Moment der Erzeugung oder Zuweisung:

Code: Alles auswählen

bBlock := {||MachWas()}
Hier geschieht nicht viel - es wird eine Variable "bBlock" vom Datentyp "B" (Codeblock) erzeugt, die Code enthält. Mehr passiert nicht. Der Code in einem Codeblock kann sehr (beliebig) komplex sein, er darf nur keine Anweisungen enthalten, etwa "DELETE" oder auch "FOR ... NEXT". Dafür gibt es Funktionen (DbDelete) oder entsprechende Repräsentationen (aEval), schlussendlich kann ein Codeblock aber auch auf eine Funktion verweisen, in der alles mögliche passiert. Nichtsdestotrotz: Im Moment seiner "Herstellung" macht der Codeblock überhaupt nichts. Er wird lediglich einer Variablen zugewiesen, was natürlich auch die Instanzvariable eines Objekts oder ein sog. "Slot" sein kann, also die iVar einer Klasse, die mit Codeblöcken bestückt werden kann oder sollte. Mache ich aber das hier:

Eval(bBlock)

wird der Code in "bBlock" ausgeführt. Genau das geschieht auch mit den Slots, wie "Datalink", "ColorBlock", "ItemMarked" usw. in der XbpBrowse-Klasse. Ein Event wird ausgelöst oder ein bestimmter Zustand tritt ein, und der Code im Slot wird abgerufen und ausgeführt. Hierfür stehen ggf. noch Parameter zur Verfügung (siehe Doku), die der Codeblock-Code verwenden kann, beispielsweise Referenzen auf das Klassenobjekt, um mit diesem arbeiten zu können.

Wichtig und entscheidend ist also, dass der Code im Codeblock quasi "losgelöst" ist. Was im Moment der Herstellung noch richtig und relevant war, muss im Moment der Ausführung/Evaluierung nicht mehr der Fall sein, denn der Code im Block ist hiervon unabhängig. Ich kann ihn auch ganz woanders ausführen. Deshalb muss dieser Code immer für sich funktionieren, und an dieser Stelle wird es dann eben schwierig, wenn man Codeblöcke in Iterationen erzeugen will. Alle Referenzen, die innerhalb der Iteration gültig waren, sind es im Moment der Codeblock-Evaluierung sehr wahrscheinlich nicht mehr, weshalb schon ein simpler Schleifenzähler im Block nahezu zwangsweise zu Fehlverhalten führt. Man kann ihn aber beispielsweise bei der Erzeugung von Browsespalten auch im Cargo-Slot der Column platzieren, um dann im Codeblock-Code darauf zugreifen zu können. Wichtig ist, dass man sich dieser Tatsache bewusst ist: Der Code im Block wird nicht im Moment der Herstellung ausgeführt, sondern später - und übrigens auch beliebig oft.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von brandelh »

Ergänzend zu Toms und Ulis Ausführungen kann man einen Codeblock als "Funktion ohne Namen" sehen.
Während man eine normale Funktion per Namen aufruft, wird der codeblock entweder zur Laufzeit übersetzt ( &cCodeBlockVar ) oder beim compilieren erzeugt ( {|| ...} ) in beiden Fällen ist es aber von der Wirkung wie FUNCTION ... RETURN.
Bei einer Funktion wird ja auch nichts ausgeführt, wenn sie zur Compilerzeit erzeugt wird.

Erst der tatsächliche Aufruf führt Code aus.
Gruß
Hubert
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von UliTs »

Tom hat geschrieben:(Vorsicht: keine LOCALs referenzieren! "aData" muss in diesem Fall PRIVATE sein!)
Tom, hast Du Dich da vertan? Hast Du die beiden Doppelpunkte vor aData übersehen: ::aData ?

Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Re: Addcolumn() und codeblöcke

Beitrag von saul »

Hallo,
da sind Sie wieder meine Probleme. Vielen Dank erstmal für die Antworten.

&cCodeBlockVar was ist der erste Buchstabe für ein Zeichen/was bedeutet er?

Was sind Iterationen?

Was ist ein Makro-Expande?

Was ist Macrooperators?

mfg
Wolfgang
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von brandelh »

Alter Code (egal ob Basic oder Clipper) ist schön matschig und vielsagend ...

a = 1
b = 3
c = "Alles"
...
c + a + b => Fehler ... warum nur ... suchen .... ach da oben :wink: eventuell auch noch Wechsel von String und numerisch ...

Wehe wenn man sowas warten muss. Darum gibt es Regeln. Eine davon ist, dass der erste Buchstabe den Variablentyp angibt, das muss man aber auch einhalten,
der Compiler hilft hier nicht (Clipper und Xbase++ kennen keine typisierten Variablen = eine Variable kann nur genau einen Datentyp beinhalten z.B. STRING).

Ich verwende eine angepaßte Version von dem hier :arrow: => http://de.wikipedia.org/wiki/Ungarische_Notation

cVar := "Strings" oder "Z" chars (einige unterscheiden da... s = String, c = char)
nVar := 0 // numerische Werte
i, x, y, z nur Index (z.B. Array) oder FOR NEXT Schleifen, daher keine Notation, nur eine Stelle
dVar := date() // Datumswerte ...

im Prinzip angelehnt an den Feldtyp bzw. vartype() Rückgabe ... wer sich daran hält, sieht sofort:

nGehalt * cFaktor ... wird wohl ein Tippfehler oder ein Programmierfehler sein, könnte aber natürlich auch die Rückgabe der transform() Formatierung sein.
Auf jeden Fall ist cFaktor wenn man sich an diese Regel hält nicht numerisch und die Zeile muss korrigiert werden.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von brandelh »

saul hat geschrieben:&cCodeBlockVar was ist der erste Buchstabe für ein Zeichen/was bedeutet er?
Achso, du meinst '&' das käufmännische UND steht für Macrooperator (wie + oder - ein Operator ist, ist auch & einer) => SHIFT 6 (ist hier schwer zu erkennen)
saul hat geschrieben: Was ist ein Makro-Expande?
Was ist Macrooperators?
SHIFT + 6 => &
"1 + 3" ist ein String
&("1 + 3) wird intern umgesetzt als ob der Quellcode nur 1 + 3 enthalten hätte und wird berechnet nach 4 !

Macros sind sehr mächtig, können aber auch verwirrend werden insbesondere bei komplexen Konstruktionen.
saul hat geschrieben:Was sind Iterationen?
Das Wort von kommt von Schleife und bezeichnet Programme, die sich selbst aufrufen um Arbeiten Schrittweise bis zur Endebedingung auszuführen.
Es gibt hier in der Wissensbasis Beispiele von mir, die z.B. alle Dateien und Verzeichnisse unter einem Verzeichnis löschen.
Ein weiteres Beispiel sind Reihenberechnungen wie z.b. die Fakultät.
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von Martin Altmann »

brandelh hat geschrieben:
saul hat geschrieben:Was sind Iterationen?
Das Wort von kommt von Schleife und bezeichnet Programme, die sich selbst aufrufen um Arbeiten Schrittweise bis zur Endebedingung auszuführen.
Falsch - das sind Rekursionen :!:
Iteration heißt einfach "wiederholte Anwendung" im Sinne von "erneuter Durchlauf".

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von brandelh »

Hast Recht, war wohl zu warm hier ;-)

... wobei ich hinzufügen würde ... wiederholter Durchlauf um das Ergebnis zu verbessern. Einen Zweck soll es ja haben :D (besser sich dem Ergebnis anzunähern.)

PS: sowas kann man toll bei Wikipedia nachsehen.
Gruß
Hubert
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Re: Addcolumn() und codeblöcke

Beitrag von AUGE_OHR »

Tom hat geschrieben:Eben, Uli hat recht. Das ist keine "Glaubensfrage". Es gibt Slots/Codeblock-Zuweisungen, die werden im Moment der Zuweisung evaluiert, und andere (die meisten), die eben für die Laufzeit bestimmt sind, was bei Datalinks äußerst sinnvoll ist, aber auch bei ColorBlock und ähnlichen. Wenn dann innerhalb der Codeblöcke Variablen referenziert werden, die zu diesem Zeitpunkt ganz andere Werte haben, scheitert dieser lineare FOR - NEXT-Aufbau. Entweder baut man dann die Blöcke als Texte für den Makro-Expander, wie in Ulis Beispiel (Vorsicht: keine LOCALs referenzieren! "aData" muss in diesem Fall PRIVATE sein!), oder man erzeugt eine Funktion - oder man arbeitet mit echten "detached LOCALs".
ihr habt die "::" gesehen ?

Code: Alles auswählen

For I = 1 to 2
  cCodeBlock := "{||::aData[::nRecNo,"+str(i)+"}"
  ::ABrowse:AddColumn (  &cCodeBlock )
endif
das geht NICHT !

was Georg mit "Glaubensfrage" hier meint ist eine FUNCTION auf ein o:Datalink zu legen statt eines Codeblock denn das geht dann auch mit dem "::" zur Laufzeit.

wenn man nicht "::" nimmt muss, wie Tom schon sagte, das "aData" eine PRIVATE sein
gruss by OHR
Jimmy
saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Re: Addcolumn() und codeblöcke

Beitrag von saul »

Hallo,
ich habe immer noch das Problem, dass ich nicht weiß wie ich mit einer For next in einer Methode umgehen soll. Was ich begriffen habe ist, dass wenn ich schreibe:

Code: Alles auswählen

For I = 1 to 2
  if ::buttons[i,1] = "aendern"
    ::oButton2:= XbpPushButton():new(::drawingArea , , {46,3}, )
    ::oButton2:autosize := .T.
    ::oButton2:caption := "  ~Žndern  "
    ::oButton2:activate := {|| PostAppEvent( xbeP_Keyboard, ::buttons[i,2] ) }     // 
    ::oButton2:visible:=.T.
  endif
next
dies nicht funktioniert, da i von ::buttons[i,2] im Codeblock während der Laufzeit einen falschen Wert annimmt. Ich bekomme auch einen Laufzeitenfehler bezüglich des Array ::buttons.

Code: Alles auswählen

For I = 1 to 2
  if ::buttons[i,1] = "bemerkung"
    ::oButton2:= XbpPushButton():new(::drawingArea , , {46,3}, )
    ::oButton2:autosize := .T.
    ::oButton2:caption := "  ~Bemerkung  "
    ::oButton2:activate := {|| PostAppEvent( xbeP_Keyboard, austausch(i) ) }     // hier Funktion eingefügt
    ::oButton2:visible:=.T.
  endif
next
....
func austausch(i)
return ::buttons[i,2] 
funktioniert aber auch nicht. Da habe ich doch wieder was nicht richtig verstanden oder?
Hat noch einer ein Idee?

mfg
Wolfgang
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2827
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 96 Mal
Danksagung erhalten: 13 Mal

Re: Addcolumn() und codeblöcke

Beitrag von georg »

Hallo, Wolfgang -

Code: Alles auswählen

{|| PostAppEvent( xbeP_Keyboard, austausch(i) ) }
erzeugt einen Codeblock, der zur Laufzeit (!) wiederum i auswertet.

Wie oben schon geschrieben (jetzt aber aus einem Programm verwendet), benutze ich eine FUNCTION, um den Codeblock zur Laufzeit zu erzeugen:

Code: Alles auswählen

STATIC FUNCTION Blockify(nI)
   Local bBlock

   bBlock := {|| LTrim(Str(nI))}
RETURN (bBlock)
Zur Laufzeit (also wenn der Codeblock zugewiesen wird), wird die Funktion aufgerufen und erhält in nI genau den aktuellen Wert, den ich brauche. Mit dem wird der Codeblock erzeugt und zurückgegeben. Da die Variable nI aus Blockify stammt, wird sie quasi eingefroren, da ihr Kontext ja nicht mehr "existiert" und verändert ihren Wert nicht mehr.


Gruss,

Georg
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Re: Addcolumn() und codeblöcke

Beitrag von saul »

Hallo,
es ist zum Haare ausraufen.

Code: Alles auswählen

abuttons:= { {"bemerkung",66,"Bemerkung"}}       //dies wir vor der Objekterstellung definiert

For i = 1 to len(abuttons)
  if buttons[i,1] = "bemerkung"
    oButton1:= XbpPushButton():new(::drawingArea , , {46,3}, )
    oButton1:autosize := .T.
    oButton1:caption := "  ~Bemerkung  "
    oButton1:activate := {|| PostAppEvent( xbeP_Keyboard, abuttons[1,2] )}
    oButton1:visible:=.T.
    oButton1:create()
  endif
next
Diese Variante funktioniert.

Code: Alles auswählen

....
  oButton1:activate := {|| PostAppEvent( xbeP_Keyboard, abuttons[Blockify(i),2] )}     // hier habe ich die 1 durch i ersetzt
....
STATIC FUNCTION Blockify(nI)
  Local bBlock
  bBlock := {|| LTrim(Str(nI))}
RETURN (bBlock)
Bei dieser Variante gibt es die unten angehängte Fehlermeldung. Wenn ich das richig sehe, so erwartet i die Rückgabe eine Zahl. Aber auch bBlock := {|| Val(LTrim(Str(nI)))} bringt keinen Erfolg.
Dateianhänge
Fenster.jpg
Fenster.jpg (18.42 KiB) 7710 mal betrachtet
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2827
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 96 Mal
Danksagung erhalten: 13 Mal

Re: Addcolumn() und codeblöcke

Beitrag von georg »

Hallo, Wolfgang -

Code: Alles auswählen

....
  oButton1:activate := {|| PostAppEvent( xbeP_Keyboard, abuttons[Blockify(i),2] )}     // hier habe ich die 1 durch i ersetzt
....
STATIC FUNCTION Blockify(nI)
  Local bBlock
  bBlock := {|| LTrim(Str(nI))}
RETURN (bBlock)
So geht es nicht. Der Trick ist, dass der Codeblock von der aufgerufenen Funktion geliefert wird, und zwar komplett, also etwa so:

Code: Alles auswählen

....
  oButton1:activate := Blockify(xbeP_Keyboard, aButtons, i)
....
STATIC FUNCTION Blockify(nEvent, aElems, nI)
  Local bBlock
  bBlock := {|| PostAppEvent(nEvent, aElems[nI, 2])}
RETURN (bBlock)
Mein Beispiel war nicht für Deinen Code gedacht, sondern aus einem Programm entnommen. Es wandelt eine Zahl in einen linksbündig gestellten String um, und der dient kaum als Index in einem Array ...


Gruss,

Georg
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Re: Addcolumn() und codeblöcke

Beitrag von saul »

Der Trick ist, dass der Codeblock von der aufgerufenen Funktion geliefert wird, und zwar komplett, also etwa so:
Das war der endscheidende Satz. Nun habe ich das verstanden. Was es nicht alles gibt. :D
Ich habe dann folgendes probiert

Code: Alles auswählen

STATIC FUNCTION Blockify(nEvent, aElems, nI)
RETURN {|| PostAppEvent(nEvent, aElems[nI, 2])}
Das funktioniert auch, aber es hat doch bestimmt einen Grund weshalb Du das in Deiner Form gemacht hast oder?

mfg
Wolfgang
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2827
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 96 Mal
Danksagung erhalten: 13 Mal

Re: Addcolumn() und codeblöcke

Beitrag von georg »

Hallo, Wolfgang -


ja. Dadurch, dass ich den Codeblock innerhalb der Funktion in einer Variablen speichere und nicht direkt in der Return-Anweisung erzeuge, kann ich im Zweifelsfall im Debugger kontrollieren, was passiert.


Gruss,

Georg
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
saul
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 284
Registriert: So, 26. Mär 2006 12:23

Re: Addcolumn() und codeblöcke

Beitrag von saul »

Siehste daran habe in noch garnicht gedacht.

mfg
Wolfgang
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Re: Addcolumn() und codeblöcke

Beitrag von UliTs »

Hallo Georg,

gute Idee!
Allerdings hatte diese einen kleinen Nachteil -meine ich- : bei jedem Aufruf der Funktion Blockify wird Speicher "gefressen": der Speicherbereich für den Parameter und die Locals innerhalb Blockify wird nie wieder freigegeben. Hast Du das mal geprüft (z.B. Schleife mit 10.000.000 Durchläufen und Aufruf von Blockify)? Andererseits wird die Funktion sicher nur selten aufgerufen...

Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2827
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 96 Mal
Danksagung erhalten: 13 Mal

Re: Addcolumn() und codeblöcke

Beitrag von georg »

Hallo, Uli -


leider können wir den Quellcode nicht einsehen, aber meine Vermutung sieht so aus:

- aus der Local Variablen bBlock wird eine Speicheradresse. Dieser Adresse wird der Codeblock zugewiesen und, und beim Return wird eine Kopie der Speicheradresse (bzw. des Codeblocks, auf den sie zeigt) zurückgegeben. Danach räumt der Garbagecollector den Kram auf.

- wird der Codeblock in der Return-Anweisung erzeugt, passiert das Gleiche, wobei auch hier zumindest ein temporärer Speicherbereich geschaffen werden muss, um den Codeblock aufzunehmen und zurückzuliefern. Auch hier sollte dann der Garbagecollector greifen.

Von daher denke ich, dass das Verhalten bezüglich des Speicherverbrauchs fast identisch sein dürfte. Ansonsten wird die Funktion bei mir pro Browse einmal je Spalte aufgerufen, wenn ich einen generischen Browse erzeuge, ansonsten ist die Spaltendeklaration meist explizit.

Generischer Browse: damit meine ich einen XbpBrowse(), der eine komplette Tabelle inclusive aller Felder anzeigt, Browse-Aufbau entspricht dabei dem Datei-/Tabellenaufbau.


Gruss,

Georg
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Antworten