time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

list.js (13040B)


      1 import { REAmbiguous, REArgumentError, REOther } from "../errors/messages.js";
      2 import { makeDefinition } from "../library/registry/fnDefinition.js";
      3 import * as E_A_Floats from "../utility/E_A_Floats.js";
      4 import { frAny, frDist, frLambdaN, frArray, frNumber, frString, frTuple, frLambdaNand, } from "../library/registry/frTypes.js";
      5 import { FnFactory, doBinaryLambdaCall } from "../library/registry/helpers.js";
      6 import { vArray, vNumber, vString, vBool, uniq, uniqBy, } from "../value/index.js";
      7 import { sampleSetAssert } from "./sampleset.js";
      8 import { unzip, zip } from "../utility/E_A.js";
      9 export function _map(array, lambda, context, useIndex) {
     10     const mapped = new Array(array.length);
     11     if (!useIndex) {
     12         for (let i = 0; i < array.length; i++) {
     13             mapped[i] = lambda.call([array[i]], context);
     14         }
     15     }
     16     else {
     17         for (let i = 0; i < array.length; i++) {
     18             mapped[i] = lambda.call([array[i], vNumber(i)], context);
     19         }
     20     }
     21     return mapped;
     22 }
     23 export function _reduce(array, initialValue, lambda, context, useIndex) {
     24     if (!useIndex) {
     25         return array.reduce((acc, elem) => lambda.call([acc, elem], context), initialValue);
     26     }
     27     else {
     28         return array.reduce((acc, elem, index) => lambda.call([acc, elem, vNumber(index)], context), initialValue);
     29     }
     30 }
     31 export function _reduceWhile(array, initialValue, step, condition, context) {
     32     let acc = initialValue;
     33     for (let i = 0; i < array.length; i++) {
     34         const newAcc = step.call([acc, array[i]], context);
     35         const checkResult = condition.call([newAcc], context);
     36         if (checkResult.type !== "Bool") {
     37             throw new REArgumentError(`Condition should return a boolean value, got: ${checkResult.type}`);
     38         }
     39         if (!checkResult.value) {
     40             return acc;
     41         }
     42         acc = newAcc;
     43     }
     44     return acc;
     45 }
     46 const _assertInteger = (number) => {
     47     if (!Number.isInteger(number)) {
     48         throw new REArgumentError(`Number ${number} must be an integer`);
     49     }
     50 };
     51 const _assertValidArrayLength = (number) => {
     52     if (number < 0) {
     53         throw new REArgumentError("Expected non-negative number");
     54     }
     55     else if (!Number.isInteger(number)) {
     56         throw new REArgumentError("Number must be an integer");
     57     }
     58 };
     59 const _assertUnemptyArray = (array) => {
     60     if (array.length === 0) {
     61         throw new REArgumentError("List must not be empty");
     62     }
     63 };
     64 function _binaryLambdaCheck1(lambda, context) {
     65     return (el) => doBinaryLambdaCall([el], lambda, context);
     66 }
     67 const maker = new FnFactory({
     68     nameSpace: "List",
     69     requiresNamespace: true,
     70 });
     71 export const library = [
     72     maker.make({
     73         name: "make",
     74         output: "Array",
     75         examples: [
     76             `List.make(2, 3)`,
     77             `List.make(2, {|| 3})`,
     78             `List.make(2, {|f| f+1})`,
     79         ],
     80         definitions: [
     81             makeDefinition([frNumber, frLambdaNand([0, 1])], ([number, lambda]) => {
     82                 throw new REAmbiguous("Call with either 0 or 1 arguments, not both");
     83             }),
     84             makeDefinition([frNumber, frLambdaN(0)], ([number, lambda], context) => {
     85                 _assertValidArrayLength(number);
     86                 return vArray(Array.from({ length: number }, (_) => lambda.call([], context)));
     87             }),
     88             makeDefinition([frNumber, frLambdaN(1)], ([number, lambda], context) => {
     89                 _assertValidArrayLength(number);
     90                 return vArray(Array.from({ length: number }, (_, i) => lambda.call([vNumber(i)], context)));
     91             }),
     92             makeDefinition([frNumber, frAny], ([number, value]) => {
     93                 _assertValidArrayLength(number);
     94                 return vArray(new Array(number).fill(value));
     95             }),
     96             makeDefinition([frDist], ([dist]) => {
     97                 sampleSetAssert(dist);
     98                 return vArray(dist.samples.map(vNumber));
     99             }),
    100         ],
    101     }),
    102     maker.make({
    103         name: "upTo",
    104         output: "Array",
    105         examples: [`List.upTo(1,4)`],
    106         definitions: [
    107             makeDefinition([frNumber, frNumber], ([low, high]) => {
    108                 if (!Number.isInteger(low) || !Number.isInteger(high)) {
    109                     throw new REArgumentError("Low and high values must both be integers");
    110                 }
    111                 return vArray(E_A_Floats.upTo(low, high).map(vNumber));
    112             }),
    113         ],
    114     }),
    115     maker.make({
    116         name: "length",
    117         requiresNamespace: true,
    118         output: "Number",
    119         examples: [`List.length([1,4,5])`],
    120         definitions: [
    121             makeDefinition([frArray(frAny)], ([values]) => vNumber(values.length)),
    122         ],
    123     }),
    124     maker.make({
    125         name: "first",
    126         requiresNamespace: true,
    127         examples: [`List.first([1,4,5])`],
    128         definitions: [
    129             makeDefinition([frArray(frAny)], ([array]) => {
    130                 _assertUnemptyArray(array);
    131                 return array[0];
    132             }),
    133         ],
    134     }),
    135     maker.make({
    136         name: "last",
    137         requiresNamespace: true,
    138         examples: [`List.last([1,4,5])`],
    139         definitions: [
    140             makeDefinition([frArray(frAny)], ([array]) => {
    141                 _assertUnemptyArray(array);
    142                 return array[array.length - 1];
    143             }),
    144         ],
    145     }),
    146     maker.make({
    147         name: "reverse",
    148         output: "Array",
    149         requiresNamespace: false,
    150         examples: [`List.reverse([1,4,5])`],
    151         definitions: [
    152             makeDefinition([frArray(frAny)], ([array]) => vArray([...array].reverse())),
    153         ],
    154     }),
    155     maker.make({
    156         name: "map",
    157         output: "Array",
    158         requiresNamespace: false,
    159         examples: [
    160             "List.map([1,4,5], {|x| x+1})",
    161             "List.map([1,4,5], {|x,i| x+i+1})",
    162         ],
    163         definitions: [
    164             makeDefinition([frNumber, frLambdaNand([1, 2])], ([number, lambda]) => {
    165                 throw new REAmbiguous("Call with either 1 or 2 arguments, not both.");
    166             }),
    167             makeDefinition([frArray(frAny), frLambdaN(1)], ([array, lambda], context) => vArray(_map(array, lambda, context, false))),
    168             makeDefinition([frArray(frAny), frLambdaN(2)], ([array, lambda], context) => vArray(_map(array, lambda, context, true))),
    169         ],
    170     }),
    171     maker.make({
    172         name: "concat",
    173         requiresNamespace: true,
    174         examples: [`List.concat([1,2,3], [4, 5, 6])`],
    175         definitions: [
    176             makeDefinition([frArray(frAny), frArray(frAny)], ([array1, array2]) => vArray([...array1].concat(array2))),
    177         ],
    178     }),
    179     maker.make({
    180         name: "append",
    181         requiresNamespace: true,
    182         examples: [`List.append([1,4],5)`],
    183         definitions: [
    184             makeDefinition([frArray(frAny), frAny], ([array, el]) => vArray([...array, el])),
    185         ],
    186     }),
    187     maker.make({
    188         name: "slice",
    189         requiresNamespace: true,
    190         examples: [`List.slice([1,2,5,10],1,3)`],
    191         definitions: [
    192             makeDefinition([frArray(frAny), frNumber], ([array, start]) => {
    193                 _assertInteger(start);
    194                 return vArray(array.slice(start));
    195             }),
    196             makeDefinition([frArray(frAny), frNumber, frNumber], ([array, start, end]) => {
    197                 _assertInteger(start);
    198                 _assertInteger(end);
    199                 return vArray(array.slice(start, end));
    200             }),
    201         ],
    202     }),
    203     maker.make({
    204         name: "uniq",
    205         requiresNamespace: true,
    206         examples: [`List.uniq([1,2,3,"hi",false,"hi"])`],
    207         definitions: [
    208             makeDefinition([frArray(frAny)], ([arr]) => vArray(uniq(arr))),
    209         ],
    210     }),
    211     maker.make({
    212         name: "uniqBy",
    213         requiresNamespace: true,
    214         examples: [`List.uniqBy([[1,5], [3,5], [5,7]], {|x| x[1]})`],
    215         definitions: [
    216             makeDefinition([frArray(frAny), frLambdaN(1)], ([arr, lambda], context) => vArray(uniqBy(arr, (e) => lambda.call([e], context)))),
    217         ],
    218     }),
    219     maker.make({
    220         name: "reduce",
    221         requiresNamespace: false,
    222         examples: [`List.reduce([1,4,5], 2, {|acc, el| acc+el})`],
    223         definitions: [
    224             makeDefinition([frNumber, frLambdaNand([2, 3])], ([number, lambda]) => {
    225                 throw new REAmbiguous("Call with either 2 or 3 arguments, not both");
    226             }),
    227             makeDefinition([frArray(frAny), frAny, frLambdaN(2)], ([array, initialValue, lambda], context) => _reduce(array, initialValue, lambda, context, false)),
    228             makeDefinition([frArray(frAny), frAny, frLambdaN(3)], ([array, initialValue, lambda], context) => _reduce(array, initialValue, lambda, context, true)),
    229         ],
    230     }),
    231     maker.make({
    232         name: "reduceReverse",
    233         requiresNamespace: false,
    234         examples: [`List.reduceReverse([1,4,5], 2, {|acc, el| acc-el})`],
    235         definitions: [
    236             makeDefinition([frArray(frAny), frAny, frLambdaN(2)], ([array, initialValue, lambda], context) => _reduce([...array].reverse(), initialValue, lambda, context, false)),
    237         ],
    238     }),
    239     maker.make({
    240         name: "reduceWhile",
    241         requiresNamespace: true,
    242         examples: [
    243             `List.reduceWhile([1,4,5], 0, {|acc, curr| acc + curr }, {|acc| acc < 5})`,
    244         ],
    245         definitions: [
    246             makeDefinition([frArray(frAny), frAny, frLambdaN(2), frLambdaN(1)], ([array, initialValue, step, condition], context) => _reduceWhile(array, initialValue, step, condition, context)),
    247         ],
    248     }),
    249     maker.make({
    250         name: "filter",
    251         requiresNamespace: false,
    252         examples: [`List.filter([1,4,5], {|x| x>3})`],
    253         definitions: [
    254             makeDefinition([frArray(frAny), frLambdaN(1)], ([array, lambda], context) => vArray(array.filter(_binaryLambdaCheck1(lambda, context)))),
    255         ],
    256     }),
    257     maker.make({
    258         name: "every",
    259         requiresNamespace: true,
    260         examples: [`List.every([1,4,5], {|el| el>3 })`],
    261         definitions: [
    262             makeDefinition([frArray(frAny), frLambdaN(1)], ([array, lambda], context) => vBool(array.every(_binaryLambdaCheck1(lambda, context)))),
    263         ],
    264     }),
    265     maker.make({
    266         name: "some",
    267         requiresNamespace: true,
    268         examples: [`List.some([1,4,5], {|el| el>3 })`],
    269         definitions: [
    270             makeDefinition([frArray(frAny), frLambdaN(1)], ([array, lambda], context) => vBool(array.some(_binaryLambdaCheck1(lambda, context)))),
    271         ],
    272     }),
    273     maker.make({
    274         name: "find",
    275         requiresNamespace: true,
    276         examples: [`List.find([1,4,5], {|el| el>3 })`],
    277         definitions: [
    278             makeDefinition([frArray(frAny), frLambdaN(1)], ([array, lambda], context) => {
    279                 const result = array.find(_binaryLambdaCheck1(lambda, context));
    280                 if (!result) {
    281                     throw new REOther("No element found");
    282                 }
    283                 return result;
    284             }),
    285         ],
    286     }),
    287     maker.make({
    288         name: "findIndex",
    289         requiresNamespace: true,
    290         examples: [`List.findIndex([1,4,5], {|el| el>3 })`],
    291         definitions: [
    292             makeDefinition([frArray(frAny), frLambdaN(1)], ([array, lambda], context) => vNumber(array.findIndex(_binaryLambdaCheck1(lambda, context)))),
    293         ],
    294     }),
    295     maker.make({
    296         name: "join",
    297         requiresNamespace: true,
    298         examples: [`List.join(["a", "b", "c"], ",")`],
    299         definitions: [
    300             makeDefinition([frArray(frString), frString], ([array, joinStr]) => vString(array.join(joinStr))),
    301             makeDefinition([frArray(frString)], ([array]) => vString(array.join())),
    302         ],
    303     }),
    304     maker.make({
    305         name: "flatten",
    306         requiresNamespace: true,
    307         examples: [`List.flatten([[1,2], [3,4]])`],
    308         definitions: [
    309             makeDefinition([frArray(frAny)], ([arr]) => vArray(arr).flatten()),
    310         ],
    311     }),
    312     maker.make({
    313         name: "shuffle",
    314         requiresNamespace: true,
    315         examples: [`List.shuffle([1,3,4,20])`],
    316         definitions: [
    317             makeDefinition([frArray(frAny)], ([arr]) => vArray(arr).shuffle()),
    318         ],
    319     }),
    320     maker.make({
    321         name: "zip",
    322         requiresNamespace: true,
    323         examples: [`List.zip([1,3,4,20], [2,4,5,6])`],
    324         definitions: [
    325             makeDefinition([frArray(frAny), frArray(frAny)], ([array1, array2]) => {
    326                 if (array1.length !== array2.length) {
    327                     throw new REArgumentError("List lengths must be equal");
    328                 }
    329                 return vArray(zip(array1, array2).map((pair) => vArray(pair)));
    330             }),
    331         ],
    332     }),
    333     maker.make({
    334         name: "unzip",
    335         requiresNamespace: true,
    336         examples: [`List.unzip([[1,2], [2,3], [4,5]])`],
    337         definitions: [
    338             makeDefinition([frArray(frTuple(frAny, frAny))], ([array]) => vArray(unzip(array).map((r) => vArray(r)))),
    339         ],
    340     }),
    341 ];
    342 //# sourceMappingURL=list.js.map