面接、カレー、および関数の部分適用のための興味深いタスク

面接に行きます。 どこか退屈で、どこかで楽しい。 どこか面白い。 これらの1つで、2つの数値を追加できる関数を作成するように求められました。 私が書いた:



  それ(「2つの数字を追加する必要があります」、関数(){
     var add = function(a、b){
       a + bを返します。
     };

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




そして、彼らが言うならば、関数の署名は次のようなものでなければなりません:add(num1)(num2)? 質問はありません、私は言います。 cなブルジョアは関数から関数が返されることを知っているかどうかをチェックしたいと考えているので、これを書きます。



  それ(「add(num1)(num2)のように呼び出す必要があります」、function(){
     var add = function(a){
      リターン関数(b){
         a + bを返します。
       };
     };

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








最初の用語が事前にわかっていて、2番目の用語が後でわかる場合はどうすればよいですか? うん、彼らはカレーについて話していると思う。 ここに:



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




それから突然2人が部屋に駆け込んで来て、4人が私に質問し始め、手を振り、大声で話しました。 彼らは私を集中させません。彼らは私がどう思うかを見たいです。 楽しみが始まりました。



彼らは尋ねます-3つの数字を追加する必要がある場合はどうなりますか? または4つ? 次に、次のような状態を覚えておく必要があると言います。



  それ(「ランダムな桁数をとる」、関数(){
     var add = function(a){
       var sum = a;
       var inner = function(b){
         if(b){
           sum + = b;
          戻り値;
         } else {
          戻り値;
         }
       };
      戻り値;
     };

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




なぜ、彼らは尋ねる、あなたは中にいるのですか? そして、内部関数は、それが呼び出される方法を知っているように-チェーン内または最後で、それに応じて、それ自体または数値を返します。 いいでしょういいでしょう そして、再び部分的なアプリケーションが必要な場合はどうなりますか? 私は書いています:



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




そして、彼らは、どういうわけか、最後にいくつかの空のブラケットを取り除くことができますか? 思った...この同じ関数は、それが何のコンテキストで呼ばれているのかを何らかの形で理解するはずです...ああ、魔法の `.valueOf`があります! 同時に過剰なものを取り除くことができます。 まあ:



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

       var inner = function(b){
         sum + = b;
        戻り値;
       };

       inner.valueOf = function(){
        戻り値;
       };

      戻り値;
     };

     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を返します。これは、意図したとおりです-最後の追加の結果を内部的に記憶し、後続の操作に使用します。 彼ら-それは明らかに覚えていないように修正する必要があります。 いいでしょう きれいな機能が必要ですか? かなり面白いですか? 条件付きIDのチェーンは次のとおりです。



     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;};

      戻り値;
     };

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

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




そして、なぜ、空の行が必要なのかと彼らは尋ねます:

   ... parseInt(val + ''、10)...




これは、 `.valueOf`を強制的に実行することです。 なぜなら、 `val`が関数(たとえば、` 3(4) `の場合に当てはまる)である場合、` 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;};

      戻り値;
     };




素敵でミニマル。 テストはまったく同じです。



一般に、4時間のインタビュー全体が非常に有用であることが判明しました。 しかし、それはあまり終わりませんでした-彼らはそれが私たちにとって面白くないだろうと言います。 朝から夕方まで座って、自慢せずに創造性を失わずに言われたことをする人が必要です。 私たちの上司は創造的な仕事に携わっており、すでに多くの人がいます。新しい人は必要ありません。 だからあなたはすぐに退屈するでしょう、あなたは新しい仕事を探します。 そして、彼らは言う、仕事の必要はありません。 そして、私が言うには、彼らはインタビューを求め、興味深い質問をし、問題を解決しましたか? そして、彼らは言う、人事部はあなたに電話した、そして私たちはあなたが失敗するだろうと思った、そしてあなたはそれほど気分を害することはないだろう-それは愚かだったので、彼らはそれを取らなかった。 そして今、彼らはそれがスマートだから彼らはそれを取らなかったことが判明しました。 これからもっと簡単に、彼らは尋ねる?



そして私は家に帰りました...



githubのテストとしての完全なソースコード: github.com/nmakarov/excercises



All Articles