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

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)
})
}

Related

How to pass method of String as callable parameter?

Assume I have a function like:
private def throwUnlessValid[T](func: (String => T)): T = {
try {
func()
} catch {
case _: Throwable => throw new Error(s"""string: "${s}" is not a numeric""")
}
}
And I want to call it like:
implicit val intParser: TryParser[Int] = (s: String) => {
s.trim.isEmpty match {
case true => 0
case false => throwUnlessValid[Int](s.toInt)
}
}
This will fail as the result of s.toInt, which is the Int. Even though I want to pass in the callable function to be called in the other method.
How can I achieve this?
The syntax is _.toInt, which is a shorthand for s => s.toInt (or without type inference, (s: String) => s.toInt). Generally, search for "scala lambdas" for a lot more information on this.
But the problem is that you call func() without passing a string to it. There's also s in throw new Error(s"""string: "${s}" is not a numeric"""); if s is in your scope, you should have func(s) instead. Or maybe you want
private def throwUnlessValid[T](func: () => T): T = { ... }
throwUnlessValid(() => s.toInt)
Using by-name parameters, you can even write
private def throwUnlessValid[T](func: => T): T = { ... }
throwUnlessValid(s.toInt)
You can pass a callable function by using _.toInt, which is shorthand for the function x => x.toInt.
However this isn't going to help because your throwUnlessValid function doesn't work, for two reasons:
You don't give a String argument to func
You attempt to print s which is not a visible to this function
You have two choices:
Pass s to throwUnlessValid and give it to func
Make func into a => T parameter and remove the references to s from the Error string.
You need to fix your throwUnlessValid function.
Currently it accepts as argument a function which takes a string as argument:
throwUnlessValid[T](func: (String => T))
However then you are trying to call it without any argument: func() which obviously won't work. Besides that you also have reference to nonexisting variable s: ${s} which also should produce error.
In order to fix the throwUnlessValid function you can pass toInt as by-name argument:
private def throwUnlessValid[T](code: => T): T = {
try {
code
} catch {
case ex: Throwable => throw new Error(s"""string: "${ex.getMessage}" is not a numeric""")
}
}
In other words you don't need to change your existing intParser implementation (including throwUnlessValid[Int](s.toInt) call), you only need to change implementation of throwUnlessValid).
If i understant correctly, you are looking for this.
Actually the problem is that you are not passing string to your function (func) hence it's not working.
import scala.util.{Failure, Success, Try}
object Solution1 extends App {
private def throwUnlessValid[T](func: (String => T)): T = {
Try {
func("1")
} match {
case Success(_) => //do Something which return T
case Failure(ex) => throw new Error(s"""string: "${ex}" is not a numeric""")
}
}
implicit val intParser: String => Int = (s: String) => {
if (s.trim.isEmpty) {
0
} else {
throwUnlessValid[Int](_ => s.toInt)
}
}
}

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

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").

scala returns doesn't conform to required S_

I got the error
found : scala.concurrent.Future[Option[models.ProcessTemplatesModel]]
required: Option[models.ProcessTemplatesModel]
My function is below
def createCopyOfProcessTemplate(processTemplateId: Int): Future[Option[ProcessTemplatesModel]] = {
val action = processTemplates.filter(_.id === processTemplateId).result.map(_.headOption)
val result: Future[Option[ProcessTemplatesModel]] = db.run(action)
result.map { case (result) =>
result match {
case Some(r) => {
var copy = (processTemplates returning processTemplates.map(_.id)) += ProcessTemplatesModel(None, "[Copy of] " + r.title, r.version, r.createdat, r.updatedat, r.deadline, r.status, r.comment, Some(false), r.checkedat, Some(false), r.approvedat, false, r.approveprocess, r.trainingsprocess)
val composedAction = copy.flatMap { id =>
processTemplates.filter(_.id === id).result.headOption
}
db.run(composedAction)
}
}
}
}
what is my problem in this case?
edit:
my controller function looks like this:
def createCopyOfProcessTemplate(processTemplateId: Int) = Action.async {
processTemplateDTO.createCopyOfProcessTemplate(processTemplateId).map { process =>
Ok(Json.toJson(process))
}
}
Is there my failure?
According to the your code - there are the following issues:
You use two db.run which return futures, but inner future will
not complete. For resolving it you should compose futures with
flatMap or for-comprehension.
You use only one partial-function case Some(_) => for pattern matching
and don't handle another value None.
You can use only one db.run and actions composition.
Your code can be like as:
def createCopyOfProcessTemplate(processTemplateId: Int): Future[Option[ProcessTemplatesModel]] = {
val action = processTemplates.filter(...).result.map(_.headOption)
val composedAction = action.flatMap {
case Some(r) =>
val copyAction = (processTemplates returning processTemplates...)
copyAction.flatMap { id =>
processTemplates.filter(_.id === id).result.headOption
}
case _ =>
DBIO.successful(None) // issue #2 has been resolved here
}
db.run(composedAction) // issue #3 has been resolved here
}
We get rid of issue #1 (because we use actions composition).

