rstoll;11021601 wrote:

Since not everyone get the same questions (depending on the answers given) I would like to know, which kind of questions you are talking about?

Hopefully I can explain 🙂

After I was asked ("does knowing about this change your thoughts"), [around #9 or #10, I think], I was then asked the exact same questions; six or seven of them, I think. As I hadn't changed my mind, I didn't see the point in being asked the same questions again. Perhaps I didn't understand something I clicked, and it went back and began again?

    oh no... that's exactly not what I wanted 🙁 Those questions should have been skipped when you choose no your opinion hasn't changed.
    Thank you for your hint.

      dalecosp;11021645 wrote:

      Hopefully I can explain 🙂

      After I was asked ("does knowing about this change your thoughts"), [around #9 or #10, I think], I was then asked the exact same questions; six or seven of them, I think. As I hadn't changed my mind, I didn't see the point in being asked the same questions again. Perhaps I didn't understand something I clicked, and it went back and began again?

      hm... I just tested it, probably you have used the back button, since I do not get the same questions again, if I choose no for the question: "Would you have answered the previous questions differently if you had had the above information?"

        Well ... the problem with that theory is that the question numbers continued to increment as expected. :eek:

          Ah... I see. That's true, unfortunatley that's how the survey web application is implemented. But I can activate a page number in addition next to the question numbers (already done now). This way it is more obvious that some questions have been skipped. Thank you for your hint. I think that's helpfull for the participants.

            I tried to take your survey several times, but it kept restarting at random points. I got about halfway through.

            I think many of the examples you give are over-simplified: you often ask "if x should be done to improve type safety" - but you don't necessarily explain how x will be implemented.

            For example,

            public function whatever( string $str ){ /*...*/ }

            What does [font=monospace]string[/font] do?

            ...Does it throw an exception if [font=monospace]$str[/font] is not a string (which could come to pass under any number of coincidences in a loosely typed language like PHP)?

            ...Does it cast [font=monospace]$str[/font] to a string?

            ...Does it cast [font=monospace]$str[/font] to a string, but only if [font=monospace]$str == (string)$str[/font]?
            (...BTW, this is the answer I would have chosen)

            ...What about
            [indent]

            public function whatever( string $str="default" ){ /*...*/ }

            Is [font=monospace]$str[/font] given the value "default" if it is not a string?
            Or only if it is not provided?[/indent]

            On several questions, I found it difficult to choose an accurate/meaningful answer because of ambiguities like these.


            Regarding templates, I think the best (simplest, most obvious) solution would be to create a template object and pass (or [font=monospace]use[/font]?) the desired variables directly to it.


            Dynamic typing is a benefit, not a shortcoming. Full type safety would completely break many PHP applications. I'm not advocating that backwards-compatibility should be the deciding factor, and while a measure of type safety (or perhaps type hinting and stricter control over type coercion is what I really mean) would be beneficial, it could also lead to unnecessarily complex code.

            As an example, [font=monospace]$GET[/font] and [font=monospace]$POST[/font] are always initially strings - do you intend to initially cast them to a "best fit" type? According to what rules? Or would one be forced to write constructs like

            function whatever( int $int ){ /*...*/ }
            $result = whatever( ((integer)$_GET['userInt']) );

            ?

              traq;11021687 wrote:

              ...Does it cast [font=monospace]$str[/font] to a string, but only if [font=monospace]$str == (string)$str[/font]?
              (...BTW, this is the answer I would have chosen)

              As I would have also chosen.

                Derokorian;11021691 wrote:

                As I would have also chosen.

                Have you read this (I don't remember where I was pointed to this; it may have even been here (on phpbuilder), so my apologies if we've already had this discussion)?

                  traq;11021687 wrote:

                  I think many of the examples you give are over-simplified: you often ask "if x should be done to improve type safety" - but you don't necessarily explain how x will be implemented.

                  Fair enough. I see what you mean and I see, that it is difficult to choose an option if one think about it as you have done. I have explicitly left out any implementation, since the survey would be even longer with it and honestly, I think now that it is already too long, I should have shorten the survey a little bit. First of all I have thought about implementing a very strict model which would have needed an explicit casting. For instance a method call would have been

                  int $a = 1;foo( (string) $a);

                  However, I have made some speed tests and have realised, that explicit casting is slower in PHP than the PHP intern casting. For instance:

                  $a = 1; 
                  $b = (int) "1"; 
                  $c = $a + $b;

                  is slower than

                  $a = 1; 
                  $b = "1";
                   $c = $a + $b;

                  Therefore I am not yet sure how I am going to implement it.

                  traq;11021687 wrote:

                  ...Does it cast $str to a string, but only if $str == (string)$str?
                  (...BTW, this is the answer I would have chosen)

                  I am not sure if I really get what you mean. Take your example with an integer. For instance:

                  function foo(int $i){
                    echo $i;
                  }
                  $a = "a";
                  foo($a); //output = 0 since $a == (int) $a;
                  

                  Is this really what you want? Or would your behaviour only be applied to strings?

                  traq;11021687 wrote:

                  Regarding templates, I think the best (simplest, most obvious) solution would be to create a template object and pass (or [font=monospace]use[/font]?) the desired variables directly to it.

                  I agree, that would be the simplest way, but I believe developers are still heavely relying on templates (including other files). I mean, it is already possible to use objects instead of including files (needless to say that classes will also be included at a certain point) but one like including files without context more than defining classes and using them. I undestand them, since including files is quite convenient.

                  traq;11021687 wrote:

                  Dynamic typing is a benefit, not a shortcoming. Full type safety would completely break many PHP applications. I'm not advocating that backwards-compatibility should be the deciding factor, and while a measure of type safety (or perhaps type hinting and stricter control over type coercion is what I really mean) would be beneficial, it could also lead to unnecessarily complex code.

                  I absolutely agree. Type-safe code leeds often to more complex code than unsafe code. I think one good point in my approach is, that I introduce TSPHP at a higher level. PHP is still available as it is now and for certain web applications it is more appropriate to use PHP rather than TSPHP. And since TSPHP is translated into PHP one can develop his component in TSPHP and another one show use PHP can use the component (unfortunatley not the other way round - but if TSPHP is usefull as I expect it to be then I will probably also develop a type inference system which transforms PHP into TSPHP as far as possible). However, especially bigger projects which underlies many changes (over the years) are quite painfull to maintain, because refactorings for PHP is poorly supported by IDEs and quite error prone. If you have done ones a refactoring in type-safe languages you exactly now what I mean. And in my opinion refactoring is very essential to keep your code quality high over the years and changes.

                  traq;11021687 wrote:

                  As an example, [font=monospace]$GET[/font] and [font=monospace]$POST[/font] are always initially strings - do you intend to initially cast them to a "best fit" type? According to what rules? Or would one be forced to write constructs like

                  function whatever( int $int ){ /*...*/ }
                  $result = whatever( ((integer)$_GET['userInt']) );

                  ?

                  Well, as said above, first of all I intended to implement a very strict model, but now I guess I will accept some operator overloadings. For instance

                  string $b="1";
                   int $a = 1 + $b;
                  

                  will be valid, since + automatically casts strings to integers. However, I am not yet sure how I will implement it for parameters. I was thinking about a strict model (thus (integer)$_GET['userInt']; whould be necessary) but with the option of an automatic casting. Anyway, I haven't made final decision yet.

                    rstoll;11021699 wrote:
                    $a = 1; 
                    $b = (int) "1"; 
                    $c = $a + $b;

                    is slower than

                    $a = 1; 
                    $b = "1";
                     $c = $a + $b;

                    I have to correct myself. Explicit casting is as fast as implicit casting.
                    Nevertheless, I will support operator overloading as mentioned and I will be strict on parameters but with the possibility to activate automatic casting.

                    traq;11021693 wrote:

                    Have you read this

                    The syntax for the automatic casting could therefore be

                    function foo((int) $i){}

                    but maybe also something more obvious as

                    function foo(cast int $i)
                      rstoll;11021699 wrote:

                      I am not sure if I really get what you mean. Take your example with an integer. For instance:

                      function foo(int $i){
                        echo $i;
                      }
                      $a = "a";
                      foo($a); //output = 0 since $a == (int) $a;
                      

                      Is this really what you want? Or would your behaviour only be applied to strings?

                      What I would expect is that since $a != (int) $a that this usage would not produce 0 but instead produce a Fatal error, much like that which would result from the following:

                      function TrimPost(BlogPost $post) {
                         $post['body'] = substr($post['body'], 0, 200);
                         return $post;
                      }
                      $a = new User();
                      TrimPost($a);
                      // Catchable fatal error: Argument 1 passed to TrimPost() must be an instance of BlogPost, instance of User given, called in /path/to/file.php on line ## and defined in /path/to/file.php on line ##
                      

                        I, too, tried to keep backwards compatibility in mind for every answer I gave on the survey.

                        One of my ideas was to by default make type violations an E_NOTICE/E_WARNING level error but to also add an option to error_reporting that would elevate these to catchable fatal errors.

                        EDIT: I should add... I came up with this idea without thinking of the approach Derokorian described (and/or what was described on the page traq linked to in post #12). I'm still on the fence as to which way I like better.

                          Derokorian;11021707 wrote:

                          What I would expect is that since $a != (int) $a that this usage would not produce 0 but instead produce a Fatal error

                          Right:

                          function intOnly( int $int ){}
                          intOnly( "a" );
                          /*
                          (int)"a" = 0
                          "a" != 0
                          throw error
                          */
                          intOnly( "1" );
                          /*
                          (int)"1" = 1
                          1 == 1
                          okay
                          */
                          # intOnly( "1thing" ); # strike that. better example:
                          intOnly( true );
                          /*
                          (int)true = 1
                          ...?
                          yeah... that's where it gets muddy.
                          */
                          bradgrafelman;11021711 wrote:

                          One of my ideas was to by default make type violations an E_NOTICE/E_WARNING level error but to also add an option to error_reporting that would elevate these to catchable fatal errors.

                          Hadn't thought of that. Good possibility.

                            As far as I'm concerned, if you specify...

                            function foo(boolean $bar) { ... }
                            

                            ...and call it as...

                            foo(1);
                            

                            ...it should throw an exception, just as it would if you type-hinted with "Array" or any class name. Automatically converting it to the desired type would not be "type safety", to my mind.

                            However, note any such implementation would now mean you could not call any of your classes "boolean" or any other implemented type names (which may already be reserved words?), or if you did, you could not use that class's name as a type-hint any more -- not that I'd generally want to call any of my classes that, but I suppose you could define classes to represent different data types as a way to implement type safety, by allowing you to type-hint with those class names?

                            Oh well, guess I'm just glad I've never really had an issue with PHP's loose typing (or whatever it's technically called?).

                              NogDog;11021795 wrote:

                              As far as I'm concerned, if you specify...

                              function foo(boolean $bar) { ... }
                              

                              ...and call it as...

                              foo(1);
                              

                              ...it should throw an exception, just as it would if you type-hinted with "Array" or any class name. Automatically converting it to the desired type would not be "type safety", to my mind.

                              Agreed - just a little muddy, since (for example) 1 and 0 are so synonymous with TRUE and FALSE.
                              But where would you draw the line? Should "5" (a string) fail where an integer is required?

                                traq;11021799 wrote:

                                Agreed - just a little muddy, since (for example) 1 and 0 are so synonymous with TRUE and FALSE.
                                But where would you draw the line? Should "5" (a string) fail where an integer is required?

                                In my mind, yes, since type-hinting means you only want to accept parameters of the specified type. If, instead, you want the normal loose typing, then simply do not type-hint for it (or embed your own type-checking/-swapping mechanism at the beginning of the function definition if you want something in between strict type-checking and no type-checking). But like I said, I'm not going to loose any sleep over it for now. 🙂

                                Hmm...now I'm imagining a class full of methods for various sorts of type-checking...darn you all, I have other things that need doing!

                                function enforceInteger(&$value)
                                {
                                    if(is_int($value)) {
                                        return true;
                                    }
                                    elseif((int)$value == $value) {
                                        $value = (int) $value;
                                        return true;
                                    }
                                    throw new TypeException("Not an integer");
                                }
                                

                                🆒

                                  traq;11021799 wrote:

                                  But where would you draw the line? Should "5" (a string) fail where an integer is required?

                                  IMHO, yes, because:

                                  gettype("5") != gettype(5)

                                  .

                                  Otherwise, why not consider the character 'a' to be an integer? Any C program would be happy to evaluate:

                                  ('a' == 97)

                                  as TRUE.

                                    Derokorian;11021707 wrote:

                                    What I would expect is that since $a != (int) $a that this usage would not produce 0 but instead produce a Fatal error.

                                    Well, if

                                    $a = "a";

                                    then

                                    $a == (int) $a 

                                    evaluates to true because the == does make a weak comparision and thus $a would be castet to a int before it is compared against (int) $a and consequentely $a and (int) $a are the same.

                                    but $a !== (int) $a. But if you compare it with === then it would be the same as having a strict type-safety as described by NogDog (what in my opinion makes absolutely sense).

                                    Maybe it would be nice if a developer can decide on his own if he wants an auto casting or not. Maybe with a construct like this:

                                    function foo (cast int $a){ //cast $a to int if $a isn't a int
                                    //...
                                    }
                                    function bar(int $a){ // does not cast $a to int and therefore would throw a fatal error if a string is given
                                    //...
                                    }
                                    

                                    if someone would call foo with an object then also a fatal error would be thrown, since an object cannot be castet to int

                                      rstoll;11021905 wrote:

                                      Well, if

                                      $a = "a";

                                      then

                                      $a == (int) $a 

                                      evaluates to true because the == does make a weak comparision and thus $a would be castet to a int before it is compared against (int) $a and consequentely $a and (int) $a are the same.

                                      yeah... it'd have to be implemented some other way.

                                      rstoll;11021905 wrote:

                                      Maybe it would be nice if a developer can decide on his own if he wants an auto casting or not.

                                      I'd thought about that. I was considering using

                                      function foo( (int)$a ){ /* cast $a if necessary */ }
                                      function bar( int $a ){ /* no casting; strict equality only */ }

                                      seems more intuitive to me.


                                      To answer bradgrafelman and NogDog,

                                      I agree that casting "if equivalent" wouldn't actually work very well, and that, if you ask for a particular type you should expect the comparison to be strict. The only examples where I'm hesitant (that I can think of) is 1/0 vs. TRUE/FALSE and numeric strings vs. integers.

                                        rstoll;11021905 wrote:

                                        ...

                                        function foo (cast int $a){ //cast $a to int if $a isn't a int
                                        //...
                                        }
                                        

                                        I do kind of like that, in that it makes it obvious what's happening just from the function prototype, regardless of what any comments or lack of comments may say. 🙂