share
Stack OverflowWhat are your most useful own library extensions?
[+18] [9] Peter Schmitz
[2011-05-10 06:08:28]
[ scala ]
[ http://stackoverflow.com/questions/5945904] [DELETED]

Sometimes I read about stackoverflow users are happy ( e.g. [1]) about grapping new ideas for their own standard library which is included in all their projects. I also have a package util where I keep all usefull stuff that isn´t included in the scala standard library but makes my life much easier. For example the pipe operator. So, I imagine that everyone has at least some small extensions common to all their projects. I am (and I guess others too) interested in the most useful extensions of the community here, so one can collect nice ideas to fresh up minds.

(3) Easy answer: Scalaz. - Apocalisp
[+13] [2011-05-10 06:10:27] Peter Schmitz

For example, the common Pipe Operator (slightly adapted):

object Pipe {
  class Piped[T] (value: T) {
    def |> [R] (f: T =>  R ): R =   f(value)
    def |>>    (f: T => Any): T = { f(value); value }
  }
}

implicit def toPiped[T](value: T) = new Pipe.Piped[T](value)

Usage (REPL):

scala> { if (math.random > 0.5) "Hi" else "Bye" } |> (_.toUpperCase + " John")
res0: java.lang.String = BYE John

scala> { math.random > 0.5 } |>> { require(_) }
res1: Boolean = true

Really smart, love that one :) - Alois Cochard
Thanks. But it´s not my own idea. I think it´s the answer of @Kevin Wright that brought this to my mind. - Peter Schmitz
Out of curiosity: what's the advantage of nesting Piped in Pipe? - Jean-Philippe Pellet
Good point, oversight, I think; was inspired respectively confused by A forward pipe (“ |> ”) operator in Scala where it´s wrapped in object Functional. - Peter Schmitz
+1: These are my two favorites also, although I call them use and effect, respectively, since I find it easier to remember that effect causes side effects than that |>> does. - Rex Kerr
@Rex Funny, |>> evolves out of my needs and I haven´t seen it before: The fact that you're also using it, is a good indication that it is useful and no coincidence. Good point about effect vs |>>. - Peter Schmitz
Thanks for the acknowledgement, though I can't take the credit :) - Kevin Wright
1
[+9] [2011-05-10 07:18:38] Jean-Philippe Pellet

A classical — the “on-loan” pattern:

def withResource[T <: { def close(): Unit }, R](resource: T)(work: T => R): R = {
  try {
    // do the work
    work(resource)
  } finally {
    // dispose resource
    resource.close()
  }
}

Reference: http://scala.sygneca.com/patterns/loan


this one save so many bugs :) - Alois Cochard
2
[+6] [2011-05-10 15:41:20] Rex Kerr

I do a lot of microbenchmarking, which makes the following methods very useful:

// Do something n times  
def lots[F](n: Int)(f: => F): F = if (n>1) { f; lots(n-1)(f) } else f

// Time something
def time[F](f: => F) = {
  var t0 = System.nanoTime
  val ans = f
  (ans , System.nanoTime - t0)
}

// Time something and tell us how long it took
def ptime[F](f: => F) = {
  val ta = time(f)
  printf("Elapsed: %.3f s\n",1e-9*ta._2)
  ta._1
}

+1, and the same again, I also have somewhat else in my lib, I called it def benchmark[T]... instead of def time[F].... - Peter Schmitz
3
[+4] [2011-05-10 15:58:58] Rex Kerr

Do you ever want the nice copying features of a case class except that you don't want equality or matching to pay attention to that entry? Well, enter the:

// These can be placed in case classes without changing equality, sort of like a comment
class Caseless[A](private[Utility] val a: A) {
  override def hashCode = 0
  override def equals(o: Any) = o.isInstanceOf[Caseless[_]]
  override def toString = "_"
  def value = a
}
implicit def anything_is_caseless[A](a: A) = new Caseless(a)
implicit def caseless_is_anything[A](c: Caseless[A]) = c.a

where you can now do things like

case class Pony(name: String, creationTime: Caseless[Long]) {}
val blaze = new Pony("Blaze", System.currentTimeMillis)
Thread.sleep(10)
val blaze2 = new Pony("Blaze", System.currentTimeMillis)
blaze == blaze2  // true
blaze2.creationTime - blaze.creationTime  // 10 or more
val spirit = blaze.copy(name = "Spirit")  // Rename blaze
spirit == blaze  // false, they have different names
blaze.creationTime.value - spirit.creationTime.value  // Zero

