In what year did the rust programming language appear? Where to start · Rust programming language. Programming language syntax

I'm new to Rust, but it's quickly becoming my favorite programming language. While writing small projects in Rust is usually less ergonomic and takes longer (at least with me at the wheel), it does challenge the way I think about program design. My battles with the compiler become less frequent after I learn something new.

The Rust community has recently focused a lot of its efforts on asynchronous I/O, implemented in the form of the Tokio library. And that is great.

Many of the community members, those who have not worked with web servers and related things, are not clear about what we want to achieve. When these things were discussed back in the 1.0 days, I too had a vague idea about it, having never worked with it before.

  • What it is - Async I/O?
  • What are coroutines? coroutines )?
  • What are lightweight threads( lightweight threads )?
  • What are futures?( futures )?

  • How do they fit together?

I'll show you how to write a small program that downloads a feed ( feed) in JSON format, parses and displays a list of notes to the console in a formatted form.

For us, everything resulted in a very concise code. How? Look under the cut.

The unsafe keyword is an integral part of the design of the Rust language. For those not familiar with it, unsafe is a keyword that, in simple terms, is a way to bypass type checking( type checking) Rust.

The existence of the unsafe keyword is a surprise to many at first. Indeed, isn't it a feature of Rust that programs don't crash from memory errors? If this is true, then why is there an easy way to bypass the type system? This may seem like a language design flaw.

Still, in my opinion, unsafe is not a disadvantage. In fact, it is an important part of the language. unsafe acts as a kind of escape valve - this means that we can use the type system in simple cases, but still allow all sorts of clever tricks that you want to use in your code. We only require that you hide these techniques (unsafe code) behind safe external abstractions.

This note introduces the keyword unsafe and the idea of ​​limited "unsafety." In fact, this is a harbinger of a note that I hope to write a little later. She discusses Rust's memory model, which specifies what can and cannot be done in unsafe code.

As a newbie to Rust, I was confused about the different ways to represent strings. The book on the Rust language has a chapter called References and Borrowing, which uses three different types of string variables in examples: String, &String, and &str.

Let's start with the difference between str and String: String is an extensible, heap-allocated data structure, while str is an immutable, fixed-length string. somewhere in mind.

Many programmers already know how to program in object-oriented languages. Rust is not a classic object-oriented language, but basic OOP tools can be used in it.

In this article we will look at how to program in Rust in an OOP style. We will do this using an example: we will build a hierarchy of classes in a training task.

Our task is to work with geometric shapes. We will display them on the screen in text form and calculate their area. Our set of shapes is rectangle, square, ellipse, circle.

Rust is an elegant language that is somewhat different from many other popular languages. For example, instead of using classes and inheritance, Rust offers its own trait-based type system. However, I believe that many programmers starting their acquaintance with Rust (like me) are unfamiliar with generally accepted design patterns.

In this article, I want to discuss the design pattern new type(newtype), as well as the From and Into traits, which help with type conversion.

I've been thinking a lot lately about design patterns and the techniques we use in programming. It's really great to start exploring a project and see familiar patterns and styles that you've seen many times before. This makes it easier to understand the project and makes it possible to speed up work.

Sometimes you're working on a new project and realize that you need to do something the same way you did it on the last project. It may not be a piece of functionality or a library, it may be something that can't be wrapped up in a neat macro or small container. It may simply be a design pattern or structural concept that solves the problem well.

One interesting pattern often applied to such problems is the "Finite State Machine". I suggest spending a little time to understand what exactly is meant by this phrase, and why it is so interesting.

Below is a graphical description of moving, copying, and borrowing in the Rust programming language. Basically, these concepts are specific to Rust and are often a stumbling block for newbies.

To avoid confusion, I have tried to keep the text to a minimum. This note is not a replacement for various tutorials, and is only made for those who believe that visual information is easier to perceive. If you're just starting to learn Rust and find these charts useful, I'd recommend marking your code with similar charts to help reinforce the concepts.

Implementing natural number arithmetic using Peano numbers is a popular task in teaching programming. I was wondering if it was possible to implement them in Rust.

