Is there a clean way to specify character literals in Swift?

swift get character at index
swift int to character
swift string index
swift substring
swift character set
extract characters from string in swift
swift character list
swift string(format)

Swift seems to be trying to deprecate the notion of a string being composed of an array of atomic characters, which makes sense for many uses, but there's an awful lot of programming that involves picking through datastructures that are ASCII for all practical purposes: particularly with file I/O. The absence of a built in language feature to specify a character literal seems like a gaping hole, i.e. there is no analog of the C/Java/etc-esque:

String foo="a"
char bar='a'

This is rather inconvenient, because even if you convert your strings into arrays of characters, you can't do things like:

let ch:unichar = arrayOfCharacters[n]
if ch >= 'a' && ch <= 'z' {...whatever...}

One rather hacky workaround is to do something like this:

let LOWCASE_A = ("a" as NSString).characterAtIndex(0)
let LOWCASE_Z = ("z" as NSString).characterAtIndex(0)
if ch >= LOWCASE_A && ch <= LOWCASE_Z {...whatever...}

This works, but obviously it's pretty ugly. Does anyone have a better way?

Characters can be created from Strings as long as those Strings are only made up of a single character. And, since Character implements ExtendedGraphemeClusterLiteralConvertible, Swift will do this for you automatically on assignment. So, to create a Character in Swift, you can simply do something like:

let ch: Character = "a"

Then, you can use the contains method of an IntervalType (generated with the Range operators) to check if a character is within the range you're looking for:

if ("a"..."z").contains(ch) {
    /* ... whatever ... */
}

Example:

let ch: Character = "m"
if ("a"..."z").contains(ch) {
    println("yep")
} else {
    println("nope")
}

Outputs:

yep


Update: As @MartinR pointed out, the ordering of Swift characters is based on Unicode Normalization Form D which is not in the same order as ASCII character codes. In your specific case, there are more characters between a and z than in straight ASCII (ä for example). See @MartinR's answer here for more info.

If you need to check if a character is in between two ASCII character codes, then you may need to do something like your original workaround. However, you'll also have to convert ch to an unichar and not a Character for it to work (see this question for more info on Character vs unichar):

let a_code = ("a" as NSString).characterAtIndex(0)
let z_code = ("z" as NSString).characterAtIndex(0)
let ch_code = (String(ch) as NSString).characterAtIndex(0)

if (a_code...z_code).contains(ch_code) {
    println("yep")
} else {
    println("nope")
}

Or, the even more verbose way without using NSString:

let startCharScalars = "a".unicodeScalars
let startCode = startCharScalars[startCharScalars.startIndex]

let endCharScalars = "z".unicodeScalars
let endCode = endCharScalars[endCharScalars.startIndex]

let chScalars = String(ch).unicodeScalars
let chCode = chScalars[chScalars.startIndex]

if (startCode...endCode).contains(chCode) {
    println("yep")
} else {
    println("nope")
}

Note: Both of those examples only work if the character only contains a single code point, but, as long as we're limited to ASCII, that shouldn't be a problem.

Swift - Literals, is the source code representation of a value of an integer, floating-point number, or string type. Being able to express basic values using inline literals is an essential feature in most programming languages. This week, let’s focus on string literals, by taking a take a look at the many different ways that they can be used and how we — through Swift’s highly protocol-oriented design — are able to customize the way literals are interpreted.

If you need C-style ASCII literals, you can just do this:

let chr = UInt8(ascii:"A") // == UInt8( 0x41 )

Or if you need 32-bit Unicode literals you can do this:

let unichr1 = UnicodeScalar("A").value // == UInt32( 0x41 )
let unichr2 = UnicodeScalar("é").value // == UInt32( 0xe9 )
let unichr3 = UnicodeScalar("😀").value // == UInt32( 0x1f600 )

Or 16-bit:

let unichr1 = UInt16(UnicodeScalar("A").value) // == UInt16( 0x41 )
let unichr2 = UInt16(UnicodeScalar("é").value) // == UInt16( 0xe9 )

All of these initializers will be evaluated at compile time, so it really is using an immediate literal at the assembly instruction level.

Swift - Characters, How do I remove a character from a string in Swift? Literals are an active topic of discussion for the future of the language. Looking forward to Swift 5, there are a number of current proposals that could have terrific implications for how we write code. Raw String Literals. At the time of writing, Swift Evolution proposal 0200 is in active review. If it’s accepted, future versions of Swift

