Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define islowercase for String #46444

Closed
jariji opened this issue Aug 23, 2022 · 12 comments
Closed

Define islowercase for String #46444

jariji opened this issue Aug 23, 2022 · 12 comments
Labels
strings "Strings!"

Comments

@jariji
Copy link
Contributor

jariji commented Aug 23, 2022

In 1.7 islowercase is defined for characters but not strings. It would be useful to have for strings.

(From discourse.)

@PallHaraldsson
Copy link
Contributor

PallHaraldsson commented Aug 23, 2022

FYI:

julia> all(islowercase, "Páll")
false

julia> all(islowercase, "páll")
true

# first I thought it might be, but it (and the above) not obvious to all:

julia> islowercase.("Páll")
ERROR: MethodError: no method matching islowercase(::String)

# since non-obvious feel free to make a PR for, and corresponding isuppercase:

julia> import Unicode.islowercase

julia> islowercase(s::AbstractString) = all(islowercase, s)

@KristofferC
Copy link
Member

I also think lowercase has to do with a character and not a string. Using all together with islowercase is therefore the natural way of expressing this.

@oscardssmith
Copy link
Member

IMO, it's very odd that lowercase("Hi") works but islower("Hi") doesn't. Adding to triage to decide what we want to do about this.

@oscardssmith oscardssmith reopened this Aug 30, 2022
@oscardssmith oscardssmith added strings "Strings!" triage This should be discussed on a triage call labels Aug 30, 2022
@stevengj
Copy link
Member

stevengj commented Aug 30, 2022

On the other hand, the definition that people seem to want in many cases is:

all(c -> lowercase(c) == c, s) # equivalent to lowercase(s) == s

which is not the same thing as all(islowercase, s):

This ambiguity may be a good argument for not defining islowercase(::String).

@stevengj
Copy link
Member

stevengj commented Aug 30, 2022

Consider

julia> "élan" == lowercase("élan")
true

julia> all(c -> c == lowercase(c), "élan")
true

julia> all(islowercase, "élan")
false

If you are confused by this, realize that "élan" includes the unicode combining character U+0301. On the other hand, if you use the NFC normalization "élan" of this string (which uses the accented character U+00E9), you get:

julia> all(islowercase, "élan")
true

(But if you define islowercase(s::String) = s == lowercase(s), then it will be inconsistent with the definition of islowercase for characters.)

@gbaraldi
Copy link
Member

gbaraldi commented Aug 30, 2022

julia> all(islowercase, "élan")
false

Is probably a wrong result for most people. which is something to worry about

@stevengj
Copy link
Member

stevengj commented Aug 30, 2022

@gbaraldi, is this the "wrong" result:

julia> all(islowercase, "1")
false

julia> islowercase('1')
false

julia> all(islowercase, "́") # "\acute"
false

julia> islowercase('́') # '\acute'
false

?

@JeffBezanson
Copy link
Member

We explicitly decided to remove these kinds of predicates for strings in v0.6.

@PallHaraldsson
Copy link
Contributor

PallHaraldsson commented Aug 31, 2022

Does it make sense to rather define as (and vise versa):

islowercase(s::AbstractString) = any(!isuppercase, s)  # also faster, and different

@stevengj
Copy link
Member

stevengj commented Aug 31, 2022

We explicitly decided to remove these kinds of predicates for strings in v0.6.

In particular, this was done in #20342, following the discussion in #14156.

Does it make sense to rather define as (and vise versa): islowercase(s::AbstractString) = any(!isuppercase, s)

No, because then islowercase("1") will return true and islowercase('1') will return false, which seems inconsistent.

In general, the fact that there are so many variations on what it might mean for a string to "be lowercase" (e.g. all(islowercase, s) or !any(isuppercase, s) or any(!isuppercase, s)) is a good argument by itself for not defining this method.

@stevengj
Copy link
Member

Note that Julia isn't alone here. See e.g. Swift’s string.lowercased() method and char.isLowercased property. Or the C# String.ToLower() and Char.IsLower methods. Or the Go ToLower(str) and IsLower(char) functions. Or …

The odd one out is Python, which does have a string.islower() method (equivalent to all(islowercase, string)), but that's probably because Python doesn't have a character type.

@JeffBezanson
Copy link
Member

I think this can be closed. I don't see an overwhelmingly convincing reason to revisit this decision.

@JeffBezanson JeffBezanson removed the triage This should be discussed on a triage call label Sep 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
strings "Strings!"
Projects
None yet
Development

No branches or pull requests

7 participants