Thus, my task is to write down and add natural numbers with type checking.

According to Wikipedia, “Peano’s axioms are one of the systems of axioms for natural numbers, introduced in the 19th century by the Italian mathematician Giuseppe Peano.”

We are interested in two of them - with which you can enter and use natural numbers:

  • 1 is a natural number
  • The number following the natural number is also a natural number.

Let's write it verbatim in rust using:

1 2 3 4 enum Nat(Zero, Succ(Nat))

Nat is either zero or the next natural number.

Comment: The futures-rs project has been reorganized and many things have been renamed. Where possible, links have been updated.

Getting started with futures

This document will help you explore the futures programming language container for Rust, which provides zero-cost implementations of futures and threads. Futures are available in many other programming languages, such as C++, Java, and Scala, and the futures container takes inspiration from the libraries of these languages. However, it is ergonomic and also adheres to the zero-cost abstraction philosophy inherent in Rust, namely: no memory allocations are required to create and compose futures, and only one allocation is required for the Task that manages them. Futures are intended to be the basis for asynchronous, composable, high-performance I/O in Rust, and early performance measurements show that a simple HTTP server built on futures is indeed fast.

This documentation is divided into several sections:

  • "Hello, world!";
  • future type;
  • type Stream ;
  • specific futures and stream(Stream);
  • return futures;
  • Task and future;
  • local task data.

Comment: The futures-rs project has been reorganized and many things have been renamed. Where possible, links have been updated.

One of the major gaps in the Rust ecosystem was fast and efficient asynchronous I/O. We have a solid foundation from the mio library, but it is very low-level: we have to manually create state machines and juggle callbacks.

We would like something more high-end, with better ergonomics, but that it has good composability, supporting an ecosystem of asynchronous abstractions working together. Sounds very familiar: the same goal was pursued by the implementation futures(or promises) in many languages ​​that support syntactic sugar in the form async/await on the top.

The primitive integer types supported by processors are a limited approximation of the infinite set of integers we are used to manipulating in real life. This limited representation does not always match the "real" numbers, for example 255_u8 + 1 == 0 . Often the programmer forgets about this difference, which can easily lead to bugs.

Rust is a programming language that aims to be bug-proof, focusing on preventing the most insidious of them - memory errors - but also trying to help the programmer avoid other problems: bugs being ignored and, as we'll see, integer overflows.

A little about Iron

Iron is a high-level web framework written in the Rust programming language and built on top of another well-known library, hyper. Iron is designed to take advantage of all the benefits that Rust provides us. Iron tries to avoid blocking operations in its kernel.

Philosophy

Iron is built on the principle of being as extensible as possible. He introduces concepts to expand his own functionality:

  • “intermediate” traits - used to implement end-to-end functionality in request processing;
  • modifiers - used to modify requests and responses in the most ergonomic way.

You will become familiar with the basic part of modifiers and intermediate types during the course of the article.

Creating a Project

First, let's create a project using Cargo using the command:

After compiling, we get the corresponding executable file:

1 2 3 $ rustc hello.rs $ du -h hello 632K hello

632 kilobytes for a simple print?! Rust is positioned as a systems language that has the potential to replace C/C++, right? So why not test a similar program on your nearest competitor?

There is a widespread belief in our environment that one of the advantages of a garbage collector is the ease of developing high-performance lock-free data structures. Manual memory management is not easy to do in them, but GC easily solves this problem.

This post will show that, using Rust, it is possible to build a memory management API for concurrent data structures that:

  • Will make it possible to implement a lock-free data structure, as GC does;
  • Creates static protection against misuse of the memory management scheme;
  • Will have comparable overhead to GC (and more predictable).

In the tests I'll show below, Rust easily outperforms Java implementations of lock-free queues, and the Rust implementation itself is easy to write.

I've implemented an epoch-based memory reclamation scheme in the new Crossbeam library, which is now ready to use with your data structures. In this post I will talk about lock-free data structures, the epoch algorithm and the internal Rust API.

