61 lines
1 KiB
JavaScript
61 lines
1 KiB
JavaScript
import { entries } from 'izuna'
|
|
import { Clone } from './clone.js'
|
|
import { IndexableIterator } from './iter.js'
|
|
|
|
/**
|
|
* @param {...any} values
|
|
*/
|
|
export class Tuple {
|
|
_values
|
|
_length
|
|
|
|
get length() {
|
|
return this._length
|
|
}
|
|
|
|
constructor(values) {
|
|
if (values.length > 0) {
|
|
this._length = values.length
|
|
values.forEach(this._setEntry.bind(this))
|
|
}
|
|
|
|
this._values = values
|
|
}
|
|
|
|
_setEntry([key, value], index) {
|
|
if (typeof key !== 'number') {
|
|
Object.defineProperty(this, key, {
|
|
get() {
|
|
return this[index]
|
|
}
|
|
})
|
|
}
|
|
|
|
this[index] = value
|
|
}
|
|
|
|
static from(values) {
|
|
return Object.freeze(new this(entries(values)))
|
|
}
|
|
|
|
|
|
toString() {
|
|
return `(${this._values.map(([_, v]) => v.toString())})`
|
|
}
|
|
|
|
clone() {
|
|
return this[Clone]()
|
|
}
|
|
|
|
[Clone]() {
|
|
return Object.freeze(new this.constructor(this._values))
|
|
}
|
|
|
|
[Symbol.iterator]() {
|
|
return new IndexableIterator(this._values.map(([_, v]) => v))
|
|
}
|
|
}
|
|
|
|
export const tuple = Tuple.from
|
|
|
|
|