Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a generic 'fill' method

I am trying to write a generic fill method, and following is what I have come up with so far:

scala> import collection.generic.{GenericTraversableTemplate => GTT}
import collection.generic.{GenericTraversableTemplate=>GTT}

scala> import collection.generic.{TraversableFactory => TF}
import collection.generic.{TraversableFactory=>TF}

scala> def fill[A, CC[X] <: Traversable[X] with GTT[X, CC]]
     |   (n: Int)(elem: => A)(tf: TF[CC]) = tf.fill(n)(elem)
fill: [A, CC[X] <: Traversable[X] with scala.collection.generic.GenericTraversab
leTemplate[X,CC]](n: Int)(elem: => A)(tf: scala.collection.generic.TraversableFa
ctory[CC])CC[A]

scala> fill(3)('d')(List)
res42: List[Char] = List(d, d, d)

This works with all traversable collections except arrays. How do I make this code work with arrays?

like image 699
missingfaktor Avatar asked Sep 05 '11 18:09

missingfaktor


People also ask

How do you write a generic method in Java?

Example: Create a Generics Method We can call the generics method by placing the actual type <String> and <Integer> inside the bracket before the method name. demo. <String>genericMethod("Java Programming"); demo. <Integer>genericMethod(25);

How do you write a generic static method?

For static generic methods, the type parameter section must appear before the method's return type. The complete syntax for invoking this method would be: Pair<Integer, String> p1 = new Pair<>(1, "apple"); Pair<Integer, String> p2 = new Pair<>(2, "pear"); boolean same = Util. <Integer, String>compare(p1, p2);

What are generic methods?

What are generic methods? Explanation: Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

What is a generic method and when should it be used?

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn't such a dependency, a generic method should not be used. It is possible to use both generic methods and wildcards in tandem. Here is the method Collections.


2 Answers

If you don't mind creating an extra object, there's

def fill[CC[_]](n: Int) = new {
  def apply[A](elem: => A)(implicit cbf: CanBuildFrom[Nothing, A, CC[A]]) = {
    val b = cbf()
    1 to n foreach { _ => b += elem }
    b.result
  }
}

It doesn't get around objection (2), but the usage is nice:

scala> fill[List](3)("wish")
res0: List[java.lang.String] = List(wish, wish, wish)

scala> fill[Array](3)("wish")
res1: Array[java.lang.String] = Array(wish, wish, wish)
like image 82
Rex Kerr Avatar answered Nov 15 '22 08:11

Rex Kerr


It is possible to change the syntax of Rex' solution a little bit:

class Filler(n: Int) {
  def timesOf[A](elem: => A) = new Builder[A](elem)

  class Builder[A](elem: => A) {
    import scala.collection.generic.CanBuildFrom
    def fillIn[CC[_]](implicit cbf: CanBuildFrom[Nothing, A, CC[A]]) = {
      val b = cbf()
      for (_ <- 1 to n) b += elem
      b.result
    }
  }
}
implicit def int2Filler(n: Int) = new Filler(n)

// use as
(3 timesOf true).fillIn[List]

Because operator notation is only allowed for parentheses, we can't omit the brackets.

like image 20
kiritsuku Avatar answered Nov 15 '22 07:11

kiritsuku