• Как привести словесный пример полиморфизма?

    Полиморфизм бывает трёх типов: параметрический, ad-hoc и полморфизм подтипов.

    Параметрический полиморфизм нужен чтобы писать логику, параметризованную типами, реализующими некоторые интерфейсы (вырожденный случай - параметризованные любыми типами). Простейший пример: функция map, применяющая функцию к каждому элементу массива. Без полиморфизма мы бы писали отдельную функцию для каждого типа:

    mapIntFloat :: (Int -> Float) -> [Int] -> [Float]
    mapIntFloat f [] = []
    mapIntFloat f (x:xs) = (f x) : (map f xs)
    
    mapIntString :: (Int -> String) -> [Int] -> [String]
    mapIntString f [] = []
    mapIntString f (x:xs) = (f x) : (map f xs)
    -- и так далее


    Выходит довольно громоздко и налицо повторение логики в каждой функции вида mapTypeType. Чтобы избежать повторения логики, параметризуем функцию map относительно типов исходного массива и массива, получаемого в результате:

    map :: forall a b. (a -> b) -> [a] -> [b]
    map f [] = []
    map f (x:xs) = (f x) : (map f xs)


    Теперь вместо конкретных типов вроде Int или Float у нас переменные типов: a и b.

    Окей, но если копнуть глубже, оказывается, что логика, похожая на map для массивов, применима и к другим типам. Например, к optional-значениям. Без ad-hoc полиморфизма мы напишем что-то типа:

    mapList :: forall a b. (a -> b) -> [a] -> [b]
    mapList f [] = []
    mapList f (x:xs) = (f x) : (mapList f xs)
    
    mapMaybe :: forall a b. (a -> b) -> Maybe a -> Maybe b
    mapMaybe f Nothing = Nothing
    mapMaybe f (Just x) = Just (f x)


    Видно, что логика везде примерно одна и та же, сигнатуры совпадают с точностью до параметризванного типа. Вот для этих случаев и нужен ad-hoc полиморфизм:

    class  Functor f  where
        map :: (a -> b) -> f a -> f b


    Мы параметризовали нужную нам логику относительно параметризованного типа f и теперь можем писать реализации для конкретных типов:

    instance  Functor Maybe  where
        map f Nothing = Nothing
        map f (Just x) = Just (f x)
    
    instance  Functor [] where
        map f [] = []
        map f (x:xs) = (f x) : (map f xs)


    Сама функция map теперь имеет тип:

    map :: forall f a b. Functor f => (a -> b) -> f a -> f b


    Теперь мы можем писать функции, которые работают с любыми функторами, то есть опять-таки сократить повторение логики в коде.

    Наконец, полиморфизм подтипов - это несколько другой подход к предыдущей проблеме. Вместо выделения общего интерфейса мы создаём базовый тип и наследуем от него остальные. В этом случае Functor будет абстрактным классом с абстрактным методом map, от которого наследуются типы Maybe, List и т.д. В таком случае сигнатура функции, принимающей и возвращающей функтор, будет выглядеть примерно так: foo :: Functor Int -> Functor String.
    Ответ написан
    1 комментарий
  • Почему не срабатывает try catch у переменной, которая выполняется как функция?

    Sanasol
    @Sanasol Куратор тега PHP
    нельзя просто так взять и загуглить ошибку
    Ошибка-то какая?

    Если синтаксическая, то и дальше будет валиться, это на старте валится, а не во время выпонения.
    Ответ написан
    4 комментария
  • Как в SQL сделать сортировку по алфавиту исключая лишние слова?

    @BorisKorobkov Куратор тега MySQL
    Web developer
    Если нужно сортировать так, чтобы "улица Белова" и "проезд Белова" были рядом, то...
    вариант 1: называть их "Белова улица" и "Белова проезд".
    вариант 2: хранить в отдельных полях "улица"+"Белова" и "проезд"+"Белова". И сортировать по второму
    Ответ написан
    Комментировать
  • Как правильно определить алгоритм для точек в слайдере?

    @kulaeff
    Front-end developer
    Если имеются ввиду точки пагинации, под слайдами, то тут просто:

    var pointCount = Math.ceil(slideCount / slidesPerView)


    где slideCount - общее количество слайдов, а slidesPerView - количество слайдов в группе.
    Ответ написан
    Комментировать
  • Доказывают ли изначально аксиомы, чтобы потом принимать их на веру?

    @Mercury13
    Программист на «си с крестами» и не только
    Аксиомы доказать невозможно. Но можно сделать одну классную вещь. А именно — построить модель теории. Другими словами: найти в соседней теории, которой вы «доверяете» (например, теории действительных чисел или евклидовой геометрии) такие «точки» и «прямые», чтобы они отвечали всем аксиомам. И эти аксиомы нужно доказывать, чтобы показать, что, например, R² с «точками» (x,y) и «прямыми» ax+by+c=0 — действительно модель евклидовой геометрии.

    Да, и математики часто, но некорректно говорят: «Векторное пространство — это совокупность из основного множества X, числового поля K, операций x+y и x·k такая, что отвечает аксиомам…» Вообще-то, требованиям, а не аксиомам, и эти «аксиомы» нужно доказывать, чтобы доказать, что, например, R² — векторное пространство над полем R.

    Да, а что же Евклид? А Евклид, вероятно, сам не догадывался, какую классную штуку он придумал. К тому же исчерпывающую аксиоматику евклидовой геометрии придумали ≈1900. Страшна, как чёрт, шесть базовых понятий… Но это зачастую и не требуется, чтобы решать задачи — надо как-то определить объект изучения и начать доказывать теорему за теоремой. Большинство из нас, даже выпускники вуза, не знают ни теорию действительного числа, ни аксиоматику Пеано для арифметики, ни аксиоматику для теории множеств…
    Ответ написан
    Комментировать
  • Нарушают ли указатели и разименование в c++ принципы ООП?

    @Mercury13
    Программист на «си с крестами» и не только
    Не будем встревать в холивар «должен ли указатель быть объектом». Примем, что указатель — простейший тип, ради совместимости и эффективности.
    К простейшему типу инкапсуляция и наследование неприменимы.
    А вот для полиморфизма указатели очень нужны. Динамический полиморфизм — это когда под одним фасадом могут оказаться разные объекты.
    1. По копии их передавать невозможно, только по указателю/ссылке.
    2. Их нельзя уничтожать под одну гребёнку. А значит, если мы их передаём в чьё-то другое владение, надо удостовериться, что они созданы в «куче» и у «фасада» есть виртуальный деструктор.

    Есть ещё два принципа ООП — абстракция и принцип Лисков. Первый имеет отношение к указателям постольку, поскольку есть полиморфизм. Второй — гугли «ковариантные/контравариантные указатели».
    Ответ написан
    1 комментарий
  • Как определять ответственность функций?

    TrueBers
    @TrueBers
    Гуглю за еду
    По своему опыту могу сказать:
    Всё это бесполезный треш, все эти описания как надо, как правильно, как делают гуру, как делают в НАСА, солиды, банды четырёх, десяти, трёхсот спартанцев и т. д. Но, ровно до того времени, пока вы сами до этого не дойдёте. А дойти до этого можно только с опытом. Когда вы пишете что-то относительно не крупное, эти все вещи можно опускать. А когда приходите к огромному проекту, всё идёт само по себе, ибо иначе вы просто не можете с этим взаимодействовать, либо если система уже достаточно хорошо спроектирована, вам приходится писать правильно, т. к. по-другому либо не получится, либо вам дадут по шапке ревьюверы.

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

    Рецепт прост: пробовать, делать, строить, ломать, перестраивать, ошибаться, снова перестраивать. Тупо взять и прочитать, как кто-то там сделал и у него получилось, не прокатит. У него звёзды сошлись, а у вас, у меня, или у неё не сойдутся точно в такой же последовательности. Используйте разные языки программирования, разные парадигмы, фреймворки. Это даёт прекрасное понимание о существовании различных архитектурных решений, которое не даст ни однин теоретический паттерн.

    Я не хочу сказать, что все эти гофы и солиды не имеют смысла, они созданы для того, чтобы для начала просто с ними ознакомиться, отложить в подсознание и... благополучно забыть! Но потом, когда вдруг что-то писал и внезапно осенило: Да это же паттерн медиатор/обсервер/репозиторий/anyPattern! Вот тут и пригодится та самая книга трёх танкистов и собаки, которая просто направит в нужное русло, объяснит остальное, что не успел понять сам, и т. п.

    Всё это моё понимание, работает для меня, может не работать для кого-то другого, кто, например, запоминает 95% прочитанной книги и может уже сразу же адекватно оценить где какой подход использовать, где нужно будет масштабироваться и т.д.

    Но, я пока что таких людей не видел...
    Ответ написан
    3 комментария
  • Как организовать смену пароля пользователя при первом входе?

    @jetkay
    Разраб
    Как вариант:

    1. Сервис регистрации пользователя генерит новый временный пароль и шлет по почте + у этого пользователя выставляется флаг PwdChangeRequired = true.
    2. Пользователь входит в систему с тем временным паролем, система знает кто вошел и проверяет флаг на true и редиректит его на форму смены пароля.

    PS: Я не знаком с Django
    Ответ написан
    2 комментария
  • Как разработчику выделять время для изучения новых технологий и самообразования?

    @o_f
    Веб-аналитик, SEO, контекстная реклама
    Именно поэтому те, кто находят время в таких же условиях успешнее и быстрее вас. :)
    А дальше будет еще меньше времени, еще меньше возможностей, мозг все медленнее, а молодые уже подпирают.
    Вам решать, где искать это время, вряд ли кто-то что-то очень полезное скажет имхо.
    На работе вы можете не ходить на обед с коллегами, а поесть за 10 минут еду, что принесли с собой и час уделить на учебу.
    Вечером ложитесь спать на час позже - еще один час в учебу.
    В дорогу берете планшет или ноут с интернетом, и практикуете то, что прочитали в книге.
    В один выходной день - полностью с семьей. Второй - целиком в учебе в отдельной комнате.
    Скажите семье, что теперь один день в неделю вы будете посвящать только учебе в течение месяца. Чтобы никто вас не трогал и помог дойти до цели, потому что изучение нового даст вам повышение/деньги/перспективы.
    Как люди в 30 лет учат английский? Как люди в 40 лет худеют на 20 кг?
    Они ЖЕРТВУЮТ чем-то.
    Ответ написан
    Комментировать
  • Как правильно перекрыть или скрыть существующий родительский метод?

    yarosroman
    @yarosroman Куратор тега C#
    C# the best
    public abstract class GrandFather
    {
    public string Description = "Grandfather";
    public virtual string GetDescription()
    {
    return Description;
    }
    public abstract double GetAge();
    }

    Если метод помечен как virtual, то вызываемая реализация берется из типа объекта, а не из типа указателя.
    Ответ написан
    4 комментария
  • Как составить регулярное выражение?

    @ldvldv
    зачем регулярные выражения?
    pathinfo('upload/iblock/1dc/1dc758d0bf.jpg',PATHINFO_DIRNAME)
    Ответ написан
    Комментировать
  • Почему методы нельзя передавать в функции без делегатов?

    Nipheris
    @Nipheris Куратор тега C#
    Делегаты - это форма существования функтора на платформе .NET. Почитайте про функтор, и поймете (наверное), зачем нужен делегат.

    Если коротко и грубо - вызвать напрямую можно всегда только конкретный метод, который будет четко известен еще на стадии компиляции. Если же вы пишете некий обобщенный алгоритм и заранее не знаете, какие КОНКРЕТНО методы у каких КОНКРЕТНО объектов будете вызывать - вам необходимо будет воспользоваться делегатом.
    Простейший пример - LINQ-методы. Метод фильтрации Where получает своим параметром функтор, который возвращает true или false, что значит - оставить элемент в коллекции или выкинуть его. В этом методе в цикле foreach вызывается переданный делегат для каждого элемента. Where понятия не имеет, какой конкретно метод (или лямбда-выражение) вы захотите подставить в качестве фильтрующего предиката.

    Другой пример - события. События в дотнете - это делегаты с урезанным публичным интерфейсом. Так как, к примеру, кнопка не знает о том, кто захочет подписаться на событие ее нажатия, она никак не может вызвать конкретные методы у конкретных объектов. Чтобы иметь возможность сообщать о своем нажатии, кнопка выставляет событие Click наружу, давая возможность записать туда конкретные методы для вызова.

    Кстати, делегат выполняет еще и функцию связывания: для нестатических методов делегат хранит еще и объект, для которого будет вызван instance-метод (т.е. связывает пару объект-метод).

    Таким образом,
    > Почему методы нельзя передавать в функции без делегатов?
    Делегаты - это и есть передача методов в функции.
    Ответ написан
    Комментировать
  • Не получается решить задачу на javascript?

    sayber
    @sayber
    Да, я программирую на PHP и еще асинхронно!
    Вот вам простой пример.
    function Fibonacci(num)
     {
         var i, a = 0, b = 1, FibonacciArray = []; 
         for (i = 0; i < num; i++) {
           b = a + (a = b); // Сумма
           FibonacciArray.push(b); // Пушим в массив
         }
         console.log(FibonacciArray); // выводим в консоль
     }
     Fibonacci(100);
    Ответ написан
    1 комментарий
  • Как правильно хранить множественные атрибуты в MySQL и их выводить на сайт?

    TheCreator
    @TheCreator
    Бездельник
    Если городов конечное множество и они редко изменяются - вам поможет поле SET.
    Если же нет - то можно использовать битовую арифметику (фактически тот же SET, но данные хранятся в другой таблице, а айди нужных городов кодируются в битовое слово), это немножко сложно, но очень эффективно.

    Например у вас таблица
    1. Москва
    2. Петербург
    3. Самара.

    Человек выбрал самару и петербург.
    Самара это 2 ^ 2, Петербург это 2 ^ 1, складываем, получаем число 5, которое в двоичном выражении записывается, как 110, а это значит (читаем его с конца), что первый элемент не задан, второй задан, третий задан, что вам и нужно. Для поиска по битовым маскам тоже есть операторы, XOR и другие.

    Почитайте, это интересно, если хотите заморачиваться, но для списка городов, наверное, излишне.

    Для них обычно создают таблицу связей, первая колонка - айди человека, вторая - айди города. И добавляете в неё несколько записей, чтобы отметить несколько городов, потом легко искать.
    Ответ написан
  • Как поправить валидацию формы на лендинге?

    S-ed
    @S-ed
    Комбайнёр
    Ваш скрипт:
    $(document).ready(function(){
      $('.my_form').validate({
    ...

    Вызывается только 1 раз, при загрузке страницы. $('.my_form').validate обрабатывает только первый найденный элемент, а не все возможные.
    $(document).ready(function(){
        $('.my_form').each(function() {
            $(this).validate({
                ...
    Ответ написан
    Комментировать
  • JQuery: Возможно ли оптимизировать добавление класса в момент нажатия на кнопку?

    Creamov
    @Creamov
    Senior Fullstack Software Engineer
    Как вам такой вариант?
    $(document).on('mousedown mouseup mouseout', '.button', function(e) {
        $(this).toggleClass('button_pressed', e.type == 'mousedown');
    });
    Ответ написан
    3 комментария
  • Как сделать сортировку большой базы данных?

    Shutik
    @Shutik
    Погромист халявщик
    SELECT id, user_name, rating, @curRank := @curRank + 1 AS rank
    FROM person p, (SELECT @curRank := 0) r
    ORDER BY rating;
    Ответ написан
    1 комментарий
  • Почему дублируются значения при джоине 2х таблиц?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Если надо получать суммы, то проще всего делать JOIN сразу с суммами.
    SELECT `o`.`ID`, IFNULL(`op`.`VALUE`, 0) AS `prepayment`, IFNULL(`ef`.`VALUE`, 0) AS `payment`
        FROM `b_sale_order` AS `o`
        LEFT JOIN  (
            SELECT `order_id`, SUM(`VALUE`) AS `VALUE`
                FROM `d_sale_order_prepayment` 
                GROUP BY `order_id`
        ) AS `op` ON `op`.`order_id` = `o`.`ID`
        LEFT JOIN  (
            SELECT `order_id`, SUM(`VALUE`) AS `VALUE`
                FROM `d_sale_order_excess_fare` 
                GROUP BY `order_id`
        ) AS `ef` ON `ef`.`order_id` = `o`.`ID`
    Ответ написан
    Комментировать
  • Почему логику по созданию обьектов выносят отдельно из паттерна Репозиторий?

    @carbon88
    .NET developer/ORM developer
    Думаю тут играет роль принцип одной обязанности. Ну и плюс паттерн фабрика.

    Класс репозитория должен отвечать за одну задачу, полагаю это действия над репозиторием. Если ему нужно получить некий объект, он не задумываясь берет нужную фабрику и получает объект и дальше работает с объектом. Классу репозитория не нужно знать как создается объект и что для этого нужно. Он должен знать лишь что от такой-то фабрики можно получить класс объектов, реализующих интерфейс или наследующих некий класс. А вот уже фабрика должна располагать алгоритмом создания того или иного объекта.

    Такой подход уменьшает связность и увеличивает гибкость. Если нужно поменять код создания объектов, то правится и тестируется только класс фабрики. Все клиенты этой фабрики должны лишь знать, что гарантированно получат объект с определенным интерфейсом.
    Ответ написан
    3 комментария