scala uanpply without parameter - scala

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

Related

What is the Scala way of using guard clauses to exit a function early?

I am wondering if there is a idiomatic way of using guard clauses to leave a method early if a condition is met.
In other languages, I would do something like this:
def myFunction(): Either[String, String] = {
if (someErrorCondition)
return Left("error msg")
// Rest of the code
}
However, this seems wrong to me, since using return does not seem to be the idiomatic way of doing it. I have considered this:
def myFunction(): Either[String, String] = {
if (someErrorCondition)
Left("error msg")
else
// Rest of the code
}
But it is ugly and would imply many if-else where multiple guards are needed.
Any suggestions on how to do this properly?
Seconding others, IMHO, the idea that conditional expression are not idiomatic is a fallacy, hence the following seem OK to me
if (errorCondition1) Left("error msg 1")
else if (errorCondition2) Left("error msg 2")
else Right(42)
The idea of early returns or short-circuiting is inherent in for-comprehensions so here is an unconventional approach which converts Booleans to Eithers where true converts to Left via extension method
implicit class GuardToLeft(p: Boolean) {
def toGuard[L](left: => L): Either[L, Unit] =
if (p) Left(left) else Right(())
}
so now we can simulate traditional early return guards like so
for {
_ <- errorCondition1.toGuard("error msg 1")
_ <- errorCondition2.toGuard("error msg 2")
} yield {
41 + 1
}
The FP way is to use a type which has some form of error handling build in, e.g. Either.
Let's say that String is your error format. Then you can return early ("circuit break") using flatMaps - for Either Left is the error format, and Right is used for threading ongoing computation:
import scala.util._
def sqrtFromString(argument: String): Either[String, Double] = {
val start: Either[String, String] = Right(argument) // just for upcasting Right to Either
start
// if start is Right, then value inside it will be passed as string variable
// Right will continue computation
// Left will circuit break them
.flatMap { string =>
Try(string.toInt) match {
case Success(int) => Right(int)
case Failure(_) => Left("Not integer")
}
}
// if so far it is still Right, the value inside will be passed as int variable
.flatMap { int =>
if (int > 0) Right(int)
else Left("Negative int")
}
// if Right, it still will be Right - no ability to circuit break using map
.map { int =>
Math.sqrt(int)
}
}
Since map and flatMap are handled by for comprehension you could rewrite it to:
import scala.util._
def sqrtFromString(argument: String): Either[String, Double] =
for {
string <- (Right(argument): Either[String, String])
int <- Try(string.toInt) match {
case Success(int) => Right(int)
case Failure(_) => Left("Not integer")
}
positive <- {
if (int > 0) Right(int)
else Left("Negative int")
}
} yield Math.sqrt(positive)
which could be further shortened to:
def sqrtFromString(argument: String): Either[String, Double] =
for {
string <- Right(argument)
int <- Try(string.toInt).toEither.left.map(_ => "Not integer")
_ <- (if (int > 0) Right(()) else Left("Negative int"))
} yield Math.sqrt(int)
The same principle works whether you are using Try or Future (they are like sync and async Either but with Left hardcoded to Throwable and build-in exception catching), IO, Task, ZIO, etc.

Scala missing parameter type for expanded function The argument types of an anonymous function must be fully known. (SLS 8.5)

I have the following snippet I need to complete for an assignment. To fulfill the asignment I have to correctly replace the comments /*fulfill ...*/. However I tried my best and I am still getting an
missing parameter type for expanded function The argument types of an anonymous function must be fully known. (SLS 8.5) error.
I found similar questions related to this error. However I could not derive a solution for my paticular problem of those answers.
So the target is to check whether the events fulfill the properties.
I am glad for every hint.
This is the code I need to complete:
import scala.collection.mutable.MutableList
abstract class Event
case class Command(cmdName: String) extends Event
case class Succeed(cmdName: String) extends Event
case class Fail(cmdName: String) extends Event
class Property(val name: String, val func: () => Boolean)
class Monitor[T] {
val properties = MutableList.empty[Property]
// (propName: String)(formula: => Boolean) was inserted by me
def property(propName: String)(formula: => Boolean) /* fulfill declaration here */ {
properties += new Property(propName, formula _)
}
var eventsToBeProcessed = List[T]()
def check(events: List[T]) {
for (prop <- properties) {
eventsToBeProcessed = events
println(prop.func())
}
}
def require(func: PartialFunction[T, Boolean]):Boolean = {
/* Fulfill body */
// This is what I came up with and what throws the compilation error
// case event:T => if (func.isDefinedAt(event)) Some(func(event)) else None
// Edit 1: Now I tried this but it prints that properties evaluate to false
var result = true
for (event <- eventsToBeProcessed){
if (func.isDefinedAt(event)){
result = result && func(event)
}
}
return result
}
}
class EventMonitor extends Monitor[Event] {
property("The first command should succeed or fail before it is received again") {
require {
case Command(c) =>
require {
case Succeed(`c`) => true
case Fail(`c`) => true
case Command(`c`) => false
}
}
}
property("The first command should not get two results") {
require {
case Succeed(c) =>
require {
case Succeed(`c`) => false
case Fail(`c`) => false
case Command(`c`) => true
}
case Fail(c) =>
require {
case Succeed(`c`) => false
case Fail(`c`) => false
case Command(`c`) => true
}
}
}
property("The first command should succeed") {
/* Add a property definition here which requires that the first command does not fail.
* It should yield OK with the events listed in the main method.
*/
// This is what I came up with
require{
case Command(c) =>
require{
case Succeed(`c`)=> true
case Fail(`c`) => false
}
}
}
}
object Checker {
def main(args: Array[String]) {
val events = List(
Command("take_picture"),
Command("get_position"),
Succeed("take_picture"),
Fail("take_picture")
)
val monitor = new EventMonitor
monitor.check(events)
// Desired output should be "true false true"
}
}
You wrote require function that returns T => Option[Boolean] intead of Boolean.
You should rewrite it on something like this:
def require(func: PartialFunction[T, Boolean]):Boolean = {
val left = eventsToBeProcessed.dropWhile(!func.isDefinedAt(_))
left.headOption.forall(head => {
eventsToBeProcessed = left.tail
func(head)
})
}

Possible ways to check if a value exists in a sequence scala

case class dummy(val prop:Seq[Test])
case class Test(val s :String)
case class Result(val s :String)
def myFunc:Result = {
val s = "11,22,33"
val t = Test(s)
val list = dummy(Seq(t))
val code = Option("25")
val result = code.exists(p => {
list.prop.exists(d => d.s.split(",").contains(p))
})
if (result) {
Result("found")
} else {
Result("Not Found")
}
}
I am calling function myFunc, but instead of evaluating a boolean using if/else construct.
Any possible ways to avoid using If else construct
There is nothing wrong with using the if/else, but you could do this:
code
.flatMap(c => list.prop.find(_.s.split(",").contains(c)))
.map(_ => Result("Found")).getOrElse(Result("Not Found"))
The idea here is that instead of returning a Boolean at each stage we are passing an Option along. Then at the end if the Option is defined we can map that into a Result("Found"), and if it is not defined the .getOrElse will return a Result("Not Found").

How to pass a Function name to a Case-Match statement in 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
}

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