0

This code produces the stack trace below it:

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

Stack trace:

$ 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)

I though that babel would handle tail call optimization? In any case, it's such a short list, it should not be that deep, right?

Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
Ivan -Oats- Storck
  • 4,096
  • 3
  • 30
  • 39

1 Answers1

2

This would be due to filtering the entire list, rather than the tail of the list for lesser and greater.

e.g. You could try something like the following:

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

Unfortunately this doesn't benefit from tail-call optimisation either, as the recursive calls to quicksort are not in tail-call position.

Scott Christopher
  • 6,458
  • 23
  • 26