Scala default parameters and null - scala

I have a method like this:
def aMethod(param: String = "asdf") = {
...
}
If the method is called as follows, then param is given the default value "asdf":
aMethod() ...
But what I would like, is that if the method is called with null, then the default value would also be applied:
aMethod(null) //inside the method, I can use `param` and it has the value "asdf".
Whats the best way to do this in Scala? I can think of pattern matching or a simple if statement.

Pattern matching
def aMethod(param: String = null) {
val paramOrDefault = param match {
case null => "asdf"
case s => s
}
}
Option (implicitly)
def aMethod(param: String = null) {
val paramOrDefault = Option(param).getOrElse("asdf")
}
Option (explicitly)
def aMethod(param: Option[String] = None) {
val paramOrDefault = param getOrElse "asdf"
}
The last approach is actually the most idiomatic and readable once you get use to it.

def aMethod(param: String = null) = {
val p =
if(param == null)
"asdf"
else
param
println(p)
}
But the question must be asked: why allow null? Would Option be possible in your case? For this you could do:
def aMethod(param: Option[String]) = {
val p = param.getOrElse("asdf")
println(p)
}
This makes it clear that your method expects the possibility of a "null" argument.

If the method has just one or two default parameters that can be set to null consider this pattern:
// please note that you must specify function return type
def aMethod (x:String = "asdf"):String = if (x==null) aMethod() else {
// aMethod body ...
x
}
There are some benefits:
The method definition clearly indicates the parameter's default value.
The correct default value can be picked by Scala tools, including ScalaDoc.
There is no need to define an additional value to substitute for the original parameter within the method body - less room for mistakes, easier to reason.
The pattern is fairly concise.
Furthermore, consider the following scenario:
trait ATrait {
def aMethod (x:String = "trait's default value for x"):String
}
class AClass extends ATrait {
....
}
Clearly, here we need to extend the trait, whilst preserving the original default value. Any of the patterns that involve initially setting the parameter to null followed by a check and actual default value will break the contract established by the trait:
class AClass extends ATrait {
// wrong, breaks the expected contract
def aMethod(x: String = null):String = {
val xVal = if (x == null) "asdf" else x
...
}
}
Indeed in this scenario the only way to preserve the original value from ATrait will be:
class AClass extends ATrait {
override def aMethod (x:String):String = if (x==null) aMethod() else {
... // x contains default value defined within ATrait
}
}
However, in the scenario when there are more than one or two default parameters that can be set to null the pattern starts getting rather messy:
// two parameters
def aMethod (x:String = "Hello",y:String = "World"):String =
if (x==null) aMethod(y=y) else
if (y==null) aMethod(x=x) else {
// aMethod body ...
x + " " + y
}
// three parameters
def aMethod (x:String = "Hello",y:String = " ",z:String = "World"):String =
if (x==null) aMethod(y=y,z=z) else
if (y==null) aMethod(x=x,z=z) else
if (z==null) aMethod(x=x,y=y) else {
// aMethod body ...
x + y + z
}
Still when overriding an existing contract this might be the only way to honour the original default values.

Related

Scala constructor overloading parameter is not taking effect

I'm trying to understand what's wrong with the way I'm implementing constructor overloading. I want to add a constructor that accepts an argument count, in a class that has a member with the same name.
The idea is to have count calculated off of one of the default constructor parameters, unless it is passed through the overload constructor. I show the code later.
To convince myself this can work, I constructed a quick and simple test:
import org.scalatest.FunSuite
class ConstructorOverloadTest extends FunSuite {
test("Overload parameter shadows class member") {
val actual = new TestME(200).length
200 === actual
1 !== actual
}
class TestME(name:String) {
val length = name.length
def this(length:Int) = {
this("*")
}
}
}
The test passes as expected. Which leads me to understand that the overload constructor parameter length shadows/replaces the class member length.
But when I do the same in another class, the class member is not shadowed/replaced.
class MyClass(input1: Array[Float], input2: Array[Byte], input3: Array[Float]) {
val count = input2.length
val index = doSomething()
def this(count: Int) = {
this(Array(), Array(), Array())
}
def printCount() = {
if (this.count == 0)
println("ZERO")
else
println("OTHER")
}
}
When I use this class as follows
val myInstance = new MyClass(200)
myInstance.printCount()
I expect it to print OTHER to the screen. Instead, it prints ZERO.
Why?
There appears to be something wrong with your test. new TestME(200).length returns 1, indicating that the constructor param does not in fact override length.
class TestME(name:String) {
val length = name.length
def this(length:Int) = {
this("*")
}
}
println(new TestME(200).length)
1
Per summerbulb's comments:
The test's assertions should be wrapped in assert:
// Closer to correct...
assert(200 === actual)
assert(1 !== actual)
Actual and expected values should be passed in that order:
// Correct!
assert(actual === 200)
assert(actual !== 1)

