Need help understanding the syntax - scala

I am Scala beginner.I know the syntax for function declaration
def function_name(parameter:return_type):return_type = {function_body}
Refering this link https://livebook.manning.com/#!/book/scala-in-action/chapter-2/161.
I can't get over the code written there
def breakable(op: => Unit) { ... }
Can anyone explain this?

This is a shorthand syntax for declaring a function that returns Unit (roughly the same as void in C-like languages).
The definition
def breakable(op: => Unit) { ... }
is the same as
def breakable(op: => Unit): Unit = { ... }
This syntax may be removed in later versions of Scala, so best to include the = even when declaring a function that returns Unit.
The parameter is declared as op: => Unit which means it is a call-by-name parameter. This means that the expression that is passed to this parameter is only evaluated when it is used, and is evaluated every time it is used. In this case it means that you can pass a block of code to breakable in a convenient way:
breakable {
println("I have been called")
}
Each time breakable evaluates op, the println statement will be executed.

In scala function can take values(pre-computed values or not-yet-computed values) along with function as arguments.
So, function which takes computed values as argument,
scala> def f(a: Int) = a * 100
f: (a: Int)Int
Example of function which takes a block of code returning Int (not yet computed) , block of code here could be just anonymous or existing method(not a function; that's where things get messy)
scala> def f(a: => Int) = a
f: (a: => Int)Int
and to use it,
scala> def a: Int = 100 * 100
a: Int
scala> f(a) //a returns Int so confirms a: => Int
res3: Int = 10000
In your example, def breakable(op: => Unit) { ... } takes a argument which WILLL be computed as Unit.
For example, you can pass println, which returns Unit,
scala> def breakable(op: => Unit) = op
breakable: (op: => Unit)Unit
scala> breakable { println("i m learning fp") }
i m learning fp
The other thing you will see is function taking function as argument, as in Functor, Monad etc.
For example, map/ flatMap on List[Int] would be
final override def map[B](f: A => B): List[B]
final override def flatMap[B](f: Int => scala.collection.IterableOnce[B]): List[B]

Related

Nice syntax for function composition in Scala

I would like to arrive to a syntax as productive as Haskell's desort = (reverse . sort) in Scala... Here is my attempt:
implicit class Composition[A,B,C](val g: A => B) {
def o(f: B => C): A => C = { a:A => f(g(a))}
}
val fg = cos _ o sin
Is there any way we can get rid of the _in the declaration of gf?
For functions yes, but for methods, no. Your problem is that you're trying to use a method for g, and not a function. For functions, there is already a method for this called andThen:
val f: Int => Int = _ + 1
val g: Int => String = _.toString
scala> val fg = f andThen g
fg: Int => String = <function1>
scala> fg(2)
res3: String = 3
Your own implicit class will work as well (though I haven't looked at the exact semantics you desire), using functions like f and g, as I've defined them. It will even work for a function and a method (in that order).
def a(i: Int): Int = i + 1
def b(i: Int): String = i.toString
scala> f andThen a
res4: Int => Int = <function1>
However, a andThen b does not work as-is, because a is a method, which you cannot call andThen on. In order to use andThen, a needs to be converted to a function, which will not happen automatically, because a function isn't necessarily expected. a _ andThen b eta-expands a into a function, in which has a method called andThen, and can be provided an argument of b (a method), because the compiler will implicitly convert b to a function, since a function is the only thing that is expected as an argument of andThen. Function isn't the only type with a method called andThen, so the compiler can't expect one 100% of the time to make the conversion from method to function for a.

Anonymous PartialFunction syntax

I asked this question earlier: Combine a PartialFunction with a regular function
and then realized, that I haven't actually asked it right.
So, here goes another attempt.
If I do this:
val foo = PartialFunction[Int, String] { case 1 => "foo" }
val bar = foo orElse { case x => x.toString }
it does not compile: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: PartialFunction[?,?]
But this works fine:
val x: Seq[String] = List(1,2,3).collect { case x => x.toString }
The question is what is the difference? The type of the argument is the same in both cases: PartialFunction[Int, String]. The value passed in is literally identical. Why one does one case work, but not the other?
You need to specify the type for bar because the compiler is unable to infer it. This compiles:
val foo = PartialFunction[Int, String] { case 1 => "foo" }
val bar : (Int => String) = foo orElse { case x => x.toString }
In the case of List(1,2,3).collect{case x => x.toString} the compiler is able to infer the input type of the partial function based off of how theList was typed.
final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That])
Based on the type parameters the compiler can infer that you are passing a correctly typed partial function. That's why List(1,2,3).collect{case x:String => x.toString} does not compile nor does List(1,2,3).collect{case x:Int => x.toString; case x: String => x.toString}.
Since List is covariant the compiler is able to infer that the partial function {case x => x.toString} is a partial function on Int. You'll notice that List(1,2,3).collect{case x => x.length} does not compile because the compiler is inferring that you're operating on either an Int or a subclass of Int.
Also keep in mind that the {case x => x.toString} is just syntactic sugar. If we do something like the below then your example works as expected
val f = new PartialFunction[Int, String](){
override def isDefinedAt(x: Int): Boolean = true
override def apply(v1: Int): String = v1.toString
}
val foo = PartialFunction[Int, String] { case 1 => "foo" }
val bar = foo orElse f //This compiles fine.
List(1,2,3).collect{f} // This works as well.
So the only logical answer from my perspective is that the syntactic sugar that is able to generate a PartialFunction instance for {case x => x.toString} does not have enough information at compile time to be able to adequately type it as a PartialFunction[Int, String] in your orElse case.
You can use the library Extractor.scala.
import com.thoughtworks.Extractor._
// Define a PartialFunction
val pf: PartialFunction[Int, String] = {
case 1 => "matched by PartialFunction"
}
// Define an optional function
val f: Int => Option[String] = { i =>
if (i == 2) {
Some("matched by optional function")
} else {
None
}
}
// Convert an optional function to a PartialFunction
val pf2: PartialFunction[Int, String] = f.unlift
util.Random.nextInt(4) match {
case pf.extract(m) => // Convert a PartialFunction to a pattern
println(m)
case f.extract(m) => // Convert an optional function to a pattern
println(m)
case pf2.extract(m) => // Convert a PartialFunction to a pattern
throw new AssertionError("This case should never occur because it has the same condition as `f.extract`.")
case _ =>
println("Not matched")
}

