Ankündigung

Einklappen
Keine Ankündigung bisher.

Funktion innerhalb einer Methode

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Funktion innerhalb einer Methode

    Heute habe ich zum ersten mal gesehen dass folgendes Möglich ist:

    PHP-Code:
    public function getAttachmentConstraints()
        {
            function 
    correct($value){
                if (
    $value == -1// to correct the xf system to work as we want 0 = Unlimited , -1 = never .
                
    {
                        return 
    $value ;
                }
                elseif(
    $value == 0)
                {
                        return 
    $value = -1;
                }
                else 
                {
                        return 
    $value;
                }
            }        
            
    $params parent::getAttachmentConstraints();
            
    $PermissionSize correct(2);
    ..

    Wieso kann man Funktionen innerhalb von Methoden deklarieren und aufrufen?
    Was für einen Sinn hat das?

  • #2
    Klassen und Funktionen können jederzeit deklariert werden, in der Form hat das aber keinen Sinn, beim zweiten Aufruf der Methode gibt es einen Fehler (already declared). Funktionen, die nur in einem bestimmten Scope existieren gibt es in PHP nicht (Closures mal außen vor). Ich schätze derjenige der das geschrieben hat, hat sich das anders vorgestellt

    Das einzige was IMHO gerechtfertigt ist, ist so etwas

    PHP-Code:
    if (!function_exists('foo')) {
       function 
    foo() { ... }

    für Funktionen, die in neueren PHP-Versionen eingeführt wurden (z.B. lcfirst)
    [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
    [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

    Kommentar


    • #3
      Nicht nur. Es gibt ja mittlerweile in PHP (ab 5.3.0 soweit ich weiß) auch "Funktionen höherer Ordnung", die als Parameter eine Callback-Funktion übergeben bekommen.

      Beispiele sind die (mir) aus Scheme (ein Lisp-Dialekt) bekannten Funktionen fold, map und filter. (fold heißt in PHP glaube ich etwas anderes, ich glaube array_reduce).

      Man auch Lambda Funktionen nutzen, oder eben speziell dafür definierte Funktionen. Beispiele findet man auf den Manual-Pages der entsprechenden Funktionen, beispielsweise hier für array_map
      Je mehr ich lerne, desto mehr wird mir bewusst, dass ich eigentlich nichts weiß.

      Kommentar


      • #4
        Und was hat das mit dem Thema zu tun?
        [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
        [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

        Kommentar


        • #5
          Zitat von fab Beitrag anzeigen
          Klassen und Funktionen können jederzeit deklariert werden, in der Form hat das aber keinen Sinn, beim zweiten Aufruf der Methode gibt es einen Fehler (already declared). Funktionen, die nur in einem bestimmten Scope existieren gibt es in PHP nicht (Closures mal außen vor). Ich schätze derjenige der das geschrieben hat, hat sich das anders vorgestellt

          Das einzige was IMHO gerechtfertigt ist, ist so etwas

          PHP-Code:
          if (!function_exists('foo')) {
             function 
          foo() { ... }

          für Funktionen, die in neueren PHP-Versionen eingeführt wurden (z.B. lcfirst)
          jo, aber auch soetwas würde ich im globalen Scope sinnvoller finden (wie zB die 100en Prüfungen in WordPress), aber innerhalb einer Methode ist mir dsa echt neu und nochimmer nicht einleuchtend.

          Kommentar


          • #6
            Zitat von fab Beitrag anzeigen
            Und was hat das mit dem Thema zu tun?
            Das ist meiner Ansicht nach ein konkretes Beispiel zur Nutzung von Funktionen, die innerhalb von Methoden oder anderen Funktionen deklariert werden.
            Je mehr ich lerne, desto mehr wird mir bewusst, dass ich eigentlich nichts weiß.

            Kommentar


            • #7
              Als Closures ($f = function(){....}), das ist aber in PHP ein großer Unterschied und um die ging es auch gar nicht.

              @ragtek: Nee, innerhalb einer Methode würde ich das auch nicht machen wollen. Halte ich auch weiterhin für sinnlos, es muss ja nicht alles sinnvoll sein nur weil es möglich ist.
              [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
              [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

              Kommentar


              • #8
                Geht ja auch als Callback, womit das unter Umständen Sinn machen könnte (aus dem PHP-Manual:

                PHP-Code:
                  <?php
                function cube($n)
                {
                    return(
                $n $n $n);
                }

                $a = array(12345);
                $b array_map("cube"$a);
                print_r($b);
                ?>
                Ich möchte mich aber nicht mit dir über Sinn und Unsinn streiten, natürlich könnte man dies auch anders lösen.
                Je mehr ich lerne, desto mehr wird mir bewusst, dass ich eigentlich nichts weiß.

                Kommentar


                • #9
                  Joah das ist legitim aber ich denke du wirst mir zustimmen dass die Deklaration von cube in der Form nicht innerhalb einer Methode stehen sollte. Grund siehe oben.
                  [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
                  [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

                  Kommentar


                  • #10
                    Dabei gebe ich dir vollkommen Recht
                    Je mehr ich lerne, desto mehr wird mir bewusst, dass ich eigentlich nichts weiß.

                    Kommentar


                    • #11
                      Zitat von ragtek Beitrag anzeigen
                      ...
                      Wieso kann man Funktionen innerhalb von Methoden deklarieren und aufrufen?
                      Was für einen Sinn hat das?
                      Keine Ahnung, vermutlich eines der unerwünschten "Features" des PHP-Parsers. Jedenfalls darf man nicht annehmen, dass man das genauso anwenden kann wie in Pascal oder D, wo es echte "nested functions" gibt, die dort auch einen Zweck erfüllen.

                      http://www.php.net/manual/en/functio...hp#example-138

                      Zitat von Daniel Beitrag anzeigen
                      Nicht nur. Es gibt ja mittlerweile in PHP (ab 5.3.0 soweit ich weiß) auch "Funktionen höherer Ordnung", die als Parameter eine Callback-Funktion übergeben bekommen.
                      "Anonyme" Funktionen gibts in PHP schon seit Ewigkeiten (Version 4.01 per create_function() ...). Die sind nicht höherer Ordnung und wie alle anderen Funktionen auch keine first class datatypes. Auch hält das Callback-Gewürge keinem ernsthaften Vergleich mit vernünftiger designeten Script-Sprachen stand.

                      Die oben erwähnten "Closures" seit PHP 5.3.0 sind ein netter Hack, aber innen drin steckt da nur ein Object einer speziellen Klasse, dessen magische __invoke()-Methode aufgerufen wird. Einzig die Deklaration einer solchen Funktion fügt sich besser in den Quellcode ein, als das mit create_function() möglich war.

                      Das flexible "Einfangen der Variablen" ist aber recht elegant gelöst, wenn auch im Handbuch nirgends vernünftig dokumentiert. Wahrscheinlich traut man dem durchschnittlichen PHP-Hacker nicht zu, dass er das Konzept von Closures versteht ...

                      Beispiele sind die (mir) aus Scheme (ein Lisp-Dialekt) bekannten Funktionen fold, map und filter. (fold heißt in PHP glaube ich etwas anderes, ich glaube array_reduce).

                      Man auch Lambda Funktionen nutzen, oder eben speziell dafür definierte Funktionen. Beispiele findet man auf den Manual-Pages der entsprechenden Funktionen, beispielsweise hier für array_map
                      Die PHP-Versionen der Funktionen höherer Ordnung sind array_map(), array_filter(), (in einem gewissen Sinn) preg_grep() und array_reduce(). Sie arbeiten nur auf PHP-Arrays, aber nicht auf anderen "iterierbaren" Objekten. Außerdem sehen sie nur die Array-Values und nicht die -Keys. Daher sind sie nur eingeschränkt zu gebrauchen. Die Filter-Iteratoren bieten ansatzweise etwas Brauchbares im PHP-OOP-Stil.

                      Fold() ist eine spezielle Form von reduce(). In der Praxis werden beide Namen aber meist synonym verwendet. Und PHP kann auch nur in eine Richtung falten|reduzieren. Andere (weniger bekannte) Higher-Order-Functions wie zip() fehlen ganz.
                      Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

                      Kommentar


                      • #12
                        Zitat von fireweasel Beitrag anzeigen
                        Einzig die Deklaration einer solchen Funktion fügt sich besser in den Quellcode ein, als das mit create_function() möglich war.
                        Sie sind auch himmelweit effizienter. create_function ist in Schleifen richtig richtig richtig übel.

                        (Es gab dazu irgendwo eine bessere Erklärung, die finde ich nur gerade nicht. Aber die grundsätzliche Aussage lautet: Jeder Aufruf von create_function erzeugt eine neue globale Funktion, die nicht wieder entfernt werden kann.)

                        Kommentar


                        • #13
                          Lässt sich übrigens leicht nachvollziehen:

                          PHP-Code:
                          $f create_function('','');
                          var_dump($f); 
                          Ausgabe:
                          Code:
                          string(9) " lambda_1"
                          Das erste Zeichen ist ein Null-Byte (ich glaube vor PHP 5.3 kam stattdessen so etwas wie created_function123456 heraus), man könnte sie also unter dem Namen nicht normal deklarieren und es ist etwas schwierig, die erstellte Funktion direkt aufzurufen aber es bleibt eine ganz normale Funktion, die zur Laufzeit geparst wurde und in der Variable steht lediglich der Name.
                          [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
                          [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

                          Kommentar


                          • #14
                            Zitat von mermshaus Beitrag anzeigen
                            Sie sind auch himmelweit effizienter. create_function ist in Schleifen richtig richtig richtig übel.
                            (Es gab dazu irgendwo eine bessere Erklärung, die finde ich nur gerade nicht. Aber die grundsätzliche Aussage lautet: Jeder Aufruf von create_function erzeugt eine neue globale Funktion, die nicht wieder entfernt werden kann.)
                            Das ständige Erzeugen einer neuen Funktion lässt sich vermeiden[1]. Man muss halt wissen, wie die "Werkzeuge" funktionieren, die man einsetzt. Und was eine Funktionsdeklaration macht.

                            Mit create_function() erzeugte Funktionen dürften zur Laufzeit schneller sein, weil nur eine Hash-Table-Abfrage zu bewältigen ist (in der globalen Funktionstabelle). Dagegen wird beim Aufruf von PHP-"Closures" die __invoke()-Methode des "versteckten" Closure-Objektes auf ihre Existenz abgefragt und aufgerufen. Gemessen habe ich das aber noch nicht. Wer auf solche Feinheiten Rücksicht nehmen muss, sollte das besser tun, am Ende erweist es sich vielleicht als unnötige Mikro-Optimierung.

                            Zitat von fab Beitrag anzeigen
                            ...

                            Das erste Zeichen ist ein Null-Byte (ich glaube vor PHP 5.3 kam stattdessen so etwas wie created_function123456 heraus), ...
                            Das mit dem führenden Zero-Byte war schon in PHP 4 so. Dieser Trick scheint den PHP-Machern bis heute zu gefallen, deswegen wenden sie ihn bspw. auch bei Objekt-Properties an.

                            ... man könnte sie also unter dem Namen nicht normal deklarieren und es ist etwas schwierig, die erstellte Funktion direkt aufzurufen aber es bleibt eine ganz normale Funktion, die zur Laufzeit geparst wurde und in der Variable steht lediglich der Name.
                            Deklariert wurden sie mit create_function(). Der Aufruf wurde absichtlich so verdongelt, dass nur "variable functions" oder die die diversen "call_user...()"-Funktionen möglich waren. Sobald eine Funktion einen Namen hat, ist sie ja nicht mehr anonym.

                            --
                            [1] Sieht aber, zugegeben, meist nicht besonders elegant aus.
                            Wenn man die Wurst schräg anschneidet, hält sie länger, weil die Scheiben größer sind.

                            Kommentar

                            Lädt...
                            X