so you can safely carry along information in your case class without it affecting equality. (If you're matching, you do still need to throw in an extra _.)


Hey, very useful trick, thanks! - Jean-Philippe Pellet
4
[+3] [2011-05-10 13:32:10] Dave Griffith

I use this one all the time when doing anything like batch processing. It's essentially a small implementation of MapReduce, usable on any Traversable

object RichTraversable {
  implicit def traversable2RichTraversable[A](t: Traversable[A]) = new RichTraversable[A](t)
}

class RichTraversable[A](t: Traversable[A]) {

  def reduceBy[B, C](f: A => B, g: A => C, reducer: (C, C) => C): Map[B, C] = {
    def reduceInto(map: Map[B, C], key: B, value: C): Map[B, C] =
      if (map.contains(key)) {
        map + (key -> reducer(map(key), value))
      }
      else {
        map + (key -> value)
      }
    t.foldLeft(Map.empty[B, C])((m, x) => reduceInto(m, f(x), g(x)))
  }

  //here are some common specializations, many more elided

  def sumBy[B, C: Numeric](f: A => B, g: A => C): Map[B, C] = reduceBy(f, g, implicitly[Numeric[C]].plus(_: C, _: C))

  def maxBy[B, C: Ordering](f: A => B, g: A => C): Map[B, C] = reduceBy(f, g, implicitly[Ordering[C]].max(_: C, _: C))


}
val test = Set("foo", "bar", "barangus")
println(test.sumBy(_.charAt(0), _.length))  //prints Map('f'->3, 'b'->11)
println(test.maxBy(_.charAt(0), _.length))  //prints Map('f'->3, 'b'->8)

5
[+2] [2011-05-10 09:11:21] Sam Stainsby

More for better code readability than making coding easier:

package net.uniscala.scala

private[scala] class OptionIfDefinedExtension[A](val self:Option[A])
  extends Proxy {

  def ifDefined[B](f:A=>B):Option[B] = self.map[B](f)

  def otherwise[B>:A](default: =>B):B = self.getOrElse(default)
}

object OptionIfDefinedImplicits {
  implicit def toOptionIfDefinedExtension[A](option:Option[A])
    = new OptionIfDefinedExtension(option)
}

Usage:

import net.uniscala.scala.OptionIfDefinedImplicits._

val topt:Option[T] = ...

topt ifDefined { t:T => ... } otherwise { ... } 

(3) I've seen that before in another SO answer, but I don't really like this one. You're inventing your own alternative for an existing language feature, if ... else, renaming the else to otherwise... And you gain almost nothing above just writing if (topt.isDefined) { ... } else { ... }. - Jesper
(1) @Jesper - No, it is not the equivalent of if if (topt.isDefined) { ... } else { ... } at all. Your way will still need to do 'get' to expose the inner value of the Option, which, if you make a mistake in logic, can lead to a runtime error. My way is safer, and also more concise than if/else. If you wanted to argue about replacing existing features, my way is actually a suggarred form of topt map { t:T => ... } getOrElse { ... } (note you don't can actually write :T - it was just clearer to write the type in for the demo). I find my way of writing it easier to read than map/getOrElse. - Sam Stainsby
@Sam Yes, I see that your solution is safer than just calling get on topt yourself. Still I find it ugly to use an alternative word for else. - Jesper
(1) @Jesper 'else' does not belong in this context. The best you could do to keep existing keywords is 'topt ifDefined { t => ... } getOrElse { ... } which no longer reads well. These days, I find myself hardly ever using 'isDefined', except where the sought value is the boolean itself. On the other hand, I'm getting used to seeing 'map'/'getOrElse' and 'foreach' applied to option, which is what you could use here instead of my construct if you want the same level of safety. You could also use 'topt => match { case Some(t) => ... ; case None => ...}' with similar effect. - Sam Stainsby
The post discussing this was stackoverflow.com/questions/5654004/… - Jean-Philippe Pellet
I also discussed it here in 2009 scala-lang.org/node/3496 - Sam Stainsby
6
[+2] [2011-05-10 06:23:10] Peter Schmitz
object DoWhile {
  class Doing[T](f: () => T) {
    def While(b: T => Boolean): T = {
      var t = f()
      while (b(t)) { t = f() }
      t
    }
  }
  def Do[T](f: () => T) = new Doing(f)
}

Usage (REPL):

scala> DoWhile.Do {
     |   () => math.random
     | } While (_ < 0.5)
res0: Double = 0.8574303051236236

Don't see the advantage of this one vs the one implemented in the language ? programming-scala.labs.oreilly.com/ch03.html - Alois Cochard
(1) You don´t have to define a var for holding the result before the loop which messes up the scope. I am not a friend of having vars in scope that should be val after the loop. - Peter Schmitz
oh yes for sure, didn't got the use of '_' first time :) thanks for the explanation - Alois Cochard
(4) Why do you have f: () => T instead of just f: => T? Anyway, I just use Iterator.continually(math.random).dropWhile(_ < 0.5).next. - Rex Kerr
@Rex Refreshing Iterator.continually...! And anyway, I should fix that () => T in my lib. Thanks. - Peter Schmitz
7
[+1] [2011-05-10 16:34:20] Peter Schmitz

I often use:

class RichTraversableOnce[A](val t: TraversableOnce[A]) {
  def mkStr = t.mkString(",")
  def mkStrln = t.mkString("\n","\n","\n")
}

class RichTraversable[A](t: Traversable[A]) {
  def toMapBy[B](f: A => B): Map[B,A] = {
    // no duplicate keys compared to library method groupBy
    val res = t.map{ e => (f(e),e) }.toMap
    require(res.size == t.size, "\n%s\n%s\n".format(res.mkStrln,t.mkStrln))
    res
  }
}

import scala.collection.mutable.{Map => MutMap, Buffer}
class RichSeq[A](val seq: Seq[A]) { 
  def isDistinct: Boolean = seq.distinct sameElements seq
  def isDistinctBy[B](f: A => B): Boolean = seq.distinctBy(f) sameElements seq
  def distinctBy[B](f: A => B): Seq[A] = {
    seq.foldLeft {(Buffer[A](),MutMap[B,A]())} {
      case ((b,m),x) if m contains f(x) => (b,m)
      case ((b,m),x) => 
        m += f(x) -> x
        b += x
        (b,m)
    }._1
  }
  def sameElementsOrderless(s: Seq[A]): Boolean = {
    // sameElements takes order into account
    seq.size == s.size && seq.toSet.subsetOf(s.toSet) &&
                            s.toSet.subsetOf(seq.toSet)
  }
}

class RichSet[A](val set: Set[A]) {
  def isDisjunct(s: Set[A]): Boolean = {
    (set intersect s).isEmpty // (set union s).size == set.size + set.size
  }
  def sameElementsOrderless(s: scala.collection.Set[A]): Boolean = {
    // sameElements takes order into account
    s.subsetOf(set) && set.subsetOf(s)
  }
}

Of course implicit conversions to Rich... are necessary.


8
[+1] [2011-05-10 15:45:07] Rex Kerr

Tuples are missing a couple of extremely useful (to me) methods that I add back in (for small sizes of tuples). I could call each map, but after using collections I find that I expect all the types to be the same, which is not true here. One could also prefer multiple argument lists instead of the two arguments in one argument list.

// Methods for 2-element tuples
class PairWrapper[A,B](ab: (A,B)) {
  def each[Y,Z](fl: A=>Y, fr: B=>Z) = (fl(ab._1),fr(ab._2))
  def fold[Z](f: (A,B)=>Z) = f(ab._1,ab._2)
}
implicit def pair_has_utility[A,B](ab: (A,B)) = new PairWrapper(ab)

// Methods for 3-element tuples
class TrioWrapper[A,B,C](abc: (A,B,C)) {
  def each[X,Y,Z](fl: A=>X, fc: B=>Y, fr: C=>Z) = (fl(abc._1),fc(abc._2),fr(abc._3))
  def fold[Z](f: (A,B,C)=>Z) = f(abc._1,abc._2,abc._3)
}
implicit def trio_has_utility[A,B,C](abc: (A,B,C)) = new TrioWrapper(abc)

...

I recently thought about the same issue and was thinking about def map[C,D](f: ((A,B)) => ((C,D))): Tuple2[C,D] = f(t) and def mapFirst [C](f: A => C) = (f(t._1), t._2 ) and def mapSecond[D](f: B => D) = ( t._1 ,f(t._2)) ... on class RichTuple2[A,B](t: Tuple2[A,B]) What do you think? - Peter Schmitz
@Peter Schmitz - mapFirst and mapSecond look reasonable. You already have your original map. It's called |>, and it's even more powerful. I have f: (A,B) => Z for a reason, namely that you don't have to take apart the tuple. - Rex Kerr
9