title: Spark UDF function gets called each time member of the struct is accessed
body: <p>I have UDF function that is returning case class <code>ProcessedResult</code>. Inside this UDF I'm using Singleton class that doing some processing.</p>
  
  <p>Example</p>
  
  <pre><code>case class ProcessedResult(
                       field1:String = null,
                       field2:String = null,
                       field3:String = null,
                       field4:String = null,
                       field5:String = null
                      )
  
  val sampleudf = udf((data: String) =&gt; {
    println("Processing")
    // processing
    ProcessedResult(field1, field2, field3, field4, field5)
  })
  
  val df1 = spark.sparkContext.parallelize(Seq(
    ("test1"),("test2"),("test3"),("test4"),("test5"),("test6")
  )).toDF("data")
  
  val df2 = df1.withColumn("processed", sampleudf($"data"))
  df2.printSchema()
  </code></pre>
  
  <p>Struct of this data:</p>
  
  <pre><code> |-- data: string (nullable = true)
   |-- processed: struct (nullable = true)
   |    |-- field1: string (nullable = true)
   |    |-- field2: string (nullable = true)
   |    |-- field3: string (nullable = true)
   |    |-- field4: string (nullable = true)
   |    |-- field5: string (nullable = true)
  </code></pre>
  
  <p>Ok, lets query our data</p>
  
  <pre><code>df2.createOrReplaceTempView("datas")
  
  spark.sql(
    s"""
       |SELECT
       |processed.field1,
       |processed.field2,
       |processed.field3,
       |processed.field4,
       |processed.field5
       |FROM datas
      """.stripMargin).collect().foreach(println)
  </code></pre>
  
  <p>I'm getting string "Processing" 30 times in return! It means our UDF was called 30 times! We had only 6 rows with 5 columns returned by our UDF. But, UDF is getting called each time I'm accessing any of the struct's column! What is the point of that ? 30 calls to the UDF for 5 rows ? Why struct isn't cached or remembered in any way ? Having complex UDF functions makes it impossible to use UDF effectively. </p>