Browse Source

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 năm trước cách đây
mục cha
commit
a2ed676862
1 tập tin đã thay đổi với 33 bổ sung0 xóa
  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
 because script queries aren't able to use the inverted index to limit the
 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.