Scala empty default closure? - scala

just a quick question I seem to be unable to find an answer to.
I have a method definition in Scala that looks like this:
def execute(goals: List[String],
profiles: List[String] = List(),
loggingCallback: (String) => Unit = { _ => }): Result = {
// method body
loggingCallback("a message")
}
I would like to know whether there is a better way to specify a default empty closure. The question is not about how to implement logging, this is just an example.

Your solution is fine. You could introduce a type alias for Function1[X, Unit]; use () as per Kevin's answer, and drop unnecessary parens.
scala> type Effect[-A] = (A => Unit)
defined type alias Effect
scala> def foo(f: Effect[String] = _ => ()) = ()
foo: (f: (String) => Unit)Unit
You could also define a noop function:
scala> val noop = (a: Any) => ()
noop: (Any) => Unit = <function1>
scala> def foo(f: Effect[String] = noop) = ()

The value () is an instance of unit, so this should do the trick:
def execute(
goals: List[String],
profiles: List[String] = Nil,
loggingCallback: (String) => Unit = { _ => () }): Result =
{
// method body
loggingCallback("a message")
// do something returning a Result
}
update
If something is optional, then it often makes more sense to state so explicitly, this also results in better self-documenting code:
def execute(
goals: List[String],
profiles: List[String] = Nil,
loggingCallback: Option[(String) => Unit] = None): Result =
{
// method body
loggingCallback forEach { _.apply("a message") }
// do something returning a Result
}
update 2
DSL-esque situations like this are also one of the very few situations where I'll condone the use of null in Scala:
def execute(
goals: List[String],
profiles: List[String] = Nil,
loggingCallback: (String) => Unit = null
): Result = {
// method body
val log = Option(loggingCallback) getOrElse {_ => ()}
log("a message")
// do something returning a Result
}
Note the Option(loggingCallback) to immediately convert the nullable loggingCallback into a nice type-safe Option, then getOrElse to provide a fallback alternative.

Related

How to use parameterless method without bracket as type parameter?

For example, I have 2 method definition as below with and without bracket.
def foo1: String = "bar"
def foo2():String = "bar"
In case of method parameter, I can create higher ordered functions for both as below:
def bar(fn: =>String) = ??? // bar(foo1)
def bar(fn: ()=>String) = ??? // bar(foo2)
However in case of generic type, I'm only able to use foo2.
val list: List[() => String] = List(foo2)
The following does not work.
val list: List[() => String] = List(foo1) //foo1 type mismatch.
val list: List[ => String] = List(foo1) //Invalid syntax.
So, my question is what is the correct type definition for parameterless and bracketless method?
Your first definition of bar def bar(fn: => String) = ??? does not describe a function parameter with no arguments, it describes a lazy parameter.
So if you have a function which produces a string, and you wish to defer the execution of this function, you can pass it as a lazy param into your function. This allows the function bar in this case, to either execute the function and produce the String, or to pass this code to another function. Take for example an if statement, it takes in 2 functions, and only executes 1 of them based on the predicate.
Now to answer your question, you can either use the _ symbol to turn your method into a function (eta expansion), or you can just use the lambda notation to manually make your foo an function.
def foo1 = "bar"
val list: List[() => String] = List(foo1) // crashes since foo1 is not a fn its
// just a string
val list: List[() => String] = List(() => foo1) // works
val foo1Eta = foo1 _
val list: List[() => String] = List(foo1Eta) // works
val foo2 = () => "bar"
val list: List[() => String] = List(foo2) // works
def foo3 = () => "bar"
val list: List[() => String] = List(foo3) // also works
To pass a parameterless def as a function parameter, you need to turn it into a function. You do this with this syntax:
val list: List[() => String] = List(foo1 _)

Specialization of Scala methods to a specific tags

