swannodette / mori

ClojureScript's persistent data structures and supporting API from the comfort of vanilla JavaScript
http://swannodette.github.io/mori
3.39k stars 148 forks source link

reduceKV fails on nested vector after updateIn #158

Open ericgj opened 9 years ago

ericgj commented 9 years ago

This may be the same issue as #103 , but not knowing the internals I'm not sure if I'm dealing with a subvec or not. The error message is the same, No protocol method IKVReduce.-kv-reduce defined for type object. These steps reproduce the problem:

var orig = mori.toClj({ things: [ {value: 1}, {value: 2}, {value: 3} ] });
var newval = mori.updateIn(orig, ['things'], function(things){ 
  return mori.map( function(thing){ 
      return mori.updateIn(thing, ['value'], mori.inc); 
    }, things
  ); 
});

var keys = mori.reduceKV( function(acc,k,v){ /* ... */ }, mori.vector(), mori.get(newval,'things'));
// => No protocol method IKVReduce.-kv-reduce defined for type object: ({"value" 2} {"value" 3} {"value" 4})

mori.isVector(mori.get(newval,'things'));
// => false

mori.isMap(mori.get(newval,'things'));
// => false

mori.isSeq(mori.get(newval,'things'));
// => true

// but for the original ....

var keys = mori.reduceKV( function(acc,k,v){ /* ... */ }, mori.vector(), mori.get(orig,'things'));
// =>  (no error)

mori.isVector(mori.get(orig,'things'));
// => true

EDIT: I see now that mori.map returns a lazy sequence, that's probably the source of the problem. Makes sense that reduceKV wouldn't work on lazy vectors.