Memory access errors and memory leaks are the two categories of errors that receive the most attention, so much effort is devoted to preventing or at least reducing their occurrence. Although their name suggests similarity, they are in some ways diametrically opposed and solving one of the problems does not relieve us of the second. The widespread use of managed languages ​​supports this idea: they prevent some memory access errors by taking over the work of freeing memory.

Simply put: a memory access violation is some kind of action with incorrect data, and a memory leak is absence certain actions with correct data. In tabular form:

I have a few thoughts about learning programming languages.

First of all, we're going about it the wrong way. I'm sure you've felt the same way. You're trying to learn a new language and you don't quite understand how everything works. Why is one syntax used in one place and another in another? All these oddities are annoying, and in the end we return to our usual language.

I believe that our perception of languages ​​plays a cruel joke on us. Think back to the last time you discussed a new language. Someone mentioned it, and someone else asked about its speed, syntax, or available web framework.

This is very similar to discussing cars. Have you heard about the new UAZ Rybak? How fast is he? Can I drive it across the lake?

When we talk about languages ​​in a similar way, we mean that they are interchangeable. Like cars. If I know how to drive a Lada Saransk, then I can drive a UAZ Rybak without any problems. The only difference is the speed and the dashboard, right?

But imagine what a PHP car would look like. Now imagine how different a Lisp car would be. Changing from one to the other requires much more than learning which button controls the heating.

Note: This article assumes the reader is familiar with Rust FFI (translation), endianness, and ioctl.

When creating bindings for C code, we will inevitably encounter a structure that contains a union. Rust doesn't have built-in support for joins, so we'll have to strategize on our own. In C, a union is a type that stores different types of data in the same memory area. There are many reasons to favor concatenation, such as: conversion between binary representations of integers and floating-point numbers, implementation of pseudo-polymorphism, and direct access to bits. I'll focus on pseudo-polymorphism.


We really liked the article "Criticism of the Rust language and why C/C++ will never die." We suggested to the author that we would translate the article into English and also publish it on our blog. He agreed, and we are pleased to present this article in Russian and English. The original article is located.

The original article is posted (text in Russian). The article was published on our blog with the agreement of the author.

Note: In the following, I am making the assumption that Rust is an attempt to make a fast and safe language. After all, the Mozilla guys made it as a browser engine development tool. If this is just another safe language, then we get something strange. There are already a dime a dozen different safe languages, everyone will find something to their liking. And if the goal is not to replace C++, then (1) why is an unsafe subset made in the language? (2) why was it necessary to remove lightweight streams from the language? Isn’t it convenient? In other words, in this case, what is happening makes no sense at all.

If you happen to be reading the linux.org.ru forum, I’ll note that this is not the list of 10 purely technical reasons not to like Rust that was discussed in this thread. As shown by a discussion on Skype with dear comrade @sum3rman, there is more than one opinion regarding how “technical” these reasons should be considered. In general, I made a crappy list, but I’ll probably still risk citing some of the most interesting points from it. In fact, there are plenty of simple, non-technical reasons here.

The fact that C/C++ is not going anywhere in the foreseeable future is clear to any sober-minded person. No one will rewrite almost all desktop applications, operating system kernels, compilers, game and browser engines, virtual machines, databases, archivers, audio and video codecs, tons of other C-based libraries, and so on. This is a lot, a lot of fast, debugged, time-tested code. Rewriting it is very, very expensive, risky, and to be honest, it makes sense only in the distorted consciousness of only the most stubborn Rust fans. The demand for C/C++ programmers has been and will be great for a very long time.

Okay, what about using Rust when writing new code?

Let us remember that this is not the first attempt to make a “more correct” C/C++. Let's take, for example, language D. It appeared in 2001, a very good language. There are no vacancies, no normal development tools, no particularly outstanding success stories. The OpenMW project was originally written in D, and then suddenly they decided to rewrite it entirely in C++. As the developers admit, they received many letters in the style of “great project, we would be happy to contribute to it, but we don’t know and don’t want to know this stupid D.” Wikipedia reports that in addition to D, there were a lot of other attempts to kill C++ to one degree or another, for example, Vala, Cyclone, Limbo, BitC. How many people have even heard of such languages?

