Skip to content

Commit 2145d36

Browse files
committed
sketched AList.sub (currently untested)
1 parent 293685b commit 2145d36

3 files changed

Lines changed: 103 additions & 1 deletion

File tree

src/FSharp.Data.Adaptive/AdaptiveIndexList/AdaptiveIndexList.fs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,87 @@ module internal AdaptiveIndexListImplementation =
11931193

11941194
delta
11951195

1196+
[<Sealed>]
1197+
type SubReader<'a>(input : alist<'a>, offset : aval<int>, count : aval<int>) =
1198+
inherit AbstractReader<IndexListDelta<'a>>(IndexListDelta.empty)
1199+
1200+
let reader = input.GetReader()
1201+
let mutable state = MapExt.empty
1202+
let mutable minIndex = Index.zero
1203+
let mutable maxIndex = Index.zero
1204+
1205+
override x.Compute(token : AdaptiveToken) =
1206+
let ops = reader.GetChanges token
1207+
let offset = offset.GetValue token
1208+
let count = count.GetValue token
1209+
1210+
if MapExt.isEmpty state then
1211+
let part = reader.State.Content.SliceAt(offset, offset + count - 1)
1212+
state <- part
1213+
if not (MapExt.isEmpty state) then
1214+
minIndex <- MapExt.minKey state
1215+
maxIndex <- MapExt.maxKey state
1216+
part |> MapExt.map (fun _ v -> Set v) |> IndexListDelta
1217+
1218+
else
1219+
let part = reader.State.Content.SliceAt(offset, offset + count - 1)
1220+
if MapExt.isEmpty part then
1221+
let delta =
1222+
state
1223+
|> MapExt.map (fun _ _ -> Remove)
1224+
|> IndexListDelta
1225+
state <- MapExt.empty
1226+
minIndex <- Index.zero
1227+
maxIndex <- Index.zero
1228+
delta
1229+
else
1230+
let newMin = MapExt.minKey part
1231+
let newMax = MapExt.maxKey part
1232+
1233+
if newMin > maxIndex || newMax < minIndex then
1234+
let ops =
1235+
MapExt.union
1236+
(state |> MapExt.map (fun _ _ -> Remove))
1237+
(part |> MapExt.map (fun _ v -> Set v))
1238+
state <- part
1239+
minIndex <- newMin
1240+
maxIndex <- newMax
1241+
IndexListDelta ops
1242+
else
1243+
1244+
let mutable delta = ops.Content.[newMin .. newMax]
1245+
1246+
1247+
let lDelta =
1248+
if minIndex < newMin then
1249+
reader.State.Content.WithMin(minIndex).WithMaxExclusive(newMin)
1250+
|> MapExt.map (fun _ _ -> Remove)
1251+
elif newMin < minIndex then
1252+
reader.State.Content.WithMin(newMin).WithMaxExclusive(minIndex)
1253+
|> MapExt.map (fun _ v -> Set v)
1254+
else
1255+
MapExt.empty
1256+
1257+
let rDelta =
1258+
if maxIndex < newMax then
1259+
reader.State.Content.WithMinExclusive(maxIndex).WithMax(newMax)
1260+
|> MapExt.map (fun _ v -> Set v)
1261+
elif newMax < maxIndex then
1262+
reader.State.Content.WithMinExclusive(newMax).WithMax(maxIndex)
1263+
|> MapExt.map (fun _ _ -> Remove)
1264+
else
1265+
MapExt.empty
1266+
1267+
minIndex <- newMin
1268+
maxIndex <- newMax
1269+
state <- part
1270+
MapExt.union lDelta (MapExt.union delta rDelta)
1271+
|> IndexListDelta
1272+
1273+
1274+
1275+
1276+
11961277

11971278
/// Gets the current content of the alist as IndexList.
11981279
let inline force (list : alist<'T>) =
@@ -1522,7 +1603,17 @@ module AList =
15221603
constant (fun () -> force list |> IndexList.pairwiseCyclic)
15231604
else
15241605
ofReader (fun () -> PairwiseReader(list, true))
1525-
1606+
1607+
let subA (offset: aval<int>) (count: aval<int>) (list: alist<'T>) =
1608+
if list.IsConstant && offset.IsConstant && count.IsConstant then
1609+
let offset = AVal.force offset
1610+
let count = AVal.force count
1611+
constant (fun () -> (force list).Content.SliceAt(offset, offset + count - 1) |> IndexList.ofMap)
1612+
else
1613+
ofReader (fun () -> SubReader(list, offset, count))
1614+
1615+
let sub (offset: int) (count: int) (list: alist<'T>) =
1616+
subA (AVal.constant offset) (AVal.constant count) list
15261617

15271618

15281619
/// Adaptively reverses the list

src/FSharp.Data.Adaptive/AdaptiveIndexList/AdaptiveIndexList.fsi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ module AList =
190190
/// Returns a list of each element tupled with its successor and the last element tupled with the first.
191191
val pairwiseCyclic : list: alist<'T> -> alist<'T * 'T>
192192

193+
val subA : offset : aval<int> -> count : aval<int> -> alist<'T> -> alist<'T>
194+
val sub : offset : int -> count : int -> alist<'T> -> alist<'T>
195+
193196
/// Tries to get the element associated to a specific Index from the list.
194197
/// Note that this operation should not be used extensively since its resulting
195198
/// aval will be re-evaluated upon every change of the list.

src/FSharp.Data.Adaptive/Datastructures/MapExt.fs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3278,6 +3278,14 @@ type internal MapExt<'Key, 'Value when 'Key : comparison>(comparer : IComparer<'
32783278

32793279
member x.WithMin(min : 'Key) = MapExt(comparer, MapExtImplementation.withMin comparer min root)
32803280
member x.WithMax(max : 'Key) = MapExt(comparer, MapExtImplementation.withMax comparer max root)
3281+
3282+
member x.WithMinExclusive(min : 'Key) =
3283+
let n, _, _ = MapExtImplementation.withMinExclusiveN comparer min root
3284+
MapExt(comparer, n)
3285+
member x.WithMaxExclusive(min : 'Key) =
3286+
let n, _, _ = MapExtImplementation.withMaxExclusiveN comparer min root
3287+
MapExt(comparer, n)
3288+
32813289
member x.Slice(min : 'Key, max : 'Key) = MapExt(comparer, MapExtImplementation.slice comparer min max root)
32823290
member x.SliceAt(min : int, max : int) = MapExt(comparer, MapExtImplementation.sliceAt min max root)
32833291

0 commit comments

Comments
 (0)