Il punto è quello di evitare di creare una variabile intermedia che probabilmente non si vuole essere in giro, o per evitare di dover creare un nuovo blocco per qualcosa che' fare di passaggio. Supponiamo di avere il gheppio come in Ruby:
implicit class RubyKestrel[A](val repr: A) extends AnyVal {
def tap[B](f: A => B) = { f(repr); repr }
}
Ora supponiamo abbiamo qualche riga di codice:
xs.map(_ + 7).filter(foo).take(n)
e vogliamo stampare un messaggio di debug dopo il filtro. Senza tap
abbiamo refactoring quella linea a:
{
val temp = xs.map(_ + 7).filter(foo)
println(temp)
temp.take(n)
}
Ugh. Ora supponiamo di avere tap
:
xs.map(_ + 7).filter(foo).tap(println).take(n)
Accidenti, modo migliore!
Supponiamo di disporre di uno stack con un metodo di aggiunta e di aggiungere qualcosa allo stack prima di utilizzarlo da qualche altra parte.
def newStack = {
val stack = new Stack
stack add "whatever"
stack
}
Ugh. Ma con tap
:
def newStack = (new Stack).tap(_ add "whatever")
piuttosto comodo - è in realtà solo consente di trasformare qualsiasi metodo side-effettuando normale in qualcosa che si può chiamate a catena. E dal momento che le chiamate incatenate sono spesso più basse, è spesso una grande vittoria.
fonte
2014-04-22 22:47:41
Mille grazie, capito !! – MaatDeamon
Questa è anche la necessità che mi ha spinto naturalmente a volere un _tap_: volevo evitare di dover creare variabili e poi ripeterle alla fine del blocco. Il codice è più breve e più leggibile con _tap_ (al punto che penso dovrebbe essere parte di Scala stessa). – Frank