I think it's high time we learned from history. Not a single sane person will drag a new language into a project until you at least show him normal development tools, tell him a couple of success stories and show him a dozen programmers in this language living nearby. Programmers, perhaps, except for the youngest ones, will never waste their time and health on learning the next most correct language until you show them normal development tools (not crafts like Racer), a couple of tens of thousands of ready-made libraries (not “experimental”, “unstable” and so on), don’t tell a couple of success stories and show a dozen open vacancies in their city. Chicken and egg problem. Very rarely, this problem can be successfully solved (conditionally, Scala can be cited as an example), mainly due to the investment of time and money on the part of some large company (Google, Typesafe), for some reason interested in popularizing the language.

As I already noted, non-technical reasons alone are more than enough. However, purely out of curiosity, let's try to imagine for a second that they are not there. Then there's no reason not to write in Rust? It turns out that this is also at least a very big question.

C/C++ is criticized for various things. By the way, criticism is very often made by those who have not even seen C++ code in production even from afar. The problem can be briefly and clearly described as follows: C++ is very fast (and also not demanding on memory, battery charge, etc.), but not safe in the sense that it allows you to go beyond the boundaries of arrays, mistakenly access freed pieces of memory, and so on Further. At one time, this problem led to the emergence of a mass of safe languages, such as Java, C#, Python and others. But it turned out that these languages, compared to C++, are too resource-demanding and have other disadvantages, for example, the inevitable stop the world during garbage collection. Therefore, people are struggling with the task of making a language as fast as C++, but also secure. One such language is Rust.

Rust is indeed secure, but unfortunately, it is far from fast. At the time of writing, Rust is comparable in speed to Java, Go and Haskell:

I sincerely hope that over time it will somehow be overclocked, but until then, in terms of speed and security trade-offs, it is not much more interesting than Scala or Go. The question still remains open whether it is possible to make a language fast and safe at all, or whether constant checks for exceeding array boundaries, safe bindings around bindings to C-libraries, and so on automatically make any language 2 times slower than C/C++.

What exactly makes Rust safe? In simple terms, it is a language with a built-in static code analyzer. A really very cool static analyzer that catches all typical C++ errors, not only those related to memory management, but also multithreading. I passed a link to a mutable object to another thread via a channel, and then tried to use this link myself - it didn’t compile. It's really cool.

