Use of _ when invoking a method - scala

Output of below :
getNum(_);
getNum(3);
def getNum(num: Int) {
println("Num is " + num)
}
is
Num is 3
Why is getNum(_); not invoked ? How is _ used in this case ?

What you'd expect it to be? getNum(null) ?
The getNum(_); is translated into, something like:
{ x:Int => getNum(x) }
Which is a anonymous function and a value itself.
You could do for example:
val f = getNum(_)
f(42)
Then you'd see:
Num is 42

_ is used to partially apply a function. Partial application of a function produces another function with some of its parameters already applied.
val f = getNum(_) // partially apply
f(3) // apply the function

Related

missing parameter type for expanded function (Scala)

Here's my function:
def sumOfSquaresOfOdd(in: Seq[Int]): Int = {
in.filter(_%2==1).map(_*_).reduce(_+_)
}
Why am I getting the error "missing parameter type for expanded function"?
map is accepting function with one parameter ((A) => B) while every _ placeholder represents a separate parameter of anonymous function (i.e. _ * _ is function with two parameters). You can use i => i * i lambda for your map function:
def sumOfSquaresOfOdd(in: Seq[Int]): Int = {
in.filter(_%2==1)
.map(i => i * i)
.reduce(_ + _)
}
Also you can use sum instead of reduce(_ + _) (note that sum will not throw for empty sequences while reduce will):
def sumOfSquaresOfOdd(in: Seq[Int]): Int = {
in.filter(_%2==1)
.map(i => i * i)
.sum
}
I guess because map wants a function of a single argument, and you ask it to call * with two arguments. Replace _ * _ with arg => arg * arg and retry.
"map" was called with a function with two parameters when it is expecting a function of one parameter. There's another small bug due to the use of "reduce" - it throws an exception if there aren't any odd Ints in the input Seq.
A better solution would be:
def sumOfSquaresOfOdd(in: Seq[Int]): Int =
in.filter(_ % 2 == 1) . map(x => x * x) . sum
You must be using Scala2. Scala3 gives a much better error message:
Error:
2 | in.filter(_%2==1).map(_*_).reduce(_+_)
| ^^^
| Wrong number of parameters, expected: 1
(Edited to reflect changes in the other answers to this question.)

Cats Writer Vector is empty

