A2 Basic 3112 Folder Collection
After playing the video, you can click or select the word to look it up in the dictionary.
Loading...
Report Subtitle Errors
Stanford University.
Okay, well welcome to CS193p, Winter 2015.
This is Lecture 3.
This is gonna be all demo.
today, my voice is mostly recovered from last week,
not 100% as you can tell.
But it's getting there.
So what we're gonna be doing today is a demo.
We're gonna extend our calculator a little bit,
we're gonna make it more powerful.
But more importantly, we're gonna have it obey this MVC
design paradigm.
'Kay?
So it's good, a pretty good example of showing how
we're gonna separate the stuff into the camps here.
Now, we're gonna cover a bunch of other things,
language features and stuff as I always do.
That's really the primary goal of these first three lectures
with the demo.
So I just mean for you to see it in action because you can
read all you want about swift or, about iOS, but until you
actually see it act, turning into an app, it's not real.
So I'm just trying to make it real for you.
I'm going to go to my last slide, because,
once I go to the demo, I'll forget to come back.
Which is just the what's coming up in this class.
On Wednesday, it's gonna be no demo, it's gonna be all
slides, it's going to be one of the few lectures where it's
all slides.
But what I'm gonna try to do,
on Wednesday, is give you the highlights of this all
this reading that you're doing.
Okay? Because you're
reading a lot of stuff and it's sometimes hard to
tell what's really important in there and what's not.
So I'm gonna kinda give you the highlights so
you can get an idea of what's important.
And then I'm also gonna start talking about some of
the foundation layer API in IOS that's the non you,
user interface layer basically and
kinda what some of the classes are in there.
And then also just a little bit of how we use the language
features of swift, and foundation, in iOS so
that you can kinda get this kind of your, this want,
next Wednesday's lecture is,
is gonna be your baseline lecture,
can kinda get you grounded in how to do all this stuff.
And then next week we'll start diving in,
to build a more sophisticated iOS application.
Okay, I know this is kind of a new whirlwind in first two
weeks, you're learning a new language, all new system.
But hopefully by the end of this week and the end of your
second assignment which will go out on Wednesday you'll be
pretty confident that you'll at least,
you know, have a, solid ground foundation to build from,
no pun intended there.
There's a holiday weekend this weekend no Friday section and
no class on Monday until we resume next Wednesday, and
the primary thing I'm gonna do next Wednesday,
not day after tomorrow but
the next Wednesday, is talk a little more about auto layout.
Cause you've only just seen kind of a glimpse of auto
layouts so far and
I haven't even really told you how to do auto layout and so
you're kinda just fumbling around and trying,
trying to reproduce what I do so next Wednesday we'll
talk about how to really do auto layout hm, and all that.
'Kay, any questions before I dive into this demo?
Hopefully my voice will hold out I can already hear it
starting to not hold out but we will see.
All right.
So, I'm going to just go to Xcode here, launch Xcode.
And we're gonna leave off right where we, were,
last time, in the calculator.
There it is right here, and so these are UI.
Hopefully you recognize that and you did,
did your homework.
I hope.
And here is this area that I selected at the end,
which is this area that's really has not,
this is not about how, how the calculator gets presented on
screen, this blue area is about how the calculator is
a calculator, okay?
This is where all our calculations are and
this blue area really shouldn't be in this class,
this view controller class because this is the C
of our MVC, okay.
And our MVC, this is the C, this is the V, the view,
these are the minions that this controller's using.
And today we're gonna create the M.
Okay? The model.
The model is gonna be what our calcu,
what our application is, which is, it's a calculator.
'Kay?
We're also going to enhance our calculator the primary new
feature we're gonna give our calculator is that
our calculators model is gonna remember every operand and
operation you ever asked it to do.
Okay, so right now as we do operations we consume all
the operands.
'Kay, they consume, kinda, they're gone.
So in this case,
we're going to actually collect all the operations and
operands in our, in a stack and then we can
ask the model to, evaluate that stack of operations and
operands at any time we want.
And the reason we're adding that ability is because your
homework, assignment number two, you're gonna add two
major features where having all the operands and the
operations in a stack is gonna be really valuable to you.
So you'll be starting your second homework with what I
do today cause you'll need this capability to do what I
ask you there.
Okay, and I'll talk about that at the end.
If I forget to talk about that, remind me.
Say, tell us about assignment two.
Okay.
So, how do we create a new class.
Because we're gonna put our model, 'kay, the calculator,
kind of, it, it's the guts, in a different class.
So how do we create a new class, in Xcode.
We do that up here from the File menu.
We go, New > File.
So, you're gonna do File menu > New > File for a lot of
different things you're gonna add to your project.
Not even just, new classes or
whatever, but, when you click that you're gonna see
there's a lot of different things you could add.
And, we're in iOS, so
you're gonna click on this iOS thing at the top.
And we wanna add a source file.
And over here we're gonna be doing this later in
the quarter, this is how we basically add subclasses of
iOS classes, Co, Cocoa Touch classes.
But we're gonna do today this one Swift File,
you can see it's an empty Swift File.
And since our model is completely UI independent it
doesn't inherit, it doesn't subclass any IOS class or
anything, it's just a basic, Swift File.
So I'm gonna pick on this Swift File,
click Next, and now it wants to know the name of
it and where we wanna put it, and we're gonna put it in
the same place that all our other swift files are.
Here's our Controller and
this AppDelegate, we moved it out of the way at the very
beginning of the very first lecture but it's in there too.
So we want to put it in this same directory.
And we're gonna call this new class CalculatorBrain.
Now, you don't have to have the name of
this Swift File here be the name of the primary class but
we always do that.
It would be kinda confusing to
people a little bit if the name of the Swift File
was different than whatever the primary class is in there.
But it's certainly legal.
All right.
And Swift, the name of
the file really doesn't mean anything.
It's what's inside that matters.
But, CalculatorBrain is gonna be the name of our class,
our model.
I'm calling it that cause it's the brain of our calculator,
I'm trying to pick a descriptive name.
Notice the capitalization here,
types in swift, we always capitalize them.
And we do not put underbars and other stuff in there.
Okay? We use what's called this
camel notation here, where every word gets capitalized,
including the first name, word for types.
Everything else, we don't capitalize.
So property names and things like that, function names,
those all start with lower case,
they still do the uppercase and the other words.
That way we, in our reading our code we
can really quickly pick out what to type and what to not.
'Kay? So please adhere to that.
If you don't, you're gonna look like a newb out there.
'Kay. Calculator brains what we're
gonna call it, I'm gonna create it.
Here it is right here.
I'm gonna make it my whole screen.
You can see that the import here is not import UI kit,
it's import Foundation.
Foundation is that layer, that kinda core services layer I
talked about in the first lecture.
It don't have many UI stuff in it which is good because our
model is UI independent so there should be no UI in here.
So we would never be importing UI kit into a model class,
'kay?
You can feel free to stop me, by the way,
if you have any questions.
All right, so we're gonna create a new class,
you already know how to do that.
We just type class and
then the name of the class, it's gonna be CalculatorBrain.
Now, this class is not going to inherit from any other
class, 'kay?
Just gonna be a basic swift, class.
Now sometimes your model might inherit from a class called
NSObject, and
I'll talk about that a little later maybe on Wednesday even.
You'll get a little bit if you inherit from NSObject, but
we're just gonna have it be basic swift base class, 'kay.
It doesn't, doesn't need to inherit any functionality.
Okay.
So what's gonna be our data structure of
our calculator brain.
It, it has to be a little different than the data
structure we used in our controller to
capture the operand because we gotta capture operand,
operations and operands both into this.
So we want it to be a stack, I'm gonna call it opStack and
but the type can't be array of double.
Okay, because operands are doubles but operations
are like a combination of a syn, a mathematical symbol
like plus, times and then also a function.
Function that actually does the thing, 'kay?
So obviously we can't do that so
we're gonna have to need some,
some new data structure I'm gonna call that data
structure op and we're gonna define that in a second.
So op is gonna be something that could be an operand or
maybe it could be an operation.
'Kay? It could be either or.
'Kay?
Now a couple of things about this here is of course I
have to initialize this so I'm gonna do
the exact same thing that I did in the controller which is
I'm just gonna create an empty array of op.
'Kay? And
I'm even gonna use a little different syntax, 'kay?
We've been using this.
I like this syntax because especially for
people who are first time to swift it's very clear,
this is an array and inside the array are these ops but
this is evidently not the syntax that is preferred.
The preferred syntax is actually to do [Op] 'kay?
So this is just an alternate syntax, putting square
brackets with the type in the middle for declaring an array.
It's exactly the same thing just different way of
typing in, identical in every possible way,
it's exactly the same.
Okay.
I think this is a little bit preferred because if
you ever initialize an array which will see later.
You use this syntax to create the array and
put things in it.
So I, I can understand why they do that.
Okay? So this is an array of op.
That make sense?
Now, let's talk about op.
What kinda thing should op be?
Well, we could make op a class.
An op could have a property for op,
for an operand, which would be the value of the operand.
It could have another property, which is the,
symbol, mathematical symbol for the operation and
another property, which was a function, which does it,
and obviously, if the operand is set,
then the other two would be not set and vice versa.
But that, that's a little bit weird to have a class that
has properties that sometimes they're set and,
and if other things are set, they're not set.
It's really not what we want.
What we really want is an enum.
Okay, so you're probably used to enums in other languages so
I'm gonna create an ema,
[UNKNOWN] enum, it looks very similar creating a class.
I just use the word enum instead of class,
obviously no inheritance for enum, sorry.
But enums can have functions, just like the class,
they can also have properties but only computed properties.
'Kay, the Camry's stored properties.
So you know enums are kinda for basic types and
enums are really great when you have something that can be
one thing one time and a different thing another time.
And never both at the same time,
that's kinda what enums are right,
they're enumerating different possibilities so
we could say you know case operand and we could have
a case operation, to have the different things that we have.
Now, in other languages, this would be as far as we can go.
And this would be pretty useless.
Because if we had an array that just said whether it
was an operand or an operation, that doesn't help.
I need the actual operand.
I need the operations mathematical symbol and
its function.
I need them, they have to be in this e-mail.
And Swift has a really cool feature where you can
associate data with any of the cases in the e-mail.
So for an operand I'm gonna associate the data double.
So if my enum is an operand it'll have this
double associated with it,
that's gonna be the value of the operand.
And similarly for
operation I'm actually gonna do unary operation first,
that's a single argument operation.
I'm gonna have a string which is gonna be the symbol,
the mathematical symbol for
it and of course I'm gonna have a function.
Okay again functions are just types in swift,
it's no different than string 'kay we're just saying this is
a function, put a function in there.
A lot of times we'll do the curly braces and
put a closure use closures to create our function but
we could create actual functions and
pass them in there, that's fine.
So, and we'd also want a binary function here that
takes two arguments.
Binary operation and
just those two arguments here in it's function.
Okay?
So now we have the stack.
Okay. Which is an array of ops.
And these ops are either each op in this, is array is either
an operand or it's one of these two kinds of operations.
Okay so so this is great.
We got this op it's either an operation or an operand.
How are we going to, you know, put things into
this op stack for example and something like that.
So let, let's go talk about, the API.
A, API stands for application programing interface.
API is kind of the meth, all the methods and properties
that make up your class, the description of them.
So I'll use that word a lot, API.
And we really need to be able to put an operand on there and
stack, and we need to be able to put an operation on.
So I'm gonna have a function called pushOperand, and
it's gonna take an operand, which is a double.
Okay it's not gonna return anything yet anyway.
And to push an operand on my stack, could not be easier,
I'm just gonna say opStack.append,
you'll remember that append is a function in array and
the thing that you put on,
obviously has to be this little type T.
T is whatever you put in here, so op in this case.
So we have to have an op here.
How do you create an enum item?
You just Op.Operand and you give it the associated value.
'Kay?
So, very simple kind of way to create these enums and
associate the value with them.
Any questions about that?
Okay, and then how about operations?
We'll have instead of push,
we're gonna call this performOperation.
And I think when I do performOperation, what I'm
gonna have is, my calculator brain is going to have
a bunch of known operations, things it knows how to do.
And when you perform an operation,
you just specify the mathematical symbol of it.
So the argument here is going to be symbol,
which is a string.
Okay?
So, to append an op on here that is, an operation,
I'm gonna need to have these known operations.
So, how am I gonna do that?
Well, to have known operations, I'm gonna create
another instance variable here called knownOps, so
my known operations.
And it's gonna be a dictionary.
Okay, now, you read about dictionaries in
last week's reading assignment.
That's why I have the reading assignment due today.
Cuz then I can know you've read about them.
I hope you have.
And so, how do I create a dictionary?
It looks like this, Dictionary.
And it's the same kind of thing with these angled
brackets, because you have to say for the dictionary,
what type are the keys, what type are the values.
And our dictionary is gonna have keys that are strings and
it's gonna have values that are ops.
Oops, sorry, ops.
Okay, and I'm gonna create one.
'Kay?
Everyone understand this?
Now, this knownOps, I'm just gonna put all of the ops that
I know in there, where the key is the symbol and the value is
the actual op, and then when someone says performOperation,
I'm gonna look it up in the knownOps.
And when I find it, then that's the operation I'm
gonna push onto the stack, all right?
Make sense?
But I have to load this knownOps up.
Oh, but first of all, so let me talk about this syntax.
Just like array has a special syntax with the square
brackets, so does dictionary.
So to have a dictionary like this with this kind of
special syntax, we're gonna do open square bracket.
And then a colon in between the key and
the value type, so it looks like that.
So it looks very similar to array, but
you've got this thing where you've got the key and
the value separated by a colon.
'Kay?
Same thing, though, exact same thing.
Just a dictionary, strings,
looking up in strings to find ops.
All right, so how am I gonna initialize this knownOps?
Well, this is a great time for
the first time for you see an initializer, okay?
So far we've been creating classes like right here, okay,
just by putting these parentheses.
And I told you that was calling an initializer in
Dictionary, okay, and
this one was calling an initializer in Array.
And so we're gonna have our own initializer in
CalculatorBrain, and
we just do that by saying init, like this, okay.
Now any time someone says something like let brain equal
CalculatorBrain, with the parentheses, okay?
It's going to call an init that
matches the same arguments.
In this case, no arguments, so it's gonna call this init.
Okay.
Couldn't be simpler there.
So what are we gonna do in this init?
We're just gonna initialize this known op, so
I'm just gonna start putting some known ops into this
knownOps dictionary.
We need our friend special characters here for that.
So let's go ahead and
put, well, let's put times here first, I guess.
Okay, and we need to create an operation.
How do we create an operation?
Very similar to how we created this enum.
Op, dot, and times is a binary operation.
And you can see that it's typing this for me.
I'm just pressing Tab to get along.
This is the symbol, which is this thing here.
Now, this is kinda bad code that I ended up
typing this twice in the same line.
If I accidentally use the wrong x,
like some x from somewhere else or the x just from my
keyboard might be different from this x, than this x, ugh,
we could get in trouble where these things don't match up.
So later, in the, right at the very end of the demo,
I'm gonna show you how we could do this in
a way where we don't have to type this x twice like that.
Okay.
But now we just need the function.
We know how to do that with closures.
We say $0 times $1.
End the closure.
And yes, I could put this closure outside,
since it's the last thing here.
That is also legal to do when you're creating
the operations like this.
'Kay?
So that's kinda nice.
Let's do our other three binary operations here.
We'll go divide.
And this is where it really gets annoying to have to
type it twice.
But I have to show you something else before I can
show you how to do that right.
Let's go here.
And there we have minus.
You can see there's two different minuses there, so
hopefully I clicked the same minus in both those spots.
And then we change these things.
We know that divide is 1 divided by $0, and
this is plus.
And this is 1 minus 0, $1 minus $0, okay, so
everyone cool here?
These enums are really easy to create.
The API of them is really, really nice, simple.
And then we have our other operation,
which is our unary operation, which is square root.
So let's put that in here, square root is right here.
And we'll put it right here.
And square root is not a binary operation it's
a unary operation.
Oops, look at all this.
'Kay?
And of course, inside here, it's square root of $0.
Okay, you remember that from last time.
So this is good.
Now, while I'm here,
I wanna show you a couple things more about closures.
Okay.
This, what is this curly brace?
It's a function that takes one argument and
returns one argument.
And we know that
it's doubles because we're creating a unary operation.
And so, it's inferring the type here, right?
Everyone understand that?
Well, there's another function that returns a function, or
there's another function that takes a double and
returns a double, that does square root,
it's called square root.
So inside here, we could just say square root.
Okay, we don't even need this business.
Just wanna emphasize that
we're just passing a function here.
And it can be a named function, or
we could use these curly braces.
Now, this is really gonna freak you out, cuz watch this.
For times, there's a function that does times called times.
Okay.
So in Swift, all these operators, times and
all these things, are just functions.
They just happen to be specified in a way that says
that they can be infix, right, between the two
arguments instead of taking the arguments in parentheses.
And we do the same thing here with plus.
All right, plus.
Now, we can't do it with divide and
minus because the order is backwards.
Right, we put the things on the stack,
we pull them out backwards, so
we can't do it with those, but.
I just wanna emphasize, that's what's going on there.
Okay, so now we have this nice knownOps.
So we have this thing.
It's loaded up.
It gets loaded up whenever the CalculatorBrain gets created.
So that's all good.
Now we can use that down here in performOperation.
All right, so how are we gonna use this in performOperation?
Well, we basically wanna let the operation equal
knownOps sub symbol.
Okay? Someone passed us a symbol.
They're trying to perform this operation.
So this is either a plus or a times.
Hopefully an operation we know.
And we're gonna look it up in knownOps.
And the way we do that is with the subscript notation with
the square brackets.
Okay? That's how you
look something up in a dictionary.
But what might be kind of surprising to you,
what type do you think this would be, operation?
Any guesses, yeah, some people are saying the right thing.
You'd think this might be an Op,
because I'm looking up in knownOps right here, a string.
And so hopefully I'm getting an Op, but this is not an Op,
this actually is an Optional Op.
Okay, now why is that an Optional Op, because you
might be looking up something that's not in there.
And it has to return, oh, nil, sorry, couldn't find it,
so that's why it has to be an optional, is returned.
So a dictionary,
whenever you look up something in a dictionary,
it always returns an Optional, okay, either nil or
the type of thing you said was supposed to be in there.
So I'm gonna if let here, I'm gonna say,
if I'm able to look up my operation in my knownOps,
then I'm going to push it on to my op stack.
Okay.
Are you cool with that?
Make sense?
Okay.
Now, what's next?
Well.
Now we have.
Oh, well.
I'm gonna take a pause here to
talk a little bit about access control.
Okay?
Access control is about public and private.
Okay? What methods in this class
are public, in other words, other people can use them,
other classes in my code allowed to call them?
And what things are private?
My internal data structures that I
don't want people messing with?
Okay, so the way public private works in
Swift is kind of interesting.
You basically specify the things you want to
be private by putting the word private on them.
If you don't put any word on them,
then they're public inside your program.
'Kay?
And you only use the word public if you're shipping out,
like, a framework of objects to other people, and
you want stuff in there to be public outside the framework.
So I'm making some framework,
a bunch of objects that I'm trying to sell to people or
I get people to use to do something, and
of course I'm gonna have things where my objects inside
my framework can talk to each other.
There's no keyword needed for that.
Then I'll have things inside certain objects
that are private only to that object, I'll say private.
And them some of them might be public that the customer who's
buying my objects, my framework, can use.
Now, in this class we're not gonna be doing frameworks,
we don't really have time to get to that, so
we're not gonna be using the keyword public,
we won't ever use that,
because we don't have any frameworks.
But we are gonna use private.
And, starting with assignment two,
it's one of your evaluation criteria is gonna be,
make private things private.
'Kay?
So that is important to do.
And you could just say,
well, I like everything to be public.
Well, that's bad.
Okay? If you make your
internal structure public, and some other object in your
program starts mucking with it and breaks your object, and
then you come to a new version of your program, and
you change something, and now everybody's breaking.
That's bad, okay, that's chaos.
So the only things that want to be not private are things
that you're committing to sign up to support.
So in this class, the only public things so
far are the initializer.
Obviously, we want to allow people to
create a CalculatorBrain.
That's clearly public.
Also pushing and performing operands and operations.
That's public.
Okay?
Everything else, for now, I'm gonna make private.
So I'm gonna make this private.
Notice that if I make this private,
it's gonna start saying, whoa,
wait a second, this can't be public, you know, it can't be
non-private because this is private and it uses it.
That's what this warning's gonna say right here, see.
Property must be
declared private because its type is private.
Okay, that's the type of this.
But I want this to be private anyway,
this is my internal data structure, opStack.
Now, knownOps is kind of an interesting one.
Maybe I would want that to be public one day,
because maybe I want people to use my calculator brain and
teach it new ops.
That wouldn't be that unreasonable.
However, I'm not ready to support that functionality in
my CalculatorBrain.
I'm just not sure I wanna do it this way.
Maybe I don't want this property to be public,
I might want to just have some functions to learn an op or
something like that, so
I'm just not sure, so I'm gonna start out private.
And that's really, when you're designing APIs,
you wanna kinda start out,
make it private first, and then open it up as you're
willing to support that functionality.
Question? >> Is the common view in
Swift to make most instance variables private and
use getters and setters, or is it to make them, if,
if they are supposed to be public, or
make them public and then let the?
>> All right. So the question is, is it,
is it kind of part of the Swift way to make
most instant variables private and
then have getters and setters that are public to get them.
That doesn't really even make sense in Swift.
That's more of an Objective-C thing.
In Objective-C, you had instance variables, and
then you had properties that would get and set them.
And Swift has kind of merged those a little bit
closer together so that properties are really kind of
the public or private getters and setters.
So, if you have a property, you just have to
decide whether you want people to access it or
not, and if not, make it private.
And if so, make it public.
And that, you know, don't make it non-private, basically.
And that's, just that's all you need to think about.
I wouldn't even think in Swift in terms of instance variable
versus the property.
Now, it is still possible in Swift to do that,
because you have computed properties.
And those could be setters and
getters that are setting private properties.
But we're gonna see on Wednesday, even,
I'm gonna talk to you a little bit about a way that when your
properties get set, you can intervene,
you can check them to make sure the value is okay.
So if you have a public property,
you can still protect it by intervening a little bit
when people set it or try and get it.
So it is possible to still have some protection there,
we'll see that.
All right, so these are our only public things.
Now, there's only one other public thing we need to do in
our CalculatorBrain, which is,
we need to let people evaluate this stack.
So people are pushing operands and performing operations,
now they wanna know what's the result.
Okay? They
pushed an operand of a five.
They pushed an operand of a four.
They performed operation plus,
they want to see four plus five.
Where's that nine, okay?
They need the result.
So we need another public method here,
which I'm gonna call evaluate.
'Kay? And evaluate,
we could have it return a double, for example.
And it would just evaluate this opStack and
return the value.
But I really can't make this a double.
Really, this has to be an optional.
'Kay, why does this have to be an optional?
Well, that's because someone might get my CalculatorBrain,
and the first thing they do is,
they say, perform operation plus.
Okay, well I have no operands.
Okay? And
you're asking to evaluate plus.
I can't do that.
So, I have to return something to you, that lets you know,
I could not evaluate what you ask me to evaluate.
So, I'm gonna return nil in that case,
so valuate here really needs to be an optional.
'Kay, so you can see some of the thinking,
when do you make something an optional when not.
'Kay, so this is a classic case of that,
where you got sometimes you wanna return it and
you can't do it, so you have to return no.
All right, so how we going to implement evaluate?
Okay, how many people in the class,
raise your hands don't be shy, are you comfortable with
the computer science concept of recursion?
Okay. Excellent, that's about 80 or
90%, so I'm gonna explain this really fast then.
And if you don't understand recursion,
if you didn't raise your hand,
that's something you should go review.
Okay? [LAUGH] Recursion is
something, you should know by the time you take this class,
so that's something you definitely wanna know.
So, how are we going to use recursion to
evaluate this stack?
All right, looks like this.
I'm gonna do a sample stack, right here.
So, let's say I put a 6 on the stack, and then I put a 5, and
then I put a plus, and then I put a 4, and then I put times.
Okay?
So here's our stack, and I'm gonna evaluate this,
I'm gonna recursion.
How am I gonna do that?
Well, really, what I'm gonna do is I'm gonna
have a helper method here, a recursive helper method.
I'm gonna call it evaluate also, actually.
And it's gonna take a stack, as an argument,
a stack of things to evaluate.
And it's only gonna evaluate the top thing on the stack.
That's it just gonna value the top of the stack and
return it, but the top thing of the stack might
involve looking at every single of one of these, right?
Cuz, this times needed to two operations.
So, lets look at this, this recursive evaluates gonna come
in here, it's gonna try and
evaluate the top of the stack, which is a times.
Okay? So it's like,
okay, I'm doing times.
Now for times it needs two operate,
two operands here for times.
So, it recursively calls,
itself to say give me to first operand for time.
And so recursively, comes in here, it finds a 4 on
the top it's like, I know how to evaluate 4, it's 4.
So, it just returns.
Okay, so now I have my first operands.
'Kay? Now,
I take the rest of the stack and
evaluate it, to get the second one.
And when I do that, I get plus, 'kay?
So, plus says, oh, I have to evaluate plus.
It needs operands.
So, I come over here, I'm getting a plus.
And I gotta go recursive again, to go get its operands.
I get the 5, that's good.
I'm gonna go recursive again, get the 6, over here.
And I've evaluated the whole stack.
So, you see how I have to keep going backward recursively to
my evaluate-
>> [COUGH]
>> To get the operands for my operations.
Once, I get to an operand I can stop,
okay number, I got it and I'm out of of there.
But every time I encounter another operation,
I have to keep going recursively to
get all my arguments, any questions about that?
'Kay, so it's actually gonna be pretty simple recursion.
When you see the code, you're gonna be, that makes sense.
So, I'm gonna have this separate I'm gonna put this up
on top for scrolling reasons.
Oops. Didn't mean that.
The separate evaluate.
And this evaluate is going to take a stack of ops,
as its argument.
And why does it take a stack of ops?
Because as it's recursing,
it's using the rest of the ops.
So, you see what I mean?
It's not,
it can't be looking at the big opStack in our brain.
It can't look at this.
'Kay, cuz it's kind of consuming it.
Right? And every time I call it
recursively, I'm gonna get fewer operands to work with.
So this is what I'm doing.
Now, the first time I call it,
right here, I'm gonna give it the full opStack.
So, I'll call my recursive one from here.
Now, what's this thing gonna return?
'Kay.
That's interesting and
here's a big new thing for you to see.
You've read about it I, I can't remember I
even asked you to read about this but I think I.
No, I guess I didn't.
Which is tuples, 'kay?
So in Swift, you can combine multiple things together
into one kind of really te,
mini data structure called a tuple, 'kay?
Don't let the tu [LAUGH] sound in there fool you.
It's not just two, it's any number, okay?
And you just put them in a parentheses, okay?
And, and that's it.
So you can use this for return values.
So I've gotta function right here,
and I actually need to return two things from this evaluate.
'Kay? One thing I
need to return is the result of a evaluating it.
But the other thing I
need to return is the rest of the stack that I didn't use.
Cuz as I'm working my way down here and I take off that
times, and the 4 and the 5, okay, I'm consuming things but
then I'm leaving the rest of the stacks, so
I have to keep returning what's left of the stacks,
while we keep consuming it.
Okay?
So, I'm gonna return this in a tuple.
Tuples could not be simpler syntax,
just open parentheses, not nine, open parentheses.
Open parentheses, and just all the types that you,
of things that you want in here.
So, I'm gonna return a double question mark,
that's my results.
'Kay?
That's what's eventually, gonna be
returned out here after all the recursion unwinds.
And then also I'm going to
have the ops that are left over.
Now, a tuple could look just like this, unnamed.
Did you see how these things are not named,
each of these things in here.
But you can also put names in here as, if you want, as well.
So maybe I would call this one the result.
Okay? And
I would call this one remainingOps, 'kay?
And I kinda recommend putting those in there, and
you'll see why in a second because there's two ways to
call a function that returns a tuple and get the results.
And one of the ways requires that you name these, 'kay?
So, it doesn't hurt to name the, you might, as well.
It's good documentation.
Someone looking at this now knows, oh, yeah,
this is the result of the evaluation, and
these the ops that were left over.
'Kay?
All right.
So let's dive in here.
The first thing,
line of code I'm gonna put in this recursive function
is the failure line of code,
which is return nil, ops, okay?
So if I fail, okay, I'm gonna try and
do my best in here to evaluate these ops you passed me, but
if I fail I'm just gonna return my result of nil.
'Kay?
And that's gonna be my default is to return nil so
I know I failed.
So, if I run out of operands or
I run out of stack can't find it for
example, it's just gonna fall out here and return nil.
Okay?
So that's good.
So, what do I need to do here?
Well, first thing is I need to make sure I have some ops.
So I'm gonna check to see if the ops is not empty.
Okay, if you've handed me a stack of no ops to evaluates,
I can't do that.
So I'm just gonna return nil.
'Kay? So
that's the very first thing,
I gotta make sure I have some ops to work with.
Now, I'm gonna grab the first op of the stack, so
in this example, I'm gonna grab that x off of here.
'Kay?
I'm gonna do that,
I'm gonna try to do that by saying, let op equal ops.
'Kay, ops is this argument, right here.
'Kay, that's the ops, you told me to work on.
And we know how to removeLast.
Remember, removeLast from last time?
Removes the last thing off an array.
And when we are trying to make an array look like a stack,
that's how we do it, okay?
We push things by putting these on the end of the array.
We pop things by, by pulling it out.
But you can see I got an error there.
[BLANK_AUDIO]
And it's very important to understand why I
have an error here, okay?
So I'm gonna click on it.
We're gonna read what it says,
it says, immutable value of type array of op,
only has a mutating member named removeLast.
Okay, well this is kind of a formal way of saying,
you can't do removeLast on ops because ops is immutable.
It's read-only.
You cannot mutate it.
You cannot change it.
Okay, why is ops read-only?
Well, there's two things to think about here.
One is, when you pass arguments into functions,
unless it's a class that you're passing,
unless you're passing an instance of a class.
The thing you pass is copied.
'Kay?
It's very important to understand that,
that's passed by value.
You're used to it in other languages,
most languages do this, pass by value.
Arrays and dictionaries are not classes.
They're not classes in Swift.
They're structs.
You know, like a C struct?
'Kay?
Arrays and dictionaries are structs.
Structs in Swift look a lot like classes.
They have functions,
they can even have properties that have storage.
They're almost identical to a class, really.
The only two huge differences between structs and classes.
One is that classes can have inheritance.
And structs cannot, okay?
But number two is that structs are passed by value and
classes are passed by reference, okay?
Very important that you understand that distinction.
So structs are usually only used for basic.
You know, components like arrays and dictionaries.
Even doubles and ints are structs in Swift, okay?
>> [COUGH]
>> And that's great because that means doubles and
ints can have functions on them and things like that,
which we will see as the quarter goes by.
But those things are all passed by values.
So that's the first thing to understand is that this ops,
when I call evaluate, whatever array of ops I pass to it,
it's gonna be copied.
Okay?
The second thing to understand here is that they're kind of
an implicit let in front of all things you pass.
In other words, they're read-only.
Make sense?
And a read-only array can't be mutated.
I can't append things to it.
You can't remove things from it cuz it's read-only.
Now, I can actually put the word var here, okay?
If I, sorry.
If I put the word var here,
then ops inside here look no error.
Ops is a mutable array.
It's still a copy though.
So they copied it, made it mutable.
And now inside here, I have a mutable copy to work with.
Now, I'm not a big fan of doing that, 'kay?
Putting var up here.
I think it's a little confusing for
readers of the code,
to understand exactly what's going on there.
So, I'm not gonna do that,
instead, I'm gonna make a local variable here, which I'm
gonna call remainingOps and I'm gonna set it equal to ops.
Now, when you set equals like this,
that copies it if it's not a class.
Classes are all by reference.
It's exactly, what you would think.
>> [COUGH]. >> But anything else,
strucks or enums or anything else.
When you do equals here,
this is actually going to make a copy of this, and
put it in here.
And since it's a var, it's going to be mutable.
Okay?
So now I have a mutable array of opts and
now I can say remainingOpts.
Remove the last one.
And now I truly do have the remainingOpts.
I've removed the first thing in there.
[BLANK_AUDIO]
Did everyone understand that little tidbit there?
Yeah? >> So there's a,
like a, a unseen let in sort of the opts?
>> Yeah. >> Why isn't that like in
front of doubles and
like ends or straightened >> It is.
So, the question is why is there not a kind of unseen,
let in front of all arguments?
Pretty much all arguments to functions kind of
have that unseen let in there.
They're all read on, 'kay?
So and you could put var in front of any one and
turn it into a mutable copy of it,
that you could use locally.
But if you only use it locally,
it's not that great a thing.
Okay?
Now, there is a way to have, to pass by value things back
out, but I'm not even gonna talk about that.
Okay.
You can read about it.
It's this in out thing.
I'm not even gonna talk about it.
I really think it's better to stay within the value,
pass by value, pass by reference parameters.
I think you can get more readable code that way.
But there is a way, there is a way I'm not going to talk
about to do in out basically, prime numbers that go in out.
Yeah.
>> Is there any way to
[INAUDIBLE]
>> Yeah that's what I just said.
There is a way to pass it kind of by reference in out.
You know, you pass it in, you modify it,
and then it'll come back out when it's done at the end.
So, it's kind of like by reference.
But the other thing you said is,
oh this is terrible I'm making three copies of
that dang thing, this must be super slow.
And the answer is no.
Swift is super smart about not actually copying it,
until you actually make a change to it.
So here when it passes a copy in it didn't really
copy it, it just kinda passed a pointer in but it knows that
pointer is by, you know, not by reference it's by value.
And then when I copied it again here.
It still didn't really copy it.
Even if this array had 10,000 things in it,
it didn't make 10,000 copy of it.
It was only here where I actually mutated,
now it had to make a copy.
And it may not even have made an entire copy.
It might have just kept track of the changes, for example.
So, it's super smart behind the scenes.
Sweet to very smart.
So, don't worry too, about much about oh,
I'm copying these things over and over.
Swift is making the minimum out of
actual copying going on.
Okay?
All right, so now I have remainingOpts here,
which truly are my remaining opts.
'Kay. Because I've
removed the top one, the x, off the top.
So now I've got all the remainingOps,
in this local variable here called remainingOps.
Okay.
Now, what am I gonna do with this op that I pulled off,
this one on the top, x?
Well I'm gonna get the associated value from
the enum.
'Kay. Either this or these or this.
And how do I do that?
I use Switch.
'Kay, I told you that Switch is really important.
And now you're seeing that Switch is really important.
Switch is how you pull things out,
associated values out of enums.
So I'm just gonna switch on the op.
'Kay, this is the op that I pulled off the top,
that x from the thing we did on the board.
And I'm just gonna look at the cases, so
I have the case operand, okay.
Notice that it puts a little dot here because it's
really Op.Operand and it's using type inference to
know that it's Op.Operand, right.
Op.op, Op.Operand but it doesn't need the op there.
And here it's asking in this space, what do you wanna do
with the associated value if you're handling this case.
Where the enum is operand.
'Kay?
Well I want to let that associated value
be assigned to a constant called operand.
'Kay?
And yes I could put var here, which would do the same thing,
except for I could then change the thing in here.
But I almost never wanna do this, almost always let.
So let operand means that inside the handling of
this case, 'kay, this case of the switch.
Inside here, operand is gonna have the associated value of
the operand.
'Kay?
Oh, that's exactly what I want.
I'm just gonna return right now I have to return this
tuple right here.
So I'm gonna returned the operand.
That's the result, 'kay.
When I go here and
I encounter that next one down which was a four, I got a four
I can just return that result to evaluate this one.
And I also though have to return the remainingOps.
'Kay, so I'm just returning the two values of this tuple,
notice I don't have to put result colon and
remaining opt colon in here it knows that those match and
so it's still doing it.
All right, makes sense.
That's it for operand that's all I have to do.
It's kind of a, in the recursion,
it's kind of an end case.
Yeah? >> Is remainingOps part of
the stack or heap?
>> This one here, or this one here?
>> What in general [INAUDIBLE].
>> Okay so, so the question is,
when I do something like this, where is remainingOps?
Is it in the heap?
Is it on the stack?
And the thing is, that's implementation detail.
So, you, you don't know, but you don't care.
All right, so that's operand.
Operand was really, really easy.
How about our operation, that's you, you,
UnaryOperation right here.
Now when we handle the case of the unary operation,
we don't need that first associated value,
that's the symbol, like plus.
Okay well I'm evaluating here I don't care what this
symbol is, I only care what the function is cause I'm
gonna evaluate the function.
So we can actually ignore this by putting in underbar, 'kay?
Underbar in swift is kind of
the universal I don't care about this thing.
Okay and we're gonna see it other places we use it
where it's kinda like, I don't really care about that.
So you just put an underbar there.
That way you don't have to declare a variable with
some dumb name or something like that.
Just put an underbar it ignores it.
'Kay?
But I do care about this.
I'm gonna let that equal the operation that I'm doing.
'Kay?
Everyone, make sense there?
So I'm ignoring the string, but
I'm grabbing the operation.
So here, what I wanna do is return and I'll try to do it,
but I'm not gonna be able to.
I'm gonna say, return this operation with
its operand which I don't have.
And there's some remaining ops that are leftover after I
get the operand.
So I'm kinda, I need to do some stuff here to
be able to return what I want.
The first thing I need to do is get the operand.
'Kay?
So, I did a unary operation let's say it was square root.
I need to go back to the staff and
pick off the next thing but I can't just
assume that it's a number it might be more operations so
I have to recurse, so here's where the recursion comes in.
And I'm gonna show you how to call a function that
returns a tuple.
And get it's value up so this is important little example
here, so there's two ways to do it.
I'm gonna do it one way here, which is,
I'm gonna let operandEvaluation,
which is just a local variable that I'm inventing, equal call
evaluate with the remainingOps that I have.
'Kay, so here I've recursed.
Okay, I'm recursing.
And I just set it to operandEvaluation.
Now, let's look at the type of this thing.
If I look at its type, you can see that it's a tuple.
That's its type.
It's a tuple result remainingOps.
It's this tuple right here.
That is the type of this operandEvaluation.
So now that I have that tuple,
it's the result of evaluation how do I get the result and
the remaining op out of it well I can get the operand by
saying operand eval, [UNKNOWN] operandEvaluation.result.
'Kay?
So that just pull this is the tuple here I'm
getting this value of the tuple out of there.
Now what type is this?
Anybody?
It's an optional.
You're pretty safe saying optional when I
ask what type it is, aren't you?
It's almost always an optional.
Cuz I usually don't ask if it's not.
But it is indeed an optional, an optional double.
It's this type right here, okay?
So we need to turn it into a double if we're gonna pass it
to this operation right here.
So I'm gonna use if let to turn that into a double.
'Kay?
Now, I can actually do this because I have the operand.
Just got it right here.
'Kay? This is now a double, see?
And I can call this operation right here.
And this is the remaining ops, but this has got to
be the remaining ops after we recursed.
So it's gotta be the remaining ops in this operandEvaluation.
So that operandEvaluation.remaining-
Ops. Everybody cool with that?
So that's it.
It's just recurse, we just recursed to evaluate that.
If this fails if, if this recursion returned nil,
then this is, this, if let's not gonna happen this
return's not gonna happen, gonna fall all the way out and
return nill which is what we want, 'kay.
We failed in any of our recursive attempts to
get the operands we need,
we gotta fail all the way up to the top level.
[BLANK_AUDIO]
Okay now binary operation.
Also okay, let's do yeah, binary here case.
Binary.
Obviously same exact thing here.
We don't care about that.
And here we're gonna let operation.
And we're gonna do the exactly the same thing we did
here but we just have to do it twice because we have two
operands to do here, through here.
So let's let opp1Evaluation = evaluate(remainingOps).
'Kay.
And then if we can let operand1 =
op1Evaluation.result.
'Kay, then we got op1, that's good.
So now let's let op2Evaluation =
evaluation(op1Evaluation.rema- iningOps).
'Kay?
And if we can let operand, oops, if we can let operand2
= op2Evaluation.result, then we can
return (operation(operand1, operand2).
'Kay? And
we'll have op2Evaluation.remainingOps) as
our remaining ops.
Okay? [BLANK_AUDIO]
Make sense?
All right. What's our.
We have an error here.
What is it?
okay. Yeah,
this is a good error to cover here.
See this it says method must be declared private because
this parameter uses a private value.
And sure enough op is private so this has to be private.
'Kay?
Now notice by the way,
I don't have default: break here in this switch.
And why do I not have that?
Because I've handled every possible value of op.
'Kay? There are only
three kinds of op.
I've handled them all.
So I don't need any default.
It wasn't like in the other one where we had a string and
we only handle a few strings, we had a default break.
You don't put default break in when you handle every thing.
And it's really bad programing style to
put a default break in every single switch.
'Kay, you should only put them in on the ones where you
truly are breaking because you can't handle every case.
'Kay? All right.
Now, the last thing we have to do is just call this recursive
version from here.
And I'm gonna call this one and
get these tuple values a little differently.
I'm not gonna call it in the same way here.
I'm not gonna say, let something equal.
Instead I'm gonna say let a tuple which has let's call it
say (result, remainder) = evaluate and
I'm gonna pass my whole (opStack) here, okay.
So this is a different way to call a function that returns
a tuple here you actually let a tuple equal the result.
Instead of letting a single thing equal result and
then using the dots to get it, you let the tuple equal it and
notice that these names don't have to be the same as these
names so result is the same, but here I
use the word remainder instead of the word remainingOps.
Okay they do not have to be the same.
And then here we just return our result.
Okay?
So we learned a lot right there, okay.
We learned about tuple,
passing you know things back tuples in
different ways you know how to ignore things in enums and
when we're getting associate values all that stuff.
So hopefully, you got all that.
I see a few people still kinda catching up on their typing.
So I'll break for second here.
[BLANK_AUDIO]
[SOUND] So that's it that's the entire implementation of
our calculator brain.
It wasn't really that bad actually, right?
Pretty simple little data structure here.
Just have to say what our known ops are.
And have this recursion which you know,
actually is quite simple, powerful code.
If you're not comfortable with your recursion I
can see how it might be a little bit disturbing.
But go stare at it for
awhile and you'll, you'll get it, how it works.
Okay.
So, now that we've got this new calculator brain,
we have to use it in our old controller.
Okay, yeah question?
>> Do we have to let like the op stack equal the remainder?
>> Do we have to let the op stack equal the remainder?
Here, you mean?
>> Yeah.
>> well, we're not gonna use remainder, so
actually, even I could put I don't care here.
I only put that remainder there to show you could have
a different name, but I'm not using the remainder.
I only want the result.
You see. >> Won't the op stack contain
what was previously in it before you evaluate it?
>> Yes, the op stack will be
unaffected by this because op stack is an array.
Arrays are passed by value so
a copy of it gets passed into here.
So this would be untouched and which is what I want.
I don't want evaluate to consume my op stack.
I wanna be able to call evaluate over and
over and over.
'Kay? Especially if,
I let's say introduced variable operands and
that's what you're homeworks gonna be, then I wouldn't
want to change the variables to different things and
be calling it over and
over with different values for the variable for example and
then maybe next week I can have an assignment where I'm
gonna make your graph such a thing, which I'm going to do.
Okay?
So that's why I wanna do that.
So anyway, yeah, remainder here can just be anything.
I'm actually gonna put this here because we're
gonna print one this in a second just so
we can get a better look at what's going on.
But first, let's go back to our controller and use this
calculator brain, this nice model we just invented.
Let's use it. Now,
I'm gonna show you how to get two things on screen at
the same time.
That aren't necessarily directly related.
Before we have the story board and then I went up and
clicked this system editor right here and
it showed me the controller.
Because the system editor figured out that, oh,
if you have the story board up you probably want
the controller for the scene you have selected.
But here it's like, I don't know what to show you.
So I'm gonna show you a different way to
get something in here, two ways actually.
One is if you go to this top bar where
it says counterparts, you can mouse down and
you can find all kinds of things about this
like subclasses of this class on the left.
Superclasses of this [UNKNOWN] class on the left.
Of course it has no superclasses or subclasses.
But other things, things it includes are included by it.
You can also just manually go in.
We can go over here for example and
find our view controller and load it up that way, but
I'm gonna show you a different way than doing that
which is to go over here to your navigator.
If you hold down Option and press on
a file like ViewController it will appear on the right.
'Kay?
So Option clicking in here is another good way to
put things on the right.
Okay?
So now here we have our calculator brain on the left
and we have our controller on the right,
we are going to rip out all of the stuff in our
controller that had to do with being calculator.
Okay, so that's all this stuff right in here.
'Kay.
All this calculating stuff, we don't need any of this
because those were only called from there.
'Kay, so our controller's getting quite simple,
our controller hardly has anything left in it.
And that's because the UI only needs this to be controlled.
'Kay?
We also don't need our operand stack because the brain is
gonna do that.
However, we do need a new instance variable here
which is the calculator brain.
Okay I'm just gonna create one like that,
this is extremely common okay this is
the green arrow that goes from the controller to the model.
Remember that in our MVC talk that I did last time I
said that the controller has a green arrow to the model,
it can talk to it all at once, say anything it wants.
This is essentially that green arrow.
This is our model right here.
And this is the controller this is how the controller
talks to it through this thing we call the brain.
Thing you can call it anything you want and
of course this might be much more complicated green arrow,
it might be a network database that is connecting to you to
get the data.
Okay?
But in our case it's this very simple little brain.
Okay.
So now we don't need this either down here.
This is where we're appending onto the op stack and
printing it out.
So we don't need that.
But we do need an enter to push the operand onto
the stack.
Okay.
So here I'm just gonna say,
that I'm gonna say I'm just gonna
say brain.pushOperand(display) value.
'Kay?
That's the main thing I need to do, is just do that.
One thing though is, I also need to update my display.
Because when I push this operand,
that's gonna change the brain.
I need to call that evaluate, right?
And get the value.
So I could call evaluate here, but
actually, I'm gonna go back to my brain, and I'm gonna change
pushOperand to return the va, the result of evaluating.
Typing today.
From it, from its, from internally, so
I'm gonna return evaluate here.
So that every time you push an operand,
it'll just return the evaluation.
Now one could argue whether this is the best thing to do.
Because, you know, you might not be interested in
the result of evaluating that right now.
But it kind of feels to me kind of good.
And it's not gonna be,
there's not gonna be that many things on the stack.
You're not gonna usually have calculator brain
have 1,000 operations and operands, although you could.
But you're not usually going to so
it's probably not a performance issue.
To have it just return this and it'll make caller's code,
you know, look a little simpler.
And if they don't want this return value,
then they can just ignore it.
They don't have to use it but I am gonna use it.
So, when I push this operand right here,
I'm gonna say, I'm gonna if let the results equal that.
Okay, because it's an optional.
And if it's not nil then I'm gonna
set the display value to the result.
So in other words, every time I push an operand,
I'm gonna up my display value with the evaluation.
Make sense?
Okay, what if this comes back nil?
So, I push something on,
this is not gonna happen probably with Push Operand,
but it might, and after your homework it might.
So, what if I push and it comes back nil?
Well, now I'm kinda stuck, okay?
This is why, in your homework assignment, I suggested, wow
wouldn't it be cool if display value took an optional.
Right, if display value took and returned an optional.
You could put something sensible in the display when
you had something that couldn't be evaluated.
So in assignment two making display value into
an optional is gonna be required task.
So you might as well do it for homework one,
cuz you're gonna have to do it for homework two anyway.
Okay.
Just wanted to give you more time because I didn't
really teach you the things about NumberFormatter and
stuff in time for assignment one.
But it's going to be required and that's because the best I
can do here is maybe say display value equals zero.
That's really lame but that's the best I can do.
I really wanna say, display value was nil, okay.
I really just wanna set display value equal to
the result of this.
And I wanna have nil, you know, clear out my display or
in assignment two,
extra credit, maybe it puts an error message in my display.
Now that's extra credit, but
that would be an even better thing to put there.
Okay?
But same thing for, for forming the operation.
Here's our operation right here.
And I'm just gonna say,
if I can let the result equal brains perform operation of
the operation that I got off the button, then I'm going to
let my display value equal that result.
Otherwise I'm going to do the very lame thing of
saying display value equals, whoops, value equals zero.
Okay? Unders,
people understand why that's kind of lame?
All right.
Okay.
So that's it.
Look at how simple our controller is here.
It has almost no code in it, okay.
And that's really iOS is great about that.
It really is pretty good about making it so
that you can build your UI mostly graphically so
that there's very little code to control what's going on.
And then even our model,
which is a pretty powerful calculator right now,
we could add as many functions as we wanted to.
It's just one liners here.
And it would be capable of, you know, evaluating any se,
series of them that's evaluatable.
And it's also set up to do your homework, okay,
which is to add those variables,
to be able to push operands that are variables.
The other thing your homework is gonna ask you to do is to
eval, to draw this, okay,
the contents of it in a human readable form.
Using infix notation like this with parentheses when
necessary, things like that and
that's gonna be a lot easier here too.
Cuz you can recur,
use recursion, use recursion to build this as well.
Okay, so that's the main two things of
your homework that's what they are.
All right, so let's see if we broke anything here all right,
so we're gonna go up here and run.
See if this all still works.
Our UI has not changed.
You notice I never even opened the storyboard here.
Didn't even open the storyboard.
Okay all these changes were pushing things out of
the controller into the model.
Okay? The co,
communication between the controller and
the view has not changed here.
So hopefully this is gonna work let's try 85, and
our number entering is still working in
our controller that's good, Enter.
Okay it still says 85 that's good,
how about 41 plus seems to actually be working.
Square root,
that's also working, nine times, excellent.
That's working.
Now what if we do something that's not evaluatable?
I'm going to press times a whole bunch of times.
Right? Times, times.
Oh, times no, zero.
See that's not really great feedback.
Okay? But, it's not really zero but
it's, it's not good either.
So your homework is going to be printing out what's on
the stack in a nice form so
you'll be able to see that you have times, times,
times, and it's gonna equal a blank display.
And that's gonna make sense that it's blank.
'Kay?
All right.
Now, I wanna do one other thing here, though, just so
you can really visualize what's going on,
which is, I wanna print out,
when we evaluate, I wanna print out this stack.
I wanna print out the thing we're evaluating,
I wanna print out the result, and I even wanna print out
the remainder here so we can see what's going on.
So, I wanna say print ln.
And I'm gonna say I'm gonna use my backslash thing here.
Op stack equals result with how did I say this?
With [NOISE], oh, yeah.
With our remainder left over.
Okay.
So wouldn't it be cool if I could just do this.
Just say, okay, the op stack evaluated equals this
result with the remainder left over.
Okay?
Let's run that.
Do you think that's going to work?
Maybe. Let's see.
[BLANK_AUDIO]
Okay.
So let's try putting eight on the stack.
Okay?
Let's make so we can see this over here, where is it,
it's this probably right there, there it is.
We don't need that one okay, so
here is our okay it's gonna be that, it's this.
Okay, so it said here hm, enum value in, in an array, equals
result of optional 8, that's good, optional 8 is good.
With nothing left over.
Okay, that's good.
Let's go 6, Enter.
Oh, now we have enum enum on the stack equals optional 6,
with enum left over.
Well that's not so good.
Times enum, enum, enum equals it with, this is terrible.
This is, I can't understand what the heck is
going on here.
Why is this happening?
Okay, when you put something in parentheses like this,
it tries to convert it to a string.
Okay, well the thing that's in here is an array.
Arrays know how to convert themselves to strings.
What they do is, they put open square bracket.
Then they ask every single thing in the array,
convert yourself to a string 'kay, and it puts them here.
Well our op is converting itself to this string.
Enum value 'kay?
That's because the system doesn't really know how to
convert it any other way so
it's just saying that's an enum value.
It doesn't know how to convert itself to a string.
So, you see, see what's going on here?
So, I'm going to show you how to teach a type to
turn itself into a string.
Okay, cuz that's really valuable for debugging and
also might be valuable for your homework.
So, how we gonna do that?
All right, the way you do that is,
you have to add a computed property to your type.
And enums, just like structs and
classes, can have properties, okay?
Only computer properties in enums, structs and
classes can have properties that are values.
Like these, like this over here, all right.
But they can only be computed.
You remember a computer property looks like this, var.
The name of it.
It has to be called description because
it's gonna be a string description of it.
The type has to be string.
It's a string description of it.
And then of course you want your get here.
And, whoops, your get and your set set.
But it has to not only be a computer property.
This description thing to make this work.
It wants to be a read only one.
So we're not going to put the set,
so there will be no set, just a get.
So this get just has to return this op as a string, so
I say someone turned it into a string.
Well how would we turn our op into a string.
Well for the operations we're just gonna return the symbol.
Okay if this is a plus operation turning into
string is I'm just gonna return a plus,
cuz that pretty well describes a plus operation, a plus.
For the operand,
I'm gonna have to turn this double into a string.
And return that.
Okay so how am I gonna do that?
I'm gonna do that using switch,
I need to switch on myself.
Okay cuz I'm gonna do this switch so that I can get these
same things out here, and you do the same thing I did here,
see how I did this switch.
So I could get these associated values out.
I'm gonna do the same thing here.
So how do I switch on my self?
I say switch self.
'Kay?
And then I just have to say the case for operand.
And I'll let that be the operand.
And I have to do the case for unary operation.
Now when I do the case for
unary operation, I want the symbol.
But I don't care about the function.
Cuz I'm not actually gonna compute anything.
I'm just going to return the symbol.
And then for binary options same,
same thing I want the symbol but I don't want this.
So that's the, the don't care.
And what am I gonna do in each of these cases?
Well in the operands case I'm gonna return a string that
is that operand.
Oops, don't like the way it puts that extra thing
on there.
Okay.
And then in the unary operation case I'm
just gonna return the symbol.
And in the binary operation case I'm also just
gonna return the symbol.
And we have, oops, don't want the parentheses there.
Kay and we've covered every case of this switch.
So not only does it know that this switch is covered but
it knows that we for sure have returned something out of
here, because we only have one expression here which is
this Swift and switch and we know that covers every case.
So there goes so we have this nice description.
Now this is not quite enough 'kay?
You have to implement this property,
this computer property read-only.
But if you do one other thing,
which is up here, you have to put, colon printable.
Now, I told you enums and structs have no inheritance.
So you're like what, wait a second, there.
You're telling me op inherits from printable?
And the answer is no, does not inherit, okay, it's an enum.
Enums don't have any inheritance, only classes do.
What this colon printable means is, and
this can be true for classes or structs or whatever.
You can put after the colon here.
This is called a protocol.
And all this means is you're telling Swift that this
enum implements whatever is in this protocol.
And this protocol happens to just be one computer
property called Description that returns the string.
Okay?
Now we're going to talk about protocols in depth.
Because protocols are very important for
explaining how things work 'kay?
But we're not gonna cover it today, though.
Okay, so if you do those two things, put description in
printable, now when we run, you'll see, I'll go 5 enter.
Six, and you see it's put a five in there.
There's a 6.
Times, it's even putting the times.
If I hit times again, now I get nil and
i tshows me the whole thing is leftover, okay.
Let's go another thing here,
what if I go 6 Enter 5 Enter 4 Enter.
Now if I do times it says times of 4 and
5 is 20 with the 6 left over, exactly right.
Kay now notice I had to rerun there to do that,
you're gonna have a clear button right,
that you do in assignment one, you're gonna have to
make that work in assignment two as well.
Okay the last thing really out of time but I'm gonna show you
the last thing really quickly that I was gonna do is use
this description to fix this problem I said right here.
Which is what if I had a function called learn
op 'kay and it took an op as an argument here.
And it just said known ops ops description equals that op.
You see, now these could all just be learn op this.
Okay which is a lot nicer, I only have to type this thing
once, and I just use the description here.
The other thing about this, notice where this function is.
Inside the init.
Okay you are allowed to
put functions inside other functions.
If this is only called inside here, you can put it in here.
If if I put it outside in fact I'd have a little a problem,
because it would have to be private.
Because it uses op, and that's what this error right here is.
All right I'd have say private func, but I don't want to do
private func, instead I'm just gonna put this right down
here, okay and obviously I would do that one last.
Okay that's it, hope you learned a lot and
stuff elsewhere for that and I will see you on Wednesday,
I'm here if you have questions.
For more, please visit us at stanford.edu.
    You must  Log in  to get the function.
Tip: Click on the article or the word in the subtitle to get translation quickly!

Loading…

Stanford - Developing iOS 8 Apps with Swift - 3. Applying MVC

3112 Folder Collection
MARURU published on May 24, 2015
More Recommended Videos
  1. 1. Search word

    Select word on the caption to look it up in the dictionary!

  2. 2. Repeat single sentence

    Repeat the same sentence to enhance listening ability

  3. 3. Shortcut

    Shortcut!

  4. 4. Close caption

    Close the English caption

  5. 5. Embed

    Embed the video to your blog

  6. 6. Unfold

    Hide right panel

  1. Listening Quiz

    Listening Quiz!

  1. Click to open your notebook

  1. UrbanDictionary 俚語字典整合查詢。一般字典查詢不到你滿意的解譯,不妨使用「俚語字典」,或許會讓你有滿意的答案喔