How can we accept function name as user input? Is there any member in standard library like readLine, readByte, etc that solves the purpose?
Context: As part of functional programming, I need to pass function name as first argument but instead of hardcoding I want to accept it as user input.
Please suggest.
Here is the sample code:
def square(x:Int):Int = x*x
def sum(f: Int => Int, a:Int, b:Int):Int ={
if(a>b) 0 else f(a) + sum(f,a+1,b)
}
println("Enter the first number:")
var num1 = readInt()
println("Enter the second number:")
var num2 = readInt()
val ressum = sum(square,num1,num2)
User input is a String. Function and method names are not. To go from one to the other you have to test the input content.
val result = usrInput match {
case "foo" => foo()
case "bar" => bar()
case "baz" => baz()
case _ => throw new Error(s"I don't know $usrInput")
}
This assumes that they all have the same return type (and the returned value is of interest). If they return different types then the code gets more convoluted.
if (usrInput == "foo") {
val fooRslt = foo()
// do more "foo" stuff
} else if (usrInput == "bar") {
val barRslt = bar()
// etc. etc.
...
Function and method calls are checked for type safety by the compiler. User input is runtime content. Compile-time, run-time, ne'er the twain shall meet.
Related
I am really new to scala, and I am currently making my way through the tour (https://docs.scala-lang.org/tour/variances.html).
Now, looking at some library (akka-http), I stumbled across some code like this:
def fetchItem(itemId: Long): Future[Option[Item]] = Future {
orders.find(o => o.id == itemId)
}
And I don't quite understand the syntax, or more precisely, the = Future { part. As I learned, the syntax for methods is def [methodName]([Arguments])(:[returnType]) = [codeblock].
However the above seems to differ in that its having the Future in front of the "codeblock". Is this some kind of object instantiation? Because I could not find documentation about this syntax, I tried in my play code stuff like this:
{
val myCat:Cat = new Cat("first cat")
val myOtherCat:Cat = Cat { "second cat" }
val myThirdCat:Cat = MyObject.getSomeCat
}
...
object MyObject
{
def getSomeCat: Cat = Cat
{
"blabla"
}
}
And all of this works, in that it creates a new Cat object. So it seems like new Cat(args) is equivalent to Cat { args }.
But shouldn't def getSomeCat: Cat = Cat define a method with a code block, not the instantiate a new Cat object? I am confused.
I think there are a couple of things here:
1.
The [codeblock] in method syntax doesn't have to be enclosed in {}. If there's only one expression, it's allowed to omit them.
E.g.
def add(x: Int, y: Int) = x + y
or
def add(x: Int, y: Int) = Future { x + y }
2.
Each class can have its companion object define an apply() method, which can be invoked without explicitly saying "apply" (this is special Scala syntactic sugar). This allows us to construct instances of the class by going through the companion object, and since "apply" can be omitted, at first glance it looks like going through the class itself, just without the "new" keyword.
Without the object:
class Cat(s: String)
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat("second cat") // error
And now with the object:
class Cat(s: String)
object Cat {
def apply(s: String) = new Cat(s)
}
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat.apply("second cat") // OK
val myThirdCat: Cat = Cat("third cat") // OK (uses apply under the hood)
val myFourthCat: Cat = Cat { "fourth cat" } // OK as well
Note how fourth cat invocation works just fine with curly braces, because methods can be passed codeblocks (last evaluated value in the block will be passed, just like in functions).
3.
Case classes are another slightly "special" Scala construct in a sense that they give you convenience by automatically providing some stuff for you "behind the curtain", including an associated companion object with apply().
case class Cat(s: String)
val myFirstCat: Cat = new Cat("first cat") // OK
val mySecondCat: Cat = Cat.apply("second cat") // OK
val myThirdCat: Cat = Cat("third cat") // OK
What happens in your case with Future is number 2, identical to "fourth cat". Regarding your question about new Cat(args) being equivalent to Cat { args }, it's most likely situation number 3 - Cat is a case class. Either that, or its companion object explicitly defines the apply() method.
The short answer is Yes, that Future code is an object instanciation.
Your Cat class has a single String argument and can be created using Cat(<string>). If you want to compute a value for the string you can put it in a block using {} as you did in your example. This block can contain arbitrary code, and the value of the block will be the value of the last expression in the block which must be type String.
The Future[T] class has a single argument of type T and can be created using Future(T). You can pass an arbitrary block of code as before, as long as it returns a value of type T.
So creating a Future is just like creating any other object. The fetchItem code is just creating a Future object and returning it.
However there is a subtlety with Future in that the parameter is defined as a "call-by-name" parameter not the default "call-by-value" parameter. This means that it is not evaluated until it is used, and it is evaluated every time it is used. In the case of a Future the parameter is evaluated once at a later time and potentially on a different thread. If you use a block to compute the parameter then the whole block will be executed each time the parameter is used.
Scala has very powerful syntax and some useful shortcuts, but it can take a while to get used to it!
A typical method structure will look like:
case class Bar(name: String)
def foo(param: String): Bar = {
// code block.
}
However, Scala is quite flexible when its comes to method definition. One of flexibility is that if your method block contains single expression, then you can ignore curly braces { }.
def foo(param: String): Bar = {
Bar("This is Bar") //Block only contains single expression.
}
// Can be written as:
def foo(param: String): Bar = Bar("This is Bar")
// In case of multiple expressions:
def foo(param: String): Bar = {
println("Returning Bar...")
Bar("This is Bar")
}
def foo(param: String): Bar = println("Returning Bar...") Bar("This is Bar") //Fails
def foo(param: String): Bar = println("Returning Bar..."); Bar("This is Bar") //Fails
def foo(param: String): Bar = {println("Returning Bar..."); Bar("This is Bar")} // Works
Similarly, in your code, fetchItem contains only single expression - Future {orders.find(o => o.id == itemId)} that return a new Future (instance of Future) of Option[Item], therefore braces { } is optional. However, if you want you can write it inside braces as below:
def fetchItem(itemId: Long): Future[Option[Item]] = {
Future {
orders.find(o => o.id == itemId)
}
}
Similarly, if a method take only single parameter, you can use curly braces. i.e. you can invoke fetchItems as:
fetchItem(10)
fetchItem{10}
fetchItem{
10
}
So, why use curly braces { } instead of brackets ( )?
Because, you can provide multiple code blocks inside braces, and this situation is required when need to perform multiple computation and return a value as result of that computation. For example:
fetchItem{
val x = 2
val y = 3
val z = 2
(x + y)*z //final result is 10 which is passed as parameter.
}
// In addition, using curly braces will make your code more cleaner e.g. in case of higher ordered functions.
def test(id: String => Unit) = ???
test {
id => {
val result: List[String] = getDataById(x)
val updated = result.map(_.toUpperCase)
updated.mkString(",")
}
}
Now, coming to your case, when you invoke Future{...}, you are invoking apply(...) method of Scala future companion object that take function literal body: =>T as parameter and return a new Future.
//The below code can also be written as:
Future {
orders.find(o => o.id == itemId)
}
//Can be written as:
Future(orders.find(o => o.id == itemId))
Future.apply(orders.find(o => o.id == itemId))
// However, braces are not allowed with multiple parameter.
def foo(a:String, b:String) = ???
foo("1","2") //work
foo{"1", "2"} //won't work.
In documentation of Option class written that following two examples are equivalent:
val name: Option[String] = request getParameter "name"
val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase }
println(upper getOrElse "")
and
val upper = for {
name <- request getParameter "name"
trimmed <- Some(name.trim)
upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
} yield upper
println(upper getOrElse "")
But I don't understand how they can be equivalent: in first code block request getParameter "name" return instance of type Option[String], but in second code block statement name <- request getParameter "name" return instance of type String (I assumed that because next statement calls trim method on name variable (trim is not defined for Option[String])).
The conversion from for ... yield comprehension to map/flatMap method calls is done by the compiler. It's not required that the Option is an Iterable; the only thing necessary in this case is Option having map / flatMap methods:
flatMap if there are more -> calls after it in the same for block
map if it's the last one
We can create our own MyOption class like this:
case class MyOption[+T](value: T) {
def flatMap[A](f: T => MyOption[A]): MyOption[A] = f(value)
def map[A](f: T => A): MyOption[A] = MyOption(f(value))
override def toString = s"Some($value)"
}
Then:
val result = for {
a <- MyOption("one")
b <- MyOption("two")
} yield a + "," + b
println(result)
// prints: Some(one,two)
Option is an Iterable (there's an implicit option2Iterable method in Option companion object), that's why it can be used in someVar <- someOption clause. In fact, that arrow means "take elements from collection on the right".
So you're right, name in the 2nd example is a String.
In the 1st one you can see there are map and other Iterable methods used on Option. It is basically the same as for expression below, but calls methods directly, while for is just a syntax sugar and gets translated into the chain of method calls by the compiler.
getFirstNotNullResult executes a list of functions, until one of them returns a not null value.
How to implement getNotNullFirstResult more elegantly/concise?
object A {
def main(args: Array[String]) {
println(test());
}
def test(): String = {
getFirstNotNullResult(f1 _ :: f2 _ :: f3 _ :: Nil);
}
def getFirstNotNullResult(fs: List[() => String]): String = {
fs match {
case head::tail =>
val v = head();
if (v != null) return v;
return getFirstNotNullResult(tail);
case Nil => null
}
}
// these would be some complex and slow functions; we only want to execute them if necessary; that is, if f1() returns not null, we don't want to execute f2 nor f3.
def f1(): String = { null }
def f2(): String = { "hello" }
def f3(): String = { null }
}
I like Rex's answer, but your question brings up so many things, I'd like to expand on it, to add:
Using Scala's Option/Some/None classes to clarify what should be returned when no match is found. Your example returned null, Rex's threw an exception. Using Option makes it immediately clear that we will return a match or "None".
Use type parameters so you don't have to operate just on functions that return a String.
Here's the code:
object A extends App {
def getFirstNNWithOption[T](fs: List[() => Option[T]]): Option[T] = fs
.view //allows us to evaluate your functions lazily: only evaluate as many as it takes to find a match
.flatMap(_()) //invoke the function, discarding results that return None
.headOption // take the first element from the view - returns None if empty
def f1 = { println("f1"); None }
def f2 = Some("yay!")
def f3 = { println("f2"); None }
println(getFirstNNWithOption(List(f1 _, f2 _, f3 _)))
}
Note that when this code runs, f2 never prints, demonstrating that, thanks to the .view call, we evaluate the minimum number of functions before returning a match.
Note that callers of this method now must consider the fact that a match might not be found: instead of returning T, we return Option[T]. In our case above, it would return Some("yay"). When all functions return None, the return value would be None. No more NullPointerExceptions when you mistake a null for an actual match!
def getFirstNN(fs: List[() => String]): String = fs.iterator.map(_()).find(_ ne null).get
You'll probably want the type passed into getFirstNotNullResult to be a Stream[String] instead of List[() => String] and construct it something like:
Stream.cons(f1, Stream.cons(f2, Stream.cons(f3, Stream.empty)))
Then getFirstNotNullResult changes to be:
fs.filter(_ != null).headOption
Which will also mean that it should really return Option[String] as well, as you can't guarantee that something will be non-null.
As suggested, the reason why I suggest a Stream is that it only evaluates the "tail" of the Stream on demand. So if getFirstNotNullResult finds that the first element is not null then the second parameter to the first Stream.cons call is never actually executed.
Disclaimer: Before someone says it: yes, I know it's bad style and not encouraged. I'm just doing this to play with Scala and try to learn more about how the type inference system works and how to tweak control flow. I don't intend to use this code in practice.
So: suppose I'm in a rather lengthy function, with lots of successive checks at the beginning, which, if they fail, are all supposed to cause the function to return some other value (not throw), and otherwise return the normal value. I cannot use return in the body of a Function. But can I simulate it? A bit like break is simulated in scala.util.control.Breaks?
I have come up with this:
object TestMain {
case class EarlyReturnThrowable[T](val thrower: EarlyReturn[T], val value: T) extends ControlThrowable
class EarlyReturn[T] {
def earlyReturn(value: T): Nothing = throw new EarlyReturnThrowable[T](this, value)
}
def withEarlyReturn[U](work: EarlyReturn[U] => U): U = {
val myThrower = new EarlyReturn[U]
try work(myThrower)
catch {
case EarlyReturnThrowable(`myThrower`, value) => value.asInstanceOf[U]
}
}
def main(args: Array[String]) {
val g = withEarlyReturn[Int] { block =>
if (!someCondition)
block.earlyReturn(4)
val foo = precomputeSomething
if (!someOtherCondition(foo))
block.earlyReturn(5)
val bar = normalize(foo)
if (!checkBar(bar))
block.earlyReturn(6)
val baz = bazify(bar)
if (!baz.isOK)
block.earlyReturn(7)
// now the actual, interesting part of the computation happens here
// and I would like to keep it non-nested as it is here
foo + bar + baz + 42 // just a dummy here, but in practice this is longer
}
println(g)
}
}
My checks here are obviously dummy, but the main point is that I'd like to avoid something like this, where the actually interesting code ends up being way too nested for my taste:
if (!someCondition) 4 else {
val foo = precomputeSomething
if (!someOtherCondition(foo)) 5 else {
val bar = normalize(foo)
if (!checkBar(bar)) 6 else {
val baz = bazify(bar)
if (!baz.isOK) 7 else {
// actual computation
foo + bar + baz + 42
}
}
}
}
My solution works fine here, and I can return early with 4 as return value if I want. Trouble is, I have to explicitly write the type parameter [Int] — which is a bit of a pain. Is there any way I can get around this?
It's a bit unrelated to your main question, but I think, a more effective approach (that doesn't require throwing an exception) to implement return would involve continuations:
def earlyReturn[T](ret: T): Any #cpsParam[Any, Any] = shift((k: Any => Any) => ret)
def withEarlyReturn[T](f: => T #cpsParam[T, T]): T = reset(f)
def cpsunit: Unit #cps[Any] = ()
def compute(bool: Boolean) = {
val g = withEarlyReturn {
val a = 1
if(bool) earlyReturn(4) else cpsunit
val b = 1
earlyReturn2(4, bool)
val c = 1
if(bool) earlyReturn(4) else cpsunit
a + b + c + 42
}
println(g)
}
The only problem here, is that you have to explicitly use cpsunit.
EDIT1: Yes, earlyReturn(4, cond = !checkOK) can be implemented, but it won't be that general and elegant:
def earlyReturn2[T](ret: T, cond: => Boolean): Any #cpsParam[Any, Any] =
shift((k: Any => Any) => if(cond) ret else k())
k in the snippet above represents the rest of the computation. Depending on the value of cond, we either return the value, or continue the computation.
EDIT2: Any chance we might get rid of cpsunit? The problem here is that shift inside the if statement is not allowed without else. The compiler refuses to convert Unit to Unit #cps[Unit].
I think a custom exception is the right instinct here.
I'm trying to write a performance measurements library for Scala. My idea is to transparently 'mark' sections so that the execution time can be collected. Unfortunately I wasn't able to bend the compiler to my will.
An admittedly contrived example of what I have in mind:
// generate a timing function
val myTimer = mkTimer('myTimer)
// see how the timing function returns the right type depending on the
// type of the function it is passed to it
val act = actor {
loop {
receive {
case 'Int =>
val calc = myTimer { (1 to 100000).sum }
val result = calc + 10 // calc must be Int
self reply (result)
case 'String =>
val calc = myTimer { (1 to 100000).mkString }
val result = calc + " String" // calc must be String
self reply (result)
}
Now, this is the farthest I got:
trait Timing {
def time[T <: Any](name: Symbol)(op: => T) :T = {
val start = System.nanoTime
val result = op
val elapsed = System.nanoTime - start
println(name + ": " + elapsed)
result
}
def mkTimer[T <: Any](name: Symbol) : (() => T) => () => T = {
type c = () => T
time(name)(_ : c)
}
}
Using the time function directly works and the compiler correctly uses the return type of the anonymous function to type the 'time' function:
val bigString = time('timerBigString) {
(1 to 100000).mkString("-")
}
println (bigString)
Great as it seems, this pattern has a number of shortcomings:
forces the user to reuse the same symbol at each invocation
makes it more difficult to do more advanced stuff like predefined project-level timers
does not allow the library to initialize once a data structure for 'timerBigString
So here it comes mkTimer, that would allow me to partially apply the time function and reuse it. I use mkTimer like this:
val myTimer = mkTimer('aTimer)
val myString= myTimer {
(1 to 100000).mkString("-")
}
println (myString)
But I get a compiler error:
error: type mismatch;
found : String
required: () => Nothing
(1 to 100000).mkString("-")
I get the same error if I inline the currying:
val timerBigString = time('timerBigString) _
val bigString = timerBigString {
(1 to 100000).mkString("-")
}
println (bigString)
This works if I do val timerBigString = time('timerBigString) (_: String), but this is not what I want. I'd like to defer typing of the partially applied function until application.
I conclude that the compiler is deciding the return type of the partial function when I first create it, chosing "Nothing" because it can't make a better informed choice.
So I guess what I'm looking for is a sort of late-binding of the partially applied function. Is there any way to do this? Or maybe is there a completely different path I could follow?
Well, thanks for reading this far
-teo
The usual pattern when you want "lazy" generics is to use a class with an apply method
class Timer(name: Symbol) {
def apply[T](op: => T) = time(name)(op)
}
def mkTimer(name: Symbol) = new Timer(name)