anchor.diff:  <5> using the subscript operator with index 1 allows retrieving the user name
   <6> we can use the subscript operator to write to a property thanks to the delegation to `putAt`
   <7> and check that it's really the property `name` which was changed
  +
  +=== Safe index operator
  +
  +Groovy 3.0.0 introduces safe indexing operator, i.e. `?[]`, which is similar to `?.`. For example:
  +
  +[source,groovy]
  +--------------------------------------
  +String[] array = ['a', 'b']
  +assert 'b' == array?[1]      // get using normal array index
  +array?[1] = 'c'              // set using normal array index
  +assert 'c' == array?[1]
  +
  +array = null
  +assert null == array?[1]     // return null for all index values
  +array?[1] = 'c'              // quietly ignore attempt to set value
  +assert null == array?[1]
  +
  +def personInfo = [name: 'Daniel.Sun', location: 'Shanghai']
  +assert 'Daniel.Sun' == personInfo?['name']      // get using normal map index
  +personInfo?['name'] = 'sunlan'                  // set using normal map index
  +assert 'sunlan' == personInfo?['name']
  +
  +personInfo = null
  +assert null == personInfo?['name']              // return null for all map values
  +personInfo?['name'] = 'sunlan'                  // quietly ignore attempt to set value
  +assert null == personInfo?['name']
  +--------------------------------------
  +
   
   === Membership operator
   
  
positive.code: |   | `.` &#160; `.&` &#160; `.@` | member access, method closure, field/attribute access
  |   | `?.` &#160; `\*` &#160; `*.` &#160; `*:` | safe dereferencing, spread, spread-dot, spread-map
  |   | `~` &#160; `!` &#160; `(type)` | bitwise negate/pattern, not, typecast
  |   | `[]` &#160; `++` &#160; `--` | list/map/array index, post inc/decrement
  | 2 | `**` | power
  | 3 | `++` &#160; `--` &#160; `+` &#160; `-` | pre inc/decrement, unary plus, unary minus
  | 4 | `*` &#160; `/` &#160; `%` | multiply, div, remainder
  | 5 | `+` &#160; `-` | addition, subtraction
  | 6 | `<<` &#160; `>>` &#160; `>>>` &#160; `..` &#160; `..<` | left/right (unsigned) shift, inclusive/exclusive range
  | 7 | `<` &#160; `\<=` &#160; `>` &#160; `>=` &#160; `in` &#160; `instanceof` &#160; `as` | less/greater than/or equal, in, instanceof, type coercion
  | 8 | `==` &#160; `!=` &#160; `pass:[<=>]` | equals, not equals, compare to
  |   | `=~` &#160; `==~` | regex find, regex match
  | 9 | `&` | binary/bitwise and
  | 10 | `^` | binary/bitwise xor
  
negative.code: ----
  include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=simple_relational_op,indent=0]
  ----
  
  Both `===` and `!==` are supported which are the same as calling the `is()` method,
  and negating a call to the `is()` method respectively.
  
  [source,groovy]
  --------------------------------------
  import groovy.transform.EqualsAndHashCode
  
  @EqualsAndHashCode
  class Creature { String type }
  
  def cat = new Creature(type: 'cat')
  def copyCat = cat
  def lion = new Creature(type: 'cat')
  
  assert cat.equals(lion) // Java logical equality
  assert cat == lion      // Groovy shorthand operator
  
  assert cat.is(copyCat)  // Groovy identity
  assert cat === copyCat  // operator shorthand
  assert cat !== lion     // negated operator shorthand
  --------------------------------------
  
  == Logical operators
  
  