2
votes

Scala has a weird drawback, that I cannot create a default argument in args. Here is my latest attempt:

object Main extends java.lang.Object with ScalaObject with App {
    override val args:Array[String]=Array(args.toList.headOption.getOrElse("f"))
    println("args(0) = " + args(0))
}

Run the code here: http://ideone.com/B20HBA

Exception in thread "main" java.lang.NullPointerException at scala.collection.mutable.ArrayOps$ofRef$.length$extension(ArrayOps.scala:114) at scala.collection.mutable.ArrayOps$ofRef.length(ArrayOps.scala:114) at scala.collection.SeqLike$class.size(SeqLike.scala:106) at scala.collection.mutable.ArrayOps$ofRef.size(ArrayOps.scala:108) at scala.collection.mutable.Builder$class.sizeHint(Builder.scala:69) at scala.collection.mutable.ListBuffer.sizeHint(ListBuffer.scala:45) at scala.collection.TraversableLike$class.to(TraversableLike.scala:628) at scala.collection.mutable.ArrayOps$ofRef.to(ArrayOps.scala:108) at scala.collection.TraversableOnce$class.toList(TraversableOnce.scala:257) at scala.collection.mutable.ArrayOps$ofRef.toList(ArrayOps.scala:108) at Main$delayedInit$body.apply(Main.scala:2) at scala.Function0$class.apply$mcV$sp(Function0.scala:40) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.collection.immutable.List.foreach(List.scala:318) at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32) at scala.App$class.main(App.scala:71) at Main$.main(Main.scala:1) at Main.main(Main.scala)

2
I wouldn't qualify it as a “weird drawback”. The argument is always provided, but it can be empty. It’s your code's responsibility to implement the rest of the logic if you're not happy with empty args.Jean-Philippe Pellet

2 Answers

2
votes

As @blast_hardcheese has shown, you cannot usefully set the value of a val to an expression dependent on itself, which is what is happening in your code above.

If you really need to do this (I can't think of a reason why you would), you can reference the original value by appending super. in front of the reference to the original value:

object Main extends App {
    override val args: Array[String] = if (super.args.isEmpty) Array("f") else super.args
    println("args(0) = " + args(0))
}

Note that your original expression would lose any provided arguments beyond the first. That may have been your intention, but in case it wasn't, you would want to change it to something like the above.

0
votes

I don't believe you can in-place modify a value, using the previous value. I know it's not possible to re-define a value in a method, what you're trying to do is override the definition from the App mixin (which, unless I'm mistaken, prevents you from even using that value).

Beyond that, to use the value in the construction of the value seems to reference null, suggesting this isn't supported.

scala> val l = List(1,2,3,4)
l: List[Int] = List(1, 2, 3, 4)

scala> val l = l.map( _ * 2)
<console>:8: error: recursive value l needs type
       val l = l.map( _ * 2)
               ^

scala> val l: List[Int] = l.map( _ * 2 )
java.lang.NullPointerException
    at .<init>(<console>:8)
    at .<clinit>(<console>)
    at .<init>(<console>:7)
    at .<clinit>(<console>)
    ...