官术网_书友最值得收藏!

  • Mastering Rust
  • Rahul Sharma Vesa Kaihlavirta
  • 670字
  • 2021-07-02 13:35:28

Generics

From the dawn of high-level programming languages, the pursuit of better abstraction is something that language designers have always strived for. As such, many ideas concerning code reuse emerged. The very first of them was functions. Functions allow you to chunk away a sequence of instructions within a named entity that can be called later many times, optionally accepting any arguments for each invocation. They reduce code complexity and amplify readability. However, functions can only get you so far. If you have a function, say avg, that calculates the average of a given list of integer values and later you have a use case where you need to calculate the average for a list of float values too, then the usual solution is to create a new function that can average float values from the list of floats. What if you wanted to accept a list of double values too? We probably need to write another function again. Writing the same function over and over again that differs only by its arguments is a waste of precious time for programmers. To reduce this repetition, language designers wanted a way to express code so that the avg function can be written in a way that accepts multiple types, a generic function, and thus the idea of generic programming, or generics, was born. Having functions that can take more than one type is one of the features of generic programming, and there are other places that generics can be used. We'll explore all of them in this section.

Generic programming is a technique that is only applicable in the case of statically typed programming languages. They first appeared in ML, a statically typed functional language. Dynamic languages such as Python use duck typing, where APIs treat arguments based on what they can do rather than what they are, so they don't rely on generics. Generics are part of the language design feature that enables code reuse and the Don't repeat yourself (DRY) principle. Using this technique, you can write algorithms, functions, methods, and types with placeholders for types, and specify a type variable (with a single letter, which is usually T, K, or V by convention) on these types, telling the compiler to fill in the actual types later when any code instantiates them. These types are referred to as generic types or items. The single letter symbols such as T on type are called generic type parameters. They are substituted with concrete types such as  u32 when you use or instantiate any generic item.

Note: By substitution, we mean that every time a generic item is used with a concrete type, a specialized copy of that code is generated at compile time with the type variable T, getting replaced with the concrete type. This process of generating specialized functions with concrete types at compile time is called monomorphization, which is the procedure of doing the opposite of polymorphic functions.

Let's look at some of the existing generic types from the Rust standard library.

The Vec<T> type from the standard library is a generic type that is defined as follows:

pub struct Vec<T> {
buf: RawVec<T>,
len: usize,
}

We can see that the type signature of Vec contains a type parameter T after its name, surrounded by a pair of angle brackets < >. Its member field, buf, is a generic type as well, and so the Vec itself has to be generic. If we don't have T on our generic type Vec<T>, even though we have a T on its buf field, we get the following error:

error[E0412]: cannot find type `T` in this scope

This T needs to be part of the type definition for Vec. So, when we denote a Vec, we always refer to it by using Vec<T> when denoting generically or by using Vec<u64> when we know the concrete type. Next, let's look at how to create our own generic types.

主站蜘蛛池模板: 苗栗市| 绥德县| 凤庆县| 雷波县| 嘉定区| 永福县| 会泽县| 偏关县| 丹阳市| 金堂县| 巍山| 郓城县| 德格县| 揭东县| 明星| 北宁市| 阜城县| 龙岩市| 梁山县| 吴江市| 西昌市| 沙洋县| 鹰潭市| 休宁县| 镇赉县| 黑山县| 威信县| 石渠县| 搜索| 巴林右旗| 长子县| 花莲县| 个旧市| 连云港市| 河北省| 古蔺县| 彰武县| 祁阳县| 唐山市| 邵阳市| 时尚|