I tried to write a test / synchronization function for the answers presented in this SO question . Some answers work on Array[T] , some on List[T] , one on Iterable[T] and one on String !
What I would like to write is a function that takes shift* functions from a question or answers, an input list, a predicate, and the expected output, and runs the function. Example:
def test[T]( func:(Seq[T], T=>Boolean) => Seq[T], input:Seq[T], predicate:T=>Boolean, expected:Seq[T]): Unit = { // may be some warm up // ... time start, run func, time stop, // check output against expected }
Except that I can define a signature, since Array seems to have mutable Seq properties, while List has immutable Seq properties.
What is the best way to handle this?
Change Using Thomas's suggestion, as far as I can get (works on Array[Char] , List[T] , but not on Array[T] ):
val inputArr = Array('a', 'b', 'C', 'D') val expectArr = Array('a', 'C', 'D', 'b') val inputList = inputArr.toList val expectList = expectArr.toList def test[I, T]( func:(I, T=>Boolean) => Traversable[T], input: I, predicate: T=>Boolean, expected: Traversable[T]): Boolean = { val result = func(input, predicate) if (result.size == expected.size) { result.toIterable.zip(expected.toIterable).forall(x => x._1 == x._2) } else { false } } // this method is from Geoff [there][2] def shiftElements[A](l: List[A], pred: A => Boolean): List[A] = { def aux(lx: List[A], accum: List[A]): List[A] = { lx match { case Nil => accum case a::b::xs if pred(b) && !pred(a) => aux(a::xs, b::accum) case x::xs => aux(xs, x::accum) } } aux(l, Nil).reverse } def shiftWithFor[T](a: Array[T], p: T => Boolean):Array[T] = { for (i <- 0 until a.length - 1; if !p(a(i)) && p(a(i+1))) { val tmp = a(i); a(i) = a(i+1); a(i+1) = tmp } a } def shiftWithFor2(a: Array[Char], p: Char => Boolean):Array[Char] = { for (i <- 0 until a.length - 1; if !p(a(i)) && p(a(i+1))) { val tmp = a(i); a(i) = a(i+1); a(i+1) = tmp } a } def shiftMe_?(c:Char): Boolean = c.isUpper println(test(shiftElements[Char], inputList, shiftMe_?, expectList)) println(test(shiftWithFor2, inputArr, shiftMe_?, expectArr)) //following line does not compile println(test(shiftWithFor, inputArr, shiftMe_?, expectArr)) //found : [T](Array[T], (T) => Boolean) => Array[T] //required: (?, (?) => Boolean) => Traversable[?] //following line does not compile println(test(shiftWithFor[Char], inputArr, shiftMe_?, expectArr)) //found : => (Array[Char], (Char) => Boolean) => Array[Char] //required: (?, (?) => Boolean) => Traversable[?] //following line does not compile println(test[Array[Char], Char](shiftWithFor[Char], inputArr, shiftMe_?, expectArr)) //found : => (Array[Char], (Char) => Boolean) => Array[Char] //required: (Array[Char], (Char) => Boolean) => Traversable[Char]
I will answer Daniel's question as accepted, how he compiles, and will provide me with another way to achieve what I wanted - if the Array [T] method does not create a new array (and leads to manifest problems).
(2): How will the functional approach to moving certain elements of the array?