scala store method in set with possibility of removal - scala

Here's some test code to demonstrate the problem:
import scala.collection.mutable.HashSet
import scala.collection.mutable.Set
object Test extends App
{
val set: Set[Int => Boolean] = new HashSet()
def test(i: Int): Boolean = {
false
}
Console.println(set.add(test)) // true
Console.println(set.remove(test)) // false
Console.println(set.add(test _)) // true
Console.println(set.remove(test _)) // false
}
What options are there for making this work?
Edit: I also want this to support lambdas.

Every time you perform "add" or "remove" operation Scala compiler creates new AbstractFunction1.mcZI.sp object instance:
Console..MODULE$.println(BoxesRunTime.boxToBoolean(set().add(
new AbstractFunction1.mcZI.sp() {
public final boolean apply(int i) { return apply$mcZI$sp(i); }
public boolean apply$mcZI$sp(int i) { return Test..MODULE$.test(i); }
})));
As I understand this object instance doesn't contain information about enclosing object and 'test' method which can be used for 'hashCode' and 'equals' methods.
I think as a workaround you may consider this:
import scala.collection.mutable.HashSet
import scala.collection.mutable.Set
object Test extends App
{
val set: Set[Int => Boolean] = new HashSet()
def test(i: Int): Boolean = {
false
}
val testFunc: Function1[Int, Boolean] = test
Console.println(set.add(testFunc)) // true
Console.println(set.remove(testFunc)) // true
val testPartFunc = test _
Console.println(set.add(testPartFunc)) // true
Console.println(set.remove(testPartFunc)) // true
}

If instead of passing methods you pass function it works:
val testFun: Int => Boolean = i => i > 10
set.add(testFun) // true
set.remove(testFun) // true
it will also work for anonymous functions:
set.add { _ => false }
but then I don't know how you would like to remove such function from the set.

Related

MVar tryPut returns true and isEmpty also returns true

