How to pass a Function name to a Case-Match statement in Scala - scala

I am a newbie to Scala Programmaing and trying to create a Case-Match or Switch-Case statement which inturn invokes different functions based on the input value.
For example please see the sample code snippet. Hope it explains what i intended to do
def getValue(x: Any):String = x match {
case "Value1"=> Function1(int)
case "Value2"=> Function2(int)
case _ => println("This is an invalid value")
}
def Function1(int) {
Do Something
}
def Function2(int) {
Do Something
}
When I give like this, I am getting an error as shown below :
Error:(26, 34) type mismatch;
found : Unit
required: String
case "Value1"=> Function1(int)
Edited :
Modified the return type of getValue to be a "Unit" instead of "String". Now this error is resolved but I am getting the following error message
Error:(26, 22) forward reference extends over definition of value
spark
case "Value1"=> Function1(int)
Modified code snippet
def getValue(x: Any):Unit = x match {
case "Value1"=> Function1(int)
case "Value2"=> Function2(int)
case _ => println("This is an invalid value")
}
def Function1(int) {
Do Something
}
def Function2(int) {
Do Something
}
I resolved this error by keeping the declaration of spark variable at the end of the code.

The problem is that your Function1 and Function2 (horrible names!) return Unit, and getValue is declared to return a String
A declaration of a function looks like def functionName(args): ReturnType = { ... }
Some parts of this can be omitted, and then defaults are assumed.
In your case, you omitted the ReturnType declaration, and (more importantly) the = sign. When there is no = before the function body, the function will always return Unit. If you want it to return a String, you need to add an = before the body, and make sure that the last statement in the body is indeed a String.
Additionally, the default case clause does not return anything. This does not work, because, again, getValue is declared to return a String. You need to either throw an exception in that case, or think of a default value to return (empty string?) or else use Options, like the other answer suggests.

Function1 and Function2 should return strings. Also, you cannot use println, since the result of it is Unit, in this case, you can throw an exception:
def getValue(x: Any):Unit = x match {
case "Value1"=> function1(1)
case "Value2"=> function2(2)
case _ => throw new IllegalArgumentException("This is an invalid value")
}
def function1(v: Int): String = {
// SOME STUF THAT RETURNS STRING
}
def function2(v: Int): String = {
// SOME STUF THAT RETURNS STRING
}

Related

scala uanpply without parameter

I am a student who studies Scala in korea. I am learning about pattern matching and unapply methods. The thing I am confused about is that Emergency object has a parameter in unapply method. I can't know the reason when I don't put the parameter in the match block.
object Solution {
def main(args: Array[String]) {
val number1 = "010-123-1234"
val number2 = "119"
val number3 = "포도먹은 돼지"
val numberList = List(number1, number2, number3)
for (number <- numberList) {
number match {
case Emergency() => println("긴급전화다")
case Normal(number) => println("일반 전화다" + number)
case _ => println("판단할 수 없습니다.")
}
}
}
}
object Emergency {
def unapply(number: String): Boolean = {
if (number.length == 3 && number.forall(_.isDigit)) true
else false
}
}
object Normal {
def unapply(number: String): Option[Int] = {
try {
Some(number.replaceAll("-", "").toInt)
} catch {
case _: Throwable => None
}
}
}
Notice that return types of to unapply methods are different.
Normal.unapply returns an Option. When you do case Normal(foo), unapply is called, and, if it returns Some(number), the match is successful, and the number is assigned to local variable foo, and if it returns None, match fails.
Emergency.unapply returns a Boolean, so case Emergency() succeeds if it returns true, and fails otherwise, but there is no result to assign in case of success, thus, no "parameter".
The parameter in unapply is the object on which you are matching.
In this case the number String variable is passed to Emergency.unapply, Normal.unapply etc.
This link explains things nicely:
https://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html

Scala - return a Boolean that is neither True or False

