Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Swift BooleanLiteralConvertible require a boolean literal?

Tags:

swift

I am trying to add BooleanLiteralConvertible support to my class so I can instantiate it with a boolean. The thing that's throwing me for a loop is the distinction between a boolean value and a boolean literal.

For example, after adding the protocol I attempted this:

func setSelected(value: Bool) {
    var node: MyClass = value
}

But Swift complained that it cannot convert Bool to MyClass. It took me a while to realize it has to be a boolean literal. Oddly enough the following works fine:

func setSelected(value: Bool) {
    var node: MyClass = value ? true : false
}

…which seems just absolutely silly to me. Is there a legitimate reason for this seemingly very bizarre requirement?

like image 783
devios1 Avatar asked Apr 08 '16 18:04

devios1


People also ask

What is a boolean value in Swift?

Swift recognizes a value as boolean if it sees true or false . You can implicitly declar a boolean variable let a = false or explicitly declare a boolean variable let i:Bool = true .

How do you initialize a boolean in Swift?

To initialize a variable with boolean value, use assignment operator and assign true or false.

Is a bool a literal?

Boolean literals represent logical value, and can be either True or False.

Is True and False a literal?

The Boolean literals are the keywords true and false . They are prvalues of type bool.

How to create boolean values in Swift?

In Swift we can express these kind of boolean values by using the Bool data type, which you can create using true or false literals. The Bool type is a struct, that you can create multiple ways. It is possible to transform these values, there are plenty of logical operators available on the Bool struct, the most common ones are the following:

What are the default types of literals in Swift?

If there isn’t suitable type information available, Swift infers that the literal’s type is one of the default literal types defined in the Swift standard library. The default types are Int for integer literals, Double for floating-point literals, String for string literals, and Bool for Boolean literals.

What is the lexical structure of the Swift language?

The lexical structure of Swift describes what sequence of characters form valid tokens of the language. These valid tokens form the lowest-level building blocks of the language and are used to describe the rest of the language in subsequent chapters.

Is swift similar to Objective-C?

Nonetheless, many parts of Swift will be familiar from your experience of developing in C and Objective-C. Swift provides its own versions of all fundamental C and Objective-C types, including Int for integers, Double and Float for floating-point values, Bool for Boolean values, and String for textual data.


2 Answers

Types conforming to BooleanLiteralConvertible can be initialized with the Boolean literals true and false, e.g.

let mc : MyClass = true

This has nothing to do with initializing the type with a Boolean value:

let value : Bool = // ... some boolean value
let mc : MyClass = value // error: cannot convert value of type 'Bool' to specified type 'MyClass'

and there is – as far as I know – no way to make such an implicit conversion work. You would have to write a custom init method

init(bool : Bool) {
    // ...
}

and initialize the object as

let value : Bool = // ... some boolean value
let mc = MyClass(bool: value)
like image 165
Martin R Avatar answered Oct 07 '22 00:10

Martin R


I like the question. Only the Swift team could definitively answer, but I can speculate as to why: converting a typed value into a variable of a different type without an explicit conversion or cast is very easy to confuse with a programmer error, and in many cases is something the compiler should warn about.

Example (and assume that Person is also a StringLiteralConvertible that can be initialized with a string variable as well as a literal as you pose in your question):

struct Person {

    private static var idCounter = 1

    var name:String
    let id:Int

    init(withName name:String) {
        Person.idCounter += 1
        self.name = name
        self.id = Person.idCounter
    }
}

var person = Person(withName:"Mary")
let name = "John"
person = name

The above code looks suspiciously like a mistake, where the programmer is assigning a value of the wrong type (String) to a variable of type Person. It may in fact be a mistake. Maybe the programmer only meant to change the name of the person (person.name = name) without creating a new Person with a new unique id. Or maybe the programmer intended to assign some other value to person but made a typo or code completion error. Hard to tell without either being the original programmer, or carefully studying all the context to see whether this conversion makes sense. And it gets harder the further the assignment is from the place where the variables are originally initialized Should the compiler warn here that a value of type String is being assigned to a variable of type Person?

The example would be far more clear, and more in line with Swift conventions as:

var person = Person(withName:"Mary")
let name = "John"
person = Person(withName:name)

The above version is completely unambiguous, both to the compiler and to any other programmers who read this later.

like image 40
Daniel Hall Avatar answered Oct 07 '22 00:10

Daniel Hall