Welcome, how's everyone's morning? Cool. So my name is Brad Hirani. This is a talk about immutable data structures. Immutable data structures are an idea from functional programming. And I gave this talk because I got interested in this because I took a course on Coursera called the Principles of Functional Programming in Scala. It's taught by Martin Odersky, who's the inventor of Scala. Very, very, very great course. Highly, highly, highly recommend you take it. It got me thinking about how we can do some types of functional programming in Ruby. And what do I mean by functional programming? Functional programming is the techniques that are used to isolate state change, basically. And it's what you get when you combine a number of techniques and also use some discipline. It's what you do and also what you don't do. Ruby has a lot of the stuff that you need for functional programming built in. Immutable data structures has that yellow squiggle there because we get that with a third party gem. Higher order functions would be like passing lambdas around. Partial functional application, that's like currying. We don't do that a lot in Ruby. We do have lazy sequences as of Ruby 2, recursion. You can always recurse in Ruby. We don't have lazy evaluation and pattern matching.  But the truth is, most of functional programming is a poor fit for Ruby. Ruby is an object-oriented language. And I have tried to do pure functional programming in Ruby and you can do it. But I don't really recommend it, at least not in production. But these immutable data structures, I thought were really, really interesting because they are a piece that we can take that I think do have some really, really interesting use cases and also are just a really, really neat topic with some really cool aha moments in them. So we do have this immutability built in a Ruby. We have this .freeze method. So we take this array, we call .freeze. And then what happens is if you try to change this array, if you try to update, add an element or delete an element, this will raise an error. So the reason we have this is to prevent certain types of bugs. So if you have this array and you're passing it to some function that the success is predicated on this not changing, you can do this to avoid certain bugs. If you jump into the Rails source code, you'll often see string.freeze, right? That's a performance enhancement. It's a memory saving device. Freezing an array does not have the same performance enhancement as far as I know. So it's for not running into certain bugs. I guess that's useful. It's not really that interesting and it's not what this talk is about. That's because this data structure is immutable but it is not persistent. These are two different things. Persistent is a data structure with some special qualities and that's what I'm gonna be explaining today. So we get persistent data structures with a third party gem. It's called Hamster. It's a really, really awesome gem. Here I've made a list just containing the items one, two, and three. Hamster is really, really awesome. It's this great gem. It's got this whole collection of persistent immutable data structures. Is anyone here like a maintainer or has anyone worked on it? Maybe not. Well, if you're watching my video later, shout out to you. This is a great gem. Great work. So we get this list one, two, and three and what actually is the difference here? Let me show you really fast. So make sure this is big enough. All right, so if I make an array in Ruby, one, two, three. So there's L. L is one, two, and three. So if I do L two equals L, dot unshift zero. And unshift if you don't remember is actually the list operation that pushes something onto the front of an array. I get zero, one, two, three. Okay, what is L right now? What happens if I print out L? Is it one, two, three? Is it zero, one, two, three? It's zero, one, two, three, isn't it? Why is that? That's because both of these references, L and L two, have a reference to the same array. There's only one array in memory and they both point to the same one. So editing it in one place, changing it for all references that have it. Hamster is a little different. Hamster list. So if I do L equals hamster list, one, two, three. There we go. All right, it's not about that. All right, so I have L which is one, two, three. And if I say L two equals L, dot cons, and cons is the same as unshift. It pushes something onto the front. Why is it called cons? It's tradition from functional programming, dating back 40 years. But same thing, I cons something onto the front. I get zero, one, two, three. What is L now? L is still one, two, three. So that's the difference here. That's the difference between just a normal array and a hamster list is that when I edit hamster list, anything with the reference to the original stays the same. It remains unchanged. That's why it's immutable. So a persistent data structure is immutable, but immutable data structures are not necessarily persistent. Persistent data structures have these special qualities. So how do they implement that? All right, let's think about this for a second. Like say you wanted to make that hamster list class yourself. How are you gonna go about and do that? Well, the first thing we can think of is, all right, when I update the list, I could just clone it, couldn't I? I could just make a whole dang copy right in memory and then I would achieve what I wanted, right? No problem, that makes sense. Interesting example from everyone's favorite language, PHP, right, is that PHP actually does this. If you take this array, which is set to two, three, you can actually swap references like that. Like just set array two equals array one, then you can add four under array two, and actually array one is still unchanged, right? This is called copy unwrite. The PHP runtime is kind of smart. Oh my God, did I just use smart talking about PHP? Oh, what's wrong with me? But yeah, it actually clones things under the hood, keeps tracking these references, and clones things under the hood for you. That's kind of interesting, but it's not very efficient, isn't it? That's not very fast. You wouldn't expect that to be very performant. So how would we implement that immutable array, that persistent array, in a way that's performant, efficient and fast? It turns out a functional persistent list is actually a linked list. Did any of you ever take an algorithms class or something where you learn regular stacks, and queues, and trees, and linked lists, and you're like, wow, why would I ever use a linked list? Well, it turns out they do actually have a use case, and that's in this. So we have this list. So if I do this, I take one, two, and three, and then I use cons to push something onto the front. You can see that it's persistent. I have one, two, three, and I have a new list. What I've actually done is this. So I have a single linked list, and I have two references to the same list, to two different nodes in the same list. That's actually awfully clever, isn't it? Because I didn't have to clone anything. The one, two, three part are shared by the two lists, only to the references list and new list. It looks like two entirely different lists. It looks immutable, doesn't it? That's actually really clever because it's fast. It's performant, it's fast. It's a neat implementation detail. Okay, so straight from Wikipedia, persistent data structure is a data structure that always preserves the previous version itself when it is modified. Such data structures are effectively immutable as their operations are not visibly updating the structure in place, but instead always yield a new updated structure. Okay, cool. So a few limitations of this list, as you might expect. First of all, it's singly linked. Why can't I make this a doubly linked list? Think about that for a second. If I have this, and if I tack zero onto the front, if I wanted to make it doubly linked, I'd have to add a reference from one to zero, wouldn't I? If I do that, I'm changing it. Is that still immutable? No, so I've violated immutability, so it has to be a singly linked list. I can't go backwards either, because it's singly linked, I can only traverse this list in one direction. Also, I can only add to the front, can't I? So that's the limitation of this list, and I can't do random access. So a hamster list, you literally cannot say, all right, give me element three. Why not? Why can't I get element three? Well, what's element three in this list? Is that relative to the first reference? Is that relative to the second reference? It's kind of a relative thing, what element three in this list is, isn't it? So it's a relative question that we can't really answer. It doesn't really make sense. Also, even if you did implement it, you'd have to recurse to be bigger than, it wouldn't be very fast. All right, so another example here is my rock band linked list. So I've got this rock band, VH1980, consists of David, Eddie, Alex, and Mike. Then I do this, I take VH1980. This is a reference to Van Halen, the rock band. I don't know if you all have got my joke. They swapped out lead singers in 1984. Okay, so I take VH1980.tail. That tail gives me everything after the head, which is Eddie, Alex, Mike, and I conned Sammy onto the front. So here I swapped David with Sammy, haven't I? So now I have this in memory, because I've taken David off and added Sammy, I've got two references. I'm starting to sort of build up a tree here. To each of these references, it looks like a list because you can only traverse one direction, and I'm basically building up a linked tree. And we can even take this further. I can take this A, I add foo and bar. To foo, I add brisket and ribs. To bar, I add chicken and sausage. We can end up entirely with a linked tree, and we can have a reference to each node in the tree. And just so you know, my inspiration from this is that I'm from St. Louis, we have awesome, amazing barbecue. I moved out to California three months ago. They don't even know what barbecue means. It's this like grilled tri-tip. It's not the real thing. I'm really excited to be here in Texas because I got to eat barbecued ribs, the real kind. But anyway, so I've got this tree now, but the arrows only point up because I can only traverse one direction, which means to the references in the nodes, it looks like a list. Okay. Could we make a persistent graph? So a graph does not have the limitations of a tree. In a graph, everything can basically link to anything else. It's like the free-for-all of data structures, isn't it? Well, let's think about this second. If we started connecting nodes in a graph and you allowed traversing both ways, you'd have to doubly link. That violates immutability, but we probably could do it if the arrows all went one direction, couldn't we? Yeah, so if it was a directed graph and it would kind of ruin our directed graph if we made the circles, wouldn't it? Because at some point we'd have to modify something. So if we had to directed a cyclic graph, we could make this a persistent data structure because we'd only adding things on the end. Does this remind you of a tool you all use? Maybe something you know and love and use every single day? Let me yell it out. Woo! Yes, Git is basically a persistent data structure on disk, isn't it? It follows these principles, right? One way traversal, singly link lists, perfect history. Yes, you all use this every day. Git is a persistent data structure. So let's solve something a little bit more interesting. Do something a little bit more interesting, rather. Ha, ha, ha, ha. That part's coming later. Okay. Maybe, no, I'm gonna do it now. All right. So I'm gonna pull up a little game here. Come on. Oh yeah. So this is my isomorphic functionally, functional reactive JavaScript app. Just kidding, it's a flash game. This is called Bloxers. I first ran into this problem when I took the class that principles, functional programming in Scala class. I ran into this problem. It's a really, really cool one. So Bloxers is this video game, right? And I am that block right there. And the deal is I have to kind of move around and try to get that block to land in that hole right there. This is the whole gist of the game. Woo! All right, very, very cool. I did not make this game. What I made is a solver for this game. So this level has these like little bridges. I did not implement the bridges in my simulation. But we have this little game here. And it turns out this game can teach us a lot about persistent data structures. Let's see if I can do this. This is always the hardest part of my talk. All right, maybe this. Oh, and then I'm like, foods and steaks flashed. Oh my God. All right, let's try this again. This is the part where the nerves get me. Oops, no, I can do this. Watch. All right, all right, cool. Woo! That's the hardest part of my talk. So memorize this board of a second. Take a look at this board. Kind of memorize the shape. You got it.  You know what it looks like. All right. So here's my sort of ASCII representation of that board. The ASS is the starting point. The g is the goal point. Let me make that a little bigger for you. The g is the goal point. The zeros are the board, right? So I made a little ASCII representation of this. And my program is a little solver. Two. My program, what it does is it spits out the, oh yeah, it spits out the quickest solution to this problem. So it's gonna give me, it's a cheating game. It's gonna give me the fastest route to the goal there. Just to prove it to you that it works. Make that a little wider. This is the second hardest part of my talk, is making this all line up. All right, ready? Here we go. Wait a minute, that's not right. Okay, so right, whoops. Right, up, right, right, right, up, left, down. Right, up, up, right, right, right, down, down, down. Right, oh it froze again. This is why we got a real flash. Can you not see it? Oh. All right, wow, it really froze on me big time. Anyway, right, oh, there we go. Yeah, all right, right, up. All right, so I made a little solver. It finds the quickest answer to this problem, right? It's a video game solver. So how on earth did I do that? What does that have to do with persistent data structures? All right, first of all, all right. So if we think about this problem, we can model basically the moves in this game as a tree. So I'm up at the start. I have four possible moves. I can either move left, right, up or down. So that's that second fear in the tree. That shows me what my possible first moves are. So if my first move is right, then I have four other possible moves. I can move left, right, up or down, right? If my first move is up, I can move left, right, up or down. So that second row in that, or that third row, that bottom row in that tree represents all my possible second moves. So I can model my game using a tree and just a little digression here. The algorithm I do this is a functional version of this, which is kind of cool. It's a breadth-first search. I want to find the most efficient solution. So I want to evaluate all the possible first moves before I evaluate all the possible second moves. So it's a breadth-first recursive tree search. And the way that I do that is the functional version. So I take my first node and I flat map it to four directions, which gives me a list of four items. Four items I can flat map to left, right, up and down, which gives me a list of 16 items that makes my second row. So just a little reminder when I'm talking about flat map here. So imagine one, two, three and four. These represent the nodes in a level of my tree and I map them to four directions. I get 16 more directions. So I'm flat mapping between levels. I take the previous level. I can catenate it to the one before it. And I end up with an algorithm that basically flattens this tree. It's a breadth-first tree-flattening algorithm that allows me to treat these trees. It's one long, continuous list so that I can search through the list and find the answer. Find the one where the block goes in the hole. If I lost you there, don't worry. This is where the persistent data structures come in. When I get to the end of this, I find the answer, right? I have to be able to print out the history. I have to be able to print out the answer of how I got there. So I need to keep a history, otherwise I can't print out the answer at the end. Additionally, I also have to keep a history because I have to check for blocks, positions that I've already visited so I don't get stuck in an infinite loop. So how do I keep that history in a way that's efficient and fast? Well, this looks kind of like a linked list, right? So what's happening is like, say I get to this green node right here, the one that's highlighted that says right, I'm gonna map this to four directions. There are four possible moves I can take from that. Each of those four moves needs a different history list, doesn't it? I've already got a history list consisting of two elements. Now I need four new ones. Well, this kind of looks like what I had before just kind of turned on its side, doesn't it? So basically what I do is I cons a new history cell onto the front of the list and I get four new history lists but because it's a linked list I don't have to clone anything. So here I'm using the linked list to keep the history in my algorithm so that I can print out the answer at the end of my blockster's game. Interesting and novel uses of these persistent data structures. Interestingly, persistent data structures are also thread safe. So you may imagine that if I wanna solve this problem absolutely as fast as possible I might wanna spawn off threads. Maybe at the first level where I've got four moves, my MacBook has four cores. I probably wanna spawn off four threads if I wanna do that real fast. With a persistent data structure you can pass a reference to four threads to the same list and not worry about it. If you do that in a Ruby array and all the threads started mutating the ray you would have utter chaos, it'd be pandemonium. Persistent lists are thread safe. Interestingly, they're also lazy. So we have laziness in Ruby. So take a look at this algorithm. So say I wanna find the first 10,000 primes. So here's some simple Ruby that finds the first 10,000 primes. Does anyone see a problem with this? Yeah, I'm finding all the primes between one and a billion aren't I? That's a little efficient, I don't need all those. I'm not sure if that would ever end. It might take a very, very long time just so I can take 10,000 at the end. So what could I do? I could use the old procedural version where I get an empty array and do a loop and keep a counter of the number of things in the loop, right? That's not very elegant. Ruby gave us this dot lazy keyword, which is brilliant. All I change here. The only difference here is that dot lazy right up there. This means, look at what I got out instead of a bunch of prime numbers. The answer I got there is like this, kind of stacked up lazy data structure waiting to be executed. So you can actually do this.   So when you like puts it or like call dot it, like 2a on it, it actually fires off and gives you the answer. Hamster data structures also do this. Hamster structures work the same way. They are lazy by default. So in addition to being a mutable persistent, they're also lazy, and that's kind of clever because the way my algorithm works, basically I'm allowed to like kind of stack up this recursive tree search algorithm, a flat map, a cat, and I only fire it off at the very end. In fact, what I actually do is I have this lazy sequence and I actually call that select like basically where is a winner, right? And then it still hasn't fired off. Then I basically call it dot first and it actually traverses through and finds it. It's very, very cool. So hamster lists are lazy. They're awesome. And we get a few more really neat things in the hamster library. We have the list class, which I showed you. There's a hash which acts like a Ruby hash but persistent. We get a set, a sorted set. A deck is a stack or a queue, but we actually get this vector. And the vector's very interesting. I mentioned there are a lot of limitations in the list class, right? We can't do random access. We can only traverse one direction. Those are some limitations, right? And sometimes we need that. Sometimes we need random access. We need to say like, what's the third element in this list? Hamster gives us this. So here I'm setting V1 is zero through eight. And V2, here I'm setting the element five to beef. So I'm getting back zero, one, two, three, four, beef, six, seven, eight. And you can see that V1 is untouched, all right? So this is persistent. How did they do this? Think about this for a second. That's actually a pretty tough thing to implement. This one I scratched my head about for a while and I was very, very pleased when I saw the answer to this because it's quite clever. This is this fancy data structure called a persistent bit-practitioned try. That's a mouthful, I know that. But notice a try, first of all, a try is a tree where all the values are in the leaves. So you can see that all the numbers that I actually care about are all the leaf nodes. That's a try. All the middle nodes are actually empty. They're just placeholders in the 10 at the top. That is just a cache of the length of the list. So what happens when I replace five with beef in this case? It actually changes things like this. So the blue here is the new vector that I've created. The orange represents the old one. You can see it builds up the tree, but the blue one actually shares some of the orange nodes with the original, right? That's pretty slick. So it has to do absolutely the bare minimum. We have to make a few of those middle tree nodes. We have to make a new node at the bottom containing four and beef. But the rest of the stuff, the six, seven, the one, two, three, four, five, those are all shared in memory. It shares the same instance. So that's how I'm able to change something right in the middle of the vector and also not have to clone the whole dang thing. A pending has a similar kind of thing. So I have zero, one, two, three, four. I tack a five on the end. I only have to rebuild just a tiny little bit part of the tree so it's nice and fast. Popping, so here I have one, two, three, four, five, six, seven, eight, A, B, and C. I remove C, and you can see that the blue part, the blue vector, shares most of the memory with the original one. Very, very clever algorithm, very, very clever implementation of a persistent vector. I thought that was real neat. Shout out to Jean-Nicholas Lorange. I took this graphics from his excellent, excellent article, which if you want to read it, I highly recommend it. It actually explains Closure's implementation of this, but the Hamster version is the same. So that's pretty, pretty neat. But what do we do with it, right? So what? Why is this useful? Turns out there's some really, really cool applications for this. So what I did is I made like a little demo application. This is Connect4. Do you all remember this game? When I was a kid, actually the colors were different. It was a yellow board with red pieces and red and black pieces, I think. I don't know what point Mattel decided to change the colors of this, but so what I did is I represented my Connect4 board as a matrix. So let me show you Connect4 real fast. It's a pretty simple program with a pretty profound difference than what you might be used to. So let's see, Ruby Connect4, Connect4 Ruby, boom. All right, so I'm gonna make this nice and big. Also to the right a little bit, yeah. All right, so I actually made this, this is a pretty simple little demonstration. I built it with emojis, just representing a Connect4 board, but so I'm gonna start adding pieces to this board. So column one, of course I'm a programmer, so I use zero based indexes, right? But I started adding pieces to this board and I'm playing my little Connect4 game. All right, pretty simple. Nothing really special there. Why is this interesting? All right, so I represent my board with a hamster matrix. Hamster matrix is a gem I made, brand new gem just for RubyConf. It's a 2D matrix. What if I change something? An original reference is untouched. It's a persistent matrix. It's pretty simple actually, it's just built on top of nested hamster vectors. But I made my little hamster matrix gem. My board is a matrix. Oh, I'm not cloning because we don't want clones in the matrix, right? No, that'd be bad, right? I know why I was too easy, sorry. Okay, but this command line program actually follows a pretty interesting architecture. Basically, I have a state manager. The state manager holds my state, which is my matrix. And when I press a key, I take that state and I send it through my game logic. The game logic does things like checks, like, okay, is this a legal move, right? You know, I drop it in this column.  You know, so where does that slot in? You know, did one of my players win the game? That's my game logic. And I get back a new state. Because it's persistent, we know for a fact that the old state, the original state is still in memory somewhere, don't we? That's kind of neat because now I can store all of the game states that I've ever been through here in memory have a reference to them all. So I have my entire history of game states here in memory in my state manager. Why is that cool? Because I can travel through time. Yes, very, very, very cool. And my state manager, that's really neat because at any point in this, I can go back. Wonk, wonk, dunk, dunk, dunk, dunk. So I can rewind my program. There are a lot of ways to implement this, but can you think of anyone that's more clever, that's more eloquent? Because I pretty much got that for free, didn't I? By using a persistent data structure, the whole memory mapping, keeping all that state memory, it's pretty much done for me. All I have to do is keep a list of references. That's real clever. I don't have to clone anything. I don't have any inefficient cloning, do I? So it's a real, really easy way to achieve that. And it's also real efficient. Of course, because my persistent data structure is in my state manager, all I'm really doing is storing diffs here, right? Since I'm not cloning anything, I'm storing the absolute bare minimum to represent the difference between one state and the next. So it's crazy efficient. It hardly takes up any room. It's very, very, very fast. There is a little caveat to this, right, to make this work. My game logic cannot have a side effect. A side effect. It has to be made of pure functions. What is a side effect? All right, so here's a little Ruby class with a person. I've got this method, steal cookies, and you can see that I'm incrementing pent-up aggression, right? I'm changing something. Pent-up aggression is being mutated, being changed. That's a side effect. If I do that in my game logic, and if I have a bunch of objects around, and I'm changing instance variables in my object, those are not reflected in the state, are they? I didn't capture them in my state manager. When I go rewind, they won't be rewound. So there's no way to rewind if I have random mutations in state variables in different places. Which means I have to be, I have to basically write my game logic in sort of a functional style, which is data in, data out. I pass arguments into a function. I operate on that. I get the answer back. And I, my virtuous circle there, I send the answer all the way back up to my state manager. That allows me to time travel. It's very, very clever. So where is this all going, right? Turns out this, a lot of the industry is moving that way. So this is more than just a novelty, right? Connect for a game. Okay, that's kind of novel. It's kind of neat. But this is a lot more than just a demo. For one thing, our front-end stack where I work at Procore is entirely based on these principles. In JavaScript, of course. This is our front-end stack. We're using React.js, which is very popular, along with a library called Redux, which is a implementation of relay. And we're following this virtuous circle. So a key press hits what's called a store, what's called a redux store, which has the data stored in immutable vectors using Facebook's Excel and immutable.js library. I pass the state into a redux reducer, which gives us a new state. And then we send it down to React and we send it down to the DOM. We can actually rewind and fast forward our front-end at Procore, which is really, really neat, really, really clever. So that's nothing to joke about because we also have a list of hot loading, which means that we can actually pull up a form, start pressing buttons, doing JavaScript-y things, to change the page, go back, rewind it, go back to make a code change, get hot reload, and then actually start clicking around things again. That's a pretty powerful debugging tool. Interestingly, this stuff is moving to the server side, too. So this is Rich Hickey. I think he's the most interesting computer scientist living today. He invented the closure programming language. He invented that persistent data structure that I showed you, that vector that he invented that, which is really, really cool. He also invented a database called Datomic. Datomic is basically a persistent data structure on disk. It's basically a database that never forgets, that uses these exact principles, like basically a vector or a link list written to disk. And he sets up very interesting things. He's got a talk. It's called The Value of Values. It's from 2012. It's a modern classic. I highly recommend you watch it. There's a reason we do place-oriented programming. And here's what he means by that. Place-oriented programming. Think of a database row. Think of a database row when you update a field. Last logged in at, right? You update that. When you go back and retrieve that, you're looking for a place. It's a place in memory.  I always know the last updated date is at the certain place in the certain row in memory. In an object, I've got an instance variable. That is a place, and it's something that I change. But if I need to know the value that I'm looking for, I go back and I find it in its place. In other words, we have places any time we mutate something, any time we change something. He says, basically, the only reason we ever do that is because in the early days of programming, memory was expensive, disks were expensive, rams were expensive, we had to update, we had to delete because we couldn't afford to have enough memory for everything we needed to do. Those limitations are gone. Ram is cheap, disk is cheap, which basically means why are we still doing that? Why are we still changing anything? Why don't we keep the history of everything we've ever done? Okay, that has some ominous 1984 tones to it. That's not really what I mean. I mean, the useful type of this. But that's a good question, and his database Datomic actually follows those principles. Can you imagine for a second if you built a Rails app on top of Datomic so that you could actually pull it up, start doing things, filling out forms, doing CRUD operations, then you could actually be wind it to a fixed point in time, then fast forward again if you could give your users the power of actually like, all right, here's where you are now, here's where your budget or your accounts are, or your email is now. Basically without any, with very simple implementation details, you could give it the power of your users to rewind and go back in time. See, here's where you were. This is what it used to look like. You have complete all of your history of everything you've done on disk. That'll be pretty, pretty amazing. Can you imagine how great of a debugging tool that is? If you can pull up a Rails app, do CRUD operations, oh man, I messed something up, there's a bug, rewind it, fix the bug, play it back forward again. Pretty slick stuff. And the thing I'm most excited about is this new language, it's called Elm. Has anyone heard of this? Yeah, this is good stuff, isn't it? Elm is a purely functional language and it takes away a lot of stuff. It has no classes. It has no nil. It has no loops. It has no variables. And it's strongly tied. If it compiles, you're guaranteed to not have runtime errors. That sounds crazy. It's like, it's literally like a quarter of Ruby. Like, it has like a quarter of mini language features. It's the most beautiful example I've ever seen is making something great by taking stuff away. And I'm gonna show you my little demo here. It was also very, very fast. And so this is my Kinect 4 game in Elm. You'll notice this is running in Chrome. It compiles the JavaScript. So this is a language for front-end games. Interestingly, it enforces that pattern. That pattern of state managers going in a loop with pure functions, it enforces that. It is impossible to write a program in Elm that does not follow that architecture. Because it's impossible, every single program you write in Elm is out of the box, time-travelable. It's, which is so nifty that they built it right into the language. I can actually, right here, go yank, add a query string, debug. The time-travel debugger that's built into Elm pops up on the right side. I can start to play Kinect 4. Well, I didn't like that move. I can pause the program. I can start to, sometimes there's a little lag. I can start to go back in time. I can start to go back in history. So because the language enforces it, every single program in Elm is automatically time-travelable. That's pretty neat. So just a few resources before I hand this off. All my code that I made is online, the block source solver, my new hamster matrix gem, my Ruby version of Kinect 4, my Elm version of Kinect 4. I highly recommend this course, principles of object-oriented design and Scala. Some great reading if you want to read more about persistent vectors. There's the article that I took those graphics from is right there. If you want to read about Git, being a purely persistent data structure, that's in there. The value of value is by Rich Hickey, modern classic. Highly suggest that if you want to learn more about this really, really cool stuff. I am Brad Urani. I'm addicted to Twitter. Follow me. I'll follow you back. Connect with me on LinkedIn if you want. I've got a blog. I don't update it very much. And usually when I do, it's me complaining about what I don't like about ActiveRecord. So, I work at Procore in Santa Barbara, California, aka Paradise on Earth. We're one of the, we make construction management software. We're one of the diamond sponsors at this conference. We've got a booth at the end of the hallway staffed with great people. All the people we brought are engineers, not recruiters. Highly recommend you check it out if you're interested. It's a great place to work. We're growing fast, hiring like crazy. We're also throwing the party tonight. It's at eight o'clock at Howell on the Moon on the Riverwalk. It's gonna have dueling piano bar, a band, free drinks for two hours. And raffling off some cool stuff. I think an iPad Pro and things like that. And that's my talk. I will tweet this and make sure that it gets out on the internet. Follow me on Twitter and I will tweet this and you can find my resources. I'll tweet the slides and the demo. All the stuff some might get, by the way. Thank you very much. Thank you very much.