The feature you want was proposed to be in Swift 5.1, but that proposal was rejected for a few reasons:

  1. Ambiguity

    The proposal as written, in the current Swift ecosystem, would have allowed for expressions like 'x' + 'y' == "xy", which was not intended (the proper syntax would be "x" + "y" == "xy").

  2. Amalgamation

    The proposal was two in one.

    First, it proposed a way to introduce single-quote literals into the language.

    Second, it proposed that these would be convertible to numerical types to deal with ASCII values and Unicode codepoints.

    These are both good proposals, and it was recommended that this be split into two and re-proposed. Those follow-up proposals have not yet been formalized.

  3. Disagreement

    It never reached consensus whether the default type of 'x' would be a Character or a Unicode.Scalar. The proposal went with Character, citing the Principle of Least Surprise, despite this lack of consensus.

You can read the full rejection rationale here.


The syntax might/would look like this:

let myChar = 'f' // Type is Character, value is solely the unicode U+0066 LATIN SMALL LETTER F
let myInt8: Int8 = 'f' // Type is Int8, value is 102 (0x66)
let myUInt8Array: [UInt8] = [ 'a', 'b', '1', '2' ] // Type is [UInt8], value is [ 97, 98, 49, 50 ] ([ 0x61, 0x62, 0x31, 0x32 ])

switch someUInt8 {
    case 'a' ... 'f': return "Lowercase hex letter"
    case 'A' ... 'F': return "Uppercase hex letter"
    case '0' ... '9': return "Hex digit"
    default: return "Non-hex character"
}

How to remove last character from a string in Swift, “the type of thing” (or “the kind of thing”) that can be stored. Swift Literals . A Literal is the direct value of variable or constant. It may be a number, character or string. Literals are used to initialize or assign value to variables or constants.

It also looks like you can use the following syntax:

Character("a")

This will create a Character from the specified single character string.

I have only tested this in Swift 4 and Xcode 10.1

The Basics, The contents of a String can be accessed in various ways, including as a Every string is composed of encoding-independent Unicode characters, and A string literal is a sequence of characters surrounded by double quotation marks ( " ). Yeah, again, a perfectly fine solution to the problem I don't have. ;) There are lots of ways to get a repeated character into a string with or without interpolation. What I was really trying to verify is that there is no way to use a string literal within a Swift string interpolation expression. There doesn't seem to be.

Strings and Characters, File Names; File Encoding; Whitespace Characters; Special Escape Sequences Aside from the line terminator, the Unicode horizontal space character All other whitespace characters in string and character literals are represented by their However, there is no single correct recipe for how to do it; different files and  Swift Literals - In most of the programming languages, literals and constants play a major role in dealing with values within a program. Swift also support the concept of literals and constants. They are used to hold a constant value for expressing them within the code and hold a memory location.

Swift Style Guide, The Character type represents a character made up of one or more Unicode scalar so the number of visible characters is generally the most natural way to count the In addition to creating a character from a single-character string literal​, you can The ASCII encoding value of this character, if it is an ASCII character. The question is to reverse vowels of a string, like you input "hello", the output should be "holle". I searched there's no such question in swift, so I want to post this as a discuss. I wrote the code as below, and turns out it takes 12ms to reverse this "hello", anyone has any better solution by using swift features?

Character, String interpolation has been around since the earliest days of Swift, but in Swift coming in Swift 2.1 where we gained the ability to use string literals in generic interpolation does nothing if an encoding error happens, but if we about controlling the way data is formatted in our apps in a really clean way  By default Swift strings can’t span more than one line. One simple way around this is to use the new line character , but that only works for strings that are displayed – if you’re just trying to format your string nicely, you should use multi-line strings instead.

Comments
  • Just note that the ordering of Swift strings or characters is not based on the ASCII code (compare stackoverflow.com/a/25775112/1187415) . Eg "a"..."z" contains the character "ä". This may be desired or not.
  • @MartinR Thanks, I hadn't realized that. I updated the answer with that info.
  • That's a nice trick, which I'll keep in the bank for other kinds of logic. Still a bit high level though: when it comes to char-by-char file format parsing, where performance matters as much as precision, there's no substitute for being able to go back and forth between an int-like and string-like representation of a character. So char-literal is still needed.
  • I don't think you know what a "literal" is
  • Mixed feelings about this... looks like it will do the job, but waiting 5 major versions for something that was available in Fortran in the 1950s is rather depressing.
  • @AlexClark I, for one, am glad that they're taking such major, irreversible changes so seriously, rather than just making a quick decision at the start that turns out to be the wrong decision (see also: JavaScript). And the fact that "5 major versions" translates to "about 5 years" is so delightful compared to the pace of other languages, where you might not see a major version in a decade, if ever.