1. Python / Говнокод #13688

    −92

    1. 1
    a < 5 and a or 5

    Вы все еще думаете, что сочетание and'а и or'а это тернарник? Тогда мы идем к вам :)

    http://ideone.com/qC0TyS

    Запостил: bormand, 28 Августа 2013

    Комментарии (82) RSS

    • Хех, минусуют т.к. все уже знают, что это нихера не тернарник?
      Или минусуют, наоборот, те, кто думает, что я зазря эту конструкцию охаиваю? :)

      Нате вам тогда на закуску говнофикс, по методике со stackoverflow:
      (a < 5 and [a] or [5])[0]
      И люди на полном серьезе предлагают юзать эту хуиту как тернарник... Куда катится мир...
      Ответить
    • О ГОСПАДИ

      http://www.diveintopython.net/power_of_introspection/and_or.html

      Вот откуда эта херня прет!
      Ответить
      • И даже на сайте ibm есть этот хак :)
        http://www.ibm.com/developerworks/linux/library/l-prog/index.html
        Причем тут даже не предупредили про подводный камень.

        А еще они там пропагандируют циклы делать в виде рекурсии... что питону вообще противопоказано, ибо он не умеет в tail-call optimization (намеренно не умеет, чтобы бектрейсы были полные и красивые).
        Ответить
        • хвостовая рекурсия успешно раскручивается в цикл

          Ведь простое лучше сложного)

          Вообще дао у питона очень верное
          Ответить
          • > хвостовая рекурсия успешно раскручивается в цикл
            Ну да. Они эквивалентны. Поэтому некоторые компиляторы, типа gcc умеют превращать хвостовую рекурсию в цикл.

            В питоне так не делают исключительно для красивых бектрейсов. И это, имхо, правильно. Один фиг это не ФЯП, такой как хаскель, в котором рекурсия это основа мироздания, а самый обычный императивный язык.
            Ответить
        • Вроде есть декоратор какой-то для хвостовой рекурсии, а вообще лиспоблядки соснули.
          Ответить
          • Там, если не путаю, брутальный хак, чуть ли не с декомпиляцией кода.
            Уж лучше явно развернуть.
            Ответить
      • все оказалось гораздо хитрее и логичнее
        Ответить
      • мы нашли их рассадник, кидай гранату
        Ответить
        • And i say we take off and nuke the entire site from orbit. It's the only way to be sure.
          http://www.youtube.com/watch?v=a88Z7YOh_us
          Ответить
        • Не, ну по сравнению с викиучебником по php это еще неплохо :)
          Ответить
    • А в чем собственно проблема? Я чет ничего неожиданного не заметил.
      Ответить
      • > А в чем собственно проблема?
        Посмотрите по ссылке на ideone вывод при a = 0.

        > неожиданного
        Ну да, результат вполне ожидаем. Вот только нубы бездумно юзают эту херню как тернарник, и потом неожиданно налетают на этот ожидаемый результат :)
        Ответить
        • Ну это тоже ожидаемо: 0 или 5, при том, что известно, что 0 эквивалентно False...
          Ж.скрипт так же работает, например.
          Ответить
          • Ну ожидаемо, да. Ожидаемо, что это не тернарник, а хреновая попытка его эмулировать ;) Ожидаемо, что эта "абстракция" течет как проржавевшее ведро.

            У тернарника ведь определение: вычисляет левую часть, и возвращает ее результат, если условие истинно; вычисляет правую часть и возвращает ее результат, если условие ложно.

            > Ж.скрипт так же работает, например.
            Угу. На лиспе вроде тоже так можно?

            P.S. В общем суть в чем - не надо рекламировать эту херню, как замену тернарника. А если кто-то и рассказыват нубу об этом хаке - то пускай не поленится рассказать и про подводный камень. В питоне до 2.4 тернарника нет, и точка. А в жс есть нормальный.
            Ответить
            • Нет, в Лиспе все числа = T.
              Ответить
              • > Нет, в Лиспе все числа = T.
                А or и and возвращают сами значения, или настоящие T и nil?

                UPD: Хотя да, там же false это только nil...
                Ответить
                • А кто это предлагал в качестве тернарника? Тут жеж явно нeсовпадение, тернарник не учитывает какой-там результат был у второго выражения.

                  Есть такое понятие, как generalized boolean. Если функция описана, как возвращающая generalized boolean, тогда она может вернуть все, что формально является подклассом T, нe обязательно именно T.
                  Ответить
                  • > А кто это предлагал в качестве тернарника?
                    Питонисты :) В питоне же относительно недавно появился их thenValue if cond else elseValue, вот они и выеживались как могли.
                    Ответить
                    • >относительно недавно
                      >Python 2.5 was released on September 19th 2006
                      Ага, недавно. Видимо, он просто некоторым людям так понравился, что они его юзают, даже не задумываясь о последствиях.
                      Ответить
                  • > формально является подклассом T
                    Кстати, я туплю, или в лиспе все кроме nil является подклассом T?

                    > все, что формально является подклассом T
                    Ну вот в яваскрипте и питоне не совсем так. Там в спеках конкретно указано, что и когда оно возвращает. Т.е. там не какое-попало значение, считающееся true, а именно последний из рассмотренных аргументов and/or. И если бы там была такая свободная формулировка, как вы привели - этот or/and хак бы не родился, или сразу бы сдох как использование UB'а ;)
                    Ответить
                    • Типа того - любой обьект кроме nil возвращает Т
                      Ответить
                      • > возвращает T
                        Наверное все-таки считается T, а не возвращает?
                        Ответить
                    • Если постараться, то можно... например, есть define-symbol-macro, и можно что-нибудь определить как nil... просто чтобы навредить кому-нибудь. Но из практических соображений вряд ли кто-то захочет что-то такое сделать.
                      Ответить
                      • > Но из практических соображений вряд ли кто-то захочет что-то такое сделать.
                        Ну, кстати, пустой список () это же алиас для nil (или наоборот), так что уже умудрились объявить ;)
                        Ответить
                        • Это скорее встроенный reader-macro, но принцип тот же, да.
                          Ответить
                • Зачем в лиспе тернарник? лисп сам как один большой тернарник
                  Ответить
                  • Действительно, там же (if cond thenVal elseVal) :) Туплю сегодня.
                    Ответить
                  • Зачем вообще тернарник? Дети, запомните, тернарник - это сахар. Он не особо и нужен.

                    Если в языке нету короткого паттерн-матчинга, или убогие свитчи(подвид:сишкоблядские), то только тогда полезно .
                    Ответить
                    • Как ни странно сахар - это вкусно. Иногда он сильно упрощает жизнь и читабельность кода. только
                      1 - нужно знать, как сделать тоже самое без сахара
                      2 - понимать что сильно сладко - это к диабету
                      Ответить
                    • Тернарник нужен, чтобы писать функциональненько. А паттерн-матчинг - это сильно функциональная хуйня.
                      Ответить
                    • А что, бывают не сишкоблядские свичи?
                      Ответить
            • del
              Ответить
    • Диллера не сдам.

      for a in range(-10,11):
          print((a < 5 and (lambda: a) or (lambda: 5))())


      http://ideone.com/VArlvi
      Ответить
      • Спасибо, поФЯПал...

        Но все равно какой-то костыль.
        Ответить
        • хитрый план такой хитрый
          Ответить
        • >все равно какой-то костыль.
          Неужели в хацкиле как-то по другому?
          По мне лучше вынести в функцию:
          ter(a < 5 , (lambda: a) , (lambda: 5))

          А всё зло оттого что люди готовы пойти на любое преступление лишь бы чтобы не писать обычный, императивный if или for, ибо так-то скучно, немодно и вообще тупо... Тяга к "умному" коду до добра не доводит.

          Ну и отчасти конструкты не возвращают значения.
          Ответить
          • Тогда уж
            ter(a < 5 , a, 5)
            Ответить
            • Не лениво. Выполняются обе ветки.
              Если конкретный случай, как тут и передается посчитанное значение, то вполне.
              Ответить
              • Не знаю питона, выражаю идею для ленивости:
                ter(a < 5, 'a', '5');
                ter(bool cond, string left, string right)
                    if cond
                        eval('return ' + left)
                    else
                        eval('return ' + right)
                Ответить
                • Строками... ну это что-то совсем из области фантастики ;) Что-то мне подсказывает, что скопы будут корявые. Т.е. переменную a оно будет искать не там где надо, а внутри ter, и благополучно его там не найдет.
                  Ответить
                  • Из области фантастики - зато лениво. Гугление по python eval подсказало, что туда надо передавать какие-то global и local, но фиг его знает. Не даром у меня код обёрнут в гринколор. Да и не только со скопами будут траблы. Сработает ли вообще return внутри eval, и куда вернёт если да.
                    Ответить
                • Отлично, проверку / посветку синтаксиса убиваем совсем (даже по сравнению с тем, что есть). Уж лучше лямбды.
                  Ответить
                  • Вам видимо плохо видно зелёный цвет. Если не дальтоник - то попробуйте что-нибудь с этим сделать.
                    Ответить
                    • А вот мигать код не хочет.
                      Ответить
                      • гирлянду себе купи
                        Ответить
                      • В фаерфоксе походу блинк тоже убили, как и в других браузерах ;( У меня теперь не то что код, а вообще ничего не мигает: тест.
                        Ответить
                        • Люди, кто знает как граватар настроить? на остальных сайтах работает - тут нет
                          Ответить
                          • Проверь, что в кабинке в личных настройках включен граватар.

                            Больше ниче не посоветую, мне граватар не светит. Во-первых домен, на котором висит это мыло, не принимается граватаром. Во-вторых я тупо забыл, на какое мыло тут зарегана учетка ;)
                            Ответить
                            • Теперь показывает, но не тот)
                              Ответить
                              • За несколько минут до этого была собака ;) Может просто подождать пока кеши просрутся?
                                Ответить
                                • У меня и щас собака отображается. Я должен быть гопокот
                                  Ответить
                                  • Кот там, кот. Жди пока кеши обновятся (или почисти сам).
                                    Ответить
          • > Неужели в хацкиле как-то по другому?
            В хацкиле вообще банальный тернарник:
            if cond then thenValue else elseValue
            Ответить
            • В смысле ленивое выполнение, когда надо вычислить кусок кода из лямбды, а не непосредственное значение.
              Ответить
              • А, вон вы о чем. Ну костыль тут в сочетании and/or/lambda, а не в использовании лямбды для лени :) Использование лямбды для лени это вполне нормальная практика, и наверное, вообще единственная для языков кроме лиспа.

                > По мне лучше вынести в функцию
                Если уж писать отдельную функцию, то в ней можно сделать человеческий if:
                def iif(cond, thenF, elseF):
                    if cond then:
                        return thenF
                    else:
                        return elseF
                
                iif(a<5, (lambda : a), (lambda : 5))
                Ответить
                • >то в ней можно сделать человеческий if:
                  Именно. Да можно сделать джве функции: iif и lazyIif.

                  Это то об чем говорилось выше: в языках с довольно развитой системой макросов или способов композиции кода тернарник не нужен вовсе. Поскольку не составит труда сделать свой средствами языка.
                  Ответить
            • python:
              thenValue if cond else elseValue
              Ответить
              • И он мну бесит :(
                Ответить
                • От чего же?
                  Прозрачная запись, никаких хаков. А что еще, если не это?
                  Ответить
                  • if x then y else z
                    Ответить
                  • Это же какая-то вывернутая наизнанку неупорядоченная питушня.
                    Сначала делаем, потом думаем, потом исправляем ошибки, если додумались до false.

                    Просто квантовая интегральная питушня <x|ψ|y> выходит.
                    <then|if|else>
                    Ответить
                    • Дело привычки, не более.
                      Остановись, если прибежал, иначе - беги
                      Если прибежал - остановись, иначе - беги

                      По-сути одно и тоже, только акценты расставлены по другому. Высказывание, где основное действие идет первым (x if y else z), будет понятнее в контексте программы, в том случае, если основное действие это продолжение алгоритма, а проверка условия - цикл или исключение. Так что все зависит от того как программист пишет, как привык писать и читать код. Читаем мы блоками, высказываниями, поэтому такая конструкция просто непривычна для тех, кто долго использует if x then y else z. Это все субъективно.
                      Ответить
                      • Привычка - дело серьёзное.

                        По мне - так тут как-то несимметрично относительно операндов-кандидатов-на-возвращение.
                        Если и использовать такой подход, то красивее он бы смотрелся в математическом смысле в выражениях вида
                        y = x, a<b | y, a>2 | z, a>4 | t, default
                        Ответить
                        • Пожалуй так и есть.
                          y = x if a<b else \
                              y if a>2 else \
                              z if a>4 else \
                              t

                          Это фактически копипаста из статьи "Тернарная условная операция" википедии, отредактированная под ваше условие.
                          Честно говоря, мне непонятно почему для таких ветвлений подходит, а как самостоятельная x if y then z - уже не нравится. По поводу симметричности не согласен =) A<- if ->B
                          P.S. Извиняюсь, если код "поехал", предпросмотра не имею.
                          Ответить
                          • Мне уже это "else" перед \ не нравится. И "t" тут особенное. Выделяется на фоне остального.
                            А в моём примере x, y, z и t стоят каждая в своём выражении, которое для всех одинаково.

                            Не надо это понимать, это
                            >>> Дело привычки

                            > По поводу симметричности не согласен =) A<- if ->B
                            В общем-то да. Ещё бы вместо then и else запилить <x|ψ|y> .
                            Ответить

    Добавить комментарий