Welcome to this short video on Fibonacci retracements. My name's Ryan Ododi. I head up Product Development here at CMC Markets and we're going to walk you through how you can use Fibonacci retracements in your trading strategy. But before we start, we need to understand a few basic principles of support and resistance because these are the key elements of what Fibonacci retracements allow us to do. So let's have a look at the screen and we can have a look at a couple of examples of how you can draw in your own support and resistance levels. So if we're looking at the market here on Tesla, you can see that the yellow line at the bottom of the screen is our support line. This is an area of support where the price moves down, the buyers come back into the market. So you can have a look at an example in the blue circles. Each time the market came down to that support level, the price went up in value. Went down, went back up in value. The opposite of a support level is a resistance level. Now a resistance level is higher than the current market price where the sellers come back into the market. So you'll notice a couple of examples here where the market reached this level and fell in value. Reached this level and fell in value. Now support and resistance levels, you can trade in a number of different ways, but the two key ways of trading it is that you think either history will repeat itself or that history won't repeat itself and the trend is broken. Just to give you an example, when we come down to this particular support here, we've seen this act as a support level in the past. So we think that history will repeat itself and we can put on a buy trade just above the support level. Now make sure to put your stop losses just below. Always place a stop loss when placing a trade on the market to give you that protection when the market moves against you. The opposite on the resistance level is when the market came up to this level here that I'm showing now, well we think, yep, it's going to repeat itself so we can put on a sell trade and we can then put on a stop loss just above the resistance level. The other way to trade is that you think that history won't repeat itself, okay? We think that the trends are finished and we think some sort of news will actually break us out of that particular support and resistance area. So what we can do there is we wait for the market to break above that resistance level and we place a limit order to buy into the market in that move. But again, remember, place that stop loss just below the resistance level. Now we've talked about support and resistance but what we want to talk about is the Fibonacci retracement levels. So if we go onto a chart here that I have for pound versus Aussie, the Fibonacci tool is available in your draw tools, simply click it and the way we draw on a Fibonacci retracement is that we find two key levels that we think are of interest on the chart. So I'm going to use the high and the low values of the price displayed on this chart level. So if I draw the lines in, you click on the high, you click on the low and what the Fibonacci retracement does is it automatically generates support and resistance levels at key levels. Now what are those levels? Well Fibonacci is key mathematical levels. Basically if you add the numbers of 0 and 1 together, you get 1, add 1 and 1 together, you get 2. 2 plus 1 is 3, 3 plus 2 is 5, 5 plus 3 is 8. If you keep going and then you divide the numbers against each other, the ones next to each, you get what we call the golden ratio and the golden ratio is 61.8%. And so one of the key levels that is drawn on the Fibonacci retracement is 61.8%. If you divide a number by the number to the right by 2, then you'll get the next key level which is 38.2%. If you divide it by the number 3 to the right, then you'll get the 23.6% level. So what the Fibonacci retracement levels are doing is providing you these automatically on the chart when you've determined the key high and low levels. So if we have a look at the example of pound versus Aussie, we've drawn it from the high to the low and then what we're looking for is the price action after that. So you can start to see that when the market moved, came up to that first retracement level of 23.6%, we started to see some sort of pullback. The sellers came back into the market and it acted like a resistance level. If we move further on down the track, you can see that when price reached the 38.2% level, the same thing happened. We started to see that the market was running out of steam, the sellers were coming back into the market and it acted again as that sort of resistance level. So here is an opportunity or a potential opportunity to look at the markets and potentially place a trade. You can see then it came back down again and then the 23.6% level active is at that support level again. Come back up, the resistance supports. So basically the Fibonacci retracement is trying to draw those levels in for you automatically. And again, one of the mistakes that clients make regularly with Fibonacci retracements is not using it with other tools. I think Fibonacci retracements are a secondary type of indicator. They provide you with an area of interest, but you should be looking at other tools, moving averages, support and resistance levels or trend lines to determine whether or not you want to enter that trade. One of those examples is the trend line. So if we go down to the draw tools, if I draw a trend line in, you can see around about this level, you've got an area of support, but it's a sloping form of resistance or support level. And it works exactly the same way as support and resistance. Each time the level reaches that trend line, bounces back up in value. That's an opportunity for you to trade. If we go and have a look at a couple of other examples, you can see here on Bitcoin. Bitcoin is a very technical type of instrument to trade. We draw the trend line between the high and the low of Bitcoin price. And we move forward, you can start to see that those key Fibonacci levels are again present and form those resistance and support levels. Now, support and resistance, trend lines, they're all great tools to use and work in conjunction with your trading strategy. Fibonacci retracements, whether or not you believe it or not, it's up to you. But basically, if a lot of traders are using the same tool, it becomes a self-fulfilling prophecy. So all traders or all those traders using that tool are looking at the exact same sort of key levels. So, you know, have a look, place them on your trades, on your charts and see whether or not you can include it as part of your trading strategy.


French defense minister Sebastien Lacourneau has announced that Paris will soon be able to supply Kiev with 78 Caesar self-propelled Howitzers and will increase supplies of shells to meet Ukraine's urgent ammunition needs.At a press conference, Lacourneau said that France, Ukraine and Denmark had reached an agreement to finance the delivery of Caesar 155 mm self-propelled Howitzers, which would allow Paris to deliver them quickly.He added that France also aimed to supply Ukraine with 80,000 rounds. With ammunition for 155 mm guns this year, compared to the 30,000 it has provided since the start of the full-scale invasion.In addition, Lacourneau noted that France was involved in the search for existing stocks of gunpowder and ammunition that could be purchased from countries outside the EU as part of Chekia's initiative, under the plan. The Czechs seek to obtain 800,000 artillery shells for Ukraine. Czech leaders previously said the first shells should be delivered to Ukraine no later than June. At least 18 countries have joined the initiative, according to officials in Prague.at the same time, Lacourneau said that European countries should reduce their dependence on the United States to ensure security on the continent. This is an absolute necessity. I think it's wrong that American taxpayers should pay so much for the security of Europeans, he said. Russians build railway to Burdiansk, but it's vulnerable to Ukrainian strikes. The Russian regime is constructing a railway in the occupied territories of Ukraine. However, it is vulnerable to precision strikes by Ukraine, according to the Ministry of Defence of Britain. Russian President Vladimir Putin announced on March 18 the construction of a railway branch from Rostov-on-Don in southern Russia through temporarily occupied territories of Ukraine to Crimea. According to Putin, the first segment of the railway allegedly restores access to Burdiansk. However, British intelligence emphasises that the existing railway passes through territory vulnerable to Ukrainian long-range precision strike systems. The new railway branch, nearly 60 kilometres long, south of Donetsk was under construction for eight months. It is almost certainly one of the largest infrastructure projects. Russia has carried out in the temporarily occupied territories of Ukraine and re-establishes the rail connection denied by the fighting outside of Donetsk the summery states. At the same time, intelligence believes that one of Russia's goals will be to support activity in Mariupol. The British Ministry of Defence stated that Russians are likely to seek to restore, as of Stahl, and other facilities destroyed in 2022. Russian forces seized Mariupol and its district in the spring of 2022 after months of fierce fighting. Afterward, the occupiers turned the ruined city into their military base. According to satellite images published online, Russian occupiers intend to connect Mariupol with Russian cities such as Rostov and Taganrog and other major cities in the Donbas. They have already begun construction of a road. The road will pass far from settlements. This may be linked to the difficulties arising from expanding an existing road. When it destroys Russia's logistics capabilities in Crimea, storm-shadow missiles are at work again. The Ukrainian armed forces have successfully hit large landing ships Yamal and Azov, a communications centre and several infrastructure facilities of the Russian Black Sea Fleet. Pavlo Narozny, founder of the charity organisation Reactive Post and military expert told RadioNV. Most likely it was a cruise missile strike or a storm-shadow or, for example, a modified Neptune, which is also a possible option. In any case, this is a very powerful strike. Narozny said he believes it was a successful attack on Russian logistics. Russia has quite a few large landing ships because this is probably the sixth ship hit. If they are not damaged but destroyed, it is also a very powerful blow to logistics because these ships can transport either a battalion or armoured vehicles. But usually, Russia employs them to transport shells, shaheads and ammunition. These ships are mostly used for ammunition. This is a very powerful blow to Russian logistics, he added. An oil depot located near the airfield was hit, which means the fuel for warplanes was most likely burned. The expert adds, Russia suffered losses in personnel as propagandists write that up to 50 soldiers were killed, 30 of them officers said Narozny, citing Russian mill bloggers. Three aircraft were also damaged at this airfield, the military expert said, with reference to Russian war correspondence. Late in the evening of March the 23rd, there were reports of the arrival of cruise missiles at a main communications centre of the Russian Black Sea fleet in occupied Sevastopol. Ossint reports on X. It looks like at least three Ukrainian storm shadow cruise missiles have just crashed into the main communications centre of the Russian Black Sea fleet, a blogger said. As we are informed, the missiles struck in the main special communications centre of the Black Sea fleet of the Russian Federation on one Nikolai Musika STR, the Crimean Wind Telegram Channel confirmed the information.


Classroom activity that are great for kinesthetic learners, FlySWAT. The FlySWAT game works best for vocabulary review, and is nice to play at the end of a lesson introducing new subject material. Using PowerPoint, or merely write on the board, prepare a slide full of vocabulary words sprawling all over the page. Have a series of definitions and questions about these vocabulary words ready to read to the students. To make it extra fun, write the words on pictures of flies. Split the class in half and be prepared for a good time. Each team sends up one person to the front of the classroom, and they are each given a FlySWATer. Read the question aloud, and then the first student to swap the answer on the board wins the round. Note, you should declare the rule that you may only hit one word per turn, to prevent students from mindlessly hitting as many words as they can. Thanks so much for watching. We are ITTT, the leading provider for TEFL and TESOL training courses. If you liked this video, please subscribe by clicking the button down here, and click on any of the videos here on the left for more interesting teaching tips for getting certified to teach English abroad and online.


Today's fountain pen unboxing brings a little bit of myth and majesty to the sea. This is the Heinz B24 Majestic Mermaid fountain pen with turquoise trim. The resin is a really beautiful purple white and turquoise mix and the pairing with that turquoise trim really makes the little bits of blue stand out. You again see the Heinz logo on that finial and it is a threaded cap and the nib also matches the trim. And these nibs are electroplated with a nano ceramic so they're durable and they have good ink flow. The section matches the barrel and cap and the B24 is a cartridge converter fountain pen. You access the converter by removing the barrel from the section and the converter is already installed in your pen when you receive it. The Heinz B24 is also compatible with standard international size ink cartridges so you can switch those out as you'd like. Subscribe at Pinchelay for more new pen features and shop your Heinz pins at pinchelay.com