Trying to implement a Circular Enumeration in Scala

Below is the trait that I would like to use
trait CircularEnumeration extends Enumeration {
class CircularVal extends Val {
def next(): Value = {
apply((id + 1) % values.size)
}
}
protected override final def Value: CircularVal = new CircularVal;
///////////////////////////////////////////////////////////////////////////
def nextValue(value: Value) = {
//first way
val nextIndex = values.toSeq.indexOf(value) + 1;
val value_nomath = if (nextIndex >= values.size) {
values.toSeq(0);
}
else {
values.toSeq(nextIndex);
}
//second way
val value_withmath = this((value.id + 1) % values.size);
assert(value_nomath == value_withmath);
value_withmath;
}
}
You can see that I already have tried two ways, and both have failed.
In the first the usage would be something like this:
MyEnumeration(index).next
and this would return me the next value of this enumeration
In the second the usage would be like that:
MyEnumeration.nextValue(MyEnumeration(index))
and once again this would return the next value
but in both occasions I have issues of which type is which. Because inside the trait the Value is actually CircularEnumeration.Value while inside the class which has this trait tha Value is MyEnumeration.Value
Any ideas?
I believe I can get it to work with the following changes - modify the return type of nextValue:
def nextValue(value: Value): CircularEnumeration.this.Value = {
and the last line (returned value) to:
value_withmath.asInstanceOf[CircularEnumeration.this.Value]
Then, defining MyEnumeration as:
scala> object MyEnumeration extends CircularEnumeration {
| type MyEnumeration = Value
| val Zero, One, Two, Three, Four = Value
| }
defined module MyEnumeration
we get:
scala> MyEnumeration.nextValue(MyEnumeration(3))
res0: MyEnumeration.Value = Four
scala> MyEnumeration.nextValue(MyEnumeration(4))
res1: MyEnumeration.Value = Zero

Parsing command line args and executing a function in scala

I am trying to parse commandline arguments and execute a function that takes the parameters upon successful extraction of the parameters. I have an object called CurrencyExchangeRunner where the main method is. I have envisioned the structure of the class as follows:
object CurrencyExtractionRunner {
def main(args:Array[String]){
parseArgs(args){
(currencyType,currencyTypeArgs) =>
CurrencyExchanger(curencyType,currencyTypeArgs){
(exchanger) => exchanger.startExchange
}
}
}
}
}
What I want to accomplish above is to parse the arguments using parseArgs(args), get the (currencyType,currencyTypeArgs) as parameters and pass those into the CurrencyExchanger factory object and then that would return the appropriate exchanger on which I will execute the startExchange method. This is what I have envisioned but I am a little clueless on how would I go about creating this flow. The first thing I tried was to create a trait that parses the command-line args as follows(I am using the jcommander library for the commandline parse):
object Args {
#Parameter(
names = Array("-h", "--help"), help = true)
var help = false
#Parameter(
names = Array("-c", "--currency-type"),
description = "Type of currency exchange that needs to be performed",
required = true)
var currencyType: String = null
#Parameter(
names = Array("-d", "--denominations"),
description = "Specific denominations to be used during the exchage")
var exchangeDenomination: String = null
#Parameter(
names = Array("-s", "--someotheroptionalarg"),
description = "Additional argument for a specific currency exchange")
var someOtherOptionalArg: String = null
}
trait ParseUtils {
//How do I do this, take the args and return a function.
def parseArgs(args: Array[String]){
val jCommander = new JCommander(Args, args.toArray: _*)
if (Args.help) {
jCommander.usage()
System.exit(0)
}
//What do I do now? How do I proceed with executing the function with
//the specific arguments?
//What do I need to do to wrap the commandline arguments so that it could
//be passed to the next function
}
}
I am pretty stuck here since I am not sure how would I make the code flexible enough to take the arbitrary sequence of commandline args and execute the next step which is the factory that returns that takes these arguments and returns the correct exchanger.
It will be great if someone could point me in the right direction.
I'm not sure why you'd use such unusual syntax to pass return values to the following methods.
I would go for a simpler solution that looks like
trait ParseUtils {
//Why would you return a function here?
//Is it a strict constraint you need to fulfill?
def parseArgs(args: Array[String]): (String, String) {
val jCommander = new JCommander(Args, args.toArray: _*)
if (Args.help) {
jCommander.usage()
System.exit(0)
}
//This is the return value of the method, a pair of parameters
(Args.currencyType, Args.exchangeDenomination)
//If you need to embed additional params, you should append them to existing one
// or you could create optional values from the Args members...
// e.g. (Args.currencyType, Args.exchangeDenomination, Option(Args.someOtherOptionalArg))
// with return type (String, String, Option[String])
}
}
object CurrencyExtractionRunner with ParseUtils {
def main(args:Array[String]){
val (currencyType,currencyTypeArgs) = parseArgs(args)
CurrencyExchanger(currencyType,currencyTypeArgs).startExchange
}
}
case class CurrencyExchanger(currencyType: String, currencyTypeArgs: String) {
def startExchange = //implementation details using the costructor arguments
}
Alternative solution
since I prefer parseArgs to be more "functional" I'd change it to
trait ParseUtils {
def parseArgs(args: Array[String]): Option[(String, String)] {
val jCommander = new JCommander(Args, args.toArray: _*)
if (Args.help) {
jCommander.usage()
None
} else
Some(Args.currencyType, Args.exchangeDenomination)
}
}
object CurrencyExtractionRunner with ParseUtils {
def main(args:Array[String]){
parseArgs(args).foreach {
case (currencyType,currencyTypeArgs) =>
CurrencyExchanger(currencyType,currencyTypeArgs).startExchange
}
}
}
case class CurrencyExchanger(currencyType: String, currencyTypeArgs: String) {
def startExchange = //implementation details using the costructor arguments
}

