I'm trying to represent a function that takes no arguments and returns no value (I'm simulating the setTimeout function in JavaScript, if you must know.)
case class Scheduled(time : Int, callback : => Unit)
doesn't compile, saying " `val' parameters may not be call-by-name"
case class Scheduled(time : Int, callback : () => Unit)
compiles, but has to be invoked strangely, instead of
Scheduled(40, { println("x") } )
I have to do this
Scheduled(40, { () => println("x") } )
What also works is
class Scheduled(time : Int, callback : Unit => Unit)
but is invoked in an even-less-sensible way
Scheduled(40, { x : Unit => println("x") } )
(What would a variable of type Unit be?) What I want of course is a constructor that can be invoke the way I would invoke it if it were an ordinary function:
Scheduled(40, println("x") )
Give baby his bottle!
Call-by-Name: => Type
The => Type notation stands for call-by-name, which is one of the many ways parameters can be passed. If you aren't familiar with them, I recommend taking some time to read that wikipedia article, even though nowadays it is mostly call-by-value and call-by-reference.
What it means is that what is passed is substituted for the value name inside the function. For example, take this function:
def f(x: => Int) = x * x
If I call it like this
var y = 0
f { y += 1; y }
Then the code will execute like this
{ y += 1; y } * { y += 1; y }
Though that raises the point of what happens if there's a identifier name clash. In traditional call-by-name, a mechanism called capture-avoiding substitution takes place to avoid name clashes. In Scala, however, this is implemented in another way with the same result -- identifier names inside the parameter can't refer to or shadow identifiers in the called function.
There are some other points related to call-by-name that I'll speak of after explaining the other two.
0-arity Functions: () => Type
The syntax () => Type stands for the type of a Function0. That is, a function which takes no parameters and returns something. This is equivalent to, say, calling the method size() -- it takes no parameters and returns a number.
It is interesting, however, that this syntax is very similar to the syntax for a anonymous function literal, which is the cause for some confusion. For example,
() => println("I'm an anonymous function")
is an anonymous function literal of arity 0, whose type is
() => Unit
So we could write:
val f: () => Unit = () => println("I'm an anonymous function")
It is important not to confuse the type with the value, however.
Unit => Type
This is actually just a Function1, whose first parameter is of type Unit. Other ways to write it would be (Unit) => Type or Function1[Unit, Type]. The thing is... this is unlikely to ever be what one wants. The Unit type's main purpose is indicating a value one is not interested in, so doesn't make sense to receive that value.
Consider, for instance,
def f(x: Unit) = ...
What could one possibly do with x? It can only have a single value, so one need not receive it. One possible use would be chaining functions returning Unit:
val f = (x: Unit) => println("I'm f")
val g = (x: Unit) => println("I'm g")
val h = f andThen g
Because andThen is only defined on Function1, and the functions we are chaining are returning Unit, we had to define them as being of type Function1[Unit, Unit] to be able to chain them.
Sources of Confusion
The first source of confusion is thinking the similarity between type and literal that exists for 0-arity functions also exists for call-by-name. In other words, thinking that, because
() => { println("Hi!") }
is a literal for () => Unit, then
{ println("Hi!") }
would be a literal for => Unit. It is not. That is a block of code, not a literal.
Another source of confusion is that Unit type's value is written (), which looks like a 0-arity parameter list (but it is not).
case class Scheduled(time : Int, callback : => Unit)
The case modifier makes implicit val out of each argument to the constructor. Hence (as someone noted) if you remove case you can use a call-by-name parameter. The compiler could probably allow it anyway, but it might surprise people if it created val callback instead of morphing into lazy val callback.
When you change to callback: () => Unit now your case just takes a function rather than a call-by-name parameter. Obviously the function can be stored in val callback so there's no problem.
The easiest way to get what you want (Scheduled(40, println("x") ) where a call-by-name parameter is used to pass a lambda) is probably to skip the case and explicitly create the apply that you couldn't get in the first place:
class Scheduled(val time: Int, val callback: () => Unit) {
def doit = callback()
}
object Scheduled {
def apply(time: Int, callback: => Unit) =
new Scheduled(time, { () => callback })
}
In use:
scala> Scheduled(1234, println("x"))
res0: Scheduled = Scheduled#5eb10190
scala> Scheduled(1234, println("x")).doit
x
In the question, you want to simulate SetTimeOut function in JavaScript. Based on previous answers, I write following code:
class Scheduled(time: Int, cb: => Unit) {
private def runCb = cb
}
object Scheduled {
def apply(time: Int, cb: => Unit) = {
val instance = new Scheduled(time, cb)
Thread.sleep(time*1000)
instance.runCb
}
}
In REPL, we can get something like this:
scala> Scheduled(10, println("a")); Scheduled(1, println("b"))
a
b
Our simulation doesn't behave exactly the same as SetTimeOut, because our simulation is blocking function, but SetTimeOut is non-blocking.
I do it this way (just don't want to break apply):
case class Thing[A](..., lazy: () => A) {}
object Thing {
def of[A](..., a: => A): Thing[A] = Thing(..., () => a)
}
and call it
Thing.of(..., your_value)
Related
I'm trying to represent a function that takes no arguments and returns no value (I'm simulating the setTimeout function in JavaScript, if you must know.)
case class Scheduled(time : Int, callback : => Unit)
doesn't compile, saying " `val' parameters may not be call-by-name"
case class Scheduled(time : Int, callback : () => Unit)
compiles, but has to be invoked strangely, instead of
Scheduled(40, { println("x") } )
I have to do this
Scheduled(40, { () => println("x") } )
What also works is
class Scheduled(time : Int, callback : Unit => Unit)
but is invoked in an even-less-sensible way
Scheduled(40, { x : Unit => println("x") } )
(What would a variable of type Unit be?) What I want of course is a constructor that can be invoke the way I would invoke it if it were an ordinary function:
Scheduled(40, println("x") )
Give baby his bottle!
Call-by-Name: => Type
The => Type notation stands for call-by-name, which is one of the many ways parameters can be passed. If you aren't familiar with them, I recommend taking some time to read that wikipedia article, even though nowadays it is mostly call-by-value and call-by-reference.
What it means is that what is passed is substituted for the value name inside the function. For example, take this function:
def f(x: => Int) = x * x
If I call it like this
var y = 0
f { y += 1; y }
Then the code will execute like this
{ y += 1; y } * { y += 1; y }
Though that raises the point of what happens if there's a identifier name clash. In traditional call-by-name, a mechanism called capture-avoiding substitution takes place to avoid name clashes. In Scala, however, this is implemented in another way with the same result -- identifier names inside the parameter can't refer to or shadow identifiers in the called function.
There are some other points related to call-by-name that I'll speak of after explaining the other two.
0-arity Functions: () => Type
The syntax () => Type stands for the type of a Function0. That is, a function which takes no parameters and returns something. This is equivalent to, say, calling the method size() -- it takes no parameters and returns a number.
It is interesting, however, that this syntax is very similar to the syntax for a anonymous function literal, which is the cause for some confusion. For example,
() => println("I'm an anonymous function")
is an anonymous function literal of arity 0, whose type is
() => Unit
So we could write:
val f: () => Unit = () => println("I'm an anonymous function")
It is important not to confuse the type with the value, however.
Unit => Type
This is actually just a Function1, whose first parameter is of type Unit. Other ways to write it would be (Unit) => Type or Function1[Unit, Type]. The thing is... this is unlikely to ever be what one wants. The Unit type's main purpose is indicating a value one is not interested in, so doesn't make sense to receive that value.
Consider, for instance,
def f(x: Unit) = ...
What could one possibly do with x? It can only have a single value, so one need not receive it. One possible use would be chaining functions returning Unit:
val f = (x: Unit) => println("I'm f")
val g = (x: Unit) => println("I'm g")
val h = f andThen g
Because andThen is only defined on Function1, and the functions we are chaining are returning Unit, we had to define them as being of type Function1[Unit, Unit] to be able to chain them.
Sources of Confusion
The first source of confusion is thinking the similarity between type and literal that exists for 0-arity functions also exists for call-by-name. In other words, thinking that, because
() => { println("Hi!") }
is a literal for () => Unit, then
{ println("Hi!") }
would be a literal for => Unit. It is not. That is a block of code, not a literal.
Another source of confusion is that Unit type's value is written (), which looks like a 0-arity parameter list (but it is not).
case class Scheduled(time : Int, callback : => Unit)
The case modifier makes implicit val out of each argument to the constructor. Hence (as someone noted) if you remove case you can use a call-by-name parameter. The compiler could probably allow it anyway, but it might surprise people if it created val callback instead of morphing into lazy val callback.
When you change to callback: () => Unit now your case just takes a function rather than a call-by-name parameter. Obviously the function can be stored in val callback so there's no problem.
The easiest way to get what you want (Scheduled(40, println("x") ) where a call-by-name parameter is used to pass a lambda) is probably to skip the case and explicitly create the apply that you couldn't get in the first place:
class Scheduled(val time: Int, val callback: () => Unit) {
def doit = callback()
}
object Scheduled {
def apply(time: Int, callback: => Unit) =
new Scheduled(time, { () => callback })
}
In use:
scala> Scheduled(1234, println("x"))
res0: Scheduled = Scheduled#5eb10190
scala> Scheduled(1234, println("x")).doit
x
In the question, you want to simulate SetTimeOut function in JavaScript. Based on previous answers, I write following code:
class Scheduled(time: Int, cb: => Unit) {
private def runCb = cb
}
object Scheduled {
def apply(time: Int, cb: => Unit) = {
val instance = new Scheduled(time, cb)
Thread.sleep(time*1000)
instance.runCb
}
}
In REPL, we can get something like this:
scala> Scheduled(10, println("a")); Scheduled(1, println("b"))
a
b
Our simulation doesn't behave exactly the same as SetTimeOut, because our simulation is blocking function, but SetTimeOut is non-blocking.
I do it this way (just don't want to break apply):
case class Thing[A](..., lazy: () => A) {}
object Thing {
def of[A](..., a: => A): Thing[A] = Thing(..., () => a)
}
and call it
Thing.of(..., your_value)
I'm trying to represent a function that takes no arguments and returns no value (I'm simulating the setTimeout function in JavaScript, if you must know.)
case class Scheduled(time : Int, callback : => Unit)
doesn't compile, saying " `val' parameters may not be call-by-name"
case class Scheduled(time : Int, callback : () => Unit)
compiles, but has to be invoked strangely, instead of
Scheduled(40, { println("x") } )
I have to do this
Scheduled(40, { () => println("x") } )
What also works is
class Scheduled(time : Int, callback : Unit => Unit)
but is invoked in an even-less-sensible way
Scheduled(40, { x : Unit => println("x") } )
(What would a variable of type Unit be?) What I want of course is a constructor that can be invoke the way I would invoke it if it were an ordinary function:
Scheduled(40, println("x") )
Give baby his bottle!
Call-by-Name: => Type
The => Type notation stands for call-by-name, which is one of the many ways parameters can be passed. If you aren't familiar with them, I recommend taking some time to read that wikipedia article, even though nowadays it is mostly call-by-value and call-by-reference.
What it means is that what is passed is substituted for the value name inside the function. For example, take this function:
def f(x: => Int) = x * x
If I call it like this
var y = 0
f { y += 1; y }
Then the code will execute like this
{ y += 1; y } * { y += 1; y }
Though that raises the point of what happens if there's a identifier name clash. In traditional call-by-name, a mechanism called capture-avoiding substitution takes place to avoid name clashes. In Scala, however, this is implemented in another way with the same result -- identifier names inside the parameter can't refer to or shadow identifiers in the called function.
There are some other points related to call-by-name that I'll speak of after explaining the other two.
0-arity Functions: () => Type
The syntax () => Type stands for the type of a Function0. That is, a function which takes no parameters and returns something. This is equivalent to, say, calling the method size() -- it takes no parameters and returns a number.
It is interesting, however, that this syntax is very similar to the syntax for a anonymous function literal, which is the cause for some confusion. For example,
() => println("I'm an anonymous function")
is an anonymous function literal of arity 0, whose type is
() => Unit
So we could write:
val f: () => Unit = () => println("I'm an anonymous function")
It is important not to confuse the type with the value, however.
Unit => Type
This is actually just a Function1, whose first parameter is of type Unit. Other ways to write it would be (Unit) => Type or Function1[Unit, Type]. The thing is... this is unlikely to ever be what one wants. The Unit type's main purpose is indicating a value one is not interested in, so doesn't make sense to receive that value.
Consider, for instance,
def f(x: Unit) = ...
What could one possibly do with x? It can only have a single value, so one need not receive it. One possible use would be chaining functions returning Unit:
val f = (x: Unit) => println("I'm f")
val g = (x: Unit) => println("I'm g")
val h = f andThen g
Because andThen is only defined on Function1, and the functions we are chaining are returning Unit, we had to define them as being of type Function1[Unit, Unit] to be able to chain them.
Sources of Confusion
The first source of confusion is thinking the similarity between type and literal that exists for 0-arity functions also exists for call-by-name. In other words, thinking that, because
() => { println("Hi!") }
is a literal for () => Unit, then
{ println("Hi!") }
would be a literal for => Unit. It is not. That is a block of code, not a literal.
Another source of confusion is that Unit type's value is written (), which looks like a 0-arity parameter list (but it is not).
case class Scheduled(time : Int, callback : => Unit)
The case modifier makes implicit val out of each argument to the constructor. Hence (as someone noted) if you remove case you can use a call-by-name parameter. The compiler could probably allow it anyway, but it might surprise people if it created val callback instead of morphing into lazy val callback.
When you change to callback: () => Unit now your case just takes a function rather than a call-by-name parameter. Obviously the function can be stored in val callback so there's no problem.
The easiest way to get what you want (Scheduled(40, println("x") ) where a call-by-name parameter is used to pass a lambda) is probably to skip the case and explicitly create the apply that you couldn't get in the first place:
class Scheduled(val time: Int, val callback: () => Unit) {
def doit = callback()
}
object Scheduled {
def apply(time: Int, callback: => Unit) =
new Scheduled(time, { () => callback })
}
In use:
scala> Scheduled(1234, println("x"))
res0: Scheduled = Scheduled#5eb10190
scala> Scheduled(1234, println("x")).doit
x
In the question, you want to simulate SetTimeOut function in JavaScript. Based on previous answers, I write following code:
class Scheduled(time: Int, cb: => Unit) {
private def runCb = cb
}
object Scheduled {
def apply(time: Int, cb: => Unit) = {
val instance = new Scheduled(time, cb)
Thread.sleep(time*1000)
instance.runCb
}
}
In REPL, we can get something like this:
scala> Scheduled(10, println("a")); Scheduled(1, println("b"))
a
b
Our simulation doesn't behave exactly the same as SetTimeOut, because our simulation is blocking function, but SetTimeOut is non-blocking.
I do it this way (just don't want to break apply):
case class Thing[A](..., lazy: () => A) {}
object Thing {
def of[A](..., a: => A): Thing[A] = Thing(..., () => a)
}
and call it
Thing.of(..., your_value)
I was reading about scala anonymous functions here and saw that they can take the format:
{ case p1 => b1 … case pn => bn }
However, I thought that this was how partial functions were written. In fact, in this blog post, the author calls a partial function an anonymous function. At first he says that collect takes a partial function but then appears to call it an anonymous function ("collect can handle the fact that your anonymous function...").
Is it just that some anonymous functions are partial functions? If so, are all partial functions anonymous? Or are they only anonymous if in format like Alvin Alexander's example here:
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}
Anonymous and partial are different concepts. We would not say the following function is anonymous
val divide2: PartialFunction[Int, Int] = {
case d: Int if d != 0 => 42 / d
}
because it is bound to the name divide2, however we could say divide2 is defined in terms of the anonymous (function) value
{ case d: Int if d != 0 => 42 / d }
in the same sense x is defined in terms of anonymous value 42 in the following definition
val x: Int = 42
Orthogonal concept of partial refers to special subtype of function, as opposed to whether values of particular type are bound to a name or not.
From the documentation on pattern matching anonymous functions that you linked:
If the expected type is SAM-convertible to scala.Functionk[S1,…,Sk, R], the expression is taken to be equivalent to the anonymous
function:
(x1:S1,…,xk:Sk) => (x1,…,xk) match {
case p1 => b1 … case pn => bn
}
Here, each xi is a fresh name. As was shown here, this anonymous
function is in turn equivalent to the following instance creation
expression, where T is the weak least upper bound of the types of all
bi.
new scala.Functionk[S1,…,Sk, T] {
def apply(x1:S1,…,xk:Sk): T = (x1,…,xk) match {
case p1 => b1 …
case pn => bn
}
}
If the expected type is scala.PartialFunction[S, R], the expression is taken to be equivalent
to the following instance creation expression:
new scala.PartialFunction[S, T] {
def apply(x: S): T = x match {
case p1 => b1 … case pn => bn
}
def isDefinedAt(x: S): Boolean = {
case p1 => true … case pn => true
case _ => false
}
}
Your first code snippet is a pattern matching anonymous function, but not necessarily a partial function. It would only be turned into a PartialFunction if it was given to a method with a PartialFunction parameter or assigned to a variable of type PartialFunction.
So you are right that just some (pattern matching) anonymous functions are partial functions (AFAIK, function literals defined with fat arrows, such as x => x, can only ever be used to create FunctionN instances and not PartialFunction instances).
However, not all partial functions are anonymous functions. A sugar-free way to define PartialFunctions is extending the PartialFunction trait (which extends Function1) and manually overriding the isDefinedAt and apply methods. For example, divide2 could also be defined like this, with an anonymous class:
val divide2 = new PartialFunction[Int, Int] {
override def isDefinedAt(x: Int) = x != 0
override def apply(x: Int) = 42 / x
}
You probably won't see this very often, though, as it's a lot easier to just use pattern matching to define a PartialFunction.
In the blog post by Alvin Alexander you linked, the author refers to the pattern matching anonymous partial function literal as an anonymous function only because it happens to be both a partial function and an anonymous function. You could also define the function like so:
List(42, "cat").collect(new PartialFunction[Any, Int] {
def isDefinedAt(x: Any) = x.isInstanceOf[Int]
def apply(x: Any) = x match {
case i: Int => i + 1
}
})
It's no longer an anonymous function, although it's still an anonymous object that's the instance of an anonymous class. Or you could define a singleton object beforehand and then use that.
object Foo extends PartialFunction[Any, Int] {
def isDefinedAt(x: Any) = x.isInstanceOf[Int]
def apply(x: Any) = x match {
case i: Int => i + 1
}
}
List(42, "cat").collect(Foo)
No matter how you define it, though, it's a partial function.
Here's another way of writing your pattern matching partial function.
val divide = new PartialFunction[Int, Int] {
def apply(x: Int) = 42 / x
def isDefinedAt(x: Int) = x != 0
}
In essence, a partial function is a function that isn't defined for a set of inputs. It could be like in the example that it doesn't make sense to divide by 0, or you could want to restrict some specific values.
The nifty thing with partial functions is that it has synergies with orElse, andThen and collect. Depending on whether or not you're inputing a 0 in the divide function, your variable can be passed along to andThen if it wasn't a 0, can go through orElse if it was a 0. Finally, collect will only apply your partial function if it is defined on that input.
The way you create a partial function is usually through pattern matching with case as shown in your example.
Last thing, an anonymous function in Scala is like a lambda in Python. It's just a way of creating a function without "naming" it.
Eg
val f: Int => Int = (x: Int) => x * x
collect {
case a: Int => 1-a
}
I was wondering how it works if I want to defining a function that takes one or more parameters and a callable (a function), and why the annotation is like this.
I will take the code from this answer as example:
// Returning T, throwing the exception on failure
#annotation.tailrec
final def retry[T](n: Int)(fn: => T): T = {
util.Try { fn } match {
case util.Success(x) => x
case _ if n > 1 => retry(n - 1)(fn)
case util.Failure(e) => throw e
}
}
In this function there are a few interesting things:
The annotation tailrec.
Generic type function retry[T]
Parameter int
callable fn
My question is on point 4. Why and how the definition of this function takes two round brackets. If you want to pass a callable function to any function should you always use a round brackets next to the "list" of optional parameter? Why not put together with the parameters?
Thank you in advance
You can have multiple parameter lists in function declaration. It is mostly the same as merging all the parameters into one list (def foo(a: Int)(b: Int) is more or less equivalent to def foo(a: Int, b: Int)) with a few differences:
You can reference parameters from previous list(s) in declaration: def foo(a : Int, b: Int = a + 1) does not work, but def foo(a: Int)(b: Int = a +1) does.
Type parameters can be inferred between parameter lists: def foo[T](x: T, f: T => String): String ; foo(1, _.toString) doesn't work (you'd have to write foo[Int](1, _.toString), but def foo[T](x: T)(f: T => String); foo(1)(_.toString) does.
You can only declare the entire list as implicit, so, multiple lists are helpful when you need some parameters to be implicit, and not the others: def foo(a: Int)(implicit b: Configuration)
Then, there are some syntactical advantages - things you could do with the single list, but they'd just look uglier:
Currying:
def foo(a: Int)(b: Int): String
val bar: Int => String = foo(1)
You could write this with the single list too, but it wouldn't look as nice:
def foo(a: Int, b: Int): String
val bar: Int => String = foo(1, _)
Finally, to your question:
def retry[T](n: Int)(f: => T)
is nice, because parenthesis are optional around lists with just a single argument. So, this lets you write things like
retry(3) {
val c = createConnection
doStuff(c)
closeConnection(c)
}
which would look a lot uglier if f was merged into the same list.
Also, currying is useful:
val transformer = retry[Int](3)
Seq(1,2,3).map { n => transformer(n + 1) }
Seq(4,5,6).map { n => transformer(n * 2) }
To be honest you don't have to use multiple parameter lists in order to pass function as an argument. E.g.
def pass(string: String, fn: String => Unit): Unit = fn(string)
would totally work. However, how would you call it?
pass("test", s => println(s))
Some would find it clumsy. You would rather want to pass it like:
pass("test")(s => println(s))
or even
pass("test") { s =>
println(s)
}
to make it look as if function is a block appended to the pass called with one parameter.
With single parameter list you will be forced to write it like:
pass("test", println)
pass("test", s => println(s))
pass("test", { s => println(s) })
With last parameter curried you just get more comfortable syntax. In languages like Haskell, where currying happens automatically, you don't have to bother with syntactic design decisions like this one. Unfortunately Scala requires that you made these decisions explicitly.
If you want to pass a callable function to any function should you
always use a round brackets next to the "list" of optional parameter?
Why not put together with the parameters?
There is no such obligation, it's (mostly) a matter of style. IMO, it also leads to cleaner syntax. With two parameter lists, where the second one is the function yielding the result, we can call the retry method:
val res: Try[Int] retry(3) {
42
}
Instead, of we used a single parameter list, our method call would look like this:
val res: Try[Int] = retry(3, () => {
42
})
I find the first syntax cleaner, which also allows you to use retry as a curried method when only supplying the first parameter list
However, if we think of a more advanced use case, Scala type inference works between parameter lists, not inside them. That means that if we have a method:
def mapFun[T, U](xs: List[T])(f: T => U): List[U] = ???
We would be able to call our method without specifying the type of T or U at the call site:
val res: List[Int] = mapFun(List.empty[Int])(i => i + 1)
But if we used a single parameter list,
def mapFun2[T, U](xs: List[T], f: T => U): List[U] = ???
This won't compile:
val res2 = mapFun2(List.empty[Int], i => i + 1)
Instead, we'd need to write:
val res2 = mapFun2[Int, Int](List.empty[Int], i => i + 1)
To aid the compiler at choosing the right types.
I don't know how to articulate my question other than by providing an example of what I would like to do and explain why it doesn't work.
I would like to do something like the following:
def yes() { println("yes") }
def no() { println("no") }
def blank() {}
var handler: Option[() => Unit] = Some(blank)
...
handler = Some(yes)
...
handler.foreach(f => f())
This does not work because the defined functions are of type Unit, not () => Unit. So Some(blank) can not be assigned as type Option[()=>Unit].
Next I tried:
var handler: Option[Unit] = Some(blank)
...
handler = Some(yes)
...
handler.foreach(f => f())
This allows me to assign the functions to the handler, but then I can't invoke the function within Option's foreach function.
How can this be accomplished?
This does not work because the defined functions are of type Unit, not
() => Unit. So Some(blank) can not be assigned as type
Option[()=>Unit].
Actually it works as expected.
Type of expression yes() is Unit, but the type of expression yes depends on context.
In context of () => Unit compiler could convert yes to something like () => yes().
You could create function () => Unit from method yes manually like this:
val functionYes = yes _
handler = Some(functionYes)
But compiler is smart enough to convert method to function in context where function is expected, like Some(yes).
Take a look at this example:
1 to 10 foreach println
println here is the method Predef.println, so compiler have to convert it to function.
It's worth supplying some vocabulary here.
The type of a method
def foo(): Unit = ???
is ()Unit (3.3.1 method types in the spec).
If you leave off the parens,
def foo: Unit = ???
then the type is => Unit.
That chapter of the spec calls them "non-value types" because you can't use them as a value.
If you want a value of type () => Unit, it applies a conversion. See 6.26.5 of the spec, where it is called "eta expansion."
I bet you saw the failure by leaving off the parens at some point:
scala> def foo: Unit = ???
foo: Unit
scala> var handler: Option[() => Unit] = Some(foo)
<console>:8: error: type mismatch;
found : Unit
required: () => Unit
var handler: Option[() => Unit] = Some(foo)
^
In this case, the conversion you're getting is "evaluation" (6.26.2).
This is a case where it matters if you supplied parens in the method definition.
Since "procedure syntax" is deprecated, maybe it's useful to practice not using it.