I wrote this simple program in my attempt to learn how Cats Writer works
import cats.data.Writer
import cats.syntax.applicative._
import cats.syntax.writer._
import cats.instances.vector._
object WriterTest extends App {
type Logged2[A] = Writer[Vector[String], A]
Vector("started the program").tell
val output1 = calculate1(10)
val foo = new Foo()
val output2 = foo.calculate2(20)
val (log, sum) = (output1 + output2).pure[Logged2].run
println(log)
println(sum)
def calculate1(x : Int) : Int = {
Vector("came inside calculate1").tell
val output = 10 + x
Vector(s"Calculated value ${output}").tell
output
}
}
class Foo {
def calculate2(x: Int) : Int = {
Vector("came inside calculate 2").tell
val output = 10 + x
Vector(s"calculated ${output}").tell
output
}
}
The program works and the output is
> run-main WriterTest
[info] Compiling 1 Scala source to /Users/Cats/target/scala-2.11/classes...
[info] Running WriterTest
Vector()
50
[success] Total time: 1 s, completed Jan 21, 2017 8:14:19 AM
But why is the vector empty? Shouldn't it contain all the strings on which I used the "tell" method?
When you call tell on your Vectors, each time you create a Writer[Vector[String], Unit]. However, you never actually do anything with your Writers, you just discard them. Further, you call pure to create your final Writer, which simply creates a Writer with an empty Vector. You have to combine the writers together in a chain that carries your value and message around.
type Logged[A] = Writer[Vector[String], A]
val (log, sum) = (for {
_ <- Vector("started the program").tell
output1 <- calculate1(10)
foo = new Foo()
output2 <- foo.calculate2(20)
} yield output1 + output2).run
def calculate1(x: Int): Logged[Int] = for {
_ <- Vector("came inside calculate1").tell
output = 10 + x
_ <- Vector(s"Calculated value ${output}").tell
} yield output
class Foo {
def calculate2(x: Int): Logged[Int] = for {
_ <- Vector("came inside calculate2").tell
output = 10 + x
_ <- Vector(s"calculated ${output}").tell
} yield output
}
Note the use of for notation. The definition of calculate1 is really
def calculate1(x: Int): Logged[Int] = Vector("came inside calculate1").tell.flatMap { _ =>
val output = 10 + x
Vector(s"calculated ${output}").tell.map { _ => output }
}
flatMap is the monadic bind operation, which means it understands how to take two monadic values (in this case Writer) and join them together to get a new one. In this case, it makes a Writer containing the concatenation of the logs and the value of the one on the right.
Note how there are no side effects. There is no global state by which Writer can remember all your calls to tell. You instead make many Writers and join them together with flatMap to get one big one at the end.
The problem with your example code is that you're not using the result of the tell method.
If you take a look at its signature, you'll see this:
final class WriterIdSyntax[A](val a: A) extends AnyVal {
def tell: Writer[A, Unit] = Writer(a, ())
}
it is clear that tell returns a Writer[A, Unit] result which is immediately discarded because you didn't assign it to a value.
The proper way to use a Writer (and any monad in Scala) is through its flatMap method. It would look similar to this:
println(
Vector("started the program").tell.flatMap { _ =>
15.pure[Logged2].flatMap { i =>
Writer(Vector("ended program"), i)
}
}
)
The code above, when executed will give you this:
WriterT((Vector(started the program, ended program),15))
As you can see, both messages and the int are stored in the result.
Now this is a bit ugly, and Scala actually provides a better way to do this: for-comprehensions. For-comprehension are a bit of syntactic sugar that allows us to write the same code in this way:
println(
for {
_ <- Vector("started the program").tell
i <- 15.pure[Logged2]
_ <- Vector("ended program").tell
} yield i
)
Now going back to your example, what I would recommend is for you to change the return type of compute1 and compute2 to be Writer[Vector[String], Int] and then try to make your application compile using what I wrote above.

delay implementation in scala

I have implemented the following cons_stream function in scala that does not work and I am not sure why.
def cons_stream[T, U](x : T, y : U) =
{
def delay = () => y
/// Delay takes no parameters but returns y
(f : String ) =>
{
if ( f == "x") x
else if( f == "y") delay
else throw new Error("Invalid string use x or y")
}
}
The corresponding car and cdr functions are:
def stream_car[T](f : String => T) : T = f("x")
def stream_cdr[T](f : String => Any) : T = force(f("y").asInstanceOf[() => T])
Now I have the definition of a stream integers starting with 1
def integers_starting_from_n[T, U](n : Int) : String => Any =
{
cons_stream(n, integers_starting_from_n(n+1))
}
Unfortunately when I try to access the stream using either stream_car or stream_cdr I get a stack overflow:
def integers = integers_starting_from_n(1)
stream_car(integers)
I have no idea why. Any help is appreciated.
I assume that the stack is full of integers_starting_from_n. Correct? That function is recursive and is called before cons_stream can be executed, because it takes value of integers_starting_from_n(n+1) as a paremeter.
In order to define a stream, you can use a call-by-name parameter by prepending => to the type. For your example, use call-by-name with y.
def cons_stream[T, U](x:T, y: => U)

scala. higher order function calling by name. does it make sense

