関数型js-独自の関数を再帰的に呼び出すことはできません

synthet1c

関数型プログラミングプリンシパルを使用して汎用reduce関数からflatten関数を生成するときに、配列flatten関数から誤った値を取得するのに問題があります。これは、呼び出し内の再帰に問題があるためだと思いますが、機能している関数と機能していない関数の両方の関数シグネチャが同じである必要があるため、それを超える方法がわかりません。

助けてくれてありがとう。

var data = [['one','two','three'], ['four', 'five', ['six']], 'seven', ['eight', 'nine']];

// here is an example of flatten that works perfectly. it takes an array and reduces 
// the internal arrays to a single flat array
function flatten( arr ){
  return arr.reduce(function( ret, curr ){
    if( Array.isArray( curr ) ){
      ret = ret.concat( flatten( curr ) );
    } else {
      ret.push( curr );
    }
    return ret;
  }, []);
}

// here is what I am trying to achieve. This one combines my reduction functon with the 
// functional `reduceWith` function. The code signature is exactly the same, however the
// end result is different.
// `functionalFlatten` does resolve to the correct function inside
var functionalFlatten = reduceWith(function( ret, curr ){
  if( Array.isArray( curr ) ){
    ret = ret.concat( functionalFlatten( curr ) );
  } else {
    ret.push( curr );
  }
  return ret;
}, []);

// this function will return a functional reduction function 
function reduceWith( fn, initial ) {
  return function _reduceWith( arr ) {
    return Array.prototype.reduce.call(arr, fn, initial || []);
  }
}

console.log('data', data);
console.log('functionalFlatten', functionalFlatten );
console.log('normal', flatten( data ));
console.log('fuctional', functionalFlatten( data ));
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>

デマルチプレクサ

コードにいくつか変更を加えました。これは機能します:

var data = [
  ['one','two','three'],
  ['four', 'five', ['six']],
  'seven',
  ['eight', 'nine']
]

function flatten(arr) {
  return arr.reduce(function(ret, curr) {
    return ret.concat(Array.isArray(curr) ? flatten(curr) : [curr])
  }, [])
}

var functionalFlatten = reduceWith(function(ret, curr) {
  return Array.prototype.concat.call(ret, Array.isArray(curr) ? functionalFlatten(curr) : [curr])
}, [])

// I assume you want to use .call to keep it functional or what ever
// But I would just do it like this:
var _functionalFlatten = reduceWith(function(ret, curr) {
  return ret.concat(ret, Array.isArray(curr) ? functionalFlatten(curr) : [curr])
}, [])

function reduceWith(fn, initial) {
  return (function (arr) {
    return Array.prototype.reduce.call(arr, fn, initial) 
  })
}

// Again, keep it simple...
function _reduceWith(fn, initial) {
  return (function (arr) {
    return arr.reduce(fn, initial)
  })
}

// You had this...
function reduceWith( fn, initial ) {
  // You don't need to name this function:
  return function _reduceWith( arr ) {
    // Let's keep this in line original function, so remove the default:
    return Array.prototype.reduce.call(arr, fn, initial || []);
  }
}

console.log('data', data)
console.log('functionalFlatten', functionalFlatten)
console.log('normal', flatten(data))
console.log('fuctional', functionalFlatten(data))

さて、実際の問題に...

var functionalFlatten = reduceWith(function( ret, curr ){
  if( Array.isArray( curr ) ){
    ret = ret.concat( functionalFlatten( curr ) );
  } else {
    // This is your culprit:
    ret.push( curr ); // push will mutate ret
  }
  return ret;
}, []);
  • reduceWith一度だけ呼び出されます(functionalFlatten定義されている場合)。
  • 内部関数は毎回呼び出されます
  • ...しかしret.push(curr)変異する可能性ありますinitial

ここに証拠があります...

function reduceWithMutationSafe(fn, initial) {
  return (function (arr) {
    // Clone initial, so that the original can't be mutated:
    var clonedInitial = eval(JSON.stringify(initial))
    return arr.reduce(fn, clonedInitial)
  })
}

var functionalFlatten = reduceWithMutationSafe(function(ret, curr) {
  if(Array.isArray(curr)) {
    ret = ret.concat(functionalFlatten(curr))
  } else {
    ret.push(curr)
  }
  return ret
}, [])

これは、functionalFlatten以前
ret.push(curr)まったく同じでクローンinitialが変更されても機能しますが、元のクローンは影響しません。

しかし、この最後のコードは単なる証拠です。を使用する必要はありませんreduceWithMutationSafe

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

非関数型 'String'の値を呼び出すことはできません

分類Dev

非関数型 'String'の値を呼び出すことはできません

分類Dev

非関数型 'String'の値を呼び出すことはできません

