You could remove match here:
(xOption, yOption, xyOption)
This expression creates Tuple3. Without syntax sugar:
Tuple3.apply(xOption, yOption, xyOption)
apply method declaration:
def apply[T1, T2, T3](_1: T1, _2: T2, _3: T3): (T1, T2, T3)
All parameters are call-by-value, so parameters values evaluated before apply method evaluation.
With call-by-name parameters lazy val will not be evaluated.
match calls unapply method, so evaluation depends on unapply method implementstion:
lazy val a = { println("a"); 1 }
lazy val b = { println("b"); 1 }
lazy val c = { println("c"); 1 }
scala> val s = a #:: b #:: c #:: Stream.empty
a
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> s match {
     |   case x #:: _ => x
     | }
b
res0: Int = 1
As you can see c is not evaluated, a is evaluated on Stream creation and b is evaluated in #::.unapply method.