Pass function argument as code block - scala

I am new to Scala. I have been searching but there is no easy "search string" for the seemingly easy question I have.
def foo( f: (String) => String ){println(f("123"))}
foo{_+"abc"} //works
def bar( f :() => String ){println(f())}
bar{"xyz"} // why does this not work?
def baz( f: => String ){println(f)}
baz{"xyz"} //works
Why does the second (bar) not work?

Second baz works because it's not a function literal, but a call-by-name parameter. Basically what it does is delaying the moment of argument computation until it's needed in the program. You can also read about this in this question.
As for bar you just need to pass a function like bar{() => "xyz"}

bar accepts a function that takes no arguments and returns String. You gave it just a String. To make it work:
bar{() => "xyz"}

This case is special to parameterless functions/blocks.
object Fs2 {
def f0=1
def f0_1()=1
}
object Main extends App {
println(Fs2.f0)
//println(Fs2.f0()) wont compile
println(Fs2.f0_1)
println(Fs2.f0_1())
}
Unit "()" is optional for f0_1. Adding it to f0 will cause an error. f0 does not accept any parameter. Unit itself is a parameter declaring there is no parameter. Fs2.f0 corresponds to baz, Fs2.f0() corresponds to bar.

Related

scala: difference between function and function _

I'm getting some unexpected behavior when using a call by name function in Scala. Can anybody explain the difference here?
class Button( act: => Unit) {def fire = act}
def foo() {println("foo got called")}
val x= new Button(foo)
x.fire
val y= new Button(foo _)
y.fire
x.fire causes foo to be called.
y.fire does not.
Why?
What function is being passed to y?
Thanks!
You should probably define your class a bit differently.
class Button( act: () => Unit) {def fire = act()}
Notice you are now taking in a Function0[Unit] instead of a call-by-name Unit value. This new definition has better typesaftey since it requires a function, while yours will accept any value, and will do nothing unless there are side effect required to evaluate the value passed in. We also now call the function passed in for its side effects instead of just returning it.
The problem with Unit is that when a unit is required any value can be provided which will be automatically discarded for a Unit. For example, with your code new Button(5) is valid, as is the code val x: Unit = 5.
The reason the first code class Button( act: => Unit) {def fire = act} "works", is you call the method foo, and pass the result into the Button constructor. Since it's a by-name parameter foo doesn't actually run until it's used. When you then use the Unit value passed into the class, the expression needs to be evaluated so foo is fun.
You second example is different however, adding the underscore (foo _) now means that you are passing in the method itself as a function, instead of calling the method and passing in the result as in your first example. It's perfectly fine to pass a function in to the constructor even thought the type now is not Unit since as discussed earlier any value can be discarded and replaced by Unit. When you evaluate the Unit value, there are no side effects this time since you don't run the method to get the unit, just create a function which is the discarded without being run. def fire = act
When you change the type to be a function.
class Button( act: () => Unit) {def fire = act()}
now only a () => Unit is a valid argument instead of anything, and the fire method runs that function.
Here is a possible explanation!
scala> foo _
res14: () => Unit = <function0>
scala> foo
foo got called
scala>
Can you see why now?
Because Button takes a (delayed) Unit as a constructor argument, you'd think that the call to new Button(foo _) wouldn't be allowed because () => Unit is not the same thing as =>Unit. But it turns out that => Unit is, essentially, the universal accepter.
new Button()
new Button(99)
new Button("str")
You'll get warnings, but these all compile and run, and you can invoke the fire method on them (but it won't do anything).

Trying to skip implicit parameter list

I'd like to call a function returned by a function with an implicit parameter, simply and elegantly. This doesn't work:
def resolveA(implicit a: A): String => String = { prefix =>
s"$prefix a=$a"
}
case class A(n: Int)
implicit val a = A(1)
println(resolveA("-->")) // won't compile
I've figured out what's going on: Scala sees the ("-->") and thinks it's an attempt to explicitly fill in the implicit parameter list. I want to pass that as the prefix argument, but Scala sees it as the a argument.
I've tried some alternatives, like putting an empty parameter list () before the implicit one, but so far I've always been stopped by the fact that Scala thinks the argument to the returned function is an attempt to fill in the implicit parameter list of resolveA.
What's a nice way to do what I'm trying to do here, even if it's not as nice as the syntax I tried above?
Another option would be to use the apply method of the String => String function returned by resolveA. This way the compiler won't confuse the parameter lists, and is a little shorter than writing implicltly[A].
scala> resolveA[A].apply("-->")
res3: String = --> a=A(1)

Why in Scala function defined without empty parentheses doesn't behave like function?

