// 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