I have read up on why using "null" in Scala is not encouraged. But I am having trouble with a method which I would like to return an "empty" Boolean that is neither true or false under certain conditions.
def exampleMethod (query: String): Boolean =
{
var result: Boolean = false
try
{
//This will take the input query and return "true" or "false"
//depending on the state of the database
result = boolQueryResult.evaluate()
return result
}
catch
{
case e: Throwable => logger.info(e.toString)
}
logger.info("Something is wrong! I want to return a boolean with nothing in it!")
return result
}
In the above code, I am using the evaluate() method which will return true or false, and then that value will be returned in the Boolean. But if something goes wrong and the catch block is executed, I want to return a Boolean that is not true or false, to show that there was an error with the input string. In the current version of this method, the Boolean is initialized to "false," which is not ideal because it indicates that evaluate() returned false, not that the catch block was executed. Is there a way to initialize this variable in a way that it will not return "true" or "false" if the exception is thrown?
#bipll is right. Option[Boolean] is the Scala way to do what you want. This is how it's done.
def exampleMethod(query: String): Option[Boolean] =
try {
Some(boolQueryResult.evaluate())
} catch {
case e: Throwable => logger.info(e.toString)
None
}
Although the other answers suggest an Option (returning either Some(true), Some(false), or None, you lose the error message in the case where None is returned. For this reason, I would suggest instead using Try with Either.
An example might look like this:
import scala.util.{Either, Left, Right}
import scala.util.{Failure, Success, Try}
// Notice the return type: we either return the error as a Left(...), or a Right(boolean result)
def exampleMethod (query: String): Either[Throwable, Boolean] = {
// Is this where you meant to use `query`? It's not used in your original post
Try(boolQueryResult.evaluate(query)) match {
case Success(result) => Right(result)
case Failure(exception) => Left(exception)
}
}
This way, the caller of the method can decide what to do. For example, you can pattern match on the result of this method and turn a Left(exception) into None while logging an error:
val queryResult: Option[Boolean] = exampleMethod("bad_query") match {
case Right(result) => Some(result)
case Left(exception) => {
Logger.warn(s"There was an issue with exampleMethod: ${exception.getMessage}", exception)
None
}
}
You can use the Option class:
https://www.scala-lang.org/api/current/scala/Option.html
This is a good case for the Try type
def exampleMethod (query: String): Try[Boolean] =
{
Try
{
//If this throws an exception, it will be caught within the Try as a Failure
// and can be handled later, otherwise the result is stored in a Success
boolQueryResult.evaluate()
}
}
Try can wrap an expression that can fail. It will contain the value in Success, if an exception is thrown, the then the Try will contain that exception instead in a Failure. You can then operate on the value with methods such as map, flatmap and foreach. Even better would be to modify your evaluate method to return a Try or some other appropriate type instead of throwing the exception, but that is not always possible.
return is unneccessary and not recommended in Scala. The result of the last expression in a method will be automatically returned
Another option is to not use Boolean at all. The trouble with Boolean is that it can only hold two states while you need three. Instead of using a wrapper you can create a new ADT that has three states.
sealed trait ExampleResult
case object TrueResult extends ExampleResult
case object FalseResult extends ExampleResult
case object QueryError extends ExampleResult
Because the Trait is sealed, only classes in the same file can extend the trait ExampleResult, so you know that it will always be one of those three options.
You can then write your code like this
def exampleMethod (query: String): ExampleResult =
{
try
{
//This will take the input query and return "true" or "false"
//depending on the state of the database
if(boolQueryResult.evaluate()){
return TrueResult
} else {
return FalseResult
}
}
catch
{
case e: Throwable => logger.info(e.toString)
}
logger.info("Something is wrong! I want to return a boolean with nothing in it!")
return QueryError
}

Use of break in Scala With Return Value

I have the below requirement where I am checking whether a value is greater than 10 or not and based on that I will break, otherwise I will return a String. Below is my code:
import scala.util.control.Breaks._
class BreakInScala {
val breakException = new RuntimeException("Break happened")
def break = throw breakException
def callMyFunc(x: Int): String = breakable(myFunc(x))
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
break
}
}
}
Now what is the happening is that I am getting the error message saying "type mismatch; found : Unit required: String" The reason is :
def breakable(op: => Unit)
But then how I will write a function which can return value as well as break if required?
The Scala compiler can evaluate that a branch throws an exception and not use it to form a minimum bound for the return type, but not if you move the throwing code out in a method: since it can be overridden, the compiler cannot be sure it will actually never return.
Your usage of the Break constructs seems confused: it already provides a break method, there is no need to provide your own, unless you want to throw your exception instead, which would make using Break unnecessary.
You are left with a couple of options then, since I believe usage of Break is unnecessary in your case.
1) Simply throw an exception on failure
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
def usemyFunc(): Unit = {
try {
println("myFunc(11) is " + myFunc(11))
println("myFunc(5) is " + myFunc(5))
} catch {
case e: Throwable => println("myFunc failed with " + e)
}
}
2) Use the Try class (available from Scala 2.10) to return either a value or an exception. This differs from the previous suggestion because it forces the caller to inspect the result and check whether a value is available or not, but makes using the result a bit more cumbersome
import scala.util.Try
def myFunc(x: Int): Try[String] = {
Try {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
}
def useMyFunc(): Unit = {
myFunc match {
case Try.Success(s) => println("myFunc succeded with " + s)
case Try.Failure(e) => println("myFunc failed with " + e)
}
}
3) If the thrown exception isn't relevant, you can use the Option class instead.
You can see how the multiple ways of working with Options relate to each other in
this great cheat sheet.
def myFunc(x: Int): Option[String] = {
if (x > 10) {
Some("I am fine") /* Some(value) creates an Option containing value */
} else {
None /* None represents an Option that has no value */
}
}
/* There are multiple ways to work with Option instances.
One of them is using pattern matching. */
def useMyFunc(): Unit = {
myFunc(10) match {
case Some(s) => println("myFunc succeded with " + s)
case None => println("myFunc failed")
}
}
/* Another one is using the map, flatMap, getOrElse, etc methods.
They usually take a function as a parameter, which is only executed
if some condition is met.
map only runs the received function if the Option contains a value,
and passes said value as a parameter to it. It then takes the result
of the function application, and creates a new Option containing it.
getOrElse checks if the Option contains a value. If it does, it is returned
directly. If it does not, then the result of the function passed to it
is returned instead.
Chaining map and getOrElse is a common idiom meaning roughly 'transform the value
contained in this Option using this code, but if there is no value, return whatever
this other piece of code returns instead'.
*/
def useMyFunc2(): Unit = {
val toPrint = myFunc(10).map{ s =>
"myFunc(10) succeded with " + s
}.getOrElse{
"myFunc(10) failed"
}
/* toPrint now contains a message to be printed, depending on whether myFunc
returned a value or not. The Scala compiler is smart enough to infer that
both code paths return String, and make toPrint a String as well. */
println(toPrint)
}
This is a slightly odd way of doing things (throwing an exception), an alternative way of doing this might be to define a "partial function" (a function which is only defined only a specific subset of it's domain a bit like this:
scala> val partial = new PartialFunction[Int, String] {
| def apply(i : Int) = "some string"
| def isDefinedAt(i : Int) = i < 10
}
partial: PartialFunction[Int, String] = <function1>
Once you've defined the function, you can then "lift" it into an Option of type Int, by doing the following:
scala> val partialLifted = partial.lift
partialOpt: Int => Option[String] = <function1>
Then, if you call the function with a value outside your range, you'll get a "None" as a return value, otherwise you'll get your string return value. This makes it much easier to apply flatMaps/ getOrElse logic to the function without having to throw exceptions all over the place...
scala> partialLifted(45)
res7: Option[String] = None
scala> partialLifted(10)
res8: Option[String] = Some(return string)
IMO, this is a slightly more functional way of doing things...hope it helps

Scala: return default value of a parameterized type

Consider the following function in Scala:
def wrapMyFunction[A](foo: =>A):A = {
try {
foo
}
catch { case e =>
//Return whatever the "empty" or "default" instance of type A would be,
//such as 0, "", None, List(), etc.
}
}
Given the type parameter A, how do I get the "empty" or "default" value of the type A? Is it even possible?
Well, technically, it is not possible, for the simple reason that there isn't such a thing as a "default" value.
The examples you give are all monoidal zeros, so, with Scalaz, you could write this:
def wrapMyFunction[A : Zero](foo: =>A):A = {
...
catch { case e: Exception => // do not catch all throwables!
implicitly[Zero[A]].zero
}
}
Another alternative would be to instantiate a value. You can use a ClassManifest or a ClassTag (Scala 2.10.0) for that. For example:
def wrapMyFunction[A : scala.reflect.ClassTag](foo: => A): A = {
...
catch { case e: Exception =>
implicitly[scala.reflect.ClassTag[A]].runtimeClass.newInstance.asInstanceOf[A]
}
}
That, however, depends on the existence of a parameterless constructor. Using a ClassManifest is pretty much the same.
As Daniel said, it's not generally possible without some type restriction on A. What about changing the method to take a default value, either explicitly or implicitly:
def wrapMyFunction[A](foo: =>A, fallback: =>A):A = ...
or
def wrapMyFunction[A](foo: =>A)(implicit fallback:A):A = ...

Why is a return statement required to allow this while statement to be evaluated properly?

Why is a return statement required to allow this while statement to be
evaluated properly? The following statement allows
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.io.BufferedReader
import java.io.InputStreamReader
trait Closeable {
def close ()
}
trait ManagedCloseable extends Closeable {
def use (code: () => Unit) {
try {
code()
}
finally {
this.close()
}
}
}
class CloseableInputStream (stream: InputStream)
extends InputStream with ManagedCloseable {
def read = stream.read
}
object autoclose extends App {
implicit def inputStreamToClosable (stream: InputStream):
CloseableInputStream = new CloseableInputStream(stream)
override
def main (args: Array[String]) {
val test = new FileInputStream(new File("test.txt"))
test use {
val reader = new BufferedReader(new InputStreamReader(test))
var input: String = reader.readLine
while (input != null) {
println(input)
input = reader.readLine
}
}
}
}
This produces the following error from scalac:
autoclose.scala:40: error: type mismatch;
found : Unit
required: () => Unit
while (input != null) {
^
one error found
It appears that it's attempting to treat the block following the use as an
inline statement rather than a lambda, but I'm not exactly sure why. Adding
return after the while alleviates the error:
test use {
val reader = new BufferedReader(new InputStreamReader(test))
var input: String = reader.readLine
while (input != null) {
println(input)
input = reader.readLine
}
return
}
And the application runs as expected. Can anyone describe to me what is going
on there exactly? This seems as though it should be a bug. It's been
persistent across many versions of Scala though (tested 2.8.0, 2.9.0, 2.9.1)
That's because it's use is declared as () => Unit, so the compiler expects the block you are giving use to return something that satisfies this signature.
It seems that what you want is to turn the entire block into a by-name parameter, to do so change def use (code : () => Unit) to def use (code : => Unit).
() => Unit is the type of a Function0 object, and you've required the use expression to be of that type, which it obviously isn't. => Unit is a by name parameter, which you should use instead.
You might find my answer to this question useful.
To go the heart of the matter, blocks are not lambdas. A block in Scala is a scope delimiter, nothing more.
If you had written
test use { () =>
val reader = new BufferedReader(new InputStreamReader(test))
var input: String = reader.readLine
while (input != null) {
println(input)
input = reader.readLine
}
}
Then you'd have a function (indicated by () =>) which is delimited by the block.
If use had been declared as
def use (code: => Unit) {
Then the syntax you used would work, but not because of any lambda thingy. That syntax indicates the parameter is passed by name, which, roughly speaking, means you'd take the whole expression passed as parameter (ie, the whole block), and substitute it for code inside the body of use. The type of code would be Unit, not a function, but the parameter would not be passed by value.
return or return expr has the type Nothing. You can substitute this for any type, as it never yields a value to the surrounding expression, instead it returns control to the caller.
In your program, it masquerades as the required type () => Unit.
Here's an occasionally convenient use for that (although you might be tarnished as unidiomatic if you use it too often, don't tell anyone you heard this from me!)
def foo(a: Option[Int]): Int = {
val aa: Int = a.getOrElse(return 0)
aa * 2
}
For the record, you should probably write:
def foo(a: Option[Int]): Int =
a.map(_ * 2).getOrElse(0)
You can get an insight into the mind of the compiler by checking the output of scala -Xprint:typer -e <one-liner>. Add -Ytyper-debug if you like sifting through the reams of output!
scala210 -Ytyper-debug -Xprint:typer -e 'def foo: Any = {val x: () => Any = { return }}'
... elided ...
typed return (): Nothing
adapted return (): Nothing to () => Any,