Consider the following 2 objects
object TestObj1 {
def testMethod = "Some text"
}
object TestObj2 {
def testMethod() = "Some text"
}
and if I call those methods directly, they do what I expect
scala> TestObj1.testMethod
res1: String = Some text
scala> TestObj2.testMethod
res2: String = Some text
But now if we define following function
def functionTakingFunction(callback: () => String) {
println("Call returns: " + callback())
}
and try to call it, the method defined without () is not accepted.
scala> functionTakingFunction(TestObj1.testMethod)
<console>:10: error: type mismatch;
found : String
required: () => String
functionTakingFunction(TestObj1.testMethod)
^
scala> functionTakingFunction(TestObj2.testMethod)
Call returns: Some text
I also noticed that you can't call the TestObj1.testMethod using parentheses, since it already is a String. But what is causing this behavior?
You are not passing the method, you're invoking it and then passing its result into the call.
If you want to pass the method, you first have to convert it into a function, and pass that:
functionTakingFunction(TestObj1.testMethod _)
Here the testMethod is converted into a partially applied function (said to be "tied").
The reason you have to do that is because TestObj1.testMethod does not evaluate to function0 (which is what need to be passed to functionTakingFunction), but to a String because of the way it is declared (without parentheses).
It works on TestObj2 because the testMethod is defined with parentheses and thus just typing TestObj2.testMethod does not invoke it.
functionTakingFunction(TestObj1.testFunction) is called as functionTakingFunction("Some text") - it is evaluated rather than passed
Here, you are not passing the function. What you are trying to do is evaluate TestObj1.testFunction and then pass that result to functionTakingFunction
But if you see the definition of functionTakingFunction, it says clearly
def functionTakingFunction(callback: () => String)
means this function expects a function with Return Type as Unit. But TestObj1.testFunction is having no return type.
The difference between Unit Return Type and No Return Type is:
No Return Type means this method will not return anything
Unit Return Type means this method will return something which is having no meaningful value.
Hope it helps you now. Happy coding and enjoy Scala.

Using method to create function? The details explanation?

def first[A] :Tuple2[A,_] => A = ( pair :Tuple2[A,_] ) => pair._1
val name = first( ("Anna", 23) )
"If you take a closer look at line 2, what you see here is a method call which returns a newly created function of type Tuple2[String,Any] => String (since the compiler kicks in and infers the needed type for applying to person). Although the whole expression looks like an ordinary method call, it’s in fact a method call (to a factory method without any parameter) and a function call which follows afterwards. " -- this is the explanation of the above code.
I am not able to reason about the first step of the above process (the process creating a function object). Can someone write out a "human compiler" procedure explicitly?
EDIT: I think the fully expanded logic for line 2 should be the following two lines
val firstAsFunc= first[String];
val name = firstAsFunc(("Anna", 23))
I'm not sure to break it down further. Here's what I can think of -- I hope you get it, or that someone else is feeling more clever than I.
scala> val func = first[String] // method call
func: Tuple2[String, _] => String = <function1>
scala> val name = func( ("Anna", 23) )
name: String = Anna
The problem with the above is that func is really a getter -- a method call itself -- so I'm hardly changing anything.
EDIT
I'm not sure what you mean by formal parameter. The method first doesn't have value parameters, just type parameters. Trying to pass a value parameter to it would be a syntactical error.
When you say
(pair: Tuple2[A,_]) => pair._1
the compiler decides that you are actually saying
new Function1[Tuple2[A,_], A] {
def apply(pair: Tuple2[A,_]) = pair._1
}
That is, the first method creates a new object (of type Function1) with a method called apply which then is transparently called when you say first(...). (You would get the same thing if you wrote first.apply(...).)
(Note: Tuple2[A,_] can itself be abbreviated (A,_).)
I'm not 100% sure that I understand which bit of the process you're asking about - are you asking about what a function object is? I'll answer that question on the assumption that it is :-)
A function object is an object that derives from one of the FunctionN (Function0, Function1 etc.) traits and implements an apply method. So your example could be rewritten:
scala> def first[A]: Tuple2[A, _] => A = new Function1[Tuple2[A, _], A] { def apply(pair: Tuple2[A, _]) = pair._1 }
first: [A]=> Tuple2[A, _] => A
scala> val name = first( ("Anna", 23) )
name: java.lang.String = Anna
You can see that a function is actually an instance of FunctionN like so:
scala> def foo(x: Int, y: Double): String = "x = "+ x.toString +", "+ y.toString
foo: (x: Int, y: Double)String
scala> (foo _).isInstanceOf[Function2[_, _, _]]
res1: Boolean = true
If you take a closer look at line 2, what you see here is a method call which returns a newly created function of type Tuple2[String,Any] => String
This explanation is wrong. Line 2 does not "return a newly created function". The function is created on line 1, as explained by Rex Kerr.
Although the whole expression [on line 2] looks like an ordinary method call, it’s in fact a method call (to a factory method without any parameter) and a function call which follows afterwards.
I don't believe this is true; there is no hidden factory method going on, because the Function1 object has already been created on line 1.
One of the questions I was asking what is the formal parameter for method first.
See Wikipedia > Parameter # Computer Science

Why do I need a curried function to be able to pass function literals with short placeholder syntax?

Given this definition:
class Foo(var x: String) {}
object Helper {
def model[T](get: ⇒ T, set: T ⇒ Unit) : Model[T] = new Model[T] {
override def getObject(): T = get
override def setObject(obj: T) { set(obj) }
}
}
I try to call model like this:
val f = new Foo("initial")
val stringModel = model(f.x, f.x = _)
But that doesn't work, the compiler gives me this, complaining about the underscore:
missing parameter type for expanded function ((x$1) => f.x = x$1)
If I change the definition of model to use two parameter lists like this:
def model[T](get: ⇒ T)(set: T ⇒ Unit) // rest is unchanged
Then I can call it like this:
model(f.x)(f.x = _)
Which I find nice and concise. I don't really mind doing it like this, though it makes method overloading harder. I would like to understand, however, why the second variant works and the first one doesn't?
The second variant works because Scala refines its types parameter-block by parameter-block. If you don't specify the type of your input parameter for the function, it's possible that it would change the type T that it has inferred based on the first parameter. If you push it to a separate parameter block, Scala's already decided what T must be by the time it hits that block, so it fills in the only possible value for the function argument type.