Just want to clarify. If we use higher-order function (f. that accepts another function as argument). Does it make any sense specify "=>" sign to call it by-name. It seems arg-function is calling by-name anyhow?
There is an example:
// 1.
// the function that accepts arg-function with: two int params and returning String
// the function passing v1 & v2 as parameters to arg-function, invoking arg-function 2 times, connecting the result to one string
def takeFunction1(f: (Int, Int) => String, v1:Int, v2:Int ): String = {
f(v1, v2) + f(v1, v2)
}
// 2. same as #1 but calling arg-function by-name
def takeFunction2(f: => ((Int, Int) => String), v1:Int, v2:Int ): String = {
f(v1, v2) + f(v1, v2)
}
def aFun(v1:Int, v2:Int) : String = {
(v1 + v2).toString
}
// --
println( takeFunction1( aFun, 2, 2) )
println( takeFunction2( aFun, 2, 2) )
And what if I want to call it like this ?:
println( takeFunction2( aFun(2,2)), ... ) // it tries to evaluate immediately when passing
The difference is that if you pass as the first argument a call to a function that returns the (Int, Int) => String value to use, this call to the generator function is evaluated only once with pass-by-value, compared to being evaluated each time the argument is used in the case of pass-by-name.
Rather contrived example:
var bar = 0
def fnGen() = {
bar += 1
def myFun(v1:Int, v2:Int) = {
(v1 + v2).toString
}
myFun _
}
Now run some calls of your methods above using fnGen:
scala> println( takeFunction1( fnGen(), 2, 2) )
44
scala> bar
res1: Int = 1
scala> println( takeFunction2( fnGen(), 2, 2) )
44
scala> bar
res3: Int = 3
As you can see, calling takeFunction1 increments bar only once, while calling takeFunction2 increments bar twice.
The argument that you're passing by name is aFun; that's a valid expression, and it does get evaluated both times that takeFunction2 uses it, but since it's just a variable, and you're not doing anything else with it, "evaluating" it is not very meaningful. (It just evaluates to the same value both times.) For pass-by-name to behave differently from pass-by-value, you have to pass in an impure expression (one that has side-effects, or that can evaluate to different values on successive calls, or whatnot).

declare variable in custom control structure in scala

I am wondering if there is a way to create a temp variable in the parameter list of a custom control structure.
Essentially, I would like create a control structure that looks something like the
for loop where I can create a variable, i, and have access to i in the loop body only:
for(i<- 1 to 100) {
//loop body can access i here
}
//i is not visible outside
I would like to do something similar in my code. For example,
customControl ( myVar <- "Task1") {
computation(myVar)
}
customControl ( myVar <- "Task2") {
computation(myVar)
}
def customControl (taskId:String) ( body: => Any) = {
Futures.future {
val result = body
result match {
case Some(x) =>
logger.info("Executed successfully")
x
case _ =>
logger.error(taskId + " failed")
None
}
}
}
Right now, I get around the problem by declaring a variable outside of the custom control structure, which doesn't look very elegant.
val myVar = "Task1"
customControl {
computation(myVar)
}
val myVar2 = "Task2"
customControl {
computation(myVar2 )
}
You could do something like this:
import scala.actors.Futures
def custom(t: String)(f: String => Any) = {
Futures.future {
val result = f(t)
result match {
case Some(x) =>
println("Executed successfully")
x
case _ =>
println(t + " failed")
None
}
}
}
And then you can get syntax like this, which isn't exactly what you asked for, but spares you declaring the variable on a separate line:
scala> custom("ss") { myvar => println("in custom " + myvar); myvar + "x" }
res7: scala.actors.Future[Any] = <function0>
in custom ss
ss failed
scala> custom("ss") { myvar => println("in custom " + myvar); Some(myvar + "x") }
in custom ss
Executed successfully
res8: scala.actors.Future[Any] = <function0>
scala>
Note that the built-in for (x <- expr) body is just syntactic sugar for
expr foreach (x => body)
Thus it might be possible to achieve what you want (using the existing for syntax) by defining a custom foreach method.
Also note that there is already a foreach method that applies to strings. You could do something like this:
case class T(t: String) {
def foreach(f: String => Unit): Unit = f(t)
}
Note: You can also change the result type of f above from Unit to Any and it will still work.
Which would enable you to do something like
for (x <- T("test"))
print(x)
This is just a trivial (and useless) example, since now for (x <- T(y)) f(x) just abbreviates (or rather "enlongishes") f(y). But of course by changing the argument of f in the above definition of foreach from String to something else and doing a corresponding translation from the string t to this type, you could achieve more useful effects.