git @ Cat's Eye Technologies Decoy / master lib / js / list.mjs
master

Tree @master (Download .tar.gz)

list.mjs @masterraw · history · blame

// Cons lists, in JavaScript.

// SPDX-FileCopyrightText: Chris Pressey, the original author of this work, has dedicated it to the public domain.
// For more information, please refer to <https://unlicense.org/>
// SPDX-License-Identifier: Unlicense

// #_# define car
export function car(x) {
  return x.head;
}
// #_# end define

// #_# define cdr
export function cdr(x) {
  return x.tail;
}
// #_# end define

// #_# define cons
export function cons(h, t) {
  return {
    head: h,
    tail: t,
  };
}
// #_# end define

// #_# define pair?
export function pair_3f(c) {
  return (typeof c === 'object' && c !== null && Object.hasOwn(c, "head") && Object.hasOwn(c, "tail"));
}
// #_# end define

// #_# define list
export function list(...args) {
    let v = null;
    let s = null;
    args.forEach(function(arg) {
        if (v === null) {
            v = {
                head: arg,
                tail: null,
            };
            s = v;
        } else {
            v.tail = {
                head: arg,
                tail: null,
            };
            v = v.tail;
        }
    });
    return s;
}
// #_# end define

// #_# define length
export function length(a) {
    if (!pair_3f(a)) return 0;
    let l = 0;
    while (a !== null) {
        l++;
        a = a.tail;
    }
    return l;
}
// #_# end define

// #_# define map
export function map(fn, a) {
    // On cons-lists.
    // ooh no
    return a.length;
}
// #_# end define

// #_# define list-ref
export function list_ref(a, n) {
    // nooo
    return a[n];
}
// #_# end define

// #_# define list?
export function list_3f(a) {
    if (a === null) {
        return true;
    } else if (!pair_3f(a)) {
        return false;
    } else {
        return list_3f(a.tail);
    }
}
// #_# end define

//local list_p
//list_p = function(value)
//if type(value) == "function" then
//    return False
//elseif value == Nil then
//    return True
//elseif Cons.is_class_of(value) then
//    return list_p(value:tail())
//else
//    return False
//end
//end
//env["list?"] = function(args)
//return list_p(args[1])
//end
// #_# end define

// #_# define null?
export function null_3f(x) {
  return x === null;
}
// #_# end define

// env["length"] = function(args)
// local c = args[1]
// local n = 0
// while c ~= Nil do
//     if Cons.is_class_of(c) then
//         n = n + 1
//         c = c:tail()
//     else
//         c = Nil
//     end
// end
// return Number.new(n)
// end
// 
// env["map"] = function(args)
// local fn = args[1]
// local c = 0
// local t = {}
// while c ~= Nil do
//     if Cons.is_class_of(c) then
//         table.insert(t, c) -- FIXME fn(c) !!
//         c = c.tail()
//     else
//         c = Nil
//     end
// end
// return Cons.table_to_list(t)
// end

// #_# define fold
// Note: not in R5RS
export function fold(fn, acc, list) {
  let head, tail;
  while (!null_3f(list)) {
    head = list.head;
    tail = list.tail;
    acc = fn(head, acc);
    list = tail;
  }
  return acc;
}
// #_# end define

// env["list-ref"] = function(args)
// local c = args[1]
// local n = args[2]
// while n > 0 do
//     if Cons.is_class_of(c) then
//         n = n - 1
//         c = c:tail()
//     else
//         n = 0
//     end
// end
// return c:head()
// end