27 Aug 2006 

Flasche leerLeer oder ohne Inhalt

Diese Flasche ist leer. Nein kein Vacuum, kein Whisky mehr drin. Also so gut wie, da kommt nix Verwertbares mehr raus, nicht mal mehr eine Neige. Kennt jemand einen Provider?

NIL = Abkürzung für Not In List. NIL ist ein in einigen Programmiersprachen vorkommender Variablentyp, der anderen Variablen (mit existierenden Speicherbereichen) zugewiesen werden kann. … Über eine Abfrage von NIL kann man die Gültigkeit aller in einem Programmcode zugewiesenen Variablen überprüfen.

Nil bedeutet auch: ist noch nichts zugewiesen. Es ist ein Unterschied zwischen das Feld vom Typ Zahl hat den Wert Null und ist Nil. Bei Nil wurde der Wert noch nicht angefaßt, bei Null wurde der Wert Null eingetragen. 4D kennt dieses Nil nicht. Sonst wäre das mit dem leeren Wert einfach.

Zurück zum Whisky. Kommt die Flasche in die Abfüllanlage, ist sie Nil. Danach ist sie nicht Nil, sondern hat den Wert 70cl oder £20, je nach Maß. Jetzt ist sie bei 0cl oder £0, aber nicht mehr Nil. Der Flascheninhalt hatte null Einfluß auf diesen Text.

Wann ist in 4D ein Wert leer?

Ein String oder Text ist leer, wenn kein Zeichen drinsteht. Ein leeres Datum könnte !00.00.00! sein und eine leere Zeit †00:00:00† und eine leere Zahl? Null ist keine leere Zahl, null € in der Kasse ist eine leere Kasse.

    Immer wieder vergleiche ich
  • einen String If($string="")
  • ein Datum If($datum=!00.00.00!)
  • eine Zeit If($zeit=†00:00:00†)
  • eine Zahl If($zahl=0)
  • und bin zu dem Schluß gekommen: ich brauche die Funktion gen_IsEmpty.

Warum eine generische Funktion?

1. aus Prinzip und 2. aus Faulheit. Nehmen wir an, ich habe zwei Datensätze Paul Müller. In dem einen habe ich Telefon und Fax, in dem anderen die eMail-Adressen. Ich will nur einen Datensatz Paul Müller haben, in dem Telefon, Fax und eMail-Adressen stimmen. Dazu habe ich mir die Methode Gen_MischTwoRecords * geschrieben und dort brauche ich die Funktion gen_IsEmpty. Denn wenn der Wert im Zieldatensatz nicht leer ist, soll die Methode diesen nehmen oder wenn der Wert im Quelldatensatz nicht leer ist soll dieser den Wert im Zieldatensatz überschreiben. Noch mal lesen!?

Nun im Detail

Grübel GrübelWann ist ein Stück Text leer? Ganz offensichtlich, wenn nichts drinsteht, ist $currObject->="" wahr. Steht nur ein Leerzeichen drin, ist der Text auch leer, aber mein Vergleich nicht wahr. Läßt sich ausbügeln. Trifft ($currObject->="") | ($currObject->=" ") zu, ist der Text leer.
Zwei Leerzeichen oder ein einzelnes Return ist ebenfalls ein leerer Text. Eigentlich sind alle Steuerzeichen funktional leere Texte. Gibt es im Text nur Zeichen, die funktional als leer gelten ist auch der ganze Text leer. Jetzt macht sich das generische Vorgehen bezahlt. Ab sofort wird in der Methode auch überprüft, ob alle Zeichen kleiner-gleich Ascii 32 und kein Nicht-brechendes-Leerzeichen sind und ggf. ein stimmt zurückgegeben. Fehlt noch was?

Grübel GrübelWann ist ein Datum leer? Ganz offensichtlich, wenn der Nullwert drinsteht. $currObject->=!00.00.00! ergibt ein wahr. Was ist, wenn ein falsches Datum drinsteht, sowas wie !6.13.06! Unsereiner sieht das bereits als falsch an. Den 13. Monat gab es noch nicht einmal im französischen Revolutionskalender. Ein Nordamerikaner sagt: „OK, see you 13th of june!“ und findet nix dabei. 4D ist smarter und macht das beste aus dem Datumsstring und berücksichtigt das Datumsformat des Systems, wenn die Funktion Date() verwendet wird. Aus einem 29.2.06 macht es den 1.3.06.
Will ich das haben?   Ist das in Ordnung?   Jein!

Stelle sich einer vor, das in Form eines Textes eingegebene Datum mit eigener Methode zu analysieren. Also rausfinden, was ist Tag, was ist Monat und dem Jahrhundertwechsel hinterher hinken. Schaltjahre sind ziemlich einfach.

Ich behelfe mir, indem ich den Wochentag des zu prüfenden Tages mit dem Wochentag des Tages nach dem zu prüfenden vergleiche. Liefert mir 4D für beide Tage den gleichen Wochentag, stinkt das Datum. Ist was faul, ist das Datum ein Null-Datum, so gut wie leer.

Darum liebe ich eine generische Funktion wie gen_IsEmpty. Es gilt, immer wieder neue Besonderheiten abzufangen. Der hinzugekommene Test muß an einer Stelle eingebaut werden und funktioniert überall.

Beispiel: Bilder prüfe ich heute auf Picture size($currObject->)=0 und halte mir offen, eventuell ein Bild als leer anzusehen, wenn dieses nur weiße Pixel enthält. Das ließe sich erahnen, sobald es sich extrem komprimieren läßt (in der Art: aus 307.200 Pixel werden 4 Byte fürs Pixel und 4 Byte für die Zahl, also keine 10 Byte) oder via ImageMagick geprüft oder via CoreImage oder wie heißt das korrekt für Longhorn oder …

Am meisten hadere ich mit dem fehlenden Nil bei Zahlen. Die Null ist eine Zahl, wenn auch eine besondere. Steht in einem 4D Zahlenfeld eine Null, ist nicht zu entscheiden, ob es tatsächlich der Zahlenwert Null ist oder ob der Wert nie angefaßt wurde. Das ist nicht gut, wie mit der Flasche Té Bheag.

Ich gebe die komplette Methode gen_IsEmpty gerne her. Anfrage per eMail reicht.

* ehe ich die Methode Gen_MischTwoRecords beschreibe, sollte ich zeigen, wie ich einen Datensatz in ein Blob packe. Auch das generisch, wg. Prinzip und Faulheit. RSS-feed abonnieren!

4D Themen: Berichte in Arbeit