I wrote simple callback(handler) function which i pass to async api and i want to wait for result:
object Handlers {
val logger: Logger = Logger("Handlers")
implicit val cs: ContextShift[IO] =
IO.contextShift(ExecutionContext.Implicits.global)
class DefaultHandler[A] {
val response: IO[MVar[IO, A]] = MVar.empty[IO, A]
def onResult(obj: Any): Unit = {
obj match {
case obj: A =>
println(response.flatMap(_.tryPut(obj)).unsafeRunSync())
println(response.flatMap(_.isEmpty).unsafeRunSync())
case _ => logger.error("Wrong expected type")
}
}
def getResponse: A = {
response.flatMap(_.take).unsafeRunSync()
}
}
But for some reason both tryPut and isEmpty(when i'd manually call onResult method) returns true, therefore when i calling getResponse it sleeps forever.
This is the my test:
class HandlersTest extends FunSuite {
test("DefaultHandler.test") {
val handler = new DefaultHandler[Int]
handler.onResult(3)
val response = handler.getResponse
assert(response != 0)
}
}
Can somebody explain why tryPut returns true, but nothing puts. And what is the right way to use Mvar/channels in scala?
IO[X] means that you have the recipe to create some X. So on your example, yuo are putting in one MVar and then asking in another.
Here is how I would do it.
object Handlers {
trait DefaultHandler[A] {
def onResult(obj: Any): IO[Unit]
def getResponse: IO[A]
}
object DefaultHandler {
def apply[A : ClassTag]: IO[DefaultHandler[A]] =
MVar.empty[IO, A].map { response =>
new DefaultHandler[A] {
override def onResult(obj: Any): IO[Unit] = obj match {
case obj: A =>
for {
r1 <- response.tryPut(obj)
_ <- IO(println(r1))
r2 <- response.isEmpty
_ <- IO(println(r2))
} yield ()
case _ =>
IO(logger.error("Wrong expected type"))
}
override def getResponse: IO[A] =
response.take
}
}
}
}
The "unsafe" is sort of a hint, but every time you call unsafeRunSync, you should basically think of it as an entire new universe. Before you make the call, you can only describe instructions for what will happen, you can't actually change anything. During the call is when all the changes occur. Once the call completes, that universe is destroyed, and you can read the result but no longer change anything. What happens in one unsafeRunSync universe doesn't affect another.
You need to call it exactly once in your test code. That means your test code needs to look something like:
val test = for {
handler <- TestHandler.DefaultHandler[Int]
_ <- handler.onResult(3)
response <- handler.getResponse
} yield response
assert test.unsafeRunSync() == 3
Note this doesn't really buy you much over just using the MVar directly. I think you're trying to mix side effects inside IO and outside it, but that doesn't work. All the side effects need to be inside.

How i get Boolean From a Future[Settings]

I have a Future [ProductSettings] which is returned from getProductSettingsMethod. Now I need the true or false from the clearedCanLoad field
def getEmployerProductSettingsQuery(employer: Employer): DBIOAction[ProductSettings, NoStream, Effect.Read] = {
val productSettingsQ = productSettingsQuery.filter(_.employerId === employer.id).result
productSettingsQ.map(_.headOrServerException(s"Could not find ProductSettings for employer ${employer.id}"))
}
def getEmployerProductSettings(employer: Employer): Future[ProductSettings] =
db.run(getEmployerProductSettingsQuery(employer))
I tried .map, filter, flatMap etc. but none is working
def cleared (employer : Employer) :Boolean = {
val f : Future[ProductSettings] =
getEmployerProductSettings(employer)
val iscleared: Boolean = f.filter { x =>
x.clearedCanLoadSpenditCards match {
case true =>
true
case false =>
false
}
}
}
This is not working also not working is filter
val f : Future[ProductSettings] = getEmployerProductSettings(employer)
val iscleared = f .
.filter(_.clearedCanLoadSpenditCards.equals(true)).equals(true)
case class ProductSettings(id: Long,
employerId: Long,
enableCard: Boolean,
enableLt: Boolean,
enableLtRefundDays: Boolean,
enableLtConversion: Boolean,
enableLtOPayment: Boolean,
clearedCanLoad: Boolean,
clearedAt:Option[LocalDateTime]) {
equals true should return boolean but i get a Future[Boolean] back. How can i extract an Boolean
The main purpose of the Future is to execute code asynchronously. Blocking the future to get the value from it defeats the purpose of it. But if you really need the cleared method to return Boolean you can block the future until its value is resolved.
You can achieve this by using Await:
import scala.concurrent.duration._
val result: ProductSettings = scala.concurrent.Await.result(f, 1 second)
This will wait for the future be resolved. If a second passes and f is still not resolved this will throw a TimeoutException.
scala.concurrent.Await#result

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

Determine if the field of a case class is a case class

I'm trying to figure out if a member field in any given case class is also a case class. Taken from this answer, given an instance or an object, I can pass it along and determine if it's a case class:
def isCaseClass(v: Any): Boolean = {
import reflect.runtime.universe._
val typeMirror = runtimeMirror(v.getClass.getClassLoader)
val instanceMirror = typeMirror.reflect(v)
val symbol = instanceMirror.symbol
symbol.isCaseClass
}
However, what I'd like, is to take a case class, extract all of its member fields, and find out which ones are case classes themselves. Something in this manner:
def innerCaseClasses[A](parentCaseClass:A): List[Class[_]] = {
val nestedCaseClasses = ListBuffer[Class[_]]()
val fields = parentCaseClass.getClass.getDeclaredFields
fields.foreach(field => {
if (??? /*field is case class */ ) {
nestedCaseClasses += field.getType
}
})
nestedCaseClasses.toList
}
I thought maybe I could extract the fields, their classes, and use reflection to instantiate a new instance of that member field as its own class. I'm not 100% how to do that, and it seems like perhaps there's an easier way. Is there?
Ah! I've figured it out (simplified the function which tells the determination):
import reflect.runtime.universe._
case class MyThing(str:String, num:Int)
case class WithMyThing(name:String, aThing:MyThing)
val childThing = MyThing("Neat" , 293923)
val parentCaseClass = WithMyThing("Nate", childThing)
def isCaseClass(v: Any): Boolean = {
val typeMirror = runtimeMirror(v.getClass.getClassLoader)
val instanceMirror = typeMirror.reflect(v)
val symbol = instanceMirror.symbol
symbol.isCaseClass
}
def innerCaseClasses[A](parentCaseClass:A): Unit = {
val fields = parentCaseClass.asInstanceOf[Product].productIterator
fields.foreach(field => {
println(s"Field: ${field.getClass.getSimpleName} isCaseClass? " + isCaseClass(field))
})
}
innerCaseClasses(parentCaseClass)
printout:
Field: String isCaseClass? false
Field: MyThing isCaseClass? true

Why is the Binding.scala router not reevaluated?

I'm trying to build a generic router for a personal project by Binding.scala.
I've defined a PageState trait
sealed trait WhistState {
def text: String
def hash: String
def render: Binding[Node]
}
with a number of subclasses for each route type. I've then trying to create a router, which based on the hash chooses the correct class.
object Router {
val defaultState: WhistState = DefaultState("Games")
val allStates: Vector[WhistState] = Vector(defaultState)
val route: Route.Hash[WhistState] = Route.Hash[WhistState](defaultState)(new Route.Format[WhistState] {
override def unapply(hashText: String): Option[WhistState] = allStates.find(_.hash == window.location.hash)
override def apply(state: WhistState): String = state.hash
})
route.watch()
}
And then I'm my application classes im trying to use this
object Application {
import example.route.Router._
#dom
def render: Binding[Node] = {
for (hash <- route.state.bind.hash) yield println("hash: " + hash)
route.state.bind match {
case default: WhistState => println("default"); default.render.bind
case _ => println("none"); <div>NotFound</div>
}
}
def main(args: Array[String]): Unit = {
dom.render(document.querySelector("#content"), render)
}
}
I've would expect that changing the hash would force a reevaluation of route.state.bind match ... expression.
Any idea to why this doesn't work?
Best regards
route.state is only changed when unapply returns a Some(newState) and newState does not equal to the previous state.
In your case, unapply always returns Some(defaultState) or None. That's why route.state never changes.