RangeError: Maximum call stack size exceeded (Babel Ramda)
RangeError: Maximum call stack size exceeded (Babel Ramda)
此代码在其下方生成堆栈跟踪:
import R from 'ramda';
function quicksort(list) {
if ( R.isEmpty(list) ) return list;
let pivot = R.head(list);
let lesser = R.filter( e => e < pivot , list );
let greater = R.filter( e => e >= pivot, list );
return R.concat( quicksort(lesser), pivot, quicksort(greater) );
}
var sorted = quicksort([2,3,1]);
console.log(sorted);
堆栈跟踪:
$ babel-node quicksort2015.js
/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/es6.object.to-string.js:3
var classof = require('./$.classof')
^
RangeError: Maximum call stack size exceeded
at Array.toString (native)
at module.exports
(/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/$.cof.js:4:19)
at module.exports
(/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/$.classof.js:13:13)
at Array.toString (/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/es6.object.to-string.js:8:25)
at type (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:3345:100)
at f1 (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:166:27)
at _equals (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:4038:13)
at equals (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:4664:16)
at f2 (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:201:24)
at Object.isEmpty (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:5220:29)
虽然那个 babel 会处理尾调用优化?反正这么短的名单,应该不会那么深吧?
这是因为过滤了整个列表,而不是过滤了 lesser
和 greater
的列表尾部。
例如您可以尝试以下操作:
function quicksort(list) {
if (list.length <= 1) return list;
var x = R.head(list);
var xs = R.tail(list);
var lesser = R.filter(R.lt(R.__, x), xs);
var greater = R.filter(R.gte(R.__, x), xs);
return R.concat(quicksort(lesser), R.prepend(x, quicksort(greater)));
}
不幸的是,这也没有从尾调用优化中受益,因为对 quicksort
的递归调用不在尾调用位置。
此代码在其下方生成堆栈跟踪:
import R from 'ramda';
function quicksort(list) {
if ( R.isEmpty(list) ) return list;
let pivot = R.head(list);
let lesser = R.filter( e => e < pivot , list );
let greater = R.filter( e => e >= pivot, list );
return R.concat( quicksort(lesser), pivot, quicksort(greater) );
}
var sorted = quicksort([2,3,1]);
console.log(sorted);
堆栈跟踪:
$ babel-node quicksort2015.js
/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/es6.object.to-string.js:3
var classof = require('./$.classof')
^
RangeError: Maximum call stack size exceeded
at Array.toString (native)
at module.exports
(/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/$.cof.js:4:19)
at module.exports
(/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/$.classof.js:13:13)
at Array.toString (/Users/ivan/.nvm/versions/node/v4.1.2/lib/node_modules/babel/node_modules/babel-core/node_modules/core-js/modules/es6.object.to-string.js:8:25)
at type (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:3345:100)
at f1 (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:166:27)
at _equals (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:4038:13)
at equals (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:4664:16)
at f2 (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:201:24)
at Object.isEmpty (/Users/ivan/dev/quicksort/node_modules/ramda/dist/ramda.js:5220:29)
虽然那个 babel 会处理尾调用优化?反正这么短的名单,应该不会那么深吧?
这是因为过滤了整个列表,而不是过滤了 lesser
和 greater
的列表尾部。
例如您可以尝试以下操作:
function quicksort(list) {
if (list.length <= 1) return list;
var x = R.head(list);
var xs = R.tail(list);
var lesser = R.filter(R.lt(R.__, x), xs);
var greater = R.filter(R.gte(R.__, x), xs);
return R.concat(quicksort(lesser), R.prepend(x, quicksort(greater)));
}
不幸的是,这也没有从尾调用优化中受益,因为对 quicksort
的递归调用不在尾调用位置。