Răsfoiți Sursa

Docs: Explain painless's method dispatch (#23021)

Painless uses Ruby-like method dispatch (reciever type, method name,
and arity) rather than Java-like (reciever type, method name, and
argument compile time types) or Groovy-like method dispatch (receiver
type, method name, and argument run time types). We do this for
mostly good reasons but we never documented it.

Relates to #22720
Nik Everett 8 ani în urmă
părinte
comite
a2ed676862
1 a modificat fișierele cu 33 adăugiri și 0 ștergeri
  1. 33 0
      docs/reference/modules/scripting/painless.asciidoc

+ 33 - 0
docs/reference/modules/scripting/painless.asciidoc

@@ -351,3 +351,36 @@ Note: all of the `_update_by_query` examples above could really do with a
 <<query-dsl-script-query>> it wouldn't be as efficient as using any other query
 <<query-dsl-script-query>> it wouldn't be as efficient as using any other query
 because script queries aren't able to use the inverted index to limit the
 because script queries aren't able to use the inverted index to limit the
 documents that they have to check.
 documents that they have to check.
+
+[float]
+[[modules-scripting-painless-dispatch]]
+=== How painless dispatches functions
+
+Painless uses receiver, name, and https://en.wikipedia.org/wiki/Arity[arity] to
+for method dispatch. For example, `s.foo(a, b)` is resolved by first getting
+the class of `s` and then looking up the method `foo` with two parameters. This
+is different from Groovy which uses the
+https://en.wikipedia.org/wiki/Multiple_dispatch[runtime types] of the
+parameters and Java which uses the compile time types of the parameters.
+
+The consequence of this that Painless doesn't support overloaded methods like
+Java, leading to some trouble when it whitelists classes from the Java
+standard library. For example, in Java and Groovy, `Matcher` has two methods:
+`group(int)` and `group(String)`. Painless can't whitelist both of them methods
+because they have the same name and the same number of parameters. So instead it
+has <<painless-api-reference-Matcher-group-1, `group(int)`>> and
+<<painless-api-reference-Matcher-namedGroup-1, `namedGroup(String)`>>.
+
+We have a few justifications for this different way of dispatching methods:
+
+1. It makes operating on `def` types simpler and, presumably, faster. Using
+receiver, name, and arity means when Painless sees a call on a `def` objects it
+can dispatch the appropriate method without having to do expensive comparisons
+of the types of the parameters. The same is true for invocations with `def`
+typed parameters.
+2. It keeps things consistent. It would be genuinely weird for Painless to
+behave like Groovy if any `def` typed parameters were involved and Java
+otherwise. It'd be slow for it to behave like Groovy all the time.
+3. It keeps Painless maintainable. Adding the Java or Groovy like method
+dispatch *feels* like it'd add a ton of complexity which'd make maintenance and
+other improvements much more difficult.