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

Paul King updated GROOVY-7433:
------------------------------
    Description: 
When treating Strings as an iterable collection of characters, Groovy provides 
each character as a String of size 1, e.g.:
{code}
assert "hello".toList() == ['h', 'e', 'l', 'l', 'o']
assert "hello".toList()[0].class.name == 'java.lang.String'
"hello".each {
  assert it instanceof String
}
{code}
There are just 3 methods where this isn't the case:
takeWhile, dropWhile and collectReplacements.
These methods supply a Character instead, e.g.:
{code}
assert "he" == "hello".takeWhile {
  assert it instanceof Character
  it != 'l'
}
{code}
This issue is to fix this inconsistency. This is a breaking change but of low 
impact:
* Most expressions within the closure such as {{it != 'A'}} or {{it < 'B'}} 
will produce the same results regardless of whether a String or character is 
passed in.
* Expressions using methods from the String class would have needed an "as 
String" or ".toString()" coercion/conversion. These will still work unchanged 
but the coercion will no longer be required.(Which aligns them with the 
expressions for all other String iteration methods.)
* Closures with an explicit String arg currently don't work but would work 
after the change.
* Closures making use of instance methods from the Character class are breaking 
but those methods are "charValue()" and "compareTo(Character anotherCharacter)" 
and are likely rarely used (there use would be non-idiomatic Groovy).

In any case, I propose supporting the detection of supplied Closures having a 
char or Character argument in which case the char would be passed in as now. 
This would make fixing the break trivial for those cases.

  was:
When treating Strings as an iterable collection of characters, Groovy provides 
each character as a String of size 1, e.g.:
{code}
assert "hello".toList() == ['h', 'e', 'l', 'l', 'o']
assert "hello".toList()[0].class.name == 'java.lang.String'
"hello".each {
  assert it instanceof String
}
{code}
There are just 3 methods where this isn't the case:
takeWhile, dropWhile and collectReplacements.
These methods supply a Character instead, e.g.:
{code}
assert "he" == "hello".takeWhile {
  assert it instanceof Character
  it != 'l'
}
{code}
This issue is to fix this inconsistency. This is a breaking change but of low 
impact:
* Most expressions within the closure such as {{it != 'A'}} or {{it < 'B'}} 
will produce the same results regardless of whether a String or character is 
passed in.
* Expressions using methods from the String class would have needed an "as 
String" or ".toString()" coercion/conversion. These will still work unchanged 
but the coercion will no longer be required.(Which aligns them with the 
expressions for all other String iteration methods.)
* Closures with an explicit String arg currently don't work but would work 
after the change.
* Closures making use of instance methods from the Character class are breaking 
but those methods are "charValue()" and "compareTo(Character anotherCharacter)" 
and are likely rarely used (there use would be non-idiomatic Groovy).
In any case, I propose supporting the detection of supplied Closures having a 
char or Character argument in which case the char would be passed in as now. 
This would make fixing the break trivial for those cases.


> API inconsistency between takeWhile, dropWhile and collectReplacements for 
> CharSequences
> ----------------------------------------------------------------------------------------
>
>                 Key: GROOVY-7433
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7433
>             Project: Groovy
>          Issue Type: Bug
>          Components: groovy-jdk
>            Reporter: Paul King
>            Assignee: Paul King
>              Labels: breaking
>
> When treating Strings as an iterable collection of characters, Groovy 
> provides each character as a String of size 1, e.g.:
> {code}
> assert "hello".toList() == ['h', 'e', 'l', 'l', 'o']
> assert "hello".toList()[0].class.name == 'java.lang.String'
> "hello".each {
>   assert it instanceof String
> }
> {code}
> There are just 3 methods where this isn't the case:
> takeWhile, dropWhile and collectReplacements.
> These methods supply a Character instead, e.g.:
> {code}
> assert "he" == "hello".takeWhile {
>   assert it instanceof Character
>   it != 'l'
> }
> {code}
> This issue is to fix this inconsistency. This is a breaking change but of low 
> impact:
> * Most expressions within the closure such as {{it != 'A'}} or {{it < 'B'}} 
> will produce the same results regardless of whether a String or character is 
> passed in.
> * Expressions using methods from the String class would have needed an "as 
> String" or ".toString()" coercion/conversion. These will still work unchanged 
> but the coercion will no longer be required.(Which aligns them with the 
> expressions for all other String iteration methods.)
> * Closures with an explicit String arg currently don't work but would work 
> after the change.
> * Closures making use of instance methods from the Character class are 
> breaking but those methods are "charValue()" and "compareTo(Character 
> anotherCharacter)" and are likely rarely used (there use would be 
> non-idiomatic Groovy).
> In any case, I propose supporting the detection of supplied Closures having a 
> char or Character argument in which case the char would be passed in as now. 
> This would make fixing the break trivial for those cases.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to