Skip to content

Commit

Permalink
Auto-generated commit
Browse files Browse the repository at this point in the history
  • Loading branch information
stdlib-bot committed Feb 13, 2024
1 parent 17dc074 commit 7fde12d
Show file tree
Hide file tree
Showing 16 changed files with 454 additions and 42 deletions.
2 changes: 1 addition & 1 deletion index/docs/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ interface Constructor {
* var dt = o.dtype;
* // returns 'uint8'
*/
get( id: string ): ArrayObject;
get<T extends BaseArrayObject = ArrayObject>( id: string ): T;
}

/**
Expand Down
132 changes: 114 additions & 18 deletions to-fancy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,19 @@ v = y[ ':' ];

The function supports the following options:

- **cache**: cache for resolving array index objects. Must have a `get` method which accepts a single argument: a string identifier associated with an array index.

If an array index associated with a provided identifier exists, the `get` method should return an object having the following properties:

- **data**: the underlying index array.
- **type**: the index type. Must be either `'mask'`, `'bool'`, or `'int'`.
- **dtype**: the [data type][@stdlib/array/dtypes] of the underlying array.

If an array index is not associated with a provided identifier, the `get` method should return `null`.

Default: [`ArrayIndex`][@stdlib/array/index].

- **strict**: boolean indicating whether to enforce strict bounds checking. Default: `false`.
- **cache**: cache for resolving array index objects. Default: [`ArrayIndex`][@stdlib/array/index].

By default, the function returns a fancy array which does **not** enforce strict bounds checking. For example,

Expand Down Expand Up @@ -156,8 +167,19 @@ var v = y[ ':' ];

The function supports the following options:

- **cache**: default cache for resolving array index objects. Must have a `get` method which accepts a single argument: a string identifier associated with an array index.

If an array index associated with a provided identifier exists, the `get` method should return an object having the following properties:

- **data**: the underlying index array.
- **type**: the index type. Must be either `'mask'`, `'bool'`, or `'int'`.
- **dtype**: the [data type][@stdlib/array/dtypes] of the underlying array.

If an array index is not associated with a provided identifier, the `get` method should return `null`.

Default: [`ArrayIndex`][@stdlib/array/index].

- **strict**: boolean indicating whether to enforce strict bounds checking by default. Default: `false`.
- **cache**: cache for resolving array index objects. Default: [`ArrayIndex`][@stdlib/array/index].

By default, the function returns a function which, by default, does **not** enforce strict bounds checking. For example,

Expand Down Expand Up @@ -205,6 +227,72 @@ The returned function supports the same options as above. When the returned func
- Indexing expressions provide a convenient and powerful means for creating and operating on array views; however, their use does entail a performance cost. Indexing expressions are best suited for interactive use (e.g., in the [REPL][@stdlib/repl]) and scripting. For performance critical applications, prefer equivalent functional APIs supporting array-like objects.
- In older JavaScript environments which do **not** support [`Proxy`][@stdlib/proxy/ctor] objects, the use of indexing expressions is **not** supported.

### Bounds Checking

By default, fancy arrays do **not** enforce strict bounds checking across index expressions. The motivation for the default fancy array behavior stems from a desire to maintain parity with plain arrays; namely, the returning of `undefined` when accessing a single non-existent property.

Accordingly, when `strict` is `false`, one may observe the following behaviors:

<!-- run throws: true -->

```javascript
var idx = require( '@stdlib/array/index' );

var x = array2fancy( [ 1, 2, 3, 4 ], {
'strict': false
});

// Access a non-existent property:
var v = x[ 'foo' ];
// returns undefined

// Access an out-of-bounds index:
v = x[ 10 ];
// returns undefined

v = x[ -10 ];
// returns undefined

// Access an out-of-bounds slice:
v = x[ '10:' ];
// returns []

// Access one or more out-of-bounds indices:
v = x[ idx( [ 10, 20 ] ) ];
// throws <RangeError>
```

When `strict` is `true`, fancy arrays normalize index behavior and consistently enforce strict bounds checking.

<!-- run throws: true -->

```javascript
var idx = require( '@stdlib/array/index' );

var x = array2fancy( [ 1, 2, 3, 4 ], {
'strict': true
});

// Access a non-existent property:
var v = x[ 'foo' ];
// returns undefined

// Access an out-of-bounds index:
v = x[ 10 ];
// throws <RangeError>

v = x[ -10 ];
// throws <RangeError>

// Access an out-of-bounds slice:
v = x[ '10:' ];
// throws <RangeError>

// Access one or more out-of-bounds indices:
v = x[ idx( [ 10, 20 ] ) ];
// throws <RangeError>
```

### Broadcasting

Fancy arrays support **broadcasting** in which assigned scalars and single-element arrays are repeated (without additional memory allocation) to match the length of a target array instance.
Expand Down Expand Up @@ -340,22 +428,6 @@ im = imag( v );
// returns 0.0
```

Note, however, that attempting to assign a real-valued array to a complex number array slice is **not** supported due to the ambiguity of whether the real-valued array is a collection of real components (with implied imaginary components equal to zero) or an array of interleaved real and imaginary components.

<!-- run throws: true -->

```javascript
var Float64Array = require( '@stdlib/array/float64' );
var Complex128Array = require( '@stdlib/array/complex128' );

var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
var y = array2fancy( x );

// Attempt to assign a real-valued array:
y[ ':' ] = new Float64Array( [ 5.0, 6.0 ] ); // is this a single complex number which should be broadcast or a list of real components with implied imaginary components?
// throws <Error>
```

</section>

<!-- /.notes -->
Expand All @@ -371,12 +443,16 @@ y[ ':' ] = new Float64Array( [ 5.0, 6.0 ] ); // is this a single complex number
<!-- eslint no-undef: "error" -->

```javascript
var Uint8Array = require( '@stdlib/array/uint8' );
var Int32Array = require( '@stdlib/array/int32' );
var idx = require( '@stdlib/array/index' );
var array2fancy = require( '@stdlib/array/to-fancy' );

var x = [ 1, 2, 3, 4, 5, 6 ];
var y = array2fancy( x );
// returns <Array>

// Slice retrieval:
var z = y[ '1::2' ];
// returns [ 2, 4, 6 ]

Expand All @@ -386,13 +462,31 @@ z = y[ '-2::-2' ];
z = y[ '1:4' ];
// returns [ 2, 3, 4 ]

// Slice assignment:
y[ '4:1:-1' ] = 10;
z = y[ ':' ];
// returns [ 1, 2, 10, 10, 10, 6 ]

y[ '2:5' ] = [ -10, -9, -8 ];
z = y[ ':' ];
// returns [ 1, 2, -10, -9, -8, 6 ]

// Array index retrieval:
var i = idx( [ 1, 3, 4 ] ); // integer index array
z = y[ i ];
// returns [ 2, -9, -8 ]

i = idx( [ true, false, false, true, true, true ] ); // boolean array
z = y[ i ];
// returns [ 1, -9, -8, 6 ]

i = idx( new Uint8Array( [ 0, 0, 1, 0, 0, 1 ] ) ); // mask array
z = y[ i ];
// returns [ 1, 2, -9, -8 ]

i = idx( new Int32Array( [ 0, 0, 1, 1, 2, 2 ] ) ); // integer index array
z = y[ i ];
// returns [ 1, 1, 2, 2, -10, -10 ]
```

</section>
Expand Down Expand Up @@ -439,6 +533,8 @@ z = y[ ':' ];

[@stdlib/array/index]: https://github.com/stdlib-js/array/tree/main/index

[@stdlib/array/dtypes]: https://github.com/stdlib-js/array/tree/main/dtypes

</section>

<!-- /.links -->
20 changes: 8 additions & 12 deletions to-fancy/docs/repl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@
scalar to a complex number argument having an imaginary component equal to
zero.

Note, however, that attempting to assign a real-valued array to a complex
number array slice is *not* supported due to the ambiguity of whether the
real-valued array is a collection of real components (with implied imaginary
components equal to zero) or an array of interleaved real and imaginary
components.

In older JavaScript environments which do not support Proxy objects, the use
of indexing expressions is not supported.

Expand All @@ -71,9 +65,10 @@

options.cache: Object (optional)
Cache for resolving array index objects. Must have a 'get' method which
accepts a single argument: an identifier associated with an array index.
If an array index associated with a provided identifier exists, the
'get' method should return an object having the following properties:
accepts a single argument: a string identifier associated with an array
index. If an array index associated with a provided identifier exists,
the 'get' method should return an object having the following
properties:

- data: the underlying index array.
- type: the index type. Must be either 'mask', 'bool', or 'int'.
Expand Down Expand Up @@ -111,9 +106,10 @@

options.cache: Object (optional)
Cache for resolving array index objects. Must have a 'get' method which
accepts a single argument: an identifier associated with an array index.
If an array index associated with a provided identifier exists, the
'get' method should return an object having the following properties:
accepts a single argument: a string identifier associated with an array
index. If an array index associated with a provided identifier exists,
the 'get' method should return an object having the following
properties:

- data: the underlying index array.
- type: the index type. Must be either 'mask', 'bool', or 'int'.
Expand Down
26 changes: 26 additions & 0 deletions to-fancy/examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@

'use strict';

var Uint8Array = require( './../../uint8' );
var Int32Array = require( './../../int32' );
var idx = require( './../../index' );
var array2fancy = require( './../lib' );

var x = [ 1, 2, 3, 4, 5, 6 ];
var y = array2fancy( x );
// returns <Array>

// Slice retrieval:
var z = y[ '1::2' ];
console.log( z );
// => [ 2, 4, 6 ]
Expand All @@ -36,6 +40,7 @@ z = y[ '1:4' ];
console.log( z );
// => [ 2, 3, 4 ]

// Slice assignment:
y[ '4:1:-1' ] = 10;
z = y[ ':' ];
console.log( z );
Expand All @@ -45,3 +50,24 @@ y[ '2:5' ] = [ -10, -9, -8 ];
z = y[ ':' ];
console.log( z );
// => [ 1, 2, -10, -9, -8, 6 ]

// Array index retrieval:
var i = idx( [ 1, 3, 4 ] ); // integer index array
z = y[ i ];
console.log( z );
// => [ 2, -9, -8 ]

i = idx( [ true, false, false, true, true, true ] ); // boolean array
z = y[ i ];
console.log( z );
// => [ 1, -9, -8, 6 ]

i = idx( new Uint8Array( [ 0, 0, 1, 0, 0, 1 ] ) ); // mask array
z = y[ i ];
console.log( z );
// => [ 1, 2, -9, -8 ]

i = idx( new Int32Array( [ 0, 0, 1, 1, 2, 2 ] ) ); // integer index array
z = y[ i ];
console.log( z );
// => [ 1, 1, 2, 2, -10, -10 ]
4 changes: 2 additions & 2 deletions to-fancy/lib/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var arraylike2object = require( './../../base/arraylike2object' );
var assign = require( '@stdlib/object/assign' );
var format = require( '@stdlib/string/format' );
var setElementWrapper = require( './set_element_wrapper.js' );
var getSliceWrapper = require( './get_slice_wrapper.js' );
var getArrayWrapper = require( './get_array_wrapper.js' );
var hasProxySupport = require( './has_proxy_support.js' );
var defaults = require( './defaults.js' );
var validate = require( './validate.js' );
Expand Down Expand Up @@ -143,7 +143,7 @@ function factory() {
'getter': arr.accessors[ 0 ],
'setter': arr.accessors[ 1 ],
'preSetElement': setElementWrapper( dt ),
'postGetSlice': getSliceWrapper( array2fancy, opts ),
'postGetArray': getArrayWrapper( array2fancy, opts ),
'cache': opts.cache,
'strict': opts.strict,
'validator': validator( dt ),
Expand Down
11 changes: 9 additions & 2 deletions to-fancy/lib/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
var hasProperty = require( '@stdlib/assert/has-property' );
var isIntegerString = require( './is_integer_string.js' );
var isArrayIndexString = require( './is_array_index_string.js' );
var getElements = require( './get_elements.js' );
var getElement = require( './get_element.js' );
var getValue = require( './get_value.js' );
var getSlice = require( './get_slice.js' );
Expand All @@ -38,7 +40,8 @@ var getSlice = require( './get_slice.js' );
* @param {Function} ctx.getter - accessor for retrieving array elements
* @param {boolean} ctx.strict - boolean indicating whether to enforce strict bounds checking
* @param {Function} ctx.ctor - proxied array constructor
* @param {Function} ctx.postGetSlice - function to process a retrieved slice
* @param {Function} ctx.postGetArray - function to process a retrieved array
* @param {Object} ctx.cache - cache for resolving array index objects
* @returns {Function} handler
*/
function factory( ctx ) {
Expand All @@ -53,6 +56,7 @@ function factory( ctx ) {
* @param {Object} receiver - the proxy object or an object inheriting from the proxy
* @throws {Error} invalid slice operation
* @throws {RangeError} slice exceeds array bounds
* @throws {RangeError} index exceeds array bounds
* @returns {*} result
*/
function get( target, property, receiver ) {
Expand All @@ -62,7 +66,10 @@ function factory( ctx ) {
if ( hasProperty( target, property ) || !isString( property ) ) {
return getValue( target, property, receiver, ctx );
}
return getSlice( target, property, receiver, ctx );
if ( isArrayIndexString( property ) ) {
return getElements( target, property, ctx );
}
return getSlice( target, property, ctx );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
// MAIN //

/**
* Returns a wrapper function for processing slices after retrieval.
* Returns a wrapper function for processing arrays after retrieval.
*
* @private
* @param {Function} array2fancy - function for creating a proxied array
* @param {Object} opts - options
* @param {boolean} opts.strict - boolean indicating whether to perform strict bounds checking
* @param {Function} opts.cache - cache for resolving array index objects
* @returns {Function} wrapper function
*/
function wrapper( array2fancy, opts ) {
Expand Down
Loading

0 comments on commit 7fde12d

Please sign in to comment.