Unit 13: Question Bot Flashcards
Enum
enumeration
enables the organisation of groups of values that are related
Case
in an enum, it’s a keyword that declares a name for one of the enum’s options; in a switch, the case keyword introduces a pattern to try to match a value against
Default
option that is selected when no other option is available; in an “if” statement, the final “else” clause would run as the default; in a “switch” statement, the default option is the catch-all option to make the switch comprehensive
Answering Questions
In this playground, you’re going to work on a function to make QuestionBot answer questions.
You can build the brains of the app in a playground before adding it to the app. This lets you concentrate on the part you’re working on right now. The “brain” of QuestionBot is the function responseTo(question:). You’re going to try out a few versions of that function. Here’s an example: func responseTo(question: String) -> String { return "Sorry, what was that?" } //: Now we can ask questions. Look at the answers in the sidebar. 👉 responseTo(question: "How are you?") responseTo(question: "I said, how are you?") responseTo(question: "Oh, never mind.") /*: This doesn’t make for great conversation. The function gives the same answer, whatever the question. There are more interesting examples coming up. */
First Words
In this exercise you’ll make a function that gives different answers depending on the first word of the question. The hasPrefix() method tests if a string begins with another string:
"swift programming".hasPrefix("swift") "swift programming".hasPrefix("programming") //: - callout(Exercise): Amend the function and tests below to respond to different first words. How about adding answers for who, what, why, and how questions? func responseTo(question: String) -> String {
if question.hasPrefix("hello") { return "Why, hello there" } else if question.hasPrefix("where") { return "To the North!" } else { return "That really depends" } }
responseTo(question: "hello there!") responseTo(question: "where should I go on holiday?") responseTo(question: "what is the capital of France?") //: You may have noticed that `where` works, but `Where` or `WHERE` does not. You’ll learn how to deal with that on the next page.
//:
Dealing with Cases
On the previous page you wrote a function that matches the start of a string against a list of possibilities. However, it would only work when the strings were of the same case. Look at the results in the sidebar:
"where" == "where" "Where" == "where" "WHERE" == "where" /*: You could deal with this by listing every possible combination of cases, but that would get silly: ``` if question.hasPrefix("where")... if question.hasPrefix("Where")... if question.hasPrefix("WHere")... if question.hasPrefix("WHEre")... ``` Instead, it’s better to change the case of the text before you try to match it, using the `lowercased` method: */ let question = "WHERE ARE THE COOKIES?" let lowerQuestion = question.lowercased() lowerQuestion.hasPrefix("where") //: - callout(Exercise): Rewrite the function below to work with aNy cAsE of QueStiOn TeXT, so you get a correct answer in the example: func responseTo(question: String) -> String {
if question.hasPrefix("hello") { return "Why, hello there" } else { return "That really depends" } }
responseTo(question: "Hello!") //:
Special Questions
As well as having general answers to who, what, where questions, you can include some special answers to specific questions.
func responseTo(question: String) -> String { let lowerQuestion = question.lowercased()
if lowerQuestion.hasPrefix("where") { return "To the North!" } else if lowerQuestion == "where are the cookies?" { return "In the cookie jar!" } else { return "That really depends" } } responseTo(question: "Where are the cookies?") /*: - callout(Exercise): The function above doesn’t work. The first `if` statement asks if the question starts with “where,” which it does. This means the later statements are never tested. Change the function above so that you get the answer “In the cookie jar!” to the question “Where are the cookies?” */
Default Answers
With the functions you’ve written so far, if there are no matches in any of the if statements, then a default answer is returned. In this exercise you’ll make it more interesting by giving a different default answer depending on the length of the question that was asked.
You can get the length of a string like this: "hello".count //: If you want to choose from one of two different default answers, you can use the remainder operator to get the remainder of the count after dividing by two: "a".count % 2 "ab".count % 2 "abc".count % 2 "abcd".count % 2 //: This means that you can convert any string into `0` or `1`, then use the result to decide on an answer: func responseTo(question: String) -> String { let lowerQuestion = question.lowercased() if lowerQuestion == "where are the cookies?" { return "In the cookie jar!" } else if lowerQuestion.hasPrefix("where") { return "To the North!" } else { let defaultNumber = question.count % 2 if defaultNumber == 0 { return "That really depends" } else { return "Ask me again tomorrow" } } } responseTo(question: "Where are the cookies?") responseTo(question: "Can I have a cookie?") responseTo(question: "PLEASE can I have a cookie?") /*: - callout(Exercise): Amend the function above to choose from one of three default answers instead of two.
_Hint:_ `question.count % 3` will give you a result of `0`, `1` or `2` */ //:
Putting it All Together
In this final exercise you’ll combine the things you’ve learned over the last few pages. Update this responseToQuestion function so that it gives the answers specified below. It’s OK to go back and look and code from earlier pages.
func responseTo(question: String) -> String { return "?" } //: 👇These answers should be “Why, hello there!” responseTo(question: "Hello there") responseTo(question: "hello there") //: 👇These answers should be “To the North!” responseTo(question: "Where should I go on holiday?") responseTo(question: "where can I find the North Pole?") //: 👇This answer should be “In the cookie jar!” responseTo(question: "Where are the cookies?") /*: Any other question can have any answer you'd like. You can also make new rules or conditions so different questions have different answers! 👇 Below are some example questions for you to test the final part. You can add or change the test questions if you like. */ responseTo(question: "Can I have a cookie?") responseTo(question: "CAN I HAVE A COOKIE?!?") responseTo(question: "Should I go?")
/*: - note: You'll be cutting and pasting the body of the `responseToQuestion` function above. When you highlight it to copy over, your function body will be different, but it'll look something like this:\ ![](copy-paste-example.png) */
Wrap Up
You’ve put a lot of work into giving QuestionBot a brain, and you’ve seen how useful playgrounds can be for working on a single function without distraction.
The final part of the lesson is to take the new function you built on the previous page, and put it into the app. The instructions for doing this are in your Guide, in the QuestionBot lesson. A helpful //TODO "to do" comment tells where you need to do your work:
Func responseTo (question: String) -> String { // TODO: write a question return "?" }
It can also be changed with the following: 1. Replace the line [return "?"] With the line: Return "I'm sorry, I don't understand the question" 2. Build and run the app 3. Ask another question. Your new answer is there!
New function:
responseTo(question: )
“On the Putting It All Together page of the playground where you built
the final version of the function, use the trick you just learned to select
the entire function body, then copy the text using the Edit menu
(Edit > Copy) or press Command-C (⌘-C).
Back in the QuestionBot project, open QuestionAnswerer.swift.
Select the entire responseToQuestion function, then paste your function from the playground over the version in the app using the Edit menu
(Edit > Paste) or press Command-V (⌘-V).
Build and run, then enjoy your new, improved QuestionBot.
If your app won’t build and run, the problem is likely with pasting the code. Undo the paste you just did using Edit menu (Edit > Undo Paste) or press Command-Z (⌘-Z), double-check the selected text and the location, and
try again. For hints, look at the errors that Xcode is giving you. Following
are some common problems:
Pasting the function into the wrong file. In this case the app might
not build, and you might see errors such as Invalid redeclaration
of responseTo(question:).
Pasting the function in the wrong place in the file. In this case, the
app might not build, and you might see[…]”
Bonus Exercises: Customizing the Interface
You can use Interface Builder to change the way QuestionBot looks.
Open Main.storyboard, and make sure the Attributes inspector is visible.
See the First App: SinglePhoto lesson for a refresher on how to do this.
Background color
Select View, as shown in the document outline below. Use the Background attribute to choose a different color. ”
“Robot head
Select the label as shown in the document outline below. Using the
Text attribute in the inspector, change the emoji to a different character. Press Ctrl-⌘-Space to bring up the emoji picker. ”
“Welcome message
Select Response Label in the document outline and change the opening text. Press Ctrl-Enter to add a new line if you need one.
Build and run to see your changes, which should look something like the screenshot shown to the left. ”