00:00:16.340
hi congratulations on making it this far
00:00:21.450
on the first day of rubyconf I know it can sometimes be a little overwhelming that start of the conference all the
00:00:27.570
excitement and everything just wanted to start off with a quick introduction my
00:00:33.390
name is Joshua Belenko if you want to follow me on Twitter I don't say that
00:00:38.460
much but I tweet under Manhattan metric and on github you can find me under jay
00:00:43.650
blank I am a software engineer for patch which is a hyperlocal news service and
00:00:50.730
it is owned and run by AOL I also happen
00:00:56.370
to be a member of the mac Ruby core team and if you grab me after the talk and
00:01:02.520
talk to me for any length of time I will probably end up bringing up matt grupe at some point I really enjoy that
00:01:10.020
project but that's not what I'm here to talk about today today I want to talk about keeping Ruby reasonable okay so
00:01:19.110
before we get into it what do I mean by reasonable well there's the standard
00:01:24.450
dictionary definition something based on good sense a reasonable price reasonable expectations and that applies to Ruby
00:01:33.660
and programming in general but I wanted to take it actually a step further and give it a double meaning and i also want
00:01:41.009
to talk about keeping ruby reasonable in the context of being able to reason
00:01:46.110
about Ruby so to start this discussion
00:01:51.509
and and by the way I should mention I I do want this to be a discussion in fact
00:01:57.360
I had a lot of material I shaved it down left plenty of time at the end for
00:02:02.459
questions comments honestly I will jump to the end and tell you I don't have a
00:02:09.000
good conclusion to this talk I wanted it to be a conversation starter so if I can
00:02:15.750
do that then I will consider it a success but I'd like to start the conversation with the story so the story
00:02:25.049
starts with a Ruby programmer goes by the name Ruby reasoner you wanted to write a class
00:02:31.610
this is a very simple class it's got two methods it's a greeter depending on the
00:02:37.890
time of day it's going to greet you with the appropriate greeting and then we throw in a little loop at the bottom so
00:02:43.590
we can do some IO present a prompt get the response present the proper greeting
00:02:50.370
by calling a method on an instance of the class so Ruby reason I wrote this is
00:02:57.630
pretty proud of it and his friend came along Peter Python Easter and his friend
00:03:03.150
Peter pie that needs to want it to help hey Ruby reasoner I got something for you I've got a library that I call fancy
00:03:10.860
pants here's what you do you call the fancified method and pass it a block whatever you put in that block we're
00:03:18.060
gonna fan safai it so Ruby reasoner said hey that's that sounds like a good idea
00:03:24.209
I'll go ahead I'll throw that in my greeter class make a fancy greeter and then go ahead and run it and this is
00:03:34.260
what happens so he goes into his directory runs his fancy greeter gets a
00:03:44.310
nice prompt said morning okay good night uh Cindy evening oh look hey that's
00:03:51.480
pretty fancy and hmm that's an interesting error let's try this again
00:03:59.720
all right let's start p on this time okay try it again just to make sure yep
00:04:05.370
okay everything looks like it's working fine that was a weird bug I don't
00:04:10.500
understand where that came from but uh
00:04:15.560
that's a really interesting error message wrong number of arguments one
00:04:22.109
for 190 what the heck is going on well
00:04:28.080
at this point Ruby reasoner a little suspicious of his friend decided to take
00:04:34.289
a look inside of that library and here's what he found so at the top we're fanta fighing things
00:04:43.699
right that's easy but then look at what Peter Python East has done to our friend
00:04:49.660
he's going to spawn a thread he's going to sleep for a random amount of time then he's going to take the block that
00:04:57.199
Ruby reasoner so naively passed to this method he's going to steal the binding from that block pick a random method out
00:05:04.370
of it and then redefine it with a somewhat reasonably looking error
00:05:10.370
message right completely redefined the class method and the thing about Ruby is
00:05:20.410
that you can do this is completely legitimate Ruby code Ruby We Need to
00:05:30.770
Talk we need to have a conversation because as programmers we very
00:05:39.110
frequently find ourselves asking this question what does it mean chances are
00:05:46.880
if you do development as a career or even as a hobby you probably end up
00:05:52.070
reading more code than you right and even the code that you do right at some point you're probably going to go back
00:05:57.500
and read it and very often when you read this code you find yourself asking what does it mean so one plus one what does
00:06:04.580
it mean well maybe it's just a math equation that's easy 1+1 2 done maybe
00:06:10.880
it's a program hmm what if we look at
00:06:15.949
this okay now that definitely looks like a program that's no math I'm familiar with so the next thing we might jump to
00:06:24.740
is okay well if it's a program what's the language right and if you tell me what language it is I can start to
00:06:30.949
understand bits and pieces I can pick out the tokens I can find the symbols right the basic tokenization parsing
00:06:39.770
style stuff that a language does but that's not really what the program means what the program means what it does
00:06:47.979
depends on the functions depends on the semantics depends on how we did value
00:06:53.030
transformations and if we take all of these together all of the information that we need in order to understand what
00:07:00.050
a program actually does you can call that an environment so when you want to
00:07:07.550
answer the question what does it mean you need to know something about the
00:07:13.580
environment that code is going to run in
00:07:18.850
okay in honor of the Ruby rogues can we
00:07:24.080
get a definition to start this off okay a couple of definitions in fact because I'm going to go ahead and use language
00:07:32.870
that's a little more sort of universally applicable which is slightly different than the language that Ruby uses to
00:07:38.750
refer to the same things so before I get into that I want to make sure that we're all on the same page so first of all
00:07:45.289
something like this a gets one that's what we call a binding okay we now have
00:07:52.190
a variable a that is bound to a value 1 we have a variable B which is bound to a
00:07:57.620
string object in that string objects values hello world right so when you
00:08:03.050
take all of these together all of the
00:08:10.580
bindings together that are in a scope we can call that an environment and it's
00:08:17.570
these bindings which allow us to make sense of code right because it's all about grabbing the bindings and then the
00:08:23.960
values the functions whatever it might be that associate with them okay so when we say an environment what we're talking
00:08:30.349
about is the collection of bindings now you're all probably familiar with the concept of a closure whether you realize
00:08:36.469
it or not any time you do an do end block and Ruby you've created a closure
00:08:41.740
and in Ruby we have this method unfortunately named binding because it
00:08:47.779
makes things a little confusing but that binding is actually not returning the binding it's returning an environment
00:08:53.830
it's returning all of the bindings right and it does so as an object and this
00:08:59.779
will call a first-class environment so environment is to first class environment the same way function is to first class function if
00:09:06.490
you've ever heard that concept for example in Python you can use functions as values you can assign them to
00:09:12.790
variables you can pass them around it's the same idea in Ruby and first-class environments right an environment is the
00:09:19.389
collection of all the bindings in a scope a first-class environment is an environment that you lift out of place
00:09:24.639
make an object and then you can pass it around and do things with it ok so with
00:09:32.050
those definitions out of the way I want to talk about what motivated me right I been very encouraged a lot of the talks
00:09:37.510
have been people pulling other sources and I think it's good that we learned
00:09:43.360
from other sources and in this case I was originally inspired to do this talk by a series of blog posts from 2009 it's
00:09:52.149
a really good blog by a guy named John Marshall he's a core contributor to MIT
00:09:57.699
scheme and the subject of the series of blog posts that he wrote in this time
00:10:03.269
referred back to the scheme standardization process so if you're not familiar with scheme scheme actually has
00:10:09.430
a standard they have a committee that gets together and agrees on a standard and every soft and they reconvene and
00:10:15.310
they revise it so they're now currently on the sixth revision which we sometimes call the r6 RS and oh yes r 7 is
00:10:24.850
currently in process so r 6 is the most recently ratified i believe so anyway in
00:10:31.510
the r6 RS ratification process of the discussions that were happening surrounding scheme one of the big
00:10:37.300
debates was on the concept of first-class environments should we have them how should they behave and in the
00:10:45.010
series of blog posts Joe Marshall does a really great deconstruction of them and
00:10:50.470
in the final blog post he comes to the conclusion he says I really liked first
00:10:55.990
class environments when I was first exposed to them at this point I believe that first class environments are
00:11:02.019
useless at best and dangerous at worse you kind of saw that at the first
00:11:08.529
example that I showed you but let's delve in a little further and understand what exactly he means by this so
00:11:17.190
in trying to define the behavior and the semantics of first class environments in
00:11:24.660
this blog post Joe breaks it down into four essential questions that you have to be able to answer about the behavior
00:11:30.540
of a first class environment okay so first should you be able to extract an
00:11:38.640
environment from any closure that is anytime we closed around a scope should
00:11:45.390
we expect to be able to get all of the bindings from that scope at any later point in time yes or no right well Ruby
00:11:54.950
Ruby says yes now keep this in mind
00:12:00.870
because we'll come back to the implications maybe the unintended implications of making this decision a little later okay next question when we
00:12:11.730
get a first class environment should all of the bindings that are in scope at the
00:12:17.430
time the closure is formed should all of them be in that first class environment you could say yeah sure everything
00:12:25.020
that's in scope when you make that closure when you get the first class environment from that closure all of
00:12:30.270
those bindings are still available or we could say no no inside your closure
00:12:35.820
you're using some of those bindings we're only going to get those right or maybe we make you tell us which bindings
00:12:44.820
should be explicitly carried across in the first class environment of course
00:12:49.920
Ruby says all of them anything that's in scope at the time you form a closure
00:12:55.740
when you get the environment from that closure they're all still valid okay now
00:13:01.650
that we've got our bindings are they going to be live right that is are they
00:13:07.290
are we just capturing the value all right so so we could say yes all the
00:13:12.690
bindings are live they're all mutable so you can query any value if another part
00:13:19.830
of the program updates the value that's reflected in the first class environment if you have a handle on the first class
00:13:25.740
environment you can go in you can redefine things or we can be more restrictive we can
00:13:30.960
the bindings are are live right so if they change somewhere else in the program then that's reflected in the
00:13:36.660
first class environment but if you have a handle on the first class environment you're not allowed to manipulate them
00:13:42.000
right or we could just make our first class environment snapshots right just collections of values at the time the
00:13:48.960
closure was created or we could do some sort of user specified version of that
00:13:56.420
of course Ruby again says all those bindings are all live there all mutable
00:14:03.110
right that's how I was able to redefine that method just by having the binding for that blog ok what happens if you
00:14:12.720
have a first class environment and you define a new binding right does the new
00:14:18.840
binding shadow any older binding right so when you redefine the method is that method redefined everywhere in that
00:14:25.260
environment maybe you clone the environment and the new binding is only
00:14:30.990
available in the clone right so behind the scenes you're duping the environment and putting the new binding in there or
00:14:36.810
maybe you just simply say look i'll give you the environment but you don't get to manipulate it it's not mutable again
00:14:45.470
right Ruby chooses one because when I
00:14:50.610
grabbed that binding and redefine that method the class which originally had
00:14:56.520
the original method so on my redefined method right so after iterating through
00:15:05.100
these four questions this is the conclusion that Joe comes to in his blog
00:15:10.590
post when someone suggests first class environments I assume they want options 1 1 1 and 1 in this variation though the
00:15:20.370
user simply cannot reason about his code
00:15:25.910
and he goes and he decomposes that a little bit he's saying essentially once
00:15:31.410
you've done that anytime you create a closure and hand that closure off to another piece of code that's it games
00:15:38.580
over you can no longer guarantee the behavior of any piece of your code Ruby chooses options
00:15:49.360
111 and one right and and again it's very understandable when you approach
00:15:56.800
these questions one at a time right why wouldn't I allow all of the bindings to
00:16:02.800
be in scope why wouldn't I allow them to all be mutable it's only when you consider them as a whole and the
00:16:07.899
implication of choosing one for all of those questions that you understand just
00:16:13.329
how dangerous this is okay so this is the problem what do we do about it well
00:16:22.720
as I said these blog posts were part of a discussion around the r6 RS process
00:16:28.269
and they eventually did come to a conclusion this is their conclusion you can find all the details all the gory
00:16:34.750
details on their website which is actually really a great read if you ever have a spare week this is about what it
00:16:42.160
will take but essentially so they've gotten a vowel method right that second
00:16:47.620
line there the third line is what we're eval and then the 4th through 6th lines
00:16:53.889
those are the environment definition and essentially what we're doing is we're
00:16:59.319
using library references so scheme introduced this concept of library references most of your code will be
00:17:05.290
encapsulated in a library and so r NR s is a library and then they have various
00:17:10.390
forms on the library so you can say out of this library only grab these bindings
00:17:15.850
right prefix all the bindings with a token so that's why in our eval line on
00:17:21.939
line three we're calling eval car and Eve are you Val cons right and not a car
00:17:27.730
and cons you can also rename you can also limit right so you can take all the
00:17:34.030
bindings except for these bindings so they have a series of forms which are really nice for manipulating these
00:17:39.630
importantly though you can't create any new bindings in an environment so you can get the environment from a library
00:17:45.520
that's fine you can get all the bindings you can use their values can't change them
00:17:53.269
another another example I wanted to bring up was objective-c and now this is a little weird probably because
00:17:59.309
objective-c doesn't actually have first class environments mostly because
00:18:04.350
objective-c doesn't have eval or any concept of eval but as I was pointing
00:18:12.600
out in the definitions a first class environment is just an environment that you are able to lift out of a closure if you have closures you still have a
00:18:19.289
concept of environments and objective-c does have closures now with blogs and therefore does have a concept of
00:18:26.100
environments for those blogs and I kind of like what objective-c does because
00:18:31.649
when you declare these variables right so here are bindings that got a name we got to create it out we got things then
00:18:37.919
we're going to create a closure right and what happens is if we reference one of these bindings inside the closure
00:18:44.330
name gets automatically retained when we do our block copyright before returning right so we retain it but we retain it
00:18:53.250
in a read-only form if however we declare something under under block then
00:19:00.509
when we reference it in the closure not only do we retain it but it's also live we can manipulate it we can mutate it
00:19:08.539
finally if we have a variable that's declared in scope but is not actually
00:19:13.919
captured in the closure it's released or garbage collected depending on your mode and it goes away all right so this is
00:19:22.230
kind of a nice you know it puts a little bit more work on the program or a little
00:19:27.659
bit more work on the compiler you have to resolve symbols and whatnot but it's
00:19:32.970
a nice I feel happy medium for how to have environments but still keep things sensible okay so so far this is all sort
00:19:44.009
of pie in the sky language design type stuff I just want to write code right
00:19:50.399
I'm not going to do anything stupid like that first file where you know I created a thread and ground to binding and
00:19:55.769
redefine things that's dumb how is this going to affect me well how many times
00:20:00.840
have you done this right you've got let's say you're doing a rails app you need a before filter and round
00:20:06.419
filter something on a name scope alright so you're gonna you're going to create a proc to use for that but to create the
00:20:15.090
proc you have a process that you have to go through there's a lot of data involved maybe you have to go out to a
00:20:20.610
service get stuff and then you have to parse a dom or who knows what until you
00:20:26.340
find the thing that you actually need and then you say but but but trust me this filter is really easy it's just an
00:20:32.429
equivalence check well guess what because anybody who gets a handle on
00:20:39.809
that proc could call binding on it and could reasonably according to Ruby expect to grab any of these other
00:20:45.570
variables they all remain live so long as your proc remains live your giant
00:20:51.179
data your big dumb all the parser they aren't going to get collected so you
00:21:02.460
thought you were safe by just passing a little tiny product mm-hmm that proc
00:21:07.710
carries a lot of baggage with it okay
00:21:14.279
now this is an honest question I said I wanted to start a conversation this is an honest question because I don't have
00:21:19.350
an answer to this but I love for somebody to tell me otherwise so let's
00:21:26.940
say you have a method that's going to return a proc you define a couple of variables and then you return the proc
00:21:31.980
and you don't refer to any of those variables inside of the proc and then later on oops and then later on you take
00:21:42.539
the proc you grab the binding and you eval to change the variable that wasn't referred to in the Prague you can do
00:21:49.559
this in Ruby um I don't know if anybody does I honestly don't even know if
00:21:56.850
that's reasonable this is a really magic you know far-reaching effects and if
00:22:05.429
you're not going to do that then we could probably remove the need to be able to do that now that said if
00:22:12.330
somebody does do something along these lines I'd love to know about I'd love to see what the use case is i
00:22:18.719
think it would certainly make me maybe a little smarter okay lots of talk about
00:22:27.519
first class environments don't want to leave you on a sour note so let's finish up by playing a game we're going to play
00:22:34.719
capture the flag hear the rules you need to provide a class class needs to have a
00:22:41.199
method met the name is flag I'm going to try and capture it class must also
00:22:46.719
contain a class constant called base that constant has to be a prog has to be
00:22:52.629
an instance of a proc object you can only define one class you cannot require
00:22:58.179
a load other source files you can't do any funny stuff no funny stuff just a class with a constant and a method and
00:23:07.769
this is the game we're going to play so you're going to pass me the name of your
00:23:13.179
class on the command line I'm going to require its file and then I'm going to create a new instance of my game class
00:23:19.119
with your class first I'm going to check make sure you're not cheating make sure you've got that class level constant and
00:23:25.690
that it is a proc we're going to play the game I'm going to use that proc to
00:23:31.539
grab a binding first class environment and I'm going to eval a redefinition of your flag method and then we're going to
00:23:39.639
call that method see if I captured your flag okay blue team you're up blue team
00:23:48.309
went for the straightforward solution I got a method I got a product what
00:23:54.759
happens so we run the game ah captured that proc
00:24:11.379
carried around a first class environment which exposed the entire internal workings of that class so the game was
00:24:17.649
able to just redefine methods willy-nilly whenever you like Red Team
00:24:23.590
Europe Red Team a little fly about this
00:24:29.429
red team is going to create a class level method called hidden base then
00:24:35.320
he's going to use the method method to get a handle on that method keep them keeping up here get a method and then
00:24:43.149
call to proc right this is just method to proc if you've ever done a map or in
00:24:48.250
each done that ampersand colon you've used method to Prague okay so we're just
00:24:53.590
writing it out here just method to proc when you do that base is still an
00:24:58.899
instance of the class Prague right what happens when we play the game
00:25:10.870
aha red team wins but why why did that
00:25:17.320
work right why did calling the method method to create a proc from a method why did that work when just simply
00:25:23.530
creating a proc didn't let's send in a spy see what's going on sir spy is real
00:25:30.340
simple our spy is just going to grab the base and instead of trying to redefine
00:25:35.680
things in an eval we're just going to query what what is self and what is the class of self okay so if we do this for
00:25:48.090
the blue team self is blue team the
00:25:53.230
class right and it is an instance of class right that they just exposed their entire class through the binding red
00:26:00.790
team on the other hand that proc that they passed its environment says I am an
00:26:07.840
instance of a method class my class is method not class ah tricky but Ruby
00:26:20.140
actually has two concepts of first class environments when you think about it this way right because the method method
00:26:26.679
in a sense gets an environment by by using the method method and calling to
00:26:32.980
proc so method to prompt gives you a prog right that proc has an environment but it's not mutable it's not even
00:26:40.740
accessible really by calling binding you're getting some method object and
00:26:46.090
method class but when you take that method to prague prague and pass it to
00:26:51.130
another thing you can call it and it has its entire environment to execute its call right so if you do something like a
00:26:57.220
through z dot map up case right method
00:27:02.530
to proc on up case it's taking that up case method and carrying around enough environment to know that this is a
00:27:08.230
string that we need to call the string up case on it right so so method objects
00:27:16.720
are a kind of if you look at them sideways they're a kind of first class environment that's far far far more
00:27:23.800
restrictive then the first class environment you get my calling binding on a prog so Ruby
00:27:30.800
kind of already has both extremes so I
00:27:39.010
told you I didn't have a really satisfying conclusion because I don't really have a patch to to cure the ills
00:27:44.990
of Ruby's first class environments this is a difficult problem and it's going to take a lot of thinking and a lot of work
00:27:51.440
and looking at the internals to see how this how this should be resolved but I
00:27:57.530
think what we can at least learn from looking at this initially is that the first class environments as they exist
00:28:03.620
in Ruby today they're kind of dangerous they're kind of really dangerous it means that once you pass a proc to any
00:28:10.910
other method you can no longer reason about your code and not just you right I
00:28:16.840
trust you're all good programmers you're not going to do anything like that first library class that I showed you but it's
00:28:24.950
not just you that we need to worry about right the Ruby runtime can't trust you
00:28:33.620
there's no mechanism you know you can you can hand me a piece of code and say trust me I didn't do anything ridiculous
00:28:40.900
but the Ruby runtime has no way for you to say Ruby trust me you don't have to
00:28:47.030
get all of those bindings I'm not using them I didn't do anything silly like that right maybe we need to give the
00:28:53.960
Ruby runtime a way to understand that we aren't trying to do anything silly we
00:29:02.000
also kind of have an eye to a way that we might be able to get to something
00:29:07.490
more sensible with the method class right in fact i think if we found a happy medium it would benefit both
00:29:15.650
first-class environments on prox and also the method objects that you get from calling the method method because
00:29:22.490
currently when you call the method method right you can turn that method into a proc you can unbind that method
00:29:28.280
from its class from its object when you unbind that method the only thing you
00:29:34.790
can do is rebind it to another instant of the same class or subclass of that
00:29:40.909
class now let's think about this unless you've dynamically defined that method after instantiation you're saying that a
00:29:48.379
method that I declared in a class I can pull off of an object and put on to another object which probably already
00:29:53.450
has that method or I can put it on a subclass which probably also already has that method not very useful what I
00:30:01.999
really like to do is be able to grab a method from one object put it on a completely different object but I can't
00:30:08.989
do that currently because the method object has this severely tightened down
00:30:14.509
first class environment concept right in fact I think if you look under the hood there is no there isn't actually an
00:30:21.049
environment there there's simply a name of a class and method object says don't bind me to anything that's not this
00:30:26.330
class right so I think by rethinking and
00:30:32.470
formalizing right because the other thing is is I don't think anybody intentionally decided that first class
00:30:41.149
environments and Ruby should operate this way I think it's a consequence of sort of iterative design of a language
00:30:47.389
like I said when you take each of those four questions one at a time it seems
00:30:53.480
reasonable to choose option one for each of them it's only when you look at them in aggregate that you realize what the
00:30:58.850
danger is and just how much trouble you can get in so I think what happened with
00:31:05.840
Ruby is that the language naturally developed and evolved to have first-class environments of a variety
00:31:13.070
that are very dangerous and maybe it's time that we take another look at first class environments it would mean that we
00:31:20.539
could make more sense of our code it would mean that we could optimize our code there are a number of optimizations
00:31:26.509
right part part of the material that I had to cut out of this talk was a deep dive into method call and what actually
00:31:34.309
happens when you call a method in Ruby when you look at that right that's a very long function c function if you
00:31:40.429
pull it up in see Ruby and there are all kinds of checks was the class redefined
00:31:46.220
was metally defined did somebody move my environment did somebody move my chair right there's all this paranoia
00:31:51.890
that ruby has because everything is so flexible right if we can remove some of
00:31:57.110
that by making things slightly less flexible then we could potentially optimized code way more than we do
00:32:04.370
currently okay well that's all I got
00:32:10.390
oops I I did put the code snippets I
00:32:16.310
presented up on my github account in case you wanted to play around with them the blog that I mentioned Joe Marshalls
00:32:22.250
blog very excellent blog he doesn't post frequently but when he does they're almost always gems he has a really good
00:32:28.610
series on persistence to that's at fun called up blogspot com it is all scheme
00:32:34.100
so there is that but and then I actually put up a couple of public links on my
00:32:40.730
pin board under the tag keeping Ruby reasonable it's all of the blog posts
00:32:46.040
that inspired this along with some of the r 6 r sr 5 RS the documents some of
00:32:53.180
the discussion and a couple of other resources if you want to get into this and learn more and with that i would
00:32:59.120
gladly take any questions and hopefully start a discussion
00:33:09.049
the difficulties in ashburn piloting things like I noticed about us and our
00:33:14.460
sins are what really did is it that's a short ability to like talk much where is
00:33:20.009
having dynamic environments and so I think what happened after our secure ms
00:33:27.090
was in a lot of people to write deficiency fireworks which in turn could compile interpreters and so effectively
00:33:35.009
the last email to your petition given that first class of Martin's over here
00:33:41.850
so open I wonder if anybody in the
00:33:48.259
difficulties of effective writing eilers well ok so so the question is regarding
00:33:54.929
the Redmond compilers and how difficult
00:34:01.169
it is given the openness so i can give you the mac ruby perspective um Matt
00:34:07.169
groovy didn't have the binding method for the first two years of its life even
00:34:13.379
today if you try I'm sure you'll find bucket loads of bugs and every time i
00:34:19.859
ask allah ralph was the lead developer on macaroni what about binding he wouldn't talk to me for a week um you
00:34:30.629
can do a lot without the binding method right we got two years into mcnamee we were developing the actual production
00:34:36.720
software so much shipped on lion um never having to touch binding I actually
00:34:43.169
was talking to somebody who wasn't familiar with rubiane i mentioned that i was giving this talk and they asked me
00:34:48.899
about the topic and started going into first class and where's why do you even need that I thought about it why do we
00:34:56.639
even need that the most obvious thing I can think of is er be a templating
00:35:02.640
language were to get so in order to get self of Papa jizz here's right IRB but
00:35:11.099
even IRB you can do without so the other thing that you mentioned was eval and I
00:35:16.410
guess mention that evil existed in scheme long before first class environments because
00:35:21.490
you don't actually need first-class environments for email right you can simply decide that eval will work in the
00:35:28.660
current lexical scope which is the way that evil normally works normally when you call eval in Ruby there is a hidden
00:35:36.750
argument that most people never bother with which is binding which if you don't specify the button it just as the
00:35:43.630
current binding right the current lexical scope is what your eval is using right so eval is different from eval
00:35:52.360
with first-class environments eval with first-class environments implies that
00:35:57.970
you can take one piece of code and execute it as it were in a completely different spot in the program right so
00:36:07.450
many languages without first class environment have rebels yes I RV can do some really fancy things with the first
00:36:16.690
class environment and by the way I mean obviously there was a desire to have first-class environments right it's not
00:36:21.910
that there are no benefits it's just a matter of when you weigh the benefits to
00:36:27.130
the wrist and the openness that a first class environment presents what it does
00:36:33.670
to the ability to form compilers what it does to the ability to reason about code optimize yeah you really seriously got
00:36:41.170
to think about whether or not it's worked out and in terms of writing Ruby compilers uh so i'm pretty sure Rubinius
00:36:50.740
I know Mac Ruby does JRuby does um they'll end up being bytecode compilers
00:36:56.500
and somewhere in the bytecode ends up being a way to for example in Mac movie
00:37:03.370
if you include eval and a string we just put the string in the data section of
00:37:09.970
the object file and we reference it from the bytecode and we spin up a full
00:37:15.550
version of the mac Ruby interpreter and just interpret the code line which is
00:37:21.460
unfortunate right it would be nice to be able to that more efficient but because we we
00:37:27.730
will have no guarantees on the environment at the time you call eval what you're passing in the only way we
00:37:34.119
can do it is to actually run it in situ oh yeah yeah there were a lot of changes
00:38:15.090
it's a little difficult specifically because the scheme community is a bit of
00:38:21.700
a esoteric entity within itself there was a lot of contention around the r6 RS
00:38:28.300
for example MIT scheme just flat-out declared they are not going to implement it they're gonna stick with our five RS
00:38:35.020
and wait and see what happens in the future seven is hopefully addressing a
00:38:40.900
lot of those concerns I'm part of it also is that the skin community I mean
00:38:47.050
actually we could probably learn something from the scheme community because they've always focused on standardizing the smallest subset of
00:38:53.680
scheme that you can basically equate languages and say this is a scheme this
00:39:00.130
is a scheme this is a seat until six right and this is the contention that a lot of people came up with six is six is
00:39:07.450
the first time that they actually for made into trying to standardize the library and there was a lot of contention about whether or not that was
00:39:13.240
a good idea whether or not you know you were doing
00:39:35.490
yes first class yes I will grant you
00:39:42.580
that however it occurs to me that first class environments encapsulate a lot of
00:39:50.380
other issues which people would bring up as other reasons that MRI is slow for example a lot of the confusion
00:39:56.920
surrounding constant resolution is somewhat related in that there are
00:40:04.810
multiple paths to a constant right because you've leave so many nodes live
00:40:10.930
and you can basically ok so i guess i should explain what i mean when you have
00:40:16.780
a constant right when you declare a constant that constant has a certain scope and later on in your program when
00:40:22.810
you want to get that constant you have to come up with a way to refer to it well Ruby actually has a myriad of rules
00:40:29.830
on how to get at those constants there's just a ton of ways because basically
00:40:35.460
constant resolution and Ruby is a matter of walking the nodes where different
00:40:40.570
scopes are defined until you get to the constant that you're looking for and if
00:40:45.790
you walk the nodes in a certain way and don't find the constant then you go back and walk them in a different way to try
00:40:51.160
and find the constant and you go back and you walk on it differently what this means is that so long as those nodes are
00:40:57.370
main live and mutable you have to walk them every time to find this constant you can't do constant folding for most
00:41:03.250
practical purposes now I know Charles nutter has a really neat thing that he's done with invoke dynamic to make it
00:41:09.610
slightly reasonable to constant fold in JRuby and that's a great advance but the
00:41:16.420
bottom line is is that there's still way too many ways that you can screw up that
00:41:22.110
optimization and you're back to walk in all the nodes to find your consequentially so yeah first
00:41:29.089
class environments are not the only reason that Ruby is slow but I feel like addressing it would be a good first
00:41:34.309
foray into figuring out how to make be more efficient both it's really the same
00:41:52.640
thing the advantage that humans have is that they're humans and they can
00:41:58.160
converse and human languages and say no seriously I didn't do anything funky
00:42:03.770
with your environment but I've seen playing places where people unintentionally do funky things with
00:42:10.430
their environment screw things up and those bugs are the hardest to find because you know the first thing you
00:42:16.039
want to do when you hit a bug is find out where where did it occur and I don't
00:42:21.799
know if you noticed but that first example that I ran right when it through
00:42:27.200
that exception if you looked at the back trace of that exception it looked like
00:42:32.720
it was occurring at the original method definition in the code so you would
00:42:39.529
stare at that all day and never understand why that method through that
00:42:45.950
exception you have to walk through all of the other code to figure it out and
00:42:51.799
those are the worst bugs to fix the ones where you really seriously have to investigate the entire source base to
00:42:59.299
figure out what's going on so from the user perspective yes but also from the compilers respective compilers can run
00:43:07.339
algorithms they can run heuristics they can speculatively optimize things but at the end of the day if the compiler can't
00:43:14.930
be confident in the conclusions that it's reached about a piece of code it's going to be slower than if it was
00:43:21.859
confident but piece of code another question
00:43:36.859
good
00:43:57.820
right so yes so the comment was that bindings are not the only reason that Ruby cartas Ruby code is hard to reason
00:44:05.390
about or the first class of artists and that is true right I mean if you look at languages like Haskell where you have a
00:44:11.869
proof system built into the runtime or actually compiler yes there is a lot
00:44:18.530
that you could do to do more reasoning about Ruby code I guess what I was
00:44:25.010
trying to bring a bring up in terms of first class environments is that there's
00:44:31.040
a spectrum of how much reasoning you can do about code right a classic example in Ruby is it's very difficult to determine
00:44:37.940
whether something is a method call or a variable reference right if I right Who
00:44:43.070
am I calling the foo method or am i referring to the foo variable right that's an ambiguity that's based into
00:44:48.950
the Ruby language and I think some would argue that that's an acceptable ambiguity it allows me to not have to
00:44:54.380
put / ends on all my function calls and maybe I like saving two key stories or
00:44:59.780
maybe like the way that coat hooks it does look that I love the way reveals so
00:45:05.300
there is a scale of how much reasoning you can do about your code I think what
00:45:11.300
I was trying to point out with first class environments his first class environment put us at the bob you cannot
00:45:18.109
know anything about your code like let's not even worried about type inference
00:45:26.270
let's not even worried about you know any sort of proof system with first class environments running around you
00:45:32.990
can't guarantee anything
00:45:38.559
so I was looking for mothers how can we take some so I guess the the thing so
00:45:47.809
Matt my man Eddie has a really great blog post that he did recently where he was looking at a dsl that he developed
00:45:53.989
and he was using prox in the dsl and he
00:45:59.059
did some benchmarking and he found out that the the prox were not really a good
00:46:05.479
choice of the way that he was using them it's not great so really I guess the more or less story is be careful when
00:46:12.229
you use progress it's not just first class environments there are other things about props that make them kind
00:46:18.799
of dangerous the other thing that you can do is for example if you find yourself doing anything like this where
00:46:24.380
you're hoping to pass along a little bit of code to be executed later right and
00:46:29.839
you know that you don't need any of these references what you can do here is right before the proc return you could
00:46:36.709
just nil out all those variables and then they would all get collected so
00:46:43.130
that would that would be like if you want to take something practical away from this when you're done with a
00:46:49.910
variable if you're going to return a prog nil adapt or move it to another
00:46:56.900
scope or yeah put it into the other stuff where you can't reach it from the
00:47:02.509
products yeah that's the other problem
00:47:07.849
is that you sometimes close over scopes when you don't intend to
00:47:13.080
yeah yeah self is and and define method
00:47:19.820
if you've ever been to mark the method right right the same method using death and define method and you don't run it
00:47:26.670
the same well you could that would be
00:47:38.460
very interesting so okay I think we're
00:47:43.500
probably way out of time so thank you all
00:48:23.520
you