Yhdessä toisessa ketjussa nousi esille linkki PHP:n omituisuuksiin ja innostuin vähän niitä lueskelemaan ja laitoinkin heti kirjanmerkiksi, että osaan vastaisuudessa PHP:llä koodatessa ottaa näitä paremmin huomioon. Tiesin kyllä, että PHP sisältää monia melko omituisia ratkaisuja, mutten ole ennen niihin paljoakaan perehtynyt. Olen vain tyytyväisenä koodaillut PHP:llä perehtymättä yhtään sen omituisuuksiin aina niin kauan kunnes olen niihin yksi kerrallaan törmäillyt ja menettänyt yöuniani niiden kanssa. :)
Noh, tuolla linkin takana tuli esiin seuraava tilanne:
lainaus:
Unlike (literally!) every other language with a similar operator, ?: is left associative. So this:
$arg = 'T'; $vehicle = ( ( $arg == 'B' ) ? 'bus' : ( $arg == 'A' ) ? 'airplane' : ( $arg == 'T' ) ? 'train' : ( $arg == 'C' ) ? 'car' : ( $arg == 'H' ) ? 'horse' : 'feet' ); echo $vehicle;prints horse.
Termien tuntemukseni ja suomentamiseni on hiukan hataraa, joten onko ensimmäinen lause kutakuinkin "toisin kuin muissa kielissä, PHP:ssä ?: -operaattori on vasemma(lta/lle) assosiatiivinen" vai "toisin kuin muissa kielissä, joissa ?: -operaattori on vasemma(lta/lle) assosiatiivinen"? Ja tarkoittaako assosiatiivisyys siis sitä, että mihin suuntaan koodia luetaan? Eli luetaanko muissa kielissä koodia vasemmalta oikealla ja PHP:ssä oikealta vasemmalle vai toisin päin?
En millään onnistunut saamaan $vehicle:n arvoksi horse vaikka mistä suunnasta koetin tilannetta hahmottaa. Voisiko joku siis vääntää minulle rautalangasta tätä PHP:n toimintaa tällaisessa tilanteessa, että miten ihmeessä tuossa päädyttiin noin outoon tulokseen.
En nyt tajunnu mikä sulla oli ongelmana, mutta Horsehan sieltä tuli kaikilla arvoilla.
Sulla on liian vähän sulkuja. Tällä toimii:
$arg ="A"; // prints airplane $vehicle = ( ( $arg == 'B' ) ? 'bus' : (( $arg == 'A' ) ? 'airplane' : (( $arg == 'T' ) ? 'train' : (( $arg == 'C' ) ? 'car' : (( $arg == 'H' ) ? 'horse' : 'feet')))) ); echo $vehicle;
Silti, itse käyttäisin tässä tapauksessa if elsejä tai casea ihan selvyyden vuoksi.
Juu, mutta kysymys ei nyt ollut miten saisin tuon toimimaan, vaan miksi PHP tulkitsee tuon väärin. Tai jos nyt ei väärin niin ainakin jotenkin epäloogisesti.
AkeMake kirjoitti:
En millään onnistunut saamaan $vehicle:n arvoksi horse vaikka mistä suunnasta koetin tilannetta hahmottaa.
auttaisiko jos antaisit $arg arvoksi 'H'?? Hyvin vaikutti toimivan..
Edit.
Lebe80 kirjoitti:
mutta Horsehan sieltä tuli kaikilla arvoilla.
Kappas vaan.. näinhän näyttäsi tulevan.. Olin hidas, ja kaikenlisäksi en kunnolla edes testannut.. :) pöh. .
Pentu kirjoitti:
AkeMake kirjoitti:
En millään onnistunut saamaan $vehicle:n arvoksi horse vaikka mistä suunnasta koetin tilannetta hahmottaa.
auttaisiko jos antaisit $arg arvoksi 'H'?? Hyvin vaikutti toimivan..
Tarkoitin siis kommentillani, etten millään ymmärrä miten PHP tulkitsee tuota koodia eli miten se tuntuu syöttävän siitä aina ulos "horse". Omalla logiikallani tuon pitäisi antaa jotain aivan muuta kuin horsen, mutta silti PHP sen antaa.
Haluaisin siis päästä sisään PHP:n ajatusmaailmaan ja tietää miten PHP onnistuu tulkitsemaan tuosta ulos jotain omille aivoilleni täysin epäloogista.
tämä toimii:
<?php $arg = 'B'; $vehicle = ( $arg == 'B' ) ? 'bus' : (( $arg == 'A' ) ? 'airplane' : (( $arg == 'T' ) ? 'train' : (( $arg == 'C' ) ? 'car' : (( $arg == 'H' ) ? 'horse' : 'feet' )))); echo $vehicle; ?>
Muuta en osaakkaan vastata
Edit
Tuo taitaa mennä niin, että jos tuo sulkeissa oleva on tosi, tulostetaan kaksois pistettä edeltävä merkkijono.. Jos taas tulos oli false, tulostetaan jälkimmäinen.. mutta tässä tapauksessa jälkimmäiseen tulee uusi ehto, jossa vertaillaan $arc muuttujaa, ja seuraavaa merkkiä.. siis if/elseif/..else -rakenne..
Ei ehkä maailman selkein tarinointi, mutta näin itse ymmärtäsin tuon näin amatöörinä ja hetken koodia tarkkaillen.
En edelleenkään kysynyt toimivaa koodia, kiitos vain. Osasin kyllä itsekin muokata tuon toimivaksi.
Mutta kysymykseeni liittyen, juuri noinhan sen pitäisi mennä kuin selititkin. Juuri sen vuoksi en ymmärrä miksi antamani koodi ei tulosta sitä loogisinta tulosta train (tai feet riippuen siitä mistä suunnasta koodia lähdetään tutkimaan).
En tiedä onko oma kysymyksen asetteluni sekavaa vai mistä johtuu, etten nyt saa vastausta siihen alkuperäiseen kysymykseen. Ensimmäinen viestini taisi tosiaan sisältää harhaanjohtavan kysymyksen, mutta jälkimmäisistä viesteistä olisi viimeistään pitänyt ongelma selvitä. Alkuperäinen kysymys ei siis ollut miten saisin koodini tulostamaan "train" vaan, että miksi se antamani koodi tulostaa sen "horse" eikä "train" tai "feet"?
Järjestellään koodi näin:
<?php header('content-type: text/plain; charset=UTF-8'); function kuka($minä, $arvo) { echo 'Kutsuttiin "' . $minä . "\"\n"; return $arvo; } $boolean = kuka('Yksi', 0) ? 1 : kuka('Kaksi', 1) ? 0 : kuka('Kolme', 0) ? 'True' : 'False'; print_r($boolean); echo "\n\n"; $boolean = kuka('Yksi', 0) ? 1 : kuka('Kaksi', 1) ? 1 : kuka('Kolme', 0) ? 'True' : 'False'; print_r($boolean);
Lopputulos:
Kutsuttiin "Yksi" Kutsuttiin "Kaksi" False Kutsuttiin "Yksi" Kutsuttiin "Kaksi" True
Eli se ehto joka on ensimmäisenä true siirtää oman totuusehtonsa arvon booleaniksi viimeisimmälle ehdolle. Eli jos mistä tahansa kysymysmerkkiä edeltävästä ehdosta tulee true, niin kysymysmerkin jälkeinen ensimmäisen arvo määrittää sen, mikä on viimeisen kysymysmerkin ehto.
Nyt päästiin asiaan. Kiitos, Merri. Antamasi esimerkki oli todella valaiseva, mutta tarkistan silti, että ymmärsin varmasti oikein. Edetäänkö siis tuossa antamassani esimerkissä kutakuinkin seuraavasti:
Tutkitaan $arg == 'B', joka antaa falsen. Seuraavaksi tutkitaan $arg == 'A', joka myöskin antaa falsen. Nyt tutkitaan $arg == 'T', josta tulee true eli $vehicle olisi tässä vaiheessa 'train'. Lopuksi otetaan kuitenkin vielä kerta kiellon päälle ja mennään tutkimaan viimeinen ehto, mutta siinä ei tutkitakaan $arg == 'H' vaan juuri saatu 'train', joka siis vastaa boolean-arvoa true. Tämän vuoksi viimeinen ehto ei olekaan false vaan true ja palautetaankin 'train' sijasta 'horse'.
Kuulostaa ihan selkeältä virheeltä, ettei totuusehtojen tutkiminen pääty ensimmäiseen true kohtaan. Eihän tuo tarkoituksellista ainakaan voi olla?
Jep, oikein meni. Ja kyllä, PHP:n logiikka tuolta osin on ihan päin honkia.
Eihän se ole kuin määrittelykysymys, miten "villit" lausekkeet pitää evaluoida. Php:n kehittäjät päättivät heittää kolikkoa kaikessa ymmärtämättömyydessään ja valitsivat kahdesta mahdollisesta sen epäintuitiivisen tavan. (Epäintuitiivinen koska kaikki muut ovat valinneet juuri toisin.)
Assosiatiivisuus tarkoittaa käytännössä laskujärjestystä eli sitä, mihin kohti voi lisätä sulut muuttamatta lausekkeen merkitystä.
Merrin testi on hieno mutta mielestäni turhan mutkikas, kun laskujärjestyksen voi todeta näin helposti:
<?php echo 1 ? 2 : 3 ? 4 : 5 , "\n"; // 4 echo (1 ? 2 : 3) ? 4 : 5 , "\n"; // 4 echo 1 ? 2 : (3 ? 4 : 5), "\n"; // 2
Testistä nähdään, että jos ensimmäinen osa sulutetaan, tulos pysyy samana, ja jos toinen osa sulutetaan, tulos muuttuu. Siis ?:-operaattorit suoritetaan PHP:ssä vasemmalta alkaen eli jälkimmäisen ?:-operaattorin ehtona on koko ensimmäinen ?:-lauseke. Siis ensin suoritetaan 1?2:3, josta tulee 2, ja sitten suoritetaan 2?4:5, josta tulee 4.
Aihe on jo aika vanha, joten et voi enää vastata siihen.