The argument is often made that only 10% of the code is executed 90% of the time (which, as far as I understand, is purely a rule of thumb - I couldn't quickly find any rigorous research on this topic). Therefore, most of the program can be written in safe Rust, with 10% of the hot code written in the unsafe subset, and the slowness of the current Rust implementation is not really a problem. Ok, but then it turns out that Rust is not needed at all, because I can write 90% of the code in Go, and 10% in C. Only silver bullet seekers and out-of-touch theorists will use Rust solely for the reason that 100% of the program can be written in one language. Although in reality these are two dialects of the same language, which is not so different from the combination of Java plus C or Go plus C.

In fact, the 10:90 rule is still a lie. By this logic, you could rewrite 90% of WebKit, 90% of VirtualBox or 90% of GCC in Java and get the same result. Obviously this is not the case. Even if the point is not that in a number of programs this attitude is very different, then watch your hands. Let's say the entire program is written in unsafe C/C++ and its execution time, relatively speaking, is equal to 0.9*1 (a small part of hot code) + 0.1*1 (a lot of cold code) = 1. Now let's compare it with a program in a safe language with inserts in Si: 0.9*1 + 0.1*2 = 1.1, roughly 10% of the difference. Is it a lot or a little? Depends on your scale. In the case of Google, even a few percent can save millions of dollars (see point 5 in the paper, “Utilization”). Or imagine that with the next update the JVM suddenly starts requiring 10% more resources! I'm afraid to even guess how many zeros there will be in the figure obtained after converting interest to American money! 10% is a lot in tasks where C and C++ are used.

We repeat “premature optimization is the root of all evil” like a mantra. But if we take it literally, let's use bubble sort instead of quicksort everywhere. We don’t know for sure that the program will slow down in this particular place! What's the point of wrapping ordinary counters of some actions in actors or transactional memory if you can immediately use the more efficient atomic? And in general, in trivial cases there is no point in forcibly initializing all, all, all variables, doing a bunch of additional checks, and so on. Let us end up with not 10% acceleration, but 2-5%. This is also not bad at all, if it only required a couple of extra minutes of thought. And as we have already found out, in problems solved in C/C++, this can be a big difference! Then, who said that finding a hot spot, rewriting the code (possibly a lot of code) and proving that it is really faster is easier than thinking about performance in advance?

If we ignore the issue of the speed-security trade-off, I also have questions about the design of the language itself. In particular, regarding the five types of pointers. On the one hand, this is not bad when the programmer thinks about where the variables are located, on the stack or heap, and whether several threads can or cannot work with them simultaneously. But on the other hand, imagine that you are writing a program, and it turns out that the variable should live not on the stack, but on the heap. You rewrite everything to use Box. So you understand that what you really need is Rc or Arc. You rewrite again. And then you rewrite it again to a regular variable on the stack. All this - without a normal IDE at hand. And regular games won't help. Well, or just in the style of "Vec" >>>", hello, Java! But the saddest thing is that the compiler already knows about the lifetime of all variables, it could output all these Box, Arc and so on automatically. But for some reason this part of the work is transferred to the programmer. Much more convenient it would be easy to write val (in the third millennium!), and where necessary, explicitly indicate Box or Rc. The Rust developers in this sense ruined the whole idea.

Because of this, in particular, the scope of application of Rust is greatly narrowed. Nobody in their right mind would write web and serverside in such a language. Especially considering that it does not provide significant advantages over the same languages ​​under the JVM. And Go with normal lightweight threads (not futurs) looks much more attractive for these tasks. With futurs, in order not to shoot yourself in the foot, you still need to learn how to work, and you say “safe language”. Yes, these languages ​​have their own characteristics, take the same stop the world, but this problem can be solved both by cutting into microservices and by other techniques. And yes, no one will translate Rust into JavaScript, write scripts in it for layout in AWS, or use it as a query language for MongoDB. It is also unlikely that they will write for Android, but for a different reason - there is much more than one architecture, and it is much easier with the JVM. If you suddenly thought that Rust was “suitable for all tasks,” I have to disappoint you.

Well, to the heap:

  • Macros are a backup to excessive verbosity caused by the lack of normal exceptions. I have already written about the problems of metaprogramming, in particular, we are unlikely to see a normal IDE for Rust because of it. And I'm not sure, but it looks like macros in Rust don't even have namespaces.
  • People are idiots, and cargo really encourages pulling packages directly from git repositories, bypassing Crates.io. As a result, there is a high probability of getting the same mess with packages as in the world of Erlang with its Rabar. By the way, in the world of Go, it seems to be the same situation.
  • Like many new languages, Rust takes the path of simplification. In general, I understand why there is no normal inheritance and exceptions in it, but the very fact that someone decides such things for me leaves an unpleasant aftertaste. C++ does not limit the programmer in terms of what to use and what not to use.
  • If we were to follow the path of simplification, then we would have to throw out all these language extensions. Otherwise, it turns out, as in the world of Haskell, each programmer writes in his own dialect.
  • Smart pointers, if anything, are far from free and do not lead to predictable garbage collection times. Some thread suddenly has the honor of freeing a very deep data structure. While he walks through the labyrinth of dead links, the threads that depend on him patiently become stupid. The same problem exists in Erlang with its small groups, I have observed it myself more than once. Smart pointers also have their own problems, the same memory fragmentation and leaks. I forgot the vikpointer in the cyclic structure, that's all. And this in a language that claims to be safe. If you want predictable GC time, either study the behavior of your application under load, and take action (remember the same object pools) if the GC time does not suit you, or manage memory manually.
  • Has anyone seen a rigorous description of Rust semantics? Does it at least have a memory model? Also to me a “safe” language that “proves the correctness” of programs, which can actually interpret the source code in ten different ways, ha!
  • I cannot help but remind you once again that The problem is almost always people, not technology.. If you end up with bad C++ code or Java suddenly slows down, it's not because the technology is bad, but because you haven't learned how to use it correctly. You will also be unhappy with Rust, but for different reasons. Wouldn't it be easier to learn to use and love more popular tools?

In general, over the next 5 years I would rather invest my time in learning C/C++ than Rust. C++ - this is an industry standard. A wide variety of problems have been successfully solved in this language for more than 30 years. And Rust and others like it are incomprehensible toys with a vague future. There have been conversations about the imminent death of C++ since at least the 2000s, but writing in C/C++ has begun no less during this time. Rather the opposite. And we see that the language is developing (C++11, C++14), new tools are appearing for it (let’s remember CLion and Clang), and there are simply a lot of corresponding vacancies.

A C++ programmer can always easily find a job with a more than decent salary, and if necessary, quickly retrain in Rust. The opposite is very, very doubtful. By the way, language, if anything, is far from the only and not the decisive factor when choosing a new place of work. In addition, an experienced C/C++ programmer can easily dig into the PostgreSQL source code or Linux kernel, use powerful modern development tools, and also have a lot of books and articles at his disposal (say, on OpenGL).

Take care of your time and health, you don’t have as much of it as you think!



Today, Rust syntax is supported in vim and emacs using syntax files supplied with the compiler.
There are also syntax packages for the popular proprietary editor Sublime Text 2 and the free editor Kate. There is no support for Rust in the IDE yet. There seems to be no debugger support either.

The following utilities are supplied with the rustc compiler:
> rustdoc- a utility for automatically generating documentation from source code like Doxygen;
> rustpkg- a package manager that allows you to easily install additional packages and libraries;
> rusti- the so-called REPL utility (read-eval-print-loop). This is essentially a test interpreter that takes a Rust expression from the command line, compiles it into an internal LLVM representation, executes it, and prints the result;
> rust- a universal utility that launches other utilities or a compiler depending on the parameters. It never worked for me.

All available documentation on the language is collected on the official website www.rust-lang.org. There is a detailed manual (http://static.rust-lang.org/doc/tutorial.html) - comprehensive formal documentation on all the nuances of the syntax, memory model, runtime system, etc., as well as documentation on the built-in core library and the standard library std. All documentation is in English. There are no current materials in Russian, and a couple of existing review articles are already very outdated.

Ideology and syntax


Rust is a C-like language that uses curly braces to separate blocks of code. The language is “multi-paradigm”, i.e. allows you to write code in an imperative-procedural, object-oriented, concurrent, or functional manner. Rust compiles to native binary code on any supported platform (uses LLVM as a backend). In theory, Rust code should be as fast as C/C++ code. Rust is positioned as a systems language, but it does not have built-in support for assembly code blocks like the “true” systems languages ​​C, C++ or D.

Rust's memory model inherently does not allow null or dangling pointers and buffer overflows. There is an optional garbage collector that works only within one thread of code. The language has built-in support for lightweight multitasking and communication between threads using messaging. Shared memory doesn't exist in Rust at all. All variables are divided into stack variables, heap variables for a given thread, and so-called “exchange” heap variables, which can be read by all threads, but cannot be changed by them. This automatically eliminates deadlock, which is considered the scourge of multi-threaded programming. The language's ABI is compatible with C, so Rust programs can be linked with libraries written in C without additional wrappers. For the needs of low-level system programming and to ensure compatibility with C, the language has a special “unsafe” mode without checking the correctness of pointers. In its ideology, Rust is closest to the Go language. Just like in Go, the main emphasis is on the simplicity of multi-threaded programming and the speed of developing large-scale applications, and the syntax is also unusual and somewhat surprising in some places. At the same time, Rust is not as minimalistic as Go and claims to be a system language.

Rust's syntax is largely borrowed from C and C++, with some ideas from Go, C#, Haskell, Python, and Ruby mixed in. I will not exhaustively describe the syntax of the language, but will focus only on the most interesting concepts.

Rust is gaining popularity, but many still do not understand its value and functions. We will tell you about the main advantages of the Rust programming language.

What do Rust and other languages ​​have in common?

The above definitions are hard to believe; it seems like an unrealistic statement, since previously all languages ​​chose one of the sides: reliability or performance.

A striking representative of high speed is, but we all know how often errors appear due to incorrect access to allocated memory, remote servers, and there is nothing to say about unpredictable outputs of work results. Due to multiple write threads, it is often difficult to predict the result.

The bias towards reliability is best demonstrated by language Haskell, which is compiled in nature and provides high security performance. Anything that can be compiled will work properly. Main disadvantage- this is low performance, it is difficult to imagine a project that requires high speed written in Haskell.

The rest also occupy a neutral position, a certain balance. They focus on practicality.

Rust incorporates the best characteristics C++ And Haskell, and was also able to maintain sufficient practicality and functionality from other competitors.

What is the beauty of the Rust language?

The magic features of Rust are made available through compilation basics and owner entity information ( owner), about a programmer who is only temporarily debugging or has taken over the project ( mutable borrow), as well as about the ordinary viewer ( immutable borrow).

When programming in Java or C++, you have to keep this information in memory, although the type of data is somewhat different. IN Rust this is implemented using language constructs; this information makes it easier for the compiler to establish the identity and correctly select the behavior model. With a compiler, you can ensure that potential and common problems are eliminated during code execution.

This language requires a slightly different approach. Despite the unusualness, the algorithm is quite obvious and effective. Now we will define the basics of the language, which can lead to a dead end when starting to study:

  1. The inheritance system has been completely eliminated; a special structure and abilities are used to replace it, more details traits.
  2. Pointers are present exclusively in code that is not subject to additional protection, that is, inside the unsafe() function. To replace them, safe code uses references that provide the correct pointer to existing objects.
  3. If the link is static and points to a specific element, for example, immutable borrow = &Object , it cannot be modified by any user until the link dies.
  4. If there is a mutable borrow = &mut Object link that changes, the contents cannot be read by any other user for the entire lifetime of the link.
  5. The developers focus on Mac and *nix platforms, because of this it works on the system Windows only possible using the GNU environment.

The target audience is quite important; the Rust language has a fairly active community, a developed system of communication and training. We recommend visiting the IRC channel or Reddit. To this day it has already been written, and most of them are still constantly being developed, their projects can be found on GitHub.

The language is most popular among developers who have taken the path of creating graphics and games. There are even developments to create a full-fledged operating system, but they are still being developed. In the near future there is the possibility of writing client programs and web servers. All of the above tasks are completely within the capabilities of Rust.

The main, and probably the only, drawback is its overly active development. As new versions are released, the syntax changes somewhat, and periodically there is a need to change the logic of behavior and development in order to adapt to the new capabilities. The situation will continue for some time until the release of Rust-1.0.

The regular column “ This Week in Rust", which can be found in Rust "n Stuffs at the link. There is always information about previous and past changes, as well as prospects for the development of the language.

By now you may have noticed that the syntax of the programming language in question is very similar to the syntax of languages ​​such as C/C++, because in both cases two slashes are used to highlight comments, code blocks are surrounded by curly braces, and function arguments are surrounded by parentheses. Also remember that the fn keyword is used to declare functions, and every program must have a main() function. The exclamation mark after the println function name in this case indicates that a macro is being used (essentially a convenient wrapper around the print function from the Rust runtime library).

To compile the program, simply run the command:

Rustc hello.rs

As a result, a binary file named hello should appear in the directory with the program source code file; to execute it, just run the command./hello. But if you pay attention to the size of this file, you will be somewhat shocked: it will exceed 800 KB. And all this is needed for such a simple program to work? Well, by default, the Rust compiler statically links most of the runtime libraries with the program, so you can copy the binary onto a system that doesn't have the Rust runtime libraries installed and run it without any problems. However, you can also tell the compiler to perform optimizations and dynamic linking:

Rustc -O C prefer-dynamic hello.rs

Now you will get a binary file of a more acceptable size, equal to 8 KB, but if you use the ldd utility, you will find that for the program to work correctly, the libstd-dynamic library must be present on the system.<версия>.so .

Programming language syntax

Now that we can compile and run programs in Rust, I propose to understand the syntax of this programming language and highlight its differences from the syntax of programming languages ​​such as C, C++ and other similar ones:

Fn doubler (x: i32) -> i32 ( x * 2 ) fn main () ( let a: i32 = 5; let b; b = doubler(a); println!("a times 2 ()", b); match b ( 1 ... 10 => println!("From 1 to 10"), _ => println!("Another number"), ) )

If you are used to working with C/C++ languages, you may think that this code is somehow strange, but it is quite logical. Let's start with the main() function: on the first line of let we declare a 32-bit integer variable a and assign it an initial value of 5. We could skip specifying the type of the variable (i32 is the standard variable type) and also not assign it an initial value , and in this case it would contain a zero value. Note that if you declare a variable and assign it a specific value in the same way as the variable a in the example, you will not be able to change its value later, so an error message will be generated when compiling the following code snippet:

Let a: i32 = 5; a = 10;

By default, variables in Rust are immutable, meaning their values ​​cannot change after initialization. You must explicitly declare mutable variables in a similar way:

Let mut a: i32 = 5;

Why is this needed? This is extra work, isn't it? Well, in essence this is true, but, on the other hand, this feature of the programming language helps to develop safe programs. You should only make variables mutable whose values ​​actually need to change. Rust forces you to be as verbose as necessary to describe as accurately as possible how the program works: the line above declares a signed integer variable a of exactly 32 bits in size, with the possibility of changing its value in the future.

Next, we call our doubler function with variable a as its argument and store the return value in variable b. Pay attention to the declaration of the doubler function, which is located at the beginning of the program code: it indicates the type of the function parameter (i32) and the type of the return value (i32) after the -> symbols. It's also easy to see that the function performs a single operation, x * 2 , which isn't even followed by a semicolon, like a normal block of Rust code; what's going on there?

It turns out that you can return the value of a function either in the same way as in C, or by simply placing the expression on the last line of the function code, as was done in this case. And, since this is just an expression, there is no need to put a semicolon after it.

Let's return to the main() function, where we used the println!() macro to print the result; Note the technique of substituting the value of a variable using the character sequence () . Finally, the example demonstrates the extremely useful "match" keyword of the Rust programming language, which can significantly reduce the amount of code if you need to perform a large number of if/else statements. In this case, 1...10 is a declaration of a range of values ​​(from 1 to 10 inclusive), and the underscore (_) character matches all other values.

In Rust, the char string type allows the use of four-byte characters, that is, any Unicode characters, and this means that the programming language was adapted at the design stage to work with different languages ​​and special characters. Another useful data type is a tuple, which is a collection of variables of different types:

Let x = (1, 2.0, "Hello");

In this case, an integer value, a float value, and a string value are placed in the same tuple. These values ​​are immutable and can be accessed in the same way:

Println!("()", x.2);

As a result, the value of the third element of the tuple x will be output, that is, the string "Hello" . As is the case with regular arrays, which are also supported in Rust, the numbering of elements of tuples starts from zero. You can use tuples to return multiple values ​​from a function:

Fn switch(input: (i32, i32)) -> (i32, i32) ( (input.1, input.0) ) fn main() ( let x = (10, 50); let y = switch(x) ; println!("(), ()", y.0, y.1); )

In this case, a function called switch() takes a tuple of two 32-bit integer values ​​and stores them in the input variable. It also returns a tuple with two integer values. This function uses a simple expression that allows you to swap the elements of a tuple and return the resulting tuple.

The main() function creates a tuple named x containing the values ​​10 and 50, and a tuple named y containing the values ​​that were returned from the call to switch(). Next, the values ​​of the tuple are simply displayed on the screen (50, 10).

Advice: If you're itching to explore Rust's capabilities yourself, we recommend starting by reading the official documentation located at https://doc.rust-lang.org/book.

This was a brief description of the syntax and capabilities of the Rust programming language; If you would like to learn more about this programming language in a special series of articles, let us know!

Continuing the topic:
Apple

Operators / 10/24/2017 MTS phone firmware (Smart Race, Sprint, Surf, Run 4G) MTS, like any other operator, offers its customers various models of smartphones for...