painless-syntax.asciidoc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. [[modules-scripting-painless-syntax]]
  2. === Painless Syntax
  3. experimental[The Painless scripting language is new and is still marked as experimental. The syntax or API may be changed in the future in non-backwards compatible ways if required.]
  4. [float]
  5. [[painless-types]]
  6. === Variable types
  7. Painless supports all of https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html[Java's types],
  8. including array types, but adds some additional built-in types.
  9. [float]
  10. [[painless-def]]
  11. ==== Def
  12. The dynamic type `def` serves as a placeholder for any other type. It adopts the behavior
  13. of whatever runtime type it represents.
  14. [float]
  15. [[painless-strings]]
  16. ==== String
  17. String constants can be declared with single quotes, to avoid escaping horrors with JSON:
  18. [source,painless]
  19. ---------------------------------------------------------
  20. def mystring = 'foo';
  21. ---------------------------------------------------------
  22. [float]
  23. [[painless-lists]]
  24. ==== List
  25. Lists can be created explicitly (e.g. `new ArrayList()`) or initialized similar to Groovy:
  26. [source,painless]
  27. ---------------------------------------------------------
  28. def list = [1,2,3];
  29. ---------------------------------------------------------
  30. Lists can also be accessed similar to arrays: they support subscript and `.length`:
  31. [source,painless]
  32. ---------------------------------------------------------
  33. def list = [1,2,3];
  34. return list[0]
  35. ---------------------------------------------------------
  36. [float]
  37. [[painless-maps]]
  38. ==== Map
  39. Maps can be created explicitly (e.g. `new HashMap()`) or initialized similar to Groovy:
  40. [source,painless]
  41. ---------------------------------------------------------
  42. def person = ['name': 'Joe', 'age': 63];
  43. ---------------------------------------------------------
  44. Map keys can also be accessed as properties.
  45. [source,painless]
  46. ---------------------------------------------------------
  47. def person = ['name': 'Joe', 'age': 63];
  48. person.retired = true;
  49. return person.name
  50. ---------------------------------------------------------
  51. Map keys can also be accessed via subscript (for keys containing special characters):
  52. [source,painless]
  53. ---------------------------------------------------------
  54. return map['something-absurd!']
  55. ---------------------------------------------------------
  56. [float]
  57. [[painless-pattern]]
  58. ==== Pattern
  59. Regular expression constants are directly supported:
  60. [source,painless]
  61. ---------------------------------------------------------
  62. Pattern p = /[aeiou]/
  63. ---------------------------------------------------------
  64. Patterns can only be created via this mechanism. This ensures fast performance, regular expressions
  65. are always constants and compiled efficiently a single time.
  66. [float]
  67. [[modules-scripting-painless-regex-flags]]
  68. ==== Pattern flags
  69. You can define flags on patterns in Painless by adding characters after the
  70. trailing `/` like `/foo/i` or `/foo \w #comment/iUx`. Painless exposes all the
  71. flags from
  72. https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html[Java's Pattern class]
  73. using these characters:
  74. [cols="<,<,<",options="header",]
  75. |=======================================================================
  76. | Character | Java Constant | Example
  77. |`c` | CANON_EQ | `'å' ==~ /å/c` (open in hex editor to see)
  78. |`i` | CASE_INSENSITIVE | `'A' ==~ /a/i`
  79. |`l` | LITERAL | `'[a]' ==~ /[a]/l`
  80. |`m` | MULTILINE | `'a\nb\nc' =~ /^b$/m`
  81. |`s` | DOTALL (aka single line) | `'a\nb\nc' =~ /.b./s`
  82. |`U` | UNICODE_CHARACTER_CLASS | `'Ɛ' ==~ /\\w/U`
  83. |`u` | UNICODE_CASE | `'Ɛ' ==~ /ɛ/iu`
  84. |`x` | COMMENTS (aka extended) | `'a' ==~ /a #comment/x`
  85. |=======================================================================
  86. [float]
  87. [[painless-operators]]
  88. === Operators
  89. All of Java's https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html[operators] are
  90. supported with the same precedence, promotion, and semantics.
  91. There are only a few minor differences and add-ons:
  92. * `==` behaves as Java's for numeric types, but for non-numeric types acts as https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-[`Object.equals()`]
  93. * `===` and `!==` support exact reference comparison (e.g. `x === y`)
  94. * `=~` true if a portion of the text matches a pattern (e.g. `x =~ /b/`)
  95. * `==~` true if the entire text matches a pattern (e.g. `x ==~ /[Bb]ob/`)
  96. [float]
  97. [[painless-control-flow]]
  98. === Control flow
  99. Java's https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html[control flow statements] are supported, with the exception
  100. of the `switch` statement.
  101. In addition to Java's `enhanced for` loop, the `for in` syntax from groovy can also be used:
  102. [source,painless]
  103. ---------------------------------------------------------
  104. for (item : list) {
  105. ...
  106. }
  107. ---------------------------------------------------------
  108. [float]
  109. [[painless-functions]]
  110. === Functions
  111. Functions can be declared at the beginning of the script, for example:
  112. [source,painless]
  113. ---------------------------------------------------------
  114. boolean isNegative(def x) { x < 0 }
  115. ...
  116. if (isNegative(someVar)) {
  117. ...
  118. }
  119. ---------------------------------------------------------
  120. [float]
  121. [[painless-lambda-expressions]]
  122. === Lambda expressions
  123. Lambda expressions and method references work the same as https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Java's].
  124. [source,painless]
  125. ---------------------------------------------------------
  126. list.removeIf(item -> item == 2);
  127. list.removeIf((int item) -> item == 2);
  128. list.removeIf((int item) -> { item == 2 });
  129. list.sort((x, y) -> x - y);
  130. list.sort(Integer::compare);
  131. ---------------------------------------------------------
  132. Method references to functions within the script can be accomplished using `this`, e.g. `list.sort(this::mycompare)`.