За последние 24 часа нас посетили 172102 программиста и 2006 роботов. Сейчас ищут 1244 программиста ...

Тернарые ? операторы : perl ? python : ruby ? php : wtf?;

Тема в разделе "Прочие вопросы по PHP", создана пользователем TheShock, 15 июн 2009.

  1. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Тернарые ? операторы : perl ? python : ruby ? php : wtf?;
    Код (Text):
    1.  
    2. shock@shock:~$ perl -e "print 1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9"
    3. 2
    4. shock@shock:~$ python -c "print 2 if 1 else 4 if 3 else 6 if 5 else 8 if 7 else 9"
    5. 2
    6. shock@shock:~$ ruby -e "print 1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9"
    7. 2
    8. shock@shock:~$ php -r "echo 1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9;"
    9. 8
    10. shock@shock:~$ WTF ?
    11. bash: WTF?: команда не найдена
    PS. Java, C++ тоже вернули бы 2.
     
  2. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    В чем причина? Возможно, оно работает так:

    PHP:
    1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9 =>
    (((1 ? 2 : 3) ? 4 : 5) ? 6 : 7) ? 8 : 9 =>
    true ? 8 : 9 =>
    8

    Другие языки:

    Мое предположение:
    1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9 =>
    1 ? 2 : (3 ? 4 : 5 ? 6 : 7 ? 8 : 9) =>
    2

    Предположение Xenius'a (наверное, более верное)
    1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9 =>
    1 ? 2 : 3 ? 4 : 5 ? 6 : (7 ? 8 : 9 == 8) =>
    1 ? 2 : 3 ? 4 : (5 ? 6 : 8 == 6 ) =>
    1 ? 2 : (3 ? 4 : 6 == 4) =>
    1 ? 2 : 4 =>
    2
     
  3. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Зачем это чудо надо?

    PHP:
    1. <?
    2. $var =  empty($a)   ? 'а должно быть числом' :
    3.             empty($b)   ? 'б должно быть числом' :
    4.             ($a < $b)   ? 'а - больше' :
    5.             ($a > $b)   ? 'б - больше' :
    6.                 'Они равны';
    7.  
    Пример, конечно, очень надуманный, но это очень помогает быстро, легко и красиво задать разные значения переменной зависимо от условий и дефолтное значение, если все условия не соблюдены.

    другой пример:

    PHP:
    1. <?
    2.  
    3. // С помощью тернарного оператора
    4. public function getSomething ($type = null) {
    5.  return
    6.  ($type === self::TYPE1) ? 'first value' :
    7.  ($type === self::TYPE2) ? 'second value' :
    8.  ($type === self::TYPE3) ? 'third value' :
    9.        'default value';
    10. }
    11.  
    12. // С помощью if-else
    13. public function getSomething ($type = null) {
    14.  if ($type === self::TYPE1) {
    15.   return 'first value';
    16.  } else if ($type === self::TYPE2) {
    17.   return 'second value';
    18.  } else if ($type === self::TYPE3) {
    19.   return 'third value';
    20.  } else {
    21.   return 'default value';
    22.  }
    23. }
    24.  
    25. // С помощью case-switch
    26. public function getSomething ($type = null) {
    27.  switch ($type) {
    28.   case self::TYPE1 :
    29.    return 'first value';
    30.    break;
    31.   case self::TYPE2 :
    32.    return 'second value';
    33.    break;
    34.   case self::TYPE3 :
    35.    return 'third value';
    36.    break;
    37.   default :
    38.    return 'default value';
    39.  }
    40. }
    41.  
     
  4. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Задам вопрос на засыпку: а зачем оно надо?
    Прошу дать адекватный обоснованный ответ, после которого я бы смог высказаться положительно об этой неудобночитаемой конструкции.
    Такой стиль написания кода называется неуважением к своему и чужому времени и совершенно бесполезен.
    Почему альтернативные управляющие инструкции менее распространены:

    PHP:
    1. <?
    2.  
    3. if($a > $b):
    4.     echo 'Yeah';
    5. endif;
    6.  
    7. ?>
    Да потому что при наличии более удобной альтернативы - фигурных группирующих скобок - эти конструкции отходят на второй план, а тернарный оператор вообще стилистически имеет ограниченное применение: только для проверки кратких условий, когда его использование ОБОСНОВАННО и приводит к более красивой группировке, нежели безосновательное использование if (пример я уже давал в другой теме).
     
  5. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Apple, добавил второй пример в третьем посте. Согласен. Чаще намного лучше использовать стандартный иф-элс, или свитч. Но изредка бывает более удобно и красиво использовать тернарный оператор.
     
  6. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Но все-равно. Крайне обидно, что вполне распространенный, удобный и используемый оператор имеет такую недоработку в пыхе. с Си ведь старались скопировать, наверное, а получилось совершенно иначе чем во всех остальных языках
     
  7. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    К примеру выше добавлю свой пример:

    PHP:
    1. <?
    2.  
    3. class ABC
    4. {
    5.     const TYPE_1 = "int";
    6.     const TYPE_2 = "string";
    7.     const TYPE_3 = "double";
    8.    
    9.     protected $types = array();
    10.    
    11.    
    12.     public function __construct()
    13.     {
    14.         $types = array(TYPE_1, TYPE_2, TYPE_3);
    15.     }
    16.    
    17.     public function getSomething($type = null)
    18.     {
    19.         if(($type = array_search($type, $this->types)) !== false)
    20.             return $this->types[$type];
    21.        
    22.         return false;
    23.     }
    24. }
    25.  
    26. ?>
    В результате имеем:

    PHP:
    1. <?php
    2.  
    3.     public function getSomething($type = null)
    4.     {
    5.         if(($type = array_search($type, $this->types)) !== false)
    6.             return $this->types[$type];
    7.        
    8.         return false;
    9.     }
    10.  
    11. ?>
    12.  
    это по теме надуманности.
    Никаких if-else или switch-case.
     
  8. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    я думаю, его вполне можно сократить до
    PHP:
    1. <?
    2. public function getSomething($type = null) {
    3.     return array_search($type, $this->types))
    4. }
    и я думал, что к константам класса можно обращатся только через "селф::ИМЯ_КОНСТАНТЫ"

    А по поводу примера. Код с тернарным оператором, я подозреваю, быстрее. Тем более, способом с array_search нельзя будет сделать чтото типа:
    PHP:
    1. <?
    2. public function getSomething ($type = null) {
    3.  return
    4.  ($type === self::TYPE1) ? $this->method() :
    5.  ($type === self::TYPE2) ? $this->prop :
    6.  ($type === self::TYPE3) ? self::CONST1 :
    7.       'default value';
    8. }
     
  9. Jensi

    Jensi Активный пользователь

    С нами с:
    9 апр 2009
    Сообщения:
    299
    Симпатии:
    0
    Тернарные операторы удобно проверять при более маленьких кодах, ибо если идёт куча проверок, то действительно можно запутаться с тернарным оператором:) А при проверках на истину/ложь, проверках значения в переменных можно и нужно использовать тернарный оператор.
    Это только моё мнение и всё
     
  10. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    тем более в способе с константами-строками легче не вызывать метод, а обращатся сразу к константам:
    PHP:
    1. <?php
    2. echo ABC::TYPE_1;
    3. // Вместо
    4. $abc = new ABC;
    5. echo $abc->getSomething(ABC::TYPE_1);
    Потому данный пример делает совершенно иное, чем любой из методов getSomething в третьем посте.
     
  11. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Jensi, а ты запутался в тернарном операторе в методе getSomething ?
     
  12. Jensi

    Jensi Активный пользователь

    С нами с:
    9 апр 2009
    Сообщения:
    299
    Симпатии:
    0
    Простите, ООП не учил( немного пробовал и получалось ), ибо не понимаю зачем оно нужно мне на данный момент. Пока буду просто следить за темой:)
    По мне уже как-то пофиг как читать маленький код, мнение отписал своё выше
     
  13. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Если я не ошибаюсь, то подобный вопрос есть в ZCE exam и где-то я статью видел про это...
     
  14. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    что за проблемы?
    PHP:
    1. <?
    2. $var=empty($a)?"a empty":(empty($b)?"b empty":($a<$b?"a < b":($a!==$b?"a > b ":"a = b")));
    3. ?>
     
  15. Kreker

    Kreker Старожил

    С нами с:
    8 апр 2007
    Сообщения:
    5.433
    Симпатии:
    0
    Создай выражение с тернарными операторами, которое компьютер будет выполнять сутки и ты прославишься на весь мир как дол///
     
  16. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    Kreker, подобный вопрос - это какой? А ссылку можно, плз?
    Mr.M.I.T., извини, но... нечитабельно
     
  17. Кстати да, по идее, ? и : имеют равный приоритет и левую ассоциативность, поэтому должны разобратся в 2.
    Но, увы )
    Хотя, в пхп есть баги и пострашней.