As a follow on to: scala loan pattern, optional function param
What would the proper syntax be to move the withLoaner param to overloaded apply methods? I've tried several versions of the following unsuccessfully. Also, any insights into my error conceptually very appreciated.
def withLoaner = new {
def apply(n:Int, op: Int => String):String = (1 to n).map(op).mkString("\n")
def apply(n:Int, op: () => String):String = apply{n, i:Int => op()} // no compile
def apply(op: () => String):String = apply{1, i:Int => op()} // no compile
}
When passing multiple parameters, you must use parenthesis around them. Using {} only works for single parameters.
Also, when using function literals, if you specify type, you have to put all of the functions parameters inside parenthesis.
So,
def withLoaner = new {
def apply(n:Int, op: Int => String):String = (1 to n).map(op).mkString("\n")
def apply(n:Int, op: () => String):String = apply(n, i => op()) // no type on i
def apply(op: () => String):String = apply(1, (i: Int) => op()) // parenthesis around parameters
}
2 little changes:
Use ( instead of { when calling apply:
apply(.......)
Use ( around the arg to an implicit function:
apply(1, (i:Int) => op())
Related
What I want to achieve is the 2 functions (one of them is no arg function) are composed into one.
Here is an example to give you idea what I am doing:
object Test extends App {
val zeroArgFunc = () => 10
val intArgFunc = (i: Int) => s"hello $i"
val stringArgFunc = (s: String) => println(s)
// This line works perfectly fine.
val intAndThenString: Int => Unit = stringArgFunc compose intArgFunc
// But this line fails with 'type mismatch' compilation error.
val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
}
Compilation error:
[error] found : () => Int
[error] required: ? => Int
[error] val zeroAndThenInt: () => String = intArgFunc compose zeroArgFunc
[error] ^
[error] one error found
Any idea what's wrong?
[UPD] The Scala version is 2.13.1 (if it matters).
Desugaring () => 10 we have
new Function0[Int] { def apply() = 10 }
and Function0 does not have compose or andThen methods
trait Function0[... +R] extends ... { ...
def apply(): R
override def toString(): String = "<function0>"
}
so it seems Function0 cannot be composed.
On the other hand (i: Int) => s"hello $i" and (s: String) => println(s) correspond to Function1 which does have compose method defined, hence they can be composed.
Consider changing () => 10 to (_: Unit) => 10 which changes the type from Function0 to Function1, and then
(intArgFunc compose zeroArgFunc)()
outputs res4: String = hello 10.
Addressing comment by #Duelist, IMHO Function0[T] is not semantically equivalent to Function1[Unit, T]. For example, given
val f = () => 10
val g = (_: Unit) => 10
then
f()
g()
indeed outputs
res7: Int = 10
res8: Int = 10
however
f(println("woohoo")) // error: no arguments allowed for nullary method apply
g(println("woohoo")) // OK!
where we see the two do not have the same behaviour. Nevertheless, if you would like to consider them as equivalent perhaps you could define an extension method on Function0 and be explicit about conversion, for example
implicit class Fun0ToFun1[A, B](f: () => A) {
def toFun1: Unit => A = (_: Unit) => f()
}
would allow the following syntax
(intArgFunc compose zeroArgFunc.toFun1)()
Addressing comment by #egordoe, out-of-the-box compose is only ever defined for Function1, thus Function2, Function3, etc., cannot be composed just like Function0. However we could define extension composeN methods on function, for example, say we want to compose Function1 with Function0, then
implicit class ComposeFun1WithFun0[A, B](f1: A => B) {
def compose0(f2: () => A): () => B = () => f1(f2())
}
gives
(intArgFunc compose0 zeroArgFunc)()
compose on Function1 (which intArgFunc is) is just defined to only accept single-argument functions:
def compose[A](g: (A) => T1): (A) => R
You could write helper functions to convert () => A to/from Unit => A
def toUnitFun[A](f: () => A): Unit => A = _ => f()
def fromUnitFun[A](f: Unit => A): () => A = () => f(())
and then
val zeroAndThenInt = fromUnitFun(intArgFunc compose toUnitFun(zeroArgFunc))
You can even make your original code work by marking to/fromUnitFun as implicit.
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 _)
I there, I'm trying to combine the Command and Chain of responsibility patterns with Scala style.
Basically, I would like to have one Executor who pass the command trough the chain and return the result. A command is anything that return a T :
class class Invoker {
type Command[T] = () => T
val handlers = new mutable.ListBuffer[PartialFunction[() => T, T]]
def invoke[T](command: => T): Future[T] = Future {
handlers.find(_.isDefinedAt(command)).map(_.apply(command))
}
}
But, because I'm a scala beginner, I have problems with the generic types for the list of handlers. I cannot figure how to define T in the declaration of handlers so that the invoke command return the correct type (wich should be T)
Can someone help me to implement this pattern ?
There are several sketchy places, but I think the closest you'll get to what you want would be (Though, it will not work, see below):
import scala.collection.mutable
import scala.concurrent.Future
object Invoker {
val handlers = new mutable.ListBuffer[PartialFunction[Any, Any]]
def invoke[T](command: () => T): Future[T] = Future {
handlers.collectFirst {
case pf if pf.isDefinedAt(command) => pf(command)
}.fold(throw new Exception("failure")) {
_.asInstanceOf[T]
}
}
}
However,
It will not work because, the partial functions or more specifically pattern matching will most certainly not work as you expect for Function0
You loose most of your type information through erasure and have to rely upon what you know about the partial functions.
In scala, the need to call asInstanceOf is a good indicator that something can be done better.
#1
When you define a list of partial functions that match on Function0 like for example this:
val T1: () => Int = () => 1
val T2: () => Int = () => 2
val T3: () => Int = () => 3
val pfs: Seq[PartialFunction[Any, Any]] = Seq(
PartialFunction[Any, Any] {
case T1 => T1()
},
PartialFunction[Any, Any] {
case T2 => T2()
},
PartialFunction[Any, Any] {
case T3 => T3()
}
)
Trying to find a match for any function literal will lead to a MatchError:
def invoke[T](c: () => T): T = {
pfs.collectFirst {
case pf if pf.isDefinedAt(c) => pf(c)
}.fold(throw new Exception("failure")) {
_.asInstanceOf[T]
}
}
invoke(() => 1) |-> scala.MatchError: <function0> (of class abc.A$A290$A$A290$$anonfun$ti1$1)
This would only work if you define Constants for allowed functions and only use those constants, when you call invoke.
You could define them with the Invoker object:
object Invoker {
val SomeCommand = () => 5 + 5
val AnotherCommand = () => 5 * 5
}
But that would utterly eliminate any flexibility.
FINALLY:
If you want to be able to perform any Command then why maintain a list of handlers anyway?
object Invoker {
def invoke[T](command: () => T): Future[T] = Future {
command()
}
}
should be sufficient for that.
I am trying to set a default value to an anonymous function in scala and so for not able to find any solution. Hope some one would help me out in SO.
I have the following structure,
case class A(id:Int = 0)
case class B(a:A)
object B {
def func1(f:Int = 0)={
........
}
def func2(f:A => B = (how to give default value ?))={
case Nothing => {
//do something....
}
case _ => {
//do some other thing......
}
}
}
Basically, I want to make passing the parameter as optional. How can I achieve this?
Like any other default parameter:
scala> def test(f: Int => Int = _ + 1) = f
test: (f: Int => Int)Int => Int
scala> test()(1)
res3: Int = 2
or with String:
scala> def test(f: String => String = identity) = f
test: (f: String => String)String => String
scala> test()
res1: String => String = <function1>
scala> test()("Hello")
res2: String = Hello
Edit:
In case if you want to use a function provided by default, you have to use () explicitly, either Scala won't paste a default argument.
If you don't wanna use a default function and provide an explicit one, just provide it yourself:
scala> test(_.toUpperCase)("Hello")
res2: String = HELLO
Use an implicit parameter. Place an implicit value for the parameter in the object. This will be used unless you provide an explicit parameter or you have provided another implicit value in the calling scope.
case class A(id:Int = 0)
case class B(a:A)
object B {
implicit val defFunc: A => B = {a: A => new B(a) }
def func1(f:Int = 0)={
}
def func2(implicit func: A => B) = { ... }
}
The differences between this method and Alexlv's method are
This works with standalone functions as well as methods.
The scope rules allow for providing appropriate overrides in appropriate scopes. Alex's method would require subclassing or eta-expansion (with partial application) to change the default.
I offer this solution since you are already using an object. Otherwise, Alexvlv's example is simpler.
The other answers show how to provide some existing default value, but if you want the default to do nothing (as suggested by case Nothing) then you can use Option/None.
def func2(f:Option[A => B] = None)={
case Some(f) =>
//do something....
case None =>
//do some other thing......
}
func2()
func2( Some(_ + 1) )
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.