2007-10-28

Od komentarzy do poprzedniego posta chodził za mną mały felietonik na temat ?:.
Niby nic wielkiego, operator jak operator.
Weźmy dla przykładu implikację, z fałszu wynika cokolwiek, z prawdy tylko prawda, więc mamy: p -> q i tablekę:
 p | q | wynik
---+---+---
 F | F | T
 F | T | T
 T | F | F
 T | T | T
to dość ładnie nadaje się do użycia ?: - o tak: !p ? true : q ? true : false.
Czasem jednak przywiązujemy większą wagę do jednego pierdolnika, niech będzie nim p, więc zmodyfikujemy kod do takiego: !p ? "Nie P" : q ? "Q" : "Nie Q".
Popatrzmy, jak działa w C/C++ (będzie w ++):
@zlom:~/public_html/felietonik$ cat f.cpp
#include <iostream>
#include <vector>
typedef std::vector<bool> vb;
int main(int argc, char* argv[]) {
    vb a(2);
    a[0] = false;
    a[1] = true;
    for (vb::iterator p(a.begin()), pe(a.end()); p != pe; ++p)
        for (vb::iterator q(a.begin()), qe(a.end()); q != qe; ++q)
            std::cout << "p = " << *p << ", q = " << *q << " "
                << (!*p ? "Nie P" : *q ? "Q" : "Nie Q") << std::endl;
    return 0;
}
@zlom:~/public_html/felietonik$ ./a.out
p = 0, q = 0 Nie P
p = 0, q = 1 Nie P
p = 1, q = 0 Nie Q
p = 1, q = 1 Q
@zlom:~/public_html/felietonik$
Kul, w Javce podobnie:
package pierdy;

public class Felietonik {

    public static void main(String[] args) {
        boolean[] a = {false, true};
        for (int p = 0; p < a.length; ++p)
            for (int q = 0; q < a.length; ++q)
                System.out.printf("p = %5s, q = %5s %s\n"
                    , a[p], a[q], !a[p] ? "Nie P" : a[q] ? "Q" : "Nie Q");
    }
}

p = false, q = false Nie P
p = false, q =  true Nie P
p =  true, q = false Nie Q
p =  true, q =  true Q
Bardzo ładnie.
Perl:
@zlom:~/public_html/felietonik$ perl -e '@a=(0, 1); for $p (@a)\
 {for $q (@a) { print "p = $p, q = $q ", (!$p ? "Nie P" : $q ? "Q" : "Nie Q"), $/ }}'
p = 0, q = 0 Nie P
p = 0, q = 1 Nie P
p = 1, q = 0 Nie Q
p = 1, q = 1 Q
I jeszcze dla porządku JavaScript (w źródle se sprawdźcie, jak chcecie):
Dobra, teraz przechodzimy do klu - PHP:
@zlom:~/public_html/felietonik$ cat f.php
<?
$a = array(false, true);

foreach ($a as $p)
    foreach ($a as $q)
        echo "p = $p, q = $q "
            .(!$p ? 'Nie P' : $q ? 'Q' : 'Nie Q')
            .'<br />';
?>
I wyniki:
p = , q = Q
p = , q = 1 Q
p = 1, q = Nie Q
p = 1, q = 1 Q
Pełna niewiara, co ten frustrat pierdoli.
No to sprawdźcie, na 4.x, na 5.x, who cares.
No ci którym się chciało wzięli i sprawdzili, i rzeczywiście.
Chodzi o to, że w PHP operator ?: jest rozwijany inaczej niż w reszcie świata.
Jakby poustawiać nawiasy, to
!p ? "Nie P" : q ? "Q" : "Nie Q"
jest rozumiany jako
!p ? "Nie P" : ( q ? "Q" : "Nie Q" )
, w PHP inaczej:
( !p ? "Nie P" : q ) ? "Q" : "Nie Q"
- już jarzycie?
W dokumentacji jest wołami napisane, że jak się nie podoba, to nawiasami można wymusić 'normalne' zachowanie.
(jak nie widać, to zaznaczenie załatwi sprawę).

Etykiety: