Taking isnan as a simple example, I'd like to understand what happens downstream of sql.functions.scala.
1. The withExpr { } construct. How does that work? I see it refers to the IsNan case class, which gets passed not the column e but e.expr, which is an Expression. I also see that withExpr is a private function of the Column class. 2. The IsNaN case class. How does that work together with the call to isnan? I notice it only has to handle DoubleType and IntegerType, as defined in its inputTypes override. So what happens (or what has happened) to any strings that were encountered in the call to .isnan? 3. Expressions. I see that values and datatypes are extracted from Expressions. But this happens in eval(), which is somehow passed an Internal row. It seems this is pretty central to understanding how data gets to a sql.function to be acted on. Can someone summarize how this works? Thanks much, Pete