In scala, check non nullity and apply method directly? - scala

With the following definitions:
class Test {
var activated: Boolean = false
}
def maybeTest(): Test = {
if(...) {
val res = new Test
if(...) res.activated = true
} else null
}
I am having a lot of if structures like this one:
val myobject = maybeTest()
if(myobject != null && myobject.activated) {
// Do something that does not care about the object
}
I would like to condensate it a little bit. Is there a nice way to define/write something like this to avoid a nullPointerException:
if(maybeTest() &&> (_.activated)) {
...
}
What is a best way of achieving this in scala?

You can wrap such code in Option like this:
class Test(num: Int) {
def someNum = num
}
val test: Test = null
Option(test).map(t => t.someNum)
In this example if your variable is null then you will get None, otherwise just work with Some(value)
Update
If you don't want to use Option, then you can define such function
class Test(num: Int) {
def give = num
}
def ifDefAndTrue[T, K](obj: T)(ifTrue: T => Boolean)(then: => K) {
if (obj != null && ifTrue(obj))
then
}
In your case this look like this:
val test = new Test // assuming that activated is false
ifDefAndTrue(test)(_.activate) {
println("results in unit")
}
But it contains side effect and not functional

How about
for {m <- Option(maybeTest())
if m.activated
}
{
... // do something with non-null, activated, m
}

Found the best way with implicit classes, which properly handles the null case (although it might not be the most efficient way).
implicit class CheckNull[T](obj: T) {
def call(f: T => Unit): Unit = if(obj != null) f(obj) else ()
def is(f: T => Boolean): Boolean = if(obj != null) f(obj) else false
}
So I can write a type safe method and even calls:
if(maybeTest() is (_.activated)) {
...
}
myObjectMaybeNull call (_.pause())
Note that parenthesis around (_.activated) are necessary.

Related

How to skip "ArrayIndexOutOfBoundsException: 0" from a Scala function (return type: Iterator String Array)?

