35,99 €
Discover the world of Rust programming through real-world examples
Rust is an open source, safe, concurrent, practical language created by Mozilla. It runs blazingly fast, prevents segfaults, and guarantees safety. This book gets you started with essential software development by guiding you through the different aspects of Rust programming. With this approach, you can bridge the gap between learning and implementing immediately.
Beginning with an introduction to Rust, you’ll learn the basic aspects such as its syntax, data types, functions, generics, control flows, and more. After this, you’ll jump straight into building your first project, a Tetris game. Next you’ll build a graphical music player and work with fast, reliable networking software using Tokio, the scalable and productive asynchronous IO Rust library.
Over the course of this book, you’ll explore various features of Rust Programming including its SDL features, event loop, File I/O, and the famous GTK+ widget toolkit. Through these projects, you’ll see how well Rust performs in terms of concurrency—including parallelism, reliability, improved performance, generics, macros, and thread safety. We’ll also cover some asynchronous and reactive programming aspects of Rust.
By the end of the book, you’ll be comfortable building various real-world applications in Rust.
This book is for software developers interested in system level and application programming who are looking for a quick entry into using Rust and understanding the core features of the Rust Programming. It’s assumed that you have a basic understanding of Java, C#, Ruby, Python, or JavaScript.
Guillaume Gomez is an open source lover (let's keep this simple). He's a reviewer for the Rust language and a member of the GNOME organization. Guillaume lives in Paris, France. Antoni Boucher has been enjoying programming for 10 years, especially functional and system programming. He works in the ad tech industry and strives to improve the performance and reliability of software. He contributes to multiple open source projects and is interested in system programming and compilers. Antoni lives in Montreal, Canada.Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 425
Veröffentlichungsjahr: 2018
Copyright © 2018 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author(s), nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Aaron LazarAcquisition Editor: Alok DhuriContent Development Editor: Akshada IyerTechnical Editor: Mehul SinghCopy Editor: Safis EditingProject Coordinator: Prajakta NaikProofreader: Safis EditingIndexer: Pratik ShirodkarGraphics: Jason MonteiroProduction Coordinator: Deepika Naik
First published: January 2018
Production reference: 1090118
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78839-063-7
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Guillaume Gomez is an open source lover (let's keep this simple). He's a reviewer for the Rust language and a member of the GNOME organization. Guillaume lives in Paris, France.
Antoni Boucher has been enjoying programming for 10 years, especially functional and system programming. He works in the ad tech industry and strives to improve the performance and reliability of software. He contributes to multiple open source projects and is interested in system programming and compilers. Antoni lives in Montreal, Canada.
Sebastian Dröge is a free software developer, currently working for Centricular Ltd. His main involvement is with the GStreamer project, a cross-platform multimedia framework. He also contributes to various other projects, such as Debian, GNOME, Rust, and WebKit. He works as a contractor on free software.
Daniel Durante is an avid coffee drinker/roaster, motorcyclist, archer, welder, and carpenter whenever he isn't programming. From the age of 12, he has been involved with web and embedded programming with PHP, Node.js, Golang, Rust, and C.
He has worked on text-based browser games that have reached over 1,000,000 active players and created bin-packing software for CNC machines. He loves working with embedded programming with cortex-m and PIC circuits, high-frequency trading applications, and he has helped contribute to one of the oldest ORMs of Node.js (SequelizeJS).
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Basics of Rust
Getting to know Rust
Installing Rust
Windows
Linux/Mac
Test your installation
Documentation and reference
Main function
Variables
Built-in data types
Integer types
Floating-point types
Boolean type
Character type
Control flow
Writing a condition
Creating while loops
Creating functions
Creating structures
References
Clone types
Copy types
Mutable references
Methods
Constructors
Tuples
Enumerations
Pattern matching
Irrefutable patterns
Traits
Default methods
Associated types
Rules
Generics
The Option type
Arrays
Slices
For loops
Macros
Multiple pattern rules
Repetitions
Optional quantifier
Summary
Starting with SDL
Understanding Rust crates
Installing SDL2
Installing SDL2 on Linux
Installing SDL2 on Mac
Installing SDL2 on Windows
Windows with Build Script
Windows (MinGW)
Windows (MSVC)
Setting up your Rust project
Cargo and crates.io
The docs.rs documentation
Back to our Cargo.toml file
Rust's modules
Tetris
Creating a window
Drawing
Playing with Options
Solution
Loading images
Installing SDL2_image on Mac
Installing SDL2_image on Linux
Installing SDL2_image on Windows
Playing with features
Playing with images
Handling files
Saving/loading high scores
Iterators
Reading formatted data from files
Summary
Events and Basic Game Mechanisms
Writing Tetris
Tetrimino
Creating tetriminos
Generating a tetrimino
Rotating a tetrimino
Tetris struct
Interacting with the game map
SDL events
Score, level, lines sent
Levels and lines sent
Highscores loading/overwriting
Summary
Adding All Game Mechanisms
Getting started with game mechanisms
Rendering UI
Rendering initialization
Rendering
Playing with fonts
Install on OS X
Install on Linux
Other system/package manager
Loading font
Summary
Creating a Music Player
Installing the prerequisite
Installing GTK+ on Linux
Installing GTK+ on Mac
Installing GTK+ on Windows
Creating your first window
Closure
Preventing the default behavior of an event
Creating a toolbar
Stock item
Improving the organization of the application
Adding tool button events
Lifetime
Ownership
Containers
Types of containers
The Box container
Adding a playlist
The MVC pattern
Opening MP3 files
Reference-counting pointer
ID3— MP3 metadata
Opening files with a file dialog
Deleting a song
Displaying the cover when playing a song
Summary
Implementing the Engine of the Music Player
Installing the dependencies
Installing dependencies on Linux
Installing dependencies on Mac
Installing dependencies on Windows
Decoding MP3 files
Adding dependencies
Implementing an MP3 decoder
Getting the frame samples
Playing music
Event loop
Atomic reference counting
Mutual exclusion
Send trait
Sync trait
Lock-free data structures
Playing music
Mutex guard
RAII
Using the music player
Pausing and resuming the song
Interior mutability
Showing the progression of the song
Improving CPU usage
Condition variable
Showing the song's current time
Loading and saving the playlist
Saving a playlist
Loading a playlist
Using gstreamer for playback
Summary
Music Player in a More Rusty Way with Relm
Reasons to use relm instead of gtk-rs directly
State mutation
Asynchronous user interface
Creating custom widgets
Creating a window with relm
Installing Rust nightly
Widget
Model
Messages
View
Properties
Events
Code generation
Update function
Adding child widgets
One-way data binding
Post-initialization of the view
Dialogs
Other methods
Playlist
Model parameter
Adding a relm widget
Communicating between widgets
Communicating with the same widget
Emit
With different widgets
Handle messages from a relm widget
Syntax sugar to send a message to another relm widget
Playing music
Computing the song duration
Using relm on stable Rust
Relm widgets data binding
Summary
Understanding FTP
File transfer protocol
Introduction to FTP
Implementing simple chunks of commands
Starting with basics
Commands implementation
Implementing the SYST command
Implementing the USER command
Implementing the NOOP command
Implementing the PWD command
Implementing the TYPE command
Implementing the LIST command
Implementing the PASV command
Back to the LIST command
Implementing the CWD command
Implementing the CDUP command
Full implementation of the LIST command
Implementing the MKD command
Implementing the RMD command
Testing it
Summary
Implementing an Asynchronous FTP Server
Advantages of asynchronous IO
Disadvantages of asynchronous IO
Creating the new project
Using Tokio
Tokio event loop
Using futures
Handling errors
Unwrapping
Custom error type
Displaying the error
Composing error types
The ? operator, revisited
Starting the Tokio event loop
Starting the server
Handling clients
Handling commands
FTP codec
Decoding FTP commands
Encoding FTP commands
Handling commands
Managing the current working directory
Printing the current directory
Changing the current directory
Setting the transfer type
Entering passive mode
Bytes codec
Decoding data bytes
Encoding data bytes
Quitting
Creating directories
Removing directories
Summary
Implementing Asynchronous File Transfer
Listing files
Downloading a file
Uploading files
Going further!
Configuration
Securing the config.toml access
Unit tests
Backtraces
Testing failures
Ignoring tests
Integration tests
Teardown
Print output to stdout
Documentation
Documenting a crate
Documenting a module
Headers
Code blocks
Documenting an enumeration (or any type with public fields)
Generating the documentation
Warning about public items without documentation
Hiding items from the documentation
Documentation tests
Tags
ignore
compile_fail
no_run
should_panic
Combining flags?
About the doc blocks themselves
Hiding code blocks lines
Fuzzing tests
Summary
Rust Best Practices
Rust best practices
Slices
API tips and improvements
Explaining the Some function
Using the Path function
Usage tips
Builder pattern
Playing with mutable borrows
Playing with moves
Code readability
Big number formatting
Specifying types
Matching
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
The aim of this book is to give a little tour of some Rust basics (playing with GUIs) and advanced (async programming) features. Because interesting projects are always a huge plus in a language learning process, we wrote the book with this focus. We think this language is awesome and we hope to give you the motivation and knowledge in order to have even more rustaceans in the future!
Readers only need a basic knowledge of the Rust language to follow through this book if they want to enjoy it the most, even though it's recommended to always have the documentation open alongside to answer questions this book might not provide (we, authors, aren't almighty, which is a shame, we know). For readers who don't know Rust at all, we recommend that they first read the Rust book that you can find here at https://doc.rust-lang.org/stable/book/ and then come back to read this one!
Chapter 1, Basics of Rust, covers the installation of Rust and teaches the syntax and basic principles of the language so that you are ready to code projects with it.
Chapter 2, Starting with SDL, shows how to start using SDL and its main features, such as events and drawings. Once the project is created, we'll make a window displaying an image.
Chapter 3, Events and Basic Game Mechanisms, takes you deeper into how to handle events. We'll write the tetrimino objects and make them change following the received events.
Chapter 4, Adding All Game Mechanisms, completes the game's mechanisms. At the end of this chapter, we'll have a fully running Tetris game.
Chapter 5, Creating a Music Player, helps you start building a graphical music player. Only the user interface will be covered in this chapter.
Chapter 6, Implementing the Engine of the Music Player, adds the music player engine to the graphical application.
Chapter 7, Music Player in a More Rusty Way with Relm, improves the music player to add a playing, allowing to process the music in the list to remove the vocals.
Chapter 8, Understanding FTP, introduces the FTP protocol by implementing a synchronous FTP server, to prepare you to write the asynchronous version in the next chapters.
Chapter 9, Implementing an Asynchronous FTP Server, implements an FTP protocol with Tokio.
Chapter 10, Implementing Asynchronous File Transfer, implements the FTP service itself. This is where the application will be able to upload and download files.
Appendix, Rust Best Practices, shows how to write nice Rust APIs and how to make them as easy and nice to use as possible.
There isn't much that you require. Besides, Rust is well supported on any operating system. Linux is the best-supported operating system here. You can also use Rust on Windows and macOS as well, you'll need a fairly recent computer; a gigabyte of RAM should be enough for the purposes of this book.
You can download the example code files for this book from your account at www.packtpub.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packtpub.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Rust-Programming-By-Example. We also have other code bundles from our rich catalog of books and videos available athttps://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/RustProgrammingByExample_ColorImages.pdf
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "Mount the downloaded WebStorm-10*.dmg disk image file as another disk in your system."
A block of code is set as follows:
html, body, #map { height: 100%; margin: 0; padding: 0}
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
[default]exten => s,1,Dial(Zap/1|30)exten => s,2,Voicemail(u100)
exten => s,102,Voicemail(b100)
exten => i,1,Voicemail(s0)
Any command-line input or output is written as follows:
$ mkdir css
$ cd css
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Select System info from the Administration panel."
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
This chapter introduces you to the basics of Rust, a systems programming language designed to be secure and fast. Rust is a good candidate to write concurrent software and it helps to prevent bugs. After reading this chapter, you'll be ready to code cool projects in the subsequent chapters. After learning about the language itself, you'll install its compiler and package manager, and you'll start programming right away. You'll also learn about the following concepts:
Variables
Built-in data types
Control flow (conditions and loops)
Functions
Custom data types
References
Pattern matching
Traits and Generics
Arrays and Slices
Macros
Rust is a system programming language developed by Mozilla, whose version 1.0 appeared in 2015. A system language means that you have control over the memory used by the program—you decide whether you want to allocate the memory on the stack or the heap, and when the memory is freed. But don't worry; in Rust, the compiler is very helpful and prevents you from making the many mistakes you can make in C and C++ that lead to segmentation faults. A segmentation fault arises when the programmer tries to access some memory that is not accessible to its process. Memory unsafety leads to bugs and security flaws.
Moreover, the compiler is smart enough to know where to insert the memory deallocation instructions so that you don't need to manually free your memory, all of that without a garbage collector, which is one of its greatest features. Since Rust is safe and fast, it is the perfect candidate for writing operating systems, embedded programs, servers, and games, but you can also use it to develop desktop applications and websites. A great example of this power is the Servo web engine, also developed by Mozilla.
Rust is multi-paradigm: it can be used in an imperative or functional way and you can even write concurrent applications safely. It is statically typed, meaning that every type must be known at compile time, but since it uses type inference, we can omit the type for most local variables. It is also strongly typed, which means that its type system prevents the programmer from some kinds of errors, such as using the wrong type for a function parameter. And Rust is very good at writing concurrent software because it prevents data races, which is concurrent access to a variable where one is a write; this is an undefined behavior in other languages. One thing to remember when reading this book is that Rust prevents you from shooting yourself in the foot. For instance, Rust doesn't have:
null pointers
data races
use after free
use before initialization
goto
automatic coercion of Boolean, numbers and enumerations
Also, Rust helps to prevent memory leaks. However, all of this is possible with unsafe code, which is explained in Chapter 3, Events and Basic Game Mechanisms.
Without further ado, let's install the tools we'll need throughout the book.
In this section we'll install rustup, which allows us to install different versions of the compiler and package manager.
Go to https://rustup.rs and follow the instructions in order to download rustup-init.exe, then run it.
Unless your distribution provides a package for rustup, you'll need to install rustup by typing the following command in your terminal:
$
curl
https://sh.rustup.rs -sSf
|
sh
info
: downloading installer
Welcome
to Rust! [
...
]
Current
installation options:
default
host triple: x86_64-unknown-linux-gnu
default
toolchain: stable
modify
PATH variable: yes
1
)
Proceed
with installation (default)
2
)
Customize
installation
3
)
Cancel
installation
This downloaded rustup and asked you whether you want to customize the installation. Unless you have particular needs, you'll be okay with the default.
Note: The $ represents your shell prompt and should not be typed; you must type the text following it. Also, a line of text that doesn't start with $ represents the text output of the program.
To proceed with the installation, enter 1 and press Enter. This will install the rustc compiler, and the cargo package manager, among other things:
info
: syncing channel updates for
'stable-x86_64-unknown-linux-gnu'
info
: latest update on 2017-07-20, rust version 1.19.0 (0ade33941 2017-07-17)
info
: downloading component
'rustc'
[
...
]
stable
installed - rustc 1.19.0 (0ade33941 2017-07-17)
Rust
is installed now. Great!
To
get started you need Cargo
's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done automatically.
To configure your current shell run source $HOME/.cargo/env
As pointed out by the installer, you need to execute the following command in order to add the directory containing these tools in your PATH:
$
source
$HOME
/.cargo/env
# Which is the same as executing the following:
$
export
PATH=
"
$HOME
/.cargo/bin:
$PATH
"
(This is only needed once because the rustup installer added it to your ~/.profile file.)
Now, test that you have both cargo and rustc, as you'll need them very soon:
$
cargo
-V
cargo
0.23.0 (61fa02415 2017-11-22) $
rustc
-V
rustc
1.22.1 (05e2e1c41 2017-11-22)
Cargo is Rust's package manager and build tool: it allows you to compile and run your projects, as well as managing their dependencies.
At the time of writing this book, the stable Rust version was 1.22.0.
Let's try to build a Rust program. First, create a new project with cargo:
$
cargo
new --bin hello_world
Created
binary (application)
`
hello_world
`
project
The --bin flag indicates that we want to create an executable project, as opposed to a library (which is the default without this flag). In the Rust world, a crate is a package of libraries and/or executable binaries.
This created a hello_world directory containing the following files and directory:
$
tree
hello_world/
hello_world/
├──
Cargo.toml
└──
src
└──
main.rs
1
directory, 2 files
The Cargo.toml file is where the metadata (name, version, and so on) of your project resides, as well as its dependencies. The source files of your project are in the src directory. It's now time to run this project:
$
cd
hello_world/ $
cargo
run
Compiling
hello_world v0.1.0 (file:///home/packtpub/projects/hello_world)
Finished
dev [unoptimized + debuginfo] target(s)
in
0.39
secs
Running
`
target/debug/hello_world
`
Hello
, world!
The first three lines printed after cargo run are lines printed by cargo indicating what it did: it compiled the project and ran it. The last line, Hello, world!, is the line printed by our project. As you can see, cargo generates a Rust file that prints text to stdout (standard output):
$
cat
src/main.rs
fn
main()
{
println
!(
"Hello, world!"
);
}
If you only want to compile the project without running it, type the following instead:
$
cargo
build
Finished
dev [unoptimized + debuginfo] target(s)
in
0.0
secs
This time, we didn't see Compiling hello_world because cargo did not see any changes to the project's files, thus, there's no need to compile again.
You can find the API documentation here: https://doc.rust-lang.org/stable/std/. The reference can be found here: https://doc.rust-lang.org/stable/reference/.
Let's look again at our first project source code:
fn
main()
{
println!
(
"Hello, world!"
);
}
It only contains a main function—this is where the execution of the program begins. It is a function that takes no arguments (hence the empty parentheses) and returns a unit, also written (). The body of the function, between curly brackets, contains a call to the println!() macro—we can see this is a macro because it ends with !, as opposed to a function. This macro prints the text between parentheses, followed by a new line. We'll see what is a macro in the Macros section.
Let's look at the basic types provided by the language, such as integers, floats, Booleans, and characters.
The following integer types are available in Rust:
Unsigned
Signed
u8
i8
u16
i16
u32
i32
u64
i64
usize
isize
The u means unsigned, while the i means signed, and the number following it is the number of bits. For instance, a number of the u8 type can be between 0 and 255, inclusive. And a number of the i16 type can be between -32768 and 32767, inclusive. The size variants are the pointer-sized integer types: usize and isize are 64-bit on a 64-bit CPU. The default integer type is i32, which means that this type will be used by the type inference when it cannot choose a more specific type.
There are two floating-point types: f32 and f64, the latter being the default. The number following f represents the number of bits for the type. An example value is 0.31415e1.
The bool type admits two values: true and false.
The char type represents a Unicode character. An example unicode scalar value is '€'.
We'll now look at how to write conditions and loops in Rust. Conditions are useful to execute a block of code when a certain situation happens, and loops allow you to repeat a block of code a number of times, until a condition is met.
We had a brief introduction to functions when we saw the main function. Let's see how to create functions with parameters and a return value.
Here's how to write a function that returns the maximum of two numbers:
fn
max(a:
i32
, b:
i32
) ->
i32
{
if
a > b
{
a
}
else
{
b
}
}
The parameters are between parentheses and must be explicitly typed since the type inference only infers the types of local variables. This is a good thing since this acts as a documentation. Moreover, this can prevent bugs when we change how we use the parameters or change the value that is returned. The function can be defined after it is used without any issue. The return type is after ->. When we return (), we can omit the -> and type.
The last expression in the body of a function is the value returned from the function. You don't need to use return. The return keyword is only needed when you want to return early.
Traits can contain default methods, which can be convenient for the implementor of the trait since fewer methods will need to be implemented. Let's add a toggle() default method in the trait:
trait
BitSet
{
fn
clear(&
mut
self
, index:
usize
);
fn
is_set(&
self
, index:
usize
) ->
bool
;
fn
set(&
mut
self
, index:
usize
);
fn
toggle(&
mut
self
, index:
usize
)
{
if
self
.is_set(index)
{
self
.clear(index);
}
else
{
self
.set(index);
}
}
}
Since the new method has a body, we don't need to update our previous implementation. However, we could do it to provide a more efficient implementation, for instance:
impl
BitSet
for
u64
{
// The other methods are the same as before.
fn
toggle(&
mut
self
, index:
usize
)
{
*
self
^=
1
<< index;
}
}
There are some rules that must be followed in order to use traits. The compiler will throw an error if they are not respected:
The trait must be imported in order to use its methods
The implementation of a trait must be in the same crate as the trait or the type
The second rule is to avoid conflicts that could otherwise happen when using multiple libraries. We can have such a conflict when two imported traits provide the same method for the same type.
Generics are a way to make a function or a type work for multiple types to avoid code duplication. Let's rewrite our max function to make it generic:
fn
max<T:
PartialOrd
>(a: T, b: T) -> T
{
if
a > b
{
a
}
else
{
b
}
}
The first thing to note is that there's a new part after the function name: this is where we declare the generic types. We declare a generic T type, : PartialOrd after it means that this T type must implement the PartialOrd trait. This is called a trait bound. We then use this T
