 Thank you for the introduction and welcome to my workshop. So let me first ask you or first I would like to explain the purpose of this workshop. It was written that it is for beginners and by that I meant it's for beginners in Rust. Although I expect you to have some knowledge of programming and memory management and so on. So I'm sorry if you're new in programming completely. And so right now, do you have any knowledge of Rust or who of you know Rust at least a bit? Okay, that's like half of the people. So I will quickly introduce Rust, the language itself and then we will try some examples. Okay, so really quick introduction to the Rust programming language. So first of all, the pretty obvious question is why just another language? And since we don't have much time, I will quickly describe what is Rust about and why you would like to use it. So I think there is no single language to rule all the applications from IoT to web applications and scientific computations but I think Rust is appropriate language for many, many domains. So I think it started as a replacement for C++. So if you're familiar with C++, the syntax is pretty similar. Although it has some features that are usually found in functional languages like for example, if expression returns a value. So as opposed to C, you don't need any ternary operators or similar constructions because everything returns a value. And also we have pattern matching which is also more popular in functional languages. Probably the most significant feature of Rust is its memory management. There is no garbage collector, although it is not as manual as in C. So you don't have to allocate memory by hand and deallocate by hand. Although there are some rules you need to obey to acquire the memory and then release the memory. And these are called ownership. And it means that every value has some unique owner and the unique owner can borrow the values and it is responsible for freeing of them. But this as opposed to C and C++ is checked during the compilation time. So you will get a memory safety, let's say for free. Okay, the type system is a little bit different than in mainstream languages. It has static typing with type inference. That means you don't have to write the types but there are types known at the compilation time. So even though you don't write them there must be a known type. And you can get errors from the compiler that you need to specify which type it should use if it's not clear from the context. And yeah, of course there is support for genetic programming but it does not support object-oriented programming as we know it from Java, for example. If you want to get polymorphism you need to use traits which is something similar to type classes from Haskell if you know. Okay, so using all these features Rust is able to guarantee memory safety. So if you use only safe Rust you should get no double freeze, no use after freeze or out of bound access which are pretty common memory related errors when you're writing in C. And using the type system it also guarantee no data races in multi-trade code which is pretty nice. The marketing expression is fearless concurrency. And this is actually really nice because usually when we are writing multi-trade code it's hard to debug when it's broken. So using Rust static analysis it's I would say much more pleasant to write. And also using the, let's say, little bit more complicated type system of Rust. You can write libraries that are hard to misuse. So for example, when I was writing some code using OpenSSL I was pretty scared that I got the API wrong because I couldn't understand the documentation and there is just a void pointer to everything. So it's really, really easy to misuse and in Rust we use the complicated type system to only allow some specific usage of the API so that you cannot misuse it. Okay, so what is the language good for? So it started as a language for writing a browser but it's of course not usable only for this purpose. You will get the presentation afterwards, I guess, right? You should take it from me, right? So I include some links to interesting blog posts which I found online. For example, many people use Rust for speeding up their web services. So for example, I read some articles about log parsing. There was a Ruby service and after they had more and more customers they found out there is bottleneck in parsing so they wrote this part in Rust and it was much faster. You can also write some network services, even operating systems. Also pretty interesting domain is web assembly although I don't really know anything about it and finally IoT. If there is a compiler backend for your platform it should be possible to compile to embedded devices as well. Okay, and final advice. If you're just starting with Rust, don't give up. It tends to be difficult in the beginning. Sometime they call learning Rust fighting with Borowchecker. I call it discussing with Borowchecker because I think it's more positive. Okay, so these are the sources and you will get them afterwards. Okay, so I hope you have laptops. Okay, perfect. And I hope the internet connection will be available for all of you, although I cannot guarantee anything. Do you have any questions right now? So we can start by opening the main page of Rust language and the install tab. So this is the recommended installation method on Linux if you find it scary, I'm sorry. Alternative is using package manager. For example, if you have Fedora there is the latest stable version of Rust and you can install it using to install Rust and cargo, is it right Igor? But I should have it already. Oh yeah, that's DNS extension, use it. It's awesome. 1.32, preferably. If you have rel, then you probably have some older version. Okay, old Fedora is poor choice. Okay, do you have a Rust compiler and cargo? Slide? Yeah, sure. Well, if you download Rust compiler using DNF, for example, you will get the compiler and the package manager. But as far as I know, if you want to use, for example, VS Code and the new Rust language server, it won't work because it uses Rust app to download all the components. So yeah, it's a shame, but what can I do? 1.32, yeah, that's quite old. And okay, next thing which is new in the 2018 edition is official Rust language server. It's possible to use it with VS Code or probably Atom and of course Vim and Emacs. The official solution is VS Code because they don't have capacity to support all editors. So I have just the official VS Code extension and if you used Rust app to get the compiler and the package manager, it should be pretty easy to install IDE integration as well. Just open extensions in VS Code, type Rust. And this extension should automatically download Rust language server and the source code for necessary for the code analysis, et cetera. Do you have any troubles? If you have any issues? So yeah, of course, alternatively, you can also use IntelliJ, which has also pretty nice plugin. It's not based on the official Rust language server, but it's their own and I think it's really, really good. Okay, so let's try some projects. If you want to start a new project in Rust, you can use the package manager cargo and just create a new, let's say first command line app. Hit enter and that's it. It used to default to library because each Rust project has its associated type. It's either library or binary. It used to default into library, now it defaults to binary. So you don't have to type binary anymore. Okay, now let's write hello world and it's done. And it's done. Sorry, it's written by default. Hello world, getting there. Downloading, yeah. That's unfortunate, yeah. Okay, now if you want to run the project, just type cargo run and it will compile the project in debug mode and run it as simple as that. Okay, so as you can see, the main function doesn't have any return value and that's because return integer return values are specific for some platforms. So they use this, let's say void return type for main and if you want to specify a return value, you just need to use exit explicitly. But in the new version of Rust, you can actually use a result type, which is something new that wasn't available in the previous edition if you tried. And that's because in Rust, we don't have exceptions. So there are no throw keywords, no catch keywords and we only use these result types. A result type is a type that contains either or successful value or an error. And if you want to get the value, you need to unwrap the result explicitly. So you can use it instead of the exceptions, but we need some, yeah. It used to be more verbose than using exceptions because as you know, when you are using exceptions, you just throw in some inner function and then 10 functions away, you just catch it. So it's pretty convenient. In Rust, you cannot do this, but we have a new question mark operator. So let me, for example, write some application that will parse command-line arguments. That's pretty common, right? So we can include standard library environment module and we will create a variable and we will load the command-line arguments using arcs function that is available in the library. Now, as you can see, there is no type, but as I said, there is a type known, but we just don't have to write it. So let's try to compile the code and yeah, of course, it doesn't work because yeah, now it works. So I also need to include the error trade because that's the return type we will use when we start doing some operations that can fail. And since we are returning result from the function, we cannot return anything. We need to return either a success or an error. So at the end of the function, I just return empty success. That's the Sauron I. Okay, perfect. Now, there is a nice way to explore variable types. When you don't know what type the variable is, you can write something ridiculous like this and then ask the compiler, hey, what's the type? And it will tell you because he's nice. So it's some arcs type. And now we should open the standard library documentation. So let's just open Google to the Rust line. And this is the official documentation. I recommend you to open it. You will find really, really useful information there. So we can see what the arcs type is. And it says that it is an iterator over arguments, yielding a string for each argument. So now we can go back and let's explore what's inside of the arguments variable. Really nice feature of Rust is that you can use the for loop for any type that implements iterator trait. And that's the polymorphism I was talking about. So if your variable implements iterator, you can use for loop to iterate over it. And as the documentation said, it will yield a string for each argument. So those values will be string. And if you have the newest compiler, the 1.32, you can use this convenient debug macro. That's the latest, greatest addition. Okay, yeah, of course. Download this nonsense, delete this nonsense. Okay, right now, there is only the name of the executable. So that's the only command line argument. But we can use cargo to actually provide something some command line arguments, for example like this. You will use the dash dash syntax, then space, and something that will be provided as a command line argument to the binary. So use the dash dash space syntax. Okay, and now we can see there is a new command line argument, c equals five. Okay, now, if we want to parse some arguments, we can, for example, check if the command line argument start with some prefix. So for example, when I want to write an application that takes dash c as an argument, I can use just if the argument starts with dash c. And that's it, just do nothing right now. And try to compile, it works, nice. Okay, so now we know that argument starts with dash c and we want to split the string with the equal sign and then take whatever is on the right side and parse it. So we can use, we can use a split and equal sign. Yeah, if you are coming from Python, there is a difference between single and double, no, quotes. So just be careful. And then we need to, this split function does not return an array, it returns some special split type and if we want to make it an array, we need to collect the result. This is pretty common in the standard library API because some structures are lazy, meaning that the result won't be evaluated unless you explicitly ask for it. So we can use collect to collect the result. And of course, we need to give it some name, now, what is, this is not going to work. I will show you the error and it says that the compiler cannot infer type for this variable. And that's because the collect function is pretty smart and you can actually choose what return type you want. So you have to explicitly state something. Okay, now you have, right now you have two options. Either you will use the syntax for regular types, meaning that you will write a colon after the name and then the type, or there is a special syntax in Rust, it's called a turbo fish which is much more funny and we write it like this, that's the turbo fish. And now into the turbo fish, you need to write what you want. So I say that I want a vector of something. Again, this is special syntax. You can sometimes use it if you need to specify only some parts of the type but not the whole type, you can use the underscore and you say basically, okay, infer this part of the type for me. So you don't have to specify the whole type. And let's see if this still works. Okay, it still works. So no problem. Now finally, we can read the number that's behind the equal sign. So let's parse the number and we'll say that it's parts. The first we are counting from zero and then parse. So right now we say take the first or well, in human terms the second argument and then parse it. Again, the parse function is generic over its return type. So you can choose what you want. So let's again use the or we will use the common syntax and let's try to build it. Okay, this doesn't work because of course parsing can fail, right? And as I said, Rust API should be hard to misuse. So you cannot just return result of parsing function into 32-bit unsigned integer because that's just not correct because it can fail, right? So you have to handle the result somehow. Yeah, you can see the type here. Now, usually in examples, you will see something like unwrap or in a lot of examples you will see something like unwrap. But that's just a convenient way to write code examples on GitHub and Stack Overflow. So please don't copy it into your production code because this will take the result and if the result is an error, it will panic the threat and just stop it. So don't just blindly copy paste, please. And instead, we will use finally the question mark. Okay, do you have the code? Any help? No? Yes, that's what I will explain right now. Let me just run the code. Oh, yeah, we can do something with let's say print line. Yes, and also what I haven't mentioned yet is that this exclamation mark means that this is a macro. It's not a function call. In Rust, we don't have variadic functions. So if you want to write something that takes variable number of arguments, you need to use macro because you don't have variadic functions as opposed to C. And let's just print the number. So this is the syntax for print macro. You write this and then you say what variable you want to print. And again, this variable needs to implement some trait and it needs to implement a display trait meaning that this value can somehow be turned into string, basically. But a lot of types in the standard library implements it already. So in the beginning you shouldn't hit problems with this. Yes, sorry. As I said, it tends to be a little bit difficult to get started with. That's pretty common when I'm trying to teach someone Rust. He says, or he or she says that it's difficult because you need to understand a lot of concepts because before you can even write some hello world, I don't know, network application. Now this is, okay, I will put it on top. This is what the question mark does. I provided a letter instead of a number, right? So that's an error. And the parse function failed. Now the question mark operator works in a way that if the return value is an error, it will immediately return from the function here. And if the result is success, it will just unwrap the successful value and assign it to the variable. So that's basically like saying if this failed, just forward the failure to the next function. And if it didn't fail, just use the value and continue. So this is like a convenient method for forwarding the failures in your code. So this is what we use instead of exceptions. And this code can fail also in at least one another way. Can you spot the place? Okay, yeah, exactly. Or you miss, yes, or you just don't write equal sign. For example, like this. Now it will fail. But, excuse me, it says that the threat main panicked at index out of bounds. So I said that you won't get any out of bounds errors, but I should probably say that you won't get any undefined behavior as a consequence of out of bound excess. So this is what Rust will do if you try to access an array out of bound, it will panic the threat. Right now we have only one threat, so the whole process fails and that's it. If we had multi-traded code, we could just catch the panic, write some note to the user and just spin up new threat. But this is also, I think, new addition in the 2018 edition. Okay, so it says, run with Rust backtrace, photo backtrace, this is pretty nice for debugging. We can try it and I'm using fish, so I will do it like this. And it's pretty huge, the backtrace. This is unfortunate, but there is nothing you can do about it, but probably summer in the middle, you can find the place in main function that failed. So it says that it failed on the main.rs file, line 12. So let's just open it and of course this is the line where we are trying to access the array and we are not checking if the array is long enough. But fortunately, okay, we can use, instead of this syntax, we can use a method that is safe and it will return a result or optional, yeah, it will return optional value from the vector. So the parts variable is of type vector. So let's see the standard documentation for vector. Again, open the standard library documentation and here on the left side, you can see a lot of methods that are available. For this structure, I must say it's so long that sometimes it's hard to find what you really want, but be sure that if you're looking for something, it's probably there. I'm looking for at, split at. Okay, so it's not at, it's get. And the get function, okay, get function returns an optional type. You can see the option over there. It's similar to the result, but in the result type, we saw that you can either return a successful value or an error. If you don't have any error to specify, but still the computation can fail, you can use optional value. It has only the successful value, but still you need to explicitly unwrap the value. For example, this method is obvious. If it fails, there was no value at number one. At index number one. So let's try it and we will write get one and question mark again. And this probably won't, yes. Now, I said that the question mark will return immediately from the function if there was an error. It works also for option, but right now we specified that the return type is heap allocated error. So right now we cannot return just none and we need to turn it into error type. So we'll go to the documentation for option, okay. I think I got lost in this example. Excuse me. Okay or function? Okay, yes, thank you. So this is the documentation for okay or function here. And what you can see is that it transformed the option into result. So that's what we want, right? Because we want to return a result if it failed. So, okay. We will just use okay or and let's just try to zero and see, no, we need to, okay. We probably should use some better error, some out of bound excess, but since I don't have time, let's just return some error. We can use parse error, okay. Sorry, I probably got lost in this one. No, right now we are not discussing with the borough checker. We are discussing with the type system. And yeah, I forgot the error type I wanted to use here. So, but we are running out of time. Do you have any questions? Let's get back to the original implementation. Do you have any questions so far? Yes? You create a new language and you try to get rid of, for example, C++, we create a new language to replace C++. And why do you make it so difficult to learn as much as C++? It's easier. Okay, this is a good question. I think you are looking for go. Yeah. Yeah. Okay, it makes sense. If, for example, you try to migrate from C to go, it goes a very easy language because it's very simple. It doesn't have all of this, yes. You can find all the languages. If you are familiar with Java and you learn go, you see what can I do with this language? There are a lot of things that I have in Java that it does not have in go. Yes, okay. Of course, this is a good question. And I think if you want a language that is easy to learn, you're good with go, but this language was supposed to be really safe. And if you want to guarantee safety at the compilation time, you need to make it this complicated because, for example, C is pretty easy to learn, right? You just write malloc and it will give you heap allocated memory space. Fine, it's pretty easy, but it's also very error prone. But you cannot use it for everything. I would say that you still have to go runtime and you cannot use it, for example, for embedded devices or writing bear operating systems. So yes, that's what people actually ask quite often if it's a good idea to compare go and rust. I think go has different goals. The goal of go was to make a simple language that can be used as a, let's say, again a replacement for a C, but in a different domain. So yeah, I'm sorry, we are out of time. But feel free to reach to me and ask more questions. Thank you. Thank you.