# 1 + 'a' = 'b'

**URL:** <https://discourse.julialang.org/t/1-a-b/77947>\
**Category:** General Usage\
**Created:** [March 16, 2022, 5:52am UTC](https://discourse.julialang.org/t/1-a-b/77947 "2022-03-16T05:52:33Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 16, 2022, 5:10pm UTC](https://discourse.julialang.org/t/1-a-b/77947/63 "2022-03-16T17:10:49Z")

</div>

> [@cjdoris](#):
>
> I assume everyone here is ok with `Date(2022, 3, 16) + Day(1)` returning `Date(2022, 3, 17)` ?

I really like this analogy (and I think it occurred to me the last time I came across this character business some time ago.)

Here’s another one: in geometry, you can subtract one Point from another Point, and get the difference as a Vector pointing from one point to the other. And you can add a Vector to a Point and get another Point. Adding two points, however, doesn’t automatically make sense.

And yet, Point and Vector normally have exactly the same encoding, so it’s not really the encoding that is causing this, but the interpretation of the quantities. You could change the coordinate system, and hence, the encoding, without invalidating the relationships.

(Vector is here different from `Vector = Array{., 1}`.)

---

<div class="post-metadata">

**Author:** ![josuagrw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josuagrw/32/1015_2.png) [@josuagrw](https://discourse.julialang.org/u/josuagrw)\
**Post date:** [March 16, 2022, 5:16pm UTC](https://discourse.julialang.org/t/1-a-b/77947/64 "2022-03-16T17:16:41Z")

</div>

> [@oheil](#):
>
> The explicit version of the same result is:  
> `Char(Int('a')+1)`

The conversion to `Int` is semantically only necessary if you think of `'a'` as something other than a number.

A code point, however, is a number. No conversion necessary.

That’s why the question of what a `Char` represents is so central. Does it represent the code point associated with a character? Or does it represent the letter we associate with a character?

For example, does `'a'` represent the code point `U+0061`? Or does it represent the lower-case letter A?

My personal answer: Julia decides this on context. In the context `'a' * 'b'` the `Char`s are treated as two letters and concatenated to form a String. In the context `'a' + 1`, the `Char` is treated as a code point which can be incremented like an integer.

The context-dependant behavior is convenient—but it also leads to lots of open questions and surprising interactions.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [March 16, 2022, 5:37pm UTC](https://discourse.julialang.org/t/1-a-b/77947/65 "2022-03-16T17:37:15Z")

</div>

I try to translate this:  
[https://docs.julialang.org/en/v1.7/base/strings/#Core.Char](https://docs.julialang.org/en/v1.7/base/strings/#Core.Char)  
to your question but I fail to produce a good answer.

`Char` can hold information which isn’t a Unicode codepoint. Therefor `Char` is not only representing a codepoint. (so we a have `isvalid` to check).  
For your exampe I would say:

`Char('a')` represents the codepoint `U+0061` which according to Unicode represents the glyph _a_.  
^---- this to distinguish it from the character literal ‘a’

I am not sure how all these diffentiations of terms will help in the OPs problem of being surprised by

> [@Jerry](#):
>
> ```julia
> julia> 1 + 'a'
> 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
> 
> ```

After all it’s a convenience to have

```julia
@inline +(x::T, y::Integer) where {T<:AbstractChar} = T(Int32(x) + Int32(y))
@inline +(x::Integer, y::AbstractChar) = y + x

```

and not a mathematical obligation to have it defined.

> [@josuagrw](#):
>
> The context-dependant behavior is convenient—but it also leads to lots of open questions and surprising interactions.

Exactly. Sometimes more, sometimes less and sometimes in between like in this case.

---

<div class="post-metadata">

**Author:** ![josuagrw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josuagrw/32/1015_2.png) [@josuagrw](https://discourse.julialang.org/u/josuagrw)\
**Post date:** [March 16, 2022, 5:41pm UTC](https://discourse.julialang.org/t/1-a-b/77947/66 "2022-03-16T17:41:41Z")

</div>

> [@oheil](#):
>
> `Char` can hold information which isn’t a Unicode codepoint. Therefor `Char` is not only representing a codepoint. (so we a have `isvalid` to check).

I dont think this is correct. The non-assigned code points mentioned above can be represented by `Char` and also pass the `isvalid` test.

```julia
julia> Char(0x1FFFE) |> isvalid
true

```

Can you provide any example of a `Char` that is not “holding” a Unicode code point?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 16, 2022, 5:55pm UTC](https://discourse.julialang.org/t/1-a-b/77947/67 "2022-03-16T17:55:33Z")

</div>

> [@josuagrw](#):
>
> Can you provide any example of a `Char` that is not “holding” a Unicode code point?

You see these to represent byte sequences in a `String` that is malformed UTF-8, e.g. if you try to interpret random bytes as a string ala `String(rand(UInt8, 20))`. You still want to be able to look at the contents of such strings, e.g. to pass them as cookies or to correct encoding errors.

```julia
julia> c = "\x94"[1]
'\x94': Malformed UTF-8 (category Ma: Malformed, bad data)

julia> isvalid(c)
false

julia> c + 1
ERROR: Base.InvalidCharError{Char}('\x94')

```

(Weirdly, I’m not sure how to easily construct such characters except via strings, e.g. [`'\x94'` gives an error](https://github.com/JuliaLang/julia/issues/44646). I guess you could `reinterpret` raw bytes.)

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 16, 2022, 6:00pm UTC](https://discourse.julialang.org/t/1-a-b/77947/68 "2022-03-16T18:00:52Z")

</div>

> [@josuagrw](#):
>
> My personal answer: Julia decides this on context. In the context `'a' * 'b'` the `Char` s are treated as two letters and concatenated to form a String. In the context `'a' + 1` , the `Char` is treated as a code point which can be incremented like an integer.

I don’t think this is necessary. You could encode `Char` as a `Float64`, and then define `+(c::Char, n::Int) = Char(nextfloat(Float64(c), n))`, and something similar for finding the number of eps’es between floats to do character subtraction.

Inconvenient, of course. But, the point is that `+(::Char, ::Int)` has meaning that is separate from the encoding of `Char` (like the coordinate system independence of vectors and points that I brought up.)

---

<div class="post-metadata">

**Author:** ![josuagrw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/josuagrw/32/1015_2.png) [@josuagrw](https://discourse.julialang.org/u/josuagrw)\
**Post date:** [March 16, 2022, 6:02pm UTC](https://discourse.julialang.org/t/1-a-b/77947/69 "2022-03-16T18:02:31Z")

</div>

> [@DNF](#):
>
> But, the point is that `+(::Char, ::Int)` has meaning that is independent of the encoding of `Char`

I’m very confused now. Wouldn’t your hypothetical `nextfloat` operation give a totally different result (from the current implementation)?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 16, 2022, 6:03pm UTC](https://discourse.julialang.org/t/1-a-b/77947/70 "2022-03-16T18:03:04Z")

</div>

Yes, this requires/imagines a different encoding of `Char`. One where, for example,

```julia
'a': 97.0
'b': 97.00000000000001
'c': 97.00000000000003
'd': 97.00000000000004
'e': 97.00000000000006
 ⋮
'z': 97.00000000000036

```

I’m sure it would be horribly inconvenient, but it’s a way to demonstrate how `+(::Char, ::Int)` could make sense, independent of the encoding.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 16, 2022, 6:16pm UTC](https://discourse.julialang.org/t/1-a-b/77947/71 "2022-03-16T18:16:13Z")

</div>

To me the biggest surprise in this thread is that the behavior surprises anyone, XD. From all languages I have already programmed, I think that only Haskell actually requires explicit conversion back and forth integer and characters. Not that is not a good idea to get rid of it for Julia 2.0, but it is an incredibly common convenience of programming languages.

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [March 16, 2022, 6:19pm UTC](https://discourse.julialang.org/t/1-a-b/77947/72 "2022-03-16T18:19:54Z")

</div>

> [@DNF](#):
>
> I’m sure it would be horribly inconvenient, but it’s a way to demonstrate how `+(::Char, ::Int)` could make sense, independent of the encoding.

It is already independent of the encoding. `+(::Char, ::Int)` is in terms of unicode code points **not** the UTF-8 encoding of those code points.

You can verify this by trying to increment an invalid char:

```julia
julia> c = "\x94"[1]
'\x94': Malformed UTF-8 (category Ma: Malformed, bad data)

julia> c + 1
ERROR: Base.InvalidCharError{Char}('\x94')

```

Since an invalid char doesn’t correspond to a code point, you can’t increment it.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 16, 2022, 6:25pm UTC](https://discourse.julialang.org/t/1-a-b/77947/73 "2022-03-16T18:25:07Z")

</div>

> [@cjdoris](#):
>
> Mathematical formalism is how good programming languages are made.

Being able to define an operation algebraically is a minimum standard. But in math there are good and bad definitions, and likewise in programming. Javascript’s `"a" + 1 == "a1"` can also be viewed algebraically, but I think it’s a mistake for a general-purpose programming language to implement it.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 16, 2022, 6:33pm UTC](https://discourse.julialang.org/t/1-a-b/77947/74 "2022-03-16T18:33:09Z")

</div>

> [@Sukera](#):
>
> Unicode itself says these are noncharacters.

Noncharacters are still [code points](https://www.unicode.org/glossary/#code_point):

> **Code point:** Any value in the Unicode codespace; that is, the range of integers from 0 to 10FFFF₁₆. (See definition D10 in [Section 3.4, Characters and Encoding](https://www.unicode.org/versions/latest/ch03.pdf#G2212).) Not all code points are assigned to encoded characters.

That being said, `Char` can represent larger values and still do arithmetic with them, so it effectively supports a superset of Unicode codespace (in addition to invalid UTF-8 encodings):

```julia
julia> Char(0x10FFFF) + 1
'\U110000': Unicode U+110000 (category In: Invalid, too high)

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 16, 2022, 6:35pm UTC](https://discourse.julialang.org/t/1-a-b/77947/75 "2022-03-16T18:35:25Z")

</div>

> [@cjdoris](#):
>
> It is already independent of the encoding.

I should have said “makes sense”, instead of “could make sense” 🙂

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [March 16, 2022, 6:44pm UTC](https://discourse.julialang.org/t/1-a-b/77947/76 "2022-03-16T18:44:13Z")

</div>

Am I the only one here who never uses `Char`?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 16, 2022, 6:48pm UTC](https://discourse.julialang.org/t/1-a-b/77947/77 "2022-03-16T18:48:04Z")

</div>

Really? I definitely prefer them over length-1 `String`s. They just seem _wrong_.

Does that mean you would write

```julia
replace("Hello", "l"=>"k")

```

?

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [March 16, 2022, 6:51pm UTC](https://discourse.julialang.org/t/1-a-b/77947/78 "2022-03-16T18:51:46Z")

</div>

> [@DNF](#):
>
> Does that mean you would write
> 
> ```julia
> replace("Hello", "l"=>"k")
> 
> ```

Yes

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 16, 2022, 6:53pm UTC](https://discourse.julialang.org/t/1-a-b/77947/79 "2022-03-16T18:53:08Z")

</div>

Hm. It seems wrong to me, it’s replacing characters, not strings, imho. It’s also slower.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [March 16, 2022, 6:55pm UTC](https://discourse.julialang.org/t/1-a-b/77947/80 "2022-03-16T18:55:50Z")

</div>

And we’ve never had a thread about this error

```julia
julia> 1 + "a"
ERROR: MethodError: no method matching +(::Int64, ::String)
Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...) at C:\Users\beasont\.julia\juliaup\julia-1.7.2+0~x64\share\julia\base\operators.jl:655
  +(::T, ::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at C:\Users\beasont\.julia\juliaup\julia-1.7.2+0~x64\share\julia\base\int.jl:87
  +(::Integer, ::Ptr) at C:\Users\beasont\.julia\juliaup\julia-1.7.2+0~x64\share\julia\base\pointer.jl:161
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[1]:1

```

(although we have had about `+(String,String)`)

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 16, 2022, 7:03pm UTC](https://discourse.julialang.org/t/1-a-b/77947/81 "2022-03-16T19:03:33Z")

</div>

To me, this is almost as bad as saying “scalars should be the same as 1x1 matrices” 😁

I guess it’s less disruptive in practice, though.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [March 16, 2022, 8:32pm UTC](https://discourse.julialang.org/t/1-a-b/77947/82 "2022-03-16T20:32:16Z")

</div>

This is a very interesting discussion. I especially like the mathematical explanation by @cjdoris considering it as group action. For me the main concern seems to be that the group action is just denoted by an integer. For instance, in the example

```julia
Date(2022, 3, 16) + Day(1)

```

it is clear that Day(1) denotes a time interval/shift. In this interpretation

```julia
'a' + 1

```

should be understood and maybe explicitly written as

```julia
'a' + NextCharacterInTermsOfUnicodeCodepoints(1)

```

being open to suggestions for any other shorter, yet descriptive type 😉

[Previous page](https://discourse.julialang.org/t/1-a-b/77947.md?page=3)

[Next page](https://discourse.julialang.org/t/1-a-b/77947.md?page=5)
