You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Milles (Jira)" <ji...@apache.org> on 2024/08/22 15:19:00 UTC

[jira] [Updated] (GROOVY-11453) Spread-safe operator differences and efficiencies

     [ https://issues.apache.org/jira/browse/GROOVY-11453?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Eric Milles updated GROOVY-11453:
---------------------------------
    Description: 
The spread-safe operator -- aka {{a*.b}} or {{a*.b(c)}} -- has some differences and inefficiencies.

# When the receiver is null, the expression produces null for dynamic mode and an empty list for static compilation.  Can this difference be safely resolved?
# When the method return type is {{void}}, there is no need for a list to collect up nulls.  This is producing "Useless object stored in variable var$1" warnings from SpotBugs.  The only benefit of this is the ability to detect the number of elements.
# The SC bytecode has a redundant null test in it.  Since a for loop is also null-safe, guarding the loop bytecode by a null check is producing "Redundant check for null" warnings from SpotBugs.  *NOTE:* If (1) above is changed in the SC classgen, the null check may not be redundant as it would guard list construction.

For reference, {{object*.method(arguments)}} is written by the static compiler like this:
{code:groovy}
def result = new ArrayList()
if (object != null) {
  for (element in object) { // also null-safe
    result.add(element?.method(arguments)
  }
}
result
{code}

And the dynamic impl: https://github.com/apache/groovy/blob/f46103d31b7574ce883ff3b6c01fa8a412f225be/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java#L189

GROOVY-7177

  was:
The spread-safe operator -- aka {{a*.b}} or {{a*.b(c)}} -- has some differences and inefficiencies.

# When the receiver is null, the expression produces null for dynamic mode and an empty list for static compilation.  Can this difference be safely resolved?
# When the method return type is {{void}}, there is no need for a list to collect up nulls.  This is producing "Useless object stored in variable var$1" warnings from SpotBugs.  The only benefit of this is the ability to detect the number of elements.
# The SC bytecode has a redundant null test in it.  Since a for loop is also null-safe, guarding the loop bytecode by a null check is producing "Redundant check for null" warnings from SpotBugs.  *NOTE:* If (1) above is changed in the SC classgen, the null check may not be redundant as it would guard list construction.

For reference, {{object*.method(arguments)}} is written by the static compiler like this:
{code:groovy}
def result = new ArrayList()
if (object != null) {
  for (element in object) { // also null-safe
    result.add(element?.method(arguments)
  }
}
result
{code}

GROOVY-7177


> Spread-safe operator differences and efficiencies
> -------------------------------------------------
>
>                 Key: GROOVY-11453
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11453
>             Project: Groovy
>          Issue Type: Bug
>            Reporter: Eric Milles
>            Assignee: Eric Milles
>            Priority: Major
>
> The spread-safe operator -- aka {{a*.b}} or {{a*.b(c)}} -- has some differences and inefficiencies.
> # When the receiver is null, the expression produces null for dynamic mode and an empty list for static compilation.  Can this difference be safely resolved?
> # When the method return type is {{void}}, there is no need for a list to collect up nulls.  This is producing "Useless object stored in variable var$1" warnings from SpotBugs.  The only benefit of this is the ability to detect the number of elements.
> # The SC bytecode has a redundant null test in it.  Since a for loop is also null-safe, guarding the loop bytecode by a null check is producing "Redundant check for null" warnings from SpotBugs.  *NOTE:* If (1) above is changed in the SC classgen, the null check may not be redundant as it would guard list construction.
> For reference, {{object*.method(arguments)}} is written by the static compiler like this:
> {code:groovy}
> def result = new ArrayList()
> if (object != null) {
>   for (element in object) { // also null-safe
>     result.add(element?.method(arguments)
>   }
> }
> result
> {code}
> And the dynamic impl: https://github.com/apache/groovy/blob/f46103d31b7574ce883ff3b6c01fa8a412f225be/src/main/java/org/codehaus/groovy/runtime/ScriptBytecodeAdapter.java#L189
> GROOVY-7177



--
This message was sent by Atlassian Jira
(v8.20.10#820010)