Skip to content

Commit

Permalink
Merge pull request #105 from pineapplemachine/sophie/feature-arrayDeep
Browse files Browse the repository at this point in the history
Add arrayDeep and newArrayDeep functions
  • Loading branch information
pineapplemachine committed Jul 30, 2017
2 parents 20ea11f + 8b68ea9 commit 22fbac2
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/functions/arrayDeep.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {isSequence} from "../core/sequence";
import {wrap} from "../core/wrap";

import {array} from "./array";

import {NotBoundedError} from "../errors/NotBoundedError";

export const arrayDeep = wrap({
name: "arrayDeep",
summary: "Recursively acquire an in-memory array from a sequence potentially containing more sequences.",
docs: process.env.NODE_ENV !== "development" ? undefined : {
introduced: "[email protected]",
expects: (`
The function expects a single known-bounded sequence as input.
`),
returns: (`
The function returns an array containing the elements of the input
sequence. Elements of that input sequence that were known-bounded
arrays also recursively have the operation applied to them, such
that a sequence of sequences becomes an array of arrays, and so on.
/Sequences which directly represent the contents of an in-memory
array will have that source array given as output.
To always acquire a new array object that is guaranteed to be safe
to modify, use @newArrayDeep.
`),
examples: [
"basicUsage",
],
related: [
"array", "newArray", "newArrayDeep",
],
},
attachSequence: true,
async: true,
arguments: {
one: wrap.expecting.sequence,
},
implementation: (source) => {
NotBoundedError.enforce(source, {
message: "Failed to create array from sequence.",
});
const result = array(source);
for(let i = 0; i < result.length; i++){
if(isSequence(result[i]) && result[i].bounded()){
result[i] = arrayDeep(result[i]);
}
}
return result;
},
tests: process.env.NODE_ENV !== "development" ? undefined : {
"basicUsage": hi => {
// This is a sequence of sequences.
const seq = hi.mapIndex(i => hi.range(i + 1)).head(3);
hi.assert(hi.isSequence(seq));
hi.assert(hi.isSequence(seq.index(0)));
// And from it is created an array of arrays.
const array = seq.arrayDeep();
hi.assert(hi.isArray(array));
hi.assert(hi.isArray(array[0]));
// Which contains these numbers:
hi.assertEqual(array, [[0], [0, 1], [0, 1, 2]]);
},
"emptyInput": hi => {
const array = hi.emptySequence().arrayDeep();
hi.assert(hi.isArray(array));
hi.assert(array.length === 0);
},
"unboundedElementInInput": hi => {
const array = hi([0, hi.range(3), hi.counter()]).arrayDeep();
hi.assert(array[0] === 0);
hi.assertEqual(array[1], [0, 1, 2]);
hi.assert(hi.isArray(array[1]));
hi.assert(hi.isSequence(array[2]));
},
"modifyOutput": hi => {
const array = [[0, 1, 2]];
const output = hi.arrayDeep(array);
output[0][0] = 10;
hi.assertEqual(output, [[10, 1, 2]]);
// Input is modified
hi.assertEqual(array, [[10, 1, 2]]);
},
},
});

export default arrayDeep;
90 changes: 90 additions & 0 deletions src/functions/newArrayDeep.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {isSequence} from "../core/sequence";
import {isArray} from "../core/types";
import {wrap} from "../core/wrap";

import {newArray} from "./newArray";

import {NotBoundedError} from "../errors/NotBoundedError";

export const newArrayDeep = wrap({
name: "newArrayDeep",
summary: "Recursively acquire an in-memory array from a sequence potentially containing more sequences.",
docs: process.env.NODE_ENV !== "development" ? undefined : {
introduced: "[email protected]",
expects: (`
The function expects a single known-bounded sequence as input.
`),
returns: (`
The function returns an array containing the elements of the input
sequence. Elements of that input sequence that were known-bounded
arrays also recursively have the operation applied to them, such
that a sequence of sequences becomes an array of arrays, and so on.
/Sequences which directly represent the contents of an in-memory
array will have a copy of that array given as output.
If it is not necessary to preserve the original arrays in case of
modification, or if the output of this function will not be
modified, then it will be more efficient to call @arrayDeep instead.
`),
examples: [
"basicUsage",
],
related: [
"array", "newArray", "arrayDeep",
],
},
attachSequence: true,
async: true,
arguments: {
one: wrap.expecting.sequence,
},
implementation: (source) => {
NotBoundedError.enforce(source, {
message: "Failed to create array from sequence.",
});
const result = newArray(source);
for(let i = 0; i < result.length; i++){
if(isSequence(result[i]) && result[i].bounded()){
result[i] = newArrayDeep(result[i]);
}else if(isArray(result[i])){
result[i] = result[i].slice();
}
}
return result;
},
tests: process.env.NODE_ENV !== "development" ? undefined : {
"basicUsage": hi => {
// This is a sequence of sequences.
const seq = hi.mapIndex(i => hi.range(i + 1)).head(3);
hi.assert(hi.isSequence(seq));
hi.assert(hi.isSequence(seq.index(0)));
// And from it is created an array of arrays.
const array = seq.newArrayDeep();
hi.assert(hi.isArray(array));
hi.assert(hi.isArray(array[0]));
// Which contains these numbers:
hi.assertEqual(array, [[0], [0, 1], [0, 1, 2]]);
},
"emptyInput": hi => {
const array = hi.emptySequence().newArrayDeep();
hi.assert(hi.isArray(array));
hi.assert(array.length === 0);
},
"unboundedElementInInput": hi => {
const array = hi([0, hi.range(3), hi.counter()]).newArrayDeep();
hi.assert(array[0] === 0);
hi.assertEqual(array[1], [0, 1, 2]);
hi.assert(hi.isArray(array[1]));
hi.assert(hi.isSequence(array[2]));
},
"modifyOutput": hi => {
const array = [[0, 1, 2]];
const output = hi.newArrayDeep(array);
output[0][0] = 10;
hi.assertEqual(output, [[10, 1, 2]]);
// Input is not modified
hi.assertEqual(array, [[0, 1, 2]]);
},
},
});

export default newArrayDeep;
2 changes: 2 additions & 0 deletions src/higher.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ import {anyPass} from "./functions/anyPass"; hi.register(anyPass);
import {all} from "./functions/all"; hi.register(all);
import {allPass} from "./functions/allPass"; hi.register(allPass);
import {array} from "./functions/array"; hi.register(array);
import {arrayDeep} from "./functions/arrayDeep"; hi.register(arrayDeep);
import {assumeBounded} from "./functions/assumeBounded"; hi.register(assumeBounded);
import {benchmark} from "./functions/benchmark"; hi.register(benchmark);
import {bigrams} from "./functions/bigrams"; hi.register(bigrams);
Expand Down Expand Up @@ -219,6 +220,7 @@ import {max} from "./functions/max"; hi.register(max);
import {min} from "./functions/min"; hi.register(min);
import {negate} from "./functions/negate"; hi.register(negate);
import {newArray} from "./functions/newArray"; hi.register(newArray);
import {newArrayDeep} from "./functions/newArrayDeep"; hi.register(newArrayDeep);
import {newObject} from "./functions/newObject"; hi.register(newObject);
import {ngrams} from "./functions/ngrams"; hi.register(ngrams);
import {none} from "./functions/none"; hi.register(none);
Expand Down

0 comments on commit 22fbac2

Please sign in to comment.