{"id":379672,"date":"2024-06-25T03:25:43","date_gmt":"2024-06-25T03:25:43","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=379672"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=379672","title":{"rendered":"<span>\u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 UDF \u0432 Apache Spark \u0438\u0437 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430: \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 (\u00ab\u043a\u043e\u0441\u0442\u044b\u043b\u044c\u00bb)<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0420\u0435\u043c\u0430\u0440\u043a\u0430:<\/h2>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e, \u043a\u0430\u043a \u0430\u0432\u0442\u043e\u0440 \u0440\u0435\u0448\u0438\u043b \u0441\u0432\u043e\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438 \u043d\u0435 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u043b\u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u0435\u0435. \u0422\u0430\u043a\u0436\u0435 \u0430\u0432\u0442\u043e\u0440 \u043d\u0435 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0435\u0448\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0438 \u043d\u0435 \u043d\u0430\u0441\u0442\u0430\u0438\u0432\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430. \u042d\u0442\u043e \u043b\u0438\u0448\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u0430\u0432\u0442\u043e\u0440\u043e\u043c, \u0438 \u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0437\u0434\u0435\u0441\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0410\u0432\u0442\u043e\u0440 \u043e\u0442\u043c\u0435\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0435 \u0441\u043c\u043e\u0433 \u043d\u0430\u0439\u0442\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u043d\u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0445, \u043d\u0438 \u043d\u0430 \u0430\u043d\u0433\u043b\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0425\u0430\u0431\u0440 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438. \u0421\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0434\u0438\u0441\u043a\u0443\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b, \u0438 \u0430\u0432\u0442\u043e\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0434 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<h2>\u0427\u0442\u043e \u044f \u043f\u044b\u0442\u0430\u044e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c:<\/h2>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 UDF <code>blue<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 &#171;0000FF&#187; \u043d\u0430 Scala API.&#187;<\/p>\n<pre><code class=\"scala\">object Example1 extends App with Configure {  spark.udf.register(\"blue\", udf(() => \"0000FF\")) \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0438 \u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c udf spark.sql(\"select blue()\").show() \/* \u0432\u044b\u0432\u043e\u0434: +------+ |blue()| +------+ |0000FF| +------+  *\/  }<\/code><\/pre>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u0441\u0430\u043c\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f UDF \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>code<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <code>\"() => \"0000FF\"\"<\/code>. \u0412 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0442\u0438\u043f\u0430 <code>Function0[String]<\/code> \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f UDF. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u043e\u044f \u0446\u0435\u043b\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u043b\u044f\u043c\u0431\u0434\u044b \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c\u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a.<\/p>\n<p>\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>&#171;(num: Int) => num * num&#187;<\/p>\n<\/li>\n<li>\n<p>&#171;(str: String) => str.reverse&#187;<\/p>\n<\/li>\n<li>\n<p>&#171;(num1: Double, str: String) => Math.pow(num1, str,size)&#187;<\/p>\n<\/li>\n<li>\n<p>\u0438 \u0442\u0434<\/p>\n<\/li>\n<\/ul>\n<h2>\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u043a\u0430\u043a\u0430\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430:<\/h2>\n<p>\u0440\u0430\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434<\/p>\n<pre><code class=\"scala\">import org.apache.spark.sql.functions.udf  import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox  object Example2 extends App with Configure {  def udfRegister(labdaCode: String): Unit = {  import universe._ val toolbox = universe.runtimeMirror(this.getClass.getClassLoader).mkToolBox()  val tree = toolbox.parse(labdaCode) val compiledCode = toolbox.compile(tree) val function = compiledCode().asInstanceOf[Function0[String]] \/\/\u0441\u0442\u043e\u0440\u043e\u043a\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u044c\u0441\u044f \u0432 Function0(String)   println(function()) \/\/ \u0432\u044b\u0432\u043e\u0434: 0000FF val udfBlue = udf(() => function()) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 udf   spark.udf.register(\"blue\", udfBlue)  }  udfRegister(\"() => \\\"0000FF\\\"\") spark.sql(\"select blue()\").show() \/\/ \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430  }<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430: <br \/><code>cannot assign instance of java.lang.invoke.SerializedLambda to field org.apache.spark.sql.catalyst.expressions.ScalaUDF.f of type scala.Function1 in instance of org.apache.spark.sql.catalyst.expressions.ScalaUDF<\/code> <\/p>\n<p>\u041e\u0448\u0438\u0431\u043a\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u0438\u043b\u0438 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Spark \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c SerializedLambda \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430 scala.Function1 (\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441 \u043e\u0434\u043d\u0438\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c).<\/p>\n<p>\u0412 Spark \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. SerializedLambda \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>\u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c <code>SerializedLambda<\/code> \u0435\u0441\u043c\u044c <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/invoke\/SerializedLambda.html\" rel=\"noopener noreferrer nofollow\">\u043a\u043b\u0430\u0441\u0441<\/a>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0432 Java \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u0441\u044b\u043b\u043e\u043a. \u042d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c Java \u043f\u0440\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. (\u0441\u0443\u0434\u044f \u043f\u043e \u0441\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u0441\u043f\u0430\u0440\u043a\u0443 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438)<\/p>\n<p>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0437\u0430\u043f\u0443\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 <code>Function0[String]<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Spark \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 UDF. \u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0443\u0436\u0435 \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0441\u043d\u043e\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"scala\">import org.apache.spark.sql.functions.udf  import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox  object Example3 extends App with Configure {  val labdaCode = \"() => \\\"0000FF\\\"\"  import universe._ val toolbox = universe.runtimeMirror(this.getClass.getClassLoader).mkToolBox()  val tree = toolbox.parse(labdaCode) val compiledCode = toolbox.compile(tree) val function = compiledCode().asInstanceOf[Function0[String]] \/\/\u0441\u0442\u043e\u0440\u043e\u043a\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u044c\u0441\u044f \u0432 Function0(String)   println(function()) \/\/ \u0432\u044b\u0432\u043e\u0434: 0000FF val udfBlue = udf(() => function()) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 udf  spark.udf.register(\"blue\", udfBlue) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 udf  spark.sql(\"select blue()\").show() \/*\u0432\u044b\u0432\u043e\u0434:  +------+ |blue()| +------+ |0000FF| +------+   *\/  }<\/code><\/pre>\n<p>\u0412 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 <code>Example3<\/code> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0435 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0447\u0442\u043e \u0438 \u0432 <code>Example2<\/code>, \u043d\u043e \u043f\u0435\u0440\u0432\u043e\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0430 \u0432\u0442\u043e\u0440\u043e\u0435 \u043d\u0435\u0442 \u0447\u0442\u043e \u0432\u0432\u043e\u0434\u0438\u0442 \u0435\u0449\u0435 \u0432 \u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u0437\u0430\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e<\/p>\n<pre><code class=\"scala\">import org.apache.spark.sql.functions.udf  import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox  object Example4 extends App with Configure {  if (true) {  val labdaCode = \"() => \\\"0000FF\\\"\"  import universe._ val toolbox = universe.runtimeMirror(this.getClass.getClassLoader).mkToolBox()  val tree = toolbox.parse(labdaCode) val compiledCode = toolbox.compile(tree) val function = compiledCode().asInstanceOf[Function0[String]] \/\/\u0441\u0442\u043e\u0440\u043e\u043a\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u044c\u0441\u044f \u0432 Function0(String)   println(function()) \/\/ \u0432\u044b\u0432\u043e\u0434: 0000FF val udfBlue = udf(() => function()) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 udf  spark.udf.register(\"blue\", udfBlue) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 udf  }  spark.sql(\"select blue()\").show() \/\/ \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430  }<\/code><\/pre>\n<p>\u043a\u0430\u043a \u0438 Example3 Example4 \u043d\u0435\u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u043d\u043e \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u043e \u0431\u043b\u043e\u043a if \u0441\u043d\u043e\u0432\u0430 \u0432\u0432\u0435\u0434\u0435\u0442 \u043a \u043e\u0448\u0438\u0431\u043a\u0435<br \/>\u0442\u0430\u043a \u0436\u0435 \u043a \u043e\u0448\u0438\u0431\u043a\u0430\u043c \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0446\u0438\u043a\u043b\u043e\u0432 \u0438 \u043c\u043e\u043d\u0430\u0434, Try \u0438 \u0442\u0434 (\u043d\u043e \u0442\u0443\u0442 \u044f \u044d\u0442\u043e \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443)<\/p>\n<p>\u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u0441\u0435 \u0441\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043a \u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>function<\/code> \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b \u043d\u0435 \u044f\u0432\u043b\u044f\u043b\u0430\u0441\u044c \u0431\u044b <code>SerializedLambda<\/code>  \u0438 \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0442\u044c \u043b\u044f\u043c\u0431\u0434\u044b\/\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043c\u043a\u0435\u0442\u043e\u0434\u0435 main<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435\u043b\u044c\u0437\u044f \u0438\u0437 \u0441\u043e\u0437\u0434\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u043b\u043e\u043a\u0430\u0445 if, try, for, \u043c\u043e\u043d\u0430\u0434\u0430\u0445 \u0438 \u0442\u0434.<\/p>\n<\/li>\n<\/ul>\n<p>\u0445\u043e\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 blue, \u043c\u043e\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u043b\u044f\u043c\u0431\u0434\u0443 (\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043e\u0442 0 \u0434\u043e 10 \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 UDF10) \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0441\u0442\u0440\u043e\u043a\u0438<\/p>\n<h2>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445:<\/h2>\n<p>\u042f \u0445\u043e\u0447\u0443 \u0447\u0442\u043e\u0431\u044b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u043e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON \u0438 \u043f\u0443\u0442\u0441\u044c \u0443 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:<\/p>\n<pre><code class=\"json\">[ \/\/\u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0439\u0442\u0438 \u043c\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0438\u0439\u0442\u0438 \u0432\u043e\u043e\u0431\u0449\u0435   {     \"name\": \"blue\", \/\/\u0438\u043c\u044f \u0431\u043b\u044f udf     \"targetType\": \"String\", \/\/\u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439     \"fun\": \"() => \\\"00ff00\\\"\", \/\/\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430 \u043b\u044f\u043c\u0431\u0434\u0430     \"imports\": [\"...\", \"...\"] \/\/\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0435, \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b   },   \/\/ \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u0435\u044e\u0442 \u0442\u0430\u043a\u0443\u044e \u0436\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443   {     \"name\": \"reverse\",     \"targetType\": \"String\",     \"fun\": \"(str:String) => str.reverse\"   },   {     \"name\": \"plus\",     \"targetType\": \"Int\",     \"fun\": \"(i1:Int, i2:Int) => i1 + i2\"   },   {     \"name\": \"sum3\",     \"types\": \"Int,Int,Int\",     \"targetType\": \"Int\",     \"fun\": \"(i1:Int, i2:Int, i3:Int) => i1 + i2 + i3\"   } ]<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 Json:<\/p>\n<pre><code class=\"scala\">\/\/ \u0434\u0443\u043c\u0430\u044e \u0442\u0443\u0442 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 case class UDFConfig(name: String,    targetType: String,  fun: String,  imports: List[String] = List.empty) <\/code><\/pre>\n<p>\u0414\u043b\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 json \u0444\u0430\u0439\u043b\u0430 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <code>json4s<\/code> \u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043b\u0430\u0441\u0441<\/p>\n<pre><code class=\"scala\">package Util  import org.json4s.Formats import org.json4s.native.JsonMethods.parse  \/\/\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0431\u044c\u0435\u043a\u0442 \u0434\u043b\u044f \u043a\u043e\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 json \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044c\u0435\u043a\u0442\u043e\u0432 \u0442\u0438\u043f\u0430 JsonType  object JsonHelper {  private def jsonToListConvert[JsonType](json: String)(implicit mf: Manifest[JsonType], formats: Formats): List[Either[Throwable, JsonType]] = { parse(json) .extract[List[JsonType]] .map(Right(_)) }  implicit class JsonConverter(json: String) {  def jsonToList[JsonType]()(implicit mf: Manifest[JsonType], formats: Formats): List[Either[Throwable, JsonType]]= { jsonToListConvert[JsonType](json) }  }  }<\/code><\/pre>\n<p>\u0418 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0440\u0435\u0439\u0442 <code>Configure<\/code> \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u044b\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b<\/p>\n<pre><code class=\"scala\">\u0418import config.UDFConfig import org.apache.spark.sql.SparkSession import org.json4s.DefaultFormats  import scala.io.Source  trait Configure {  lazy val spark = SparkSession .builder() .appName(\"Example UDF runtime compile\") .master(\"local[*]\") .getOrCreate() lazy val sc = spark.sparkContext \/\/ \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u043f\u0440\u0430\u043a \u0441\u0435\u0441\u0441\u0438\u044e \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442  lazy val pathUdfsJson = \".\/UDFs.json\" \/\/\u043f\u0443\u0442\u044c \u0434\u043e json c \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438  implicit lazy val formats = DefaultFormats \/\/ \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0434\u043b\u044f json4s, \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0445\u0432\u0430\u0442\u0435\u0430\u0435\u0442 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 import Util.JsonHelper._  lazy val udfJson = getJson(pathUdfsJson) \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0430\u043c json \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 lazy val udfsConfigs: List[UDFConfig] = udfJson .jsonToList[UDFConfig] .filter(_.isRight) .map { case Right(udfconfig) => udfconfig } \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 udfconfig   \/\/ \u044d\u0442\u043e\u0442 \u043e\u0431\u0435\u043a\u0442 \u043c\u043d\u0435 \u0438 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f  \/\/\u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432   private def getJson(path: String): String = { val file = Source.fromFile(path) try { file.getLines().mkString(\"\\n\") } finally { file.close() } }  }<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043e\u0431\u044c\u0435\u043a\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 udfconfig \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u0442 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u0440\u0430\u0442\u0430\u0439\u043c\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0432 FunctionN \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438<\/p>\n<pre><code class=\"scala\">package Util  import config.UDFConfig  object UDFHelper {  private def configToStringConvert(udfConfig: UDFConfig): String = {  \/\/\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432\u0441\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b \u0434\u043b\u044f \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 val imports = udfConfig .imports  \/\/ \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u044b \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0430 .map(_.trim.stripPrefix(\"import \").trim) \/\/ \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0441 \u043b\u0435\u0432\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u0435\u0441\u0442\u044c .distinct  \/\/ \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 .map(imp => f\"import ${imp}\")            \/\/ \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0438\u0440\u0443\u0435\u043c \u0441\u043b\u0435\u0432\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e .mkString(\"\\n\")                          \/\/ \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0435\u043d\u044f\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u0441\u0442\u0443\u043f  val Array(params, functionBody) = udfConfig.fun.split(\"=>\", 2).map(_.trim) \/\/ \u041e\u0442\u0434\u0435\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043e\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445  val paramsTypes: Seq[(String, String)] = params .stripPrefix(\"(\") \/\/ \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u0441 \u043b\u0435\u0432\u0430 \u0441\u043a\u043e\u0431\u043a\u0443 .stripSuffix(\")\") \/\/ \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u0441 \u043f\u0440\u0430\u0432\u0430 \u0441\u043a\u043e\u0431\u043a\u0443 .split(\",\")       \/\/ \u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b .map(_.trim)      \/\/ \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u043b\u0438\u0448\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u0435\u043b\u044b .map { case \"\" => null case param => val Array(valueName, valueType) = param.split(\":\").map(_.trim) (valueName, valueType) }                 \/\/ \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u0438\u043c\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043e\u0439 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u044d\u0442\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 .filter(_ != null) \/\/ \u043e\u0442\u0432\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u044b\u0432\u0430\u0435\u043c null-\u044b  val funcTypes: String = paramsTypes.size match { case 0 => udfConfig.targetType case _ => f\"${List .fill(paramsTypes.size)(\"Any\") .mkString(\"\", \", \", \", \")}${udfConfig.targetType}\" } \/\/\u0437\u0434\u0435\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043f\u044f\u0442\u0443\u044e \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 Function  val anyParams = paramsTypes.map(_._1.trim + \"_any\").mkString(\", \") \/\/\u043f\u0430\u0440\u043c\u0435\u0442\u0440\u044b \u043b\u044f\u043c\u0434\u0430 \u0432\u044b\u0440\u043e\u0436\u0435\u043d\u0438\u044f  val instances = paramsTypes.map { case (valueName, valueType) => f\"val ${valueName}: ${valueType} = ${valueType}_any.asInstanceOf[${valueType}]\" }.mkString(\"\\n\") \/\/ \u0442\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u043c\u0435\u0442\u0440\u043e\u0432 \u043b\u044e\u043c\u0431\u0434\u044b \u0432 \u043d\u0435\u043e\u0431\u0445\u0430\u0434\u0438\u043c\u044b\u0435 \u0442\u0438\u043f\u044b  \/\/ \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435 \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0441\u0442\u0440\u0438\u043d\u0433 f\"\"\"  |${imports}  |  |val func: Function${paramsTypes.size}[${funcTypes}] = (${anyParams}) => {  |  |${instances}  |  |  (  |${functionBody}  |  ).asInstanceOf[${udfConfig.targetType}]  |  |}  |  |func  |\"\"\".stripMargin  }  implicit class Converter(udfConfig: UDFConfig) {  def configToString(): String = { configToStringConvert(udfConfig) }  }  } <\/code><\/pre>\n<p>\u041f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u0430 <code>Any<\/code>: \u043a\u0430\u043a \u044f \u0443\u0436\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0430, \u043c\u043e\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438, \u0433\u0434\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u0430\u044f \u0447\u0435\u0440\u0435\u0437 JSON \u043b\u044f\u043c\u0431\u0434\u0430 \u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 (\u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043e\u0442 0 \u0434\u043e 10). \u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445, \u0433\u0434\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 <code>FunctionN<\/code>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 <code>Any<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0432\u044b\u0445\u043e\u0434\u043e\u043c (\u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u044f\u0441\u043d\u043e, \u043f\u043e\u0447\u0435\u043c\u0443). \u0418\u043d\u0430\u0447\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"formula\" source=\"\\sum_{i=0}^{10} {9^{i+1}}\" alt=\"\\sum_{i=0}^{10} {9^{i+1}}\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/aed\/d23\/d7b\/aedd23d7b209490e66c397d604a0e6b6.svg\" width=\"66\" height=\"60\"\/><\/p>\n<p>\u0447\u0442\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u043c\u043d\u043e\u0433\u043e. <br \/>9 \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044f \u0440\u0435\u0448\u0438\u043b\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u0442\u044c\u0441\u044f 9-\u0442\u044c\u044e \u0442\u0438\u043f\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445: <code>String, Int, Boolean, Byte, Short, Long, Float, Double, Date, Timestamp<\/code> <\/p>\n<h2>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u044c\u0435\u043a\u0442\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b:<\/h2>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u043d\u0435 \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 <code>if<\/code> \u0438\u043b\u0438 <code>match<\/code>, \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u043e\u0434\u043d\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0435 <code>UDFRegN<\/code> \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 <code>UDFRegN<\/code>, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u044f \u0441 \u043d\u0443\u043b\u0435\u0432\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 <code>UDFRegN<\/code>.<\/p>\n<p>\u042d\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0438\u0437-\u0437\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 UDF \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c 11 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 <code>UDFRegN<\/code> \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0435\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432.<\/p>\n<pre><code class=\"scala\">import org.apache.spark.sql.functions.udf  import java.sql.{Date, Timestamp} import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox  object UDFReg0 extends App with Configure { \/\/ \u043a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u043b\u043e\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e main \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c  val indexcode = Integer.parseInt(args(0)) \/\/ \u044d\u0442\u043e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0430\u0440\u043c\u0435\u0442\u0440 \u0438\u0437\u0432\u043d\u0435 \u0438 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442\u0441\u044f \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u043d\u0434\u0435\u043a\u0441 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 UDFsConfig  import Util.UDFHelper._ val udfConfig = udfsConfigs(indexcode) \/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c udfConfig (\u0438\u0437 Configure) val functionCode = udfConfig.configToString() \/\/ \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043a\u043e\u0434  val toolbox = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()  val tree = toolbox.parse(functionCode) val compiledCode = toolbox.compile(tree) val function = compiledCode().asInstanceOf[Function0[Any]] \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0437 \u043a\u043e\u0434\u0430  val myUDF = udfConfig.targetType match { \/\/ \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c instanceOF \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f case \"String\" => udf(() => function().asInstanceOf[String]) case \"Int\" => udf(() => function().asInstanceOf[Int]) case \"Boolean\" => udf(() => function().asInstanceOf[Boolean]) case \"Byte\" => udf(() => function().asInstanceOf[Byte]) case \"Short\" => udf(() => function().asInstanceOf[Short]) case \"Long\" => udf(() => function().asInstanceOf[Long]) case \"Float\" => udf(() => function().asInstanceOf[Float]) case \"Double\" => udf(() => function().asInstanceOf[Double]) case \"Date\" => udf(() => function().asInstanceOf[Date]) case \"Timestamp\" => udf(() => function().asInstanceOf[Timestamp]) case _ => throw new IllegalArgumentException(f\"\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u0438\u043f\") }  spark.udf.register(udfConfig.name, myUDF) \/\/ \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u044f UDF  } <\/code><\/pre>\n<p>\u0418 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0449\u0435 10 \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u044b\u0445 \u043f\u043e\u0447\u0442\u0438 \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0438\u0445 \u0436\u0435 &#171;\u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u0432&#187;<br \/>\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0441\u043a\u0440\u0438\u043f\u0442, \u0447\u0442\u043e\u0431 \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0436\u0442\u043e \u0432 \u0440\u0443\u0447\u043d\u0443\u044e)<\/p>\n<pre><code class=\"scala\">import java.io.{File, PrintWriter}  object GenerateRegestrators extends App {  (0 to 10).toList.map {  num =>  val types = (0 to num).toList.map(_ => \"Any\").mkString(\", \") val lambdaVaues = (0 until  num).toList.map(n => f\"value${n}: Any\").mkString(\", \") val functionValues = (0 until  num).toList.map(n => f\"value${n}\").mkString(\", \")  f\"\"\"  |import org.apache.spark.sql.functions.udf  |  |import java.sql.{Date, Timestamp}  |import scala.reflect.runtime.universe  |import scala.tools.reflect.ToolBox  |  |object UDFReg${num} extends App with Configure {  |  |val indexcode = Integer.parseInt(args(0))  |  |import Util.UDFHelper._  |val udfConfig = udfsConfigs(indexcode)  |val functionCode = udfConfig.configToString()  |  |val toolbox = universe.runtimeMirror(getClass.getClassLoader).mkToolBox()  |  |val tree = toolbox.parse(functionCode)  |val compiledCode = toolbox.compile(tree)  |val function = compiledCode().asInstanceOf[Function${num}[${types}]]  |  | val myUDF = udfConfig.targetType match {  |case \"String\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[String])  |case \"Int\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Int])  |case \"Boolean\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Boolean])  |case \"Byte\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Byte])  |case \"Short\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Short])  |case \"Long\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Long])  |case \"Float\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Float])  |case \"Double\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Double])  |case \"Date\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Date])  |case \"Timestamp\" => udf((${lambdaVaues}) => function(${functionValues}).asInstanceOf[Timestamp])  |case _ => throw new IllegalArgumentException(f\"\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u0438\u043f\")  |}  |  |spark.udf.register(udfConfig.name, myUDF)  |  |}  |\"\"\".stripMargin   } .zipWithIndex .foreach { case (str, index) => val file = new File(f\".\/src\/main\/scala\/UDFReg${index}.scala\") val writer = new PrintWriter(file)  try { writer.write(str) } finally { writer.close() } }   }<\/code><\/pre>\n<p>\u0442\u0443\u0442 \u043f\u043e\u044f\u0441\u043d\u044f\u0442\u044c \u043d\u0435\u0447\u0435\u0433\u043e, \u043e\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044c\u0435\u043a\u0442\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438<br \/>\u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u0434\u043e\u043c\u0442\u043e\u044e\u0449\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b <code>UDFRegN<\/code>.<\/p>\n<h2>\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435:<\/h2>\n<p>\u0418\u0442\u043e\u0433\u043e \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u0438\u0448\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0433\u0434\u0435 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f UDF \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"scala\">object Example5 extends App with Configure {  import Util.UDFHelper._ udfsConfigs.zipWithIndex.foreach { \/\/\u0438\u043d\u0434\u0435\u043a\u0441 \u043d\u0443\u0436\u0435\u043d \u0447\u0442\u043e\u0431 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 args case (udfConfig, index) =>  udfConfig.fun.split(\"=>\", 2)(0).count(_ == ':') match {                \/\/\u0442\u0443\u0442 \u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0431\u043e\u0440 \u043a\u0430\u043a\u043e\u043c\u0443 \u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c case 0 => UDFReg0.main(Array( index.toString )) case 1 => UDFReg1.main(Array( index.toString )) case 2 => UDFReg2.main(Array( index.toString )) case 3 => UDFReg3.main(Array( index.toString )) case 4 => UDFReg4.main(Array( index.toString )) case 5 => UDFReg5.main(Array( index.toString )) case 6 => UDFReg6.main(Array( index.toString )) case 7 => UDFReg7.main(Array( index.toString )) case 8 => UDFReg8.main(Array( index.toString )) case 9 => UDFReg9.main(Array( index.toString )) case 10 => UDFReg10.main(Array( index.toString )) case _ => Unit }  }  spark.sql(\"select blue(), reverse('namoW tobor ociP ociP') AS rev, plus(1, 2), sum3(1, 1, 1)\").show     \/* \u0432\u044b\u0432\u043e\u0434  +------+--------------------+----------+-------------+ |blue()|                 rev|plus(1, 2)|sum3(1, 1, 1)| +------+--------------------+----------+-------------+ |00ff00|Pico Pico robot W...|         3|            3| +------+--------------------+----------+-------------+   *\/  } <\/code><\/pre>\n<p>\u0438 \u0442\u0430\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c.<\/p>\n<p>P.S. \u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u0433\u043b\u044f\u043d\u0443\u0442\u044c <a href=\"https:\/\/github.com\/PicoPicoRobotWoman\/UDFRegN\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/823978\/\"> https:\/\/habr.com\/ru\/articles\/823978\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0420\u0435\u043c\u0430\u0440\u043a\u0430:<\/h2>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e, \u043a\u0430\u043a \u0430\u0432\u0442\u043e\u0440 \u0440\u0435\u0448\u0438\u043b \u0441\u0432\u043e\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438 \u043d\u0435 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u043b\u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u0435\u0435. \u0422\u0430\u043a\u0436\u0435 \u0430\u0432\u0442\u043e\u0440 \u043d\u0435 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0438\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0435\u0448\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0438 \u043d\u0435 \u043d\u0430\u0441\u0442\u0430\u0438\u0432\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430. \u042d\u0442\u043e \u043b\u0438\u0448\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u0430\u0432\u0442\u043e\u0440\u043e\u043c, \u0438 \u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0437\u0434\u0435\u0441\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0410\u0432\u0442\u043e\u0440 \u043e\u0442\u043c\u0435\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0435 \u0441\u043c\u043e\u0433 \u043d\u0430\u0439\u0442\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u043d\u0438 \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0445, \u043d\u0438 \u043d\u0430 \u0430\u043d\u0433\u043b\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0425\u0430\u0431\u0440 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438. \u0421\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0434\u0438\u0441\u043a\u0443\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b, \u0438 \u0430\u0432\u0442\u043e\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0434 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<h2>\u0427\u0442\u043e \u044f \u043f\u044b\u0442\u0430\u044e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c:<\/h2>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 UDF <code>blue<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 &#171;0000FF&#187; \u043d\u0430 Scala API.&#187;<\/p>\n<pre><code class=\"scala\">object Example1 extends App with Configure {  spark.udf.register(\"blue\", udf(() => \"0000FF\")) \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0438 \u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c udf spark.sql(\"select blue()\").show() \/* \u0432\u044b\u0432\u043e\u0434: +------+ |blue()| +------+ |0000FF| +------+  *\/  }<\/code><\/pre>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u0441\u0430\u043c\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f UDF \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <code>code<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <code>\"() => \"0000FF\"\"<\/code>. \u0412 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0442\u0438\u043f\u0430 <code>Function0[String]<\/code> \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f UDF. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u043e\u044f \u0446\u0435\u043b\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u043b\u044f\u043c\u0431\u0434\u044b \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c\u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a.<\/p>\n<p>\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>&#171;(num: Int) => num * num&#187;<\/p>\n<\/li>\n<li>\n<p>&#171;(str: String) => str.reverse&#187;<\/p>\n<\/li>\n<li>\n<p>&#171;(num1: Double, str: String) => Math.pow(num1, str,size)&#187;<\/p>\n<\/li>\n<li>\n<p>\u0438 \u0442\u0434<\/p>\n<\/li>\n<\/ul>\n<h2>\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u043a\u0430\u043a\u0430\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430:<\/h2>\n<p>\u0440\u0430\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434<\/p>\n<pre><code class=\"scala\">import org.apache.spark.sql.functions.udf  import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox  object Example2 extends App with Configure {  def udfRegister(labdaCode: String): Unit = {  import universe._ val toolbox = universe.runtimeMirror(this.getClass.getClassLoader).mkToolBox()  val tree = toolbox.parse(labdaCode) val compiledCode = toolbox.compile(tree) val function = compiledCode().asInstanceOf[Function0[String]] \/\/\u0441\u0442\u043e\u0440\u043e\u043a\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u044c\u0441\u044f \u0432 Function0(String)   println(function()) \/\/ \u0432\u044b\u0432\u043e\u0434: 0000FF val udfBlue = udf(() => function()) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 udf   spark.udf.register(\"blue\", udfBlue)  }  udfRegister(\"() => \\\"0000FF\\\"\") spark.sql(\"select blue()\").show() \/\/ \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430  }<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430: <br \/><code>cannot assign instance of java.lang.invoke.SerializedLambda to field org.apache.spark.sql.catalyst.expressions.ScalaUDF.f of type scala.Function1 in instance of org.apache.spark.sql.catalyst.expressions.ScalaUDF<\/code> <\/p>\n<p>\u041e\u0448\u0438\u0431\u043a\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u043a\u043e\u0434\u0435 \u0438\u043b\u0438 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Spark \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c SerializedLambda \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430 scala.Function1 (\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441 \u043e\u0434\u043d\u0438\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c).<\/p>\n<p>\u0412 Spark \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. SerializedLambda \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<p>\u0412 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c <code>SerializedLambda<\/code> \u0435\u0441\u043c\u044c <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/invoke\/SerializedLambda.html\" rel=\"noopener noreferrer nofollow\">\u043a\u043b\u0430\u0441\u0441<\/a>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0432 Java \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441\u0441\u044b\u043b\u043e\u043a. \u042d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u043c Java \u043f\u0440\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439. (\u0441\u0443\u0434\u044f \u043f\u043e \u0441\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u0441\u043f\u0430\u0440\u043a\u0443 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438)<\/p>\n<p>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0437\u0430\u043f\u0443\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 <code>Function0[String]<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Spark \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 UDF. \u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0443\u0436\u0435 \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0441\u043d\u043e\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"scala\">import org.apache.spark.sql.functions.udf  import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox  object Example3 extends App with Configure {  val labdaCode = \"() => \\\"0000FF\\\"\"  import universe._ val toolbox = universe.runtimeMirror(this.getClass.getClassLoader).mkToolBox()  val tree = toolbox.parse(labdaCode) val compiledCode = toolbox.compile(tree) val function = compiledCode().asInstanceOf[Function0[String]] \/\/\u0441\u0442\u043e\u0440\u043e\u043a\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u044c\u0441\u044f \u0432 Function0(String)   println(function()) \/\/ \u0432\u044b\u0432\u043e\u0434: 0000FF val udfBlue = udf(() => function()) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 udf  spark.udf.register(\"blue\", udfBlue) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 udf  spark.sql(\"select blue()\").show() \/*\u0432\u044b\u0432\u043e\u0434:  +------+ |blue()| +------+ |0000FF| +------+   *\/  }<\/code><\/pre>\n<p>\u0412 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 <code>Example3<\/code> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0441\u0435 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0447\u0442\u043e \u0438 \u0432 <code>Example2<\/code>, \u043d\u043e \u043f\u0435\u0440\u0432\u043e\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0430 \u0432\u0442\u043e\u0440\u043e\u0435 \u043d\u0435\u0442 \u0447\u0442\u043e \u0432\u0432\u043e\u0434\u0438\u0442 \u0435\u0449\u0435 \u0432 \u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u0437\u0430\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e<\/p>\n<pre><code class=\"scala\">import org.apache.spark.sql.functions.udf  import scala.reflect.runtime.universe import scala.tools.reflect.ToolBox  object Example4 extends App with Configure {  if (true) {  val labdaCode = \"() => \\\"0000FF\\\"\"  import universe._ val toolbox = universe.runtimeMirror(this.getClass.getClassLoader).mkToolBox()  val tree = toolbox.parse(labdaCode) val compiledCode = toolbox.compile(tree) val function = compiledCode().asInstanceOf[Function0[String]] \/\/\u0441\u0442\u043e\u0440\u043e\u043a\u0430 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u044c\u0441\u044f \u0432 Function0(String)   println(function()) \/\/ \u0432\u044b\u0432\u043e\u0434: 0000FF val udfBlue = udf(() => function()) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 udf  spark.udf.register(\"blue\", udfBlue) \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0435 \u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 udf  }  spark.sql(\"select blue()\").show() \/\/ \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430  }<\/code><\/pre>\n<p>\u043a\u0430\u043a \u0438 Example3 Example4 \u043d\u0435\u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u043d\u043e \u043f\u043e\u0447\u0435\u043c\u0443 \u0442\u043e \u0431\u043b\u043e\u043a if \u0441\u043d\u043e\u0432\u0430 \u0432\u0432\u0435\u0434\u0435\u0442 \u043a \u043e\u0448\u0438\u0431\u043a\u0435<br \/>\u0442\u0430\u043a \u0436\u0435 \u043a \u043e\u0448\u0438\u0431\u043a\u0430\u043c \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0446\u0438\u043a\u043b\u043e\u0432 \u0438 \u043c\u043e\u043d\u0430\u0434, Try \u0438 \u0442\u0434 (\u043d\u043e \u0442\u0443\u0442 \u044f \u044d\u0442\u043e \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443)<\/p>\n<p>\u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u0441\u0435 \u0441\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043a \u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c <code>function<\/code> \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b \u043d\u0435 \u044f\u0432\u043b\u044f\u043b\u0430\u0441\u044c \u0431\u044b <code>SerializedLambda<\/code>  \u0438 \u0435\u0441\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0442\u044c \u043b\u044f\u043c\u0431\u0434\u044b\/\u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043c\u043a\u0435\u0442\u043e\u0434\u0435 main<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435\u043b\u044c\u0437\u044f \u0438\u0437 \u0441\u043e\u0437\u0434\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u043b\u043e\u043a\u0430\u0445 if, try, for, \u043c\u043e\u043d\u0430\u0434\u0430\u0445 \u0438 \u0442\u0434.<\/p>\n<\/li>\n<\/ul>\n<p>\u0445\u043e\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 blue, \u043c\u043e\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043b\u044e\u0431\u0443\u044e \u043b\u044f\u043c\u0431\u0434\u0443 (\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043e\u0442 0 \u0434\u043e 10 \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 UDF10) \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0441\u0442\u0440\u043e\u043a\u0438<\/p>\n<h2>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445:<\/h2>\n<p>\u042f \u0445\u043e\u0447\u0443 \u0447\u0442\u043e\u0431\u044b \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u043e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON \u0438 \u043f\u0443\u0442\u0441\u044c \u0443 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:<\/p>\n<pre><code class=\"json\">[ \/\/\u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0439\u0442\u0438 \u043c\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0438\u0439\u0442\u0438 \u0432\u043e\u043e\u0431\u0449\u0435   {     \"name\": \"blue\", \/\/\u0438\u043c\u044f \u0431\u043b\u044f udf     \"targetType\": \"String\", \/\/\u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0439     \"fun\": \"() => \\\"00ff00\\\"\", \/\/\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430 \u043b\u044f\u043c\u0431\u0434\u0430     \"imports\": [\"...\", \"...\"] \/\/\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0435, \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b   },   \/\/ \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u0435\u044e\u0442 \u0442\u0430\u043a\u0443\u044e \u0436\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443   {     \"name\": \"reverse\",     \"targetType\": \"String\",     \"fun\": \"(str:String) => str.reverse\"   },   {     \"name\": \"plus\",     \"targetType\": \"Int\",     \"fun\": \"(i1:Int, i2:Int) => i1 + i2\"   },   {     \"name\": \"sum3\",     \"types\": \"Int,Int,Int\",     \"targetType\": \"Int\",     \"fun\": \"(i1:Int, i2:Int, i3:Int) => i1 + i2 + i3\"   } ]<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 Json:<\/p>\n<pre><code class=\"scala\">\/\/ \u0434\u0443\u043c\u0430\u044e \u0442\u0443\u0442 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u0435 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 case class UDFConfig(name: String,    targetType: String,  fun: String,  imports: List[String] = List.empty) <\/code><\/pre>\n<p>\u0414\u043b\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 json \u0444\u0430\u0439\u043b\u0430 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <code>json4s<\/code> \u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043b\u0430\u0441\u0441<\/p>\n<pre><code class=\"scala\">package Util  import org.json4s.Formats import org.json4s.native.JsonMethods.parse  \/\/\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0431\u044c\u0435\u043a\u0442 \u0434\u043b\u044f \u043a\u043e\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 json \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043e\u0431\u044c\u0435\u043a\u0442\u043e\u0432 \u0442\u0438\u043f\u0430 JsonType  object JsonHelper {  private def jsonToListConvert[JsonType](json: String)(implicit mf: Manifest[JsonType], formats: Formats): List[Either[Throwable, JsonType]] = { parse(json) .extract[List[JsonType]] .map(Right(_)) }  implicit class JsonConverter(json: String) {  def jsonToList[JsonType]()(implicit mf: Manifest[JsonType], formats: Formats): List[Either[Throwable, JsonType]]= { jsonToListConvert[JsonType](json) }  }  }<\/code><\/pre>\n<p>\u0418 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0440\u0435\u0439\u0442 <code>Configure<\/code> \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u044b\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b<\/p>\n<pre><code class=\"scala\">\u0418import config.UDFConfig import org.apache.spark.sql.SparkSession import org.json4s.DefaultFormats  import scala.io.Source  trait Configure {  lazy val spark = SparkSession .builder() .appName(\"Example UDF runtime compile\") .master(\"local[*]\") .getOrCreate() lazy val sc = spark.sparkContext \/\/ \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u043f\u0440\u0430\u043a \u0441\u0435\u0441\u0441\u0438\u044e \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442  lazy val pathUdfsJson = \".\/UDFs.json\" \/\/\u043f\u0443\u0442\u044c \u0434\u043e json c \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438  implicit lazy val formats = DefaultFormats \/\/ \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0434\u043b\u044f json4s, \u0432 \u043c\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0445\u0432\u0430\u0442\u0435\u0430\u0435\u0442 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 import Util.JsonHelper._  lazy val udfJson = getJson(pathUdfsJson) \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0430\u043c json \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 lazy val udfsConfigs: List[UDFConfig] = udfJson .jsonToList[UDFConfig] .filter(_.isRight) .map { case Right(udfconfig) => udfconfig } \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 udfconfig   \/\/ \u044d\u0442\u043e\u0442 \u043e\u0431\u0435\u043a\u0442 \u043c\u043d\u0435 \u0438 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f  \/\/\u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432   private def getJson(path: String): String = { val file = Source.fromFile(path) try { file.getLines().mkString(\"\\n\") } finally { file.close() } }  }<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043e\u0431\u044c\u0435\u043a\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 udfconfig \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u0442 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u0440\u0430\u0442\u0430\u0439\u043c\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0432 FunctionN \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438<\/p>\n<pre><code class=\"scala\">package Util  import config.UDFConfig  object UDFHelper {  private def configToStringConvert(udfConfig: UDFConfig): String = {  \/\/\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432\u0441\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b \u0434\u043b\u044f \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 val imports = udfConfig .imports  \/\/ \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u044b \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0430 .map(_.trim.stripPrefix(\"import \").trim) \/\/ \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0441 \u043b\u0435\u0432\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u0435\u0441\u0442\u044c .distinct  \/\/ \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 .map(imp => f\"import ${imp}\")            \/\/ \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0438\u0440\u0443\u0435\u043c \u0441\u043b\u0435\u0432\u0430 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0441\u043b\u043e\u0432\u043e .mkString(\"\\n\")                          \/\/ \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0435\u043d\u044f\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u0441\u0442\u0443\u043f  val Array(params, functionBody) = udfConfig.fun.split(\"=>\", 2).map(_.trim) \/\/ \u041e\u0442\u0434\u0435\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043e\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445  val paramsTypes: Seq[(String, String)] = params .stripPrefix(\"(\") \/\/ \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u0441 \u043b\u0435\u0432\u0430 \u0441\u043a\u043e\u0431\u043a\u0443 .stripSuffix(\")\") \/\/ \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u0441 \u043f\u0440\u0430\u0432\u0430 \u0441\u043a\u043e\u0431\u043a\u0443 .split(\",\")       \/\/ \u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b .map(_.trim)      \/\/ \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u043b\u0438\u0448\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u0435\u043b\u044b .map { case \"\"<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-379672","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/379672","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=379672"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/379672\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=379672"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=379672"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=379672"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}