Skip to content

Commit

Permalink
Docs: Explain painless's method dispatch (#23021)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nik9000 committed Feb 7, 2017
1 parent 4612931 commit 431020c
Showing 1 changed file with 33 additions and 0 deletions.
33 changes: 33 additions & 0 deletions docs/reference/modules/scripting/painless.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -356,3 +356,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.

0 comments on commit 431020c

Please sign in to comment.