I'd like to be able to pass in callback functions as parameters to a method. Right now, I can pass in a function of signature () => Unit, as in
def doSomething(fn:() => Unit) {
//... do something
fn()
}
which is fine, I suppose, but I'd like to be able to pass in any function with any parameters and any return type.
Is there a syntax to do that?
Thanks
To be able to execute a function passed as a callback you have to be able to call it with the arguments it requires. f: A => R must be called as f(someA), and g: (A,B) => R must be called as f(someA, someB).
Implementing a callback you want a function that accepts a context and returns something (you don't care what the something is). For example foreach in scala.Option is defined as:
def foreach[U](f: (A) => U): Unit
The function is called with a value of type A but the result is discarded so we don't care what type it has. Alternatively if you don't care what was completed the callback function could be implemented as:
def onComplete[U](f: () => U): Unit
It would then allow being called with any function that takes no arguments:
val f: () => Int = ...
val g: () => String = ...
onComplete(f) // In result is discarded
onComplete(g) // String result is discarded
If you really wanted a function that accepted any possible function there are some tricks you could use (but you really shouldn't). For example you could define a view bound with implicit conversions:
// Type F is any type that can be converted to () => U
def onComplete[F <% () => U, U](f: F): Unit
// Define conversions for each Function type to Function0
implicit def f1tof0[A,U](f: A => U): () => U = ...
implicit def f2tof0[A,B,U](f: (A,B) => U): () => U = ...
implicit def f3tof0[A,B,C,U](f: (A,B,C) => U): () => U = ...
.
.
etc.
Now onComplete accepts any function:
val f: Int => String = ...
val g: (List[Int], String) => String = ...
onComplete(f)
onComplete(g)
Defining the types for the above conversions is relatively simple, but there is no rational way to implement them so is pretty much entirely useless.
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.
Suppose I have a function definition like
def twice(f: Int => Unit): Unit = {
f(1)
f(1)
}
def oneParam(i: Int) = println(1)
twice(oneParam)
I can pass around oneParam by name, but if I do the same with a no parameter function:
def twice(f: Unit => Unit): Unit = {
f()
f()
}
def noParams() = println(2)
twice(noParams)
I get a compiler error because even though I declared noParams with an empty paramter list the compiler thinks I'm trying to call the function with no parameter list. How can I pass around this function then?
Your function is declared wrong. Unit => Unit is not a function, that takes no params, it's a function that takes one parameter of type Unit.
Try declaring it like this instead: def twice(f: () => Unit)
this should work:
scala> def twice(f: () => Unit): Unit = {
| f()
| f()
| }
twice: (f: () => Unit)Unit
scala> def noParams() = println(2)
noParams: ()Unit
scala> twice(noParams)
2
2
I am trying to write a partially applied function. I thought the below would work but it doesn't. Grateful for any help.
scala> def doSth(f: => Unit) { f }
doSth: (f: => Unit)Unit
scala> def sth() = { println ("Hi there") }
sth: ()Unit
scala> doSth(sth)
Hi there
scala> val b = sth _
b: () => Unit = <function0>
scala> doSth(b)
<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
doSth(b)
^
Thanks!
The difference is subtle. sth is a method, so you can call it without the parentheses, which is what is happening here:
doSth(sth)
But b is just a function () => Unit, which you must use the parentheses to invoke.
doSth(b())
Otherwise you would not be able to assign b to another identifier.
val c: () => Unit = b
If we automatically invoked b here, c would be Unit instead of () => Unit. The ambiguity must be removed.
Let me also clarify that doSth is not a method that accepts only functions. f: => Unit means it accepts anything that evaluates to Unit, which includes methods that return Unit when they are invoked. doSth(sth) is not passing the message sth to doSth, it's invoking sth without parentheses and passing the result.
I think the difference is that b has type () => Unit, and doSth expects an expression that returns Unit (minor difference). If you want to store sth as a variable without the side effects, you could do:
lazy val b = sth
doSth(b)
The other option would be to make it so that doSth takes in () => Unit:
def doSth(f: () => Unit) { f() }
def sth() = { println ("Hi there") }
doSth(sth)
val b = sth _
doSth(b)
I'm starting to learn Scala and I've come across a snippet from the Programming in Scala textbook which I don't quite understand. Was hoping some one could help me?
This is from Listing 9.1 from Programming in Scala, 2nd Edition.
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
}
private def filesMatching(matcher: String => Boolean) =
for (file <- filesHere; if matcher(file.getName)) yield file
def filesEnding(query: String) =
filesMatching(_.endsWith(query)) // ???
def filesContaining(query: String) =
filesMatching(_.contains(query)) // ???
def filesRegex(query: String) =
filesMatching(_.matches(query)) // ???
I'm a little confused with the lines that have // ???. Does the use of the _ somehow create an anonymous function that is passed to filesMatching? Or does the _ have nothing to do with this, and instead the compiler sees that filesMatching requires a function and therefore doesn't execute _.endsWith(query) as an expression but instead makes the expression a function?
extended definition
Anonymous function are defined, in their more verbose and complete form, as
(a: A, b: B, ...) => function body //using a, b, ...
E.g.
(a: String, b: String) => a ++ b // concatenates 2 Strings
inferred types
if the context provides the needed information (as when a higher order function expects a specific signature for its function arguments), you can omit the parameters' types, as
(a, b, ...) => function body //using a, b, ...
E.g.
val l = List(1, 2, 3)
//you can omit the type because filter on List[Int] expects a (Int => Boolean)
l.filter(i => i < 3)
placeholder syntax
Finally you can use a shorter form still, if your parameters are used once each and in the same order that you declare them, by the function body, as
_ ++ _ // which is equivalent to (a, b) => a ++ b
Each _ is a placeholder for the function's arguments
E.g.
filesMatching's argument is a function of type String => Boolean so you can use
_.endsWith(query) // equivalent to (s: String) => s.endsWith(query)
_.contains(query) // equivalent to (s: String) => s.contains(query)
_.matches(query) // equivalent to (s: String) => s.matches(query)
The _ as used here is shorthand for a function argument. Thus filesMatching(_.endsWith(query)) is equivalent to filesMatching(f => f.endsWith(query)). As filesMatching has as argument a function of String => Boolean, the compiler can infer that f is expected to be a String here. So you are right that this expression is an anonymous function.
This kind of operation is best done by defining function types. I found an excellent demonstration here. Combined with this post, the demonstration should clarify best practices for passing functions as arguments
This is a followup to this question.
Here's the code I'm trying to understand (it's from http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/):
object io {
sealed trait IO[A] {
def unsafePerformIO: A
}
object IO {
def apply[A](a: => A): IO[A] = new IO[A] {
def unsafePerformIO = a
}
}
implicit val IOMonad = new Monad[IO] {
def pure[A](a: => A): IO[A] = IO(a)
def bind[A,B](a: IO[A], f: A => IO[B]): IO[B] = IO {
implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) => () => f(x).unsafePerformIO)()
}
}
}
This code is used like this (I'm assuming an import io._ is implied)
def bufferFile(f: File) = IO { new BufferedReader(new FileReader(f)) }
def closeReader(r: Reader) = IO { r.close }
def bracket[A,B,C](init: IO[A], fin: A => IO[B], body: A => IO[C]): IO[C] = for { a <- init
c <- body(a)
_ <- fin(a) } yield c
def enumFile[A](f: File, i: IterV[String, A]): IO[IterV[String, A]] = bracket(bufferFile(f),
closeReader(_:BufferedReader),
enumReader(_:BufferedReader, i))
I'm now trying to understand the implicit val IOMonad definition. Here's how I understand it. This is a scalaz.Monad, so it needs to define pure and bind abstract values of the scalaz.Monad trait.
pure takes a value and turns it into a value contained in the "container" type. For example it could take an Int and return a List[Int]. This seems pretty simple.
bind takes a "container" type and a function that maps the type that the container holds to another type. The value that is returned is the same container type, but it's now holding a new type. An example would be taking a List[Int] and mapping it to a List[String] using a function that maps Ints to Strings. Is bind pretty much the same as map?
The implementation of bind is where I'm stuck. Here's the code:
def bind[A,B](a: IO[A], f: A => IO[B]): IO[B] = IO {
implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) => () => f(x).unsafePerformIO)()
}
This definition takes IO[A] and maps it to IO[B] using a function that takes an A and returns an IO[B]. I guess to do this, it has to use flatMap to "flatten" the result (correct?).
The = IO { ... } is the same as
= new IO[A] {
def unsafePerformIO = implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) => () => f(x).unsafePerformIO)()
}
}
I think?
the implicitly method looks for an implicit value (value, right?) that implements Monad[Function0]. Where does this implicit definition come from? I'm guessing this is from the implicit val IOMonad = new Monad[IO] {...} definition, but we're inside that definition right now and things get a little circular and my brain starts to get stuck in an infinite loop :)
Also, the first argument to bind (() => a.unsafePerformIO) seems to be a function that takes no parameters and returns a.unsafePerformIO. How should I read this? bind takes a container type as its first argument, so maybe () => a.unsafePerformIO resolves to a container type?
IO[A] is intended to represent an Action returning an A, where the result of the Action may depend on the environment (meaning anything, values of variables, file system, system time...) and the execution of the action may also modify the environment. Actually, scala type for an Action would be Function0. Function0[A] returns an A when called and it is certainly allowed to depend on and modify the environment. IO is Function0 under another name, but it is intended to distinguish (tag?) those Function0 which depends on the environment from the other ones, which are actually pure value (if you say f is a function[A] which always returns the same value, without any side effect, there is no much difference between f and its result). To be precise, it is not so much that function tagged as IO must have side effect. It is that those not so tagged must have none. Note however than wrapping impure functions in IO is entirely voluntary, there is no way you will have a guarantee when you get a Function0 that it is pure. Using IO is certainly not the dominant style in scala.
pure takes a value and turns it into a value contained in the
"container" type.
Quite right, but "container" may mean quite a lot of things. And the one returned by pure must be as light as possible, it must be the one that makes no difference. The point of list is that they may have any number of values. The one returned by pure must have one. The point of IO is that it depends on and affect the environment. The one returned by pure must do no such thing. So it is actually the pure Function0 () => a, wrapped in IO.
bind pretty much the same as map
Not so, bind is the same as flatMap. As you write, map would receive a function from Int to String, but here you have the function from Int to List[String]
Now, forget IO for a moment and consider what bind/flatMap would mean for an Action, that is for Function0.
Let's have
val askUserForLineNumber: () => Int = {...}
val readingLineAt: Int => Function0[String] = {i: Int => () => ...}
Now if we must combine, as bind/flatMap does, those items to get an action that returns a String, what it must be is pretty clear: ask the reader for the line number, read that line and returns it. That would be
val askForLineNumberAndReadIt= () => {
val lineNumber : Int = askUserForLineNumber()
val readingRequiredLine: Function0[String] = readingLineAt(line)
val lineContent= readingRequiredLine()
lineContent
}
More generically
def bind[A,B](a: Function0[A], f: A => Function0[B]) = () => {
val value = a()
val nextAction = f(value)
val result = nextAction()
result
}
And shorter:
def bind[A,B](a: Function0[A], f: A => Function0[B])
= () => {f(a())()}
So we know what bind must be for Function0, pure is clear too. We can do
object ActionMonad extends Monad[Function0] {
def pure[A](a: => A) = () => a
def bind[A,B](a: () => A, f: A => Function0[B]) = () => f(a())()
}
Now, IO is Function0 in disguise. Instead of just doing a(), we must do a.unsafePerformIO. And to define one, instead of () => body, we write IO {body}
So there could be
object IOMonad extends Monad[IO] {
def pure[A](a: => A) = IO {a}
def bind[A,B](a: IO[A], f: A => IO[B]) = IO {f(a.unsafePerformIO).unsafePerformIO}
}
In my view, that would be good enough. But in fact it repeats the ActionMonad. The point in the code you refer to is to avoid that and reuse what is done for Function0 instead. One goes easily from IO to Function0 (with () => io.unsafePerformIo) as well as from Function0 to IO (with IO { action() }). If you have f: A => IO[B], you can also change that to f: A => Function0[B], just by composing with the IO to Function0 transform, so (x: A) => f(x).unsafePerformIO.
What happens here in the bind of IO is:
() => a.unsafePerformIO: turn a into a Function0
(x:A) => () => f(x).unsafePerformIO): turn f into an A => Function0[B]
implicitly[Monad[Function0]]: get the default monad for Function0, the very same as the ActionMonad above
bind(...): apply the bind of the Function0 monad to the arguments a and f that have just been converted to Function0
The enclosing IO{...}: convert the result back to IO.
(Not sure I like it much)