/* * Copyright (c) 2005-2006 Wojciech Knapik. * Copyright (c) 2005-2008 The University of Wroclaw. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of Wojciech Knapik may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using SCG = System.Collections.Generic; namespace Nemerle.Collections { /** An auxillary data-structure for RList used instead of a regular tuple (which is a struct) for performance reasons. */ [Record] public class Pair ['a] : System.Collections.Generic.IEnumerable ['a] { public fst : 'a; public snd : 'a; [Nemerle.OverrideObjectEquals] public Equals (p : Pair ['a]) : bool { this.fst.Equals (p.fst) && this.snd.Equals (p.snd) } public override ToString () : string { $"($(this.fst), $(this.snd))" } public GetEnumerator () : SCG.IEnumerator ['a] { yield (this.fst); yield (this.snd) } } /** RList is short for Random Access List. It is a purely functional data-structure. This implementation is based on the SML sources found in Chris Okasaki's "Purely Functional Data Structures" (Cambridge University Press, 1999). */ public variant RList ['a] : System.Collections.Generic.IEnumerable ['a] { | Nil | Zero { arg : RList [Pair ['a]] } | One { arg1 : 'a; arg2 : RList [Pair ['a]] } /** Returns an empty RList. Time complexity: O (1). An empty RList. */ public static Empty : RList ['a] = Nil (); /** Checks, whether the RList [xs] is empty. Time complexity: O (1). The list to check for emptiness. true if the [xs] is empty, false otherwise. */ public static IsEmpty (xs : RList ['a]) : bool { | Nil => true | _ => false } /** Checks, whether [this] is an empty RList. Time complexity: O (1). true if [this] is an empty RList, false otherwise. */ public IsEmpty () : bool { IsEmpty (this) } /** Checks, whether two RLists are equal, by cheking if their respective elements are equal. Time complexity: O (min (|xs|, |ys|)). The first compared RList. The second compared RList. true if [xs] and [ys] are equal, false otherwise. */ public static Equals (xs : RList ['a], ys : RList ['a]) : bool { | (Zero (ps), Zero (qs)) | (One (x, ps), One (y, qs)) when x.Equals (y) => RList [Pair ['a]].Equals (ps, qs) | (Nil, Nil) => true | _ => false } /** Checks, whether [this] and [ys] are equal RLists, by cheking if their respective elements are equal. Time complexity: O (min (|this|, |ys|)). The RList [this] is compared to. true if [this] and [ys] are equal, false otherwise. */ [Nemerle.OverrideObjectEquals] public Equals (ys : RList ['a]) : bool { //PERFORMANCE: maybe it would be worth checking lenghts first ? Equals (this, ys) } /** Returns a new RList composed by adding [x], to the head of the RList [xs]. Time complexity: O (log (|xs|)). The element being added to the head of [xs]. The RList, to which head [x] is being added. A new RList composed of [x] as the new head and [xs] as the new tail. */ public static Cons (x : 'a, xs : RList ['a]) : RList ['a] { match (xs) { | One (y, ps) => Zero (RList [Pair ['a]].Cons (Pair (x, y), ps)) | Zero (ps) => One (x, ps) | Nil => One (x, Nil ()) } } /** Returns a new RList composed by adding [x], to the head of the RList [this]. Time complexity: O (log (|this|)). The element being added to the head of [this]. A new RList composed of [x] as the new head and [this] as the new tail. */ public Cons (x : 'a) : RList ['a] { Cons (x, this) } /** Separates and returns the head and tail of the RList [xs]. Time complexity: O (log (|xs|)). The RList, which tail is going to be returned along with the separated head. The head and tail of [xs]. */ public static UnCons (xs : RList ['a]) : 'a * RList ['a] { | Zero (ps) => def ((x, y), ps') = RList [Pair ['a]].UnCons (ps); (x, One (y, ps')) | One (x, Nil) => (x, Nil ()) | One (x, ps) => (x, Zero (ps)) | Nil => throw Exception ("Empty") } /** Separates and returns the head and tail of the RList [this]. Time complexity: O (log (|this|)). The head and tail of [this]. */ public UnCons () : 'a * RList ['a] { UnCons (this) } /** Returns the head of the RList [xs]. Time complexity: O (log (|xs|)). The RList, which head is going to be returned. The head of [xs]. */ public static Head (xs : RList ['a]) : 'a { | Zero (ps) => def (x, _) = RList [Pair ['a]].Head (ps); x | One (x, _) => x | Nil => throw Exception ("Empty") } /** Returns the head of the RList [this]. Time complexity: O (log (|this|)). The head of [this]. */ public Head () : 'a { Head (this) } /** Returns the head of the RList [xs]. Time complexity: O (log (|xs|)). An alias for Head. The RList, which head is going to be returned. The head of [xs]. */ public static Hd (xs : RList ['a]) : 'a { Head (xs) } /** Returns the head of the RList [this]. Time complexity: O (log (|this|)). An alias for Head. The head of [this]. */ public Hd () : 'a { Head (this) } /** Returns the tail of the RList [xs]. Time complexity: O (log (|xs|)). The RList, which tail is going to be returned. The tail of [xs]. */ public static Tail (xs : RList ['a]) : RList ['a] { def (_, xs') = UnCons (xs); xs' } /** Returns the tail of the RList [this]. Time complexity: O (log (|this|)). The tail of [this]. */ public Tail () : RList ['a] { Tail (this) } /** Returns the tail of the RList [xs]. Time complexity: O (log (|xs|)). An alias for Tail. The RList, which tail is going to be returned. The tail of [xs]. */ public static Tl (xs : RList ['a]) : RList ['a] { Tail (xs) } /** Returns the tail of the RList [this]. Time complexity: O (log (|this|)). An alias fot Tail. The tail of [this]. */ public Tl () : RList ['a] { Tail (this) } /** Returns the last element of the RList [xs]. Time complexity: O (log (|xs|)). The RList, which last element is going to be returned. The last element of [xs]. */ public static Last (xs : RList ['a]) : 'a { | Zero (ps) => RList [Pair ['a]].Last (ps).snd; | One (x, Nil) => x | One (_, ps) => RList [Pair ['a]].Last (ps).snd; | Nil => throw System.ArgumentException ("RList.Last called for empty RList") } /** Returns the last element of the RList [this]. Time complexity: O (log (|this|)). The last element of [this]. */ public Last () : 'a { Last (this) } /* An auxillary function used by the Length property. Time complexity: O (log (|xs|)). */ static _Length (xs : RList ['a], tmp = 1, count = 0) : int { match (xs) { | Zero (ps) => RList [Pair ['a]]._Length (ps, tmp * 2, count) | One (_, ps) => RList [Pair ['a]]._Length (ps, tmp * 2, count + tmp) | Nil => count } } /** Returns the length of the RList [this]. Time complexity: O (log (|this|)). The length of [this]. */ public Length : int { get { _Length (this) } } /** Returns true if there exists an element on [xs], that satisfies the predicate [f] (that is f (elem) == true). Time complexity: O (|xs|). The RList containing the tested elements. The predicate used during the tests. Returns true if for any element on the RList [xs], applying [f] to that element returns true, otherwise returns false. */ public static Exists (xs : RList ['a], f : 'a -> bool) : bool { def f' (x) { f (x.fst) || f (x.snd) } match (xs) { | One (x, ps) => f (x) || RList [Pair ['a]].Exists (ps, f') | Zero (ps) => RList [Pair ['a]].Exists (ps, f') | Nil => false } } /** Returns true if there exists an element on [this], that satisfies the predicate [f] (that is f (elem) == true). Time complexity: O (|xs|). The predicate used during the tests. Returns true if for any element on the RList [this], applying [f] to that element returns true, otherwise returns false. */ public Exists (f : 'a -> bool) : bool { Exists (this, f) } /** Returns true if the element [elem] exists on the RList [xs]. Time complexity: O (|xs|). The RList containing the tested elements. The element, which existence on the RList [xs] is being tested. Returns true if for any element on the RList [xs], element.Equals ([elem]), otherwise returns false. */ public static Member (xs : RList ['a], elem : 'a) : bool { Exists (xs, x => x.Equals (elem)) } /** Returns true if the element [elem] exists on the RList [this]. Time complexity: O (|this|). The element, which existence on the RList [this] is being tested. Returns true if for any element on the RList [this], element.Equals ([elem]), otherwise returns false. */ public Member (elem : 'a) : bool { Member (this, elem) } /** Returns true if the element [elem] exists on the RList [xs]. Time complexity: O (|xs|). An alias for Member. The RList containing the tested elements. The element, which existence on the RList [xs] is being tested. Returns true if for any element on the RList [xs], element.Equals ([elem]), otherwise returns false. */ public static Contains (xs : RList ['a], elem : 'a) : bool { Member (xs, elem) } /** Returns true if the element [elem] exists on the RList [this]. Time complexity: O (|this|). An alias for Member. The element, which existence on the RList [this] is being tested. Returns true if for any element on the RList [this], element.Equals ([elem]), otherwise returns false. */ public Contains (elem : 'a) : bool { Member (this, elem) } /** Returns the [i]-th element of the RList [xs]. Time complexity: O (log (|xs|)). The RList, which [i]-th element is going to be returned. The index under which the return element is located in [xs]. The [i]-th element of [xs]. */ public static Nth (xs : RList ['a], i : int) : 'a { match (xs) { | Zero (ps) => def (x, y) = RList [Pair ['a]].Nth (ps, i / 2); if (i % 2 == 0) x else y | One (x, ps) => if (i == 0) x else { // the three lines below could be substituted with Nth (Zero (ps), i - 1) def (x, y) = RList [Pair ['a]].Nth (ps, (i - 1) / 2); if (i % 2 != 0) x else y } | Nil => throw Exception ("Subscript") } } /** Returns the [i]-th element of the RList [this]. Time complexity: O (log (|this|)). The index under which the return element is located in [this]. The [i]-th element of [this]. */ public Nth (i : int) : 'a { Nth (this, i) } /* A helper function used by update Time complexity: O (log (|xs|)). */ static _Update (f : 'a -> 'a, i : int, xs : RList ['a]) : RList ['a] { match (xs) { | Zero (ps) => def f' (p) { if (i % 2 == 0) Pair (f (p.fst), p.snd) else Pair (p.fst, f (p.snd)) } Zero (RList [Pair ['a]]._Update (f', i / 2, ps)) | One (x, ps) => if (i == 0) One (f (x), ps) else Cons (x, _Update (f, i - 1, Zero (ps))) | Nil => throw Exception ("Subscript") } } /** Returns a new RList composed by substituting the [i]-th element of the RList [xs], with [x]. Time complexity: O (log (|xs|)). The RList used in composing the return value. The index under which the element to be substituted resides in [xs]. A new RList composed by substituting the [i]-th element of the RList [xs], with [x]. */ public static Update (i : int, y : 'a, xs : RList ['a]) : RList ['a] { _Update (_ => y, i, xs) } /** Returns a new RList composed by substituting the [i]-th element of the RList [this], with [x]. Time complexity: O (log (|this|)). The index under which the element to be substituted resides in [this]. A new RList composed by substituting the [i]-th element of the RList [this], with [x]. */ public Update (i : int, y : 'a) : RList ['a] { Update (i, y, this) } /** Iterates over the RList [xs] from left to right, composing the return value, by applying [f], to each of [xs]'s elements and the current [acc]. Time complexity: O (|xs|). The RList over which FoldLeft is going to iterate. The accumulator being updated on each level of recursion, to finally become the return value of FoldLeft. The supplied value will be used by [f] in the first step. The function being applied to ([RList-elem], [acc]) in each step. Acc in it's final state at the last step of recursion */ public static FoldLeft ['b] (xs : RList ['a], acc : 'b, f : 'a * 'b -> 'b) : 'b { match (xs) { | Zero (ps) => RList [Pair ['a]].FoldLeft (ps, acc, (a, b) => f (a.snd, f (a.fst, b))) | One (x, ps) => RList [Pair ['a]].FoldLeft (ps, f (x, acc), (a, b) => f (a.snd, f (a.fst, b))) | Nil => acc } } /** Iterates over the RList [this] from left to right, composing the return value, by applying [f], to each of [this]' elements and the current [acc]. Time complexity: O (|this|). The accumulator being updated on each level of recursion, to finally become the return value of FoldLeft. The supplied value will be used by [f] in the first step. The function being applied to ([RList-elem], [acc]) in each step. Acc in it's final state at the last step of recursion */ public FoldLeft ['b] (acc : 'b, f : 'a * 'b -> 'b) : 'b { FoldLeft (this, acc, f) } /** Iterates over the RList [xs] from right to left, composing the return value, by applying [f], to each of [xs]'s elements and the current [acc]. Time complexity: O (|xs|). The RList over which FoldRight is going to iterate. The accumulator updated on each level of recursion and used by [f]. The supplied value will be used by [f] in the last step. The function being applied to ([RList-elem], [acc]) in each step. The result of applying [f] to each element of [xs] and the current [acc]. */ public static FoldRight ['b] (xs : RList ['a], acc : 'b, f : 'a * 'b -> 'b) : 'b { match (xs) { | Zero (ps) => RList [Pair ['a]].FoldRight (ps, acc, (a, b) => f (a.fst, f (a.snd, b))) | One (x, ps) => f (x, RList [Pair ['a]].FoldRight (ps, acc, (a, b) => f (a.fst, f (a.snd, b)))) | Nil => acc } } /** Iterates over the RList [this] from right to left, composing the return value, by applying [f], to each of [this]' elements and the current [acc]. Time complexity: O (|this|). The accumulator updated on each level of recursion and used by [f]. The supplied value will be used by [f] in the last step. The function being applied to ([RList-elem], [acc]) in each step. The result of applying [f] to each element of [xs] and the current [acc]. */ public FoldRight ['b] (acc : 'b, f : 'a * 'b -> 'b) : 'b { FoldRight (this, acc, f) } /** Returns a new RList composed from [xs] by applying [f] to every element on that RList. Time complexity: O (|xs|). The source RList from which the return RList is composed by applying [f] to each of its elements. The function being applied to every [xs] element. The values it returns will make up the new RList returned by Map. A new RList composed from [xs] by applying [f] to every element on that RList. */ public static Map ['b] (xs : RList ['a], f : 'a -> 'b) : RList ['b] { def f' (x) { Pair (f (x.fst), f (x.snd)) } match (xs) { | One (x, ps) => One (f (x), RList [Pair ['a]].Map (ps, f')) | Zero (ps) => Zero (RList [Pair ['a]].Map (ps, f')) | Nil => Nil () } } /** Returns a new RList composed from [this] by applying [f] to every element on that RList. Time complexity: O (|this|). The function being applied to every [this] element. The values it returns will make up the new RList returned by Map. A new RList composed from [this] by applying [f] to every element on that RList. */ public Map ['b] (f : 'a -> 'b) : RList ['b] { Map (this, f) } /** Iterates over [xs] applying [f] to each of its elements. Time complexity: O (|xs|). The RList on which [f] is iterated. The function being applied to every [xs] element during iteration. */ public static Iter (xs : RList ['a], f : 'a -> void) : void { def f' (x) { f (x.fst); f (x.snd) } match (xs) { | One (x, ps) => f (x); RList [Pair ['a]].Iter (ps, f') | Zero (ps) => RList [Pair ['a]].Iter (ps, f') | Nil => () } } /** Iterates over [this] applying [f] to each of its elements. Time complexity: O (|this|). The function being applied to every [this] element during iteration. */ public Iter (f : 'a -> void) : void { Iter (this, f) } /** Returns an RList composed by reversing [xs]. Time complexity: O (|xs| * log (|xs|)). The RList used when composing the return value. An RList composed by reversing [xs]. */ public static Rev (xs : RList ['a]) : RList ['a] { FoldLeft (xs, Nil (), Cons) } // PERFORMANCE: O (n) complexity - gotta benchmark if it's faster, than the above // public static Rev_2 (xs : RList ['a]) : RList ['a] { // FromList (FoldLeft (xs, [], _ :: _)) // } /** Returns an RList composed by reversing [this]. Time complexity: O (|this| * log (|this|)). An RList composed by reversing [this]. */ public Rev () : RList ['a] { Rev (this) } /** Returns an a new RList composed by appending [ys] at the end of [xs]. Time complexity: roughly O (|xs| * log (|ys| + |xs|)). The RList, which elements come first in the resulting RList. The RList, which elements come second in the resulting RList. An RList composed by appending [ys] at the end of [xs]. */ public static Append (xs : RList ['a], ys : RList ['a]) : RList ['a] { FoldRight (xs, ys, Cons) } // PERFORMANCE: O (n) complexity - gotta benchmark if it's faster, than the above // public static Append_2 (xs : RList ['a], ys : RList ['a]) : RList ['a] { // FromList (FoldRight (xs, ToList (ys), _ :: _)) // } /** Returns an a new RList composed by appending [ys] at the end of [this]. Time complexity: roughly O (|this| * log (|this| + |ys|)). The RList, which elements come second in the resulting RList. An RListcomposed by appending [ys] at the end of [this]. */ public Append (ys : RList ['a]) : RList ['a] { Append (this, ys) } /** Returns an a new RList composed by appending [ys] at the end of [xs]. Time complexity: roughly O (|xs| * log (|ys| + |xs|)). An alias for Append. The RList, which elements come first in the resulting RList. The RList, which elements come second in the resulting RList. An RList composed by appending [ys] at the end of [xs]. */ public static @+ (xs : RList ['a], ys : RList ['a]) : RList ['a] { Append (xs, ys) } /** Returns an RList composed of the elements of list [xs]. Use RList (xs, |xs|) if |xs| is known. Time complexity: O (|xs|). The list used when composing the return value. An RList composed of the elements of [xs]. */ public static FromList (xs : list ['a]) : RList ['a] { FromList (xs, xs.Length) } /** Returns an RList composed of the elements of list [xs], of length [i]. Time complexity: O (|xs|). The list used when composing the return value. The length of [xs] and therefore of the return value as well. An RList composed of the elements of [xs]. */ public static FromList (xs : list ['a], i : int) : RList ['a] { _FromList (xs, i, l => match (l) { | x :: tl => (x, tl) | [] => throw Exception ("Empty") }) } /* An auxillary function used by FromList (xs, i). Time complexity: O (|xs|). */ static _FromList ['b] (xs : list ['b], i : int, f : list ['b] -> 'a * list ['b]) : RList ['a] { def f' (l) { def (elem1, rest1) = f (l); def (elem2, rest2) = f (rest1); (Pair (elem1, elem2), rest2) } if (i % 2 == 1) { def (elem, rest) = f (xs); One (elem, RList [Pair ['a]]._FromList (rest, i / 2, f')) } else if (i == 0) Nil () else Zero (RList [Pair ['a]]._FromList (xs, i / 2, f')) } /** Returns a list of elements of the RList [xs] in the same order. Time complexity: O (|xs|). The RList used when composing the return value. A list of elements of the RList [xs] in the same order. */ public static ToList (xs : RList ['a]) : list ['a] { FoldRight (xs, [], _ :: _) } /** Returns a list of elements of the RList [this] in the same order. Time complexity: O (|this|). A list of elements of the RList [this] in the same order. */ public ToList () : list ['a] { ToList (this) } /** Returns a string representation of the RList [xs]. Time complexity: O (|xs|). The RList used when composing the return value. A string representation of the RList [xs]. */ public static ToString (xs : RList ['a]) : string { xs.ToString () } /** Returns a string representation of the RList [this]. Time complexity: O (|this|). A string representation of the RList [this]. */ public override ToString () : string { match (this) { | Zero (ps) => $"Zero ($ps)" | One (x, ps) => $"One ($x, $ps)" | Nil => "Nil" } } public GetEnumerator () : SCG.IEnumerator ['a] { match (this) { | Zero (ps) => foreach (elem in ps) { yield elem.fst; yield elem.snd } | One (x, ps) => yield x; foreach (elem in ps) { yield elem.fst; yield elem.snd } | Nil => {} } } public Item [index : int] : 'a { get { Nth (this, index) } } } }