I have a Scala function as shown below. Input neighborhood is array of strings. However, sometimes it (i.e. neighborhood) can be empty. In that case I get "ArrayIndexOutOfBoundsException", which is understandable. I want to avoid this exception. I mean, my code has to skip this error and move on to the next job (not shown here).
I tried this:
if(neighborhood.isEmpty){
true
} else {
val key = neighborhood(0)
neighborhood
.filterNot { _.equals(key) }
.combinations(k - 1)
}
But IntelliJ shows 'type mismatch between iterator and boolean.'
How to deal with this? I am newbie in Scala. Thanks!
Here is original function:
private def scanData(neighborhood: Array[String], k: Int): Iterator[Array[String]] = {
val key = neighborhood(0)
neighborhood
.filterNot { _.equals(key) }
.combinations(k - 1)
}
```scala
You can make use of headOption for a clean approach.
neighborhood.headOption.map { key =>
neighborhood.tail
.filterNot(_ == key)
.combinations(k-1)
}.getOrElse(Iterator.empty)
Use Option. You may find information here. Here you are en example :
object Run {
def main(args:Array[String]):Unit = {
val neighborhood:Array[String] = Array("1", "2","3")
val k = 1
val isa = geta(emptyArray) match {
case Some(isa) => scanData(neighborhood,k)
case None => Array.empty
}
}
def scanData(neighborhood: Array[String], k: Int): Iterator[Array[String]] = {
val key = neighborhood(0)
neighborhood
.filterNot { _.equals(key) }
.combinations(k - 1)
}
def geta(neighborhood:Array[String]):Option[Array[String]] = {
if(neighborhood.isEmpty){
return None;
} else {
return Some(neighborhood)
}
}
}

How to make only few datatype which is not related to each other acceptable by generics

There is a trait which works perfectly. However, I would like to refactor the part related to generic [T] in order to limit the data type which could be accepted by generic [T] (I need only Option[JsValue] , JsValue , StringEnumEntry , String ). Is it possible to solve this problem through shapeless coproduct? Maybe there are other solutions?
trait ParameterBinders extends Log {
def jsonBinder[T](json: T, jsonType: java.lang.String = "json"): ParameterBinderWithValue = {
val jsonObject = new PGobject()
jsonObject.setType(jsonType)
json match {
case json: Option[JsValue] =>
jsonObject.setValue(json.map(Json.stringify).orNull)
case json: JsValue =>
jsonObject.setValue(Json.stringify(json))
case json: StringEnumEntry =>
jsonObject.setValue(json.value)
case json: String =>
jsonObject.setValue(json)
case _ =>
logger.error("unexpected data type ")
}
if (jsonType == "JSONSCHEMATYPE" || jsonType == "SYSPROPERTYTYPE") {
ParameterBinder(this, (ps, i) => {
ps.setObject(i, jsonObject)
})
} else {
ParameterBinder(json, (ps, i) => {
ps.setObject(i, jsonObject)
})
}
}
}
The easiest way is to use an ADT as described in the link of the first comment.
If you don't want to change the types that are accepted in jsonBinder then you can solve the problem by using a typeclass.
e.g.
trait JsonBindValue[T] {
def value(t: T): String
}
you would then have to provide instances for your accepted datatypes
object JsonBindValue {
implicit val OptJsBinder = new JsonBindValue[Option[JsValue]] {
def value(t: Option[JsValue]): String = {
t.map(Json.stringify).orNull
}
}
... more instances here
}
finally your function would look like this:
def jsonBinder[T : JsonBindValue](json: T, jsonType: java.lang.String = "json"): ParameterBinderWithValue = {
val binder = implicitly[JsonBindValue[T]]
jsonObject.setType(jsonType)
jsonObject.setValue(binder.value(json))
...
}
if you call the function without a implicit instance in scope you will get a compile time error.

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

Eliminating null usage in a Scala stack implementation

I'm learning Scala and am making some Stack implementations as practice. I made this and there are some apparent issues.
class LinkedStack[T] extends Stack[T] {
var current: Node = null
var n: Int = 0
private class Node(e: T, prev: Node) {
val element: T = e
var previous: Node = prev
}
override def pop(): T = {
if (n == 0) {
throw new NoSuchElementException
}
val popNode: Node = current
current = current.previous
popNode.previous = null
n -= 1
popNode.element
}
override def peek(): T = {
if (n == 0) {
throw new NoSuchElementException
}
current.element
}
override def push(element: T): Unit = {
if (element == null) {
throw new NullPointerException
}
val newNode: Node = new Node(element, current)
current = newNode
n += 1
}
override def size(): Int = {
n
}
override def toString(): String = {
val builder = new StringBuilder("Stack top [")
var temp: Node = current
if (n == 0) {
builder.append("]")
return builder.toString()
}
while (temp.previous != null) {
builder.append(temp.element).append(", ")
temp = temp.previous
}
builder.append(temp.element).append("]")
builder.toString()
}
}
The trait includes all of the elements except toString. My main problem is that I'm using null pretty liberally. I know this shouldn't be done at all in Scala, and the line
var current: Node = null
in the constructor generates a compile error. How should I implement a constructor to create an empty stack? What's the best substitution for null?
Edit:
You may have noticed that the Node class should be rewritten as
private class Node(val element: T, var previous: Node) {}
I realized this after reading Rex Kerr's answer. I forgot that I was programming in Scala when I first wrote that.
There's nothing terribly wrong with using null as part of the internals for your class as long as those nulls never leak out and the logic is straightforward enough so you can be sure of that.
But if you want to not use null for practice, you have two choices. One is to use a built-in alternative: instead of Node use Option[Node] and use None for null. Given that your list is invariant, this is the easier way.
Second, you can replace Node with a hierarchy like so:
trait Node
class Elt(val element: T, val previous: Node) extends Node {}
object End extends Node
And then you use End wherever you use null now, and match on the Node any time you need to walk or do something, e.g.
def peek = current match {
case End => throw new NoSuchElementException
case Elt(e, _) => e
}
Of course this means each list has to create an extra object (End), and there are various other drawbacks, most of which can be gotten around to some extent. But for an exercise in avoiding null, you can ignore those complications.
i'm also scala learning my stack implementation ,it;s simple i used scala mutable array buffer
object Stack{
var stack=scala.collection.mutable.ArrayBuffer[Int]()
def isEmpty():Boolean={
if(stack.length==0) true
else false
}
def push(input:Int):Unit={
stack+=input
}
def size():Int={
stack.length
}
def pop():Int={
stack.remove(stack.length-1)
}
def peek()={
stack(stack.length-1)
}
}

scala - cache and reload a future which will become invalid later

private class FutMemorizer[T](valid: T => Boolean)(f: () => Future[T]) {
private val ref = new AtomicReference[Promise[T]]
#scala.annotation.tailrec
final def get(): Future[T] = {
val nullableRef = ref.get()
val valid = checkPromise(ref.get())
if(valid) {
nullableRef.future
} else {
val p = Promise[T]
val success = ref.compareAndSet(nullableRef, p)
if(success) {
p.completeWith(f())
p.future
} else {
get()
}
}
}
private def checkPromise(nullable: Promise[T]) = {
nullable != null && {
nullable.future.value match {
case None => true // future is not complete all caller should wait
case Some(Success(v)) => valid(v)
case _ => false
}
}
}
}
I am implementing an Future memorizer that only cache a valid future value.
It must meet following requirements
Futures created by f never executed paralleled
get never return a invalid value (once invalid recall f() to reload)
Is my implementation correct ?
Is there a more functional or simpler way to do this (because I hardly prove correntness of mime)?
As far as I understand this is wrong:
p.completeWith(f())
The caller gets a future the value of which is (or will be sometimes) that of the future returned by f(), but it's not checked anywhere that this value satisfies or will satisfy valid(...); same for other callers that came while the resulting future returned by f() is in progress if it takes time. It's only when result of f() completes will the next caller probably start "fixing" it.
I would probably go about fixing this problem the following way (see the fixed method), with some stylistic changes:
class FutMemorizer[T](valid: T => Boolean)(f: () => Future[T]) {
private val ref = new AtomicReference[Future[T]]
#tailrec
final def get: Future[T] = {
val current = ref.get
if (current != null && isValid(current)) current
else {
val p = Promise[T]
val pf = p.future
if (ref.compareAndSet(current, pf)) {
p.completeWith(fixed(f))
pf
} else get
}
}
private def fixed(f: () => Future[T]): Future[T] =
f() flatMap { t =>
if (valid(t)) Future.successful(t) else fixed(f)
}
private def isValid(future: Future[T]) =
future.value match {
case None => true // future is not complete all caller should wait
case Some(Success(v)) => valid(v)
case _ => false
}
}
As for your question about a more functional way of doing it I guess f and valid having effects on the external state and basing their computations on it (which I guess is the point of having a memorizer with invalidation) would seriously hinder it.
Just find spray-cache already have this feature