well
hi will two-lap
I realize I'm the last person between you guys in the bar
I'm really impressed that you're still here time there's been some amazing
talks today I've seen a lot of them
so amazing talks going on right now so thanks a lot for coming I really
appreciate it
I and thanks to Ruby sensual and often you guys are in the room
I'm for giving me a chance to talk to rubicam like a once in a lifetime
opportunity I'm really excited
on it it's thrilling for me to be here thanks a lot
on my name is Pat China Sea and I'm to be talking about blocks
so that's why I talked for 45 minutes about Ruby blocks
and back together we're gonna be dissecting
a ruby block so don't worry there be no blood no gore
I know lab animals will be harmed in this experiment
I what what I'm gonna do is look at how Ruby implements blocks internally
and see what we can learn about blocks by doing that and I'll be talking about
I'm mats is Ruby implementation today not about JB rebellious
other versions a movie I'm before going into blocks a
let me just start by saying a little bit about myself probably have heard before
I work at a company called mckinsey which is a management consulting firm
but I'm not a consultant I just I'm just a Ruby developer every code
for them I'm in my spare time I read a blog
about Ruby development at Pats on a C-dot net I am really excited actually
just finished my first book I wrote a book
I've been working for the last say thank you
I just release a book this week on Monday called
Ruby under a microscope and it's all about I Ruby internal
suck taken six months of my my job and I went to
into my just at my house I wrote about how Ruby works
and the way I the way I like think it is I went on a long road trip
was kinda like visiting Japan or foreign country where you don't really know the
language
and you see all these amazing exotic sights and your
on you know but you begin to learn a little bit the local language get to
know people there you can appreciate their customs and their food in
that's what it was like for me so the book is for today travel journal about
I Ruby MRI internals also touch on Jay will be in the billions in the book
I'm so if you're into internal stop and i actually the presentation today this
is really a synopsis above the chapters from the book
I please check it out on so
the first question probably have for me is look at pat why Ruby internals
who cares about how Ruby works all i care about. is
that Ruby does what it's supposed to do you fight takes a value Pfizer something
into a hash I see evidence or a
I need to know is that I'm gonna get it back when I give it the same key
II I don't care how really works I'm busy I had a job to get stuff done
I have to you may have an open source project tonight I work on my spare time
on the weekends
it was time to look into Ruby internals and figure it out
you know I took sixth month of I did and I'm kinda crazy maybe
but I'm here the reasons why I did it may be wise to learn about Ruby
internals to
so I can pick up three reasons on the first one is I think it if you study
group internals
you can help you become a better Ruby developer I think you can learn
about the language more deeply than you may have up
you can look at more deeply than you did before I'm you can learn about how ruby
was intended to be used
how mats and the rest at the core team intended the language to be used not
just use it the way you happen to learn how to use it
I'm and I'm I think you can learn a lot just become a better developer for it
I'm
maybe a second reason could be there's a lot to learn from the core team
you know that which in the other teak people on Team are there really smart
people that SOB difficult problems
and maybe you can learn from their solutions their algorithm their code
and learn about me you know maybe pull some ideas from them that you can try in
your own projects
I'm so there's a lot of amazing solutions you know we can all learn from
on its a little inaccessible miss you take the time to learn it I mean I think
the last reason the most important one is just a lot of fun I had a black I had
so much fun learning about Ruby trials
and I hope you guys I'm guilty so that today if you if you like it
then check out the book has a lot of really amazing stuff going on there
fascinating to me to learn how language works internally
I never knew this I'm not a computer science major anything and so for me to
learn about how language worked
internally it was just it was just super fun so that the most important
have fun on so today I'm not talk about blocks
you know here's a black and it seems kinda hard to believe that there's
really that much interesting to say about blocks
you know what can we say that well we call them you call a block
you can pass an argument to block like this on
and you know most about special here rubicam you go are you guys can tell me
how this
you what this code will do in two seconds or less you can tell me what the
score is gonna do
you know what am I possibly gonna say what can we say about blocks that that
interesting
on the hold that thought will get to the blocks in a second the real reason
however I want to talk about blocks
is I'm when I think back to when I first came across Ruby
I imagine a lot of you here had the same experience you for star ruby for me was
in 2000 eight maybe and before that I was a PHP
I job at C plus plus developer I did a few other random things to
on yes if I wanted to write code that did this in C
I have to say you know in its I a semicolon
for Francies I equals 0 semicolon I less than 10
semicolon I plus plus Francies brace
lullaby with much more verbose way of doing the same thing
my first came across this is my might have been two thousand 8
I thought to myself wow this is something different I haven't seen
anything like this before
I'm you know it was it seemed really elegant and beautiful to me
and it got me to think twice about Ruby I thought to myself
ruby is something special and I think back about that
it it really was the blocks the way that you can use blocks and Ruby
that got me to fall in love with the language so you know aside from all the
technical stuff about to go into
for me the real reason I wanted to talk to you guys today about blocks was
it's what I like the most about Ruby our hands you know
think back to your own history where you discover the language what it was about
Ruby that made you fall in love
with enough to come to rubicam so for me it was blocks
so what am I gonna save up blocks while the first thing I want to do is define
what is a block enough we ask that question what is a black what can answer
to get
you know and so the way I want to do that is it mattered if I could slice
open a block and look inside
you know what's inside a block other moving parts in there my gonna see blood
gots chromosomes you amoebas
by the slice a peaceful block at look at under look added under a microscope
you what I see on in so the first half the presentation to talk about
on what blocks Armin answer that question
what is a block and we'll find out in a few minutes
on that blocks are ruby's implementation of closures
and define what a closure is on the way on at the second half miss which here to
talk about closures and met a programming
and how those two things are related so two different very different concepts
but I think they're actually related to each other
and so on we'll talk about that second
so let's get into it if you were to look inside the Ruby C source code
and you were to try to figure something out about what blocks are
the first thing that you would see is that there's a/c memory structure called
RB underscore block and I'm not showing the conference over here
the reason why is I want us to discover as we go along what's in this structure
on and but the nice thing about studying Ruby internals is
if you had a question like this you know what is a block or what is object what
is a module
you know you can actually directly answer that all you need to do is go
into the C code
find the definition up this or that or the other thing and that's your answer
you have to think about it very much you can just look at how it was implemented
and so that's not maybe another reason for studying Ruby internals as you can
answer all these sorts of questions that you might have about how language works
or how it was intended to be used
so before we go any farther away about my diagram saw you know today and also
my ebook
I have a lot of pictures it's like an illustrated book on
my pictures are not definitive exhaustive definitions up
exactly how it really works I'm not gonna show you every single thing
inside the block structure on and is the reason why is I want to point out to use
the details about Ruby internals I think are important for
for you Ruby developers to know on there's a lot of other very technical
things in London nitty-gritty details that may be on
on is interesting and so I'm gonna glass over ignore some of those details
and so my diagrams are oversimplified vers reality
that'll make them hopefully easier for you to understand as well
I made it easier for me to drive them to so
what we're going to do is I were you do a series of experiments
and the reason I called the book will be under a microscope is I wanted to use
for the scientific method
for discovering and learning things about Ruby you know it's one thing to
start talking about how it works and what does
it's nothing to test your hypothesis with an experiment
I'm so I'm not going to real experiments today I was going to do it you know if
you simplify experiments we have much time
but in the book I go into more detail about on one thing or another and
actually
run some code experiments are written in Ruby codes you can download them in one
them yourself if you're interested
so the first thing I do is really the most basic thing you can do with the
block is call a block so how do we call a block
so not rocket science. all you know how to call a block here's an example
on here's a block that takes us string value the quick brown fox
the rest of that of course is jumps over the lazy dog that didn't on slide
but we're gonna come back to that string over and over again and you're gonna get
very bored and tired of hearing me say that
on and we're gonna save it in a string variable call
II local very local STR and then we're gonna print that out and we'll do that
ten times
not very instinctive good but what it does is it allows me to answer the
question
what is a block and so the first the most obvious answer to that question is
well
it's right there on the screen everything between the do keyword and'.
and keyword
you know the first most obvious definition of a block is it's just a
code snippet
it's something that I'm units code that you type in it's sort of like a function
if we were to look inside Ruby you know through a microscope so to speak
this is what you would see so that RB block
see structure I'm sorry now on the right announced showing you one up
feels are one of the values inside that in there are many more but here's one up
on this call I S
EQ and I think and help me out here core team I think that stands for
instruction sequence and that's a point or two points to
and instruction sequence that some showing on the left side
I'm yeah and instruction sequences a series of bytecode a virtual machine
instructions
the first one is put streams that dynamic et cetera et cetera
don't worry don't try to read that don't try to understand it I'm not gonna
explaining that today
I have a lot more that in my book ob
but what I wanted to point out is this is really want to block it
its a snippet of code internally this is what it looks like
on just taking a step back for a moment I will stay just one
you know me one minute about how on the virtual machine works and how these by
code instructions work
at a ten thousand foot level when you look at ruby from you know from a
distance
the wave Ruby works at least starting with 319 is
you give it some your code really parses that and compiled your roomie code into
these instructions
and then executes them with the virtual machine and that's what I quit she was
talking about earlier today
so on 30 wait this is our first answer to the question what is a block
its a on it's a snippet of code or a function
on now is to another spent the summer when I i'm look at how you can reference
variables from the parents cope
that sounds kinda complicated but it's really actually obvious ok you to look
at a block like this
so now I'm doing the same thing and bring the same three and ten times
I'm just doing in a more complicated silly fashion
I and so what I've done years I've taken the first happened strain
the quick brown fox and say that in the same STR variable
but I'm I'm doing and outer go oMG I call the block 10 times in the block I
think FTR to
so I have a second variable I and that when I'm saving the second half for the
string
jumps over the lazy dog and I have to put a statement that says put ass
you know string and string to so pretty simple code you can own standards
on and in fact you know what's the which thing about this is all kinda obvious
are you guys write did disorder called probably every day this is probably a
reflex
prices take this to mean that even realizing it on
you know why my points out to you well for me to something
actually kinda profound interesting going on here has to do with the
question again what is a block
so it the way I look at it is blocks happened is dual personality
a kind of schizophrenic you know they have on the one hand there a separate
function
I'm calling on the other hand their part up the surrounding
function and so that put a statement can access equally well I can access
STR you can access STR to
it doesn't it doesn't matter that's kinda obvious we all take that for
granted
but it's not you know don't take it for granted a lot goes on inside a privy to
make that work
so let's take a look inside a booby see how to implemented
on thought what am i jus a misstep through this slowly and I go through
this in great detail explain how this is implemented
so the first thing we do is we take that string the box during
we save it in a variable STR what is really do when you save
a value in a variable so we would look inside Ruby
I'm again you can tell these are super oversimplified diagrams
what I'm trying to get across here are the essential ideas
so mom first ball on the left we have a stack this is something called
not be virtual machines internal stack so the way the virtual machine works
on if you heard that the presentation earlier you know this it's a stack-based
machine as it runs those instructions that we saw
earlier I'm that local get local whatever is it runs as internal
instructions those instructions to pick lee used
are they take values of this internal stack they do some kind of operation
and they pushed the result back on the stack on so this internal stack is
actually not something that you ever see as a Ruby developer really need to know
much about
on but yeah I just remember that the the virtual machine inside Ruby
is a stack-based machine and so when we save a value in a local variable like
STR example that value get saved
on that stack internally okay on the right is actually a different stack
so on the right to something called our beacon full frame structure and I'm
showing one member from that structure
and which he asked earlier you know how many members are in this I think there
are 11
so there's a lot more going on you're not showing you but I what I want to
point out is that there's one pointer
the DFP which I think stands for dynamic frame pointer
that indicates that you will be used to keep track of where the variables are
for the current on for the current scope leading to explain here is that
as your Ruby program runs you call from one method to another to a block to
lambda
you have this Ruby call stack you build up and if you ever run the command put a
scholar
that will print out that whole call stack and so each level on that call
stack is represented by this
RB control frame structure on and so what you have to imagine here then it
will have time to explain all this today
that there's a stack or an array of these control frames
that represent your Ruby call stack so if you think about it inside ever be
there to stacks there's a
Ruby stack on the right and is the internal virtual machine stack
on the left those two things are related and connected
anyway let's get back to block so how does this work so
now we've said the value in st. are and now we're going to call the block
so what happens well actually we're not calling the block army what are we doing
here
what we're doing here is we're taking a number 10
and we're concerned that mean object that the receiver other message
the 10 is an instance up the fixed number integer class
and we're sending a message to it which is the times method
so what we're doing is we're calling the times method on that class objects known
and that has nothing to do with the block back or not on the block at all
what we're doing is we're
we're taking that block more pass it into the method as an argument
so it's on there's more going on in my think so let's look at
what happens inside a ruby at the moment when you pass a block into a method
called an argument
okay we're not going up come on the block at were simply referring to that
block for the first time
so when you do that when you when you first refer to our use a block
Ruby says oh I have a new block I need to create a new RB block structure
and so what it does and again I'm I'm showing and ok over simplified version
up the same structure but it creates a second value in their
any copies that the DFP a copy that from the control frame
to the block okay to remember that the FBI was a pointer over to
the internal stack where the local variables for that method were stored
so what's going on years interesting is that ruby is saving information inside
the block
about where you first referred to that block from
where you I've decided to pass it into a method
so blocks are not as simple as they seem not just the code snippet to have this
other value inside of them
which is a a pointer to the environment where you
reference them from interesting on what we want that type from NC where would
where we go
okay so now we're calling not attend dot times methods were calling into the
times method inside the pics numb class
and so we have you call a method in Ruby it creates another stack frame on that
internal static which is a bunch of values
on the air in the lot details are not showing I just want to get across the
fact that
as you call deeper and deeper into your code it creates more more the stack
frames
on now 269 primes class is implemented in C++
not something you write your cell on but it works the same way that you probably
would write it
loops over you know the number 0- 12 up to n -1
so in this case will go up to nine and finally now it's time to call it a lot
so that will
echoed inside the pics numb class will yield to the block
yield is just a fancy word to use for calling on the blocks from Shin
on and in Los a passenger argument if you want to
if you want to okay so now I'm in the block I'm gonna create the STR to
variable
where I save jumps over the lazy dog and I and then open up the two strings we'll
see how that works
okay so now I'm getting a little complicated in my
internal stack my yard internal stack now I have 3 stack frames impact is more
than £3m
glassing that over to the fort stack frame in there but
just to keep things simple today on the bottom we have
the parents cope where the STI variable was
in the middle we have another scope for the times method
and then on the top we have the top of the stack is now being used
as we run the code inside the block and so that's where the STR to variable goes
and so they put us call when it says put s STR STR to
the code input at is able to access both STR to
in the car in scope and then using that the FB point2 go down to the parents go
farther down on the stack and finance STR variable
and the reason you can't do that is that when yield to a block in Ruby when you
call a block
Ruby take that DFT pointer out of the block and put it onto
back so that you all the code inside your block is able to access
the environment where you originally again when you first referred to tap
Locke
so ruby is not wasted emerging those two things together the
original surrounding environment and the current scope up the block itself
so that side now back to that dual personality that's the way blocks were
able to behave in this way
how they're smart enough to do both things
on just taking a step back and reviewing we found out so far discovered two
to feels our values inside the block structure we have
the iseq pointer this is the instruction sequence
that points over to the again a series a bytecode instructions that the virtual
machine is going to run
so this is the compiled version might function and it has that dynamic frame
points or DFP
that points down to the stack and again not to wear the stack is
you know at the moment we run the code but it to the referencing environment
where I first referred to that stack
that that block that turns out in computer science is a fancy
name for this combination of two ideas a function
and the environment where you refer to that function from I and that was
invented a long time ago back in 1975 Annabeth
opyat applied the back in 1975 I
an MIT professor named Gerald susman and his colleague I steal wrote a paper
called
scheme in extended I interpreter for extended lambda calculus
sounds like complicated in spree it's a pretty hard-core academic paper
exactly online you can download it read it yourself ID Act did the other day was
really fun
on I love the stuff I'm kinda language geek
on and this paper defines in and
and explain their implementation of a language called scheme
scheme is a dialect less and what's interesting about scheme scheme is still
being used today
I is that it was the first time that in computer science there was a formal
definition of the word closure
so they define if I did on this academic paper what a closure is and here's how
to find it
so we just read through this for second year to solve this problem night don't
know upon their solving
on we introduce the notion of a closure up which is a data structure containing
a lambda expression
whatever that is and environment to be used when that lambda expression is
applied to its arguments
so can a hot you know fun you know convoluted language here a lambda
expression at a fancy way of saying a function or method
and job applying that land expressions with
arguments just means the call the function in passing yards
but if you think about this for a minute this is actually what we have in Ruby
with the block we have a function and environment to be used
when we call a function you backing up this is what a block is
it's the function on the top left and the environment on the lower left
and so I and so what we've done here is we've shown that blocks in Ruby
are are ruby's implementation of closures ruby is taken
and i've not do this on purpose or you know indirectly but ruby is taken
I'm a concept from the nineteen seventies and applied to
language that was invented in nineteen nineties and i were so using today
I find a common staying on what we want to talk about Lambert slams a related
two blocks and let's see if we could do experiment figure out
you know what land as our on before we get to the lambda
themselves you know where the woodland come from you know why in the world is
Ruby have a key word that is the Greek letter
lamb is a a letter in the Greek alphabet what does have to do with computer
science
I'm so it turns out the same thing that Ruby borrowed the idea
lambda are the word Banda from less this is the first computer that ever ran
on the list languages from the early nineteen sixties
with was invented by John McCarthy in the late nineteen fifties actually so
this is
what is that almost job fifty years ago now
and a in the list John McCarthy introduce the idea the lambda
which is the way in so here's a list how you would create an anonymous function
I'm not a list developer and many do your might be I'm what I think this is
doing is
its defining a function waterfront see the list
but when I think it's doing is too funny a function that takes argument
and then divide that argument by two and returns that value
so it sa but it's not doing that immediately its returning a function as
a value
and so what list introduced in other functional programming languages do this
to
they allow you to treat coder functions as data values
I and so they you know quote-unquote they treat code as a first-class citizen
sewing room you can do the same thing Ruby Baroda land the key word from this
and I'm curious you know here's my thing silly example
on now I'm doing in in an even more complicated and confusing manner
so what I want to do is demonstrate how you use them to in Ruby
we're gonna do the same thing when a print out the same string I'm not ten
times as one time today
well for this experiment so how does this work
so I'll let you guys might know exactly how lambs work on but OK from you
donor have and use one in a while we go through it the way this works
is on the bottom I call a method display message
cause into the method in the method we save the quick brown fox the first half
at the string in a variable
STR same thing we did earlier and then we have a block that takes
on the first after the string and print that out concatenated with the second
half a string
except the difference here as I don't call the block immediately instead I say
lambda
and what lambda does the returns that block has a value it converts it into a
tape a data value of some kind
and that becomes since that's the last thing in the display message
method that becomes the return value for that matter
and then finally we say dot call at the very bottom so it's not until the bottom
here right they don't call that it prints out
people straight you can try this on your own computers
so I'm let's go through this and see how it is implemented inside Ruby
know what goes on when you can when you use land so will go through one minute
I'm slowly at first thing is
I take the clock string I put it in the STR burials same story here
on you know not no surprise we save the string
on the stack and there's a control freak structure on
and the bottom empty one is the outside scope and then we have one
for the message but that in that method ever calling
should be display message on okay what do we do next
now we call them to so what happens inside Ruby when you call the land the
keyword
that's going to be a complicated diagram don't panic I'm gonna go through this
slowly let's see if we can figure this out together
on and meet a couple minutes just explain this picture
so before I get all the boxes and arrows on the right let me talk about the two
words on the left stack and heap
so what i'm indicating there is this really two different types the memory in
your Ruby process
are really in any process that matter their stack memory
that's what we've been talking about so far were you push values onto a stacking
pop them off
stack is used for values are very temporary in nature
so they're only ballot or they only needed for a short period time usually
during the context that one method
or function on the on the bottom under the dotted line we have to keep
and a lot you may know the keepers for whereas for when you wanna savings for a
long period time
know when you on one some value to persist around there are you know the
liar around for a while so you can use it later
I N the biggest or most obvious example abusing the heap in a review program is
when you create an object
it gets saved in heat will be out it's a memory at heap and use it for that
object
so what's going on here when I call them that what is it do you well the first
thing it does let's start from the top left take that internal stack
where we have that FDR variable any copy that
from the stack copy that stack frame down into the heat
so creates a persistent sorta on
a new second copy all the same information what's special about that is
it
now in the heat so I can persist for a longer period of time
on and the other thing too because it creates on the bottom and i know i don't
know everyone can see this summer you're pretty far back
is a structure called RB underscore yen VY
in this is a I with call the environment object I i assume
and this is a sorta the structure that will be used to manage that keep copy of
the stack
on so interesting what else is going on here the other thing that really does on
the right is it takes the control frame structure
and a cop is it into something called RB underscore Prock
structure and as you might know some you the return value avail and a
key up the land the key word is actually a prop object
and so this is Rubys internal representation of approx
and you can see it put in there the DFP pointer the iseq pointer
and a couple other things on and one instinct detailed notice here that
inside the prop structure is a block structure
and so in fact what we what we're seeing here by looking at the way the
these things are implemented that proximal and as and blocks are all
really the same thing
they're all closures they're all the combination of the iseq pointer
the colder the function and the DFP pointer which is the
referencing environment through all really different ways looking at the
same thing
and so when you call them that creates that new object copies a stack frame for
that environment into the heat
and then it Tom and then it returns at proctor you as a as a return value
okay so finally ready to print out the string and rate is a display message dot
calling its gonna perhaps during a work just fine
but what I want to point out here's something interesting which is on
if you look at this carefully think about it how is it possible that my call
dot call at the bottom it prints out the whole string
if you look at that first variable STR that the local variable inside a method
normally when a method returns
all the variables that you create in a method are you know they're free to
release they're gone forever
but obviously here that STR variable lives on
that serve a second lease on life able to do more you know more good for you
good morning your program how does that work well that's really
back up to this picture that's the whole reason why
ruby is doing all this work all this copying all these new structured players
all this is just so that you can continue to refer to the environment
where you call Amanda from so at the moment I call and that that environment
not only what's inside the land a
but the surrounding values are all saved away that later when I
they got call it works fine and
looking at how that's implement inside Ruby on its or other similar pictures
except the opposite so what we do now is Ruby take the DFP pointer from the block
that inside that prop and copies it up into a new stack frame
that it sets up to run the code inside the block and remember in the block
we're creating STR to left the dog park the string
so that is pushed onto the stack now on the top left
and its save that the FP pointer there which points now it points out to the
heap
where the referencing environment that in you know copia reference
that environment say so it's just like on a normal block
except that detail the DFP now pointing out to the heat
so that's all and its work on so it's mine it's not about blocks
and I we've seen how blocks and lamb is approx are all the same thing in there
all
on and they're all closures I'm not just here to talk about closures and mentor
programming the two different period
very different ideas how are they related and you know what is
met for me have to do closures the first of all I'm so as to experiment using a
closer to the
find a method so what the world does that mean on
let's take another example let's say I creat now I'm gonna wrap my exciting
I'm box dog wrap it up in a class democratic last fall quote
and I'm you on how to create methods what you do is use a class
name a class quote and use a deft this staff that def the other thing you start
typing method definitions
and use the Deaf keyword yet all very obvious
so how do you do met a programming what is better programming
well one way of doing that a programming and ruby is to dynamically create
methods
and all that means is instead of saying def teef I can say
define method display message so the only difference between this what you
normally do
and this the defined netted met method
is that you pass the name of the Met up the new method as a parameter to it
so the name is my new Massa on my new method is display message
shit I have a different sample that was on tongue twister
so Here I am too funny a method and more confusing calm blue demanded that
doesn't make as much sense that's what made a firming really is all about isn't
self on but you know in a real example what you do is you probably have a loop
here you might create 10 or 20 methods of the same time you're going through
that you know each name
each method names may be an array or maybe the name on the map it is from
user input or from a database query to the IP certainly
valid reasons for doing something like this but what I want to point out here
something different
I think there's actually some there's another minor detail are you may not
have noticed that
different between yes and
which is that when you say defined method you pass on that the name
then you have to say do at so that that
the methods body is actually a block you're passing a block
into this the Find method method
and that's not what we did over here we do said def the name and wheat are
typing in the code
and remember blocks are closures so because the block is the closer it means
that the code inside of the block
can access things in its surrounding environment
now in this example there really is nothing interesting around that is no
there's no reason to do this well maginnis in Europe your Ruby application
there was an interesting environment there was a place in your code where
you had a lot of instinct values you wanted your new method to be aware of
that access to so I'll make up a contrived example let's say
I only remember to put the the Fox the first half a string
in in the instance variable at STR
but then I discovered later I have the dog the the second happens during
STR to somewhere else in my code you know how can I
how can I allow my exciting method to bring out the same thing both
strings together well sense that the closure is able to access
the on instance variable it's going to become a method up this
quo class it's able to access equally well at STR
on the top an STR to which is on
in the surrounding scope there one confusing detail here
here as I have to say quote dots and define method
that's because the defined method on method is a is private to the module
class:
but other than that it's actually not that complicated so this is how you can
define a method
using a closure okay let's take another example
on let's look at sort of the classic example have met a programming
amid a programming really means to write code that writes code
and in Ruby on the simplest way to do that is to say
eyes to use the email function if I create a string like
put ass two plus two %ah again this is silly but you can imagine
I really example we are dynamically writing code that based on some kind of
data
you're getting from somewhere on you can pass that stricken to eat out what it
will do is it will
recursively call that virtual machine again and on compile that code into
those bytecode instructions and then run
I and so in this case is a printout for not really interesting
one one detail about you know that maybe didn't know is that its also a closer
so the code inside this string can access the environment around the call
to me Val
so what does that mean and how does that work well another way of doing this is
to use the binding
keyword this allows you to formally specified that environment
that you want the Val to work with on so
so madge in for minute I went back to my core class and I said
def get bindings like create a method called get binding
and the reason I want to do that you'll see in a minute reason I wanna do that
is to be able to access
the scope or the environment inside of this class
on so well so I can access that at st. are variable
so hold that thought let's move on and look at I'm
creating a new instance of the quote class of the object equals quote got you
not have a new object on what I want to do is something so let me take a moment
to explain
just for for 10 seconds or less how Ruby implements objects and I have a lot more
about this my book
on there's a on a lot more detail chapter on objects
but in a nutshell we have you created object Ruby creates
a structure called are object at least for custom object that you write
now for strings and arrays something else on book one of the other details I
didn't show now control frame structure is that
there's another thing called a self pointer that points to
the current value itself object in which you're running
at the moment solve your problem me with self but if not
just imagine as you go through your Ruby call stack you call one method called
another call another
each one of those methods belongs to some object some instanceof some class
and so the way will be implements that is in this control frame structure is
one of these for each level in your Ruby call stack
there's a self pointer that points to I'm which
instance which object instance is currently the cell
current value cell on our object
on structure itself has some other things in it but the most important to
values are
there's a class with a que that's the class pointer that will point out to
indicate which class this object is instanceof
and then there's another thing called I DPTR the instance variable pointer and
its points to an array of
the instance variables for this object I'm so in this case for my hat at st.
are in that and that iraq
okay to back for example now we know something about how objects work
internally
and have created an object or BJ Eagles quote that new
and I called me Val and what I want to have happen in this
a course that will work you can try this if you really want to what I want to do
here is
allow the compiler when it compiles that strain
to compile in the context I love the old BJ object
and so the way you can do that in with the email method is you can pass and
a second parameter which is that binding and remember we got that
sourcing 0 BJ dot get binding the backing up to my
class at the bottom we have that that method that we saw earlier get binding
that is called the special on mysterious keyword
binding and what is that doing what happens at the moment I call binding
and what is a binding anyway I'm so well we can see what it's intended to do its
gonna tell you now
when you compile that code do it in the context
up this binding not binding can be anywhere your application
and so how does that work what happens inside Ruby when I say
binding well let's take a look
on so this is the serve a similar picture what we had earlier we have on
the top we have
stack on the bottom have to keep on the top we have the control frame structure
and now my point out there's the South Point to their along with the DFP
on and all the same things will happen with the stack your copy to stack
out into the heap and it'll set the DFP pointer to the heat poppy
I'm not showing that in this pictures to keep things simple
but when you call binding Ruby will also call I'll also create a new
structure called RB underscore binding
on the lower right and in that structural save the file name the line
number where you call the binding
keyword case I wanna you know debug something you can
if you print out the binding I'll tell you on but it also creates this thing
called me and B which points to
the same environment structure we saw earlier on with the land the keyword
except this time on what I actually showing in five environment a block
structure
it turns out there's another block structure in the environment and
I'm also showing an additional value here inside the block call itself
that when you call binding a copy is not only the DFP
from that control frame into the new block a copy is also that sell pointer
and at some point to a point over to the are object
to cart value cell and that's how when I
you know compile that code using the valley it's able to access
all the way down lower left the at st. are valuable
so what we've seen here is bindings landers proxim blocks are all really the
same thing
they're all closures in all different ways of looking at the same thing
on and i find you know I think this is of passing
okay so and then just reviewing you know going back to our my original question
what is a block
now we've seen there's on three things in this block structure
RB block structure we have first I i think you'd instruction sequence
appoints the function we have to DFP did that dynamic frame pointer that points
to the
referencing environment and now we have this third thing which is the fell
pointer that points
are object I'm structure which is the current value
cell so this is really the best definition I love
you know what is a block and it's also the way out the best
at the way that ruby has implemented closures
so on Ruby the cloacal I closure ruby is a function combined with its
referencing environment and I guess what you call the object environment
so the condo objects contact are the context
about in which work on that block
so that's it for today at you guys go with you today
if you like this stuff endurance to Ruby internals wanna learn more
you buy my book Ruby under microscope on and then you find it online on my
website
thanks a lot
well
0
Tuesday, October 04, 2016
Ruby Conf 2011 The Well-Grounded Nuby by David A. Black
yeah
- the well-grounded newbie advice for Ruby newcomers and their mentors
I know that not all of you are Ruby newcomers in fact I see some reasonably
seasoned Ruby programmers in the room but as you'll see this is advice partly
for newbies and partly for people who might have occasion and turn to advise
or mentor newcomers to Ruby just a couple of words about me
i started using ruby in two thousand which was when the pickaxe book came out
the book programming Ruby by dave thomas and Andy hunt
I sort of stumbled on the book literally well you know manually anyway at a
bookstore right after it came out and I've been hooked on Ruby ever since i'm
one of the directors and founders of Ruby central and we are the parent
organization of this event as well as railsconf and other projects
what are we going to do today well we're going to learn some what i consider
major common points of confusion essentially what I've done here is to
choose and this is a purely subjective choice but i have chosen points that I
think because I've seen it happen over and over again I think are particularly
either difficult or more tricky or in some way kind of the hard too hard to
grasp for particularly for newcomers
we're going to look at some of these points and hopefully this will improve
both your ability to understand code
and to write code because you'll see exactly what's going on in some of these
cases
we're going to look at seven points again this is purely subjective choice
seven points that I think are common stumbling blocks and i should add it's
not just for absolute newcomers to Ruby this is my choice of of the seven points
is based on years of training
rubyists including people who are not necessarily complete beginners but these
are things that I've seen people kind of have trouble with again and again and
we'll look at how these particular seven points can help you understand Ruby
questions throughout if you have questions just go ahead and and raise
your hand and we may have some time at the end to but if you you know as we go
along if you have questions that's fine i'll try to accommodate them
alright so we're going on this this little trek through seven points
custom chosen by me to help you get a handle on some of the tricky things in
Ruby
ok every expression evaluates to an object
you'll sometimes hear people say of Ruby
everything is an object everything is not an object for example an if
statement is not an object an argument list is not itself an object it's a
syntactic construct keywords are not objects
so there are things in Ruby sort of peppered throughout the code that are
not themselves objects you can point to something and say that that isn't an
object it's a keyword or whatever but everything does evaluate to an object
including things like if statements method definitions class definitions are
so everything evaluates or reduces to an object and we're pretty used to this
with you know what if you just type in like the number ten it evaluates to the
number 10
but here's a couple of the loved ones that you might come across and not not
know exactly what to expect
for example an ifs to have failed if statement always returns nil
so if you say if something
that's not true and there's no branch of the if that returns true or that that
that evaluates to true
the entire if statement those three lines evaluate to nil
so everything reduces to an object and if statement reduces to an object in
this case it reduces to the object mill and it does it never reaches that middle
line that with that string not reach so this is a failed if statement on the put
s or puts method also evaluates to nil and sometimes again especially if you're
not used to IRB which has this read eval print loop going
I RB is very literal if I say put s hello
it will obediently print the word hello
but the entire operation the actual call to the method put s returns nil and put
us always returns nil it that's it
it does not return the string that it prints it prints the string as a kind of
side effect and it returns no that's why you get in
IRB you get the the string printed out but then you get nil as the return value
the evaluation of of the entire statement empty class definitions now
you get this is a little bit arcane there's not too many use cases where you
care what a class definition evaluates to you care about defining a class
you don't necessarily care what the class definition ends up producing too
but it's there
there are a couple of use cases and it's I think just instructive to know that a
class definition does have a value an empty class definition evaluates to nil
so if i say classy
and that's an empty class definition it's nil
if you happen to have an object other than ill in your as the last value in
your class definition the entire definition will evaluate to that object
so the value of those three lines at the bottom classy some value in class
definition and the value of that statement is the string some value in a
class definition
so again everything reduces to an object and went when in doubt if you sort of
wondering why something is nil or why something is until for that matter
think about the the literal kind of looking at what the statement or
expression reduces to all right . number two
it's all about sending messages to objects
this is not an obscure . this is kind of the the lifeblood of Ruby but it's worth
noting that and i think this is one of the kind of really interesting and cool
characteristics of Ruby that it's all about sending messages to objects even
when it doesn't look like it is so for example you have
well you have on messages that come after dots
those are kind of the you know the sort of bread and butter ABC . up case that's
sort of the the the most kind of canonical way to send a message to an
object you put a dot after it and then you put a message in this case the
message up case however in fix and you know
unary operators are usually also sending messages on and I'll show some examples
2 square brackets are a message case statements also end up sending messages
to object so let's look at a couple of these for example 3 plus 2 in Ruby that
in fix plus sign is actually a method call
it's actually three it essentially it's three . + with the with the
the argument - so you're sending the message plus sign to the object three
with the argument to Ruby very nicely allows you to write it as an infix
operator
but you're literally calling a method whose name is a plus sign the same thing
for most of the other arithmetic operators including star and division
and so forth square brackets or another one if you look at a sub - I use the
word sub four square brackets i think it's very old school and not sure but
that what i mean by sub is a square brackets to the object a in this case
has a method
whose name is a pair of square brackets and I'm calling that method with the
argument -
so again i'm sending a message to an object even though Ruby because of its
just what it allows my way of syntactic sugar
so to speak Ruby of has it it looks like syntax but it's actually calling a
method in this case the square bracket method
interestingly even the unary plus the plus sign in front of an object can
actually be defined through this method called + @ sign now this is a kind of
bogus example because you can't actually call it with a . so this is more just to
give you kind of an x-ray of the fact that the behavior of an object in the
face of a unary plug a proceeding plus sign will actually be determined by that
method for example let's see if I can we get this is an IRB session in a
slightly malformed terminal well if I think you'll be able to see this
if I say something like calm class person when I feel like the indentation
is weird here let's let's try this again
ok class person
atra reader name this is just a very simple will say initialize name equals
name and now i'm going to define plus at whoops
+ @ sign and i'm just going to define it as name . up case and you'll see this
just allows us to kind of follow the the the dye through the bloodstream so to
speak
so now i'm going to go David equals person . knew this is just going to run
off the screen
home is that how clever of me just invented the mouse ok David equals
person . new
and we'll give me a name
now this is you know this is just sort of whimsical example but if I now say
plus david i get my name in uppercase right in others I i have defined the
logic for the unary plus sign and it it behind the scenes involves sending a
message calling a method and coming up with the result of that
alright so operators are mostly methods and that this is actually just an
example of of the regular plus sign in this case I hope it's not too small but
I mean you can you know sort of experiment with this - on your own
this is another person class it has an inner class called couple
the idea here is that when you have a couple of people which you achieved
through a plus sign
you get if you look at where it says def to s basically the string representation
of a couple is the two names joined by the word and so if i say John equals
person knew
Marcia equals person new give them the appropriate names a nice a couple equals
John plus Marcia what happens is the the plus method gets called and it returns a
new couple and then if i print the couple it it falls back on the 2's
method for couples and it Prince John and Marcia
so basically you can again this is sort of whimsical example as most of them are
as you'll see but you can you can basically do what you want with the the
plus logic but again it's always calling a method and and by the same token you
can sort of look into it by defining that meant yes
right
that's just the name of the Met that's the the name of the sort of the hook
you have to define so yeah yeah i mean if you define just plus then you get the
the in fix operator syntax if you define the plus at it gives you the unary plus
behavior
ok
another i think really prime example of a case where where Ruby looks like it
isn't sending messages to objects but it actually is is the case statement now if
you look on the column on the left and just ignore the rest of the moment I
have case some string which is whatever when ABC which means if this if the
string is the string ABC do so you know such and such to other that when regular
expression d e f if the string matches the EF do something else and case
statements in Ruby are governed or engineered by this method whose name is
three equal signs now or the the threequel operator if you will
um what actually happens under the hood
when I say when ABC I have a when Klaus
what's actually happening in terms of of what Ruby is doing is it's saying if a b
c 3 equal signs some string right if I say case some string when ABC
I'm really saying if ABC three cool
some string and that in turn is really just syntactic sugar for this
there is a method called three equal signs and it like the plus sign if you
use it as an infix operator
you're actually calling a
method now this middle one where use it as an infix operator that sort of a you
know kind of hypothetical you know you don't actually necessarily see that I
mean when you do the case statement this is all you know wrapped in layers of
syntactic sugar on top of sugar but what's really going on is that I'm
calling the threequel Matt the three equals I method on the string ABC with
the argument of my my case expression some string
now what this means again is that you can also roll your own
in other words if you want to define your own case behavior
how am I objects going to fare in the pace of a case statement
well here what I've done is again that the good old class person i I've now got
name and social security number
so with SSN and up there in red I've defined my frequent method and what it
basically says is the threequel method returns true if my social security
number is the same as the social security number of the argument to the
threequel method
so what happens then i create David with a number joe with a number and mystery
person with as it happens david's number
so now we're going to see which which person is the mystery person well when
Joe but as it's joe when David because it's david and again this is based on
Joe three cool mystery and David three cool history and of course it turns out
to be
David so you can actually govern the behavior of your objects in case
statements by hooking into this three cool math that you never actually other
than defining it you never work a statement at least you never actually
have to type it it happens just happens automatically
but that's kind of the underpinning of some of the the case behavior
alright so we see messages are being sent to objects even wear it doesn't
necessarily look like they are as in case statements and infects operators
it is also true and this is our third .
that objects resolve messages into methods now I am splitting hairs here i
am i am kind of putting in a wedge between the message and the method in
normal conversation right we talked about we send messages to objects or we
say you know I i called the up case method on this object or i sent the
message up case to this are probably more often say I called the up case
method on this object method and message
are you know that there's a little bit of fluidity just in kind of how we use
the most of the time but I'm again i'm driving a wedge through that I want to
be be clear about the difference between sending the message and calling the
method
my take on this and I've actually gotten in trouble on a mailing list for saying
it this way but I thought about it and I've decided I'm sticking to it on that
objects do not have methods now it is sort of a half-truth I mean you can say
yes the string has an up case method but what i mean by this wednesday objects do
not have methods
what I mean is that the method itself does not live in the string object
the method itself let every method lives in a class or a module there are no
exceptions to that every methods are defined in classes or modules
they're not defined even a method that you define on an individual basis just
for one object that method and you can do that in Ruby defining singleton
methods that method still lives in a class
it lives in what we call the singleton class of the object
so every method even if it's just a method on one object every method lives
in a class or module so object that's what I mean when I say objects do not
have methods objects have intelligence you send a message
- an object the object has the intelligence to to search through app at
a predetermined path of classes and modules to find a a method that
corresponds to the meth best sausage
so I sent the message up case to a string the string has a search path
where it looks for a method
whose name is up case and when it finds it executes if it doesn't find it you
get a method method missing ever
this is a diagram actually from my book the well-grounded rubyists and what's
going on here is if you look at the bottom we create a new object and send a
message X now this just gives you a sense of of where an object looks for
methods we in this case we're looking for a method called X going to actually
not find it according to this because it's not actually defined the first
place it looks is actually in what I referred to as the singleton class of
the object which is really just a storehouse for methods that belong only
to this object and in fact singleton classes are only created sort of on
demand objects just for efficiency reasons objects don't even have a single
to method unless you are sorry singleton class unless you define a singleton
method or or open the class explicitly as I've done here
now the singleton class this this notation class
arrow arrow object that actually opens up the singleton class of of the object
and what i've done here is i've included a module called and what that means is
in its as the object searches for this X method after it looks in it singleton
class it will look in any modules that are included in that class so it goes
off and makes us what I think of its kind of side trip to the module and
does not find a method called X comes back to the main track and goes up and
now it's at the class d which is the class of this object so it's now looking
in its in its original class and saying you know is there an X method
well no there isn't ok how about any modules that are included in this class
well there's a module called am that's included in this class so let's go
looking at them
is there an X method No so back we go and up to the superclass of d
notice the d inherits from sea we look and see
we find that there's no x.x method and it actually would go beyond that
once you hit sort of the top of your class tree it would then go up to the
object class on the the kernel module which is included an object and then
finally up to the basic object class which is really the top of the tree and
if it doesn't find it the carrots
it's it's failed and you get a method missing error
this is just a little bit of sort of showing the the lookup in action again
that the person class with the name accessory i create a person object named
david i'm now going to create a module called vocal which simply has a method
called talk and it's it's a little bit tightly coupled with the person class
admittedly it it depends on the name method but will will let me
will will give me a free ride on that one house that so we have a method
called talk which basically just says your name
now I class person i include the vocal module that means if I say put s David .
talk
David the object David this person object now has access to a talk method
and notice one important thing here is that when i created David David did at
that time did not have a talk method because there's no talk method in the
person class but even after i've created the person object I can include a module
in the person class
and even the pre existing objects will be able to find the methods that are in
that module
it's all about what the object nose at the moment that you send a message so i
sent the message talk and at that moment all it cares about is is there such a
method in my classes are such a method and a module included in my class I
guess there is because it includes vocal
so that's a good a good illustration of the fact that are all objects care about
is what is the state of the things at the time that you send them the message
all right now I have a second module called loud and what this does is it
actually called super which suit what super does is super walks up this path
of of method searching and finds a previous definition and execute that so
it's going to walk up the up the class and module path looking for a method
called talk and it's going to find it well I'm sorry i should mention i can do
class person include loud
so now when I say put s David talk it says hi my name is David but in capital
letters with ! because now it's loud now one thing here this is a little bit of a
contrived example well most of them are in this in this talk but one thing that
this illustrates is the order of execution when you include more than one
module the object when I say put as David talk
it actually finds the talk in the loud module and look the loud module finds
the talk in the vocal module
basically when you when the object is doing this search through classes of
modules when it's looking at modules it goes in reverse order of inclusion
so the most recently included module will be the first in the search path and
then the next you know that if you call if it doesn't find
there goes to the next one and so forth or in this case super takes it to the
next one
so it's a very sort of you know strict set of rules governing the to look up
the method look up process and then this one is just a illustration of extend in
this case what i've done is i've said module quiet defined talk and this is
you know multiple parentheses just to show you how quiet it is and what I do
here is I i take the David object and I extend it with quiet and when you extend
your it's similar to including a module except it's on a per object basis
so what I'm saying is you know most personal objects are going to talk loud
at this point but this one person object i'm extending with the quiet module so
now when I say David . talk
I get the result of of the quiet on the quiet version of talking
so basically you can you can manipulate you know what where the object is going
to find a method on where along the path that's going to either find it or fail
to find it on and it's good to to know again that objects are looking along a
path of modules and classes the object is not itself sort of possess the method
all right classes and modules are objects
the answer is seventy-five percent of all questions about ruby is because
classes are objects me and its really remarkably true
huh there's a lot of a lot of things that get clarified when you when you
totally grasp this idea that classes are objects because classes and modules are
objects and classes sort of our modules actually quite the class class is a
subclass of the module class so classes and modules are very very similar
objects and not in every way but in a lot of ways but class of the modules are
objects therefore you can send them messages right just like you can with
any other object you can put them in collections
you can assign them to local variables perhaps one that that causes some
confusion is the fact that a class can actually have its own instance variables
every object in Ruby hat has at least potentially a stash of instance
variables that represent the private state of that object
well since the class is an object it can have its own instance variables that can
have its own private state
it's not something you do every day
you don't necessarily you know always have a need to give instance variables
to class objects but it's good to understand that you can because the
class itself is an object and therefore it has you know sort of all of the the
rights and privileges connected with being an object like being able to have
its own its own its own instance variables here is just again a little
code illustration I i have a class person i assign it to a local variable
this is just to you know make it clear that it's the object that matters it's
not the fact that it's a reference in a constant like person you can put in it
you can bind it to any identifier
I say David equals my class . new so even though my class does not begin with
a capital letter it the object it evaluates to is a class and therefore i
can call new on it
the the commented out line is if i take class myclass that doesn't work because
the class keyword does expect a constant so you can't just drop in the local
variable in that position
however you can do something like my class . class event
all and what that will do is it will put you into a class definition block that's
based on that class and then you can proceed to define methods and so on so
there's as usual there's ways to sort of us related alternate techniques for
doing stuff that that at first it might seem you're not allowed to do
alright so classes are objects is is an important one and worth sort of playing
around with . number five
there's always a self now self play several different roles whatever object
itself at a given moment and there's always exactly one
it's the default receiver of messages so if you are if you're in a context where
we're a string is self then if you just say like down case and not string . down
case or even self dark is a sort of bare word like that
Ruby well first we'll try to resolve it as a local variable and if it fails it
will try to resolve it as a method being called on self the self is the default
receiver of messages when you when you don't specify a receiver and you don't
have a . think they like that
self is the owner of all instance variables now this is a really important
one and this one
this leads to a lot of confusion and and it's worth really internalizing this
every time you look at ruby code and you see an instance variable at whatever
that instance variable without exception belongs to whatever self is at the
moment that it's being executed every instance variable belongs to self
so if you for example one of my favorite examples actually if I say let's just
say class see it doesn't much matter
now look what I've done here I've created an instance variable this also
connects up with the point about classes owning their own instance variables so
that instance variable belongs to sell
now what is what exactly is self at this moment
well if we evaluate self we find itself is the Class C so that instance variable
let's go back in here just I don't actually have to do it again but now if
i say def misleading method
now here's what's going to happen i say see . new and i'm going to say see
misleading method
anyone want to walk into my little trap what's it going to print so mean of me I
really should
well let's just say if you glance at it you could you could easily and many
people have assumed that it will print one because look you've got you know
you're you're assigning to an instance variable bar equals well at bar equals
12 lines later you're printing an instance variable
the reason it doesn't print one a prince nil
the reason is that self has changed and that second line where they add bar
equals oneself is the class object two lines later because i'm in a method
definition itself is an instance of this class so it is a different object yes it
is an instance of the class that was self before but they are to the the
class sea and the sea . new object are two unrelated other than the fact that
one is an instance of the other there
they're unrelated they're not the same object they do not share instance
variables
so what's happening is that ruby is being very literal and saying every
instance variable belongs to sell and as far as that's concerned i had never
initialized the one that's on line 19
right thats that defaults to know because i actually didn't did not
initialize that particular variable the value of self changes it will flip to
something different in a class definition where it becomes the class
itself in a method definition and again this is sort of echoes the example i
just showed where itself becomes the object that will call the method on an
instance of valve it becomes the receiver of instance about instance of l
is basically a way to to flip self to be something else if you want
if you want to to change cell for the duration of a code block use instance of
valve and the object on which you call instance of Al become self for that code
block and in class about becomes the class and module so there's this you
know place is kind of fairly you know fairly small number of places but
important to to grasp yourself will actually change or or flip to another
object
this is just kind of tracing self at different points
one thing to note is that
well self in the class definition body comes out as person self in the instance
method comes out as the person instance again notice the difference this is the
class this is an instance the one in the middle self at the top level main when
you're at the top level in other words you're not inside a class definition
you're not inside a method definition you're just floating in sort of Ruby
outer space
Ruby creates this special object called main which really exist its kind of the
backstop object it's like it exists because there has to be a self so it it
sort of bootstraps the object model by creating this this sort of default
object main and that's why when I say you know show me self at the top level
is actually comes out as main if you type main you can't actually refer to it
as may
and that's just the tag or sort of rapper named that Ruby gives it but but
that's that the top level object before the top level self before you enter into
any context context where self is going to be changed
this is just a quick example of instance eval
I string equals i am a string and I just I print itself and then I do string .
instance eval and here I'd say self is now self and put it up case basically
what's happening is again in that second line self is main right because I'm out
in the the top level when you do an instance of value swap in self
I've swapped in the str the string
I've swapped that in itself for those two or three lines so everything that
happens in that instance of a block happens in relation to that the self
that is that I've called instance of a long class about
similarly here i've got i've actually just created an anonymous class Mike my
class equals class . knew if i print itself in a class about that it's going
to be the class that I've called class about on
so self is is important and again there's there's always there's always
one and it does it does change from one object to another
all right . number six variables contain references to objects
what that means is for example here I say string equals high and I say string
2 equals string
now what i've done here is i've copied a reference to a string from one variable
to another and i put it that way to make it clear that i have not copied the
string i still only have one string object and you can tell that because if
i append the word that
error to the second variable through or through the use of the second variable
and then I print out the first variable the there is there right in other words
I've manipulated the original string by using a second variable and that's
because each of those variables contains a red direct reference to that exact
object so there's no copying going on it's it is actually the same object and
that again can be a source of some confusion especially at first when
you're not sure why objects are being are being damaged in mysterious ways
this is just an example using an array essentially i create an array of three
objects
I copy you reference into a ray - I then add an element to array to and it's
showing up when i print array that that fourth element is present so again i'm
i'm using references to manipulate objects but every reference refers to
the same object every copy of the reference
now here's one that's kind of a another slightly cautionary tale
I have a variable called one which is the string 1 and then I have an array
that consists of one to three notice two and three are capitalized and one isn't
if I capitalized one in place using the capitalized bang method then I've
changed the string 1 to capital
oh and it that is also reflected in the array because the array contains that
same object that that object one
here you see the results are kind of similar behavior in the face of a method
call here i have a method called add bang which takes a string and just adds
an exclamation point to it and you can see if i call add bang on a string
are you using a variable using a reference it operates on exactly that
object because then when I printed out it has the ! the method does not copy
the string it does not return a copy it returned it actually operates on the
original object and and the object reflects that change
note however that if you use plus on strings or plus equals you actually get
it you do get a new strings if I say string 2 plus equals there that is not
going to affect the original string because i'm actually reassigning on
I must I'm reassigning to the string to variable a new string that has the word
there at the end
so if you if you want to not or if you want to use copies and so forth and you
can use the plus equals and that will kind of diverge one object away from
another
all right be careful with fries
the thing with fries is that if you freeze an array for example if I have an
array i freeze it I try to push something onto the array I can't do that
but notice that I can
change the first the first element in the array right i can say a race of 0 .
up case bang and here I've actually changed the first element in the array
to its up case version so be careful with fries because this is you know sort
of it's a little bit tangential to this but it's it's sort of related to
references to you just want to be careful that even if an object is if
it's a collection object and it's frozen
the items in the collection are not frozen
that's what you have to be careful with all right finally
just a little bit about true and false true and false in Ruby are objects but
true and false are also states every object has a boolean value either true
or false
those are the states only two objects have the boolean value false those
objects are nil and falls every other object in ruby is true
so 0 is true and empty strings are true and so forth
now that's usually if it is a source of confusion it's usually pretty brief so
you know coming from other languages
a lot of people expect 02 befalls for example but but it isn't
and you can always run a sort of truth test if you in anything where you can
put an if and here there's again a couple of sort of whimsical examples
where I'm actually i'm testing testing the truth of a class definition
um so if class a and put s true well that's going to return nil so that will
not be true if Class A zero and put us through that will output true because
Class A zero and evaluates to 0 which is true
so this is really just illustrate that you can you can and this may be more of
a mental exercise and something you would do with literally with with if
statements but you can always anything you want to know the truth value of you
can plug into an if statement and if it if it passes that then it's then it's
true
in the boolean sense
all right just a little summary of of what we've covered seven points and
again my goal in doing this is to give you
hopefully the benefit of some of my observations over the years of of things
that that people have found confusing things where people had great sort of
aha moments because they you know it's like aa classes are objects or whatever
or you know other self changed because i entered a method definition so hopefully
like I said at the beginning hopefully some of this will you know be helpful to
you personally it may be that if you work with people or our mentoring people
who are learning ruby it will give you a little bit of you know some ideas about
trouble spots to emphasize and make sure that they understand and I i am going to
stop here i have a few little things but but we will will I think end here
because we're just about out of time
are there any questions yes
morning the rounds
value
just do your place and I just prevented that
yeah you can you can do to avoid the reference problem
yeah i mean duping is is certainly one like you
you do have to be careful also though like when remember that duping is not a
deep operation
so if you do but array you actually get a new array but it has the same object
in it so you can you have to be careful that that it's a shallow do operation
sorry what's the right
right
you have any suggestions for other other approaches to avoid during beautiful
objects
Harry knows that
right I've been I think do thing is sort of
that's the thing that comes to mind
let's say there's nothing else but that's what
that's what
bread and butter somehow it ends up not being too huge problem not sure why
exactly but like just people don't write that many methods that can change their
argument I mean I think it's sort of a bad practice anyway to change are
questionable practices change that you know you send an argument to a method to
actually destroy it and not you know kind of silently changes unless you know
some really compelling reason but
so I think people just avoid some of those things that that old
yes are exhausting behaviors that you have died there
they actually find they discovered hers already defined to be tended movie would
be like that and then with the exception that is that the jruby
and all the other Ruby's implies a few little things especially there
I think I mean I had anybody going to be able to prove me all about this i think
i've stuck two things here that are really are in the language like the fact
that everything reduces to an object like a class definition again there's
not that many cases where you where you use that back directly but i believe
that it is sort of inherent in the line think the language that everything in
another class definition we would evaluate to an object if it's time to
evaluate
well now there and I'm not so they've been talking about for example having
method definitions evaluate two symbols that are the name of the method and
things like that
I don't know whether any other implementation is actually done that
I don't think so but it that's something where you could because Ruby makes very
little you can basically any method definition whatever is inside it
the definition block itself value X to the hill so that in a way it's a wasted
opportunity because we could evaluate to a name
you could evaluate to a man that object whatever
so I'm not sure whether any any of the other implementations that sort of
stepped into that particular space and it certainly could happen but I i think
most of you know what i would probably I think would have applied all
yeah
you get what
ok there yet so everybody's you get back
compiling the object ok let from the definition body parts that i didn't
really talk about those
that's an example where something sort of you know in this family of things
might be different
all right thank you very much
- the well-grounded newbie advice for Ruby newcomers and their mentors
I know that not all of you are Ruby newcomers in fact I see some reasonably
seasoned Ruby programmers in the room but as you'll see this is advice partly
for newbies and partly for people who might have occasion and turn to advise
or mentor newcomers to Ruby just a couple of words about me
i started using ruby in two thousand which was when the pickaxe book came out
the book programming Ruby by dave thomas and Andy hunt
I sort of stumbled on the book literally well you know manually anyway at a
bookstore right after it came out and I've been hooked on Ruby ever since i'm
one of the directors and founders of Ruby central and we are the parent
organization of this event as well as railsconf and other projects
what are we going to do today well we're going to learn some what i consider
major common points of confusion essentially what I've done here is to
choose and this is a purely subjective choice but i have chosen points that I
think because I've seen it happen over and over again I think are particularly
either difficult or more tricky or in some way kind of the hard too hard to
grasp for particularly for newcomers
we're going to look at some of these points and hopefully this will improve
both your ability to understand code
and to write code because you'll see exactly what's going on in some of these
cases
we're going to look at seven points again this is purely subjective choice
seven points that I think are common stumbling blocks and i should add it's
not just for absolute newcomers to Ruby this is my choice of of the seven points
is based on years of training
rubyists including people who are not necessarily complete beginners but these
are things that I've seen people kind of have trouble with again and again and
we'll look at how these particular seven points can help you understand Ruby
questions throughout if you have questions just go ahead and and raise
your hand and we may have some time at the end to but if you you know as we go
along if you have questions that's fine i'll try to accommodate them
alright so we're going on this this little trek through seven points
custom chosen by me to help you get a handle on some of the tricky things in
Ruby
ok every expression evaluates to an object
you'll sometimes hear people say of Ruby
everything is an object everything is not an object for example an if
statement is not an object an argument list is not itself an object it's a
syntactic construct keywords are not objects
so there are things in Ruby sort of peppered throughout the code that are
not themselves objects you can point to something and say that that isn't an
object it's a keyword or whatever but everything does evaluate to an object
including things like if statements method definitions class definitions are
so everything evaluates or reduces to an object and we're pretty used to this
with you know what if you just type in like the number ten it evaluates to the
number 10
but here's a couple of the loved ones that you might come across and not not
know exactly what to expect
for example an ifs to have failed if statement always returns nil
so if you say if something
that's not true and there's no branch of the if that returns true or that that
that evaluates to true
the entire if statement those three lines evaluate to nil
so everything reduces to an object and if statement reduces to an object in
this case it reduces to the object mill and it does it never reaches that middle
line that with that string not reach so this is a failed if statement on the put
s or puts method also evaluates to nil and sometimes again especially if you're
not used to IRB which has this read eval print loop going
I RB is very literal if I say put s hello
it will obediently print the word hello
but the entire operation the actual call to the method put s returns nil and put
us always returns nil it that's it
it does not return the string that it prints it prints the string as a kind of
side effect and it returns no that's why you get in
IRB you get the the string printed out but then you get nil as the return value
the evaluation of of the entire statement empty class definitions now
you get this is a little bit arcane there's not too many use cases where you
care what a class definition evaluates to you care about defining a class
you don't necessarily care what the class definition ends up producing too
but it's there
there are a couple of use cases and it's I think just instructive to know that a
class definition does have a value an empty class definition evaluates to nil
so if i say classy
and that's an empty class definition it's nil
if you happen to have an object other than ill in your as the last value in
your class definition the entire definition will evaluate to that object
so the value of those three lines at the bottom classy some value in class
definition and the value of that statement is the string some value in a
class definition
so again everything reduces to an object and went when in doubt if you sort of
wondering why something is nil or why something is until for that matter
think about the the literal kind of looking at what the statement or
expression reduces to all right . number two
it's all about sending messages to objects
this is not an obscure . this is kind of the the lifeblood of Ruby but it's worth
noting that and i think this is one of the kind of really interesting and cool
characteristics of Ruby that it's all about sending messages to objects even
when it doesn't look like it is so for example you have
well you have on messages that come after dots
those are kind of the you know the sort of bread and butter ABC . up case that's
sort of the the the most kind of canonical way to send a message to an
object you put a dot after it and then you put a message in this case the
message up case however in fix and you know
unary operators are usually also sending messages on and I'll show some examples
2 square brackets are a message case statements also end up sending messages
to object so let's look at a couple of these for example 3 plus 2 in Ruby that
in fix plus sign is actually a method call
it's actually three it essentially it's three . + with the with the
the argument - so you're sending the message plus sign to the object three
with the argument to Ruby very nicely allows you to write it as an infix
operator
but you're literally calling a method whose name is a plus sign the same thing
for most of the other arithmetic operators including star and division
and so forth square brackets or another one if you look at a sub - I use the
word sub four square brackets i think it's very old school and not sure but
that what i mean by sub is a square brackets to the object a in this case
has a method
whose name is a pair of square brackets and I'm calling that method with the
argument -
so again i'm sending a message to an object even though Ruby because of its
just what it allows my way of syntactic sugar
so to speak Ruby of has it it looks like syntax but it's actually calling a
method in this case the square bracket method
interestingly even the unary plus the plus sign in front of an object can
actually be defined through this method called + @ sign now this is a kind of
bogus example because you can't actually call it with a . so this is more just to
give you kind of an x-ray of the fact that the behavior of an object in the
face of a unary plug a proceeding plus sign will actually be determined by that
method for example let's see if I can we get this is an IRB session in a
slightly malformed terminal well if I think you'll be able to see this
if I say something like calm class person when I feel like the indentation
is weird here let's let's try this again
ok class person
atra reader name this is just a very simple will say initialize name equals
name and now i'm going to define plus at whoops
+ @ sign and i'm just going to define it as name . up case and you'll see this
just allows us to kind of follow the the the dye through the bloodstream so to
speak
so now i'm going to go David equals person . knew this is just going to run
off the screen
home is that how clever of me just invented the mouse ok David equals
person . new
and we'll give me a name
now this is you know this is just sort of whimsical example but if I now say
plus david i get my name in uppercase right in others I i have defined the
logic for the unary plus sign and it it behind the scenes involves sending a
message calling a method and coming up with the result of that
alright so operators are mostly methods and that this is actually just an
example of of the regular plus sign in this case I hope it's not too small but
I mean you can you know sort of experiment with this - on your own
this is another person class it has an inner class called couple
the idea here is that when you have a couple of people which you achieved
through a plus sign
you get if you look at where it says def to s basically the string representation
of a couple is the two names joined by the word and so if i say John equals
person knew
Marcia equals person new give them the appropriate names a nice a couple equals
John plus Marcia what happens is the the plus method gets called and it returns a
new couple and then if i print the couple it it falls back on the 2's
method for couples and it Prince John and Marcia
so basically you can again this is sort of whimsical example as most of them are
as you'll see but you can you can basically do what you want with the the
plus logic but again it's always calling a method and and by the same token you
can sort of look into it by defining that meant yes
right
that's just the name of the Met that's the the name of the sort of the hook
you have to define so yeah yeah i mean if you define just plus then you get the
the in fix operator syntax if you define the plus at it gives you the unary plus
behavior
ok
another i think really prime example of a case where where Ruby looks like it
isn't sending messages to objects but it actually is is the case statement now if
you look on the column on the left and just ignore the rest of the moment I
have case some string which is whatever when ABC which means if this if the
string is the string ABC do so you know such and such to other that when regular
expression d e f if the string matches the EF do something else and case
statements in Ruby are governed or engineered by this method whose name is
three equal signs now or the the threequel operator if you will
um what actually happens under the hood
when I say when ABC I have a when Klaus
what's actually happening in terms of of what Ruby is doing is it's saying if a b
c 3 equal signs some string right if I say case some string when ABC
I'm really saying if ABC three cool
some string and that in turn is really just syntactic sugar for this
there is a method called three equal signs and it like the plus sign if you
use it as an infix operator
you're actually calling a
method now this middle one where use it as an infix operator that sort of a you
know kind of hypothetical you know you don't actually necessarily see that I
mean when you do the case statement this is all you know wrapped in layers of
syntactic sugar on top of sugar but what's really going on is that I'm
calling the threequel Matt the three equals I method on the string ABC with
the argument of my my case expression some string
now what this means again is that you can also roll your own
in other words if you want to define your own case behavior
how am I objects going to fare in the pace of a case statement
well here what I've done is again that the good old class person i I've now got
name and social security number
so with SSN and up there in red I've defined my frequent method and what it
basically says is the threequel method returns true if my social security
number is the same as the social security number of the argument to the
threequel method
so what happens then i create David with a number joe with a number and mystery
person with as it happens david's number
so now we're going to see which which person is the mystery person well when
Joe but as it's joe when David because it's david and again this is based on
Joe three cool mystery and David three cool history and of course it turns out
to be
David so you can actually govern the behavior of your objects in case
statements by hooking into this three cool math that you never actually other
than defining it you never work a statement at least you never actually
have to type it it happens just happens automatically
but that's kind of the underpinning of some of the the case behavior
alright so we see messages are being sent to objects even wear it doesn't
necessarily look like they are as in case statements and infects operators
it is also true and this is our third .
that objects resolve messages into methods now I am splitting hairs here i
am i am kind of putting in a wedge between the message and the method in
normal conversation right we talked about we send messages to objects or we
say you know I i called the up case method on this object or i sent the
message up case to this are probably more often say I called the up case
method on this object method and message
are you know that there's a little bit of fluidity just in kind of how we use
the most of the time but I'm again i'm driving a wedge through that I want to
be be clear about the difference between sending the message and calling the
method
my take on this and I've actually gotten in trouble on a mailing list for saying
it this way but I thought about it and I've decided I'm sticking to it on that
objects do not have methods now it is sort of a half-truth I mean you can say
yes the string has an up case method but what i mean by this wednesday objects do
not have methods
what I mean is that the method itself does not live in the string object
the method itself let every method lives in a class or a module there are no
exceptions to that every methods are defined in classes or modules
they're not defined even a method that you define on an individual basis just
for one object that method and you can do that in Ruby defining singleton
methods that method still lives in a class
it lives in what we call the singleton class of the object
so every method even if it's just a method on one object every method lives
in a class or module so object that's what I mean when I say objects do not
have methods objects have intelligence you send a message
- an object the object has the intelligence to to search through app at
a predetermined path of classes and modules to find a a method that
corresponds to the meth best sausage
so I sent the message up case to a string the string has a search path
where it looks for a method
whose name is up case and when it finds it executes if it doesn't find it you
get a method method missing ever
this is a diagram actually from my book the well-grounded rubyists and what's
going on here is if you look at the bottom we create a new object and send a
message X now this just gives you a sense of of where an object looks for
methods we in this case we're looking for a method called X going to actually
not find it according to this because it's not actually defined the first
place it looks is actually in what I referred to as the singleton class of
the object which is really just a storehouse for methods that belong only
to this object and in fact singleton classes are only created sort of on
demand objects just for efficiency reasons objects don't even have a single
to method unless you are sorry singleton class unless you define a singleton
method or or open the class explicitly as I've done here
now the singleton class this this notation class
arrow arrow object that actually opens up the singleton class of of the object
and what i've done here is i've included a module called and what that means is
in its as the object searches for this X method after it looks in it singleton
class it will look in any modules that are included in that class so it goes
off and makes us what I think of its kind of side trip to the module and
does not find a method called X comes back to the main track and goes up and
now it's at the class d which is the class of this object so it's now looking
in its in its original class and saying you know is there an X method
well no there isn't ok how about any modules that are included in this class
well there's a module called am that's included in this class so let's go
looking at them
is there an X method No so back we go and up to the superclass of d
notice the d inherits from sea we look and see
we find that there's no x.x method and it actually would go beyond that
once you hit sort of the top of your class tree it would then go up to the
object class on the the kernel module which is included an object and then
finally up to the basic object class which is really the top of the tree and
if it doesn't find it the carrots
it's it's failed and you get a method missing error
this is just a little bit of sort of showing the the lookup in action again
that the person class with the name accessory i create a person object named
david i'm now going to create a module called vocal which simply has a method
called talk and it's it's a little bit tightly coupled with the person class
admittedly it it depends on the name method but will will let me
will will give me a free ride on that one house that so we have a method
called talk which basically just says your name
now I class person i include the vocal module that means if I say put s David .
talk
David the object David this person object now has access to a talk method
and notice one important thing here is that when i created David David did at
that time did not have a talk method because there's no talk method in the
person class but even after i've created the person object I can include a module
in the person class
and even the pre existing objects will be able to find the methods that are in
that module
it's all about what the object nose at the moment that you send a message so i
sent the message talk and at that moment all it cares about is is there such a
method in my classes are such a method and a module included in my class I
guess there is because it includes vocal
so that's a good a good illustration of the fact that are all objects care about
is what is the state of the things at the time that you send them the message
all right now I have a second module called loud and what this does is it
actually called super which suit what super does is super walks up this path
of of method searching and finds a previous definition and execute that so
it's going to walk up the up the class and module path looking for a method
called talk and it's going to find it well I'm sorry i should mention i can do
class person include loud
so now when I say put s David talk it says hi my name is David but in capital
letters with ! because now it's loud now one thing here this is a little bit of a
contrived example well most of them are in this in this talk but one thing that
this illustrates is the order of execution when you include more than one
module the object when I say put as David talk
it actually finds the talk in the loud module and look the loud module finds
the talk in the vocal module
basically when you when the object is doing this search through classes of
modules when it's looking at modules it goes in reverse order of inclusion
so the most recently included module will be the first in the search path and
then the next you know that if you call if it doesn't find
there goes to the next one and so forth or in this case super takes it to the
next one
so it's a very sort of you know strict set of rules governing the to look up
the method look up process and then this one is just a illustration of extend in
this case what i've done is i've said module quiet defined talk and this is
you know multiple parentheses just to show you how quiet it is and what I do
here is I i take the David object and I extend it with quiet and when you extend
your it's similar to including a module except it's on a per object basis
so what I'm saying is you know most personal objects are going to talk loud
at this point but this one person object i'm extending with the quiet module so
now when I say David . talk
I get the result of of the quiet on the quiet version of talking
so basically you can you can manipulate you know what where the object is going
to find a method on where along the path that's going to either find it or fail
to find it on and it's good to to know again that objects are looking along a
path of modules and classes the object is not itself sort of possess the method
all right classes and modules are objects
the answer is seventy-five percent of all questions about ruby is because
classes are objects me and its really remarkably true
huh there's a lot of a lot of things that get clarified when you when you
totally grasp this idea that classes are objects because classes and modules are
objects and classes sort of our modules actually quite the class class is a
subclass of the module class so classes and modules are very very similar
objects and not in every way but in a lot of ways but class of the modules are
objects therefore you can send them messages right just like you can with
any other object you can put them in collections
you can assign them to local variables perhaps one that that causes some
confusion is the fact that a class can actually have its own instance variables
every object in Ruby hat has at least potentially a stash of instance
variables that represent the private state of that object
well since the class is an object it can have its own instance variables that can
have its own private state
it's not something you do every day
you don't necessarily you know always have a need to give instance variables
to class objects but it's good to understand that you can because the
class itself is an object and therefore it has you know sort of all of the the
rights and privileges connected with being an object like being able to have
its own its own its own instance variables here is just again a little
code illustration I i have a class person i assign it to a local variable
this is just to you know make it clear that it's the object that matters it's
not the fact that it's a reference in a constant like person you can put in it
you can bind it to any identifier
I say David equals my class . new so even though my class does not begin with
a capital letter it the object it evaluates to is a class and therefore i
can call new on it
the the commented out line is if i take class myclass that doesn't work because
the class keyword does expect a constant so you can't just drop in the local
variable in that position
however you can do something like my class . class event
all and what that will do is it will put you into a class definition block that's
based on that class and then you can proceed to define methods and so on so
there's as usual there's ways to sort of us related alternate techniques for
doing stuff that that at first it might seem you're not allowed to do
alright so classes are objects is is an important one and worth sort of playing
around with . number five
there's always a self now self play several different roles whatever object
itself at a given moment and there's always exactly one
it's the default receiver of messages so if you are if you're in a context where
we're a string is self then if you just say like down case and not string . down
case or even self dark is a sort of bare word like that
Ruby well first we'll try to resolve it as a local variable and if it fails it
will try to resolve it as a method being called on self the self is the default
receiver of messages when you when you don't specify a receiver and you don't
have a . think they like that
self is the owner of all instance variables now this is a really important
one and this one
this leads to a lot of confusion and and it's worth really internalizing this
every time you look at ruby code and you see an instance variable at whatever
that instance variable without exception belongs to whatever self is at the
moment that it's being executed every instance variable belongs to self
so if you for example one of my favorite examples actually if I say let's just
say class see it doesn't much matter
now look what I've done here I've created an instance variable this also
connects up with the point about classes owning their own instance variables so
that instance variable belongs to sell
now what is what exactly is self at this moment
well if we evaluate self we find itself is the Class C so that instance variable
let's go back in here just I don't actually have to do it again but now if
i say def misleading method
now here's what's going to happen i say see . new and i'm going to say see
misleading method
anyone want to walk into my little trap what's it going to print so mean of me I
really should
well let's just say if you glance at it you could you could easily and many
people have assumed that it will print one because look you've got you know
you're you're assigning to an instance variable bar equals well at bar equals
12 lines later you're printing an instance variable
the reason it doesn't print one a prince nil
the reason is that self has changed and that second line where they add bar
equals oneself is the class object two lines later because i'm in a method
definition itself is an instance of this class so it is a different object yes it
is an instance of the class that was self before but they are to the the
class sea and the sea . new object are two unrelated other than the fact that
one is an instance of the other there
they're unrelated they're not the same object they do not share instance
variables
so what's happening is that ruby is being very literal and saying every
instance variable belongs to sell and as far as that's concerned i had never
initialized the one that's on line 19
right thats that defaults to know because i actually didn't did not
initialize that particular variable the value of self changes it will flip to
something different in a class definition where it becomes the class
itself in a method definition and again this is sort of echoes the example i
just showed where itself becomes the object that will call the method on an
instance of valve it becomes the receiver of instance about instance of l
is basically a way to to flip self to be something else if you want
if you want to to change cell for the duration of a code block use instance of
valve and the object on which you call instance of Al become self for that code
block and in class about becomes the class and module so there's this you
know place is kind of fairly you know fairly small number of places but
important to to grasp yourself will actually change or or flip to another
object
this is just kind of tracing self at different points
one thing to note is that
well self in the class definition body comes out as person self in the instance
method comes out as the person instance again notice the difference this is the
class this is an instance the one in the middle self at the top level main when
you're at the top level in other words you're not inside a class definition
you're not inside a method definition you're just floating in sort of Ruby
outer space
Ruby creates this special object called main which really exist its kind of the
backstop object it's like it exists because there has to be a self so it it
sort of bootstraps the object model by creating this this sort of default
object main and that's why when I say you know show me self at the top level
is actually comes out as main if you type main you can't actually refer to it
as may
and that's just the tag or sort of rapper named that Ruby gives it but but
that's that the top level object before the top level self before you enter into
any context context where self is going to be changed
this is just a quick example of instance eval
I string equals i am a string and I just I print itself and then I do string .
instance eval and here I'd say self is now self and put it up case basically
what's happening is again in that second line self is main right because I'm out
in the the top level when you do an instance of value swap in self
I've swapped in the str the string
I've swapped that in itself for those two or three lines so everything that
happens in that instance of a block happens in relation to that the self
that is that I've called instance of a long class about
similarly here i've got i've actually just created an anonymous class Mike my
class equals class . knew if i print itself in a class about that it's going
to be the class that I've called class about on
so self is is important and again there's there's always there's always
one and it does it does change from one object to another
all right . number six variables contain references to objects
what that means is for example here I say string equals high and I say string
2 equals string
now what i've done here is i've copied a reference to a string from one variable
to another and i put it that way to make it clear that i have not copied the
string i still only have one string object and you can tell that because if
i append the word that
error to the second variable through or through the use of the second variable
and then I print out the first variable the there is there right in other words
I've manipulated the original string by using a second variable and that's
because each of those variables contains a red direct reference to that exact
object so there's no copying going on it's it is actually the same object and
that again can be a source of some confusion especially at first when
you're not sure why objects are being are being damaged in mysterious ways
this is just an example using an array essentially i create an array of three
objects
I copy you reference into a ray - I then add an element to array to and it's
showing up when i print array that that fourth element is present so again i'm
i'm using references to manipulate objects but every reference refers to
the same object every copy of the reference
now here's one that's kind of a another slightly cautionary tale
I have a variable called one which is the string 1 and then I have an array
that consists of one to three notice two and three are capitalized and one isn't
if I capitalized one in place using the capitalized bang method then I've
changed the string 1 to capital
oh and it that is also reflected in the array because the array contains that
same object that that object one
here you see the results are kind of similar behavior in the face of a method
call here i have a method called add bang which takes a string and just adds
an exclamation point to it and you can see if i call add bang on a string
are you using a variable using a reference it operates on exactly that
object because then when I printed out it has the ! the method does not copy
the string it does not return a copy it returned it actually operates on the
original object and and the object reflects that change
note however that if you use plus on strings or plus equals you actually get
it you do get a new strings if I say string 2 plus equals there that is not
going to affect the original string because i'm actually reassigning on
I must I'm reassigning to the string to variable a new string that has the word
there at the end
so if you if you want to not or if you want to use copies and so forth and you
can use the plus equals and that will kind of diverge one object away from
another
all right be careful with fries
the thing with fries is that if you freeze an array for example if I have an
array i freeze it I try to push something onto the array I can't do that
but notice that I can
change the first the first element in the array right i can say a race of 0 .
up case bang and here I've actually changed the first element in the array
to its up case version so be careful with fries because this is you know sort
of it's a little bit tangential to this but it's it's sort of related to
references to you just want to be careful that even if an object is if
it's a collection object and it's frozen
the items in the collection are not frozen
that's what you have to be careful with all right finally
just a little bit about true and false true and false in Ruby are objects but
true and false are also states every object has a boolean value either true
or false
those are the states only two objects have the boolean value false those
objects are nil and falls every other object in ruby is true
so 0 is true and empty strings are true and so forth
now that's usually if it is a source of confusion it's usually pretty brief so
you know coming from other languages
a lot of people expect 02 befalls for example but but it isn't
and you can always run a sort of truth test if you in anything where you can
put an if and here there's again a couple of sort of whimsical examples
where I'm actually i'm testing testing the truth of a class definition
um so if class a and put s true well that's going to return nil so that will
not be true if Class A zero and put us through that will output true because
Class A zero and evaluates to 0 which is true
so this is really just illustrate that you can you can and this may be more of
a mental exercise and something you would do with literally with with if
statements but you can always anything you want to know the truth value of you
can plug into an if statement and if it if it passes that then it's then it's
true
in the boolean sense
all right just a little summary of of what we've covered seven points and
again my goal in doing this is to give you
hopefully the benefit of some of my observations over the years of of things
that that people have found confusing things where people had great sort of
aha moments because they you know it's like aa classes are objects or whatever
or you know other self changed because i entered a method definition so hopefully
like I said at the beginning hopefully some of this will you know be helpful to
you personally it may be that if you work with people or our mentoring people
who are learning ruby it will give you a little bit of you know some ideas about
trouble spots to emphasize and make sure that they understand and I i am going to
stop here i have a few little things but but we will will I think end here
because we're just about out of time
are there any questions yes
morning the rounds
value
just do your place and I just prevented that
yeah you can you can do to avoid the reference problem
yeah i mean duping is is certainly one like you
you do have to be careful also though like when remember that duping is not a
deep operation
so if you do but array you actually get a new array but it has the same object
in it so you can you have to be careful that that it's a shallow do operation
sorry what's the right
right
you have any suggestions for other other approaches to avoid during beautiful
objects
Harry knows that
right I've been I think do thing is sort of
that's the thing that comes to mind
let's say there's nothing else but that's what
that's what
bread and butter somehow it ends up not being too huge problem not sure why
exactly but like just people don't write that many methods that can change their
argument I mean I think it's sort of a bad practice anyway to change are
questionable practices change that you know you send an argument to a method to
actually destroy it and not you know kind of silently changes unless you know
some really compelling reason but
so I think people just avoid some of those things that that old
yes are exhausting behaviors that you have died there
they actually find they discovered hers already defined to be tended movie would
be like that and then with the exception that is that the jruby
and all the other Ruby's implies a few little things especially there
I think I mean I had anybody going to be able to prove me all about this i think
i've stuck two things here that are really are in the language like the fact
that everything reduces to an object like a class definition again there's
not that many cases where you where you use that back directly but i believe
that it is sort of inherent in the line think the language that everything in
another class definition we would evaluate to an object if it's time to
evaluate
well now there and I'm not so they've been talking about for example having
method definitions evaluate two symbols that are the name of the method and
things like that
I don't know whether any other implementation is actually done that
I don't think so but it that's something where you could because Ruby makes very
little you can basically any method definition whatever is inside it
the definition block itself value X to the hill so that in a way it's a wasted
opportunity because we could evaluate to a name
you could evaluate to a man that object whatever
so I'm not sure whether any any of the other implementations that sort of
stepped into that particular space and it certainly could happen but I i think
most of you know what i would probably I think would have applied all
yeah
you get what
ok there yet so everybody's you get back
compiling the object ok let from the definition body parts that i didn't
really talk about those
that's an example where something sort of you know in this family of things
might be different
all right thank you very much
Code Blocks in Ruby by Alex Chaffee
so now let's talk about block um
blocks are used all over the place and route
on there so ubiquitous that a lot of people don't even know they're using
them
when they re learn Ruby they're just following the example
and they don't know that every time they say the word do
they're creating a bloc and passing it in to a map it
but that's what happened a block
is a jungle coat the concept of blocks overlaps
not entirely identical with but it overlaps with the following
set up terms they're all waterways are doing the same thing which is
taking up one trip code: and instead of executing it immediately
making it in and a little capsule love code and then letting someone else call
it a little later
so some languages do this with something a function pointer
some languages do this with runnable
like Java you can't actually yet
have a closure in Java and you can't get a proper pointer to a function in Java
so you instead you make an object that has a method name
run and that's a runnable right
arm in javascript a function
is a function pointer really it's an object but it's also serve appointed to
its up to you to find a function you can then
just set the variable 2.2 that function and that
allows you to call it later if you want um
other terms prague lambda call back
front door delegates the sharp as something up delegates
and the other a lot like fun to play alright the basic idea is
it's a chunk of code that you're not going to execute
right now your executed a little later or maybe a lot later
or maybe never another term for what this is doing is it is real fining
Co to rate by does that mean the lakes and
rate means out on the tiles to rate by means to make it into a thing
it comes from the Latin term race between think
are yes right been to think up by
it's making coated with think Ruby
has 3 different well several different on Sat
that are very closely related on but
distinct a function which I should really call a method
but really doesn't have actual functions so when everything function in really
really mean that
a method is a chunk of code that starts with debt
that gets attached to a class and executed
by a map a dispatcher a block
is a chunk of code that begins with do that gets passed
into another map it and we're gonna see exactly how in just a minute up rock
is actually an object that contains
a block so
if you want to get a pointer to a block put it into a variable
you can't do that directly in rupee you have to make a block
and then make a proper out at the block and then point to the proxy the little
convoluted I'm gonna show you exactly how that works in the
starting in the next slide but just the I just wonder for these Terms out here
there's subtle but important distinction between methods
blocks and props approx is an object that points to a blog a block at the
chunk of code
and a method is also a chunk of code but was completely different calling from it
yes
a block starts with do
curly braces a short and Purdue right
and it I don't like the curly braces it be better the curly braces didn't exist
it because curly braces are also used for hashes that a little ambiguity in
the language that's
irritating sup
every time you do as you this having to preview
every time you do started a blog so
69 as a method called times
and times executes that block this fax number of times
so if I'm I want to execute this code here
there by
I'm executing this I'm taking the sly hopeful
put a correct I am making it into a block
Rafael and then
Pines is calling that three times in a row
noticed that at the moment clear nothing is happening
it's the times method that is calling back
and activity mecca so
yes blocks can be wrapped in curly braces
a lot of people who are new to really prefer the curly braces
because it looks more like Java or C++ or JavaScript get over it
news do and rather than curly braces for the reason I just said which is that
with the curly braces there's an ambiguity
with parsing because it could be a hash
and that leads to some subtle annoying syntax error sometime
%uh indentation is also yeah it's
well depending on your editor it it technically there's no difference it's
just a simple
like do versus curly braces does the symbol for you should be able to figure
it out it's just
it's better to use do at
um we're gonna see in Justin a fewer flights
it's not actually a parameter or technically it's not a name
parameter it's an anonymous parameter and we're gonna see what that mean for
this to me
but yes it is being passed into time that's not in the normal way
so um blocks our youth for
lot the different purposes are used to solve lots a different problem
on the idea is that leave it up to the receiver the block to decide
what to do with that code and when or whether to call
so one thing that blocks are used for is called backs
let's say that you want to ask your network in library
to read in a TCP connection
and then as soon as that connection is closed take the content that
the entire can the entire packet
up love stuff that got past them by your network line
and past that into a block right so you're gonna call it later at a specific
time
but you don't want your code to wait for that to happen
doesn't I O found it might take seconds and seconds
you know but it's like eons to a computer you don't want to wait for that
I O
to come so you make a block and pass a block in
and then you trust the library call that block later when that
data is available alright
you can also use blocks for initializer lease the initial life
let's say that um I'm writing a sinatra
said after the is the weather framework that lets you set variables
arm maybe at the time that you can clear your program you don't know what the
proper value it's
so you make a block that will be called later and %um
that block will know what the proper value with at the time but it's call
alright so for initializing bank but initializing them later on
not like when you declare the program but when you're running from
so some more stuff has been set up in the meantime
they're also use for iterator with we've been using a lot
their use for separating a content
the body of an algorithm from the boilerplate around but after
loops are the classic example the generators
keep track love initializing an index incrementally and that
grabbing the value and in the case map
collecting the results into a new collection
and then after having done all that standard stuff they call your blog your
block does
the specific stuff the idiosyncratic stuff that your particular
loop will need extracts comment boilerplate stuff
inside a map it and then called back in that case does like with time that
happened
immediately but it's still a little bit later
and it still makes sense to do it it's not a call back in offensive waiting
for something happened long in the future
it happens immediately into the future but it still in the future
um it's also useful
for testing like that before block
in our spec write your specify a bit ago that's going to be run before every
single
examples back everything ok it block
by the way the if block is also a a do block it's also a
you know turns into a prop also it looks cool
sometimes your code it looks better you do things with blocks rather than doing
things in the exploded seaside
for lot stamina makeup on
yeah force or up
that's a another great example he didn't hear the
um sort for Team has a standard
comparison which is to use the flying saucer
but if you want you can pass in a customized sort blah
right the sort block would take two parameters the left side and right side
then return
you know negative 10 positive one but you can do whatever comparison you want
inside that block
sonya is a carried out sort do your configuring the algorithm
the way that you want
so let's talk about up rock keyword
crop terms a block into a variable or other into a reference
and then you can store that reference into a variable so in this case here
if I wanna say a
Prock do right in this case it's on one line so using
rates but I think prop do but I
that has made a reference to an object that when you call
that up to it will execute that block
and by call I mean say object outcall
so in this case I put it into a variable called say hi and then I say say I dot
call
and that will execute this book
and of course procs can take parameters
right blocks can take parameters and therefore proper call passes its
parameters in
block yes question
yet yeah and and I i've been
it a little technical but what's happening here is profits actually about
that
for act like a map it and then this is
the block so this if this is do but I and
that the find the block proctor that into a reference
and then meet a reference that call that executes block
so when you say call called us passes its arguments
directly into the blood
make that okay so
if I wanted to write aversion up times
that wasn't at school that a dumbed down version pot
I could do it this way I have a method called twice to do
that takes up rock which i'm naming action
could name it anything and is calling an action right now
and insider that meant that I'm calling it quite so now when I say
place do likely let me let me spell it out
I now have a variable say hi
and that variable adjusting the value that is actually a prop
so if I wanted to say say I dot call it does its thing
or I could pass that %um
as a name parameter and then placed he was gonna call it what
I'm now
I don't need to put into a variable if I don't want to
I could do that all in one go like that
place do crock do
but hi and
right so this same here to find the proper
and after that what's the proper gonna do well it's gonna do that
gonna do whatever i sat in the US
I now here comes the kicker
but the fault block so they've been called the anonymous blog for the
invisible blah
but it's called the ball
it is invisible and it gets past and just like this guy got past them
except instead of being passed into unnamed parameter
get passed into an unnamed invisible anonymous magic parameter
and on the inside a map it in order to call it
instead of saying action up call day
yield
so if I wanted to do the thing I just did a crock but using
the default block instead this is the implementation about map
and now you see why I put that weird underscored do in the previous
methodName because now i can say place
do quote up alright but
that work yeah let me try that again
place to put hi at
so this year is equivalent to death here
but this second version is much more concise
and reads moral English E right it's got that
domain-specific language thing going on here
I can actually take place do this
yeah
it is actually a block I if I had said the word prop here that would turn it
into a named parameter
an explicit parameter but because I didn't it turned into it implicit
forever
and this is something that magic and built into room
now I want to point something out this is not the only magic invisible
parameter
there's also one called self
all object-oriented languages most of the card
languages have a variable called this for sale
and that actually now the global that the parameter
it gets passed him to every function call
so that that function knows which objected that it's attached to
right now
the same thing happens here it's another invisibly passed in parameter to every
single map
most the time its black but
when you actually specify if the value is building
the only different yet between self and this guy is this guy doesn't have a name
it's not even called self it does help nothing it's called the default block
it's anonymous self at least has a name for himself
but this guy doesn't okay question
refile final
absolutely and we're going to see that in a minute
not right now but in a minute so I don't wanna
be labor this point forgive me for the late reply but as one pointed out
Ruby could have worked perfectly well without
invisible block it could have
worked just fine except that it would look like this
maps decided that this go down here
was prettier than this code up here it more concise and arguably it more clear
and that's the only reason why we have this weird
magic you know plumbing up
the default block which makes an anonymous parameter
past and every single map and that's weird
call yield which really means default block to call
right in just to make the language look nicer
and their other reason for that as well like there's
there are certain ways in which in with now crossed the magic wrestle
where we can make it means we can make our code look really super nice instead
of just a little nicer
but but this year place do but I
this allows us to make a method case twice
that looks for all intents and purposes like it's a key word in the language
so for instance yes right is a key word in the land
while is the key word in the language and
in is a while condition blah blah blah and
in this case they say place do blah blah blah at
it just looks like a departed language and let the language grow
right if this is Matt a program it makes it it does
make the syntax for method
approach the syntax for keywords
alright thats that the reason for it you might think that the done thing to do
but that's why they did okay
question yeah
name
no not at all I could name it twice but then I couldn't executed in the same
window
at up I could have named this that twice
fully by out I'll do that right now you up
night so now I can say place crock
do parts
hi and
I messed up but he didn't see this is why
the syntax get a little weird
I with Brazilian stuff if you don't follow the rules but
anyway there
that was just part in the net underscored it was a real
yeah
I when you let me put it this way when you call yield
if there wasn't the fault block it to run
rightfully right now take this call yielded of a block given
London in item
I have oh well thats I'm I'll of the original place but
yes like nothing no bucket
so if your gonna call yield you better make sure that the block
I'm sorry I'll
so course for the public to accept parameters just like any other block am
so here I say do with vertical bars
rather than parentheses
so here this is a block that takes a parameter
and then prince that parameter
with the string mississippi so here I am saying
yield with 0 and yield with one
and that way when I call that's this guy gets
0 print that
at 12 it because we want they want this is it became a 13 after a missed that
one
iraq for her unyielding 0 that this means I'm calling the default block with
the parameter
um and
let me show you a more advanced example a
blocks that take forever here I'm rearmament think each
and again this for underscore that's just my decision
for the name of that I didn't want to call it each as we've heard about a
method called he's on a red
but this one takes on a red so here we have a method
that takes unnamed parameter and a name with parameter
so when I call it I say for each
passing in the red and then I'm also passing in a blog
notice another little impact weird the do
have to be outside au the parentheses
you have for it
it's like a whole separate parameter left that can only have one item
I thought just going to this and a little more detail this
iterator initializes Ananda
says while that index is less than the size of the rat
grab a that item
pass it in as a parameter to this blog
and then incrementally iterator and then when we're done return self because
that's what you stop
not tell in the fifth Theoret right returning the original collection
is what he's
any questions on the flight
okay
so blocks can also return bout just like a
regular old method they can accept parameters they can print stuff they can
do calculations and they can refer
so here's an example
map I'm reimplemented map on the outside
up an array rather than on the inside other so let's look at how this works I
think I initialize
the index and I make an array that
starts out empty and then for each item inside a bit I'm gonna heal
that item life retirement but the original array
ideal that item and then I take the return value and appended to the output
arrest and then at the end I return the output arrest so
in here doesn't works just like a regular map acceptance that have names
dot map
it map that name this block
accepts and item and reverses that occurred so this works
just like a raid on map accepted map over a questions on this
okay let me up
let me out how many people understand OJ
everybody's got a guy like that that's all I can expect for
well 25 in the morning Ananya morning and be
give you another okay let me move our
this answer the was a question that where
for which is what if you didn't get past the block in the spirit of duck typing
usually you should just fail if you're supposed to be passed in a blog and the
caller didn't pass in a block you should let it fail fail fast track bail early
fell off a
is the model a run the program right
you want the runtime errors to happen because that can all you've got
it helps the programmer right it helps the caller
if the receiver failed with bad day you don't wanna
protect the caller from sup so in this case
I'm assuming not the normal case but the case in which the method
works with out with a block past 10 but also works without a blockbuster
sup in that scenario I can call a method asking whether the block was passed in
the night that is Paul
block your and usually that's use in code like this:
instead of just yielded field here good luck with your
again
this is not the standard is that reveal you should have a reason for calling
block given and that reason should be that you know your method should work
with the block or without a blog it's a decision that
an actual proactive design decision the new blog given it's not the standard
um
okay here some relatively about
stuff sometimes you wanna write a map it
that tanks entered the fault block but then saves that block away
for later use in that case you have to turn a block
into approx money inside a map it remember
you can't actually store a block inside a variable
you can only store a block in approx and then put the prop in a very
so this is what does that if you say
ampersand and then name a variable
that's just the magic incantation that says
take the fall block make a profit for it and put it in a very common p
so later on I can store P an instance variable
or this API call remember it's a proxy is a prop to call
if it's just a block and you say you the little
disorienting I know I'm sorry I see a couple people
exploding sorry as well go on for much longer maybe we'll pick it up again
after lunch
but this is just the ampersand turns
the default block into a prop you can also
per approx into the default block
on the other side right if you're a caller
and you're calling a method to take the default block but you got up
prop maybe it's something stashed away from long ago
in your variable you can't turn back into the default block by using the same
percent that means the opposite
on the outside it means turn
up rock into the default block on the inside it means
for the potluck into a prop say sense but it's just completely the opposite
okay now up
I promise this is the last flight before lunch
I've been using or Prock all over the place sprocket blah
roomie has actually two types and closures:
really have props but they also have lambert's
proximal and other almost the same thing with to
very important but very subtle and technical differences
the first difference is that in a lambda
in cares about the number of parameters that you pass it
but in a profit doesn't care so
let's say that there's a proxy if you call the prop with 10 parameters
but the problem is defined do blah blah blah and with no brainer that fine
but it with the lambda then it would care
it would actually say wrong number parameters as like a method
the other difference there's even more subtle which is the behaviour return
if you use the term return inside of a block
if that block is in approx than that return statement returns from the
method that is calling it but if the tunnel and that it returns
just from the block
and that fact there just means never use return ever in your life
ever because it's too confusing cuz you're just gonna met you just gonna
mess it up
at some point in your life if you ever use return so just don't do it
does is if statements and then and at the very last line
seriously trust me has gotten me maybe okay in a year you can start using
returning to
but thats that's one of the reasons why I recommend
not using return at all because you might be inside a block
and that his return would return from the map it or you might be inside
Atlanta and that is with his return from
do and blah and the fact that
you might not know what's going on is just part I think you're looking at him
so you can use your kernel %ah
okay anyway
so now you might have enough information that in his lap
I have one more hint which is
the silly blocks lab are silly they don't make any sense at all
they're really done there's no reason why any real program or whatever right
function
that they have that way the problem is it's really hard
to write tests for teaching blocks
the letters give you a hint about the very first one
there's a method called reverser you need to write the method reverser
that method takes in a block that block returns a string
your method leaves the call that block and then reverse this trend
and then return that so it's weird because
there's just so many things going on so many moving parts right to test called
your method
with a block your map it call that block which oh by the way it back in the past
doesn't stop returned it back to your boat and then you do more stuff to it
and return it back to the test it's just insane
the hopefully have made it a little less than them by jumping around and waving
my hands
okay everybody any more questions for lunch
okay thank you
blocks are used all over the place and route
on there so ubiquitous that a lot of people don't even know they're using
them
when they re learn Ruby they're just following the example
and they don't know that every time they say the word do
they're creating a bloc and passing it in to a map it
but that's what happened a block
is a jungle coat the concept of blocks overlaps
not entirely identical with but it overlaps with the following
set up terms they're all waterways are doing the same thing which is
taking up one trip code: and instead of executing it immediately
making it in and a little capsule love code and then letting someone else call
it a little later
so some languages do this with something a function pointer
some languages do this with runnable
like Java you can't actually yet
have a closure in Java and you can't get a proper pointer to a function in Java
so you instead you make an object that has a method name
run and that's a runnable right
arm in javascript a function
is a function pointer really it's an object but it's also serve appointed to
its up to you to find a function you can then
just set the variable 2.2 that function and that
allows you to call it later if you want um
other terms prague lambda call back
front door delegates the sharp as something up delegates
and the other a lot like fun to play alright the basic idea is
it's a chunk of code that you're not going to execute
right now your executed a little later or maybe a lot later
or maybe never another term for what this is doing is it is real fining
Co to rate by does that mean the lakes and
rate means out on the tiles to rate by means to make it into a thing
it comes from the Latin term race between think
are yes right been to think up by
it's making coated with think Ruby
has 3 different well several different on Sat
that are very closely related on but
distinct a function which I should really call a method
but really doesn't have actual functions so when everything function in really
really mean that
a method is a chunk of code that starts with debt
that gets attached to a class and executed
by a map a dispatcher a block
is a chunk of code that begins with do that gets passed
into another map it and we're gonna see exactly how in just a minute up rock
is actually an object that contains
a block so
if you want to get a pointer to a block put it into a variable
you can't do that directly in rupee you have to make a block
and then make a proper out at the block and then point to the proxy the little
convoluted I'm gonna show you exactly how that works in the
starting in the next slide but just the I just wonder for these Terms out here
there's subtle but important distinction between methods
blocks and props approx is an object that points to a blog a block at the
chunk of code
and a method is also a chunk of code but was completely different calling from it
yes
a block starts with do
curly braces a short and Purdue right
and it I don't like the curly braces it be better the curly braces didn't exist
it because curly braces are also used for hashes that a little ambiguity in
the language that's
irritating sup
every time you do as you this having to preview
every time you do started a blog so
69 as a method called times
and times executes that block this fax number of times
so if I'm I want to execute this code here
there by
I'm executing this I'm taking the sly hopeful
put a correct I am making it into a block
Rafael and then
Pines is calling that three times in a row
noticed that at the moment clear nothing is happening
it's the times method that is calling back
and activity mecca so
yes blocks can be wrapped in curly braces
a lot of people who are new to really prefer the curly braces
because it looks more like Java or C++ or JavaScript get over it
news do and rather than curly braces for the reason I just said which is that
with the curly braces there's an ambiguity
with parsing because it could be a hash
and that leads to some subtle annoying syntax error sometime
%uh indentation is also yeah it's
well depending on your editor it it technically there's no difference it's
just a simple
like do versus curly braces does the symbol for you should be able to figure
it out it's just
it's better to use do at
um we're gonna see in Justin a fewer flights
it's not actually a parameter or technically it's not a name
parameter it's an anonymous parameter and we're gonna see what that mean for
this to me
but yes it is being passed into time that's not in the normal way
so um blocks our youth for
lot the different purposes are used to solve lots a different problem
on the idea is that leave it up to the receiver the block to decide
what to do with that code and when or whether to call
so one thing that blocks are used for is called backs
let's say that you want to ask your network in library
to read in a TCP connection
and then as soon as that connection is closed take the content that
the entire can the entire packet
up love stuff that got past them by your network line
and past that into a block right so you're gonna call it later at a specific
time
but you don't want your code to wait for that to happen
doesn't I O found it might take seconds and seconds
you know but it's like eons to a computer you don't want to wait for that
I O
to come so you make a block and pass a block in
and then you trust the library call that block later when that
data is available alright
you can also use blocks for initializer lease the initial life
let's say that um I'm writing a sinatra
said after the is the weather framework that lets you set variables
arm maybe at the time that you can clear your program you don't know what the
proper value it's
so you make a block that will be called later and %um
that block will know what the proper value with at the time but it's call
alright so for initializing bank but initializing them later on
not like when you declare the program but when you're running from
so some more stuff has been set up in the meantime
they're also use for iterator with we've been using a lot
their use for separating a content
the body of an algorithm from the boilerplate around but after
loops are the classic example the generators
keep track love initializing an index incrementally and that
grabbing the value and in the case map
collecting the results into a new collection
and then after having done all that standard stuff they call your blog your
block does
the specific stuff the idiosyncratic stuff that your particular
loop will need extracts comment boilerplate stuff
inside a map it and then called back in that case does like with time that
happened
immediately but it's still a little bit later
and it still makes sense to do it it's not a call back in offensive waiting
for something happened long in the future
it happens immediately into the future but it still in the future
um it's also useful
for testing like that before block
in our spec write your specify a bit ago that's going to be run before every
single
examples back everything ok it block
by the way the if block is also a a do block it's also a
you know turns into a prop also it looks cool
sometimes your code it looks better you do things with blocks rather than doing
things in the exploded seaside
for lot stamina makeup on
yeah force or up
that's a another great example he didn't hear the
um sort for Team has a standard
comparison which is to use the flying saucer
but if you want you can pass in a customized sort blah
right the sort block would take two parameters the left side and right side
then return
you know negative 10 positive one but you can do whatever comparison you want
inside that block
sonya is a carried out sort do your configuring the algorithm
the way that you want
so let's talk about up rock keyword
crop terms a block into a variable or other into a reference
and then you can store that reference into a variable so in this case here
if I wanna say a
Prock do right in this case it's on one line so using
rates but I think prop do but I
that has made a reference to an object that when you call
that up to it will execute that block
and by call I mean say object outcall
so in this case I put it into a variable called say hi and then I say say I dot
call
and that will execute this book
and of course procs can take parameters
right blocks can take parameters and therefore proper call passes its
parameters in
block yes question
yet yeah and and I i've been
it a little technical but what's happening here is profits actually about
that
for act like a map it and then this is
the block so this if this is do but I and
that the find the block proctor that into a reference
and then meet a reference that call that executes block
so when you say call called us passes its arguments
directly into the blood
make that okay so
if I wanted to write aversion up times
that wasn't at school that a dumbed down version pot
I could do it this way I have a method called twice to do
that takes up rock which i'm naming action
could name it anything and is calling an action right now
and insider that meant that I'm calling it quite so now when I say
place do likely let me let me spell it out
I now have a variable say hi
and that variable adjusting the value that is actually a prop
so if I wanted to say say I dot call it does its thing
or I could pass that %um
as a name parameter and then placed he was gonna call it what
I'm now
I don't need to put into a variable if I don't want to
I could do that all in one go like that
place do crock do
but hi and
right so this same here to find the proper
and after that what's the proper gonna do well it's gonna do that
gonna do whatever i sat in the US
I now here comes the kicker
but the fault block so they've been called the anonymous blog for the
invisible blah
but it's called the ball
it is invisible and it gets past and just like this guy got past them
except instead of being passed into unnamed parameter
get passed into an unnamed invisible anonymous magic parameter
and on the inside a map it in order to call it
instead of saying action up call day
yield
so if I wanted to do the thing I just did a crock but using
the default block instead this is the implementation about map
and now you see why I put that weird underscored do in the previous
methodName because now i can say place
do quote up alright but
that work yeah let me try that again
place to put hi at
so this year is equivalent to death here
but this second version is much more concise
and reads moral English E right it's got that
domain-specific language thing going on here
I can actually take place do this
yeah
it is actually a block I if I had said the word prop here that would turn it
into a named parameter
an explicit parameter but because I didn't it turned into it implicit
forever
and this is something that magic and built into room
now I want to point something out this is not the only magic invisible
parameter
there's also one called self
all object-oriented languages most of the card
languages have a variable called this for sale
and that actually now the global that the parameter
it gets passed him to every function call
so that that function knows which objected that it's attached to
right now
the same thing happens here it's another invisibly passed in parameter to every
single map
most the time its black but
when you actually specify if the value is building
the only different yet between self and this guy is this guy doesn't have a name
it's not even called self it does help nothing it's called the default block
it's anonymous self at least has a name for himself
but this guy doesn't okay question
refile final
absolutely and we're going to see that in a minute
not right now but in a minute so I don't wanna
be labor this point forgive me for the late reply but as one pointed out
Ruby could have worked perfectly well without
invisible block it could have
worked just fine except that it would look like this
maps decided that this go down here
was prettier than this code up here it more concise and arguably it more clear
and that's the only reason why we have this weird
magic you know plumbing up
the default block which makes an anonymous parameter
past and every single map and that's weird
call yield which really means default block to call
right in just to make the language look nicer
and their other reason for that as well like there's
there are certain ways in which in with now crossed the magic wrestle
where we can make it means we can make our code look really super nice instead
of just a little nicer
but but this year place do but I
this allows us to make a method case twice
that looks for all intents and purposes like it's a key word in the language
so for instance yes right is a key word in the land
while is the key word in the language and
in is a while condition blah blah blah and
in this case they say place do blah blah blah at
it just looks like a departed language and let the language grow
right if this is Matt a program it makes it it does
make the syntax for method
approach the syntax for keywords
alright thats that the reason for it you might think that the done thing to do
but that's why they did okay
question yeah
name
no not at all I could name it twice but then I couldn't executed in the same
window
at up I could have named this that twice
fully by out I'll do that right now you up
night so now I can say place crock
do parts
hi and
I messed up but he didn't see this is why
the syntax get a little weird
I with Brazilian stuff if you don't follow the rules but
anyway there
that was just part in the net underscored it was a real
yeah
I when you let me put it this way when you call yield
if there wasn't the fault block it to run
rightfully right now take this call yielded of a block given
London in item
I have oh well thats I'm I'll of the original place but
yes like nothing no bucket
so if your gonna call yield you better make sure that the block
I'm sorry I'll
so course for the public to accept parameters just like any other block am
so here I say do with vertical bars
rather than parentheses
so here this is a block that takes a parameter
and then prince that parameter
with the string mississippi so here I am saying
yield with 0 and yield with one
and that way when I call that's this guy gets
0 print that
at 12 it because we want they want this is it became a 13 after a missed that
one
iraq for her unyielding 0 that this means I'm calling the default block with
the parameter
um and
let me show you a more advanced example a
blocks that take forever here I'm rearmament think each
and again this for underscore that's just my decision
for the name of that I didn't want to call it each as we've heard about a
method called he's on a red
but this one takes on a red so here we have a method
that takes unnamed parameter and a name with parameter
so when I call it I say for each
passing in the red and then I'm also passing in a blog
notice another little impact weird the do
have to be outside au the parentheses
you have for it
it's like a whole separate parameter left that can only have one item
I thought just going to this and a little more detail this
iterator initializes Ananda
says while that index is less than the size of the rat
grab a that item
pass it in as a parameter to this blog
and then incrementally iterator and then when we're done return self because
that's what you stop
not tell in the fifth Theoret right returning the original collection
is what he's
any questions on the flight
okay
so blocks can also return bout just like a
regular old method they can accept parameters they can print stuff they can
do calculations and they can refer
so here's an example
map I'm reimplemented map on the outside
up an array rather than on the inside other so let's look at how this works I
think I initialize
the index and I make an array that
starts out empty and then for each item inside a bit I'm gonna heal
that item life retirement but the original array
ideal that item and then I take the return value and appended to the output
arrest and then at the end I return the output arrest so
in here doesn't works just like a regular map acceptance that have names
dot map
it map that name this block
accepts and item and reverses that occurred so this works
just like a raid on map accepted map over a questions on this
okay let me up
let me out how many people understand OJ
everybody's got a guy like that that's all I can expect for
well 25 in the morning Ananya morning and be
give you another okay let me move our
this answer the was a question that where
for which is what if you didn't get past the block in the spirit of duck typing
usually you should just fail if you're supposed to be passed in a blog and the
caller didn't pass in a block you should let it fail fail fast track bail early
fell off a
is the model a run the program right
you want the runtime errors to happen because that can all you've got
it helps the programmer right it helps the caller
if the receiver failed with bad day you don't wanna
protect the caller from sup so in this case
I'm assuming not the normal case but the case in which the method
works with out with a block past 10 but also works without a blockbuster
sup in that scenario I can call a method asking whether the block was passed in
the night that is Paul
block your and usually that's use in code like this:
instead of just yielded field here good luck with your
again
this is not the standard is that reveal you should have a reason for calling
block given and that reason should be that you know your method should work
with the block or without a blog it's a decision that
an actual proactive design decision the new blog given it's not the standard
um
okay here some relatively about
stuff sometimes you wanna write a map it
that tanks entered the fault block but then saves that block away
for later use in that case you have to turn a block
into approx money inside a map it remember
you can't actually store a block inside a variable
you can only store a block in approx and then put the prop in a very
so this is what does that if you say
ampersand and then name a variable
that's just the magic incantation that says
take the fall block make a profit for it and put it in a very common p
so later on I can store P an instance variable
or this API call remember it's a proxy is a prop to call
if it's just a block and you say you the little
disorienting I know I'm sorry I see a couple people
exploding sorry as well go on for much longer maybe we'll pick it up again
after lunch
but this is just the ampersand turns
the default block into a prop you can also
per approx into the default block
on the other side right if you're a caller
and you're calling a method to take the default block but you got up
prop maybe it's something stashed away from long ago
in your variable you can't turn back into the default block by using the same
percent that means the opposite
on the outside it means turn
up rock into the default block on the inside it means
for the potluck into a prop say sense but it's just completely the opposite
okay now up
I promise this is the last flight before lunch
I've been using or Prock all over the place sprocket blah
roomie has actually two types and closures:
really have props but they also have lambert's
proximal and other almost the same thing with to
very important but very subtle and technical differences
the first difference is that in a lambda
in cares about the number of parameters that you pass it
but in a profit doesn't care so
let's say that there's a proxy if you call the prop with 10 parameters
but the problem is defined do blah blah blah and with no brainer that fine
but it with the lambda then it would care
it would actually say wrong number parameters as like a method
the other difference there's even more subtle which is the behaviour return
if you use the term return inside of a block
if that block is in approx than that return statement returns from the
method that is calling it but if the tunnel and that it returns
just from the block
and that fact there just means never use return ever in your life
ever because it's too confusing cuz you're just gonna met you just gonna
mess it up
at some point in your life if you ever use return so just don't do it
does is if statements and then and at the very last line
seriously trust me has gotten me maybe okay in a year you can start using
returning to
but thats that's one of the reasons why I recommend
not using return at all because you might be inside a block
and that his return would return from the map it or you might be inside
Atlanta and that is with his return from
do and blah and the fact that
you might not know what's going on is just part I think you're looking at him
so you can use your kernel %ah
okay anyway
so now you might have enough information that in his lap
I have one more hint which is
the silly blocks lab are silly they don't make any sense at all
they're really done there's no reason why any real program or whatever right
function
that they have that way the problem is it's really hard
to write tests for teaching blocks
the letters give you a hint about the very first one
there's a method called reverser you need to write the method reverser
that method takes in a block that block returns a string
your method leaves the call that block and then reverse this trend
and then return that so it's weird because
there's just so many things going on so many moving parts right to test called
your method
with a block your map it call that block which oh by the way it back in the past
doesn't stop returned it back to your boat and then you do more stuff to it
and return it back to the test it's just insane
the hopefully have made it a little less than them by jumping around and waving
my hands
okay everybody any more questions for lunch
okay thank you
Subscribe to:
Posts (Atom)