 Right, yeah, I'm Tom Stewart and the evil Tom Stewart, the way I will be expressing how evil I am, is by talking to you for half an hour about stuff you're not interested in when you're waiting for a talk with a man dancing with robots. If for some reason you want to follow me on Twitter, I'm Rental Custed. If you don't know what custard is, it's crema catalana, but more liquid and without the nice sugary bit at the top. So just think about that on a rental basis. I'm all, this is all just stalling because the clicker is not clicking. Okay, well just nothing is clicking. Okay, that's probably why. Yes, good. There we go. So today I want to talk to you about Small Talk and Shell, three interesting languages. Hopefully you'll see by the end why they're interesting. Two health warnings before we get going properly. The first health warning is this talk was made in the factory where Ruby is processed and it cannot be guaranteed to be Ruby free. The second warning, and this is an important one, is I have no idea what I'm talking about, and this is in fact true for everyone except the other Tom Stewart that's still on the stage. In general, like people are going to express opinions to you at conferences, there might be some facts in suspense, this talk is fact free, but you should just take everything I say and everything everyone else says to you at a conference with a pinch of soul, a very large one. Okay, on that note, let's talk about, talk about, nothing is, wow, okay, let's talk about Small Talk. Hands up if you've written a programme in Small Talk. Oh wow, a few. Okay, good. I haven't. Thank you for that. Also my timing is off. This is a badly organised talk, never mind. So I haven't written a programme in Small Talk, but what I did is I learnt a programme with Small Talk. So when I was a teenager, I wanted to be a computer programmer and I kept trying to learn and I never got there and I tried it with various languages. I wrote programmes but I didn't understand what was going on and the fifth language that I tried to learn programming with was Small Talk and by the end of doing that I sort of understood how to put a programme together. So I sort of proved the concept that I could programme and I didn't feel the need to actually go any further than that, a bit like maths. So that said, I would like to give you my reckons about Small Talk for a few minutes. So I reckon that in Small Talk there are three main concepts. I think we've got objects and classes. I think we've got message passing to objects and that can be polymorphic and I think we've got blocks and I think that's basically all there is in Small Talk. If you discount where it gets executed, which is admittedly important, I'm just going to ignore that. So what's an object in Small Talk? Objects have a class and every object has to have a class. Classes can have superclasses and the class sort of defines where the object gets its behaviour, like the methods are defined on the class. Objects have local state, instance variables and they can sort of decide what to do based on the local state and they have methods. So what's a method? Well, a Small Talk method looks a lot like a Ruby method. Slightly different syntax. You've got this sort of square brackety thing and you'll notice that every argument is named. So here I'm calling the method show on the canvas variable. So the name of this method is show at x at y and the first argument unlike Ruby or the name of the method is not special. All of these arguments make up the name or the signature of that method. The methods can return values. You probably want to avoid that a lot of the time. With canvas show, you're probably not interested in the return value, but they can return values and that's important. We'll see that later on. And they have a receiver which is called self and that's the object to which the method call was sent. And one method or the name of one method can be defined on different object classes which gets us our polymorphic dispatch. So this is also far very Ruby and hopefully nice and familiar. There's a reason I started with Small Talk. Okay, blocks, the last, I think, important concept in Small Talk. So they work a lot like methods. They can return values and they can take arguments. And they have access to the variables in the calling context. So that means that, you know, when you pass a block, you've still got all the variables from that scope available in that block. They can be accepted by methods. And the thing about blocks in Small Talk like pretty much everything else is that they're objects with methods defined on them. Importantly in Small Talk, the method on block is value and that runs the block and gets the thing out. Okay, so I reckon that with these three concepts, we can do anything in Small Talk. And I think basically everything in Small Talk happened in terms of these three concepts. So this is how we do if in Small Talk. This is writing an if statement in my Small Talk code. So let's just try and break this down. What we've got is, I'm going to try and use a laser pointer. Oh, it works. Look at that. It's over the shoulder. Yeah, so we're sending the message double equals to two. It doesn't look like a normal message call because it's a bit of syntactic sugar. That's what we're doing. So we're sending that message with an argument two to the object one. We get something returned. It's a booleum, right? And then we call this method if true if false, which accepts two blocks. And what that method will do is based on whether the booleum that we get back is true or false, it will run either the first or the second one. A transcript is an object that's available in a lot of Small Talk systems. That is a bit like a sort of debugging output and it has a show method that you can send strings to. So this is just like puts. Okay, so how does that work? I mean, you can't really understand that without seeing the implementation of if true or false in booleum, right? And that's dead simple to understand as well. It's just a method definition. We've got, this is the definition as it might look inside true. Actually, it probably gets optimised away and it's probably done in a sort of hidden way because if true or false is pretty common. But you know, you could write it like this. If true if false, take the true block and the false block. And if we're in the true object or objects of the true class, of which there should only be one, we call value on true block and we return it. That's what that character is. Okay, interesting. Then we've got the false implementation. And that just does what you would expect. It calls false block. All right, this is all pretty simple. And in fact, if you've ever heard about small talk, someone's probably showed you this example. So why am I doing it again? Well, I think the point about this is you can understand this based on understanding those three concepts I've presented you at the start. There is nothing else to understand here. There is objects, methods, blocks, returning values. That is it. And I find that interesting in a language. And the point is that with those three concepts, we're basically equipped to look at anything else that's there in small talk and have a way of understanding how it must be built. So that's interesting to me. All right, let's move on to Lisp, our next interesting language. Who's written a program in Lisp? You can include closure if you've written a program in closure. Yeah, a few people, a few more. I actually have wrote a program in closure. I never deployed it, but I did write it. That was fun. Also, when I was doing that classics degree, I had to write essays about ancient Greek literature, and that included large quotes from ancient Greek literature, and it's very difficult to type ancient Greek into a computer because you have all these accents, and they're all going in different directions. You have lots and lots of different sort of diacritics. And I was using Open Office for this, and it was horrible. So I thought, well, the thing for this is latech, right? Yeah, it can do that. So I was trying to type it in latech, and you've got to do all these sequences with backslashes and curly braces, and it was horrible. I couldn't see what it was going to be. Then I discovered Emacs has a major mode for inputting ancient Greek. That's awesome. Unfortunately, I can't do cording. It doesn't agree with my fingers. So that was as close as I ever got to Lisp, really. So what I reckon about Lisp is it's got just a few concepts. Bearing in mind, of course, I haven't written a programme in it. These are the things that I think Lisp has as its basic concept. You've got functions, you've got values, and you've got macros and special forms, which are sort of the same as functions in some way. All right, so what's a function in Lisp? Well, like a small talk method, it's accepting zero to n arguments. It's going to return values. Most of the time it's one, you can return more than one thing in various ways and various dialects. If it's a good function, you're going to try to avoid side effects, but that's not like an essential feature of a function. But if you do avoid side effects, then when you're interpreting Lisp, you can replace a call to a function with the result of that call without changing the meaning of the programme. That's called referential transparency. That's just a nice buzzword to use if you want to sound clever. So a Lisp macro, and this depends on the dialect, I'm going to be using closure largely because I'm going to be using the same as to verbose to fit on slides. They look like functions, but importantly, they sort of operate on programmes. That means that you can define a function that what is output is more Lisp, and you can define syntax that way. You have full access to the underlying language, so you can sort of conditionally define syntax, which is interesting. We also have special forms, I forgot that that was coming up. They just have different evaluation rules, but they look just like functions or macros when you're using them. All right, so you can see this coming a mile off, but I would like to have a look at how we could do if in closure in terms of these basic concepts. So I could define a function, right? I could call it new if. The square brackets is just the arguments list, so I could say, right, well it takes a predicate, this is the thing that's true or false. It takes a then clause and an else clause, and based on whether or not the predicate is true, that's what the con function does, it takes pairs and evaluates the left-hand side for truth and evaluates the right-hand side, sorry, returns the right-hand side as soon as one of them is true. It will either run the then clause or the else clause. Okay, this looks great, right? Good? No, doesn't work, does it? Anyone know why it doesn't work? Why doesn't it work? The arguments are strictly evaluated. Is that what you said? That sounds about right. I don't really know what he means by that, but I think I can show you an example of where it stops working, and I think it's because of that evaluation. It is to do with the evaluation rules. If I call new if with functions that have side effects or functions that cause a recursion back into new if, I'm going to have problems. Here what I'm doing is I'm calling new if with a predicate that's not true, and I'm saying print high if it's true and print by if it's false. Unfortunately, what Clojure does is print both of them and then return nil, right? The problem is that the way Clojure gets evaluated is you replace all of the functions, function calls with their value, which means you have to evaluate them and you reduce them back until you've just got one value left. That means that even though we only return the thing that print by return, we still have to evaluate both, and that means we get the side effects. If I was calling new if inside print high, the function would never exit. So it seems clear to me that we can't use functions to define if in list, but we've got another concept, which is a special form, right? That's boring because I can't show you how it gets done. I mean, we can look at the source code, but it's just going to use Java's if, so that's boring. What if we did a less enclosure? So to make it easy for myself, I'm going to define it as a function because then I can understand what it's got to do, even though I know it's not going to work because of this problem with the evaluation rules, but all that UNLESS has to do is do the same thing as if, but flip the predicate, right? Just call not on the predicate, and then everything should be fine. I could equally swap around the positions of then and else. So that's not going to work, but we have macros. Macros, as I said, let us define new syntax and reshape the world. So this is what I have to do, because macros syntax, every dialect of this will do this slightly differently. So all I'm going to do is not make UNLESS a function, I'm going to make it a macro, and then I use the back tick, hopefully the next slide, oh no, it doesn't, the next slide should have highlighted that, but I use the back tick there to quote the thing, and this says just expand this and rewrite this code that the person is going to write of UNLESS into an if not, but don't evaluate these things yet, right? So this is like defining a syntax rule. And then I put the tilde's on all of the arguments there to say, again, just expand those, don't evaluate them yet. So that way I can use functions to understand lists and I can use macros to sort of rewrite lists. And with those things and understanding about values, I can basically understand how the language works without really having to write programs in it. And anything I come across in a list, I can explain in terms of these things, even though it's not going to be straightforward, the explanation will always be done in terms of these three concepts. So that's interesting. I'm going to take a break now, because I know you're all in suspense about how bash might be similar to these two languages. So I'm going to string that out. So who's written a significant program in bash more than about 100 lines of code? A few. More than lisp. OK. I have. I wrote a hangman. I wrote interactive hangman in bash without using said or orc. I was very proud of it at the time. But that's about it for my knowledge of bash. So I think that equips me again to reckon about bash. And I'm calling it shell here because it has the same characteristic as lisp and small talk, which you'll see in a bit. So shell has a few concepts. It's got commands, including functions as commands, because they're user-defined commands that are only available in a certain scope. You've got redirection based on exit status, and you've got arguments, space-limited arguments that can be sent to commands. All right. What's a command? Just like a function in lisp or a method in small talk, it accepts zeros of many arguments. Unlike those things, it doesn't return values in the same way. It has an exit status. That's sort of what it returns. Between zero and two-five-five, zero is success. Everything else is some kind of failure. It gets input from standard in and also from the arguments, I suppose. It sends an output to standard out, and it can send errors to standard out. And that's basically how you return things from commands or functions in bash is that you send them to standard out. So with standard out and standard in, we can do certain things. We can redirect them using these symbols that once looked cryptic to us, but now that we have programmers and have superpowers, make perfect sense all the time, right? And that means that you can do conditional things with commands with, like, double ampersand and so on and so forth. So we can examine how bash does if. Well, actually, no, we can't because it's a built-in. It's not actually a command like everything else in bash. It's one of the few built-ins. So that's kind of disappointing. The reason it has to be a built-in, by the way, there's not actually much stopping it from being something we could define ourselves, but in bash, I can't define a function that, like, takes control of the program and then has multi-line stuff. I can't say this thing doesn't terminate until we get to the fee and it needs it then after it. I could do it with here docs and I tried. I did, but it looks really ugly and it's not really the same because you're just sending one string as an argument. So that's unfortunate, but, like, built-ins in bash are not that much different from this special form if you kind of squint a bit, so I'll just leave that hanging there and move on. The square bracket, on the other hand, is a command. It's not syntax, it's a command. And you can prove this. If you go to your shell and type man square bracket, now this depends what you're on because sometimes when you type man square bracket it will send you to man bash, but that's sort of a lie. On Linux, certainly the distribution I use, I get this, man square bracket and it sends me to the man page for the test command. The test command is a really handy command. It does... What it does is if you send it a file with certain arguments, it will check if the file's there and it will return an exit status of zero success. If you send it, it will check the arguments one minus eq2. This is just an argument list on a command. Then it will give you an exit status based on whether or not that's true. So it will evaluate those things. And you'll notice that in the synopsis there, you've got expression in square brackets. So what this means is that somehow square bracket is the same as test, sort of. All right, I looked at the source code. For utils, that's what's on my Linux laptops, user space. You've got dsd system 5 bash something, who knows. Anyway, line 839 of test is this ifL bracket thing. And if you can bear with the C, what that says is if the number of arguments is less than two, or the last argument is not closing square bracket, give a syntax error, missing square bracket. So that's interesting. And if you look a bit further up, you'll see that there's a C define for L bracket, which is by default 0. And if it's there, then the program name is open square bracket. If it's not, then it's test. So what this appears to mean is that an if statement of the kind I showed you in bash doesn't work unless you've compiled test twice, once with this flag on and once with the off, it's available in the environment. So that looks to me a bit like the way that if works in small talk. It's like a property of other things in the system, right? You have to have the true class and the false class defining how to do if for their things in order for things to work. Whereas for bash is if to work, you need this command open square bracket, which will take a list of things and then fall over if you don't close the square brackets so it looks like a normal bit of syntax. But it's actually just a command. So this is interesting to me. It appears to me that in bash we essentially build everything out of these concepts of commands, exit status, control flow, sorry, commands, exit status, what was the other thing I said? Oh yeah, and space to limited arguments. You can be understood in those terms as long as you've got the built-ins, but you have to learn the built-ins in lists as well. So, what do these languages have in common? Well, as I've been trying to argue there, sort of minimal with respect to concepts, and that's like not a virtue in itself unless you happen to be an architect in the early 1960s. It's just a characteristic, right? But there is a certain sort of purity, isn't there? A sort of conceptual purity to these languages. I don't mean the pure that functional programmers use to beat us over the head. I mean the purity of knowing that anything you find in this language can be expressed in those concepts that you understood right at the beginning. But of course the other thing about these languages is that they're not very useful. I wouldn't say they're totally useless, but I don't think many people, with the exception of maybe closure, no one really reaches for the most conceptually pure and minimal versions of these languages. I mean even closure builds some extra things onto lists to make it sort of everyday usable. And if you look at the history of these languages, they've all got variants, different dialects for different purposes. I mean autolisp on that list there is a variant of list, a dialect that is supposed to make scripting easier. And you've also got all the languages that are inspired by them or taken their ideas on because presumably the creators of those languages thought there are interesting ideas in these languages, but it's not quite humane enough for me to do everyday programs with. So I want to leave you with a question which is, what if? What if we had a language which combined all of these concepts in some way was not only inspired by these three languages, but in fact let us build programs in each of these three ways, some way or another. Could that be a useful language? Could we mix these concepts effectively where appropriate? Would they be intention with one another sometimes? Would it be possible to get the same power and flexibility? Would it be easier to write programs in this language? Would it be more difficult? I don't know, but thank you for listening. So we were talking just before Tom came out backstage, and in fact Tom and Julian were chatting and they'd both watched these YouTube videos on gyroscropic procession. I said, what's that? Tom said, if no one asks a question, why don't you come on stage and ask me that because it's fucking awesome. So, what is gyroscropic procession? Well I'm glad you asked. Not in any way choreographed. This is a great question to ask before the talk about robots because I was watching another thing that I'm qualified to be an instant expert about is the physics of helicopters because I watched a series of YouTube videos about the physics of helicopters. So when you want to make a helicopter do this, like go forward right, you would think that what you would need to do is increase the lift at the back and decrease the lift at the front, right? I don't have any physics but I think this is what you would have to do. So that would mean that this rotor would have to take more air and this one would take less to generate less differential and pressure so it would go up at the back down at the front. But this is dead wrong. It's not correct. What you do if you want to make a helicopter go forward is you increase the lift on this, depending on which way the rotors are going you increase the lift on this side and decrease it on that side so you try and push it to the right and that would cause it to go forward because of gyroscopic procession. Which is... A thing in physics which I didn't study because I studied ancient Greek. Unbelievable. Let's give a round of applause.