Why the inference engine need explicit type with currying

Let's define f, a function that supports currying :
def f(a: Int)(b: Int) = a + b
This code doesn't compile
def g= f(1)
<console>:10: error: missing arguments for method f;
follow this method with `_' if you want to treat it as a partially applied function
def g= f(1)
I've found these 2 workarounds :
scala> def h = f(1) _
h: Int => Int
scala> def i : Int => Int = f(1)
i: Int => Int
But i don't understand why the inference engine need help in a trivial case like that ?
This is because def f(a: Int)(b: Int) is not a function but a method with multiple parameter lists. Scala doesn't unify both of them to a single concept, thus you have to distinguish between them as well.
To partially apply a method with multiple parameter lists (and therefore implicitly convert this method to a function) you have to add an underscore after the method, as the error message suggests. When you tell the compiler explicitly which signature you want to have, it can also implicitly convert a method to a function (as seen in your second workaround).
If you want to use currying in Scala it's best to create a function from the beginning:
scala> val f = (a: Int) => (b: Int) => a+b
f: Int => (Int => Int) = <function1>
scala> val g = f(1)
g: Int => Int = <function1>

Scala - understanding a code snippet involving currying

I'm new to scala and I'm having a little trouble understanding currying - I'm practicing by coding simple functions for now, and would need clarification about the following
def mul (a: Int) (b: Int): Int =
{
{
a * b
}
}
Is the above function definition same as the below?
def mul: Int => Int => Int = {
(a: Int) =>
{
(b: Int) =>
a * b
}
}
From syntax I could interpret mul as a function that accepts an integer, and returns a function that accepts an integer and returns an integer. But I'm not sure if my interpretation is actually correct. Any explanation regarding the above example or the syntax of curried functions will be really helpful.
Your interpretation is correct. But you don't need all those braces.
def mul(a: Int)(b: Int) = a*b
val mulAB = (a: Int) => { (b: Int) => a*b } // Same as mul _
val mul5B = (b: Int) => 5*b // Same as mulAb(5) or mul(5) _
In general, you can rewrite any function with multiple arguments as a curried chain instead, where each argument produces a function that takes one fewer arguments until the last one actually produces the value:
f(a: A ,b: B ,c: C, d: D): E <===> A => B => C => D => E
In Scala, the natural grouping is by parameter block, not by individual parameter, so
f(a: A)(b: B, c: C)(d: D): E <===> A => (B,C) => D => E

Why is PartialFunction <: Function in Scala?

In Scala, the PartialFunction[A, B] class is derived from type Function[A, B] (see Scala Reference, 12.3.3). However, this seems counterintuitive to me, since a Function (which needs to be defined for all A) has more stringent requirements than a PartialFunction, which can be undefined at some places.
The problem I've come across is that when I have a partial function, I cannot use a Function to extend the partial function. Eg. I cannot do:
(pf orElse (_)=>"default")(x)
(Hope the syntax is at least remotely right)
Why is this subtyping done reversely? Are there any reasons that I've overlooked, like the fact that the Function types are built-in?
BTW, it would be also nice if Function1 :> Function0 so I needn't have the dummy argument in the example above :-)
Edit to clarify the subtyping problem
The difference between the two approaches can be emphasized by looking at two examples. Which of them is right?
One:
val zeroOne : PartialFunction[Float, Float] = { case 0 => 1 }
val sinc = zeroOne orElse ((x) => sin(x)/x) // should this be a breach of promise?
Two:
def foo(f : (Int)=>Int) {
print(f(1))
}
val bar = new PartialFunction[Int, Int] {
def apply(x : Int) = x/2
def isDefinedAt(x : Int) = x%2 == 0
}
foo(bar) // should this be a breach of promise?
Because in Scala (as in any Turing complete language) there is no guarantee that a Function is total.
val f = {x : Int => 1 / x}
That function is not defined at 0. A PartialFunction is just a Function that promises to tell you where it's not defined. Still, Scala makes it easy enough to do what you want
def func2Partial[A,R](f : A => R) : PartialFunction[A,R] = {case x => f(x)}
val pf : PartialFunction[Int, String] = {case 1 => "one"}
val g = pf orElse func2Partial{_ : Int => "default"}
scala> g(1)
res0: String = one
scala> g(2)
res1: String = default
If you prefer, you can make func2Partial implicit.
PartialFunction has methods which Function1 does not, therefore it is the subtype. Those methods are isDefinedAt and orElse.
Your real problem is that PartialFunctions are not inferred sometimes when you'd really like them to be. I'm hopeful that will be addressed at some future date. For instance this doesn't work:
scala> val pf: PartialFunction[String, String] = { case "a" => "foo" }
pf: PartialFunction[String,String] = <function>
scala> pf orElse { case x => "default" }
<console>:6: error: missing parameter type for expanded function
((x0$1) => x0$1 match { case (x # _) => "default" })
But this does:
scala> pf orElse ({ case x => "default" } : PartialFunction[String,String])
res5: PartialFunction[String,String] = <function>
Of course you could always do this:
scala> implicit def f2pf[T,R](f: Function1[T,R]): PartialFunction[T,R] =
new PartialFunction[T,R] {
def apply(x: T) = f(x)
def isDefinedAt(x: T) = true
}
f2pf: [T,R](f: (T) => R)PartialFunction[T,R]
And now it's more like you want:
scala> pf orElse ((x: String) => "default")
res7: PartialFunction[String,String] = <function>
scala> println(res7("a") + " " + res7("quux"))
foo default