Hello everyone I'm Abby Frye from Moodle HQ. Today I have with me Marie Ashua who is our global head of products and has just presented on Moodle's product vision. Marie it's lovely to have you here. Hi Abby thanks. Marie I really enjoyed your presentation. One of the things I noticed very early on was that you talked about the product vision of Moodle, not just being Moodle's product vision, but actually the vision of the community. Can you talk to that a little bit? Yeah absolutely. Well we don't build Moodle on our own. Moodle is built by our Moodle HQ developers and UX designers but it's also created by thousands of people out there in the world that contribute to Moodle regularly. Every one of our release includes at least 30 different new improvements and features and sometimes that number can go up to a hundred. We haven't developed ourselves that people have contributed to Moodle because they believe in the project and they want to see it improved and those community members also are instrumental in all sorts of other things like doing our QA testing or translating Moodle in the hundreds of languages in which it's available. So this vision for the product is designed to really unite us all along some key development things that we can all focus on to drive Moodle forward in the direction that we think it needs to go to stay relevant and competitive and useful in our market for decades to come. That's lovely and it is really the power of open source technology of course. So what is this vision? What is your manifesto that you explain to the audience? So the vision is three key development themes but it's premised so the decisions that we've made in terms of what those development themes are and what key features and enhancements we want to focus on are. They're all based on our manifesto and our manifesto we created it as part of the vision really because we wanted to ensure that we were clear on our why, our purpose and our raison d'etre and it's really very much about ensuring that education is available not as a privilege but as a right for everyone and that no matter your location or financial situation or circumstance you can have access to quality education and access to the best experience Moodle can provide and a lot of the vision at the moment is thinking about how do we unlock the potential of Moodle and make sure it gets in the hands of more people because so many people can do amazing things with Moodle but unless you have the technical acumen to or access to resources to help you do that you just you get not as good value as Moodle as you should so how can we make a product where everybody can benefit from its full potential that's at the crux of our vision. Wonderful and of course that's very closely aligned to our mission of course. Exactly. And I noticed that you talked about creativity I think is one of your themes and how nice is that because we're talking about technology and it's really nice to connect that to the concept of creativity. Yeah. So our first theme is called unlocking creativity and we really want to ensure that if you are a learning designer or a teacher or learning and development manager and you have content, learning content that you want to make available out to the world Moodle is the best tool to do that and it facilitates easy content creation, easy content sharing has a good look and feel is easy to use and all of those things getting those things right allow people to create on Moodle. They have to spend a lot less time trying to understand how to do things and just can spend a lot more time making beautiful things in Moodle and useful things in Moodle. And there's this story that really kind of inspires a lot of this theme from a teacher in Germany who created she's one of those people who know how to do magic in Moodle. She created a course in a few days for schoolchildren who were fleeing war in the Ukraine. And it's this super simple course, but it's beautifully made. It's really easy, embedded is translations from Ukrainian to German so they could learn how to say hello and thank you. And within a few days, because she's really great at what she does and so creative in Moodle, she was able to give all these little kids something to do when they went to school for the first time after fleeing their homes in Germany. And it's that kind of power that we want to unlock in everybody who's using Moodle. Absolutely. It's like a toolbox that they can build their own experience and really unlock their creativity as an educator or trainer. So that is really awesome. You use another humanist term in your themes, which is around collaboration or connection. Collaboration. Yeah. Yeah. And is that a technical collaboration? It's a little bit. Yeah. So that one's not as beautiful as creativity, but actually it's very important. So one of the magic pieces of Moodle is that you can plug it into anything. We have a database of over 2000 plugins that are contributed by the community and you add that plugin in and all of a sudden Moodle can do more than it does out of the box. But one of the challenges behind that is the connections that we build between those plugins in Moodle are not really stable. And if something changed within Moodle, then often the plugins have to change. And when you're an institution and you use a lot of plugins, new themes, extensions and customizations that can be quite challenging. So you want to keep up with the new versions of Moodle because it has new features and new developments and even things like security features that are really important. But the effort that it takes to continue up with our new versions that we release every six months can be quite heavy. So we want to try and simplify that and make that collaboration between the external technologies and Moodle Core itself easier to manage. So that's a key part of that. So in it is collaboration, but it's technical collaboration. Well, that makes sense because we want people on the latest version of Moodle. It's an important priority. Yeah. Finally, what's your last theme? Optimizing outcomes. And in that space, we are really talking about learning outcomes, right? So Moodle is there for a purpose for people to learn something on it, right? And so how can we make the learners have a better experience in Moodle in the sense that we give them tools that might help them save time, same effort, get better feedback faster or support when they need it most. How can we optimize outcomes for their teachers or their instructors or trainers where we are helping them save time, again, save effort, enable them to connect more directly to the students who actually need them. So have enough insights to know that student needs my help this week. I better get into that. So providing extra tools that allow them to do that. And then for our Moodle administrators, the people who operate and run Moodle, how do we make Moodle leaner, cheaper to run, easier to maintain, easier to administer. So optimizing their outcomes with that lens. And we're seeing a lot of ideas in that space that are emerging from the AI space, particularly those learner focus tools and teachers focus tools that can help them save time and effort. And that rapid feedback is really coming to the fruition with AI. And we've already seen in the conference, a lot of people present on real life examples of where they're doing that right now with Moodle. Because in that plugin ecosystem of 2000 plugins that I was telling you about earlier, there's already some great plugins that allow you to unlock the potential of AI with Moodle today. So I like the idea of connecting AI to actually allowing people to save time and effort so that they can engage more deeply and more socially and learning experiences. Exactly. So they can focus on learning and not the administration of learning. Yeah. So important community information. How can people become involved? Yes. So we've got two pretty good ways that you can actually hands on help shape the vision and actually help us execute to that vision. So hands on shaping the vision. We've launched very recently something that we call a product advisory group for our community members. After an embedding period that we're going to run exclusively with our Moodle user association members. We're going to open that up to everyone who wants to participate. And if you go on Moodle.org and do some searching, you'll probably find where you can do so. But you can send us a little note and say, Hey, I want to be part of the Moodle community PAG for our learning management, our LMS product, not workplace, just LMS. And in that product advisory group, you'll have the opportunity to actually shape our roadmap. Vote for the things that what you think we should be doing by we're going to do that through some card sorting exercises, which is always kind of fun, suggest new ideas. And those groups will be meeting every eight weeks or so, we're going to try and rotate them in terms of time zones and time. So everyone around the globe can participate. And I think we have something like about 80 to 100 people who've already signed up. So we've we're ready for it to scale the processes that sit behind it are there so that we can have more people. And it's a direct voice on the roadmap of Moodle, which is, you know, the vision, what we're actually doing. Word of warning, it takes a little work. So if you're going to be part of the PAG, expect that you will be doing some work, maybe a couple hours a month or something like that. So but we really do want people to come in who care and who want to have something to say about where Moodle's going. So that's probably that the shaping the vision. And then helping us execute on that vision is the Moodle product experience lab. So through the experience lab, you sign up. And when we're doing things like designing a new solution or trying to see if the way that we've designed something already works for you as somebody who uses Moodle or somebody who's never used Moodle. Actually, we'd love to have no Moodle users on there. And you might test a prototype with us. So the experience lab is the place that we go to first when we want to co design with our end users and ask them questions and do some user testing. So signing up for the experience lab a little bit less work than the PAG, but also a really great way to help shape the future of Moodle. Brilliant. Thank you so much. A very speedy summary of the product vision. Thank you. Thanks, Marie. Thanks. Thanks, everyone.