catch a string in boolean option

How do I prevent error when someone does not choose one of the options in scala. This is using Map to get options and I tried to implement Try and catch blocks in case options but it does not work. I'm not sure if this is the right way to do it, if there is any other way let me know. The error is Exception in thread "main" java.lang.NumberFormatException: For input string: "e".
object main extends menu {
def main(args: Array[String]): Unit = {
var opt = 0
do { opt = readOption }
while (menu(opt))
}
}
class menu extends database {
def menu(option: Int): Boolean = try {
actionMap.get(option) match {
case Some(a) => a()
case None => println("That didn't work.")
false
}
} catch {
case _: NumberFormatException => true
}
val actionMap = Map[Int, () => Boolean](1 -> cWords, 2 -> cCharacters, 3 -> exit)
def readOption: Int = {
println(
"""|Please select one of the following:
| 1 - Count Words
| 2 - Count Characters in words
| 3 - quit""".stripMargin)
StdIn.readInt()
}
Use scala.util.Try on readInt(),
import scala.io._
import scala.util._
Try(StdIn.readInt()).toOption
// returns Some(123) for input 123
Try(StdIn.readInt()).toOption
// returns None for input 1a3
Thus readOption delivers Option[Int]. Then
def menu(option: Option[Int]): Boolean = option match {
case Some(a) => actionMap(a)()
case None => println("Try again..."); false
}
Note
A more concise version of main,
def main(args: Array[String]): Unit = while (menu(readOption)) ()
Namely, while menu is true do Unit (or () ).
Here is some working implementation:
import scala.io.StdIn
import scala.util.Try
object Main extends Menu with App {
while (menu(readChoice)) ()
}
class Menu {
val actionMap = Map[Int, () => Boolean](1 -> (() => true), 2 -> (() => true), 3 -> (() => false))
def menu(choice: Option[Int]): Boolean = {
choice.flatMap(actionMap.get)
.map(action => action())
.getOrElse({ println("That didn't work."); false })
}
def readChoice: Option[Int] = {
println(
"""|Please select one of the following:
| 1 - Count Words
| 2 - Count Characters in words
| 3 - quit""".stripMargin)
Try(StdIn.readInt).toOption
}
}
For the first, you can mixin App trait to skip main method boilerplate.
You can simplify your do while loop like this, it has to do nothing inside so you either need some expression or block. A Unit value can be your expression that does nothing.
In scala we name classes using camel case, starting with capital letter.
As readInt throws whenever input is wrong you can catch that using Try, that will return Success(result) of Failure(exception) and change this result to an Option to discard the exception.
what happens in menu is shorthand for
choice match {
case Some(number) =>
actionMap.get(number) match {
case Some(action) =>
action()
case None =>
println("That didn't work.")
false
}
case None =>
println("That didn't work.")
false
}
And could be as well written with for
(for {
number <- choice
action <- actionMap.get(number)
} yield {
action()
}) getOrElse {
println("That didn't work.")
false
}
On as sidenote, you named choice of user an "option" which unfortunately is also a scala class used here extensively, I renamed the variables to avoid confusion.
I would make readOption return a Try[Int], (a Try surrounding StdIn.readInt()), then deal with the possible cases in the menu function