分類Dev

非関数型「UIImage?」の値を呼び出すことはできません

分類Dev

非関数型「CIImage?」の値を呼び出すことはできません

分類Dev

非関数型の値を呼び出すことはできません:UITableView

分類Dev

非関数型 'UIScreen'の値を呼び出すことはできません

分類Dev

非関数型の値を呼び出すことはできません '[UIImage]

分類Dev

非関数型DateCallBackの値を呼び出すことはできません

分類Dev

.attrの後に関数を呼び出すことはできません

分類Dev

REST関数を呼び出すことはできません

分類Dev

PHP関数を呼び出すことはできません

分類Dev

ラムダ関数はそれ自体をPythonで再帰的に呼び出すことができますか?

分類Dev

jqueryで関数を再帰的に呼び出すことができないのはなぜですか?

分類Dev

jqueryで関数を再帰的に呼び出すことができないのはなぜですか?

分類Dev

if()内で別の関数を呼び出すことはできません

分類Dev

typeaheadを別の関数内で呼び出すことはできません

分類Dev

クラスの添え字は、非関数型の値を呼び出すことはできません

分類Dev

JavaScript 関数を相互に呼び出すことはできません

分類Dev

ResponseSerializer 'はSwift3で非関数型' NSHTTPURLResponse? ''の値を呼び出すことができません

分類Dev

QSslSocket:未解決の関数を呼び出すことはできません

分類Dev

小道具の子関数を呼び出すことはできません

分類Dev

CoreDataを使用して非関数型「NSManagedObjectContext」の値を呼び出すことはできません

分類Dev

非関数型の値を呼び出すことはできません '((UInt)-> Data?)!' Alamofire4を使用

分類Dev

Swift3-非関数型 'XCUIElement'の値を呼び出すことはできません

分類Dev

非関数型の値を呼び出すことはできません '((AnyObject)-> AnyObject?)!' -スウィフト3

分類Dev

コンストラクターの子型から関数を呼び出すことはできません

分類Dev

iOS-非関数型「NSProgress」の値を呼び出すことはできません

分類Dev

非関数型「HTTPURLResponse?」の値を呼び出すことはできません Alamofire 4、Swift 3

Related 関連記事

  1. 1

    非関数型 'String'の値を呼び出すことはできません

  2. 2

    非関数型 'String'の値を呼び出すことはできません

  3. 3

    非関数型 'String'の値を呼び出すことはできません

  4. 4

    非関数型「UIImage?」の値を呼び出すことはできません

  5. 5

    非関数型「CIImage?」の値を呼び出すことはできません

  6. 6

    非関数型の値を呼び出すことはできません:UITableView

  7. 7

    非関数型 'UIScreen'の値を呼び出すことはできません

  8. 8

    非関数型の値を呼び出すことはできません '[UIImage]

  9. 9

    非関数型DateCallBackの値を呼び出すことはできません

  10. 10

    .attrの後に関数を呼び出すことはできません

  11. 11

    REST関数を呼び出すことはできません

  12. 12

    PHP関数を呼び出すことはできません

  13. 13

    ラムダ関数はそれ自体をPythonで再帰的に呼び出すことができますか?

  14. 14

    jqueryで関数を再帰的に呼び出すことができないのはなぜですか?

  15. 15

    jqueryで関数を再帰的に呼び出すことができないのはなぜですか?

  16. 16

    if()内で別の関数を呼び出すことはできません

  17. 17

    typeaheadを別の関数内で呼び出すことはできません

  18. 18

    クラスの添え字は、非関数型の値を呼び出すことはできません

  19. 19

    JavaScript 関数を相互に呼び出すことはできません

  20. 20

    ResponseSerializer 'はSwift3で非関数型' NSHTTPURLResponse? ''の値を呼び出すことができません

  21. 21

    QSslSocket:未解決の関数を呼び出すことはできません

  22. 22

    小道具の子関数を呼び出すことはできません

  23. 23

    CoreDataを使用して非関数型「NSManagedObjectContext」の値を呼び出すことはできません

  24. 24

    非関数型の値を呼び出すことはできません '((UInt)-> Data?)!' Alamofire4を使用

  25. 25

    Swift3-非関数型 'XCUIElement'の値を呼び出すことはできません

  26. 26

    非関数型の値を呼び出すことはできません '((AnyObject)-> AnyObject?)!' -スウィフト3

  27. 27

    コンストラクターの子型から関数を呼び出すことはできません

  28. 28

    iOS-非関数型「NSProgress」の値を呼び出すことはできません

  29. 29

    非関数型「HTTPURLResponse?」の値を呼び出すことはできません Alamofire 4、Swift 3

ホットタグ

アーカイブ