Пользователь
0,0
рейтинг
16 июня 2014 в 10:33

Разработка → Интересная задачка для интервью, карринг и частичное применение функции из песочницы

Хожу по job interview. Где-то скучно, где-то весело. Где-то интересно. На одном из таких меня попросили написать функцию, которая умеет складывать два числа. Я написал:

  it ('should add two numbers', function () {
    var add = function (a,b) {
      return a + b;
    };

    assert.equal(add(2,3), 5);
  });


А если, говорят, сигнатура функции должна быть типа такой: add(num1)(num2)? Не вопрос, говорю. Думая, что хитрый буржуин хочет проверить, знаю ли я про то, что можно возвращать функции из функций, пишу вот такое:

  it ('should be called like add(num1)(num2)', function () {
    var add = function (a) {
      return function (b) {
        return a + b;
      };
    };

    assert.equal(add(2)(3), 5);
  });




А вдруг нам первое слагаемое известно заранее, а вот второе будет известно потом, что делать? Ага, думаю, про currying разговор ведут. Вот:

    var add3 = add(3);
    assert.equal(add3(4), 7);
    assert.equal(add3(5), 8);


Тут вдруг в комнату набежало еще двое, и начали они вчетвером меня распрашивать, махают руками, говорят громко. Не дают сосредоточиться, хотят посмотреть на то, как я думаю. Началось самое интересное.

Спрашивают — а вдруг нужно сложить три числа? Или четыре? Говорю, что надо тогда запоминать состояние, примерно так:

  it ('should take random number of digits', function () {
    var add = function (a) {
      var sum = a;
      var inner = function (b) {
        if (b) {
          sum += b;
          return inner;
        } else {
          return sum;
        }
      };
      return inner;
    };

    assert.equal(add(2)(3)(), 5);
    assert.equal(add(2)(3)(6)(), 11);
  });


Зачем, спрашивают, у тебя внутри if есть? А чтоб внутренняя функция знала, как она вызывается — в цепочке или в самом конце и, соответственно, возвращала бы себя или число. Ладно, говорят, пока ладно. А если опять надо частичное применение? Пишу:

    var add2 = add(2);
    assert.equal(add2(6)(), 8);


А можно, спрашивают, как-нибудь избавиться от пары пустых скобок вконце? Задумался… Это же функция должна как-то сообразить, в каком контексте ее вызывают… А, есть же волшебный `.valueOf`! И от лишнего if заодно можно избавиться. Ну-ка:

    var add = function (a) {
      var sum = a;

      var inner = function (b) {
        sum += b;
        return inner;
      };

      inner.valueOf = function () {
        return sum;
      };

      return inner;
    };

    assert.equal(add(3)(4), 7);
    assert.equal(add(3)(5), 8);
    assert.equal(add(9)(-5), 4);
    assert.equal(add(1)(2)(3), 6);  


а теперь примени-ка эту add2 к другому числу, скажем, 10 — и чтоб 2+10=12 получилось. Добавляю строку, получаю:

    var add2 = add(2);
    assert.equal(add2(6)(), 8);
    assert.equal(add2(10)(), 12);  


Не работает! Возвращает 18. Это, объясняю, так и задумано — оно внутри запоминает результат последнего сложения и использует для последующих операций. Они — надо исправить, чтоб так явно не запоминало. Хорошо, говорю. Хотите чистых функций? Хотите совсем интересно? Нате цепочку conditional identities:

    var add = function (orig) {
      var inner = function (val) {
        return add(parseInt(val+'', 10) == val ? inner.captured+val : inner.captured);
      };
      inner.captured = orig;
      inner.valueOf = function () {return inner.captured;};

      return inner;
    };

    assert.equal(add(3)(4), 7);
    assert.equal(add(3)(4)('aa')(5)(), 12);

    var three = add(3);
    var four = add(4);
    assert.equal(three, 3);
    assert.equal(four, 4);
    assert.equal(three(5), 8);
    assert.equal(three(6), 9);
    assert.equal(three(four), 7);
    assert.equal(three(four)(three(four)), 14);


