🤖

BFE.dev解答記録 #2. placeholderをサポートするcurry()を実装する

2020/09/30に公開

https://bfe.dev/ja はFrontEnd版のLeetCode、GAFAの面接を受けるなら練習した方がいいかなと。
以下は自分の練習記録です。

Alt Text

第2問 BFE.dev#2. placeholderをサポートするcurry()を実装する

BFE.dev#1. curry()を実装するとちょっと違って、今度はplaceholderの対応が必要になる

curriedJoin(1, 2, 3) // '1_2_3'
curriedJoin(_, 2)(1, 3) // '1_2_3'
curriedJoin(_, _, _)(1)(_, 3)(2) // '1_2_3'

実装方針は一緒、引数の数が足りるかどうかを確認する他、placeholderの除外が必要、以下のように

const expectedArgLength = func.length
const isArgsEnough = args.length >= expectedArgLength &&
  args.slice(0, expectedArgLength)
    .every(arg => arg !== curry.placeholder)
    
if (isArgsEnough) {
  return func.apply(this, args)
} else {
  // TODO
}

引数が足りない場合は、第1問と同じ引数を保存して次回の実行に渡す。

問題は、Function.prototype.bindは引数のリストを連結するだけで、欲しいのはplaceholderの入れ替えですね。

なのでこの場合は、bind()を使うのでなく、新しいfunctionを返して、古い引数と新しい引数をいい感じにmergeするように。

if (isArgsEnough) {
  return func.apply(this, args)
} else {
  return function(...newArgs) {
    // we need merge two arg list,  newArgs and args
    const finalArgs = []
    let i = 0
    let j = 0
    while (i < args.length && j < newArgs.length) {
      if (args[i] === curry.placeholder) {
        finalArgs.push(newArgs[j])
        i += 1
        j += 1
      } else {
        finalArgs.push(args[i])
        i += 1
      }
    }

    while (i < args.length) {
      finalArgs.push(args[i])
      i += 1
    }

    while (j < newArgs.length) {
      finalArgs.push(newArgs[j])
      j += 1
    }
     
    // then just call the curried function again
    return curried(...finalArgs)
  }
}

よし、通った!

Alt Text

BFE.dev#1. curry()を実装するよりこの問題は難しい。

役に立てると嬉しいです! 次回を楽しみに!

Discussion