I have a generic map with values, some of which can be in turn lists of values.
I'm trying to process a given key and convert the results to the type expected by an outside caller, like this:
// A map with some values being other collections.
val map: Map[String, Any] = Map("foo" -> 1, "bar" -> Seq('a', 'b'. 'a'))
// A generic method with a "specialization" for collections (pseudocode)
def cast[T](key: String) = map.get(key).map(_.asInstanceOf[T])
def cast[C <: Iterable[T]](key: String) = map.get(key).map(list => list.to[C].map(_.asIntanceOf[T]))
// Expected usage
cast[Int]("foo") // Should return 1:Int
cast[Set[Char]]("bar") // Should return Set[Char]('a', 'b')
This is to show what I would like to do, but it does not work. The compiler error complains (correctly, about 2 possible matches). I've also tried to make this a single function with some sort of pattern match on the type to no avail.
I've been reading on #specialized, TypeTag, CanBuildFrom and other scala functionality, but I failed to find a simple way to put it all together. Separate examples I've found address different pieces and some ugly workarounds, but nothing that would simply allow an external user to call cast and get an exception is the cast was invalid. Some stuff is also old, I'm using Scala 2.10.5.
This appears to work but it has a some problems.
def cast[T](m: Map[String, Any], k: String):T = m(k) match {
case x: T => x
}
With the right input you get the correct output.
scala> cast[Int](map,"foo")
res18: Int = 1
scala> cast[Set[Char]](map,"bar")
res19: Set[Char] = Set(a, b)
But it throws if the type is wrong for the key or if the map has no such key (of course).
You can do this via implicit parameters:
val map: Map[String, Any] = Map("foo" -> 1, "bar" -> Set('a', 'b'))
abstract class Casts[B] {def cast(a: Any): B}
implicit val doubleCast = new Casts[Double] {
override def cast(a: Any): Double = a match {
case x: Int => x.toDouble
}
}
implicit val intCast = new Casts[Int] {
override def cast(a: Any): Int = a match {
case x: Int => x
case x: Double => x.toInt
}
}
implicit val seqCharCast = new Casts[Seq[Char]] {
override def cast(a: Any): Seq[Char] = a match {
case x: Set[Char] => x.toSeq
case x: Seq[Char] => x
}
}
def cast[T](key: String)(implicit p:Casts[T]) = p.cast(map(key))
println(cast[Double]("foo")) // <- 1.0
println(cast[Int]("foo")) // <- 1
println(cast[Seq[Char]]("bar")) // <- ArrayBuffer(a, b) which is Seq(a, b)
But you still need to iterate over all type-to-type options, which is reasonable as Set('a', 'b').asInstanceOf[Seq[Char]] throws, and you cannot use a universal cast, so you need to handle such cases differently.
Still it sounds like an overkill, and you may need to review your approach from global perspective

Can you partially bind a 0-ary function in Scala?

I was trying to create a function pointer like:
def foo(a: String): Unit = { println(s"a = $a") }
val parameter = "some parameter"
// Here I'd want something like foo(parameter) _, but that doesn't work.
val partialFooWithParameter: () => Unit = ???
Is there something I could replace the ??? with that would work, or is this just not possible in Scala?
Update: Seems like the answer is No.
Best solutions is a function literal:
def partialFooWithParameter: () => Unit = () => foo(parameter)
Although it's still not a partially-applied function:
def bar(a: String, b: String): String = a + b
// Partially-applied.
val partial: (String => String) = bar("a", _)
// Function literal.
val literal: (String => String) = b => bar("a", b)
I think this is what you are looking for. Some of your types are incorrect.
def foo(a: String): Unit = { println(s"a = $a") }
val parameter = "some parameter"
// Here I'd want something like foo(parameter) _, but that doesn't work.
def partialFooWithParameter: () => Unit = () => foo(parameter)

What type parameters should I use to make List.map work with delimited continuations?

