Arithmetic with Chars in Julia
Asked Answered
A

2

8

Julia REPL tells me that the output of

'c'+2

is 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase) but that the output of

'c'+2-'a'

is 4.

I'm fine with the fact that Chars are identified as numbers via their ASCII code. But I'm confused about the type inference here: why is the first output a char and the second an integer?

Araujo answered 3/12, 2022 at 15:57 Comment(0)
B
6

The reason is:

julia> @which 'a' - 1
-(x::T, y::Integer) where T<:AbstractChar in Base at char.jl:227

julia> @which 'a' - 'b'
-(x::AbstractChar, y::AbstractChar) in Base at char.jl:226

Subtraction of Char and integer is Char. This is e.g. 'a' - 1.

However, subtraction of two Char is integer. This is e.g. 'a' - 'b'.

Note that for Char and integer both addition and subtraction are defined, but for two Char only subtraction works:

julia> 'a' + 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)

This indeed can lead to tricky cases at times that rely of order of operations, as in this example:

julia> 'a' + ('a' - 'a')
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

julia> 'a' + 'a' - 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)

Also note that when working with Char and integer you cannot subtract Char from integer:

julia> 2 - 'a'
ERROR: MethodError: no method matching -(::Int64, ::Char)

Motivation:

  • subtraction of two char - this is sometimes useful if you want to get a relative position of a char with reference to other char, e.g. c - '0' to convert char to its decimal representation if you know char is a digit;
  • adding or subtracting an integer and char - the same but in reverse e.g. you want to convert digit to char and write '0' + d.

I have been using Julia for years now, and I used this feature maybe once or twice, so I would not say it is super commonly needed.

Bernhard answered 3/12, 2022 at 16:30 Comment(2)
Thanks, that explains it. Though I'm still confused about the motivation for these conventions in the first place.Araujo
I have added a comment how I understand the motivation behind introducing these methods.Hallie
S
8

Regarding the motivation for conventions, it’s similar to time stamps and intervals. The difference between time stamps is an interval and accordingly you can add an interval to a time stamp to get another time stamp. You cannot, however, add two time stamps because that doesn’t make sense—what is the sum of two points in time supposed to be? The difference between two chars is their distance in code point space (an integer); accordingly you can add an integer to a char to get another char that’s offset by that many code points. You can’t add two chars because adding two code points is not a meaningful operation.

Why allow comparisons of chars and differences in the first place? Because it’s common to use that kind of arithmetic and comparison to implement parsing code, eg for parsing numbers in various bases and formats.

Sickroom answered 3/12, 2022 at 16:52 Comment(1)
That's a good analogy, thanks!Araujo
B
6

The reason is:

julia> @which 'a' - 1
-(x::T, y::Integer) where T<:AbstractChar in Base at char.jl:227

julia> @which 'a' - 'b'
-(x::AbstractChar, y::AbstractChar) in Base at char.jl:226

Subtraction of Char and integer is Char. This is e.g. 'a' - 1.

However, subtraction of two Char is integer. This is e.g. 'a' - 'b'.

Note that for Char and integer both addition and subtraction are defined, but for two Char only subtraction works:

julia> 'a' + 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)

This indeed can lead to tricky cases at times that rely of order of operations, as in this example:

julia> 'a' + ('a' - 'a')
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

julia> 'a' + 'a' - 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)

Also note that when working with Char and integer you cannot subtract Char from integer:

julia> 2 - 'a'
ERROR: MethodError: no method matching -(::Int64, ::Char)

Motivation:

  • subtraction of two char - this is sometimes useful if you want to get a relative position of a char with reference to other char, e.g. c - '0' to convert char to its decimal representation if you know char is a digit;
  • adding or subtracting an integer and char - the same but in reverse e.g. you want to convert digit to char and write '0' + d.

I have been using Julia for years now, and I used this feature maybe once or twice, so I would not say it is super commonly needed.

Bernhard answered 3/12, 2022 at 16:30 Comment(2)
Thanks, that explains it. Though I'm still confused about the motivation for these conventions in the first place.Araujo
I have added a comment how I understand the motivation behind introducing these methods.Hallie

© 2022 - 2024 — McMap. All rights reserved.