All this month, get up to $50 off any Android smartphone from Appalachian Wireless, any Android you desire. All $50 off with two-year agreement, better service, bigger savings, that's today's Appalachian Wireless and East Kentucky Network Company. For the past few weeks, national headlines have centered around Hurricane Harvey, which damaged 100,000 homes and claimed at least 40 lives in the Houston area.  Both of these storms will leave millions of Americans devastated. As they have done many times in the past, the radio and television stations of East Kentucky Broadcasting are partnering with Pikeville Medical Center to host a radio telethon to raise money for relief efforts on Thursday, September 14th, beginning at noon. It's the kind of thing we do at times like this. We really want to help and we know we've got great listeners and great viewers and they want to help, so this is a good opportunity to pull everybody together and see what we can do when we really pool our resources. And Johnson says by bringing two companies together with one common goal in mind, much more can be accomplished. That partnership with Pikeville Medical Center is so powerful. Their employees donate so much in terms of giving up their vacation time and turning that into cash they can donate. They also do payroll deductions. The past two radio telethons have raised money for natural disasters that occurred here in Eastern Kentucky. But she says now those in our region who received help have the opportunity to pay it forward. The people around here are accustomed to natural disasters. We've experienced our own floods and blizzards and terrible storms, so we know what this is like and that's a big reason I think people want to help so much. And that opportunity will come Thursday beginning at noon on the radio and television stations of East Kentucky Broadcasting as well as online at EKBTV.com. And volunteers will be on hand to accept donations as they come in, whether by phone, online or in person. Also we'll have people outside taking donations. It'll be like a drive-through. If you want to come through that circle and drop off your change from your car or from your pockets, or hopefully people will have done some fundraisers between now and then they'll have some bigger amounts to bring. The radio telethon will be broadcast from the second floor atrium of Pikeville Medical Center. In Pikeville, I'm Shannon Deskins for EKB News.


Hi everybody, Joe for jaspyscasebrakes.com. Happy new release day. Coming at you with our first live look at 2022 Tops Tribute Baseball Six Box Full Case. Pick your team, number one, from jaspyscasebrakes.com. A very big thank you to everybody here for making it happen, appreciate it. Austin ended up with that last spot, Mojo Starr next to his name. Thanks everybody who got their team straight up, I appreciate it. We had a big 15 team random number block as well. So basically we pulled those teams out, turned it into a serial number break for that. So thanks everybody for getting in. We'll tribute to break right afterwards. If it's sold out, then yes, I don't think it is though. All right, but let's sell it out, jaspyscasebrakes.com. And there we go, 2022 Tops Tribute Baseball Three on-card autographs in three game use memorabilia cards per box. That's nice. Good luck everybody. We're a big fan of the Tribute Baseball. I always thought that this looks really nice. The hit is in the middle. So I'm gonna slide these cards up to the top. Think someone just bought all the rest. Don't think so, there's probably a filler for it. Keep an eye out for that, Yohan. So someone double check that website, jaspyscasebrakes.com. Ah, there you go, Adam. Thank you for looking. Yeah, there's an 18 team random number block, just like we did with this number block right here. And remember, as stated in the number block, there's gonna be a lot of non-numbered base cards for this group of teams. That'll go to one person as one lot right here. Slide all the base cards out first. All right, there's all of these right here. Although that goes to Austin, because that's a red. That'll go to 23 out of 50 on the number, that goes to Kenneth. Kenneth has the cardinal straight up. Really nice design. I kind of like the wood border right there. Kind of gives it a warm look and the hollow foil. I dig that. Tribute always has a really nice clean design. All right, now let's go with the hits. First one out of the gate is a triple relic, Joe Maurer. 007 out of 199. That'll go to twins seven. Ray, what's going on? How are you? So twins seven is for Jeff. The autograph, Shane Bieber, 116 out of 150. Nice Shane Bieber for the Cleveland Guardians. So in case you're wondering how the number blocks work, we go by that digit right there. So number six. Cleveland six. Chris Perrin. Cleveland, this is for you. I'm Tom Glavin. Is stamp of approval, Aaron Judge, 117 out of 199. That goes to Justin and the Yankees. Now what's great about these, Justin, is that they got the MLB hologram sticker here. It's VT049-795. VT049-795. If you go to mlb.com slash authentication, you could type those letters and numbers in and you'll see when this jersey, where that jersey came from, what date it came from. And a lot of times you can go to like baseballreference.com or something like that and look up that day and see if, see what Aaron Judge did that day. Maybe nothing or maybe something. We got a two player dual relic. Both Braves, John Smoltz, Shipper Jones. Nice, five out of 99. So Braves five is for Oliver. There you go, Oliver. And we got a Stuart Fairchild autograph. Nine out of 10. Nice low number there for Mark and the Diamondbacks, picked up the snake straight up. That's a really cool design. You kind of see the red foil right there too. It really pops. Behind Garrett Cole is another autograph. Wow. Yes, 22 out of 25 solid gold grates. On card autograph, Carl Yastremski. And that is Jonathan who bought the red socks straight up on the board. We got more in the store folks, jaskyscasebrakes.com. The gang was saying that pick your team two is in some sort of filler. Random number block and a filler for the random number block. So be sure to get your spots there. Let's knock out another one of these. A lot of value in that number block. And remember pick your team three until I have 24 teams left.  Especially if you want to avoid a number block situation. Or if you love the number blocks, we can do it that way too. Whatever makes the breaks fill. There's Jonathan, love the yes. Nice, congrats. How sharp these cards are. I really dig that. There's Josh Hader and the big unit, Randy Johnson, Astros edition, 57 out of 99. Scott with the Stroze. Ooh, Oliver looked up that Aaron Judge stamp of approval. Judge info. Original hologram, Aaron Judge White, home jersey worn on October 7th, 2020 for game three of the ALDS, raised at Yankees. How did he do that? Does someone look up the box? Now you gotta look up the box score. See how he did that day. And it was autograph too. So I don't know, the autograph must be somewhere else but we got a piece of that jersey. See, that's how cool those hologram stickers are. There's young Carlo Stan, 26 out of 50. Triple relic for Justin W. There's a Justin S in this break too. Justin W and the Yankees. We got another stamp of approval, 33 out of 50. Another Yankee, Corey Kluber, VT052671.  That's another one for Justin W and the Yankees. And we've got another Stewart Farrah child this time out of 99, 89 out of 99 for the D-Backs. That's gonna be for Mark. Oh, this is nice. Tribute to MVPs. Dale Murphy, your 1982 and 83 NL MVP award winner. Back-to-back MVPs for Dale Murphy. I didn't realize that. That is 23 out of 25. So that goes to Atlanta three. That'll be for Arayano with that one. Nice, nice Dale Murphy. And we've got a Matt Veerling, 150 out of 199 for the Fightin' Fills. Phillies are a number block team. And that'll go to Philadelphia zero. That'll be for Chad. And behind Yordan Alvarez is a dual relic. DJ Lameyoo, Glaibor Day, Glaibor Torres. Justin W with that one. That's 006 out of 199. Nice, Oliver looked up the cluber too. Thanks, Oliver. Gray Road, Jersey, worn April 27th, 2021. Yankees at Orioles. Maybe a little game log research on baseballreference.com could let you know if you made a start that day or not. Yeah, that's a really cool feature. I hope that over the years that we'll see more and more of that in our relics across a lot of, across more products. Bonus hit or just an extra base card? I think just an extra base card. Unless that's a hit? No, it's not. Yeah, I hope Fanatics just kind of deploys that hologram sticker more often. I think when relics first came out, you know, way back when I think everyone was just happy to see relics. And now I think, now I think there's a little more demand for now we wanna know where these relics are coming from. That's hopefully that's a next level situation there. That's a cool picture of Reggie Jackson. Aha, Jaren Duran rookie card for the Red Sox. That's gonna go to Jonathan. I think these rookie cards are fewer and far between in tribute, which makes, you know, especially for the top players and top rookies and makes their, gives it a little additional value. And there's Rhino, right? They're five out of 99, Cubs five. That will be for Oliver, Cubs five. All right, your hits. Dual relic, Noma, 106 out of 199. Does a lot of studio work for the Dodgers TV network out here. Noma, goes to Jonathan and the Red Sox. Nice dual relic piece of his lumber. Real Muto reveals a Paul O'Neill autograph, 83 out of 175. Nice break for the Yankees, Justin W with the Bronx bombers. There you go, nice. Jonathan's saying rookies are about two per case. So yeah, that does give it a boost in value. Got a triple relic, Johnny Bench. Nice, five out of 10. Like that Reds logo right there too. All right, Austin with the Red Legs, last spot Mojo. Don't look now, but the Reds been playing pretty well. Oh yeah, Jersey number on that Johnny Bench too. Good eye, Oliver. There's Matt Olson, A's edition, 85 out of 150. Oakland A's are a number block team. So that goes to Oakland five. What about that digit right there? That's for Oliver, Oliver and Oakland five. There you go, Oliver. Next is another stamp of approval, 97 out of 199, Rhyme Latapia. And that is VT044633, I think. Numbers are kind of small.  And the last one here behind Jack Flaherty is Raleigh Fingers, four out of 50. Another Oakland A, different number. Number four, Martin with Oakland four. All right, we are halfway through this six box break. Another 10, 15 minutes on this. Nice, I got those numbers right. Or Oliver, look it up, thanks Oliver. Rhyme Latapia, Game News Jersey, June 18th, 2017. Giants at Rockies.  And you'll be able to see what kind of day he had. Donald in the Rockies. Maybe he did something cool that day. There was an old, remember Strata, I think it was called Strata baseball. Strata baseball also had those hologram stickers. We saw one for, I think an old Padres catcher, I wanna say. And the Raleigh was a white jersey but with like red stains on it. Like it looked like juice, Gatorade. So we did our due diligence and we looked up the hologram sticker, we looked up the box horror and turns out it was a walk-off home run. So that was like the Gatorade celebration from the walk-off home run, it was really cool. There's Steve Carlton, 88 out of, 88, can't be 80 out of 25, it's eight out of 25. That'll be for Phillies eight. It's gonna go to Jeff. Nice little back of the baseball card here too. Oh, nice, Oliver, thanks. He looked it up, Ryan Maltopio pinched it in the ninth of that game. One for one with a run scored, Rockies one, seven, five. I love that it could add like an additional story to the Raleigh. There's Buster Posey, 12 out of 99. Giants, big boys, 007 with his Giants. I think they did a Buster Posey little tribute, pregame tribute the other day. We've got Max Krannick, Pittsburgh Pirates, 47 out of 99. Pirates beating my Dodgers today. Pirates are a number block team, so that goes to Pittsburgh seven, which will be for Jeff. We've got a Gene Segura, 43 out of 199, stamp of approval. That's for Ariano and number Philadelphia three. And that is VT 015, 092. And there's the other rookie card right here that's Jake Berger, and behind Jake Berger is Patrick Corbin, 41 out of 199, marked with the Nets. Got the Nationals straight up. Here's the other rookie card for the White Sox, and that is not numbered, so it'll go to that non-numbered group. All right, behind Joe Maurer is Dustin Padreau, a laser show, 124 out of 199. Two-color triple relic for Jonathan and the Bo Sox. And behind Steve Carlton is Josiah Gray, nice, 117 out of 150, former Dodgers prospect. Now a National, and I think with every start, he's been getting better and better. One of the top Dodgers pitching prospects. Went to the Nets in that Scherzer-Trey Turner deal. All right, the next tribute, we need to do a number block, a random, fill up the random number block spots, and do the filler for the random number block. So I would highly encourage everybody to get into that. And if you just want to get your team straight up, I would encourage that as well. So we got a lot of cases of tribute baseball on the side right now. Or actually two cases, but a lot of teams to pick from. It's Justin Turner, he's starting to heat up this season. There's Dennis Eckersley, 47 out of 50. A is seven, it'll be for Jeff. All right, there's Sal Perez and a dual relic, both for the A's, 87 out of 199. Jeff with Oakland seven gets the Matt Chamin and the Matt Olson. Both Matt's unfortunately no longer with the A's, they've moved on. It's still nice. Behind Rhino, should be an auto. It is, it's JT Real Muto. 163 out of 199. So Philly's three, that's gonna be Adriano with number three, behind Corbin Burns. A Dodgers triple relic, there's Justin Turner. 128 out of 199. Dodgers are a number block team, so Dodgers eight is for Jeff. I think that's another rookie card here, nice. Luis Gill, it'll be for Justin W. and the Yankees. And we got a Mason Thompson, 91 out of 150 for Mark and the Nationals. We got Justin Verlander, 13 out of 199, stamp of approval. That VT, 053, 116. Verlander took a no-no, kind of late yesterday, but you know who did it? This kind of happened late on the West Coast, so read Deadmer's, Angel's rookie, read Deadmer's with the first no-hitter of the season. So that's a pretty awesome day for him. I think it was a pretty efficient no-hitter too. I think you only threw 108 pitches. And another Joe's, I agree, 34 out of 50, another one for Mark and the Nats. And Scott has the Astros, by the way, so you'll get that Verlander. Nice, thanks Oliver, looked it up, Verlander. Oh, that's kind of cool. It's Verlander Gray, a wager, as he won on May the 5th, 2019, Astros at Angels in Mexico. That's how those stamp of approval cards are so cool. And I think that's one of the underrated features of Tribute Baseball. If you have that additional information, you have an additional story to tell behind it. If you're trying to sell a card or just keeping it for yourself, you've got an additional story to tell. Ooh, he had to start that day too. He went six and a third, four runs, five hits, seven Ks. Got the win. Got the win to go five and one on the season. Nice, thanks Oliver. See? Now that seemingly plain gray jersey now has some extra weight behind it. Look at the centering on that, rough. All right, there's a Manny Machado as well, 20 out of 50 for Ariano and the Padres. Got the team straight up. And we got a Corey Kluber. Nice, not only do we got a hologram sticker here, also an autograph. 10 out of 50 for Justin W. and the Yankees. Got the Bronx Bombers straight up. So on that, is it the same jersey as the other one? VT052337. Nice, maybe a start that day, I don't know, but take a look ladies and gentlemen. MLB.com slash authentication. There's Matt Olson, eight out of 150, Oakland eight, Jeff. Got a Giancarlo Stanton, 13 out of 25, home jersey. Kluber was from April 27th, 2021, Yankees at Orioles. The Giancarlo stand to 25, nice low number there. Another Yankee. VT053688, another one for Justin W. and the Yankees. Behind Bregman is a Triple Relic, Miguel Cabrera, 29 out of 50. Tigers are a number block team, Detroit nine.  Jose Ramirez reveals a new jersey. Ramirez reveals a dual relic Byron Buxton, 40 out of 99. Minnesota zero, that'll be for Chad. Oh, that was a start for Kluber. Nice, five Ks over six and two thirds and a win. Nice, so there you go Justin. Little extra story behind that jersey right there. And Andre Dawson, what year is it? Reveals a Tom Glavitt, 43 out of 99. Atlanta Braves, Braves three. Atlanta three, that's for Ariano. Nice, and there you go gang, that's the break. Thanks Oliver for your help looking up those stamps of approval to hologram stickers. We'll do a quick little recap as well. But first we're gonna randomize those non numbered base cars to somebody. So let's gather everybody's names here. New dice, new list, name on top. We'll get some extra cards. After four times, three and a one. One, two, three, and a one. Fourth and final time, and that'll be for Martin. Martin, you'll get all the non numbered base cards for that group of teams right there. All right, and let's take a quick look at the break. So that was nice. Oliver looked at the Giancarlo Stanton spring training game. March 7th, 2021. Sharp looking release ladies and gentlemen. I just feel like tribute every year is a little underrated. People kind of sleep on the tribute baseball, but you can kind of see the quality here already. That was really nice.  Some nice stuff in here boys and girls. So I hope you keep working through those fillers and the random number block spots and whatnot. I would appreciate it. Thanks for watching. Thanks for breaking with us. I'm Joe for jaskyscasebreaks.com and I will see you next time for the next tribute baseball break, volunteer as tribute, bye bye.


Okey, this is a talk about soft typing Nw soft typing is something that Mark spoke about at Rubynoise for last year And he spoke about it as one of the possibilities for Ruby 3 So word of soft typing, well in essence, it's a way of combining the benefits of static typing, with the flexibility of dynamic typing So to give you an example of what this might mean here's a little piece of Ruby code, very simple thing It's just a method that takes an argument, anything and then comes times 2 in it Now, because this is Ruby, we don't need to tell it anything about the types, but this also means we don't know much about the types but there are some things that we can work out. So, for example, just by looking at the code, we can say that this thing, whatever it is, has to respond to the times 2. And we go a little bit further. We can say if we call this method passing in some kind of object, this object also has to respond to times 2. And we know that if it doesn't respond to times 2, then our code is going to explode with some kind of runtime error. The important thing to get across here is, when I say static typing, static means that we can work stuff out without having to run the code. This is a huge idea for Ruby. Previously in Ruby there was no way of thinking about things like correctness without running the code, but this is a big philosophical shift in the way that we think about things like correctness in Ruby. Given that this is a candidate for Ruby 3 and given it's such a big deal, you think a lot of people would be talking about soft typing, but nobody really seems to be. There was one talk by Tom Stewart at RubyConf Australia called Consider Static Typing, and this serves as a kind of primer on types and what they're useful for, and at the end he says a little bit about soft typing in Ruby, but not that much. But apart from that, I've heard nothing. And even worse than that, going to conferences and speaking to people, nobody seems to be thinking about it and nobody seems to be talking about it. So I'd like to address that today, and I thought it would be a good idea to give a talk about what soft typing is and how it works, and that really means talking about type reconstruction for a lit binding structurally-typed language such as Ruby, and then working out how we deal with inevitable failures. I thought it would be a good idea to talk about this, but then I wrote the talk and it turns out it's actually really boring. There's an awful lot of really heavy academic theory in there, and I think a lot of you would just get up and leave. And worse than that, it's boring and it's also really difficult. I mean, I'm not sure I actually could talk to you about how soft typing works. It's too hard for me, and if that wasn't bad enough, it's also really impractical. I mean, even if I could teach it to you by the end of it, all you'd know was some mathematics about type systems in functional languages like ML that have never left academia, and you couldn't really take that and apply it to your everyday Ruby work. Boring, difficult and impractical. This is going to be like the best talk you've ever seen. Now, I think this is the way a lot of people think about type theory in general, and certainly if you've read the soft typing paper, these are some words that are very good for describing it. But this isn't the way that I feel about type theory, and it's not the way that I feel about type theory in Ruby. I think it's actually a really exciting area. I think it's something that we can engage with as Rubyists, and I think it's something that can improve our Ruby code. So, what I want to do today is try and make it more accessible. I can't tell you everything you need to know about soft typing, but I can maybe tell you where to start or give you an idea of how to explore this topic. I'm going to do this today by writing a static type analyser. So, what is a static type analyser and how do you write it? Well, there's a talk by a guy called Matt Might. He's a professor at the University of Utah, and the talk is what is static analysis. Quite early on in this talk, he gives a general formula for how we write a static analysis tool like a static type analyser. He says, what we do is we take an interpreter and we make it more abstract. So, to give you an idea of what this means, imagine you've written a programme and you feed it into the interpreter, and what the interpreter is designed to do is run the code and produce the resultant value. So, you might run your programme and it produces the value 42. Now, to make this more abstract, we still return the same kind of thing just with less detail. So, instead of saying the answer is 42, we'd say the answer is just a number. It's something more abstract about the value. Now, it doesn't have to be as clearly about types as a number. You could say it's a number greater than 10, or maybe we just say it's a value, and that can be a useful thing to know on some occasions. So, I'm going to write a static type analyser by writing an interpreter, but I'm not going to do this for Ruby. Ruby is a very complicated language, and we get bogged down into details very quickly. So, instead of that, what I'm going to do is create a very simple language, a very simple programming language. Then I'm going to write an interpreter for this in Ruby. Then I'm going to write a static type analyser by making my interpreter more abstract. Okay, so this is a language I want to start with, and it is very, very simple. I can take some numbers and I can assign it to a variable, and then later on I can recover that variable. So, how do we write an interpreter for this? I think it's kind of helpful to think about how we interpret this as human beings. The first thing I want to observe is that we don't just see this as a kind of big amorphous blob of code. We break it down in our minds into some structure, and we say, okay, these different lines are different expressions in our language, and they're not the same kinds of expressions. We can say that the top line is probably an assignment, and the second line is just using a variable. When we look at this assignment line, well, the reason we think it's an assignment is probably because it's got equals in the middle of it. And once we recognise it's being an assignment, we can say the thing on the left-hand side is some kind of identifier. It's telling us where to store the value, and it's not just any value. We can look at this and say this is clearly a number. So, that's maybe how we see it, but for a computer it looks entirely different. It just looks like an undifferentiated sequence of characters, like an A in a space and equals and so on. So, the first challenge is to take this and impose the structure back on it. And the way we do this is by writing a parser. So, we're going to take this string of characters, feed it into a parser, and it's going to spit out some kind of structured data. So, how do we write a parser? Well, this is Ruby, so of course there's a gem for it. In fact, there are many gems for it. The one I'm going to use today is called Parslet. I find it quite easy to work with. And I'm almost ready to get started, but before we start I need to work out a name for this. Just for practical reasons, I need to name some classes.  And what do we call this? Well, maybe we can pick a name based on the characteristics of our language. So, like it's simple. I thought it was simple, it's like really, really obscenely simple. And this makes it kind of accessible at the start, but after a while we realise it's actually quite limiting. And not only is it limiting, the more we work with it, the more frustrating it becomes. So, I'm going to name it something that's like obscenely simple and really very limited and just becomes more and more frustrating. Oh, sorry. That shouldn't be in there. So, for no particular reason, I'm going to call this language Trump. Okay. So, let's start writing a parser. To do this, I'm just going to write a class and I'm going to call it Trump parser. And it's going to inherit from Parslet parser. And the way that the Parslet parser works, oops. Is you give it a set of rules that describe how to match the input string. Okay. And we're going to start by telling it where to begin. You give it something called a root. And the root that we identified when we first looked at the programme was that it was a series of expressions. So, we just say to start parsing this programme, look for expressions. Okay. Now we need to tell it what we mean by expressions. So, we'll write a rule for that. We'll have a rule that says expressions or a single expression. But we're going to repeat this. So, it could be more than one of these things. Okay. This is how we tell Parslet that this thing repeats at least one time. So, now we need to tell it what we mean by expressions. So, again, we just write another rule. We say an expression. Now, there are different types of expressions in our language, but we're going to start by just assuming it's always going to be a number. This helps us get started and we can add in the structure later. So, I'm going to say an expression is just a number. And finally, we'll tell it what we mean by number. Okay. So, a number is one or more digits. So, we can tell it to match a digit by saying match and then passing back slash d, which will match 0 to 9. Let me say there may be more than one of these. So, we'll say repeat, and there's going to be at least one. Okay. So, now what we can do is we can create like a sample program, a source string for a program. We'll just set it to be a number for now. And then we can create an instance of a or a parser class. We'll just call new and that. Then we can tell it to parse the input string. And then we look at what this... Oops. If you look at what this produces, we can see it gives the string back to us followed by this at 0. What this is actually telling me is that our parser will accept the input program. It thinks it's a valid program. Now, if we make it invalid, so let's say we add some letters into here that we haven't told it how to match and then we run this again, it throws an error and it says, I don't understand how to parse this. It rejects our program. We put it back to being a number and run it. OK, we don't want to match just one number and we want to match multiple expressions. So in theory, we should be able to do this. But when we run this, it explodes and it says there's something I don't recognize at character 4 which is a space character. So we need to be really, really precise with our parser which is very annoying when you're live coding. So what I need to do is tell it how to handle space. So I'm going to create a couple of rules for this. I'll say a space, we just want to match and then we can use backslash s which is any kind of space character. And there may be many of these. So I'm going to run this once. And then we'll add another rule which is called space question mark which says it's a space or it might not be. The reason we use this is because our first number is followed by space but our second number is not followed by space and we want a rule that matches both of those. What we then do is we say when we have a number, it may be followed by a space. OK, so the double chevrons just say followed by. If we run this again, we can see it now gives our numbers back to us. Now, this isn't very good. We don't just want a string back. What we want to do is apply some structure back onto our input code. So what we can do in parsley is we can say I'm interested in this thing, this number, and then we just give it a tag. We say match this as a number. And now when I run it, the output is very different. It's now an array of hashes and these hashes say here's a number that you told me to match and here is the bit of the input string that I identified when I matched this. OK, so that's how we match numbers. We can now bulk out our expression because we have more than just numbers in our language. We can say it could also be an assignment or it could be just a single variable. And now we need to write rules for these. OK, so the rule for an assignment is we have some kind of identifier and this is followed by an equal sign and then that's followed by some kind of value. So now we need to write the rules for all these things. So identifier we'll start with. So identifier, I've decided identifiers are just lowercase sequences of letters so we can match a to z, lowercase a to z. OK, this repeats at least one times and it's maybe followed by space as well. Equals is even simpler. So we write a rule for equals and this is just literally the character equals. OK, so straw here just means literally this character, we have fancy rejects matching and again this might have a space after it. Everything is going to have a space after it. Now value is interesting. The things that we can assign to any kind of identifier is not just a number. It could also be another variable or it could also be another assignment. So really what we're saying here is any kind of expression is valid as being the value. Then we'll just tag these things. So we'll say we're going to match this as a value. We're going to match the identifier as a target. OK. Let's get to it along now. And then we're going to wrap this whole up. I'm going to say we've matched a whole thing as an assign. OK, and then we have another rule that we need to write for variable. Now this is really easy. A variable is just an identifier. So we just match the identifier and we match it as being a variable. We just tag it. Now another couple of things I need to do. So I want to change my source string to be more realistic. I'm going to type A equals 6 and then A. Now you see we've got a new line at the end of here and there's a new line at the very end of our program so I need to tell it how to cope with these things. So we'll say it may start with a space and our expressions may also end with a space. OK. If I've typed this right first time live on stage which would be amazing. Oh, I did. OK, it works and it gives us back a structured representation of our input string. Whole day applause, this may still be broken later. OK, so what we've done so far is we've taken our source of just characters and we've turned it into these tree-like structures. We've imposed some structure back on top of it but I don't really want to work with arrays of hashes. That's not a good way of working in Ruby. So I'm going to take it a step further and turn these things into objects. To do that, parts that provide something called a transform and it's a similar principle instead of matching against our characters we're going to match against our tree and we're going to turn those into something more useful. OK, new class and it's going to be called transform and this is going to inherit from parcel transform. Again, we're just going to build up some rules on here. The output tree from our parser step looks a little bit like this. It's not exactly this but it's pretty close to this. If I create an instance of my transform and then I apply it to that tree what this does is it gives me back an unmodified version of the tree. OK, so it doesn't have any rule to tell it how to transform any of this so it just leaves it untouched. I'm going to start with variable because it's a very simple structure inside this tree. So the rule for this is we just say when we match the key variable followed by some kind of value it's just a simple value here just a little bit of text and I'm going to call that identifier and then we give it a body because there's a replacement for where they've been matched so I can just get it to say, for example, hello. If I go down and run my code again we can see that the variable has gone from the end and it's replaced it with the stuff in the blocks here. Now I don't want to really return a string saying hello I want to return a Ruby object that we can use so I'm just going to require a file where I've defined some basic objects and all that's in here at the minute is the initialiser to take an argument and then some kind of inspect so we can see what's going on. Now I'm going to use it in here so instead of returning a string a new instance of my variable class I'm going to pass on the identifier to that and then we can write something very similar for the other parts of our input string so we can write it for matching numbers and for matching assignments. So if I go down here and run this we can see that it's now turning into Ruby objects when it says assign, call on and then number call and so on this is showing me that it's matching my Ruby objects so we can now go from a source input string to Ruby objects and we're kind of in this situation now and these objects represent single expressions inside my program. Okay, so now that we can match stuff I can start to write the interpreter proper and what I'm going to do is I'm going to take each expression so we'll take for example this assign and I'm going to call eval on it and what I want eval to do is basically run this code for me and really what I mean is I want it to turn it into the simplest possible form it can. Now the simplest possible form from an assignment is going to be the simplest possible form of its value and the value here is a number so then we need to go again and say okay number what is your simplest possible form and for that I'm just going to return the Ruby integer so in this case calling eval on assign is just going to return the value of 6 now because it's an assignment we also need to do some side effect as well so we need to go to our environment at this point and say please remember that the identifier has got the value of 6 and that's it, that's what eval means when we call an assignment now if we're calling it on a variable we're going to go to the environment and say hey give me whatever the value is for the identifier A and that of course is also 6 so I'm going to go and pull this all together now I've written a class for the environment it's just really a wrapper around a hash that lets me get and set stuff using a nicer API but I've got all the parts in place that I can start writing my interpreter to do that I'm going to write a method called nodes and it's going to take some source string what I'm going to do is I'm going to take that and pass it to the parser and then we call pars and that passing in the string and then I'm going to take the output from that which is going to be some kind of tree I'm going to pass it straight into the transform and then that's going to give me the Ruby objects back so when I say nodes a single node is really just an expression in my program I'm just going to test that works because if that doesn't work we're going to be in trouble later so our program looked a bit like this and we just call nodes with the source and then check it excellent that's never happened before so we now get the Ruby objects back out again which is what we wanted so now we have our nodes we can write a method called interpret oops we can't because we can't spell and this is going to take the source thing again now when I said we were going to write interpreter by calling eval one of the things we had to deal with the side effecting and putting stuff into the environment so I'm going to create something called end which is a new instance of the environment in the program so we're going to put all our global variables then I'm simply going to take the nodes by calling this nodes method and I'm going to say I'm going to map these into take each node and I'm just going to call eval on them so I'm going to take node.eval and I'm going to pass in the environment at that point and then these eval methods will modify the environment as they go along so now we can replace this call to nodes with a call to interpret but this isn't going to work yet it says I've got to a sign and I've tried to call eval but I can't call this yet so what I'm going to do is go and write those eval methods and these are all very simple okay so to evaluate a variable it gets passed in the environment and I said we'd simply go and look it up in the environment so we just say m.get and then we pass and identify for a number again we'll write eval it gets passed in the environment but it doesn't use it we'll just chuck it away so it's a numerical value okay so all we do here is write value and then finally to evaluate an assignment it gets passed in the environment now I said to evaluate an assignment we go to its value and we evaluate that passing in the environment at this point okay then we take that and we set it in the environment so we say m.set then we'll use the identifier as the key and then we'll set the value so we go back here and run this we can see it now gives us a new array with each value set to six so when the value is the first expression it says the simplest form of this is just the value six and then if it values the second expression it then goes and looks up in the environment and says okay this is also a six so that's our interpreter and that's great but we're not really here to write an interpreter we're here to write a type checker so the next step to do is to write the type checking algorithm now this works just like eval so instead of calling eval on our on our nodes we're going to call type instead when we call type it works in the same way the assignment will go to its value and say hey value what is your type in this case it's a number now a number is going to be like a primitive type in this language so we can just give it a name I'm going to say the type of number is number type so the type of assignment is also number type and again because of side effects we're going to go and update something called a context now the context is just like the environment I mean it stores types so when I talk about context I'm always talking about types when I'm talking about environment I'm always talking about variables I'm sorry values okay so that's how we work out the type for assignment to work out the type for the variable it's the same process we just go back up to the context and say hey what's the type that's been set for the identifier A okay so we can go and write these things so in here we can say a new method called type it gets past the context these are going to look very similar to the eval so instead of saying m.get we say context.get and we just pass in the identifier okay for number we call type it gets past the context doesn't use it this is a primitive type so we say number type.new okay I need to go and write number type because I don't have that yet so we'll just write a quick class called number type the only thing inside here I'll just add an aspect method so we can see what's going on it'll just print out the number like that okay so that's the type for number the type for an assignment is going to be very similar to the eval for an assignment it gets past the context okay we go to our value we say what is your type passing in the context and then we take that and we set it in the context so it gets remembered for later pass in the identifier is the key and it's like that okay so if we come back to here we can then write our type check method in fact it's very very similar to the interpret method it's so similar I'm going to just copy and paste it always a good programming practice okay so we could call this type check now instead of creating an environment I'm going to create a context so we can remember that it stores types we'd still map over the nodes that it seems before but instead of calling eval we call type and instead of passing an m we pass in context okay and then down here I can change the call to interpret to call to type check run the code and you can see it says number for both these expressions so that's great what we've just written is something which is a type analyser for a very simple language and it does this without us having to add any type information to our source code it goes and works it out just by looking at what the source code is and this is okay but it's a little bit boring because we only have one type in our language so it's always going to say number so what I'm going to do is make this a little bit more interesting I'm going to add some more contracts to our language particularly I'm going to add functions because functions are pretty useful so to write a function I'm going to use the keyword fn it's going to be followed by a parameter list so say like x and y then it's going to have a body inside these braces and in this case I'll just return the first argument okay so that creates a function then we're going to assign it to a variable like we do for a normal value so we'll say like first is equal to a function which returns the first argument and then once we've created a function like this we can then call it by taking the identifier following it by a bracket and then passing in some arguments so we can pass in an example a and 2 now when we run this we would expect it to return the first argument so we expect to return a which has got the value 6 so I'll write an old code for functions here but I can go through quickly how they work and then show you in practice so evaluate a function I'm going to go through the parser step and then go through the transform step and it's going to spit out two objects two new types of objects either a function or a call like a function call when we evaluate a function it just returns itself okay it doesn't actually do anything at that point it just returns itself the reason we return self is because then when we assign it the assignment will have the type or the value of that function and it's that function that gets stored in the environment and that means when we do a function call we can then go to the environment and look it up by the identifier in this case first it'll return that function object and we just pass the call back to the function when we call a function we call it with two different types of arguments we call it with our list of arguments that we want to use for a function call and we pass in the environment at that point and the way that function violation works is actually really really simple we call it with our outer environment at that point but then we set up some special values we set x to be the first argument that's passed in in this case six and then y to be the second argument passed in in this case two then we go to our function body and we just call eval on that on each expression inside there but instead of calling eval with our outer environment we call it with this new inner environment and then that's it that's how you write function evaluation okay so I've written this in a file called basic functions I hope that's a name okay and we go down to here and then I can take our source code with a function in it and run it through the interpreter you can see that the first thing it's still a equals six it still goes back to value six the second thing is a function declaration which gives us back one of these function objects and the final thing is a function call and it values this correctly it works out that the first of a and two is in fact a which has got the value six okay so just so it works we pass in a different value last thing in our output stream here okay so that's how we write a function let's look at the type checker for this now the type checker works in a very similar way I'm not going to go through the code again but instead of calling eval on game back a value we just always return the type of that value so if I run the type checker it says we've got a number followed by a function type followed by a number type having to add any type annotations to the code I'm going to write a more complex function I'm going to write something called apply and this takes three arguments it takes an x and a y and a z and what it does is it assumes that x is a function so I'm going to say we're going to call this first thing that you pass in as though they're a function passing in the arguments y and z and then we can replace our call to first with a call to apply and the first just becomes the first argument now if I go back and run this to the interpreter you can see that this still works it's getting a bit long now so let's require a pb and then pre-print this we see it still works so it's still a value it's the first thing to be a 6 then we've got two function declarations for first and then apply and then when we call apply with this complex of arguments it still just works, it still goes back to the answer we would expect then we run this type checker it says that we have something of type number and then two things of type function and another thing of type number now I'm not really happy with that, it's correct but there's more information that we can get out of this when we say that things are the same type we typically mean that we can interchange them in the program and the program will still work you get different values out perhaps but the program should still work but that's not the case for functions the way the actual type of first is not the same as the actual type for apply they are both functions but first is a function that accepts two arguments is a particular return type and apply is something that takes three arguments and one of those arguments has to be another function and it's got a very different return type so I'm not really happy with the way this works I think we can do better so this is our function and we can say what do we think the type of this is now when we declare a function we don't know what the type of X is we don't know what type of Y is we're not going to know these things until run time but we do know there are two of them and we know that they can have any type at all then it returns something and we don't know what it returns yet we won't know until run time but we can say it returns something of any type and that's kind of true but it's not the full story because the thing that is passed in as the first parameter X is also the thing that gets returned so the any type for the parameters also the any type that has to be used for return so instead of just saying any type I'm going to use type variables I'm going to say the type of X is A we don't know what A is yet it's just a variable that will be filled in a letter with a value and it's the same thing and that's the important point and for apply we can go even further if we start off the same way we say we use type variables for the three different arguments that passed in and then when we look at return type well the return type is whatever A applied to B and C is the trouble is that we've said that A is any type and applying any type doesn't make any sense so we get an error at this point it doesn't know what the return type is but we can work at more information by looking at the definition of the function body so we look at where these variables are used we can say that A isn't any type that means we don't yet know what it's going to be but it's not any type really it's constrained to be a function in particular a function that takes two arguments of types B and C now because we know it's a function we then know it's going to return something and we don't know what it's going to return yet because we don't know what the type is for sure but we do know it's going to have some return type so we can use a new type variable D in this case as the return type and we can go back and we can say the full type of this function is something that takes another function of type B and C mapped to D and then two more arguments of type B and C and then return something of type D now don't worry about the detail here I know this looks really confusing the most important thing to notice from this is we could find a lot of information about the type of this function just by looking at the source code we haven't had to tell it anything we haven't had to tell it what the types are so I've written this up and again it's in a file called better functions this time so I can go down here and just to make sure it still works I can call my interpreter but it still gives me back the correct answers but this time when I ask it to do a type check it gives me back a lot more information instead of just saying it's any old function this time it's saying it's a function which takes something of type A and then returns something of type A again and for the apply it gives me this detailed thing about the type of function it's something that takes another function and then a couple of arguments returns return type of the first parameter there's quite a lot of information we can extract from this this can be quite useful as well if we make a mistake in our code for example if I call apply and pass in A and A in this case is the number it's not a function it's going to raise an error but it can only tell us that it's wrong it can tell us or it can give some hints about why it's wrong and what it expects instead so it's saying you gave me a number but I expected a function and in particular I expected a function of type B and C map to D so this is kind of useful and we can do all of this without having to add any type information into our source code we can do it all just by looking and reconstructing the types okay one final thing I want to add to our language I want to add something called maybe the way maybe works is you can add it before any expression and the behaviour of maybe is it will either run the expression or it won't now this seems a little bit weird but I'm using it to simulate a lot of the uncertainty we get at runtime in real programming languages and what the implementation maybe has got a random number generator in it and half of the time it will just run the function and return whatever the value is from that and the other half of the time it will just kind of mess with you as a developer so I'm going to go and pull in definition of this it's in a file called maybe okay if I go down and run the interpreter in this sorry I'm going to set it back to first as well okay I don't know at this point whether or not it's going to work it's up to the random number generator it may work and just give me back the answers that we saw before or it might explode so first time running it it worked okay so it picked the random number that was high enough and it said run the expression if I run it again it worked this is the great thing about random things if I run it again if I run it again yay it broke that time so we can see in this case instead of returning the thing it just returned ha ha and the whole thing blew up so what about types for this if I run the type checker what can we say the type of for example first is because it's got this maybe in place we don't know what's going to happen and what's the type of applying something with a maybe so think about this what's the type of A well it depends on what happens at run time now if at run time we decide to run the expression then the type of A is going to be something of function type there's a bit more detail but if maybe it decides not to run the function then it's going to be this funny method of developer type called null here for no particular reason so what's the type of A well actually the type of A is either null or function type but we don't quite know it's like a kind of Schrödinger's type we don't know until we look in the box so when I run a type checker this is exactly what's going to come back now we have a bit of a problem because if the type is this special new type of either a null or the function can we say that this works because remember we had something that checked the argument past it was the right type and the answer is we don't know we don't know whether it's going to be the right type how to deal with that now in a strict language you might reject it and say we cannot guarantee that your program works therefore we're going to reject the whole thing and we're just going to stop and say go away and fix this in a more permissive language something like Ruby for example we're more likely to perhaps warn you about it we'll say hey it's a bit of a danger here you know this thing might not work but I trust you as a developer to get it working you know what you're doing okay so if I run the type checker now first of all we can see this warning it's saying you're passing in this union type this or type the thing that's either a function or it's this kind of null thing and this might not work there's no guarantee that your program is valid but then we look at it it carries on and does the full type check actually the final return type it doesn't quite know what's going to happen either it says the whole thing is either going to produce a number or it's just going to explode we don't really know it's not always going to be this ambiguous though so for example if I say A is maybe a 6 on the type checker okay you can see the type of our first expression is now set to either number or this null type we know that neither of those work for a function so if I then pass in our maybe type here as the first argument to apply it knows enough to reject it it knows enough to say this can never work it doesn't matter which path we go down it's never going to work so there are things we can reject but we can't reject everything and this is a big idea non determinism in programs is not our friend when writing a type checker if we don't know what's going to happen our type checker is not going to work very well and in particular it changes the nature of our type checker I mean initially when we wrote type check and we said is this program valid it can come back and say yes it's valid or no it's not valid when we throw non determinism into the mix and we say is it valid it can come back and say it's not valid it'll definitely never work or else it can say you go and run it and find out and that's not very useful and there's a risk that as the non determinism increases the value of the type checker decreases because it's saying I don't know more of the time I think one of the important questions asked is how much Ruby is non deterministic I don't know the answer to that I think a lot of it is but until we actually run this against real programs we're not going to know for certain okay so this was supposed to be a talk about type checkers but I spend an awful lot of time writing an interpreter and talking about how evaluation works and that's no accident in order to understand types we need to understand how our interpreter works we need to build an interpreter and this is part of a deeper truth that understanding types is not separate from understanding the syntax and semantics of your program they're not two separate things they're just different views on the same concept and there is this idea thing that we can take Ruby as it is and add soft typing to it without addressing the syntax and semantics without changing the nature of Ruby and I think that idea is optimistic at best I'm not convinced it's going to work but I don't want to end here I don't want to end on a negative note and I really don't know the answers to whether or not soft typing would be good for Ruby without changing the syntax and semantics I certainly don't want to stop here because there's something more important I've been trying to get across today and this is the type theory in Ruby go together type theory is not the kind of thing that we say we don't have to use this we don't have to be interested in this because we don't write Java with static type checking or we don't play with Haskell like the other weirdos type theory is something that we can engage with as Rubyists and it's something that can potentially give us some benefit back it's something that can improve our confidence that our programs are correct or will behave in the way that we expect I think that's the most important thing I've tried to talk about today so is type theory boring and difficult and impractical well, that's not for me to answer that's the question that you guys answer and I'm not stupid here, I know that some of you think yes to all of these and that's fine, I mean type theory is not for everybody but I hope at least some of you here have found it interesting and I find that it's more accessible than you maybe previously thought and maybe think that there is some use for this in Ruby and if even one person here today goes away and thinks I'm going to explore this some more then I can't just talk as a success so I've written up all of the code that I've used today, it's available on github under this URL but that's it, thank you very much for listening okay that went way quick and expected because the code worked first time, this has never happened before I do this from time for questions I'm generally not a big fan of questions at the end but I am a wrong for the next three days so if you've got anything to say to me please come up and discuss this with me even if it's just to say you find it very boring and annoying but has anybody got any questions they think they want to share with everybody else or any observations that we've been worth sharing with everybody oh there's a hand up over there okay so the question was what they think about the gem contracts so the gem contracts is an attempt to add some kind of structural typing on to Ruby you kind of say this is the type of my function it's like a way of adding type annotations where you are describing to Ruby the types without actually changing the Ruby parser and the interpreter is that a good summary of contracts? okay cool so what I think about it I think any tool you can run statically that gives you some more information about Ruby and types of Ruby and the safety of Ruby is worth exploring personally I don't think the contract is the right way to go I think type reconstruction to demonstrate here today is probably a lot more interesting where you go to your code and we try and pull out as much information as possible but I think that contracts is an interesting attempt to add type signatures and to get people thinking about types in Ruby but unless we have a good way of running a tool and Nick coming back and saying yes program is valid or no it's not and being able to trust that tool I'm a little bit dubious as to the value okay so the question or the observation was that nil is very important in Ruby it's like a first class citizen it comes up a lot and this is going to be a stumbling block to adding something like static type checking yep yes you guess okay so yeah you're an idiot nil is not a stumbling block in itself nil in itself is not a problem if we can correctly identify nil then everything is fine okay we can handle nil properly and we can just say nil will never satisfy the constraints that we need for our particular piece of program okay nils do exist in other languages you know something like ML for example has got something it's not undefined it's another thing but you know in something like ML which is strongly typed they do have concepts like nil inside there a unit for example can act in a null like way so I don't think that's the problem with type checking in Ruby I don't think just having a nil is a problem I think the bigger problem is we don't know when there are going to be nils until we run the code so when you access an array for example you don't know whether it's going to give you back a number or a hash or another array or some object or a null we don't have access to that at the static analysis phase and I think that's the big problem the non-determinism is the problem the problem is not the fact that one of those types may be a null that makes sense any more yep over there what plug-in is it using to evaluate the code the plug-in is called seeing as believing by Josh Cheek who's around somewhere I can't see him oh there he is standing up at the back I really recommend you check this out it'll plug into pretty much any editor and it's a really good way of doing this kind of quick evaluations you're writing code yeah definitely go and check that out seeing as believing I'll tweet it afterwards as well okay so the question was is there a way we can write a code to avoid non-determinism the answer is yes stop using Ruby go and use Haskell maybe not the answer you're looking for I think that non-determinism is something that we like as Ruby developers part of the attraction of Ruby is that we don't have to be very specific at the outset about what's going to happen in our program and it allows a whole class of programs that would not be possible otherwise every language will have non-determinism in it somewhere any language that's got IO for example you cannot guarantee at compile time what the IO is going to be there are probably ways we could reduce non-determinism or even guard it so we can say this bit is non-deterministic but I think if the program works properly it will return this type you could do something like that I think that's very complex this is an idea I'm kind of interesting exploring over the next year or two the idea of how do we kind of marry this non-deterministic language with trying to get guarantees about strong typing or static typing but I don't yet know what the answer is going to be to that any more? okay more hands up, okay go right hand side first so the question is what I think about gradual type systems like type script so gradual typing systems are perhaps a little bit different in intent in gradual typing systems as far as I understand it you add type annotations as you go so you're saying to the compiler this is the type of this thing and the compiler then does a check and then there's something called type eraser it says okay I've checked it, I'm happy that it's valid and it throws it away and at the run time it never uses that information again I think that it's probably not going to catch on I think if you are prepared to write the annotations you're probably going to be happy enough to move to a strongly typed language there's maybe something like Elm instead that compiles onto JavaScript rather than using TypeScript it's seen as a stock gap movement I've never really seen it used that successfully but I'm sure people do but I've never seen it used that successfully because if you're only kind of half thinking about types you don't get the consistency you don't get the strong guarantees but you do have all the extra effort of having to go along and annotate your code and deal with situations where you don't really know what the type is going to be or the type is very complex so the question was could the approach I was using be extended to Erlang Dialyder okay you could do some kind of type reconstruction error line it would probably be more successful than it would be in Ruby Erlang is interesting actually because they use what's the name of the approach property typing to give some guarantees so the tools use property checking to give some guarantees about safety rather than using static types and property testing is kind of it'll find a value and then try and break it it'll try all sorts of different things in there and see what breaks it that's surprisingly successful I think tools like that are probably going to be successful enough that doing some type reconstruction is not worth the effort it wouldn't give you any better guarantees okay we're out of time exactly zero minutes so thank you very much everybody