I'm basically following the example given at the Scala API page for delimited continuations. The code below works fine:
import scala.util.continuations._
import scala.collection.mutable.HashMap
val sessions = new HashMap[Int, Int=>Unit]
def ask(prompt: String): Int #cps[Unit] = shift {
ret: (Int => Unit) => {
val id = sessions.size
printf("%s\nrespond with: submit(0x%x, ...)\n", prompt, id)
sessions += id -> ret
}
}
def submit(id: Int, addend: Int): Unit = {
sessions.get(id) match {
case Some(continueWith) => continueWith(addend)
}
}
def go = reset {
println("Welcome!")
val first = ask("Please give me a number")
val second = ask("Please enter another number")
printf("The sum of your numbers is: %d\n", first + second)
}
However, when I modify go to the following:
def go = reset {
println("Welcome!")
List("First?","Second?").map[Int #cps[Unit]](ask)
}
I get this error:
error: wrong number of type parameters for method map: [B, That](f: String => B)
(implicit bf: scala.collection.generic.CanBuildFrom[List[String],B,That])That
List("First?","Second?").map[Int #cps[Unit]](ask)
^
Adding Any as a second type parameter doesn't help. Any idea what types I should be supplying?
The reason is that this is simply not possible without creating a CPS-transformed map method on List: the CPS annotations make the compiler turn your methods “inside out” in order to pass the continuation back to where it is needed and the standard List.map does not obey the transformed contract. If you want to have your mind wrapped in Klein bottles for a while you may look at the class files produced from your source, in particular the method signatures.
This is the primary reason why the CPS plugin will never be a complete generic solution to this problem, which is not due to a deficiency but caused by an inherent mismatch between “straight” code and continuation passing style.
You need to give correct parameter for the CanBuildFrom implicit to be found:
List("First?","Second?").map[Int #cps[Unit], List[Int #cps[Unit]](ask)
But do you really need to be explicit about type? maybe just do .map(ask) will work.
Here's the closest thing I could work out. It uses shiftR to reify the continuation rather than reset it, uses a foldRight to construct the suspended continuation chain, uses a shift/reset block to get the continuation after the suspension, and an "animate" method to kick off the suspended continuation.
import scala.collection.mutable.HashMap
import scala.util.continuations._
val sessions = new HashMap[Int, (Unit=>Unit, Int)]
val map = new HashMap[Int, Int]
def ask(pair:(String, Int)) = pair match {
case (prompt, index) => shiftR { (ret: Unit => Unit) => {
val id = sessions.size
printf("%s\nrespond with: submit(0x%x, ...)\n", prompt, id)
sessions += id -> (ret, index)
()
}}
}
def submit(id: Int, addend: Int): Unit = {
sessions.get(id) match {
case Some((continue, index)) => { map.put(index, addend); continue() }
}
}
def sum(m:HashMap[Int,Int]) : Int = {
m.fold[(Int, Int)]((0, 0))((a, b) => (0, {a._2+b._2}))._2
}
type Suspended = ControlContext[Unit,Unit,Unit]
class AnimateList(l:List[Suspended]) {
def suspend(k: => Unit) = (c: Unit) => k
def animate(k:Unit => Unit): Unit = {
l.foldRight(k)(
(elem: Suspended, acc: Unit => Unit) => suspend(elem.fun(acc, ex => ())))()
}
}
implicit def listToAnimateList(l:List[Suspended]) = new AnimateList(l)
reset {
val conts = List("First?","Second?","Third?").zipWithIndex.map(ask)
shift { conts.animate }
println(sum(map))
}

Scala variable argument list with call-by-name possible?

I've got some code like this:
def foo (s: => Any) = println(s)
But when I want to transform this to an argument list with variable length, it won't compile anymore (tested on Scala 2.10.0-RC2):
def foo (s: => Any*) = println(s)
What must I write, that it works like this?
You have to use zero-argument functions instead. If you want, you can
implicit def byname_to_noarg[A](a: => A) = () => a
and then
def foo(s: (() => Any)*) = s.foreach(a => println(a()))
scala> foo("fish", Some(7), {println("This still happens first"); true })
This still happens first
fish
Some(7)
true
There is an issue:
https://issues.scala-lang.org/browse/SI-5787
For the accepted answer, to recover the desired behavior:
object Test {
import scala.language.implicitConversions
implicit def byname_to_noarg[A](a: => A) = () => a
implicit class CBN[A](block: => A) {
def cbn: A = block
}
//def foo(s: (() => Any)*) = s.foreach(a => println(a()))
def foo(s: (() => Any)*) = println(s(1)())
def goo(a: =>Any, b: =>Any, c: =>Any) = println(b)
def main(args: Array[String]) {
foo("fish", Some(7), {println("This still happens first"); true })
goo("fish", Some(7), {println("This used to happens first"); true })
foo("fish", Some(7), {println("This used to happens first"); true }.cbn)
}
}
Excuse the lolcats grammar.