Skip to content

Commit bb2fcc9

Browse files
authored
[FEA] Update to Arrow v8.0.0 (#393)
* update to Arrow v8.0.0 * update fastify-arrow version
1 parent 0ce8ea7 commit bb2fcc9

31 files changed

Lines changed: 1554 additions & 1508 deletions

modules/cudf/notebooks/Geospatial Demo.ipynb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,16 @@
4848
" });\n",
4949
"\n",
5050
" function featureToVector(coordinates) {\n",
51-
" return Vector.from({\n",
52-
" values: coordinates,\n",
53-
" highWaterMark: Number.POSITIVE_INFINITY,\n",
54-
" type: new List(Field.new({\n",
51+
" return vectorFromArray(\n",
52+
" coordinates,\n",
53+
" new List(Field.new({\n",
5554
" name: 'rings', type: new List(Field.new({\n",
5655
" name: 'coords', type: new List(Field.new({\n",
5756
" name: 'points', type: new Float32()\n",
5857
" }))\n",
5958
" }))\n",
6059
" })),\n",
61-
" });\n",
60+
" );\n",
6261
" }\n",
6362
"}\n",
6463
"\n",

modules/cudf/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"dependencies": {
3737
"@rapidsai/cuda": "0.0.1",
3838
"@rapidsai/rmm": "0.0.1",
39-
"apache-arrow": "^4.0.0"
39+
"apache-arrow": "^8.0.0"
4040
},
4141
"devDependencies": {
4242
"ix": "4.4.1"

modules/cudf/src/column/from_arrow.ts

Lines changed: 69 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import * as arrow from 'apache-arrow';
1616

1717
import {Column} from '../column';
18+
import {Table} from '../table';
1819
import {
1920
Bool8,
2021
Categorical,
@@ -40,61 +41,60 @@ import {
4041
import {ArrowToCUDFType} from '../types/mappings';
4142

4243
/** @ignore */
43-
interface VectorToColumnVisitor extends arrow.Visitor {
44-
visit<T extends arrow.DataType>(node: arrow.Vector<T>): Column<ArrowToCUDFType<T>>;
45-
visitMany<T extends arrow.DataType>(nodes: arrow.Vector<T>[]): Column<ArrowToCUDFType<T>>[];
46-
getVisitFn<T extends arrow.DataType>(node: arrow.Vector<T>): () => Column<ArrowToCUDFType<T>>;
44+
interface DataToColumnVisitor extends arrow.Visitor {
45+
visit<T extends arrow.DataType>(node: arrow.Data<T>): Column<ArrowToCUDFType<T>>;
46+
visitMany<T extends arrow.DataType>(nodes: readonly arrow.Data<T>[]):
47+
Column<ArrowToCUDFType<T>>[];
48+
getVisitFn<T extends arrow.DataType>(node: arrow.Data<T>): () => Column<ArrowToCUDFType<T>>;
4749
}
4850

49-
class VectorToColumnVisitor extends arrow.Visitor {
50-
// visitNull<T extends arrow.Null>(vector: arrow.Vector<T>) {}
51-
visitBool<T extends arrow.Bool>(vector: arrow.Vector<T>) {
52-
const {nullBitmap: nullMask} = vector.data;
53-
return new Column({type: new Bool8, data: new Uint8Array(vector), nullMask});
54-
}
55-
visitInt8<T extends arrow.Int8>({length,
56-
data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
51+
class DataToColumnVisitor extends arrow.Visitor {
52+
// visitNull<T extends arrow.Null>(data: arrow.Data<T>) {}
53+
visitBool<T extends arrow.Bool>(data: arrow.Data<T>) {
54+
const {values, nullBitmap: nullMask} = data;
55+
return new Column({
56+
type: new Bool8,
57+
data:
58+
// eslint-disable-next-line @typescript-eslint/unbound-method
59+
new Uint8Array(new arrow.util.BitIterator(values, 0, data.length, null, arrow.util.getBit)),
60+
nullMask
61+
});
62+
}
63+
visitInt8<T extends arrow.Int8>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
5764
return new Column({type: new Int8, length, data: data.subarray(0, length), nullMask});
5865
}
59-
visitInt16<T extends arrow.Int16>({length,
60-
data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
66+
visitInt16<T extends arrow.Int16>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
6167
return new Column({type: new Int16, length, data: data.subarray(0, length), nullMask});
6268
}
63-
visitInt32<T extends arrow.Int32>({length,
64-
data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
69+
visitInt32<T extends arrow.Int32>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
6570
return new Column({type: new Int32, length, data: data.subarray(0, length), nullMask});
6671
}
67-
visitInt64<T extends arrow.Int64>({length,
68-
data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
72+
visitInt64<T extends arrow.Int64>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
6973
return new Column({type: new Int64, length, data: data.subarray(0, length * 2), nullMask});
7074
}
71-
visitUint8<T extends arrow.Uint8>({length,
72-
data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
75+
visitUint8<T extends arrow.Uint8>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
7376
return new Column({type: new Uint8, length, data: data.subarray(0, length), nullMask});
7477
}
75-
visitUint16<T extends arrow.Uint16>({length, data: {values: data, nullBitmap: nullMask}}:
76-
arrow.Vector<T>) {
78+
visitUint16<T extends arrow.Uint16>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
7779
return new Column({type: new Uint16, length, data: data.subarray(0, length), nullMask});
7880
}
79-
visitUint32<T extends arrow.Uint32>({length, data: {values: data, nullBitmap: nullMask}}:
80-
arrow.Vector<T>) {
81+
visitUint32<T extends arrow.Uint32>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
8182
return new Column({type: new Uint32, length, data: data.subarray(0, length), nullMask});
8283
}
83-
visitUint64<T extends arrow.Uint64>({length, data: {values: data, nullBitmap: nullMask}}:
84-
arrow.Vector<T>) {
84+
visitUint64<T extends arrow.Uint64>({length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
8585
return new Column({type: new Uint64, length, data: data.subarray(0, length * 2), nullMask});
8686
}
87-
// visitFloat16<T extends arrow.Float16>(vector: arrow.Vector<T>) {}
88-
visitFloat32<T extends arrow.Float32>({length, data: {values: data, nullBitmap: nullMask}}:
89-
arrow.Vector<T>) {
87+
// visitFloat16<T extends arrow.Float16>(data: arrow.Data<T>) {}
88+
visitFloat32<T extends arrow.Float32>({length, values: data, nullBitmap: nullMask}:
89+
arrow.Data<T>) {
9090
return new Column({type: new Float32, length, data: data.subarray(0, length), nullMask});
9191
}
92-
visitFloat64<T extends arrow.Float64>({length, data: {values: data, nullBitmap: nullMask}}:
93-
arrow.Vector<T>) {
92+
visitFloat64<T extends arrow.Float64>({length, values: data, nullBitmap: nullMask}:
93+
arrow.Data<T>) {
9494
return new Column({type: new Float64, length, data: data.subarray(0, length), nullMask});
9595
}
96-
visitUtf8<T extends arrow.Utf8>({length, data: {values, valueOffsets, nullBitmap: nullMask}}:
97-
arrow.Vector<T>) {
96+
visitUtf8<T extends arrow.Utf8>({length, values, valueOffsets, nullBitmap: nullMask}:
97+
arrow.Data<T>) {
9898
return new Column({
9999
length,
100100
type: new Utf8String,
@@ -112,48 +112,48 @@ class VectorToColumnVisitor extends arrow.Visitor {
112112
]
113113
});
114114
}
115-
// visitBinary<T extends arrow.Binary>(vector: arrow.Vector<T>) {}
116-
// visitFixedSizeBinary<T extends arrow.FixedSizeBinary>(vector: arrow.Vector<T>) {}
117-
// visitDate<T extends arrow.Date_>(vector: arrow.Vector<T>) {}
118-
visitDateDay<T extends arrow.DateDay>({length, data: {values: data, nullBitmap: nullMask}}:
119-
arrow.Vector<T>) {
115+
// visitBinary<T extends arrow.Binary>(data: arrow.Data<T>) {}
116+
// visitFixedSizeBinary<T extends arrow.FixedSizeBinary>(data: arrow.Data<T>) {}
117+
// visitDate<T extends arrow.Date_>(data: arrow.Data<T>) {}
118+
visitDateDay<T extends arrow.DateDay>({length, values: data, nullBitmap: nullMask}:
119+
arrow.Data<T>) {
120120
return new Column({type: new TimestampDay, length, data: data.subarray(0, length), nullMask});
121121
}
122122
visitDateMillisecond<T extends arrow.DateMillisecond>(
123-
{length, data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
123+
{length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
124124
return new Column(
125125
{type: new TimestampMillisecond, length, data: data.subarray(0, length), nullMask});
126126
}
127127
visitTimestampSecond<T extends arrow.TimestampSecond>(
128-
{length, data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
128+
{length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
129129
return new Column(
130130
{type: new TimestampSecond, length, data: data.subarray(0, length * 2), nullMask});
131131
}
132132
visitTimestampMillisecond<T extends arrow.TimestampMillisecond>(
133-
{length, data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
133+
{length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
134134
return new Column(
135135
{type: new TimestampMillisecond, length, data: data.subarray(0, length * 2), nullMask});
136136
}
137137
visitTimestampMicrosecond<T extends arrow.TimestampMicrosecond>(
138-
{length, data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
138+
{length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
139139
return new Column(
140140
{type: new TimestampMicrosecond, length, data: data.subarray(0, length * 2), nullMask});
141141
}
142142
visitTimestampNanosecond<T extends arrow.TimestampNanosecond>(
143-
{length, data: {values: data, nullBitmap: nullMask}}: arrow.Vector<T>) {
143+
{length, values: data, nullBitmap: nullMask}: arrow.Data<T>) {
144144
return new Column(
145145
{type: new TimestampNanosecond, length, data: data.subarray(0, length * 2), nullMask});
146146
}
147-
// visitTimeSecond<T extends arrow.TimeSecond>(vector: arrow.Vector<T>) {}
148-
// visitTimeMillisecond<T extends arrow.TimeMillisecond>(vector: arrow.Vector<T>) {}
149-
// visitTimeMicrosecond<T extends arrow.TimeMicrosecond>(vector: arrow.Vector<T>) {}
150-
// visitTimeNanosecond<T extends arrow.TimeNanosecond>(vector: arrow.Vector<T>) {}
151-
// visitDecimal<T extends arrow.Decimal>(vector: arrow.Vector<T>) {}
152-
visitList<T extends arrow.List>(vector: arrow.Vector<T>) {
153-
const {type, length, data: {valueOffsets, nullBitmap: nullMask}} = vector;
147+
// visitTimeSecond<T extends arrow.TimeSecond>(data: arrow.Data<T>) {}
148+
// visitTimeMillisecond<T extends arrow.TimeMillisecond>(data: arrow.Data<T>) {}
149+
// visitTimeMicrosecond<T extends arrow.TimeMicrosecond>(data: arrow.Data<T>) {}
150+
// visitTimeNanosecond<T extends arrow.TimeNanosecond>(data: arrow.Data<T>) {}
151+
// visitDecimal<T extends arrow.Decimal>(data: arrow.Data<T>) {}
152+
visitList<T extends arrow.List>(data: arrow.Data<T>) {
153+
const {type, length, valueOffsets, nullBitmap: nullMask} = data;
154154
const offsets =
155155
new Column({type: new Int32, length: length + 1, data: valueOffsets.subarray(0, length + 1)});
156-
const elements = this.visit(vector.getChildAt(0) as arrow.Vector<T['valueType']>);
156+
const elements = this.visit(data.children[0] as arrow.Data<T['valueType']>);
157157
return new Column({
158158
length,
159159
type: new List(type.children[0].clone({type: elements.type, nullable: elements.nullable})),
@@ -164,9 +164,9 @@ class VectorToColumnVisitor extends arrow.Visitor {
164164
]
165165
});
166166
}
167-
visitStruct<T extends arrow.Struct>(vector: arrow.Vector<T>) {
168-
const {type, length, data: {nullBitmap: nullMask}} = vector;
169-
const children = type.children.map((_, i) => this.visit(vector.getChildAt(i) as arrow.Vector));
167+
visitStruct<T extends arrow.Struct>(data: arrow.Data<T>) {
168+
const {type, length, nullBitmap: nullMask} = data;
169+
const children = type.children.map((_, i) => this.visit(data.children[i] ));
170170
return new Column({
171171
length,
172172
type: new Struct(children.map(
@@ -175,25 +175,28 @@ class VectorToColumnVisitor extends arrow.Visitor {
175175
children,
176176
});
177177
}
178-
// visitDenseUnion<T extends arrow.DenseUnion>(vector: arrow.Vector<T>) {}
179-
// visitSparseUnion<T extends arrow.SparseUnion>(vector: arrow.Vector<T>) {}
180-
visitDictionary<T extends arrow.Dictionary>(vector: arrow.Vector<T>) {
181-
const {type, length, data: {nullBitmap: nullMask}} = vector;
182-
const codes = this.visit(arrow.Vector.new(vector.data.clone(type.indices))).cast(new Uint32);
178+
// visitDenseUnion<T extends arrow.DenseUnion>(data: arrow.Data<T>) {}
179+
// visitSparseUnion<T extends arrow.SparseUnion>(data: arrow.Data<T>) {}
180+
visitDictionary<T extends arrow.Dictionary>(data: arrow.Data<T>) {
181+
const {type, length, nullBitmap: nullMask} = data;
182+
const codes = this.visit(data.clone(type.indices)).cast(new Uint32);
183183
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
184-
const categories = this.visit(vector.data.dictionary!);
184+
const categories = fromArrow(data.dictionary!);
185185
return new Column(
186186
{length, type: new Categorical(categories.type), nullMask, children: [codes, categories]});
187187
}
188-
// visitIntervalDayTime<T extends arrow.IntervalDayTime>(vector: arrow.Vector<T>) {}
189-
// visitIntervalYearMonth<T extends arrow.IntervalYearMonth>(vector: arrow.Vector<T>) {}
190-
// visitFixedSizeList<T extends arrow.FixedSizeList>(vector: arrow.Vector<T>) {}
191-
// visitMap<T extends arrow.Map_>(vector: arrow.Vector<T>) {}
188+
// visitIntervalDayTime<T extends arrow.IntervalDayTime>(data: arrow.Data<T>) {}
189+
// visitIntervalYearMonth<T extends arrow.IntervalYearMonth>(data: arrow.Data<T>) {}
190+
// visitFixedSizeList<T extends arrow.FixedSizeList>(data: arrow.Data<T>) {}
191+
// visitMap<T extends arrow.Map_>(data: arrow.Data<T>) {}
192192
}
193193

194-
const visitor = new VectorToColumnVisitor();
194+
const visitor = new DataToColumnVisitor();
195195

196196
export function fromArrow<T extends arrow.DataType>(vector: arrow.Vector<T>):
197197
Column<ArrowToCUDFType<T>> {
198-
return visitor.visit(vector);
198+
const cols = visitor.visitMany(vector.data);
199+
if (cols.length === 1) { return cols[0]; }
200+
return Table.concat(cols.map((col) => new Table({columns: [col]}))).getColumnByIndex(0);
201+
// return visitor.visit(vector);
199202
}

modules/cudf/src/data_frame.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ export class DataFrame<T extends TypeMap = any> {
984984
return [name, type.children.map((f) => toArrowMetadata(f.name, f.type))];
985985
};
986986
const names = this.names.map((name) => toArrowMetadata(<string|number>name, this.types[name]));
987-
return arrow.Table.from<T>(this.asTable().toArrow(names));
987+
return arrow.tableFromIPC<T>(this.asTable().toArrow(names));
988988
}
989989

990990
protected __constructChild<P extends keyof T, R extends T[P]>(name: P,

modules/cudf/src/dataframe/concat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export function concat<TFirst extends DataFrame, TRest extends DataFrame[]>(firs
8282
let data: any[]|undefined;
8383
return (type: DataType) => {
8484
// Lazily create and reuse the empty data Array
85-
data = data || new Array(df.numRows);
85+
data = data || new Array(df.numRows).fill(null);
8686
return Series.new({type, data})._col;
8787
};
8888
})();

modules/cudf/src/series.ts

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import {
2929
} from '@rapidsai/cuda';
3030
import {DeviceBuffer, MemoryResource} from '@rapidsai/rmm';
3131
import * as arrow from 'apache-arrow';
32-
import {VectorType} from 'apache-arrow/interfaces';
3332
import {compareTypes} from 'apache-arrow/visitor/typecomparator';
3433

3534
import {Column} from './column';
@@ -195,30 +194,26 @@ export class AbstractSeries<T extends DataType = any> {
195194
* import {Series, Int32} from '@rapidsai/cudf';
196195
* import * as arrow from 'apache-arrow';
197196
*
198-
* const arrow_vec = arrow.Vector.from({
199-
* type: new Int32,
200-
* values: [1,2,3,4],
201-
* highWaterMark: Infinity
202-
* });
197+
* const arrow_vec = arrow.vectorFromArray(new Int32Array([1,2,3,4])));
203198
* const a = Series.new(arrow_vec); // Int32Series [1, 2, 3, 4]
204199
*
205-
* const arrow_vec_list = arrow.Vector.from({
206-
* values: [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
207-
* type: new arrow.List(arrow.Field.new({ name: 'ints', type: new arrow.Int32 })),
208-
* });
200+
* const arrow_vec_list = arrow.vectorFromArray(
201+
* [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
202+
* new arrow.List(arrow.Field.new({ name: 'ints', type: new arrow.Int32 })),
203+
* );
209204
*
210205
* const b = Series.new(arrow_vec_list) // ListSeries [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
211206
*
212-
* const arrow_vec_struct = arrow.Vector.from({
213-
* values: [{ x: 0, y: 3 }, { x: 1, y: 4 }, { x: 2, y: 5 }],
214-
* type: new arrow.Struct([
207+
* const arrow_vec_struct = arrow.vectorFromArray(
208+
* [{ x: 0, y: 3 }, { x: 1, y: 4 }, { x: 2, y: 5 }],
209+
* new arrow.Struct([
215210
* arrow.Field.new({ name: 'x', type: new arrow.Int32 }),
216211
* arrow.Field.new({ name: 'y', type: new arrow.Int32 })
217212
* ]),
218-
* });
213+
* );
219214
*
220-
* const c = Series.new(arrow_vec_struct); // StructSeries [{ x: 0, y: 3 }, { x: 1, y: 4 },
221-
* // { x: 2, y: 5 }]
215+
* const c = Series.new(arrow_vec_struct);
216+
* // StructSeries [{ x: 0, y: 3 }, { x: 1, y: 4 }, { x: 2, y: 5 }]
222217
* ```
223218
*/
224219
static new<T extends arrow.Vector>(input: T): Series<ArrowToCUDFType<T['type']>>;
@@ -1225,7 +1220,7 @@ export class AbstractSeries<T extends DataType = any> {
12251220
* Copy the underlying device memory to host, and return an Iterator of the values.
12261221
*/
12271222
[Symbol.iterator](): IterableIterator<T['TValue']|null> {
1228-
return this.toArrow()[Symbol.iterator]() as IterableIterator<T['TValue']|null>;
1223+
return this.toArrow()[Symbol.iterator]() ;
12291224
}
12301225

12311226
/**
@@ -1261,9 +1256,9 @@ export class AbstractSeries<T extends DataType = any> {
12611256
/**
12621257
* Copy a Series to an Arrow vector in host memory
12631258
*/
1264-
toArrow(): VectorType<T> {
1259+
toArrow() {
12651260
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1266-
return new DataFrame({0: this._col}).toArrow().getChildAt<T>(0)!.chunks[0] as VectorType<T>;
1261+
return new DataFrame({0: this._col}).toArrow().getChildAt<T>(0)!;
12671262
}
12681263

12691264
/**
@@ -1687,13 +1682,8 @@ function asColumn<T extends DataType>(value: any) {
16871682

16881683
// If `data` is an Array, convert it to a Vector and use C++ Arrow-to-cuDF conversion
16891684
if (Array.isArray(data)) {
1690-
return fromArrow<T>(arrow.Vector.from({
1691-
highWaterMark: Infinity,
1692-
type: value.type ?? inferType(data),
1693-
// Slice `offset` from the Array before converting so
1694-
// we don't write unnecessary values with the Arrow builders.
1695-
values: typeof offset !== 'number' ? data : data.slice(offset)
1696-
}));
1685+
return fromArrow<T>(arrow.vectorFromArray(
1686+
typeof offset !== 'number' ? data : data.slice(offset), value.type ?? inferType(data)));
16971687
}
16981688

16991689
// If `data.buffer` is a ArrayBuffer, copy it to a DeviceBuffer

modules/cudf/src/series/list.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ export class ListSeries<T extends DataType> extends Series<List<T>> {
2929
* import {Series} from '@rapidsai/cudf';
3030
* import * as arrow from 'apache-arrow';
3131
*
32-
* const vec = arrow.Vector.from({
33-
* values: [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
34-
* type: new arrow.List(arrow.Field.new({ name: 'ints', type: new arrow.Int32 })),
35-
* });
32+
* const vec = arrow.vectorFromArray(
33+
* [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
34+
* new arrow.List(arrow.Field.new({ name: 'ints', type: new arrow.Int32 })),
35+
* );
3636
* const a = Series.new(vec);
3737
*
3838
* a.offsets // Int32Series [0, 3, 6, 9]
@@ -48,10 +48,10 @@ export class ListSeries<T extends DataType> extends Series<List<T>> {
4848
* import {Series} from '@rapidsai/cudf';
4949
* import * as arrow from 'apache-arrow';
5050
*
51-
* const vec = arrow.Vector.from({
52-
* values: [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
53-
* type: new arrow.List(arrow.Field.new({ name: 'ints', type: new arrow.Int32 })),
54-
* });
51+
* const vec = arrow.vectorFromArray(
52+
* [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
53+
* new arrow.List(arrow.Field.new({ name: 'ints', type: new arrow.Int32 })),
54+
* );
5555
* const a = Series.new(vec);
5656
*
5757
* a.elements // Int32Series [0, 1, 2, 3, 4, 5, 6, 7, 8]

0 commit comments

Comments
 (0)