Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Array.build(length, mapFn = undefined)

Array.build

Originally conceived by Dave Herman, based on: http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Flist..rkt%29._build-list%29%29

Rationale

There is no easy way to create an array, of user defined length, containing values that are not undefined. Easily build range functionality ontop.

Prior Art

> (build-list 10 values)
'(0 1 2 3 4 5 6 7 8 9)

> (build-list 5 (lambda (x) (* x x)))
'(0 1 4 9 16)
> Array.new(10) {|index| index}
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

> Array.new(5) {|n| n * n}
=> [0, 1, 4, 9, 16]

Array.build(length, mapfn = undefined)

When the build method is called with arguments method is called with argument length and optional argument mapfn the following steps are taken:

  1. Let len be ToLength(length).
  2. Let C be the this value.
  3. If IsConstructor(C) is true, then
  4. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
  5. Else,
  6. Let A be ArrayCreate(len).
  7. Let k be 0.
  8. If mapfn is undefined, then let mapping be false.
  9. Else,
  10. If IsCallable(_mapfn_) is false, throw a TypeError exception.
  11. Let mapping be true.
  12. Repeat, while k < len
  13. If mapping is true, then 1. Let mappedValue be the result of calling the [[Call]] internal method of mapfn with A as thisArgument and a List containing k as argumentsList. 1. ReturnIfAbrupt(mappedValue).
  14. Else, 1. Let mappedValue be k.
  15. Let Pk be ToString(k).
  16. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue).
  17. ReturnIfAbrupt(defineStatus).
  18. Increase k by 1.
  19. Let putStatus be Put(A, "length", len, true).
  20. ReturnIfAbrupt(putStatus).
  21. Return A.

Examples:

> Array.build(10);
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

> Array.build(5, n => n * n);
[0, 1, 4, 9, 16]
function range(lower, upper) {
  return Array.build(upper - lower, n => n + lower);
}

range(9, 18);

[9, 10, 11, 12, 13, 14, 15, 16, 17];
function isConstructor(C) {
try {
new C();
return true;
} catch (e) {
return false;
}
}
Array.build = function(length, mapFn) {
var len = length >>> 0;
var C = this;
var mapping = false;
var k = 0;
var A;
if (isConstructor(C)) {
A = new C(length);
} else {
A = new Array(length);
}
if (typeof mapFn === "function") {
mapping = true;
}
while (k < len) {
A[k] = mapping ? mapFn.call(A, k) : k;
k++;
}
return A;
};
@caub

This comment has been minimized.

Show comment
Hide comment
@caub

caub May 27, 2018

Could we re-propose it to ECMA-proposals? since it makes things really simpler

- Array.from({length: n}, (_, i) => ({id: `foo${i}`}))
+ Array.build(n, i => ({id: `foo${i}`}))

caub commented May 27, 2018

Could we re-propose it to ECMA-proposals? since it makes things really simpler

- Array.from({length: n}, (_, i) => ({id: `foo${i}`}))
+ Array.build(n, i => ({id: `foo${i}`}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment