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

Хожу по 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
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 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
                                                                      красиво ), плюсую, правда виртуально )
                                                              • НЛО прилетело и опубликовало эту надпись здесь

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