Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accessing node path from walk / visit #2

Open
felixroos opened this issue Aug 24, 2020 · 0 comments
Open

accessing node path from walk / visit #2

felixroos opened this issue Aug 24, 2020 · 0 comments

Comments

@felixroos
Copy link

Hello, thanks for this cool lib. Is there any possibility to access the path info of a node inside walk or visit?

Simple example:

const SimpleZipper = makeZipper(
  n => !!n.children?.length,
  n => n?.children,
  (parent, children) => {
    console.log('make node', parent, children)
    return { children, parent }
  }
);

const s = SimpleZipper({
  children: [
    'a',
    { children: ['b', 'c'] }
  ]
});

console.log(s.value())
// { children: [ 'a', { children: [ 'b', 'c' ] } ] }

console.log(s.next().next().next().value()) 
// 'b'

// on a Zipper node, i get the parentItems as I would want them:
console.log(s.next().next().next().path.parentItems)
/* [
  { children: [ 'a', { children: [ 'b', 'c' ] } ] }, // grandparent
  { children: [ 'b', 'c' ] } // parent
] */

So far so good, but if I use preWalk, the passed node is not a Zipper, but just what would be returned from value():

const mapLeafs = mapFn => makeZipper => preWalk(
  (node) => { // ideally, node should be a Zipper
    const t = makeZipper(node); // I tried creating a "subzipper" (without path info)
    if (t.isLeaf()) {
      console.log('map', node)
      return t.edit(item => mapFn(item /*,path*/).item; // would need path here
    }
    return node;
  }
);

const uppercase = mapLeafs(leaf => leaf.toUpperCase())(SimpleZipper);
const uppercased = uppercase(s).value();

console.log(uppercased);
// { children: [ 'A', { children: [ 'B', 'C' ] } ] }

For this case (🙊) the mapping works, but without the path, I have no structural info of the current node, which would be needed for many common operations (like accumulating parent values to a child).

My second attempt was creating a reduce function like mentioned in the readme:

const makeReduceVisitor = fn => onPre((item, state) => {
  return ({ state: fn(state, item) })
});
const reduce = (fn, initialAcc, z) => {
  const { state } = visit([makeReduceVisitor(fn)], initialAcc, z);
  return state;
}

reduce((acc, node) => {
  if(!node.children) {
    // also no Zipper object here
    return acc + node 
  }
  return acc;
}, '', s)
// yields 'abc'

Still no luck here, as the given node is also just the value.

Am I missing something? The only other solution I can think of is using pipe magic like described in the readme for arrays, but I think it would be much simpler to have a Zipper instead of just the value available to walk/visit.

Thank you for this refreshing lib, which would be the perfect candidate to reimplement my hierarchical music format :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant