So yesterday I got to look around our Twitter account and see what was going on. I saw some speakers doing some last minute beach time slide updating. I talked to some speakers. They hadn't updated any of their slides or looked at any of their slides. I talked to one speaker who freaked out that he thought his session was 30 minutes long and didn't know what to do. And apparently instead of cutting down slides, he was adding more slides. I'm not sure that really works out very well. But I did run into something special from our keynote speaker, Mr. Patterson. So I was wondering what this meant and what we could really do about this. So I'm guessing he must really want spam or he's a really big fan of spam. So what's the situation here? Did you get to eat spam yet? No, that's great because we have one for you right here. Yes. Thank you. So if you can come on up and I'll give you this spam moussivi. Awesome. Thank you. And since this is your time in Hawaii, you also have a delay. Thank you. Yes, spam. This is Hawaii.  All right. Who's ready for day one? Who here wants me to get off stage and let this guy talk? All right, let's do that. Okay. So I'm going to talk about Rails 4 and the future or as I like to call it, Rails 4 for you and me. I was told that you're not supposed to introduce yourself when you're giving keynotes but I'm not very good at speaking. So I'm not going to tell you my name is Aaron Patterson and that if you want to follow me on Twitter you can. So I'm just, for the record, I'm not telling you this stuff, okay? I'm not introducing myself. I just want to say hi to everyone. First I got to start out and say thanks to some people. Well, I got to say thanks to my employer AT&T. Without them I wouldn't be here. So thank you. I also want to thank the conference organizers for having a conference in a really awesome place. I've never been to Hawaii before. This is my first time. So I'm super excited and the reason I'm really excited about it is because I love spam. So thank you. Also my favorite TV shows are here like Dog the Bounty Hunter. I was looking around for Dog the Bounty Hunter last night, I couldn't find him. And also like Magnum PI, I love Magnum PI as you can see by my mustache. If you don't believe me that I love Magnum PI you can see like I name my computers after Magnum PI characters.  So he went first and then he came back and I went over to the bathroom and I got there and I looked out on the floor and there was a $5 bill on the floor right in front of the bathroom. So I was like, well, he must have dropped this money.  So I go to the bathroom and come back and they're collecting donations on the aircraft for breast cancer awareness and if you donate money then they enter you into a raffle and you can win some prizes on the airplane. So I sit down and the guy says to me, this isn't mine. I didn't drop this. And I was like, okay, well, it's not mine either. And he's like, why don't you donate it to the raffle thing? So I said, okay, that's a great idea. Don't know whose money this is. We'll put it to a good cause. So I donated it figuring, well, I'm not going to win any prizes. It's just going to get donated so that will be great. And then of course I win. And I was also the first one to choose the prize like I could have chosen a bottle of champagne or like chocolates or all this stuff and I didn't know what to do because it wasn't my money. So I picked chocolates, but now I feel like there's an imbalance in the world. Like I have these illegal chocolates. I shouldn't have them. So I don't know what to do with them.  But I guess it's too late now. Anyway, I don't know if you can tell this, but I am insanely nervous on stage. And one of the things that I have to do to comfort myself is I told a friend of mine, well, I get super nervous. What should I do? I love speaking, but I'm so nervous on stage. What should I do about it? And he said to me, well, when you're on stage, you just need to think to yourself, what would Freddie Mercury do?  Now, most speakers think, well, it's common knowledge. Just imagine the entire audience is in their underwear. Well, actually for me, it's the opposite. I imagine that I'm on stage in my underwear. I figure that's what Freddie Mercury would do. Anyway, I also want to tell you I have a cat and his name is Gorbachev Puff Puff Thunder Horse. That's his full legal name. We call him Gorby Puff though. And I love him a lot. I love him a lot. And I thought he's the first cat I've owned and I thought owning a cat, it's going to be 99% fun in the sun. We're going to go riding bikes together, get ice cream, go swing in the park and do all the stuff. But it turns out that basically 99% of the time, he's sleeping. So I try to take pictures of him, but the only pictures I can ever get are him yawning. He's about to go to sleep all the time. And it just kills me. I like. So we never get to go bike riding together. But anyway, if you want to see more pictures of him yawning, you can follow him on Twitter. So all right. So we're going to talk about Rails 4 for you and me. We're going to look at some features of Rails 4 and we're going to talk a little bit about the future of the web. Now despite my looks, I'm not a television psychic. So I can't tell you exactly what's going to happen in the future, but I can talk about where I think it's going. And basically the point of this talk is to get you guys, get ideas flowing among you guys, talk about where I think we're going, and then hopefully have you guys pick up the ball and run with it. So what we're going to do is we're going to look at some behaviors in Ruby and then we're going to look at some changes in Rails and then we're going to look at how these changes in Rails interact with the web. So we're going to start pretty close to the server and then move our way out to the client. So the first thing I want to talk about is concurrency in Ruby or parallelization. And I like to shorten this down, but I'm not super good at spelling, so it's p56n. That's how I shorten it up. It's possibly misspelled, I'm not sure. And I know most of you probably know about this or at least heard about this, that MRI has a GIL or what is known as a global interpreter lock. And this lock prevents concurrent CPU execution. So what that means practically is that we can't schedule two threads to run on two different CPUs at the same time. So if you want to have an interpreter that's able to do that, I suggest you look at alternatives such as JRuby or Rubinius. These are GIL-free alternatives. But I want to share some good news. And where is Charlie? Is he here? No, he's not. Jerk. Anyway, I want to share some good news with you. The GIL was removed in 1.9. So we can be super happy about that. But I also want to share some bad news with you next, is that the GIL was replaced with a GVL, which is exactly the same thing. It just has a V instead of an I. So if you go read the source code to 1.9, you'll see many references to GVL. And that's what that is. So this leads to the question, well, is MRI useless for P32N?  Your programs don't actually work. It just seems like they work. I don't know if there's really too much of a difference to be made. If your program seems like it's working, does that mean it's actually working? I think this is a question probably left for philosophers, people smarter than me. But anyway, what I want to do is I want to take a look at the impact of the GVL on MRI and see what that means to us in our day-to-day Ruby basis. And the thing that I like to use for looking at how the GVL impacts MRI is the use of the Fibonacci sequence. And the reason I like to do this is because I used to work in online advertising. I don't know if any of you guys have worked in online advertising, but online advertising is basically all about doing Fibonacci sequence calculations. So that's how they decide what ads to show to you. So of course, how many lies am I telling you this presentation? So of course, I like to use this in all of my benchmarks because of online advertising. So all right, run this on my machine, notice that says Higgins. I'm not lying about the Magnum PI. I run this and it takes about 5.7 seconds on my machine.  I need to be able to deliver ads faster. So I'm going to calculate my Fibonacci sequences in threads. So I've got four CPUs on my machine, so I'll throw up four threads here and calculate the Fibonacci sequence, hopefully all of them in parallel. And then I run this and it takes exactly the same amount of time, just about the same amount of time. And the reason is because time spent in the VM can't be done in parallel. So hence it's called a GVL or global VM lock. So anytime, whenever we're spending time in the virtual machine, that can't be executed in parallel. So what do we do about this? Things to fix this are people use JRuby or Rubinius if they want to actually have threads scheduled on multiple CPUs. But very common is what people do is just use multiple processes. And this is what you're doing when you're running your Rails application with say like Unicorn. Right? You're running a whole bunch of different Ruby processes so that you can actually handle concurrent requests on multiple CPUs on your machine. So just run multiple Ruby processes. So I want to look at another thing and this is an example of using a slow web server or a slow web service. We have a slow web service here because, again, basically online advertising is all about Fibonacci sequences and slow web services. So if you look at this, it's just super simple. Just prints out hello world. But the important thing is like we have a sleep here for half a second. So each request takes at least half a second to complete. And we run our client here. We have a client and we just say, okay, well, go fetch some data from the server. And we run this and it takes a little over two seconds and this makes sense because we're doing four requests each at half a second, takes two seconds. Not surprising. So we're like, well, we totally forgot about the previous thing, the previous knowledge about the GVL. We've just somehow we forgot about it, haven't had our coffee yet. So we decided to throw this into threads. And then we remember, well, this isn't going to work out for us because we can't execute anything in parallel. So what is the point of doing threads? Well, we run it anyway, but it actually takes half a second this time. So we were able to execute this, make requests to this web service, even in MRI, using threads and decrease the amount of time spent. Now, how did this work? Like how did this work inside of Ruby? Well, there's different things, there's different methods inside of Ruby where we know where the interpreter knows, well, okay, nothing can actually happen inside of the Ruby VM while we're trying to read off of a socket. We can't actually execute anything right there. So what we're gonna do is we're gonna release the GVL, let other threads execute on the CPU while we're waiting for data off of the socket. And then once we actually get data on the socket, we're gonna acquire the GVL again and enter back into the Ruby VM. So there's certain things that we can do this trick with which is any type of IO operations. And for those of you who are writing C extensions or looking into MRIs and turtles, the function you actually wanna look for is this function RB thread blocking region. This is the thing that actually unlocks the GVL. So you give it a function pointer, it'll unlock the GVL, call your function, execute some code, and then reacquire the GVL. And you can actually use this function when you're doing things like, for example, cryptography. Where you're doing things that are like CPU intensive, but you're never actually gonna be in the Ruby virtual machine. You're just doing computations in C. Then you can use this function as well. So what does this mean? What does it mean that we can actually run things in parallel on MRI? Well, I mean from an advertising perspective, obviously it means that we need to build Fibonacci as a service. Or what I like to call F-Faz, which is the next big thing. Yes, I'm looking for investors now, so come talk to me after. I promise to use your VC wisely. But really what it means is it means two things. It means that, number one, a block to VM is a block to VM. It's always a block to VM. Block to VM is a block to VM. So if you find some library that's like, well, we're using fibers to make your stuff like super duper fast and in parallel, it's actually probably a lie. It's just adding complexity to your code. The VM can't actually magically switch out when you're using fibers. So the more important thing is that threads matter. If you're doing IO on MRI, threads matter. And I'm guessing many of you have web apps, probably. Or at least some of your code does IO, I'm guessing. It would be nice if we didn't have to, but you know. So even on interpreters that have a GVL, using threads is important. And I think that web servers like threaded web servers like Puma are going to become more important. Because while we're doing IO operations, we should be able to serve up CPU operations at the same time. So having solutions like multi-threaded servers that are running in multi-process should become more popular, I would hope. Or using gil-free solutions like JRuby with just a straight up threaded server would also do as well. So the next thing I want to talk about is thread safety in Rails. And I'm going to talk about some of the changes that we've made in Rails to make it more thread safe. And what it means to you as developers, and what we had to do. I want to talk about common problems we ran into and how you can fix those things in your applications. So the first thing that we did in Rails was we deleted config.threadsafe. So we didn't actually remove it, it's actually still there, it's just a no op. So you can still call it and it'll probably output a message saying something like cool story bro, you're already thread safe. So the question is, well why should we delete this? Why should we delete this configuration option? Like what is the point of deleting this? Why do we want to delete this? Well, in my opinion, we should probably just always be writing programs that are thread safe. So if that's the case then it boggles my mind why we would have some particular flag that's like okay, now you should run thread safe. Or now you should run thread safe. And if you think about it, so does that mean like are there branches in the code where it's checking okay, is it thread safe now? Are we thread safe? If we are then let's do it in a thread safe manner.  It just doesn't make sense to me. So this is my opinion why we should remove this configuration flag is just because it's ridiculous. But the other thing is that it simplifies the Rails code base. So we can actually find those branches where we're saying, okay, well now let's do this in a thread safe way or let's not do this in a thread safe way and we can eliminate those branches and actually simplify the code. So is it safe to remove thread safe? The next question you might be asking and in order to figure out the answer to this question we need to understand well what did thread safe do? So let's take a look at that. What thread safe does is it set these four different configuration options inside of Rails and we'll look at what each of those are. But the first thing that I want to say is that loading code isn't thread safe and I put a star there because it's not actually true. Require is now thread safe on trunk. I think require has been thread safe in JRuby for a while. I'm not totally sure about that. But the thing is it doesn't actually matter because well, I'm sure many of you have seen warnings that are like circular require is considered dangerous. You might have seen this somewhere. And the problem with that is that, well, if we decide to take out a lock and do this, do these requires, a circular require can lead to a deadlock, right? And we don't actually want to, it would not be very fun if when we're booting our Rails application it just deadlocks. I wouldn't be too excited about that. So in Rails, we just treat all code loading as not thread safe. And we say, okay, we're not gonna do any sort of threading now.  So, configuration options. The first one, we enable preloading frameworks. And what this does is it says, okay, we're gonna load all of Rails into, we're gonna load up all of Rails. Now, I'm not sure, this Rails is typically lazily loaded if you don't have this set, which means, okay, I'm gonna reference, when I reference ActiveRecordBase, then it's actually gonna load up ActiveRecord. And it also does this for all of your code, so it won't actually load your model files until you actually reference that constant. And why the framework and your code is treated differently, I don't actually know why, but this is one of the configuration options is, okay, we'll do it this way. The next thing we do is we enable caching classes. This makes sense because, well, if we're gonna load up all of our code, we don't wanna be reloading. We know that it's an axiom that loading code is not thread safe. So we don't wanna be reloading code in production. That would not be a good thing. We lead to deadlocks, our app dies, not super excited about that. The next thing we do is we disable dependency loading. And this is the option that says, okay, when you reference a user constant, like an application constant, like your user model or whatever, we go load up that user model. So we disable that because we're hopefully preloading all of your code. So it doesn't make sense to go out and find these constants because hopefully we've already found them all. We're done. Now, the next thing, the next option is we enable concurrency, we allow concurrency. This is my favorite option.  So what this option does is it actually removes a middleware called racklock. What racklock does is it wraps up your requests. So it says, okay, when a request comes in, we're gonna obtain a lock. So thread one comes in, it gets a lock, it reads from the socket, and we enter your Rails application and we try to process stuff. Well, let's say we have a second thread that comes along. It tries to obtain that lock, but thread one already has that lock taken out, right? So thread two just sits there until thread one is done. It writes to the socket, releases its lock, and then thread two can say, okay, it's my turn. So it goes through the entire process and releases the lock finally. So with things like multiprocess setups, like if you're running Unicorn in production, racklock doesn't make any sense because you only have one thread in each process. You only have one thread processing a request, so what's the point of taking out a lock? If no other thread can acquire that lock, then what is the point of the middleware? So if you're using a multiprocess setup, this simply just adds overhead to your application. So the other problem is that if you noticed in the way that we process requests there, it only allows one request at a time. So if you're running in a multi-threaded server, all of a sudden you can only do one request at a time, so what is the point of running the multi-threaded server? If you can only do one at a time, you boot this up, you boot up your server and you're like, why is it only running one request at a time? I guess I need to start up multiple processes of my threaded server and you're like, why is this happening? Well, this is why. So in the best case, it's extra overhead. This is our best case scenario with rack lock. In our worst case, we can only process one request at a time. So I think that options like this, or default configurations like this, is one of the reasons why nobody chooses thread-safe servers. They start up their thread-safe server and they're like, why, I can only process one request at a time, this web server sucks. I'm gonna move on to something else. So what is the impact of removing thread-safe bang? We're just gonna say, all right, we're gonna enable this for everything. It doesn't matter anymore. The impact is that boot time will probably increase. So boot time and production will probably increase because we're gonna preload all of your code.  Now it just happens all up front. If you're a middleware, so you should have a slightly smaller stack size, maybe one or two stack frames. But it is slightly smaller. Multi-proc servers should stay about the same. So after you boot up, you should see about the same profile, speed-wise, and threaded servers will just work. So now we don't have that anymore. Oh, that reminds me. There was a survey out that was like, who, Rails survey, what web server do you use? Like, oh, who has the most popular web server? And what I think is funny is that I don't think Web Brick was listed anywhere in there. I don't know if you guys know what Web Brick is, but it's the web server that comes with Ruby. And if you don't specify the web server that you use when you deploy to Heroku, you use Web Brick. I think many people don't know that. And the other interesting thing about Web Brick is it is a threaded web server. So I'm pretty sure it's the first threaded Ruby web server. Anyway, so fun fact, that survey is probably wrong because I'm guessing there are many people who have pushed applications to Heroku without specifying a web server and they're using Web Brick in production. Woo, Web Brick! Anyway, removing thread safe wasn't the only thing that we had to do to fix, or the only thing that we did in Rails to support threaded applications. We actually had to fix bugs where we were doing unsafe things. And what I wanna do is look at some of the common scenarios where we were having bugs in Rails and what we had to do to fix them. And hopefully you can use this, look for these types of issues in your application too and fix threading bugs in your Rails apps or your gems. Now, I guess we're kind of lucky because 100% of our bugs were race conditions around caching. So we didn't actually have any deadlock situations which was pretty nice. So what we're gonna do is look at a few different caching race conditions and what you have to do to fix them. So people don't seem to notice this, but or equals is a form of caching. So you're caching the right hand side of the statement, you do some calculation, do or equals and assigns it to some instance variable. We're lazily initializing that instance variable. And the way that this is a problem is we say, okay, we have a check then act, race condition. The thread comes in and it says, okay, is that instance variable nil? If so, let's calculate it, set it and return it. But the problem is while we're calculating that value, another thread could come along and be like, hey, is this instance variable nil? And it says yes, it is nil. So now you have two different threads doing the same calculation twice. Now one thing to note is that this particular operation is only dangerous when you're sharing it among threads. So if you see this happening, if you're sharing this data among threads, that's really where you have to worry about it. And what you can do is you can eagerly initialize it. And of course I'm using Fibonacci sequence here, as I said, Fibonacci sequence, very important. We eagerly initialize this instance variable on the class. And we know that booting the application and requiring files is considered to be not thread safe, so we're guaranteed that this is only gonna happen inside of one thread. So we pre-calculate this cache stored on the class and then we're good to go. The other fix that we can do is we can lock. So this requires that we add a mutex and we say, okay, we're gonna go synchronize on that mutex, calculate the Fibonacci sequence and then return it. So the other thing that we can do is we can move this to instance methods. Class methods are gonna be shared among threads, so depending on the particular problem that you're trying to solve, moving to an instance method may be a better solution. So you say, well, I'm not gonna share this instance among threads, we can actually generate a new instance per thread and we just do the calculation and initialize and we have a cache there. We can also do a lazy initialization if we want to using a synchronized block and initializing there. Now, if you really, really, really need this to be a class method, another thing that you can do is create a singleton, store that on, store that as a constant and use that and actually we found that to be fairly handy throughout the Rails source because we can actually instantiate that object and test it. So dealing with singletons is kind of a pain because maybe if they store any type of state you have to reset that and it's just much easier to test against an instance of something. Now, another problem that we ran into was hash.newblocks and this is kind of an insidious problem because you don't notice at the method level that, well, this isn't gonna be thread safe. You just look at the method and you're like, well, I'm pulling a value out of the hash. It's totally fine, it's gotta be fine but actually what's happening is the hash is doing the same issue that we had in the or equals, the or equals section. It's saying, okay, we have to check, then act. Do we have this key? If we don't have the key, then we need to go calculate a value for it. One thing that we can do is synchronize around, synchronize around key fetching. The other thing that you can do is which I recommend is getting this thread safe gem from Charles and I have to say, I wish that the type of stuff that Charles has in this gem was in Ruby's standard library because I feel like that's another problem with thread safety in Ruby itself is we don't have a lot of the primitives available to us in the standard library like thread safe hashes, thread safe arrays, even some things like I don't know, futures, latches, barriers, those types of concurrency data structures just aren't available to us in the standard library so I feel that that is something that's keeping Ruby developers from writing thread safe code. So this is well and great but what about at the app level? I'm talking about all this stuff from the perspective of somebody working on the framework itself and I suspect most people are actually working on Rails applications so what do we do at the Rails app level? Well the answer is actually very easy. It's actually really easy and you shouldn't be afraid of making your code thread safe. The main thing you need to do is avoid shared data. Once you learn how to spot where shared data is happening in your application, it's actually pretty easy to eliminate that or put locks around it and the reason I say that this is the most important thing you need to remember is because most people don't actually type thread.new in their applications. It's very rare. So if you're not actually spooling up new threads then mostly what you need to do is watch out for shared data and you need to look for things that are global. We're gonna look at a few things that are global, like this obviously if you're using global variables it is a global and probably shared among threads. Another global that you need to watch out for are constants, constants are gonna be shared among threads.  You're modifying global data but you don't know. And I think the one that's most common are class level methods, class methods like this. You have to remember that all these classes these classes are all shared among threads and when you set a method on that class that method is also shared among all of your threads. So you need to be careful about these. So like I said avoid global data in ad locks. The next thing I wanna talk about is streaming. And to be honest this isn't a new feature in Rails 4 it's actually we just tried to make it easier to use. So we're gonna look at streaming and then we'll look at template rendering how template rendering works today we'll look at streaming and we'll look at some features beyond Rails 4. So I wanna look at template rendering from a high level a very, very high level perspective. When we process our ERB templates the results are buffered and stored into memory and as such all the Rails internals are built around buffering up this template and then spitting it out to the socket spitting it out to the client. Now what sucks about this is it means that clients are blocked while Rails is working. So when somebody makes a request to your web server they say give me the index page and Rails is like okay we're gonna calculate the index page and it's sitting there churning away calculating the index page while the client is just sitting there going okay what am I gonna get some data what am I gonna get some data. When you could be sending data down to the client and letting them fetch like assets or process JavaScript in advance. So the client is blocked while Rails is working. The other annoying thing about the way that template processing is handled is that we have to fit the entire page into memory before we spit it out to the client. Usually this is fine but it means that we're constantly resizing strings and we'll see the process growing as it builds up the page and then hopefully reducing again hopefully and then spitting out to the client. So most people expect that they have to return something from Rack here they have to return the entire page and I think Rack encourages buffering. If you look at the Rack API this is a Rack application that third parameter in the array is actually the page buffer itself and the simplicity of this API makes it seem like well I have to buffer up the entire page before I send it off to the client because we have to actually return this value up the stack. So the thing that's annoying about this is we know that even in MRI even in MRI we can do IO and CPU in parallel. So why are we buffering up this page? What is the point of buffering it up? We could be sending data down to the client actually getting some parallelization P37N out of this. So this is where Action Controller Live comes in and what this is is a module that you mix into your controller and it gives you an IO type an IO like API to send data down to the client. And here's an example the reason we stick with this module is because today people are expecting that everything gets buffered and we don't wanna break that assumption in Rails 4. We don't wanna break your applications when you're upgrading so this is an opt-in feature. So here's an example of using it you just mix in Action Controller Live and then you get this stream object on your response object that you can write to it acts like an IO. That means you have to close it like an IO. It acts like an IO. So it's natural for us to do computations with IOs. So Action Controller Live gives you an object that quacks like an IO. This IO API is important to me because on Unix systems everything is a file. Everything is a file. So why aren't we treating our output like a file as well? So I wanna look at how this works. How does it work? We're gonna look at some of the internals and how to actually build this. So this is the API we want. We want something where we set the status, we set some headers and we write out to our stream and then we close it. That's what we wanna, ideally, that's what we would have our API look like. Now the problem is if we look at the Rack API, we don't have that with the Rack API so how can we accomplish this? X whatever equals heart. Well, what we need to do is we need to wrap this up into a response object and have people write to it. So we wrap it up in a response object and it looks like this, like here's our response. But the problem is down there at the bottom that's our Rack application, sets the response on the controller and then it calls the index and then returns back up the stack. But the problem is that this still doesn't stream. This doesn't solve our problem. We're calling into the controller, waiting for the controller to return and then returning back up the stack. So how do we fix this? Like, what do we do? Well, we can call the action inside a thread. Ah, now we're seeing why thread safety in Rails is important. We can call the action inside of a thread and then return back up the stack outside of that thread. But this still isn't good enough because if you're looking at this carefully you're saying to yourself, well, ah, man, this could return back up the stack before anything has actually happened inside the controller. Maybe nobody's set the response status. Maybe nobody's set the headers. What are we gonna do? So how do we deal with this? Ideally what we wanna do is we wanna wait. Right here we'll say, okay, we're gonna wait on the stream. Wait until something has actually been written. And the way that we do this is we have a buffer class and this buffer class has a latch in it and we call a wait on the buffer class and that just blocks there until somebody has actually written. And you'll see down here in the right method that releases the latch and then we return back up the stack. Okay, cool. So there is our internal implementation and this is an exact code but it's very similar inside the Rails source code. So you can go look for this and it should seem familiar. So cool, but what can we do with this? What can we do with this streaming stuff? Well, I wanna say like this really excites me from a Rails internals perspective because we can use this to build streaming ERB. We already have streaming ERB but this greatly simplifies the process and we can see this by taking a look at how ERB does processing. So here we have an ERB template, we output the source and this is what the actual source of the ERB template is. So we see that it can catch a bunch of stuff. But what's cool is that we can control, we can control the way that ERB writes things out and we can control the variable that it writes to. So in this example, what we're doing is we're saying, okay, I want you to use the right method and I want you to call the right method on standard out. So now if we take a look at the template source, we're actually writing the standard out. This is awesome because we can refactor Rails internals to more easily produce streamed template output. This is the result of that template. So how is this cool and wet? That's awesome for Rails internals, but how is this cool for web applications? Refactoring Rails internals excites me, but maybe it doesn't excite you guys very much. So let's take a look at how we can use this with web applications. One thing we can do is we can build infinite stream API server similar to Twitter. But I don't actually think that's as exciting as the other things that we can do with this. The most interesting thing to me now is using server-sent events. I don't know if you've seen server-sent events, but they're basically infinite streams where the browsers will fire a JavaScript function every time it sees an event. This is a JavaScript API. So this is what an SSE response looks like. It has this content type of text event stream, and every time the browser receives a particular event like this one, it'll fire a JavaScript function and pass this data payload to that JavaScript function. So this is the source. This is the JavaScript source to set up an SSE. And you can see here this actually makes a request back to your server, so it calls, it makes a request to slash control on the server, and it actually keeps that socket open. Now, we add an event listener on the reload event. So every time we get an event named reload, the browser will execute a JavaScript function, and we can have the JavaScript function do whatever we want to. And in this particular instance, I'm having to just reload the page. And I think this is cool because we can have the server notify the browser about events and actually have real-time browser communication. So I wanna show a video of an example of this.  And every time we change a file, we can actually have that notify the server. So it changes it, say, what do I say, OMG, I think. And it'll actually notify the browser, hey, you need to do a reload. It's time to do a reload. We can have it watch assets, too, so if you change your CSS, it'll automatically do reloads. Change it down there. We can see the user's background has changed, delete it, and it'll go away. And the other cool thing is we can do it from other processes, too. So we can say, well, let's fire up the Rails console and we're gonna modify the database. We'll create a user here, and as soon as we create the user, it notifies the browser, hey, data changed, you need to reload, or do whatever you want to, whatever we define that JavaScript function to do. So how does this work? When the file system changes, we use FS events, and when the file system changes, the file system notifies our web server saying, hey, this FS events gem says, hey, something changed, you need to do something. And then our web server says, okay, cool, we're gonna send an event down on this control socket that we have with the browser. And then the browser does its thing and reloads. Now what's interesting is that all these three boxes are actually within the same process. These are all running within our web server. So yes, all these three boxes are in the same process. Now the way that it works with the console that we were looking at, that console example is a little bit more tricky. We actually fire up a DRB server inside of your web server, and it opens up a socket, and the console opens up a socket to our DRB server saying, hey, and across that socket, we can send events to the server and have those send it down to the client. So other possible input sources besides file system changing or database changing to get your mind churning are we can use embedded systems. For example, I have my meat curing box hooked up to a web server. We can use it with telephony or maybe other users, for example, chat systems, like we could use this to build say, oh, I don't know, IRC or something like that. So we looked at these three topics and P72N parallelization, thread safety, parallelization and streaming, and hopefully I was able to relate them all to each other. So you can see how each of these are related inside of your applications as well as inside of Rails internals. Now, I think that cores are increasing. I don't think that this is a stretch to say that every time you buy new machines, the cores are increasing on your new machine. I just bought a MacBook Air and a new MacBook Air and now I'm up to four cores and that's crazy. It's really awesome. But the thing is we need to start utilizing the entire machine, which is why investigating things like doing parallelization with our virtual machines is so important. We need to understand how we can make the most of these machines. The other thing that I think is changing is we have high latency clients. We're starting to get more and more high latency clients, like people who are out on their really terrible edge server or edge connections on their cell phones. And we need to get data down to these clients as quickly as possible. Having them wait on our server to process templates is unacceptable. We should be getting data down to them as soon as possible. The other thing that I think is changing is that patience is decreasing. And I mean this among people. Like I think everybody's patience is decreasing and personally I blame this on Honey Boo Boo. But I think that people are expecting, like they're starting to expect more instantaneous responses from their web servers and we need to figure out how to do this. And I think the way that we need to do this, I was thinking about this, the way that we need to do this is we need to lie. When somebody is asking for a particular calculation, we should be using cache data where we can't. We're not actually performing that calculation, we're caching and we're lying to you about it. We need to cheat. So updating partial pages, partials on the page, we don't update the whole thing. You do a request, we're only gonna update the part of the page that changed. So we're cheating, we're not actually returning the entire page and we also need to steal. And I mean steal computation from our end users. So moving calculations into JavaScript and having those calculated on the client side.  In other words, I want you all to be good engineers. Thank you. If you have questions about this, please come see me after. I don't know if we have time for questions and I'm not sure what the protocol is on questions here, but if we have time, I'm happy to take them. If we don't, come find me. So thank you. Do we have time for questions? Are we gonna do that? Oh, okay. Five minutes, questions, go. And go. So I was wondering, if we don't have questions, I was wondering like, so are there like boutique spam places here in Hawaii? Like, is there, I wanna try, I wanna see if I can find some like organic shade grown fair trade spam and like try that. Does that exist? Is it a thing? Deep fried spam. Ooh, that sounds delicious. Questions, questions. Anyone? Yes, Constantine. So the question is, in template streaming, how do you handle, how do you handle exceptions that happen during streaming? And the answer is, don't have any exceptions. No. So there's things we can do like, spit out JavaScript to redirect you or some kind of hacks, but really they're total hacks. I don't have a good answer for you. Total hacks. Yes, Kobe. Anything on timing with the release candidates of Rails 4? Timing, the question is about timing on the release candidates of Rails 4.  We thought we would have a beta out at the beginning of September and obviously it's past September, but I think we're mostly unblocked now. We're hoping to get a beta out shortly and a final before the end of the year. Like, so soon-ish. Yes. The question is, is there a way to take advantage of the new queue system right now? And let's see. Yes and no. Yes, because it's basically just a queuing API and really the only thing that's really in Rails to support that is a fancy hash where you set a queue type object. So if you get, I think rescue has, well, okay. If an in-memory queue is good enough for you then just use the queue object. If you need something that's serialized, say like Redis, Jeremy Kemper is working on a queuing API for rescue, wraps around rescue and you can use it. I'm not sure if you can use that today but it will be out along with Rails 4. Sidekick has a queuing API but it's on an experimental branch. So if you wanna use it today, tweet at me and I will help you get set up. How's that? Yes. People who work with jQuery know about futures but can I talk about latches and barriers for a second? Yes. All a latch does is say, it allows you to coordinate two different threads. You're basically saying, well, one thread, you share the latch among multiple threads and you say, well, okay, I want this thread to go to sleep until this other thread has done some particular calculation. When that other thread is finished with its particular calculation, it'll unlock the latch and let the other thread go and typically you use like a countdown latch or something like that. So you say, well, I need five different threads to finish their job before I'm gonna continue. So it'll just count down on each of those and then barrier is, I believe a barrier is basically the same thing except that you can also do cyclic barriers. So basically reuse your latch. The thing about latches is that they're one-time use so you can't reuse it but if you have a cyclic barrier, you can reset it. Question use, yes. Yes. So the question is, let me see if I'm getting this right. Is there going to be a plan for standardizing SSEs inside of Rails? Is that... So giving you like a default when you start up, when you first get started for using SSEs. So the question is, is there going to be like some sort of default for people to be able to use SSEs when they fire up their web applications? The answer is there's no plan for that right now. And it's also, it's kind of hard because it's kind of hard to do something like that because right now like action controller live doing streaming is an opt-in thing. It's not default for all of your, it's not default for all of your controllers. My personal plan is I would actually like to make that default. I'd like to refactor the Rails internal such that we're always using streams. And I think once we get to that point, then it would make sense to say like, okay, we're going to give you easy sane defaults for doing SSEs. But right now it's like, it's total DIY basically. So if somebody did a, I think what would really help and what I, I've been, I'm going to admit I'm a really terrible person.  So I write an object to it and it translates that into a JSON object that spit out as an SSE. Probably somebody should write a gem for that. Hint, not me. I hope that answered your question. Okay. Do we have time? Anything else? Last question. Am I going to come to the spam jam festival next summer? I didn't know there was one. That's awesome. If I'm not somewhere else, yeah, totally. Does anyone else like spam? Am I the only one? Yes. Yeah. All right. Thank you.


This study determined the pathogenic abilities and morphology of dioporthe eries isolates obtained in 2010-2012 from fruit trees in Poland through cross-tests on apple, pear, cherry and plum tree shoots. The results confirmed the pathogenic nature of de-eres in relation to fruit trees and showed that the morphological features of studied de-eres cultures were very similar, regardless of the isolate and host plant. This article was authored by Barbara Anna Abramczyk, Ava Dorda-Kroll, Ava Dorda-Zalewska and others.


Russia sends ground-based combat robots for fighting in Ukraine. The ground-based BR-2 robotic vehicle with a flexibly-mounted machine gun and Mignon BR-1 mine-laying equipment were unveiled. At the Interpolitex 2023 International Security Show in Moscow, the Grand Scientific and Production Association told TASS. The BRG-1 robotic vehicle designed to evacuate casualties and delivery cargo was also unveiled at the security show. It said, All the three robotic vehicles are on display for the first time. The systems are being successfully employed in the zone of the special military operation and the feedback is positive. In all, about 60 of our combat robots are being employed in the zone of the special military operation. The platforms are operated with a joystick. Russian service members learn how to operate them very quickly. The tech firm said, The BR-2 robotized platform is employed by Russian assault teams in the special military operation in Ukraine. Russian troops also use the Mignon BR-1 robotic vehicle for remote-controlled mine-laying. The robot Miner BR-1 is used in the special operation. As the name implies, the device is designed for setting minefields. Seven such products have already been delivered to the front zone. In addition, the developer of the platform, the Russian Scientific and Production Association, the name of which is not disclosed, has created a Miner Kamikaze, a one-time version of the device.


The Chair recognizes the Honorable Philip J. Pierre, Prime Minister of St. Lucia. Madam Chair, Heads of State and Heads of Government, Distinguished Ministers, Excellencies and Heads of Delegation, Citizens of the Americas, Let me thank the President, the City of Los Angeles and the Government of the United States for hosting this ninth summit of the Americas and for the excellent welcome given to our delegations. This inevitable march of time, in the decade since the first summit of the Americas in 1994, finds us meeting here in Los Angeles at one of the most critical junctures in world history, a time of universal and grim crisis that causes deep anxiety among our peoples. It is manifested in the ever-deepening climate crisis visible in a COVID-19 pandemic that has created health and economic predicaments and compounded power in Ukraine with its worldwide disastrous impacts on the cost of energy and food supplies. For us in St. Lucia and the small island states of the Caribbean, the smallest members of the Americas, these crises are not of our making, none more so than that of climate change. The first of June marked the commencement of this year's hurricane season in our hemisphere and while hurricanes have always been a future of our environment and the increasing velocity and destructive power in the last decade have undisputedly been driven by climate change. Consider also that the world only hears of the major weather events because they are covered by the press regionally and sometimes internationally. However, there are persistent small events brought about by average rainfall that cause significant damage, often manifested in landslides and flooding and the process imposes additional severe strain on our already limited financial capability. For us therefore, climate financing that will allow us to adapt to the effects of climate change and which will enable us to build the resiliency needed to survive it is of paramount importance. It is therefore disappointing that the wealthy developed countries are yet to deliver on their pledge to raise 100 billion a year the deadline for which has moved from 2020 to 2023 to assist poor developing countries to cope with climate change. What is even more disconcerting is the acknowledgement now that the developing countries will need even more than US 100 billion a year for climate change adoption. To complicate matters, it is evident that weaknesses in the mechanisms for the delivery of climate finance are affecting the flow and impact of such funds to developing countries.  I therefore call upon multilateral development banks and other regional and hemispheric financial institutions to take action to mobilize greater climate change financing for our countries and to streamline and accelerate its distribution. The economic crisis from COVID-19 pandemic and the war in Ukraine have worsened our vulnerability by further contracting our fiscal ability to execute the economic and social programs that will bring progress to our people. In order to summon the setbacks from these crises, it is imperative that the countries of the Americas work out innovative forms of hemispheric economic cooperation that will generate the financing and other initiatives that will stimulate economic recovery and growth including food security in our nations. It is important that in this new mode of economic cooperation, simplistic measures of gross national income that debars small island states from accessing badly needed financing and debt relief are discarded in favor of the multi-dimensional vulnerability index, MVI, that is a fairer path to sustainable development. We have adopted political commitments at this summit that seek to address some aspects of the challenges confronting us. If we can implement them, then we will be on our way to securing a better future for the peoples of the Americas because in the final analysis, it is the people who matter. Youth development empowerment must be a vital part of the solutions being prescribed. In solution, my government is determined to create a special space for youth entrepreneurship and business growth within the general economic system to be pursued in the immediate future. In that space, youth will be provided with state resources to help them convert hobbies into entrepreneurship and skills into business through finance and marketing support, training and mentorship, thus creating sustainable livelihoods and a new country of indigenous business people. A dedicated agency which is agile, flexible and responsive is being created to drive that policy. The well-being of our people must be full in our deliberations and our decisions. My country therefore welcomes President Biden's announcement of the Americas Partnership for Economic Prosperity, which aims for a new model of cooperation between the U.S. and the other countries of the Americas in the face of the crisis of our time. However, let me state clearly that the Americas can only successfully take the highway out of this crisis if the Americas act together. It is therefore disappointing that some countries of this hemisphere, namely Cuba, Venezuela and Nicaragua, were not invited to this summit, and the summit has been marred by debates over inclusion and exclusion. The Americas cannot prosper if there is division and conflict in the hemisphere. There is always more to gain in cohesion and engagement than in fragmentation and confrontation. At this time, we must never forget the situation in Haiti which is causing untold hardship among the people. Our generation must not miss the opportunity to create true solidarity among the nations of the Americas. St. Lucia's Nobel laureate, Hon. Derek Walcott, lends us words from his poem Love After Love to help us capture this moment, and I quote, The time will come when, if elation, you will greet yourself arriving at your own door, in your own mirror, and each will smile at the other's welcome. St. Lucia has a deep and sincere desire to see the realization of true unity among the peoples of the Americas. The great South American, Simon Bolivia of Venezuela, said, In the unity of our nations rests the glorious future of our peoples. This is as true today as it was two centuries ago. And so, as I applaud and welcome the boldness of President Biden's American partnership, I say to our esteemed host and chair, President Biden, Take another bold step for our nations, put an end to the economic hardship in this hemisphere by leading your country to revoke the six-year-old economic embargo against Cuba and remove the economic sanctions in Venezuela. It is the people who are suffering. These times demand more than ever that we reflect on the futility of division in our hemisphere and do all within our power to ensure that this ends now. As I conclude, I quote from President Barack Obama, Change will not come if we wait for some other person or some other time. We are the ones we have been waiting for. We are the change that we seek. Let the Americas come together for a sustainable, resilient, and glorious future for our people. I thank you.


You need a financial advisor with the freedom to focus on your specific needs. Whatever your goals, Reeve Potter can create a game plan tailored to you. Call Reeve at 432-0777 at Pikeville, Kentucky to learn more. Mountain Engineering Day, or Mountain E Day for short, was held for the first time Saturday to engage youth in engineering activities for potential career paths. The biggest thing is the different types of engineering that are available right here in their hometown.  So our goal was to try to not only encourage them to do what they love but also to do what they love and the place that they love and to come home and celebrate with us. With activities spread across three locations, kids and young adults could explore the Appalachian Wireless Arena, U-Pike and Downtown's BitSource to try out their skill. So we want to expose them as much as we can to low tech as well as high tech. Here today we brought everything from squishy circuits to where they learn how circuitry works all the way to some of our robots that they can actually learn to code. Those robots are on different levels. We have puzzle coding for the younger kids all the way up to block coding and python coding for the older kids. Well, we started out with very simple hand tools because we want to teach route engineering skills but then they go all the way up to advanced computer technology. This is a wireless remote control vehicle. We do drones, we do wireless robots that involve programming and things like that. As part of the three location event, BitSource held a Q&A with Kentucky native and NASA engineer Dr. Tracy Prater who spoke about the life and challenges of being an engineer. Aria Ferguson, a NASA enthusiast, hopes to be an astrophysicist when she grows up. So I've always been obsessed with space and I first wanted to be an astronaut but then I wanted to stay on land. So then I found out about astrophysicists and stuff so I wanted to be one. And while kids were eager to learn more about engineering, director of digital literacy Tracy Tackett says she's happy adults see the value in engineering. I'm thrilled that parents see the value of an educational event. This isn't just a carnival. It is fun, hands-on learning and something that kids can leave today thinking, oh, engineering is fun and it's something that they might want to think more about. For Mountain Top News, I'm Jewel Courgell.


Going on everyone Sam here with late sports cards have been five boxes the 23 tops inception baseball hobby for Jeremy H So good luck here Jeremy Here we go Never forget speaking of that a couple weeks ago. I think it was when I think Jake was trolling me and Me and Kyle on Tuesday night with Jake you underscore 8 on Twitch and we kept saying it was like They have two redemptions that's got to be a mistake if there's two redemptions in this plus an autos. There's three hits in this Clayton Kershaw Green J Ram Green and a rookie of Justin Steele God whoa, Max Shoiza Trevor story say a Suzuki. Yeah, so first auto is gonna be Nick Vespy videos It's you 99 we've got a redemption Michael Bush Inception first MLB milestone relic Nice one there. Congrats on that. That is again the game use base of Michael Bush and Another first milestone this time of Jordan Walker.  Yeah, that's awesome We'll take that is a hell of a box right there. Let's go Jeremy good stuff, buddy We take extra we take two extra autos all day all day Hell yeah, that's on wonder. Yeah, not a good guy No, thanks, what are your thoughts on it? I mean dude's a scumbag.   I have any Pascantina Just to get the just to make himself laugh in bed Manuel Valdes, and I don't know I can do it with that damn dog. Yeah Langley's Connor Cappell Nick Prado and Francisco Alvarez. This is a really good one so far Really good break so far Jeremy that'll work Francisco Alvarez. Yeah, it's that whole thing. Yeah, he's done. Yeah, he's all done He should be Period end of discussion. Yeah, wait till he gets in the prison too. Oh, yeah, it's a 25 drew waters It's gonna be a catcher in prison. Oh, yeah, Cole Regans Beatty Leo Pueblo and another Francisco Alvarez. It's time to 99. It's been a hell of a first three boxes To Francisco Alvarez autos and a three autos in the first one That's true. Timmy. It's a good way of putting it. Yeah. Good way of putting it trust me Tomo's or not looked at no Oh Especially his Choyza Purple to 150 Nolan Jones on the color match for the rocks and James Outman Ozzy Albies Corbin burns Alec Thomas and Josh Wynchowski on our own cow ski auto To at 299 for the Red Sox And then we've got one last box Jeremy. Good luck, buddy Yuri Perez green Purple to 150 Miguel Amaya Tarro Fuginami Aaron Judge one Soto and Brian Serban to 125 for the Rockies not a bad personal for you there Jeremy not a bad personal at all Thanks again as always for the sport buddy get them right out to you moment


This paper proposes a Novel Lightweight Object Detection Framework for Radar Ship Detection called Multiple Hybrid Attention Ship Detector, MAST. This framework utilizes multiple Hybrid Attention Modules to reduce the complexity while maintaining detection precision. First, a Hybrid Attention Residual Module, HARM, is used to extract features quickly and accurately from the SAR image. Additionally, a Parallel Self-Attention Mechanism is employed to ensure high detection accuracy. Second, an Attention-Based Feature Fusion Scheme, AFFS, is introduced to combine the features extracted from HARM and the Parallel Self-Attention Mechanism. Finally, a new Hybrid Attention Feature Fusion Module, HAFFM, is constructed to fuse the features from HARM and AFFS. Experimental results show that MAST outperforms existing methods in terms of both detection speed and precision. This article was authored by Nan Jingyu, Hao Houran, Tianmin Deng, and others. We are article.tv, links in the description below.


People with generalized anxiety disorder, or GAD, are characterized by constant stress or excessive anxiety. When something stressful happens, the brain releases cortisol and adrenaline, causing the muscles to prepare to fight off the stressor or run away from it. This is otherwise known as a sympathetic nervous system response, or the fight or flight reflex. People with GAD have fight or flight constantly running on the back burner. Each of the following points is a result of that reflex. Restlessness and fidgeting. This is more the flight than the fight response. The muscles and brain are ready to go, but there's nothing to run from. This is why doctors say that regular exercise alleviates symptoms of anxiety, because people are using all their pent-up GO hormones in their bodies to actually go. Some people find it helpful to have a small object to occupy their hands, like a scrap of paper to fold and tear. This way the hands are kept busy and prevented from harmful fidgeting habits like chewing or picking at their fingers. Lack of energy or rapid fatigue. The flip side of your body constantly being ready to run or fight is that it's truly exhausting. For example, if you were to tense every muscle possible in your body right now and hold it for the rest of forever, you'd get exhausted pretty quick. When all your energy is going towards something that could require an immediate response, then everyday tasks like getting up to turn off the lights seem much more tiring. Irritable bowels, acid reflux, nausea, or other stomach ailments. The first thought is probably you. But if you think about it, this makes a lot of sense. People can't run long distances or perform heavy workouts with a full stomach or that leads to cramps. So this is your body attempting to rush the job of digestion so that it can allow for a fight and make your body lighter and more aerodynamic, which makes fleeing easier. Trouble falling asleep or staying asleep. This one is pretty simple. If you're in one place for too long, the danger could catch up to you. Your body, however, doesn't realize that there isn't actually any danger. So if you stay awake or only sleep short periods of time, it's safer. Unfortunately, this system is a nasty cycle. You get anxious so you can't sleep, which leads to even more stress on your mind and body, which makes it even harder to sleep, and so on. Hyperventilation. Muscles processing more energy require more oxygen to keep up the exertion. So breathing quickly would help to maximize oxygen intake. The challenge occurs when we over exert this response and the lungs don't have time to pull the oxygen out of the air we breathe before we exhale. That's when oxygen intake decreases and results in that dizzy sensation many people experience during a panic attack. Heart palpitations. Similar to the hyperventilation symptom, heart palpitations happen because the body uses blood to carry oxygen to the muscles. In order to carry the most oxygen fastest to hardworking muscles, the heart has to pump it faster, resulting in palpitations. Clenched jaw or teeth grinding. Your body is ready for action. However, the challenge with anxiety disorders is not knowing what action. So your body responds with tensed muscles like a clenched jaw and teeth grinding. Other common muscle tension responses could be clenched fists, curled toes, tension headache or chronic migraines and neck and shoulder pain. Shaking hands. This is another sign that adrenaline is sending your body's signals to go in a situation when you don't want to go anywhere. This can also be a byproduct of tension due to overexertion of the muscles. Sweating. Sweat is our body's way of cooling off during intense energy exertion. Muscles are burning energy being tensed and ready to go to work, which is generating heat. So the body moderates its temperature by sweating, even when you feel cold. Hot and cold sensations. The fight or flight response excites the body, which causes increased energy flows and creates heat. If the heat generated is intense enough, the body's parasympathetic nervous system is triggered, which creates a relaxation response. However, the body also sweats to cool itself when heat is generated. Coupled with the sudden relaxation courtesy of the parasympathetic system, the body can experience chills because it cools too fast and is not used to the lower core temperature. Anxiety is a state of constant fear due to stressors from your body. This fear was a logical response for a priest or a human who needed to run or scare away predators when in danger, but it can be distracting in today's fast-paced world. The silver lining, though, is that people with anxiety are the ones most prepared for surviving the zombie apocalypse. Do you or someone around you suffer from these symptoms of anxiety? If so, do you have any helpful tips on how to deal with them? Be sure to let us know in the comments section below. If you enjoyed this video, please be sure to follow our social media for more psychology content, and don't forget to subscribe. Thank you for watching, and have a wonderful day.


This algebraic geometry video will be about regular functions on varieties and their open subsets. So we recall that an affine variety in, affine variety Y in n-dimensional affine space is defined by some ideal I. And the coordinate ring of Y is the polynomial ring. We think of this as being polynomial functions on affine space restricted to Y. And this coordinate ring is going to be the ring of regular functions on Y. So for affine varieties, or for that matter, for closed subsets of affine space, regular functions are just restrictions of polynomials. Fine. More generally, we want to define regular functions whenever U is an open subset of an affine variety Y. So open subsets of affine varieties are called quasi-affine varieties. As I said, quasi is usually a sign that someone messed up the terminology, but anyway. So some examples, we might take U is equal to A1, one-dimensional space with the origin root. And as we mentioned earlier, U will actually turn out to be isomorphic to the hyperbola of points where X, Y is equal to 1 in A2. Because the X coordinates of a hyperbola are exactly non-zero values of K. So you can map U to the hyperbola by taking X to X, and it's inverse and vice versa. So this quasi-affine variety is really just an affine variety in a slightly disguised form. Another example is A2, the orange move. We will see later that this is not isomorphic to any affine variety. So this is an example of a quasi-affine variety that isn't affine. So quasi-affine varieties are definitely more general sorts of objects. So now we want to think about what do we want the regular functions on U to be? So if we take U to be A1 minus the origin, we want X to the minus 1 to be regular on U. It's a perfectly good function. You can define an algebraic way. And it's obviously not the restriction of a polynomial. I mean, the polynomials on here would just be K of X. So we don't want the regular functions on U to be K of X. We want the ring of regular functions to be K of X, X to minus 1. So we need to think of a slightly different definition. So we define a regular function on U. Here now we're taking U to be an open subset of an affine variety. It's a function, all functions for the next, most of the rest of this lecture, functions to the field K, by the way. It's a function that is locally regular, all points P of the quasi affine variety U. Well, we haven't yet said what locally regular means. Locally regular means that if our function is F, then F is equal to G over H in some neighborhood of P, where G and H are polynomials. In other words, they're just elements of this polynomial ring restricted to U. And H is not zero at the point P. So a regular function sort of looks locally like a rational function, except the denominator must be non-zero. G and H, by the way, may depend on the point P. So X to minus 1 would now be a regular function on A1 minus 0 because we're allowed to invert by X because X is non-zero everywhere here. So roughly speaking, regular functions mean you're allowed to divide by polynomials so long as the polynomial is non-zero at all the points we're interested in. Well, we have a bit of a problem here because we seem to have defined Wittler in two ways. So we have the following problem. Suppose Y is affine. Then we can ask, are regular functions regular? Well, the problem you see is we've defined regular in two ways. So here we have defined to be regular if they're polynomials on affine space. And here, this means regular at each point. So we should check these are compatible. So this is a sort of local regularity condition. So this says they're locally regular. And this says they're globally regular in some sense. So we want to show that saying something is regular using this local condition is the same as saying it's regular using this global condition. So let's assume that Y is a union of open subsets. So each UI is open. Here Y is a variety on Y as usual with values in K. And suppose it's regular on all UIs. So if F is regular at every point, then we can cover Y by open subsets such that F is regular on each open subset. Well, this means F is equal to GI over HI on UI, where HI is not zero on UI. Where the GI, the HI are of course just both polynomials. And the question is, is F a polynomial? And this isn't made obvious since we've defined F to be locally given by rational functions. Well, in order to show this, we observe that one is equal to A1H1 plus A2H2 and so on, modulo I for some polynomials, AI. And this has to make sense all the definite number of these AI should be zero. The reason for this is that Y is covered by all these sets UI. Well, this means that no point of Y is outside all the UIs. This means that no maximal ideal of KX1 to XN containing I contains all the HI's because the maximal ideals containing I are the same as the points of I by the wheat and all still and that's and saying that a point is not outside all the UIs. The same as saying that the corresponding maximal ideal contains all these HI's because UI is the place where I is none zero. So since no maximal ideal of K, if there's no maximal ideal containing I and all these HI's, this means the ideal generated by I and all the HI's must be the unit ideal. So the ideal generated by H1H2 and so on and I is the ideal generated by one. In other words, one can be written as a linear combination of the HI's. Now we're going to use this relation to construct a polynomial F. Well, so, well, we've got a function F and we want to write F as a polynomial. So since one is equal to A1H1 plus A2H2 and so on, modulo I, we multiply by F and we find F is equal to A1H1F plus A2H2F and so on. Again, mod I and now we know that H1F is equal to G1. So this is equal to A1G1 plus A2G2 and so on, mod I. So this suggests the definition of F, so just 5 plus A2G2 and so on. And now we should just check that defining F in this way does actually have the properties we want and this is pretty trivial because we want to show, we want to check that HIF is equal to GI on UI and this just follows because HIF is equal to HIA1G1 plus HIA2G2 and so on. And it is that HIJ is equal to HJGI because GI over HI and GJ over HJ must be the same on the intersection of the sets UI and UJ. So this is, I'm just like confused, so. And this is just equal to, sorry, now we notice that this is equal to GI A1H1 plus GI A2H2 using this relation here. And this is equal to GI times A1H1 and so on, mod I, which is equal to GI mod I, which is what we wanted to prove. So now we show that HI times F is equal to GI mod I. So the local condition of regularity is the same as the global condition of regularity. Next we can ask you is a quasi-projective. So what does quasi-projective mean? Well quasi-affine means open subset of an affine variety. Quasi-projective means open subset of a projective variety. So we've got four sorts of varieties. We've got affine varieties, which are special cases of quasi-affine. And we've got projective varieties, which are special cases of quasi-projective. And quasi-affine are in fact special cases of quasi-projective varieties because any affine variety is an open subset of a projective variety. So quasi-projective are the most general sort of things we have. And now you notice that any quasi-projective variety is covered by affine subvarieties. Or if you like open subsets of affine subvarieties, it's the open subsets of. So this is because projective space is covered by a finite number of copies of affine space. So any quasi-projective variety you can easily see is covered by a finite number of open subsets of affine varieties. And now we say a function on a quasi-projective variety, which people thought was a shorter name for these things, is regular, if it is locally regular. Where locally regular means for each point has a neighborhood that is an open subset of an affine neighborhood where it is regular. So we find regularity for open subsets of affine varieties. We can extend regularity to all local affine subsets of projective varieties, and this allows us to define regularity of functions on open subsets of projective varieties. Next we notice that if we have a quasi-projective variety, then for each open subset u of y we have a ring sometimes denoted by o of u of regular functions. And these rings are the following property. Suppose u is a union, u1, union, u2, union, u3 and so on of other open subsets, then it has the following two rather obvious properties. First of all, if a function on u is equal to zero on o of ui, where we can just restrict it for all i, then f is zero. In other words, if a function is zero or six other than it's i are functions on ui, and suppose that they're compatible, fi equals fj on ui intersection uj, then we can find f that's regular on u such that f becomes fi on ui. So this is essentially just the condition we showed earlier that if a function is locally regular on an affine set, then it's regular. Now, these are the conditions that you need to define a sheaf. And we will see later when we do schemes that schemes also have a sheaf of rings on them with these two properties. Now for ordinary quasi-projective varieties, it's kind of pointless introducing sheaves because it's just the properties of sheaves are completely obvious because we're just talking about regular functions on the space and regularity is a local property and being a local property is sort of like this. However, when we cover affine schemes, things will be a bit more complicated because the elements of these rings won't correspond in any obvious functions on something. So we will need to start working with sheaves. So let's finish up this lecture with an example. Let's just find regular functions on dimensional project space. Well, we know the regular functions on affine space is just the ring of polynomials. So to find the regular functions on projective space, we cover it with two copies of affine space. You remember if we denote points of the line by x colon y, we can think of these as the points with x not equal zero and these are the points with y not equal zero. So we have a sort of picture like this. Here we've got one copy of A1. And here we've got another copy of A1. And the intersection is A1 minus the origin. So to specify a regular function on projective space, well, we have to give its restriction. Well, here will be a regular function on affine space. So pick regular function on A1 and a regular function on the second A1. So we have to pick a function here. And these functions must be the same on their intersection. So these must be the same on A1 minus zero, which is the intersection of these two one functions here. Well, A1 minus zero. So if we think of this as being the points of this A1 denoted by x, then the regular functions on A1 minus naught. Will be the ring of polynomials kx, x minus one. And these functions will be the ring of functions kx. And so if this is x and this is y, we notice that these regular functions will be the ring ky, which we can identify with k of x minus one. So what we need to do is we need to pick a function that is a polynomial in x and a function that is a polynomial x minus one that become the same in this ring here. So we've got maps from these two rings to that ring, which are these maps here. Well, pretty obvious there's only one-dimensional space of functions in here, which you can produce in both these ways. So f must actually be a constant. So this is the only element of this ring which can be obtained as the restriction of something here and as the restriction of something there. So all functions on the projective line are just constants. Okay, next lecture we will show how to use regular functions in order to define morphisms of varieties.