Skip to content

Commit

Permalink
$mol_range3 draft
Browse files Browse the repository at this point in the history
  • Loading branch information
zerkalica committed Sep 16, 2023
1 parent 5784c92 commit 64f3f68
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 3 deletions.
11 changes: 8 additions & 3 deletions range2/range2.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
namespace $ {
const options_key = Symbol('$mol_range2_options')

/** Lazy computed lists with native Array interface. $mol_range2_array is mutable but all derived ranges are immutable. */
export function $mol_range2< Item = number >(
item : ( index : number )=> Item = index => index as any ,
size = ()=> Number.POSITIVE_INFINITY ,
sample = new $mol_range2_array<Item>
) : Item[] {

return new Proxy( new $mol_range2_array< Item >() , {
return new Proxy( sample , {

get( target , field ) {

if( typeof field === 'string' ) {
if( field === 'length' ) return size()

Expand All @@ -21,7 +22,7 @@ namespace $ {
} ,

set( target , field ) {
return $mol_fail( new TypeError( 'Lazy range is read only' ) )
return $mol_fail( new TypeError( `Lazy range is read only, ${String(field)}` ) )
} ,

ownKeys( target ) {
Expand Down Expand Up @@ -128,6 +129,10 @@ namespace $ {
)
}

at(index: number): Item | undefined {
return this[index >= 0 ? index : this.length + index]
}

some< Context > (
check : ( this : Context , val : Item , index : number , list : Item[] )=> boolean ,
context? : Context ,
Expand Down
38 changes: 38 additions & 0 deletions range3/range3.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace $ {
function stub_ids(max = 10): string[] {
const ids: string[] = []
for (let i = 0; i < max; i++) {
ids.push($mol_stub_code())
}
return ids
}

function make_range() {
const range = new $mol_range3<string>()
const chunk_size = 10
const chunks = [
stub_ids(chunk_size),
stub_ids(chunk_size),
stub_ids(chunk_size / 2),
]
const count = chunks.reduce((acc, row) => acc + row.length, 0)
range.count = () => count
range.chunk_size = () => chunk_size
range.chunk = offset => chunks[offset]

return { range, chunks }
}

$mol_test({

'chunk addressing'() {
const { range, chunks } = make_range()
const arr = range.range()

$mol_assert_equal(arr[0], chunks[0][0])
$mol_assert_equal(arr.at(-1), chunks.at(-1)?.at(-1))
}

})
}

80 changes: 80 additions & 0 deletions range3/range3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
namespace $ {
export class $mol_range3<Item> extends $mol_range2_array<Item> {
count(): number {
throw new Error('implement')
}

chunk(offset: number): readonly Item[] {
throw new Error('implement')
}

chunk_size() {
return 100
}

page(page: number) {
return this.chunk(page * this.chunk_size())
}

item(index: number) {
const limit = this.chunk_size()

const chunk_index = index % limit
const page = Math.floor(index / limit)

const chunk = this.page(page)
const id = chunk[chunk_index]

return id
}

@ $mol_mem
temp(next?: readonly Item[]) {
return next ?? []
}

push(...ids: readonly Item[]) {
this.temp([ ...this.temp(), ...ids ])
this.temp_cut()

return this.length
}

temp_chunk_min() {
return 1
}

temp_cut() {
const temp = this.temp()
if (! temp) return

const limit = this.chunk_size()
const delete_chunks = Math.ceil(temp.length / limit) - this.temp_chunk_min()
if (delete_chunks <= 0) return

const delete_count = delete_chunks * limit
this.removed_count = this.removed_count + delete_count
this.temp(temp.slice(delete_count))
}

at(index: number) {
const count = this.count() + this.removed_count
if (index < 0) index = Math.max(0, count + this.temp().length + index)

if (index < count) return this.item(index)
return this.temp()[index - count]
}

protected removed_count = 0

get length() {
return this.count() + this.removed_count + this.temp().length
}

@ $mol_mem
range() {
return $mol_range2(index => this.at(index), () => this.length, this)
}

}
}

0 comments on commit 64f3f68

Please sign in to comment.