Skip to content

Commit 2a8d84f

Browse files
committed
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
1 parent f96cd45 commit 2a8d84f

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

docs/reference/modules/scripting/painless.asciidoc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,35 @@ Note that unsafe classes and methods are not included, there is no support for:
345345
* Manipulation of processes and threads
346346
* Input/Output
347347
* Reflection
348+
349+
[[modules-scripting-painless-dispatch]]
350+
=== How painless dispatches functions
351+
352+
Painless uses receiver, name, and https://en.wikipedia.org/wiki/Arity[arity] to
353+
for method dispatch. For example, `s.foo(a, b)` is resolved by first getting
354+
the class of `s` and then looking up the method `foo` with two parameters. This
355+
is different from Groovy which uses the
356+
https://en.wikipedia.org/wiki/Multiple_dispatch[runtime types] of the
357+
parameters and Java which uses the compile time types of the parameters.
358+
359+
The consequence of this that Painless doesn't support overloaded methods like
360+
Java, leading to some trouble when it whitelists classes from the Java
361+
standard library. For example, in Java and Groovy, `Matcher` has two methods:
362+
`group(int)` and `group(String)`. Painless can't whitelist both of them methods
363+
because they have the same name and the same number of parameters. So instead it
364+
has <<painless-api-reference-Matcher-group-1, `group(int)`>> and
365+
<<painless-api-reference-Matcher-namedGroup-1, `namedGroup(String)`>>.
366+
367+
We have a few justifications for this different way of dispatching methods:
368+
369+
1. It makes operating on `def` types simpler and, presumably, faster. Using
370+
receiver, name, and arity means when Painless sees a call on a `def` objects it
371+
can dispatch the appropriate method without having to do expensive comparisons
372+
of the types of the parameters. The same is true for invocations with `def`
373+
typed parameters.
374+
2. It keeps things consistent. It would be genuinely weird for Painless to
375+
behave like Groovy if any `def` typed parameters were involved and Java
376+
otherwise. It'd be slow for it to behave like Groovy all the time.
377+
3. It keeps Painless maintainable. Adding the Java or Groovy like method
378+
dispatch *feels* like it'd add a ton of complexity which'd make maintenance and
379+
other improvements much more difficult.

0 commit comments

Comments
 (0)