2

In general, can you declare a val in scala before assigning it a value? If not, why not? An example where this might be useful (in my case at least) is that I want to declare a val which will be available in a larger scope than when I assign it. If I cannot do this, how can I achieve the desired behavior?

And I want this to be a val, not a var because after it is assigned, it should NEVER change, so a var isn't ideal.

For example:

object SomeObject {
    val theValIWantToDeclare // I don't have enough info to assign it here

    def main(): Unit = {
        theValIWantToDeclare = "some value"
    }

    def someOtherFunc(): Unit {
        val blah = someOperationWith(theValIWantToDeclare)
    }
}

3 Answers 3

4
object SomeObject {
  private var tviwtdPromise: Option[Int] = None
  lazy val theValIWantToDeclare: Int = tviwtdPromise.get
  private def declareTheVal(v: Int): Unit = {
    tviwtdPromise = Some(v)
    theValIWantToDeclare
  }

  def main(args: Array[String]): Unit = {
    declareTheVal(42)
    someOtherFunction()
  }

  def someOtherFunction(): Unit = {
    println(theValIWantToDeclare)
  }
}

It will crash with a NoSuchElementException if you try to use theValIWantToDeclare before fulfilling the "promise" with declareTheVal.

Sign up to request clarification or add additional context in comments.

8 Comments

This looks like it will fix my issue! One question, what does the: theValIWantToDeclare () do in the private def function? Don't you just need the tviwtdPromise = Some(v) line?
There's also Promise.
@MichaelBlankenship you definitely should force theValIWantToDeclare to evaluate the value right now by using it in statement position. Otherwise you could "redeclare" it multiple times, and each time, it would override the hidden tviwtdPromise value. The () in the very end is just to make clear that Unit is returned. It's not needed, actually, I've removed it.
@som-snytt Yes, but AFAIR it requires some strange imports with default executor pools etc. I decided that adding Promise into the mix would be more confusing rathen than more "DRY".
@AndreyTyukin I cannot thank you enough for the solution as well as answering my second question. Great explanations! Thank you! :)
|
0

It sounds to me that you need a lazy val.

A lazy val is populated on demand and the result is cached for all subsequent calls.

https://blog.codecentric.de/en/2016/02/lazy-vals-scala-look-hood/

1 Comment

The problem is lazy doesn't help me because I don't have "some value" at declaration time. So, I don't have the 'expression' which would execute when the val is needed.
0

Why not define a SomeObjectPartial that is partially constructed, and class SomeObject(theVal) that takes the value as a parameter?

Then your program has two states, one with the partial object, and another with the completed object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.