# Concise ASCII Usage

**URL:** <https://forums.swift.org/t/concise-ascii-usage/36091>\
**Category:** Pitches\
**Created:** [May 2, 2020, 6:45pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091 "2020-05-02T18:45:29Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![kyledr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kyledr/32/11491_2.png) [@kyledr](https://forums.swift.org/u/kyledr)\
**Post date:** [May 2, 2020, 6:45pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/1 "2020-05-02T18:45:29Z")

</div>

Forgive me if there's a better way.

Old way:

let c = Character("a").asciiValue!

New way:

`let c: UInt8 = "a"`

or

`let c: UInt8 = 'a'`

Why is the new way better?

In the old way, `let c = Character("🐶🐮").asciiValue!` crashes at runtime.  
In the new way, `let c = "🐶🐮"` gives a compiler error.

A compiler error is preferred to a runtime crash (or failure to coalesce nil) for safety and code simplicity reasons.

Open to thoughts on double quotes only, single quotes only, or supporting both.

---

<div class="post-metadata">

**Author:** ![woolsweater](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/woolsweater/32/2402_2.png) [@woolsweater](https://forums.swift.org/u/woolsweater)\
**Post date:** [May 2, 2020, 6:50pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/2 "2020-05-02T18:50:17Z")

</div>

I'd like to see something like this as well.

It was pitched a while back: [SE-0243: Codepoint and Character Literals](https://forums.swift.org/t/se-0243-codepoint-and-character-literals/21188), and evenually [rejected as presented](https://forums.swift.org/t/se-0243-codepoint-and-character-literals/21188/341); the rejection suggests that it should be revised and reconsidered.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [May 2, 2020, 6:52pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/3 "2020-05-02T18:52:12Z")

</div>

There have been extensive discussions on this topic which you may be interested to read.

If, after reviewing these links, you feel like there's a new direction or perspective to be had on the topic, then by all means please do share! In that case, it can be helpful for the community if you'd write a short synopsis of what you learn from these readings so that we're not starting back at square one.

> [@Prepitch: Character integer literals](https://forums.swift.org/t/prepitch-character-integer-literals/10442):
>
> In C, 'a', is a char literal, equivalent to 97. Swift has no such equivalent, requiring awkward spellings like ("a" as Unicode.Scalar).value, which may or may not need additional casts to convert it to the right integer type. Or worse, spelling out the values in hex or decimal directly. This harms readability of code. static char const hexcodes[16] = { '0', '1', '2', '3', '4' ,'5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; let hexcodes:[UInt8] = [48, 49, 50, 51, 52, 53…

> [@SE-0243: Codepoint and Character Literals](https://forums.swift.org/t/se-0243-codepoint-and-character-literals/21188):
>
> Hi Swift Community, The review of [SE-0243: Codepoint and Character Literals](https://github.com/apple/swift-evolution/blob/master/proposals/0243-codepoint-and-character-literals.md) begins now and runs through March 12, 2019. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager via [email](mailto:ben_cohen@apple.com) or direct message on the forums. If you send me email, please put "SE-0243" somewhere in the subject line. What goes into a review of a proposal? The goal o…

> [@Unicode scalar literals](https://forums.swift.org/t/unicode-scalar-literals/22224):
>
> In light of the [core team's decision on SE-0243](https://forums.swift.org/t/se-0243-codepoint-and-character-literals/21188/341), I'd like to kick off a pitch for single-quoted literals based on the feedback given. It's the product of multiple people's work but, while we figure out who's signing on to it, here it is so that we can relaunch the conversation. I'll take the blame for all typos and other errors: Unicode scalar literals Introduction Swift's String type accommodates Unicode by default and models a Collection of extended grapheme clusters, which in Swift are in …

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [May 2, 2020, 7:50pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/4 "2020-05-02T19:50:03Z")

</div>

this topic was discussed to death last year so i’m just gonna summarize the main issue with this idea, which is that this becomes allowed:

```swift
'a' + 'b' == 195

```

there are not good ways around this problem, since if you want to use an ascii literal as an integer, then you also have to be okay with ascii literals appearing _anywhere_ you can use an integer

the _right_ thing to do here is to have the `'a'` literals be their own `ASCII` type, and then somehow have a way of safely rebinding a `[UInt8]` buffer to an `[ASCII]` buffer without copying it (since the underlying memory representation is the same). but we don’t have zero-cost abstractions in swift, so this isn’t going to work.

i’m nowadays in the camp that any solution to the `'a' as UInt8` problem is probably going to have to go through `newtype` or something like it

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [May 2, 2020, 8:01pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/5 "2020-05-02T20:01:30Z")

</div>

> [@taylorswift](#):
>
> we don’t have zero-cost abstractions in swift

"Zero-cost abstractions" usually refers to "zero runtime cost" (EDIT: although I suppose that's zero _code_ cost and not zero _data_ cost, because of Swift's runtime metadata), and we absolutely do have zero-cost abstractions in Swift—a struct with one member has the same layout as that member. I don't think that was the problem.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [May 2, 2020, 8:05pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/6 "2020-05-02T20:05:19Z")

</div>

> [@jrose](#):
>
> "Zero-cost abstractions" usually refers to "zero runtime cost", and we absolutely do have zero-cost abstractions in Swift—a struct with one member has the same layout as that member. I don't think that was the problem.

what i mean is right now you have to do this

```swift
let buffer:[UInt8]
let ascii:[ASCII] = .init(buffer)

```

which involves copying the entire bytestring. ofc you can use the unsafe memory rebinding APIs to do this without the copy, but we shouldn’t expect people to have to drop down to `withMemoryRebound(to:_:)` to do ascii string processing

---

<div class="post-metadata">

**Author:** ![Nickolas\_Pohilets](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nickolas_pohilets/32/10659_2.png) [@Nickolas\_Pohilets](https://forums.swift.org/u/Nickolas_Pohilets)\
**Post date:** [May 3, 2020, 6:58am UTC](https://forums.swift.org/t/concise-ascii-usage/36091/7 "2020-05-03T06:58:42Z")

</div>

@kyledr, would StaticString help in some of your use cases? Something like this:

```
let hexcodes: StaticString = “0123456789abcdef”
let buffer = UnsafeBufferPointer(start: hexcodes.utf8Start, count: hexcodes.utf8CodeUnitCount)
print(buffer[4])

```

Do you need to distinguish between ASCII and UTF8?

---

<div class="post-metadata">

**Author:** ![Saklad5](https://avatars.discourse-cdn.com/v4/letter/s/4491bb/32.png) [@Saklad5](https://forums.swift.org/u/Saklad5)\
**Post date:** [May 3, 2020, 5:49pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/8 "2020-05-03T17:49:51Z")

</div>

Why do you need this, anyway? It shouldn’t be a common task.

As for your proposal, consider that there are multiple ways to interpret `a` as an integer, and if Swift was going to choose one of them it would be UTF-8.

I think the current approach is fine. Just use `UInt8(ascii: "a")`. If you don’t want that to fail, don’t explicitly restrict it to ASCII: `UInt32("a" as Unicode.Scalar)`.

By the way, it is really weird that that `UInt32` initializer doesn't have any argument labels. You'd expect it to be `init(utf8:)`.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [May 3, 2020, 6:13pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/9 "2020-05-03T18:13:20Z")

</div>

> [@Saklad5](#):
>
> By the way, it is really weird that that `UInt32` initializer doesn't have any argument labels. You'd expect it to be `init(utf8:)` .

It is a lossless conversion. There are no labels for those cases.

Edit:

If you're feeling fancy, you can also do

```swift
.init("a") as UInt32

```

---

<div class="post-metadata">

**Author:** ![Saklad5](https://avatars.discourse-cdn.com/v4/letter/s/4491bb/32.png) [@Saklad5](https://forums.swift.org/u/Saklad5)\
**Post date:** [May 3, 2020, 8:11pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/10 "2020-05-03T20:11:07Z")

</div>

That explains a lot. Still, I would expect an exception to be made here, since there are multiple initializers taking a single parameter with a type that conforms to `ExpressibleByUnicodeScalarLiteral`.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [May 3, 2020, 8:30pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/11 "2020-05-03T20:30:13Z")

</div>

> [@Lantua](#):
>
> If you're feeling fancy, you can also do
> 
> ```swift
> .init("a") as UInt32
> 
> ```

the weird thing about this is that

```swift
UInt32.init("a") as UInt32

```

gives you `97`, but

```swift
UInt32.init("a")

```

gives you `nil`. yes i know technically this is overloading on argument type which is okay, but from the perspective of the user it’s effectively overloading on return type (`init(_:)` vs `init?(_:)`) which is just bad swift.

---

<div class="post-metadata">

**Author:** ![Saklad5](https://avatars.discourse-cdn.com/v4/letter/s/4491bb/32.png) [@Saklad5](https://forums.swift.org/u/Saklad5)\
**Post date:** [May 3, 2020, 8:46pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/12 "2020-05-03T20:46:45Z")

</div>

That's my problem with it: the compiler happily assumes the (in this case) wrong thing, without any indication that there's an issue.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [May 3, 2020, 8:54pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/13 "2020-05-03T20:54:37Z")

</div>

> [@taylorswift](#):
>
> the weird thing about this is that
> 
> ```swift
> UInt32.init("a") as UInt32
> 
> ```
> 
> gives you `97` , but
> 
> ```swift
> UInt32.init("a")
> 
> ```
> 
> gives you `nil` .

Yeah this is not great and merits some reconsideration in my view.

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [May 3, 2020, 8:58pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/14 "2020-05-03T20:58:45Z")

</div>

Personally, I think the idea of exposing conversions between characters and integers in the language to be just plain weird, especially with Swift's String model. It seems straightforward at a glance, but the more you think about it, the more confusing it becomes.

Instead, I use an ASCII struct (note: this is pretty rough, and I'm still trying to refine the API).

```swift
public struct ASCII: Equatable, Comparable {
    public var codePoint: UInt8
    @inlinable public init(_ v: UInt8) { self.codePoint = v }
}

public extension ASCII {
    // Control Characters.
    @inlinable static var null : ASCII { ASCII(0x00) }
    @inlinable static var startOfHeading : ASCII { ASCII(0x01) }
    @inlinable static var startOfText : ASCII { ASCII(0x02) }
    @inlinable static var endOfText : ASCII { ASCII(0x03) }
    @inlinable static var endOfTransmission : ASCII { ASCII(0x04) }
    @inlinable static var enquiry : ASCII { ASCII(0x05) }
    @inlinable static var acknowledge : ASCII { ASCII(0x06) }
...
   // Upper-case letters.
    @inlinable static var A: ASCII { ASCII(0x41) }
    @inlinable static var B: ASCII { ASCII(0x42) }
    @inlinable static var C: ASCII { ASCII(0x43) }
    @inlinable static var D: ASCII { ASCII(0x44) }
...
}

```

Additionally, I've got a bunch of heterogenous operator overloads so you can use `==` between ASCII-type values, `Character`, and `UInt8`, as well as pattern-match between them, like this:

```swift
let input: String = ...

let c = input[idx]
switch c {
  case ASCII.questionMark:
    url.query = ""
    state = .query
  case ASCII.numberSign:
    url.fragment = ""
    state = .fragment

```

Like I said, it's still kind of rough, but I've found it pretty okay so far. You can try it out and see what you think: [ascii prototype · GitHub](https://gist.github.com/karwa/9454ba908f2ecbdd2474db383862f0cd)

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [May 3, 2020, 9:06pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/15 "2020-05-03T21:06:42Z")

</div>

> [@Karl](#):
>
> Instead, I use an ASCII struct (note: this is pretty rough, and I'm still trying to refine the API).

the issue for me, which i [brought up](https://forums.swift.org/t/unicode-scalar-literals/22224/14) the last time this got slugged out was i can just never remember the full names of all the special characters

> [@Karl](#):
>
> Additionally, I've got a bunch of heterogenous operator overloads so you can use `==` between ASCII-type values, `Character` , and `UInt8` , as well as pattern-match between them, like this:

i cant find the post but i think this got ruled out pretty early on last time because it’s a very band-aidy solution and just exacerbated existing issues with over-overloaded operators

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [May 3, 2020, 9:10pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/16 "2020-05-03T21:10:28Z")

</div>

> [@xwu](#):
>
> Yeah this is not great and merits some reconsideration in my view.

i just don’t know what even justifies the existence of this method when you can just use `Unicode.Scalar.value` it’s not like it’s that shorter, and its way less clear what’s going on if you don’t include the name `Unicode.Scalar`

```swift
.init("a") as UInt32
("a" as Unicode.Scalar).value

```

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [May 3, 2020, 9:11pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/17 "2020-05-03T21:11:22Z")

</div>

> [@taylorswift](#):
>
> the issue for me, which i [brought up](https://forums.swift.org/t/unicode-scalar-literals/22224/14) the last time this got slugged out was i can just never remember the full names of all the special characters

Oh, yeah - that happens to me quite often as well. I tried to be as objective as possible, so I took the list of names from somewhere official-looking. For example, I grew up calling `#` "hash" or "pound", but that list calls it "number sign" so that's what I use in that type, even though the British names are more familiar to me.

As for the operators - it works for me. Certainly the `Character` operators make sense IMO, but I could see some people taking issue with comparing an integer directly with an ASCII character.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [May 3, 2020, 9:13pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/18 "2020-05-03T21:13:25Z")

</div>

> [@Karl](#):
>
> As for the operators - it works for me. Certainly the `Character` operators make sense IMO, but I could see some people taking issue with comparing an integer directly with an ASCII character.

i really don’t like `==` with different types on the left and right hands, first off it kind of contradicts the whole meaning of `==` second it basically doubles the amount of overloads you have to provide since it has to work in both orders

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [May 3, 2020, 9:17pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/19 "2020-05-03T21:17:49Z")

</div>

> [@taylorswift](#):
>
> i really don’t like `==` with different types on the left and right hands, first off it kind of contradicts the whole meaning of `==`

Does it? I'm not sure. That's certainly a matter for debate.

Besides, at some point you need to balance pedantry with usability. I certainly prefer doing this over the alternative of making character literals assignable to integer-type values!

> [@taylorswift](#):
>
> second it basically doubles the amount of overloads you have to provide since it has to work in both orders

Sure, but you do that once when you implement the type, and never again. I think it is worth paying the boilerplate cost for a more natural interface (assuming the type-checker can handle it).

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [May 3, 2020, 9:31pm UTC](https://forums.swift.org/t/concise-ascii-usage/36091/20 "2020-05-03T21:31:54Z")

</div>

> [@Karl](#):
>
> (assuming the type-checker can handle it).

(_Narrator voiceover:_ it can't.)

* * *

The longer reply to this is that, as we all know, literals + operators (see what I did there?) are a major bottleneck for type checking. Essentially any new operator overload that takes integer literals will throw some existing expressions that are just under the "too complex" limit over that limit. This is very much not a nice thing to do to users who write manifestly well-formed code; nor is the increase in compilation time. Until there is a dramatic reworking of this area of the compiler, vending additional overloads in the standard library is a big no-go.