А зачем, спрашивают, нужна вот эта пустая строка:
  ... parseInt(val+'', 10) ...


Это для принудительного запуска `.valueOf`. Потому что, говорю, если `val` — это функция (что верно для случая, скажем, `three(four)`), то `parseInt` не станет запускать механизм преобразования типов, который в конце концов вызовет `.valueOf`. А `parseInt(func)` — всегда `NaN`.

Смотрю на них — молчат. Не заметили лишнего присваивания, значит. Ладно, надо довести оптимизацию до логического конца. Пишу последний вариант:

    var add = function (orig) {
      var inner = function (val) {
        return add(parseInt(val+'', 10) == val ? orig+val : orig);
      };
      inner.valueOf = function () {return orig;};

      return inner;
    };


Симпатично и минималистично. Тесты в точности те же самые.

Вообще все четырехчасовое интервью получилось весьма полезным. Но окончилось не очень — говорят, тебе у нас не интересно будет. Нам нужны люди, которые будут сидеть с утра до вечера и делать, что сказано, не выпендриваясь и не креативя. Креативом у нас начальство занимается, и у нас его вон уже сколько, новых не надо. Так что тебе вскорости станет скучно, будешь искать себе новую работу. А нам, говорят, текучка ни к чему. А что же тогда, говорю, на интервью позвали, вопросы интересные задавали, задачки решали? А, говорят, звал тебя отдел кадров, а мы думали тебя завалить и тогда тебе не так обидно было бы — не взяли потому, что глупый. А сейчас вот выходит, что не взяли потому, что умный. Легче тебе от этого, спрашивают?

И поехал я домой…

