-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AList.partition #89
Comments
A proper way (but clearly an not optimized one) : let partition (predicate : 'T -> bool) (list: alist<'T>) =
// TODO; Avoid reapplying the filter a second time
if list.IsConstant then
(constant (fun () -> list |> force |> IndexList.filter predicate),
constant (fun () -> list |> force |> IndexList.filter (predicate >> not)))
else
match list.History with
| Some history ->
(ofReader (fun () -> history.NewReader(IndexList.trace, FilterReader.DeltaMapping (fun _ v -> predicate v))),
ofReader (fun () -> history.NewReader(IndexList.trace, FilterReader.DeltaMapping (fun _ v -> predicate v |> not))))
| None ->
(ofReader (fun () -> FilterReader(list, fun _ v -> predicate v)),
ofReader (fun () -> FilterReader(list, fun _ v -> predicate v |> not))) I don't see how to make a simple reader function which makes only one pass from the list to be read. |
An easier (just as inefficient) way would be let partition (predicate : 'T -> bool) (list : alist<'a>) =
AList.filter predicate list, AList.filter (predicate >> not) list I'm currently thinking about that but I suspect there might not be a significantly more efficient way. I'll let you know once I concluded my experiments |
So here's my current best attempt which basically uses a shared I'm off for now and maybe I'll come up with something better. Or maybe someone else has a better idea... [<Sealed>]
type PartitionReader<'a>(input : alist<'a>, predicate : IndexCache<'a, bool>, side : bool) =
inherit AbstractReader<IndexListDelta<'a>>(IndexListDelta.empty)
let reader = input.GetReader()
static member DeltaMapping (side : bool, predicate : IndexCache<'a, bool>) =
IndexListDelta.choose (fun i op ->
match op with
| Remove ->
match lock predicate (fun () -> predicate.Revoke(i)) with
| Some v when v = side -> Some Remove
| _ -> None
| Set v ->
let o, n = lock predicate (fun () -> predicate.InvokeAndGetOld(i, v))
match n = side with
| true ->
Some (Set v)
| false ->
match o with
| Some v when v = side -> Some Remove
| _ -> None
)
override x.Compute(token) =
reader.GetChanges token |> IndexListDelta.choose (fun i op ->
match op with
| Remove ->
match lock predicate (fun () -> predicate.Revoke(i)) with
| Some v when v = side -> Some Remove
| _ -> None
| Set v ->
let o, n = lock predicate (fun () -> predicate.InvokeAndGetOld(i, v))
match n = side with
| true ->
Some (Set v)
| false ->
match o with
| Some v when v = side -> Some Remove
| _ -> None
)
let partition (predicate : Index -> 'a -> bool) (l : alist<'a>) =
if l.IsConstant then
let t, f = AList.force(l).Content |> MapExt.partition predicate
AList.ofIndexList (IndexList.ofMap t), AList.ofIndexList (IndexList.ofMap f)
else
let predicate = IndexCache predicate
match l.History with
| Some history ->
AList.ofReader (fun () -> history.NewReader(IndexList.trace, PartitionReader.DeltaMapping(true, predicate))),
AList.ofReader (fun () -> history.NewReader(IndexList.trace, PartitionReader.DeltaMapping(false, predicate)))
| None ->
AList.ofReader (fun () -> PartitionReader(l, predicate, true)),
AList.ofReader (fun () -> PartitionReader(l, predicate, false))
|
Pardon my ignorance on the subject, but isn't an internal compiler memoization for the predicate already there, this making this cache somewhat redundant? |
Hey, I don't think there's any optmization done for these predicates because any kind of memoization introduced by the compiler would need information about when to evict caches (which it generally can't have) So afaik. there's no such thing (unless of course I am wrong) |
You're surely right, I just thought of trivial predicates for which memoization should be too much a waste of memory and cpu cycles to be enforced on a compiler level basis. |
Similar to List.partition, adaptively.
A quick and dirt would be :
The text was updated successfully, but these errors were encountered: