Jump to content

Recommended Posts

  • Moderators

I read an article the other day which caught my attention, 


"anamorphisms in javascript" describes functions to increase or decrease the number of dimensions in data-structures




I like to think of the integer 5 as having all the whole numbers except for five to be folded up inside itself




It then describes how this can be used to split traversing loops (for var i := 0 to length-1 do something) into traversing functions and do-something functions.


I thought I would try that out


However the code fragments in this article have been written in ES6, or rather ECMA-262 6th Edition, the ECMAScript 2015 Language Specification


I've not been exposed to this upgrade of the JS language much, but I see there are lots of changes

'use strict';
function unfoldWith(fn) {
  return function * unfold (value) {
    let { next, element, done } = fn(value);
    if (!done) {
      yield element;
      yield * unfold(next);
const butLast = (array) => array.slice(0, array.length - 1);
const last = (array) => array[array.length - 1];
const inReverse = unfoldWith(
    (array) => array.length > 0
      ? {
          element: last(array),
          next: butLast(array)
      : { done: true }
[...inReverse(['a', 'b', 'c'])]

The above code for a reversal function looks sort of weird, in any case much different from what I know as 'normal' javascript.


I suppose DWScript will not compile to ES6 any time soon, if at all (question to Eric : will it ?)


The solution is to convert it back to the current flavour of js using online tools such as Babel


This translates the above snippet into

'use strict';
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function unfoldWith(fn) {
  return regeneratorRuntime.mark(function unfold(value) {
    var _fn, next, element, done;
    return regeneratorRuntime.wrap(function unfold$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _fn = fn(value), next = _fn.next, element = _fn.element, done = _fn.done;
            if (done) {
              _context.next = 5;
            _context.next = 4;
            return element;
          case 4:
            return _context.delegateYield(unfold(next), 't0', 5);
          case 5:
          case 'end':
            return _context.stop();
    }, unfold, this);
var butLast = function butLast(array) {
  return array.slice(0, array.length - 1);
var last = function last(array) {
  return array[array.length - 1];
var inReverse = unfoldWith(function (array) {
  return array.length > 0 ? {
    element: last(array),
    next: butLast(array)
  } : { done: true };
[].concat(_toConsumableArray(inReverse(['a', 'b', 'c'])));

which to me is more recognisable, but not more readable.

Worst thing is it exposes functions which are not even defined in these snippets, so you need to include the babel.js lib (hosted on CDN somewhere)


Anyway, after all that it all does work as expected


See code or demo for an Array object with a 'reverse' function


So getting back to the article, the question is: is it something worthwhile keeping in mind or is it more a solution looking for a problem?


Probably the latter

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...