Полный исходник в виде теста на гитхабе: github.com/nmakarov/excercises
Петрович @nmakarov
карма
27,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (74)

  • +27
    Ну что за люди пошли… умных у них хватает, глупых тоже не надо…
    • +11
      Они не «умные», им самим нужно поучиться менеджменту. Не умеют использовать мозг других людей в интересах компании.
    • +3
      На самом деле эта ситуация не так уж и идиотична, как может показаться. Большая корпорация не может делать ставку на одного конкретного человека (если, конечно, его не зовут Элон Маск или Стив Джобс). Работники должны быть взаимозаменяемы, а весь процесс — задукоментирован и стандартизован. Шибко умный гарантировано не впишется в такой процесс. Беда в том, что местная политкорректность не позволяет в объявлении о работе написать конкретно про тип и стиль отдела, где соискателю предстоит работать — а стили эти весьма и весьма отличаются. Два последних проекта я специально искал в «болоте» — транснациональных корпорациях, где все предсказуемо и четко. Скучно, правда, но большие деньги. И не штормит. К текущему моменту отдохнул, и уже хочу щупать новых технологий и смотреть в горящие глаза, так сказать. Статистически (вот прямо из личного опыта) — из семнадцати компаний, где у меня были интервью за последний месяц, такая молодая-активная-технологичная-анархическая — попалась всего одна. Так что выбирать не из чего :)
  • –30
    image
    • +29
      Вообще-то я ходил на интервью в американскую контору, неподалеку от вашингтонского обкома.
      • +1
        Что ж, тогда извините, шутка не удалась.
        • 0
          Ещё как удалась. Вашингтон — это же Россия. Расслабься :)
      • +57
        Этот неловкий момент, когда поросёнок Пётр не знает, что ответить.
      • –22
        Товарищи, что вы хотите сказать всеми этими минусами? Что в России такого нет? В статье нет ни слова о том, что собеседование было в Америке.
        Или это такая фанатичная любовь к России и нежелание признавать косяки процесса отечественной веб-разработки? Поясните, хотя бы…
        • +6
          Ну, во-первых, постинг «смешных картинок» сам по себе надоел. Во-вторых, тут ещё и шутка не удалась. Зато удалась шутка «Этот неловкий момент, когда поросёнок Пётр не знает, что ответить.»
          • –8
            Меня поражает то, что за плохую шутку можно получить больше минусов в карму, чем плюсов за хорошую статью.
            • +45
              Вот тут твоя картинка отлично вписалась бы.
            • +3
              Просто вы сравниваете эффект от катастрофически ужасного комментария и умеренно полезной статьи. Эффект по модулю от катастрофически ужасного комментария и умопомрачительно потрясающей статьи примерно равный, тут всё честно. Проблема в том, что первое написать несравнимо проще, чем второе…
        • +14
          Видимо, хотим сказать, что хоть хабр и не для политики, но откровенная русофобия, особенно беспричинная, тут тоже не приветствуется.
          • +1
            Да ну какая русофобия, какая политика, бросьте… Это просто неудачная шутка.
      • 0
        Тогда может быть к нам хотите прийти пообщаться на тему работы?
  • 0
    Идиоты… да простит меня «работодатель» =)
    А вообще от таких комманд надо бежать что есть мочи, ибо нет на свете большего зла, нежели держащийся зубами за кресло коллектив.
    • +3
      Бежать — в точку. Я решил с глобальными корпорациями не сотрудничать пока. ПередохнУть надо. В корпорациях — много денег, членство в фитнесс-клубе и бесплатные завтраки. И никакого личностного и професионального роста (и сплошной микрософт). Я вот сейчас решил вложить свои ближайшие пол-года в стартап. Полная анархия, любые технологии, лишь бы работало. Буду учить Erlang и Ruby, наверно.
      • 0
        Работаю год в стартапе, теперь вот охота в корпорацию, нервы уже заканчиваются на все эти «Полная анархия, любые технологии, лишь бы работало». Особенно устал от «лишь бы работало». С профессиональным ростом тоже не всё хорошо, учиться не у кого, спецов не хватает, что-то хорошо изучить самому тяжело, т.к. времени на изучение не всегда много, т.к. надо быстрее, а не качественнее…
      • +3
        Лучше не надо руби, Эрланг же с хаскелем замечательно пойдет!
        • +1
          На Ruby сидит вся Силиконовая долина, так что иметь в портфолио пару сделанных RoR проектов полезно для карьеры. Хаскель должен щупать каждый современный программер, потому как вправляет мозги и повышает качество кода (в свое время сделал первые 50 задачек из Project Euler на Хаскеле исключительно для этой цели). Но мне почему-то кажется, что для реальных проектов Хаскель нежизнеспособен. Я, конечно, знаю пару людей, которые на нем пишут всякие крутые штуки, но…
          • 0
            Блин, не Силиконовая, а Кремниевая. Кремниевая долина. Ну мы же образованные люди. Давайте называть вещи их именами.
            • –2
              Здравсвуй, брат, я уже не думал, что найду хоть кого-то, кто правильно называет это место. Спасибо.
          • 0
            До сих пор сидят? Я думал тренд прошел уже, или они теперь пожинают плоды?)
            • 0
              Реально сидят. Я вот сейчас искал себе работу, и недели не проходило, чтоб какой-нибудь агент меня не дергал насчет Руби в окрестностях Сан-Франциско. Я им — ну вы же резюме читали, нет там никакого Руби. Они — ну ты же веб-девелопер, вдруг знаешь. И насчет зарплат, Руби-девы у них там получают примерно так же, как ДжаваСкрипторы, что обычно процентов на тридцать больше, чем чисто ПХПшники. Вообще, я думаю, Руби-на-Рельсах у них рванул, потому что Джава — уже не модно, а .NET — не круто и для лохов Про .NET не я придумал, это мне один стартапер сообщил (Кстати, на днях прогорел уже со своими Руби :)
              • 0
                Что значит прогорел? И кстати, как же скала, она сейчас даже в Раше вроде в моде) Хотя судя по всему там по-быстрее мода меняется, чем в СФ
                • 0
                  Скальщиков — единицы. Причина — сложно найти рабротников, так что нет вакансий. Вот и нет программеров. Такая же фигня с некоторыми другими технологиями. Я тут общался с владельцем одного видеохостинга (хотят побить Netflix), спрашивал, почему у них не Erlang. Ответ — невозможно найти программеров, ни за какие деньги.

                  А прогорел — значит прогорел. Не смог вовремя найти очередной мешок денег (с инвесторами не сложилось, наверное) и все.
                  • 0
                    А если брать Python?
  • 0
    Вот у таких компаний потом и висят открытые позиции по 2 года.
    • +3
      Не, программеров-середнячков тут реально много. И у них весьма четкое разделение по национальному признаку. На эту конкретную позицию возьмут, скорее всего, китайца. Они весьма, хмм… усердны. И не лезут, куда не надо.
      • +1
        Тайный гиковский апартеид.
      • +3
        А можете подробнее рассказать про разделение по национальному признаку? Про разные национальности, по отношения к ним и т.п. Лучше даже отдельной статьёй. Было бы очень интересно почитать.
        • +20
          Раз пять начинал писать ответ, но все какой-то неполиткоректный расизм получается, хоть и заходил с разных сторон. Пробую в шестой раз.

          Две американки филипинского происхождения (бизнес-аналист и проджект-менеджер) коряво рисуют wireframes и подробно расписывают всяческие user stories. Лондонское дизайн-бюро берется нарисовать/наверстать красивых HTML+CSS (на деле отдают на оутсорс индусам, а сами только правят конечный вариант, но в коде кое-где попадаются комментарии на индусском английском). Этот дизайн достается канадским китайцам (которые очень хреново говорят по-английски) которые, на самом деле, junior-Java-backend-что-то там, но упрямо делают вид, что пишут на джаваскрипте и ExtJS. Упорно с утра до вечера пишут горы кода, который все равно нихера не работает. Про тесты слышали, даже сделали чего-то там, но все равно билд запускают со --skip-tests, потому что иначе валится. Билд-система, естественно, на Maven (тяжелое Java-наследие). Спустя четыре месяца во время очередной демонстрашки к видеоконференции подключается один из CTO (канадец немецко-датских кровей), система некстати валится, все получают мощный втык (а кое кто и пендель под зад), а разработка переезжает в филиал в Hong-Kong, которые втихаря оутсорсят в Индию, по совпадению тем же индусам, которые рисовали HTML. Пока эти индусы делают вид, что работают, местные канадские индусы — спецы по Oracle валят систему и уходят в глухую несознанку, обвиняя во всем Jenkins (с какого-то перепугу). Тут неожиданно происходит десант разнокалиберного начальства, свежевыгнанных китайцев берут обратно на работу делать надстройку над java-middleware, местных индусов отправляют в Индию помогать тамошним индусам, нанимают еще филипинцев рисовать бизнес-диаграммы, пару канадцев и одного американца координировать девелоперов и через месяц проект окончательно клинит, потому что все на всех показывают пальцами и обвиняют во всех девелоперских грехах. Программить некогда — все круглосуточно сидят на митингах. Тут опять происходит явление CTO народу, китайцев опять выгоняют (потому что контрактники), индусы коллективно получают втык, говорят, что вся беда и зло от ExtJS и надо все переделать в Dojo, потому что IBM. Им дают карт-бланш и они нанимают субподрядчика для делания build pack'а, который благополучно растворяется в Лондонском тумане со всеми деньгами и сроками (догадайтесь с одного раза, какую компанию в Лондоне они наняли). Вот в этом месте наступает реальная задница, потому как новая система уже разрекламирована в национальной прессе, и даже брошюры уже отпечатаны и разосланы клиентам. Никто уже никуда не бегает, все (включая среднее начальство) спокойно сидят и рассылают резюме. Тут появляется русский девелопер. На самом деле он был тут изначально, просто его и его идеи никого не интересовали, а филиппинские тетки вообще четко, внятно и сразу сказали, чтоб он не лез, куда не надо. Сейчас же ситуация безвыходная, и все идеи хороши. А идеи такие — повыкидывать всю избыточную функциональность, оставить пару интересных опций, назвать этот минимализм первым релизом, убедиться, что оно выдержит пару сотен тысяч клиентов и, затаив дыхание, запустить в продакшн. Через неделю код в продакшне, а тим круглосуточно в офисе наживую фиксит баги под лидерством русского программера. Еще через неделю все выдохнули — все ведь зашибись работает. Еще через неделю филиппинские тетки опять начали рисовать wireframe'ы, индусские индусы — потирать руки в предвкушении заказов, канадские китайцы — пожимать плечами, потому как это все копошение не способно поколебать ихний дзен, а русский программер уволился нафиг. Ибо нефиг.

          Я ответил на ваш вопрос?
          • +2
            Жаль что топику уже больше суток и этот комментарий мало кто прочитает. Из него могла бы получиться отличная статья.
            • 0
              В этом и смысл – не хочу разводить холивары на пустом месте.
          • +1
            Как-то черезчур правдоподобно, непридуманная история?
            • +2
              Ну конечно же чуть приврал, как же без этого? Но вообще это все фактически срисовано с моего позапрошлого контракта. И это сейчас вспоминать весело, а тогда было ой не до смеха.
              • +1
                Боюсь спрашивать: а кто был русским программистом? Уж не вы ли?
                • +2
                  Ну конечно же, я, кто ж еще :)

                  На самом деле так обычно и происходит. Наш программер обычно универсален, креативен и болеет душой за проект. Есть немного буржуйских начальников, которые это понимают и которым подходит такой стиль работы подчиненных. Тогда в компании получается сразу много русских программеров и контора тогда процветает. Праавда, бывает и наоборот — мы так же известны своим разгильдяйством и запросто можем ушатать крепкий бизнес :)
  • 0
    Меня такую же задачу на интервью в яндексе спрашивали.
    • 0
      И как результат?
      • 0
        Решил, но только мне toString в голову пришел а не valueOf.
  • 0
    С valueOf красиво получилось. Возьму на вооружение
  • +4
    Вариант с if(b) содержит ошибку. Попробуйте вычислить add(2)(0)(3)()
    • +1
      Я тоже в этом месте подумал про
       'undefined'===typeof b
      

      или
       undefined===b
      

      или
      arguments.length
      
  • +2
    А если, говорят, сигнатура функции должна быть типа такой: add(num1)(num2)?

    Вот тут уже и становится понятно, что собеседование пошло не так — либо это действительно прийдется использовать по работе, либо они хотят от вас странного.
    Это как если на собеседовании архитектора будут спрашивать «а если надо построить это на луне Юпитера и из пенопласта?». И пусть он может даже в этом разбираться, но должность и оплата завялены были для строительства коттеджей.
    • –3
      Ок, так лучше:

      var sum = add(num1);
      alert(sum(num2)); // алерт для примера, что бы что-то сделать с результатом

      Это базовые вещи, которые не знать глупо…
      • –2
        Ок, переиначу: я знаю как сделать тринитротолуол, но если меня будут это спрашивать на собеседуя на программиста, то это будет первый звоночек.

        Возвращаясь к теме автора я не вижу никакой фактической полезности в этой задаче, умение сделать задачу с implicit преобразованием класса в функцию или число это похвально как хобби, но если это понадобится для проекта, либо активно там используется, то черт рад такому проекту.
  • +17
    Четырехчасовое интервью и такой финал. Офигеть!
    Что за контора такая мудацкая, огласите уж.
    Может кто-нибудь 4 часа сэкономит.
  • +2
    Мне как то раз так же ответили в Яндекс… почему то было обидно. :(
  • +10
    Вот вам ещё 3 теста, которые не проходит ваш текущий код:

    assert.equal(add(0)(0.5), 0.5);
    assert.equal(add('aa')(1), 1);
    assert.equal(add('aa'), 0);
    


    Лучше заменить parseInt(val+'', 10) на более стандартное приведение к числу +val (оно вызовет .valueOf), а если предполагаем что строки и другие объекты у нас считаются нулями (с чем я бы поспорил), то добавляем "|| 0". Получаем короче и симметричнее:

    var add = function (orig) {
      var inner = function (val) {
        return add((+val || 0) + (+orig || 0));
      };
      inner.valueOf = function () {return +orig || 0;};
    
      return inner;
    };
    
    • +2
      Вот возращением хитрых функций для последующего использования в JS я занимался, но вот рекурсивный вызов для ()() не попадался (кроме книжных примеров как с add). Это на практике где то используется?
      • –1
        вот мне тоже интересно, чего стараются добиться интервьюеры, предлагая подобные задачи на собеседовании? интересный трюк, забавный. но какова практическая польза? ведь, если кто-то напишет такой чудо-код для продакшен, сами же выгонят за проф.невменяемость.
        • 0
          Частичное применение вполне полезный прием, когда понимаешь как работает. Вот пример из живого проекта:

          cas.on(cas.EVENT_CA_EXTENDED_MESSAGE, ui.emit.bind(ui, ui.EVENT_SHOW_POPUP));
          


          Аналог без частичного применения:

          cas.on(cas.EVENT_CA_EXTENDED_MESSAGE, function (message) {
            ui.emit(ui.EVENT_SHOW_POPUP, message);
          });
          


          Пробрасывает событие с новой меткой, почему бы и нет…
          • 0
            Ага, я что то подобное то же делаю, но не для экономии 2 строчек а сразу так 100. ;)
            Только почему у меня странное дежавю… как будто это декоратор из Python.
          • +1
            придумать реализацию для функции высшего порядка, которой часто пользуешься — наивную как в underscore или быструю как lodash — почему бы нет. но в описанном случае ведь ежу понятно, что карринг и частичное применение функций — разные вещи. для карринга арность функции должна быть фиксированой (см. определение). а то что было предложено сделать это плод какого-то нездорового воображения.
        • +5
          В больших корпорациях подавляющее большинство технических интервьюеров — какие-то девелоперы, зачастую даже не имеющие отношение к отделу или проекту, куда хотят нанять человечка. Это вроде как обязательная отработка, сидеть на таких интервью (сам часто сидел, знаю). На таких интервью очень часто спрашивают заковыристые штуки, недавно прочитанные в какой-нибудь статье, и мало имеющие отношение к реальной работе или, что хуже, очень конкретно-специфические вещи (точные параметры функций, к примеру), которые никто не помнит, потому что они гуглятся за 10 секунд. В этом случае практической пользы не так чтобы много, но все-таки можно вытянуть разговор в нужное русло, чтобы очаровать остальных не шибко технических присутствующих товарищей. Главное – что? Главное — уметь решать задачи. Выкрутиться из такой противной ситуации — это тоже задача, так?
          И меньшинство случаев тоже имеется. Реальные задачи, где надо в натуре понимать паттерны и шаблоны, потому как на этом у них строится вся кодовая база.
          Ну и экстремальные случаи встречаются. Уникумы. К примеру, у меня был один такой — там в натуре надо было натягивать глаз на задницу через ухо — не просто написать тестовое задание, но написать его с использованием некоего фреймворка, и в задании были прописаны совершенно нежизнеспособные обязательные ответвления, чтоб использовать разные особенности этого фреймворка. Я там убил два с половиной дня, чтоб оно все заработало как надо, потому как документации практически никакой, комьюнити отсутствует, гугль ничего не знает, а код этого фреймворка ужасен в своей эпичности — фабрики классов, производящие другие фабрики и прочая прелесть. Была выдана даже ссылка на ютуб с презентацией этого фреймворка на какой-то конференции. Количество просмотров этой презентации было 78. За год. Наверно, половина просмотров — такие же несчастные соискатели, как и я. Муть полнейшая. Зато из презентации я узнал, что интервьюер — это как раз автор этого фреймворка. Мне потом агент сказал, что этот автор уже несколько месяцев пытается кого-то нанять на работу.
    • 0
      Дальше оптимизируем для множественных обращений :)
      var add = function (n) {
      
          var orig = +n || 0,
              inner = function (val) {
                  return add((+val || 0) + orig);
              };
      
      
          inner.valueOf = function () {return orig;};
      
          return inner;
      
      };
      
    • +1
      по вашему примеру, если разрешить складывать произвольные значения, а не только числа:

      assert.equal(add('aa')(1), 'aa1');
      

      то получается еще короче:

      var add = function (orig) {
        var inner = function (val) {
          return add(orig + val);
        };
        inner.valueOf = function () {return orig;};
      
        return inner;
      };
      
    • 0
      Отлично. Добавил в гитхаб с указанием авторства.
  • +3
    Я не знаток в JS. Расскажите пожалуйста что это за странное начало кода it ('text', function () {? Я как бы понимаю ещё такое начало (function () { (создаём отдельный приватный контекст), но причём тут it и текст в начале? И желательно линк на чтиво.
    • +4
      Это же тесты так пишут. Если надо чего оттестировать, заворачивают код в describe('test name', function () { /* вот тут тестируемый код */});
      Ну и всякие assert и should используют. Короче, visionmedia.github.io/mocha/
      • 0
        Премного благодарен. Никогда не связывался с тестированием JS, очень познавательно.
  • 0
    Интересная задача. Я не смог удержаться и прежде чем читать спойлеры в комментариях решил сделать свою реализацию )

    var add = function (x) {
        x = +x;
        var adder = function (y) {
            y = +y;
            return add(x + y);
        };
        adder.valueOf = function () {
            return x;
        };
        adder.toString = function () {
            return x.toString();
        };
        return adder;
    };
    

  • 0
    небольшой апгрейд :)

    var sum = function (args) {
      return Array.prototype.slice.call(args).reduce(function (m, el) { return m + el; }, 0);
    };
    
    var add = function () {
      var orig = sum(arguments);
      var inner = function () {
        var val = sum(arguments);
        
        return add((+val || 0) + (+orig || 0));
      };
      inner.valueOf = function () {return +orig || 0;};
    
      return inner;
    };
    
    assert.equal(add(2, 0)(3), 5);
    
    • 0
      Прикольно. Добавил в гитхаб с указанием авторства.
    • 0
      Скажите, а какой смысл делать операцию +||0 уже после sum()? По-хорошему, эту операцию должна сама sum делать.
  • +1
    вдруг кому-нить будет интересна такая задачка
    function sum(a,b) {return a+b}
    function mul(a,b) {return a*b}
    var a = make(1)(2)(3)(4)(5)
    var b = make(2)(3)(4)
    
    a(sum) // 15
    b(sum) // 9
    a(mul) // 120 
    b(mul) // 24
    

    смысл понятен — применить к последовательности заранее не известную функцию
    решили?
    … а теперь тоже самое только без массивов )
    • 0
      Скрытый текст
      function make(x){
        var args = [];
        function f(y){
          if(typeof y == 'function')return args.reduce(y);
          return args.push(y), f;
        }
        return f(x);
      }
      
      function make(x){
        function f(){
          var y = Array.prototype.pop.call(arguments);
          if(typeof y == 'function')return Array.prototype.reduce.call(arguments, y);
          return f = f.bind(null, y);
        }
        return f(x);
      }
      

      Вот только толку от второго варианта? :) Ни скорости, ни красоты функциональщины.
      • +4
        Я думаю, rmaksim имел в виду СОВСЕМ без массивов
        function make(x) {
          return f(function(y) { return x; });
        
          function f(h) {
            return function(x) {
              if(typeof x == 'function') return h(x);
              return f(function(y) { return y(x, h(y)); });
            }
          }
        }
        
        • +1
          Так во 2ом варианте массива и нет СОВСЕМ, только аргументы :) Хотя да, ваш вариант посимпатичней, после 3 дней без сна сразу до такого не додумался.
          • +1
            красиво ), плюсую, правда виртуально )
  • НЛО прилетело и опубликовало эту надпись здесь

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.