I am confused about this sentence "If the identifier is bound to a thunk or a text". How can I check that? I have code where identifier is an extension of expression, while thunk and text are of type values. I have this code here but when I run it, I get a stackoverflow error.
package expression
import context._
import value._
case class Identifier(val name: String) extends Expression{
override def toString = name
/*def execute(env: Environment): Value = {
env(this)
}*/
def execute(env:Environment): Value =
{
val envThis = env(this)//wrong here
println(this.getClass)
if(envThis.isInstanceOf[Text])
{
//println(envThis.asInstanceOf[Text].body.getClass) identifier class type
envThis.asInstanceOf[Text].body.execute(env) //wrong here
}
else if(envThis.isInstanceOf[Thunk])
{
envThis.asInstanceOf[Thunk].apply()
}
else
{
env(this)
}
}
}
It is hard to tell without knowing more about the context, but perhaps you should be looking up the name of the identifier in the environment, rather than the Identifier instance?
It would certainly be much clearer to use a match statement, something like this:
def execute(env: Environment): Value =
{
val envThis = env(name)
println(this.getClass)
envThis match {
case text: Text =>
text.body.execute(env)
case thunk: Thunk =>
thunk()
case other =>
other
}
}
Related
I have a series of inherited classes,with some more methods than the base class. Like this:
class Animal
{
var Name: String
}
class Fish extends Animal
{
def swim()
{
println("I'm a Fish and i'm swimming!");
}
}
class Turtle extends Animal
{
def swim()
{
println("I'm a Turtle and i'm swimming!");
}
}
I would like to use the type match pattern to a generic Animal class, to recognize the exact type and apply the swim() method if it can, like this:
myAnimal match {
case m:Fish => m.Swim()
case m:Turtle => m.Swim()
case _: => doSomethingElse()
}
I would like to write it in an elegant way, avoiding to repeat continuously the lines.
I know that I can do this:
myAnimal match {
case (_:Fish | _:Turtle) => println("I can do this!")
}
And I know, as I wrote above, that I can do:
myAnimal match {
case m:Fish => m.swim()
}
but, I can't put them in or, like this
myAnimal match {
case (m:Fish | m:Turtle) => m.swim() //ERROR (cannot recognize swim() method)
//Not even this
case m # (_:Fish | _:Turtle) => m.swim() //ERROR (cannot recognize swim() method)
case _: => doSomethingElse()
}
A good solution would be to insert an intermediate class, like AnimalsThatCanSwim that extend Animals. This solution should be the last option, because I have to avoid changing the extended classes.
You can use structural types combined with an extractor that uses reflection to check if your object has a swim method. Thanks to Mateusz Kubuszok and Dmytro Mitin, I now have a solution that seems to work.
Use like this:
myAnimal match {
case CanSwim(m) => m.swim()
case _ => println("Boohoo, I can't swim!")
}
The other stuff:
import scala.reflect.runtime.universe._
type CanSwim = { def swim(): Unit }
object CanSwim {
def unapply(arg: Any): Option[CanSwim] = {
try {
var res: Option[CanSwim] = None
for (symb <- runtimeMirror(arg.getClass.getClassLoader)
.reflect(arg)
.symbol
.info
.member(TermName("swim")) //get all methods named swim
.asTerm
.alternatives) { //alternatives because it might be overloaded
if (symb.isMethod) {
val msymb = symb.asMethod
//Check if the signature matches (Returns Unit and has 1 empty parameter list)
if (msymb.returnType =:= typeOf[Unit] && msymb.paramLists == List(List()))
res = Some(arg.asInstanceOf[CanSwim])
}
}
res
} catch {
case _ => None
//Might want to change this, but I don't think it's necessary to handle or throw exceptions
//If it failed, it probably means it can't swim
}
}
}
Link to Scastie
However, I really wouldn't recommend it. It's probably just easier to refactor your code.
<script src="https://scastie.scala-lang.org/gFBe7jTQQiW3WnPVTJoFPw.js"></script>
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
}
I have a simple flash implementation for use with Jersey that looks like this:
#PostConstruct def before { flash.rotateIn }
#PreDestroy def after { flash.rotateOut }
object flash {
val KeyNow = "local.flash.now"
val KeyNext = "local.flash.next"
// case class Wrapper(wrapped: Map[String, Seq[String]])
case class Wrapper(wrapped: String)
def rotateIn {
for {
session <- Option(request.getSession(false))
obj <- Option(session.getAttribute(KeyNext))
} {
request.setAttribute(KeyNow, obj)
session.removeAttribute(KeyNext)
}
}
def rotateOut {
for (obj <- Option(request.getAttribute(KeyNext))) {
request.getSession.setAttribute(KeyNext, obj)
}
}
def now = Option(request.getAttribute(KeyNow)) match {
case Some(x: Wrapper) => x.wrapped
case Some(x) if x.isInstanceOf[Wrapper] => "WHAT"
case _ => "NOPE"
}
def next(value: String) {
request.setAttribute(KeyNext, Wrapper(value))
}
}
I have simplified it here somewhat, but it lets me set a value for flash with flash.next and read the current flash value with flash.now.
The weird thing is that my now value is always "WHAT". If I do something similar in my REPL, I don't have the same issues:
val req = new org.springframework.mock.web.MockHttpServletRequest
val res = req.getSession
res.setAttribute("foo", Wrapper("foo"))
req.setAttribute("foo", res.getAttribute("foo"))
// Is not None
Option(req.getAttribute("foo")).collect { case x: Wrapper => x }
Am I missing something obvious?
EDIT
I've added a minimal example webapp replicating this issue at https://github.com/kardeiz/sc-issue-20160229.
I tried your example. Check my answer for your other question for details how pattern matching works in this case.
In short, as you Wrapper is an inner class, patter matching also checks the "outer class" reference. It seems that depending on the application server implementation Router.flash can be different instance for each request, so pattern matching fails.
Simple fix for that is to make Wrapper top-level class, so it doesn't have reference to any other class.
I want to verify if the business logic passes the expected user object to dao, but I can't figure how to write an custom argument matcher for it.
"user" should {
"be saved" in {
val dao = new UserDao()
dao.save(any[User]) returns mock[User]
runMyBusinessLogic();
val expectedUser = new User("Freewind", 123.23234)
there was one(dao).save(mymatcher(expectedUser));
}
}
The User class:
case class User(name:String, random: Double)
Which contains a double field, that I need to do some special comparison for it.
The mymatcher is the matcher I want to define:
def mymatcher(expected: User) = ??? {
// compare `name` and `random`
}
But I don't know how to do it in spec2, and can't find any useful documents. Any helps?
I use beLike matcher. Like this:
one(daoMock).insert { beLike[MyEntity] { case t:Entity => {
t.summary mustEqual "Summary"
t.description mustEqual "Description"
}}}
Inside beLike matcher you could use ordinary value matchers.
For mockito matching I used Matchers.argThat
import org.mockito.Matchers
import org.mockito.Mockito.verify
verify(service).methodCall(Matchers.argThat({
case CaseClass("const", arg2) =>
arg2 == expected
case _ => false
}))
Using the Play! Framework 1.2.4. I've got a nifty trait that checks an API key and HTTPS, but if I want to access the account associated with that key and reference it in my controller, it throws a type mismatch; found : java.lang.Object required: Long
So here's my API controller (incomplete):
object API extends Controller with Squeryl with SecureAPI {
import views.API._
def job(param:String) = {
val Job = models.Job
param match {
case "new" => Job.createFromParams(params,thisAccount) //thisAccount comes from the trait
case "update" =>
case "get" =>
case "list" =>
}
}
}
and the secure trait:
trait SecureAPI {
self:Controller =>
#Before
def checkSecurity(key:String) = {
if(!self.request.secure.booleanValue) {
Redirect("https://" + request.host + request.url);
} else {
models.Account.getByKey(key) match {
case Some(account) => {
renderArgs += "account" -> account.id
Continue
}
case _ => Forbidden("Key is not authorized.")
}
}
}
def thisAccount = renderArgs("account").get
}
How would I properly access thisAccount? Thanks
Your problem is simply that renderArgs is only declared to return an Object from its get call (which is fair enough because it could be just about anything).
Consequently the inferred type of your thisAccount method will be () => Object.
You'll need to cast the returned type into a Long, something like (though perhaps with some error-checking):
def thisAccount = renderArgs("account").get.asInstanceOf[Long]