Ябло (Свежее) / Говнокод #23907 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
protocol Multi {
    associatedtype T
    associatedtype U

    func printSelf()
}

extension Multi where T == Int, U == Float {
    func printSelf() {
        print("Int & Float!")
    }
}

extension Multi where T == String, U == Int {
    func printSelf() {
        print("String & Int!")
    }
}

extension Multi {
    func printSelf() {
        print("Unknown")
    }
}

class MultiImplementationIntFloat: Multi {
    typealias T = Int
    typealias U = Float
}

class MultiImplementationStringInt: Multi {
    typealias T = String
    typealias U = Int
}

class MultiImplementationInvalid: Multi {
    typealias T = Float
    typealias U = String
}

let m1 = MultiImplementationIntFloat()
m1.printSelf()

let m2 = MultiImplementationStringInt()
m2.printSelf()

let m3 = MultiImplementationInvalid()
m3.printSelf()

Multimethods в Swift с проверкой в compile-time

Запостил: Desktop Desktop, (Updated )

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

  • Типа ты сделал экстеншен методы разные, в зависимости от того, каким типом параметризован интерфпротокол?

    Это не совсем честно, потому что завист от типа m, а не от переданных в printSelf аргументов, с таким же успехом ты мог printSelf в каждом классе переопределить:)
    Ответить
    • Разница огромна. Чтобы переопределить в каждом классе, нужно иметь к нему доступ. А здесь можно где угодно сделать примесь. В самом коде не писал, но вообще имелось ввиду:

      class blahblah { }
      и где-то в недрах клиентского кода
      extension blahblah: Multi {...}

      И получаешь миксин
      Ответить
      • Рубист бы навесил метод на класс, и даже не задумался бы

        Я имел ввиду разницу в точки зрения диспатча: всё таки тип m2 известен в момент компеляции, и потому свифт может подобрать нужный метод статически. Котлин тоже так может, например:)
        Полезность extensionов я под сомнение не ставлю, это супер-крутая фича для method discovery (которая, кстати, была в ObjC [категории называлась вродеъ задолго до Kotlin, и наверное до C#)
        Ответить
        • Идея кмк одинаковая.

          Категории ОбжСи сосут у Свифта в данном случае: там нет default implementation
          Ответить
          • Идея была про вызов разных методов в рантайме в зависимости от параметров.
            Представь себе такой псевдокод
            fun doAll(cat: Cat){}
            fun doAll(dog: Dog){}
            ///
            let data:Mammal = getMammal();
            //data может быть cat, а может и dog
            doAll(data); //вызовет разные методы в зависимости от типа в рантайме

            В твоем случае это не так, потому что тип data известен в момент компеляции.

            А вот с перегрузкой методов или с visitor это бы сработало.

            >>Категории ОбжСи сосут у Свифта в данном случае: там нет default implementation
            Ты про print("Unknown")?

            Удобно, да. Я почти ничего не знаю про Swift:( Во время моего близкого знакомства с Apple везде был Objc, кажется только ARC завезли.
            Ответить
            • Моя идея была в

              "Сами generic functions тоже не похожи. В CL они не привязываются к одному конкретному типу. Например, можно определить функцию (defgeneric intersects (a b)) и написать методы для случаев (defmethod intersects ((a rectangle) (b circle))), (defmethod intersects ((a circle) (b circle))), (defmethod intersects ((a interval) (b point)))…
              В рантайме будет выбран наиболее подходящий эффективный метод. Т.е. это настоящие мультиметоды." (c) roman с той разницей, что выбор будет в компайлтайме.

              > В твоем случае это не так, потому что тип data известен в момент компеляции.

              У тебя он тоже известен, это ж Mammal.

              > А вот с перегрузкой методов или с visitor это бы сработало.
              - превед ООПед

              > Ты про print("Unknown")?
              - не. Я про то, что можно:
              1) определить протокол
              2) заэкстендить его, дав некоторым методам default implementation
              3) потом заэкстендить какой-то класс этим протоколом, voila!, класс умеет в default implementation методов протокола

              В ObjC так нельзя (ну или я чего-то не знаю).

              Ещё таким образом можно сэмулировать @optional из обж сей. Экстендим метод пустым телом, кому реально надо, реализует сам.
              Ответить
              • >>У тебя он тоже известен, это ж Mammal.
                И что? Этой информации не достаточно чтобы выбрать метод в комплайт тайме.
                А в твоем случае достаточно. Смотри:

                Компилятор в твоем примере на строке 42 (m1.printSelf()) думает: "а что за метод такой -- printSelf? Ах, у нас же тип m1 это MultiImplementationIntFloat, значит и метод понятно какой". Экстеншены в котлине резолвятся статически, в момент компиляции, думаю что и в Свифте -- тоже.

                А в моем примере он НЕ знает типа data и вынужден отложить решение о выборе метода до рантайма, как если бы это был виртуальный метод.

                В том-то и разница.

                >>- превед ООПед
                Ну в мейнстрим ЯПах с ООП обычно только так и бывает)

                >> класс умеет в default implementation методов протокола
                Но весь код, юзающий класс, придется перекомпилировать, да?

                >> сэмулировать @optional из обж сей.
                А у вас нету optinal? А спросить respondsToSelector можно?
                Ответить
                • > Но весь код, юзающий класс, придется перекомпилировать, да?
                  - да.

                  > А у вас нету optinal? А спросить respondsToSelector можно?
                  - у нас это в свифте? Только в @objc протоколах. В обычных свифтовых нету. Спросить respondsToSelector можно у классов, которые известны рантайму ObjC (т.е. потомки NSObject)
                  Ответить
        • Вообще, кстати, неоспоримость полезности extension'ов под вопросом. Примеси делать или в рамках одного файла разбивать на функциональные элементы да, пихать всюду и везде - яйца за такое отрывать
          Ответить
          • Extensions позволяют легче найти нужный API.
            Допустим, у меня есть user. Я хочу его удалить. Интуитивно я ищу метод delete(), но конечо его нет в классе User (потому что он ничего про удаление себя не знает).
            Тогда я говорю user.[cntrl space] и IDE находит мне все его extension методы (по сути те, где он является первым аргументом). Так я нахожу свой метод. Но так делает Intellij для Kotlin, и кажется R# для C#. Делает-ли так XCode для Swift я не знаю (думаю что может быть и нет), но может AppCode делает.

            Вот куда его класть -- вопрос. Это вообще часто большая проблема. Люди любят насоздавать всяких UserUtils где хрен чего найдешь.

            Проблему можно решить документированием API, но где (кроме публичных проектов) такое бывает? В проприетарном коде, которым пользуются 20 человек в одной конторе, почти никого такого нет:(((

            Вот если бы IDE умели "найти все публичные методы, доступные в этом модуле/пакете, где определённого класса инстанс является одним из параметров" то может быть было бы не плохо и без exntesions, но всё равно явный вызов метода выглядит приятнее.
            Ответить
            • > найти по параметрам
              Емнип, в squeack (одна из реализаций smalltalk) была такая фишка.
              Ответить
            • > Делает-ли так XCode для Swift я не знаю (думаю что может быть и нет)
              - проверил, для классов умеет, для протоколов нет. XCode это блокнот, они рефакторинг для свифта только к 4 версии языка смогил добавить.

              > Вот куда его класть -- вопрос.
              - ну на крайняк в TypeNameExtensions.swift.

              > Интуитивно я ищу метод delete(), но конечо его нет в классе User (потому что он ничего про удаление себя не знает).
              Тогда я говорю user.[cntrl space] и IDE находит мне все его extension методы
              > Проблему можно решить документированием API
              - когда что-то ищется интуитивно и не находится, то kill hire repeat
              Ответить
              • >> XCode это блокнот
                У меня тоже было такое ощущение, например его парсер не умеет восстанавливаться: забыл ] в одном месте и всё дерево пошло по песде. Я помню что думал пересесть на AppCode, но побоялся что сториборды не будут там работать:)

                >>- ну на крайняк в TypeNameExtensions.swift.
                Немножечко "god objfile"

                >>то kill hire repeat
                У нас в большинстве проектов оче хуёво с API:((
                Ответить
                • >Я помню что думал пересесть на AppCode
                  они уже пару лет точно забили на UI, потому что яббл в каждом релизе что-нибудь меняет. Я пишу код в appcode, ui - в xcode. Коллеги жалюутся на то, что в xcode постоянно падает парсер и он превращается в блокнот. Appcode как-то стабильнее, но тоже может не увидеть либу или какой-нибудь экстеншн

                  И да, сториборды - говно. Лучше делать отдельные xib
                  Ответить
                  • >>сториборды - говно
                    почему? Мне нравилось визуально наблюдать перемещение экранов, и сигвеи тоже нравились
                    Ответить
                    • Особенно классно в сторибордах фиксить конфликты в vcs
                      Ответить
                      • Их классно фиксить в любой автогенеренной хуйне.
                        Нужна пессимистичная блокировка, как была в source safe:)
                        Ответить
                        • Не, сториборды и все прочие xcproj имени эппла это такое особое извращение.

                          Но вообще да, много маленьких сторибордов вместо одной большой + lock, если возможно
                          Ответить
                  • Забавно, что Visual Studio for Mac умеет хоть как-то работать с Interface Builder.
                    Ответить
  • Совершенно непонятно, зачем это надо, если инстанс руками создавать надо. Ну а в компайл-тайме "мультиметоды" и в крестах легко сделать.
    // https://ideone.com/GZowyg
    #include <iostream>
    #include <utility>
    
    template <class U, class V>
    struct intersect_impl;
    
    template <class U, class V>
    bool intersect(const U& u, const V& v) {
        return intersect_impl<U, V>::apply(u, v);
    }
    
    template<>
    struct intersect_impl<std::pair<int, int>, int> {
        static bool apply(const std::pair<int, int>& interval, int value) {
            return interval.first <= value && value <= interval.second;
        }
    };
    
    template<>
    struct intersect_impl<std::pair<int, int>, std::pair<int, int>> {
        static bool apply(const std::pair<int, int>& u, const std::pair<int, int>& v) {
            return intersect(u, v.first) || intersect(u, v.second);
        }
    };
    
    int main() {
        std::cout << "[0, 2] ∩ 1 ? " << intersect(std::make_pair(0, 2), 1) << "\n";
        std::cout << "[0, 2] ∩ 1 [3, 4] ? " << intersect(std::make_pair(0, 2), std::make_pair(3, 4)) << "\n";
        std::cout << "[0, 2] ∩ 1 [1, 4] ? " << intersect(std::make_pair(0, 2), std::make_pair(1, 4)) << "\n";
        return 0;
    }
    Вся суть настоящих мультиметодов в том, что можно сложить объекты разных типов в гетерогенный контейнер и работать с ними универсальным образом.
    Ответить
    • Инстанс чего?

      > Вся суть настоящих мультиметодов в том, что можно сложить объекты разных типов в гетерогенный контейнер и работать с ними универсальным образом.
      - зачем нужна гетерогенная динамическая метушня, если в общем случае проблем с ней больше? Вон Пи сокрушался по поводу того, что эксепшон вылетит в C#, если нет нужной перегрузки. Кстати, как CL будет вести себя в таком случае?
      Ответить
      • > Инстанс чего?
        >> let m1 = MultiImplementationIntFloat()

        > зачем нужна гетерогенная динамическая метушня

        Ну вот есть у тебя все объекты какой-нибудь игры, ты хочешь положить их в дерево, чтобы быстро считать столкновения.

        > Кстати, как CL будет вести себя в таком случае?
        Если совсем нет реализации, кинет исключение "кондишен". Тех конфликтов, которые пи нашёл в c#, там не будет, там по-другому "перегрузки" разрешаются. http://govnokod.ru/23894#comment407460
        Ответить
        • А, так это пример просто, никто ж не мешает законформить уже существующий тип к протоколу:
          extension Int: Multi { ... }
          и поехали

          > Ну вот есть у тебя все объекты какой-нибудь игры, ты хочешь положить их в дерево, чтобы быстро считать столкновения.
          - composition же. У объектов должны быть geometric bodies, по ним и считать. Geometric bodies по идее должны обладать одинаковыми геометрическими свойствами, так что гетерогенность вроде и ни к чему здесь. А, если хочется динамики, не взять ли duck typing с чем-то типа forwardInvocation (это из смолтолка пришло вроде)?
          Ответить
          • > У объектов должны быть geometric bodies, по ним и считать

            Это что-то меняет? Ну хранишь ты геометрию вместо реальных объектов. Всё равно потом надо найти, каким объектам эта геометрия принадлежит, и вызвать соответствующую типам функцию.
            Ответить
            • Если я храню только геометрию, то зачем мне гетерогенный список?) Я теряю причинно-следственную связь беседы.

              Но в ObjC даже проще сделать то, о чем ты говоришь
              Ответить
              • > Если я храню только геометрию, то зачем мне гетерогенный список?) Я теряю причинно-следственную связь беседы.

                Ну так можно утверждать, что Tree<GameObject> никакой не гетерогенный контейнер. В нём же только GameObject-ы лежать могут.

                Допустим, у тебя какой-нибудь "однородный" SpaceTree<Polygon>. Дерево помогло тебе быстро посчитать, что полигон p1 теперь пересекается с полигоном p2. Что дальше-то будем делать? Теперь надо понять, чем именно являются полигоны p1 и p2 и вызвать соответствующую функцию, ибо корабли, к примеру, взрываются и аннигилируют, а астероиды распадаются на несколько мелких астероидов. Вот тут ты и будешь пилить наколенный аналог мультиметодов.
                Ответить
                • Обычно столкновения считает физический движок, который является отдельной либой, и в принципе не знает ни про какие корабли и астероиды, т.к. работает он с какими-то своими сущностями, и просто создаёт ивенты, которые уже обрабатывает другой слой.
                  Внутри него есть некий отдалённый аналог "мультиметодов", т.к. нужно обрабатывать столкновения soft и rigid bodies, например, но количество типов сущностей известно и невелико, а требования к перфомансу существенны, так что CLOS и там нафиг не впёрся.
                  Ответить
                  • > Обычно столкновения считает физический движок
                    > CLOS и там нафиг не впёрся

                    Это всё и так понятно, можно десятилетиями песать опупенные сайты игоры без всякого там «CLOS».

                    Я просто поясняю, почему (в теории) в компайл-тайме не всегда перегрузку выбрать можно.
                    Ответить
  • Hi

    I wanted to order a desktop from your webshop.
    but I can not find the computer anymore on your site,
    it looks like this on this site https://bit.ly/DesktopItem204
    I hope you will sell it again soon,
    mail me if you are going to sell it again, I'll wait

    Greetings
    Ответить
  • Hello

    I regularly order from your shop, and I love your Fasion.
    But I have a question, I see a lot of clothes on this site http://bit.ly/FashionBrandsCheaper that you also sell,
    but there products are 40% cheaper, well my question is what is the difference between your shop and theirs,
    is it the quality or something else, I hope you can answer my question.

    greetings
    Ответить
  • Hi

    I regularly order from your shop, and I love your store.
    But I have a question, I see a lot of Items on this site http://bit.ly/CheaperProducts that you also sell.
    but there products are 40% cheaper, well my question is what is the difference between your shop and theirs,
    is it the quality or something else, I hope you can answer my question.

    Yours truly
    Ответить
  • Hey

    I just want to say what a marvelous webshop you have!.
    I am a regular customer of your shop.
    I had visited your store last month, and I saw a very nice product i wanne order.
    But I have a question! today I wanted to order it, but can not find the product anymore in your webshop.
    The product looks like this picture http://item.pictures/screenshot
    i hoop you sell it soon.
    I'll wait.

    Sincerely

    "Sent from my iPhone"
    Ответить

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

Из-за тебя ушел bormand, guest!

    А не использовать ли нам bbcode?


    8