1unitedpower: Quicktip: Rest-Parameter für typisierte Arrays

Holla!

Arrays können in PHP beliebige Werte enthalten. Das ist eine häufige Fehlerquelle; wenn man schon zur Entwicklungszeit sicherstellen will, dass ein Array nur Werte eines bestimmten Typs enthält, kann man dafür Rest-Parameter benutzen:

function ints (int ...$rest) : array {
  return $rest;
}
var_export(ints(1,2,3));
var_export(ints('foo')); // type error

Zum Ausprobieren: https://repl.it/Em7U/4

  1. Holla!

    Arrays können in PHP beliebige Werte enthalten. Das ist eine häufige Fehlerquelle; wenn man schon zur Entwicklungszeit sicherstellen will, dass ein Array nur Werte eines bestimmten Typs enthält, kann man dafür Rest-Parameter benutzen:

    Die Perl-Variante wäre tie(), damit wird ein Array an eine Klasse gebunden. Und diese Klasse stellt dann sicher, dass die Einzelwerte nur integer sind oder wie auch immer, beispielsweise auch nur Großbuchstaben.

    Perl's tie() gibt es seit Perl 5 (OOP) etwa um das Jahr 2000.

    Schönen Sonntag!

    1. Die Perl-Variante wäre tie(), damit wird ein Array an eine Klasse gebunden.

      Du hast meinen Knackpunkt überlesen, der handelte nämlich davon die Typkorrektheit bereits zur Entwicklungszeit (=statisch) und nicht erst zur Laufzeit (=dynamisch) sicherzustellen.

      1. Die Perl-Variante wäre tie(), damit wird ein Array an eine Klasse gebunden.

        Du hast meinen Knackpunkt überlesen, der handelte nämlich davon die Typkorrektheit bereits zur Entwicklungszeit (=statisch) und nicht erst zur Laufzeit (=dynamisch) sicherzustellen.

        Bitte erklär das mal, am Besten anhand eines Beispiels.

        1. Du hast meinen Knackpunkt überlesen, der handelte nämlich davon die Typkorrektheit bereits zur Entwicklungszeit (=statisch) und nicht erst zur Laufzeit (=dynamisch) sicherzustellen.

          Bitte erklär das mal, am Besten anhand eines Beispiels.

          Das heißt, dass Fehler durch falsch-getypte Programme bereits während der Entwicklung ausgeschlossen werden können. Macht man das nicht, können sich Typfehler ins Programm schleichen und während der Programmausführung auftreten. Im besten Fall hat der Programmierer eine Fehlerbehandlung für diesen Fall geschrieben und das Programm kann seine Arbeit fortsetzen. Im mittelschweren Fall erkennt das Laufzeitsystem den Fehler und bricht die Programmausführung ab. Im schlimmsten Fall wird der Fehler gar nicht erkannt und das Programm verhält sich undefiniert. Statisches Typchecking ist also eine Fehler-Früherkennung. In der Praxis werden diese Überprüfungen von der IDE durchgeführt und fehlerhafte Ausdrücke werden gekennzeichnet. Aber auch CI-Services (wie travis) prüfen Programme auf Typ-Korrektheit.

          1. Du hast meinen Knackpunkt überlesen, der handelte nämlich davon die Typkorrektheit bereits zur Entwicklungszeit (=statisch) und nicht erst zur Laufzeit (=dynamisch) sicherzustellen.

            Bitte erklär das mal, am Besten anhand eines Beispiels.

            Das heißt, dass Fehler durch falsch-getypte Programme bereits während der Entwicklung ausgeschlossen werden können.

            Danke Dir, gut erklärt ;)

            Mit meinem geliebten Perl würde das so aussehen:

            tie my @numbers, 'IntArray';
            push @numbers, 123;   # alles gut
            push @numbers, 'foo'; # schmeißt ne Exception
            

            Macht man das nicht, können sich Typfehler ins Programm schleichen und während der Programmausführung auftreten.

            Die Exception wird bspw. aufgefangen und das Programm mit einer ordentlichen Fehlermeldung beendet.

            Im besten Fall hat der Programmierer eine Fehlerbehandlung für diesen Fall geschrieben

            Bei einer Exception ist sowieso Schluss ;)

            Also: Es geht auch mit Perl.

            MfG

            1. Du hast meinen Knackpunkt überlesen, der handelte nämlich davon die Typkorrektheit bereits zur Entwicklungszeit (=statisch) und nicht erst zur Laufzeit (=dynamisch) sicherzustellen.

              Bitte erklär das mal, am Besten anhand eines Beispiels.

              Das heißt, dass Fehler durch falsch-getypte Programme bereits während der Entwicklung ausgeschlossen werden können.

              Danke Dir, gut erklärt ;)

              Offensichtlich nicht gut genug, denn

              tie my @numbers, 'IntArray';
              push @numbers, 123;   # alles gut
              push @numbers, 'foo'; # schmeißt ne Exception
              

              Exceptions sind Laufzeit-Fehler. Ein statischer Typchecker sollte das falsch-getypte Programm aber schon vor der Laufzeit des Programms zurückweisen.

              1. Exceptions sind Laufzeit-Fehler. Ein statischer Typchecker sollte das falsch-getypte Programm aber schon vor der Laufzeit des Programms zurückweisen.

                Hab grad Deinen Code getestet: Er wirft eine Exception:

                Uncaught TypeError: Argument 1 passed .... thrown.

                1. Wir machen mal ein Rollenspiel, du bist der Programmierer und hättest dieses Programm geschrieben, ich bin der Typchecker.

                  function ints (int ...$rest) : array {
                    return $rest;
                  }
                  var_export(ints(1,2,3));
                  var_export(ints('foo'));
                  

                  Du: „Ey Typchecker, ist das Programm korrekt getypt?“
                  Ich: „Nope, denn das Argument 'foo' in dem Ausdruck ints('foo') ist vom Typ string, aber ich hätte da einen int-Wert erwartet. Wenn du das nicht behebst bevor einer das Programm ausführt, könnte es hier zu einem Laufzeit-Fehler kommen.“
                  Du: „Ich verstehe. Und wenn ich 'foo' durch 42 ersetze?“
                  Ich: „Dann hab ich nichts weiter zu meckern. Wenn das Programm jetzt ausgeführt wird, gibt es keinen Typfehler zur Laufzeit.“
                  Du: „Wow, und das kannst du sehen ohne das Programm selber auszuführen?“
                  Ich: „Ja, ich gucke mir nur den Syntax-Baum an.“
                  Du: „Danke.“
                  Ich: „Nicht dafür.“

                  Und nun zurück zu deiner Antwort:

                  Hab grad Deinen Code getestet: Er wirft eine Exception:

                  Uncaught TypeError: Argument 1 passed .... thrown.

                  Du hast also das Programm ausgeführt, obwohl der Typchecker dir prophezeit hat, dass das Programm fehlerhaft ist und es zu einem Laufzeit-Typfehler kommen kann, wenn du den Fehler nicht behebst. Und es ist genau das eingetreten, was der Typchecker dir gesagt hat.

                  1. Hallo 1unitedpower,

                    Wir machen mal ein Rollenspiel, du bist der Programmierer und hättest dieses Programm geschrieben, ich bin der Typchecker. […]

                    rotfl made my day

                    LG,
                    CK

  2. Zwei Anmerkungen hätte ich.

    1. Ohne declare(strict_types=1); geht ints(1, '2', 3) ohne Fehler durch. Ob das richtig ist oder nicht, weiß der Jongleur... (der vom PHP Type Juggling). Mit dem declare wirft es den Type Error.

    2. Es ist definitiv ein Laufzeitcheck, und nicht statisch, wie von Dir unterstellt.

    function ints (int ...$rest) : array {
      return $rest;
    }
    var_export(ints(1,2,3));
    if (1 > 2)
       var_export(ints('foo')); // type error
    

    wirft keinen Fehler. Sollte es bei statischem Check aber.

    Rolf

      1. Ohne declare(strict_types=1); geht ints(1, '2', 3) ohne Fehler durch. Ob das richtig ist oder nicht, weiß der Jongleur... (der vom PHP Type Juggling). Mit dem declare wirft es den Type Error.

      Mit declare(strict_types=1); sagst du dem PHP-Laufzeitsystem, dass du Type-Coercing unterbinden möchtest.

      1. Es ist definitiv ein Laufzeitcheck, und nicht statisch, wie von Dir unterstellt.

      Nein, hier bist du dem selben Missverständnis wie pl aufgelaufen. Du hast das Programm durch den PHP-Interpreter gejagt ohne vorher einen statischen Typchecker zu fragen. Anders als Java oder C++ hat PHP keinen eingebauten statischen Typchecker. Falls du also von Typchecks zur Entwicklungszeit profitieren willst, musst du das mit einem externen statischen Typchecker komplementieren.

      1. Nee, ich habe nur nicht verstanden dass Du einen EXTERNEN Typchecker meinst. Ich bin davon ausgegangen, dass Du unterstellt hast, dass PHP das beim Laden des Scripts zurückweist und das Script gar nicht erst startet.

        Alles gut :)
        Rolf