1. C# / Говнокод #13746

    +142

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    private static string AddStr(string s1, string s2)
    		{
    			string result;
    			if (s1 == string.Empty)
    			{
    				result = s2;
    			}
    			else
    			{
    				if (s2 == string.Empty)
    				{
    					result = s1;
    				}
    				else
    				{
    					result = s1 + " " + s2;
    				}
    			}
    			return result;
    		}

    Код - бессмысленный и беспощадный

    Запостил: leon_mz, 06 Сентября 2013

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

    • показать все, что скрытоА почему тут д.б. C++
      Ответить
    • А как бы вы его переписали? Ну не учитывая того, конечно, что скорее всего эту функцию юзают вместо join'а для всяких непотребств, например для поклейки всего массива через пробел.
      Ответить
      • string.Format("{0} {1}", s1, s2).Trim()
        Ответить
        • Капитан говорит, что код поста будет работать быстрее
          Ответить
          • а надо ли
            Ответить
            • А нужна ли эта функция вообще? Скорее всего, как я писал выше, автор будет сворачивать ей массив, вместо того, чтобы поюзать join...
              Ответить
              • >string.Format("{0} {1}", s1, s2).Trim()
                то есть так сливать массивы лучше?

                я не говорил, что код поста хорош - я сказал что приведенный - еще хуже
                Ответить
                • > то есть так сливать массивы лучше?
                  Имхо - нет. И оригинал был нагляднее (если пофиксить некоторые недоразумения типа обработки null'ов).

                  Но я о другом писал - мне кажется, что автор будет в цикле бежать по какому-нибудь массиву строк и вызывать функцию из топика для аккумулятора и текущей строки (говноаналог string.Join(" ", array))... И я искренне надеюсь, что эту функцию не юзают в таком контексте... Вот из-за этого у меня сомнения в нужности данной функции.
                  Ответить
                  • вполне возможно. Тогда без стригбилдера как без рук
                    Ответить
                    • > Тогда без стригбилдера как без рук
                      string.join(" ", array), если не учетывать потенциальную пустоту строк. А если учитывать - можно сначала отфильтровать их, а потом join.
                      Ответить
                      • Ну так внутри все равно стрингбилдер, какая разница? тем более я думал пишем метод сами.

                        можно фильтровать в процессе слияния
                        Ответить
              • А как насчёт соединения имени с фамилией? Как раз ровно две строки.
                Только надо метод переименовать. И я бы через условный оператор написал.
                А вариант с Format + Trim - гадость.
                Ответить
                • > насчёт соединения имени с фамилией
                  Там потенциально может захотеться еще и отчество добавить... Поэтому я бы или 3 аргумента сделал (и назвал бы соответственно), или методом к объекту, хранящему инфе о человеке прикрутил...
                  Ответить
                  • > отчество
                    Потенциально может и не захотеться. Код интернационален, комментариев на русском мы в нём не видим. Откель нам знать, что у пользователей этого софта вообще есть отчество. У них там за бугром вторые имена в ходу.
                    Ответить
                    • >У них там за бугром
                      Прям таки везде "за бугром"? Кое-где, например, встречаются двойные имена.
                      Ответить
                    • В общем в идеале - что-нибудь типа getFullName() у объекта Person. А там он уже пусть сам разбирается как эти Ху Ли Цзяо правильно поклеить.
                      Ответить
          • преждевременная оптимизация - корень всех зол
            Ответить
            • Да где вы там оптимизацию нашли... Имхо в топике вполне логичный и понятный код. Убрать лишние скобки, result, и получится вполне читаемо.

              По крайней мере оно предсказуемей чем Format+Trim, которые пожирают пробельные символы по краям s1 и s2.
              Ответить
            • Употребление чужих цитат не в тему - корень всех зол.
              Ответить
              • > Употребление чужих цитат не в тему - корень всех зол.
                Тем более в покоцаном виде.
                Ответить
        • Если s1 начинается с какого-то из пробельных символов или s2 на него заканчивается, то trim порежет эти символы. Код не совсем эквивалентен.
          Ответить
          • вопрос в том - нужны ли эти пробелы на выходе? что-то мне подсказывает, что их удаление это скорее фича чем баг
            Ответить
      • > А как бы вы его переписали?
        (defun add-strings (a b &key stream)
          (labels ((%f (x) (if (zerop (length x)) 0 1)))
            (format stream "~[~2*~;~a~*~;~*~a~;~a ~a~]" (+ (%f a) (* 2 (%f b))) a b)))

        ;)
        Ответить
        • на последней строчке непарная закрывающая скобка
          Ответить
        • > %f
          Почему такое странное имя для функции проверяющей на непустоту строки, если не секрет?

          > (+ (%f a) (* 2 (%f b)))
          > "~[~2*~;~a~*~;~*~a~;~a ~a~]"
          А если строк будет три? :)
          Ответить
        • Как-то так будет поуниверсальней:
          (defun join-strings (&rest strings)
            (labels ((%f (x) (if (zerop (length x)) 0 1)))
              (format nil "~{~a~^ ~}" (remove-if-not '%f strings))))
          Ответить
          • Да, вариант с remove-if-not не рабочий, нужно было бы что-то типа:
            (remove-if (compose #'length #'zerop) strings)
            Ответить
            • > не рабочий
              Почему?
              Ответить
            • А, понял, кажется, почему не рабочий. А просто %f без ' же должно нормально работать?
              Ответить
              • %f - процент, эти типа подчерка в Си-подобных, значит что функция приватная / определена внутри другой функции. f - просто типичное название для "какой-нибудь" функции, если ее имя не важно.

                Почему не рабочий: %f всегда возвращает true. remove-if-not ничего не удалит.

                Ну, предположительно, для большого количества строк эта функция не нужна, т.как можно просто сделать (format ? "~{~a~^ ~}").
                Ответить
                • > %f всегда возвращает true
                  Хм, да, тупанул я. В лиспе же только nil это false.
                  Ответить
                • >эти типа подчерка в Си-подобных
                  В каких?
                  Ответить
                  • В питоне.
                    Ответить
                  • В том же Ц++ двойные подчерки вначале или вконце зарезервированы для нужд писателей библиотек и т.п.
                    Ответить
                    • > двойные подчерки вначале или вконце зарезервированы для нужд писателей библиотек и т.п.
                      А живущим у подножья олимпа их юзать строжайше запрещено... А в вашем случае % это нечто используемое лисперами в повседневной практике. Поэтому, имхо, ассоциация не катит...

                      P.S. А почему бы не назвать эту функцию просто f, ведь за скоп labels'ов ее имя не вылезет. С пометкой глобальных переменных звездочками я полностью согласен, а вот локальные, имхо, помечать не стоит.
                      Ответить
                      • Почему не назвать? Такая традиция, такая же, как астериски вокруг специальных переменных и плюсы вокруг констант.

                        В Лиспе нет глобальных переменных.

                        Это не предикат, с чего бы ее так называть? Она просто техническая функция без какого-то определенного названия.
                        Ответить
                        • > Это не предикат
                          А ну да, я забыл, что она возвращает не nil/t, а 0/1. Тогда да, not-empty не катит.

                          > В Лиспе нет глобальных переменных.
                          defvar package-private получается?
                          Ответить
                          • Нет вообще понятия такого нет как глобальный / локальный. Символы всегда создаются в каком-то пакете, потом это уже дело пользователя: импортировать этот пакет, или нет.
                            defvar создает символ и объявляет связаную с ним переменную как "специальную" + если это происходит в топ-левел, следит за тем, чтобы значение переменной обозначенной этим символов назначалось только один раз (т.е. при повторном прочтении файла значение не будет переустановлено). Но если сильно хочется, то можно потом отменить "специальность" этой переменной.
                            Ответить
                            • > Символы всегда создаются в каком-то пакете
                              Ага, т.е. все-таки package-private получается.

                              > отменить "специальность" этой переменной
                              Насовсем, или только внутри какого-то скопа?
                              Ответить
                              • Нет, такого понятия как приват / паблик нет. Эти символы ничем не приватнее символов из другого пакета. В Дилане пересмотрели эту позицию, и сделали что-то похожее на то, что в Яве называют internal, с той разницей, что internal не определялся названием пакета или именем файла. Но в Лиспе ничего такого нет.

                                Отменить можно вообще. Это свойство хранится в списке свойств символа, а он как-бы один всегда.
                                Ответить
                                • > Это свойство хранится в списке свойств символа, а он как-бы один всегда.
                                  Каждый пакет имеет свой неймспейс для символов?

                                  Все, кажется понял, что такое special. Просто флаг, увидев который let'ы, setf'ы, и обращения к помеченному им символу раскрываются в другой код.
                                  Ответить
                                  • Нет, неймспейсом в Лиспе называется что-то другое. Неймспесы это в Лиспе-2 (Common Lisp, Emacs Lisp) - места где опеределяютыса функции и переменные. И в Лиспе-1 (Scheme, Clojure) - место, где определяются переменные.
                                    Пакет сам по себе и является "неймспейсом" для символов. "Неймспейсом" в том смысле, в котором бы это слово использовалось в Ц++.
                                    Ответить
                                    • А есть, кстати, преимущества лиспа-2 над лиспом-1, ну помимо того, что можно переменную и функцию назвать одинаково? Или же CL является лисп-2 чисто по историческим причинам?
                                      Ответить
                                      • Скорее всего это бесполезная фича. Многие лисперы, даже те, кто пишут на CL считают Схему более рафинированым и продуманным языком, и эта "универсальность" видится как положительная черта. Почему так в CL / e-lisp'e? - хз, скорее всего так удобнее было когда-то реализовать парсер. Стандарт очень щепетильно описывает как должен работать парсер, поэтому в CL особо вариаций на эту тему и не было.
                                        Дилан, на сколько я понимаю, тоже Лисп-1.
                                        Ответить
                • > если ее имя не важно
                  А я бы написал not-empty, все-таки хоть имя для такой мелочи в таких мелких скопах и не важно, но с именем читать как-то приятней.
                  Ответить
        • P.S. Так я и на сишке могу:
          void join_strings(const char *a, const char *b, char *buf, size_t n) {
              static const char * f[] = { "", "%s", "%2$s", "%s %s" };
              snprintf(buf, n, f[!!*a|!!*b*2], a, b);
          }
          http://ideone.com/s5kGgA
          Ответить
          • Вариант попроще:
            sprintf(..., "%s%s%s", a, *a&&*b ? " " : "", b)
            Ответить
            • ачивмент гет - великий оптимизатор
              Ответить
              • sprintf(..., "%s%s%s", " "[!*a||!*b], b)
                Ответить
                • У тебя баг, надо так:
                  sprintf(..., "%s%s%s", a, " "+(!*a||!*b), b);
                  Сложение, а не индекс. Ну и первая строка ещё.
                  Ответить
                  • > Сложение, а не индекс. Ну и первая строка ещё.
                    Да, все верно.
                    Ответить
          • Я думал про вариант с распечаткой списка, но:
            1. Консит новую память (плохо).
            2. Можно передать больше двух параметров (не эквивалентно исходному варианту).

            Вариант с printf в принципе похож, но я сам ничего не выбираю, выбор описан декларативно в строке формата. Полным аналогом было бы (format stream (aref #("~a ~a" ...)) a b)
            Ответить
            • Так все-таки почему функция проверки на непустоту названа %f?

              > Консит новую память (плохо).
              Есть такая проблема. Но с произвольным количеством строк по другому, походу, и не получится.

              > Можно передать больше двух параметров (не эквивалентно исходному варианту)
              Да я хотел немного универсальности добавить... Отсюда и переименование в join-strings.
              Ответить
            • А как вам такой вариант (хотя он тоже выделяет память под результат):
              (if (%f a) (if (%f b) (concatenate 'string a " " b) a) b)
              Ответить
              • Тогда так:
                (defun add-strings (a b &key stream)
                  (labels ((%f (x) (if (zerop (length x)) 0 1)))
                    (format stream "~a~[~; ~]~a" a (* (%f a) (%f b)) b)))


                Если уже пользоваться форматом, так для всего.
                Ответить
                • Все-равно изврат какой-то... умножение тут, имхо, не в тему...

                  А нет ли там какой-то конструкции в format'е, которая управлялась бы не числом а nil/t?
                  Ответить
                  • Неа, выбрать можно только по индексу :(
                    Ответить
                    • А как-то так?
                      (format stream "~a~:[ ~]~a" a (and (%f a) (%f b)) b)
                      Ответить
                    • Ну вернее вот так, т.е. для false левая часть: "~a~:[~; ~]~a"
                      Ответить
        • Хацкель:
          addStrings  a "" = a
          addStrings ""  b = b
          addStrings  a  b = a ++ " " ++ b
          Ответить
          • joinStrings = intersperse " "
            Ответить
            • Он лишних пробелов насует. Имхо как-то так надо:
              joinStrings = intercalate " " . filter (not . null)
              UPD: intersperse это не то, надо intercalate.
              Ответить
    • s1 == null && s2 == null, то вернется пробельный символ " ". Отличный код!
      Ответить

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