In scala, check non nullity and apply method directly?

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.

Is it possible to know if a default argument was supplied as an actual parameter value (when they are equal) in Scala?

Is it possible to know if a default argument was supplied as an actual parameter value? In other words, assume that I defined a method:
def myMethod(x: Int = 1) = x + 1
Then is it possible to distinguish between these two calls (which return identical results because the parameter in the second method call has the same value as the default value in method definition) within the method body:
myMethod()
myMethod(1)
In other words, I want to know if there is technique to achieve an effect that is similar to -supplied-p feature in Common Lisp function definitions (see http://www.gigamonkeys.com/book/functions.html and http://www.psg.com/~dlamkins/sl/chapter21.html for details and more context).
No, you can't directly know this.
Here's an ugly workaround that relies on the fact that the default parameter can be a method call. It comes with many caveats, the biggest of which is that it is not thread-safe.
private var usedDefault = false
private def default = {
usedDefault = true
1
}
def myMethod(x: Int = default) = {
if (usedDefault) {
println("default")
} else {
println("supplied")
}
usedDefault = false
}
Another more practical workaround is this:
def myMethod(): Unit = myMethod(1, usedDefault = true)
def myMethod(x: Int): Unit = myMethod(x, usedDefault = false)
private def myMethod(x: Int, usedDefault: Boolean) = {
if (usedDefault) {
println("default")
} else {
println("supplied")
}
}
If you have a small number of parameters you could always overload your functions, so that
def myMethod(x: Int) = x + 1
def myMethod() = myMethod(1)