How is the equals function defined for a 'function' type:
val javaVersion = () => sys.props("java.version")
val anonfun0 = new Function0[String] {
def apply(): String = sys.props("java.version")
}
assert(javaVersion() == anonfun0()) // This works!
It works because you're comparing the result and not the functions. Remove the () and it should return false.
Your assertion is not testing the equality of the functions , but the value they return.
Note the difference between:
assert(javaVersion() == anonfun0()) // equality of return values
and:
assert(javaVersion == anonfun0) // equality of vals
Your assertion returns true because both functions return the result of sys.props("java.version").
Related
def checkHappynumber(n: Int): Boolean = {
val set = scala.collection.mutable.HashSet[Int]()
var num: Int = n
while(num != 1) {
var newnum: Int = 0
while (num != 0) {
newnum += (num % 10) * (num % 10)
num /= 10
}
if(!set.add(newnum)){
return false;
}
num = newnum
}
return true
}
What's "!" role in there? the if(!set.add(newnum))? I know that hashset can't have repeated value. The only question is how "!" works here.
In Scala, !foo is syntactic sugar for foo.unary_!. In other words, !foo is just calling the method named unary_! just like foo.bar is calling the method bar. There is nothing special about unary_! in that regard.
In your case, this means that !set.add(newnum) is just syntactic sugar for set.add(newnum).unary_!.
Like with all other methods, if you want to know what the method does, you first need to find where it is defined. In this case, the return type of scala.collection.mutable.Set.add is scala.Boolean which means the specific method being called is scala.Boolean.unary_!, which is defined like this:
def unary_!: Boolean
Negates a Boolean expression.
!a results in false if and only if a evaluates to true and
!a results in true if and only if a evaluates to false.
Returns: the negated expression
! is a negation operator (!true is false, !false is true). HashSet.add returns true if element was not present in the set (successfully added), false otherwise. This code returns false if element was already present in the hashset (trying to add it for the second time).
Here's documentation of add method.
i would like to resolve a problem,
i've done this code and i have this output
found : Unit
[error] required: Boolean
[error] for (data <- category(i)) {
i have to return : (List[String], (List[String], (List[String])
i choose to use the filter method for to realise a compact code.
i don't understand why it doesn't work. Why the code doesn't return a bool but a Unit.
I would like this method to return true if at least 1 element of the list starts with x otherwise the method must return false.
Thanks
def classifiedColumns(columnNames: List[String]): (List[Column], List[Column], List[Column]) = {
val category = List(
List("t01", "t03", "t11", "t1801", "t1803"), // 1
List("t05", "t1805"), // 2
List("t02", "t04", "t06", "t07", "t08", "t09", "t10", "t12", "t13", "t14", "t15", "t16", "t18")) // 3
def get_info(x: String, i: Int, category: List[List[String]]): Boolean = {
for (data <- category(i)) {
if (data.startsWith(x)) true
else false
}
}
(columnNames.filter(x => get_info(x, 1, category)).map(column),
columnNames.filter(x => get_info(x, 2, category)).map(column),
columnNames.filter(x => get_info(x, 3, category)).map(column))
}
classifiedColumns(List("t0201", "t0408", "t0600084"))
Your use of for does not behave as you expect. You're using this for-comprehension:
for (data <- category(i)) {
if (data.startsWith(x)) true
else false
}
This expression "desugars" into (i.e. is shorthand for):
category(i).foreach(data => {
if (data.startsWith(x)) true
else false
})
foreach returns Unit, and therefore the type of this expression (and the type returned from your get_info method, this being the body of the method) is Unit.
It's unclear what you expect to be returned here, I'm assuming you want the method to return true if any of the elements in category(i) start with x. If so, you can implement it as follows:
category(i).exists(_.startsWith(x))
Which returns a Boolean, as expected.
i have the following code, which query DB and return value, the value is wrapped in a EitherT class,
val result = emailModel.getStatusByEmail(emailAddress)
result type is : ProcessorResult[List[EmaiStatusDTO]] and
type ProcessorResult[A] = ServiceResult[PermissionError, A]
type ServiceResult[Err, A] = EitherT[Future, Err, A]
I need to check if the return from DB is empty, how do i do that? i tried this but obviously not working, i'm new to Scala, still try to figure it out...
if (result.collectRight().onComplete().isEmpty()) {
return ProcessorResult(List(new EmaiStatusDTO(emailAddress, "Normal")))
} else {
return result
}
As I understand you work with something like EitherT from scalaz
getStatusByEmail returns a "future" (a delayed computational task), which (if you run it) will return either a PermissionError, or a list - List[EmaiStatusDTO].
Your intention is to change the empty list result to some fixed constant.
For this you could just use the EitherT.map function:
val result = emailModel.getStatusByEmail(emailAddress)
val defaultStatusList = List(new EmaiStatusDTO(emailAddress, "Normal")
return result.map(l => if (!l.isEmpty) l else defaultStatusList)
I came across a puzzling, but interesting, code construct that I whittled down to a small example, and that
I still have trouble wrapping my head around.
The example is shown below. Note that I have a simple Future that immediately returns a String. I map this
to a comparison of the Future itself using != and ==
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object Dummy extends App {
val taskReturningString: Future[String] = Future{ "foo"}
val falseResult: Future[Boolean] = taskReturningString.map(taskReturningString ==)
System.out.println("false result:" + Await.result(falseResult, 0 nanos) )
val trueResult: Future[Boolean] = taskReturningString.map(taskReturningString !=)
System.out.println("true result:" + Await.result(trueResult, 0 nanos) )
}
The output is
false result:false
true result:true
But I'm not sure why I got those results. In the case of ==, and != the first item being compared is
'taskReturningString' -- the Future. But what is it being compared to ? I am assuming that what is happening
is a comparison, but I've never seen a case where the operators == and != appear with one operand instead of two.
That behavior is due to eta expansion. Those map need a function String => Boolean (because type inference) and taskReturningString == is a method that can be expanded to that kind of function.
Here is a simplified example.
val equals: String => Boolean = "foo" ==
println(equals("foo"))
// true
println(equals("bar"))
// false
or with +
val plusTwo: Int => Int = 2 +
println(plusTwo(2))
// 4
drop from String
val drop: Int => String = "abcd".drop
println(drop(2))
// cd
or ::: from List
val concat: List[Int] => List[Int] = List(1,2,3) :::
println(concat(List(4,5,6)))
// List(4,5,6,1,2,3)
The use of _ is not always necessary if the compiler realizes that it can expand a method with missing parameters and the types are correct.
This code doesn't work because there is no way that the compiler knows the type of equals
val equals = "foo" ==
so I need to help it with _
val equals = "foo" == _
The answer for this lies with following facts,
Fact 1: Even operators are methods in Scala,
// something like
val a = "abc" == "def"
// is actually
val a = "abc".==("def")
So, taskReturningString == is actually method taskReturningString.==
Fact 2: methods can be converted to functions (by using _),
val string1 = "abc"
val func1 = string1.== _
// func1: Any => Boolean = sof.A$A0$A$A0$$Lambda$1155/266767500#12f02be4
// or if you want more specific type,
val func2: String => Boolean = string1.== _
// func2: String => Boolean = sof.A$A0$A$A0$$Lambda$1156/107885703#19459210
Fact 3: Scala compiler is smart. It supports eta-expansion which is conversion of a method to an appropriate function (to match the requirement)(if possible). So, if we tell the compiler that we want a Function of type String => Boolean and give it a method, it will smartly convert it to function.
// so our func3 did not need that explicit conversion using `_`
val func3: String => Boolean = string1.==
// func3: String => Boolean = sof.A$A1$A$A1$$Lambda$1161/1899231632#4843e7f0
Now, since your taskReturningString is a Future[String] thus taskReturningString.map wants an function of type String => A for any type A.
Also, taskReturningString.== takes an argument of type Any and return type of Boolean,
the compiler will expand it to a function String => Boolean,
val future1 = Future("abc")
val func4: String => Boolean = future1.==
// func4: String => Boolean = sof.A$A4$A$A4$$Lambda$1237/1577797787#2e682ccb
// And since `func4` will compare the argument string with `future1` for equality
// it will always return `false`
// So what you are doing is actually,
val falseResult: Future[Boolean] = future1.map(func4)
Let's suppose I've defined a macro as below. It essentially types an expression of type T and returns an object of type MyType[T] (the actual types involved don't really matter).
object MyMacro {
def macroImpl[T : context.WeakTypeTag, U : context.WeakTypeTag](context : scala.reflect.macros.blackbox.Context) (expression : context.Expr[T]) : context.Expr[U] =
}
object MyObj {
def callMacro[T](expression : T) : MyType[T] = macro MyMacro.macroImpl[T, MyType[T]]
}
In my macro, I'd like to determine if the expression passed is constant or not. By that I mean, I want to know if the expression, once evaluated at runtime, could ever subsequently evaluate to a different value. If it is constant, I can apply certain optimizations that are very useful.
I know an expression is constant if it is:
a literal expression.
a 'this' expression.
a reference to a val or parameter.
a member invocation where the object expression is constant, and the member being invoked is a val or lazy val.
For example, the expressions passed in the first five calls to callMacro below should be considered a constant:
class MyClass {
val i = 0
val myLiteral = callMacro("Hi!") //constant - literal expression
val myThis = callMacro(this) //constant - this expression
val myInt = callMacro(i) //constant - reference to a val
def myMethod(p : MyOtherClass) {
val myParameter = callMacro(p) //constant - reference to a parameter
val myValMember = callMacro(p.x) //constant - invocation of val member
val myVarMember = vallMacro(p.y) //NOT constant - invocation of var member
val myVarMember = vallMacro(p.z) //NOT constant - invocation of def member
}
}
class MyOtherClass(val x : Int, var y : Int) {
def z = x + y
}
I've already implemented code for the first two cases (which is rather trivial).
def isConstant[T](context : scala.reflect.macros.blackbox.Context) (expression : context.Expr[T]) = {
import context.universe._
expression.tree match {
case This(_) =>
true
case Literal(_) =>
true
/*...put additional cases here...*/
case _ =>
false
}
}
However, I'm not sure whether something like this already exists, or if its even possible to detect whether the member being called on an object is a val or not.
Is it possible to implement the fourth criteria? Or, does anything like this already exist in the API?
I figured out a solution. It basically boiled down to me not knowing about Symbols in scale's reflection system.
I ended up adding a fifth criteria to handle the case in which an implicit parameter or object is referenced.
implicit class extendSymbol(symbol : scala.reflect.macros.blackbox.Context#Symbol) {
def isStable =
(symbol.isTerm && symbol.asTerm.isStable) || (symbol.isMethod && symbol.asMethod.isStable)
}
def isConstant[T](context : scala.reflect.macros.blackbox.Context) (tree : context.Tree) : Boolean = {
import context.universe._
tree match {
case This(_) =>
true
case Literal(_) =>
true
case ident # Ident(_) =>
ident.symbol.isStable
case select # Select(objExpr, term) =>
isConstant(context) (objExpr) && select.symbol.isStable
//for implicit values
case Apply(TypeApply(Select(Select(This(TypeName("scala")), TermName("Predef")), TermName("implicitly")), _), _) =>
true
case _ =>
false
}
}