It is recommended that friends first study “Prompt Guide” and then read this article for better understanding. It is suggested to use GPT-4; if GPT-4 is not available, GPT-3.5 can also be used to build this system, although GPT-4 is more precise. Additionally, this system can also be applied to other programming languages. The cover image is “Café at Amsterdam Port,” drawn by me using Midjourney.
Introduction#
Recently, I've been following the trend of playing with AI, including ChatGPT and Midjourney, to experience what it feels like to be a Prompt Engineer with a rumored annual salary of one million dollars. Until this week, I discovered that GPT-4 is very helpful for learning Rust code. So, I attempted to create this Rust learning assistance system, which I named RustChat, and created a repository on GitHub for everyone to communicate.
When we learn Rust, having a handy system that can quiz us on our knowledge points at any time and provide accurate answers and explanations would be great. Or, when we don't know what project to practice on, it could recommend project ideas.
Now, with AI, we can build such a magical and useful system.
RustChat: The Ultimate Rust Learning Assistance “Magic” System Introduction#
Let’s start with the idea. Since we want a prompt command mode, we should design the command format first, just like designing a program API.
It is worth mentioning that this idea seems relatively simple, but it was explored after numerous attempts. Previous failed designs resulted in new commands directly breaking GPT's old settings, leading to command confusion.
“Magic” Design#
Here are the command prompt examples I want to implement:
work // work is the main command, representing outputting work-level Rust questions
work -tech trait // `-tech` indicates a primary command, representing an output of a work-level conceptual explanation of the specified content trait, along with code examples
work -tech --cn trait // `--cn` indicates a secondary command, representing outputting the content set by the main command and primary command in the specified language Chinese
work -type --en eBPF // `-type` indicates a primary command, representing outputting work-level questions for the specified content eBPF,
work -idea --cn // `-idea` indicates a primary command, representing outputting project practice ideas and thoughts corresponding to the main command level for reference, `--cn` indicates a secondary command, representing outputting content in the specified language Chinese
I plan to categorize the questions into three levels:
- Work level. Work-level questions cover common features and knowledge for beginners and daily Rust code writing.
- Professional level. Professional-level questions cover expert-level features and knowledge points in Rust.
- Quiz type. Quiz-type questions specifically test confusing features of the Rust language.
The main commands corresponding to these three levels are:
- work command, corresponding to work-level questions.
- expert command, corresponding to professional-level questions.
- quiz command, corresponding to quiz-level questions.
- answer command, used to specify the number of questions to be answered.
Next, I will introduce primary commands, which can be combined with the main command in any way:
-tech
, indicating a primary command, representing outputting a corresponding main command level conceptual explanation of the specified content, along with examples.-type
, indicating a primary command, representing outputting corresponding main command level questions for the specified content.-idea
, indicating a primary command, representing outputting corresponding main command level project practice ideas and thoughts for reference.-crate
, indicating a primary command, limited to the main commandwork
, representing recommending corresponding third-party crates for the specified content.-n
, indicating a primary command, limited to the main commandanswer
, representing the number of questions to be answered.
Next, I will introduce secondary commands, which can act on primary commands:
--cn
, indicating a secondary command, representing outputting content in Chinese.--en
, indicating a secondary command, representing outputting content in English.--jp
, indicating a secondary command, representing outputting content in Japanese.
Thus, the commands that this learning assistance system should support are as follows:
work // work is the main command, representing outputting work-level Rust questions
work -tech trait // `-tech` indicates a primary command, representing an output of a work-level conceptual explanation of the specified content trait, along with code examples
work -tech --cn trait // `--cn` indicates a secondary command, representing outputting the content set by the main command and primary command in the specified language Chinese
work -type --en eBPF // `-type` indicates a primary command, representing outputting work-level questions for the specified content eBPF,
work -crate eBPF // `-crate` indicates a primary command, representing recommending corresponding third-party crates for the specified content eBPF
work -idea --cn // `-idea` indicates a primary command, representing outputting project practice ideas and thoughts corresponding to the main command level for reference, `--cn` indicates a secondary command, representing outputting content in the specified language Chinese
answer -n 2 ,// indicates a primary command, limited to the main command `answer`, representing the number of questions to be answered before this command
expert // work is the main command, representing outputting work-level Rust questions
expert -tech trait // `-tech` indicates a primary command, representing an output of a work-level conceptual explanation of the specified content trait, along with code examples
expert -tech --cn trait // `--cn` indicates a secondary command, representing outputting the content set by the main command and primary command in the specified language Chinese
expert -type --en eBPF // `-type` indicates a primary command, representing outputting work-level questions for the specified content eBPF,
expert -idea --cn // `-idea` indicates a primary command, representing outputting project practice ideas and thoughts corresponding to the main command level for reference, `--cn` indicates a secondary command, representing outputting content in the specified language Chinese
quiz // work is the main command, representing outputting work-level Rust questions
quiz -tech trait // `-tech` indicates a primary command, representing an output of a work-level conceptual explanation of the specified content trait, along with code examples
quiz -tech --cn trait // `--cn` indicates a secondary command, representing outputting the content set by the main command and primary command in the specified language Chinese
quiz -type --en eBPF // `-type` indicates a primary command, representing outputting work-level questions for the specified content eBPF,
quiz -idea --cn // `-idea` indicates a primary command, representing outputting project practice ideas and thoughts corresponding to the main command level for reference, `--cn` indicates a secondary command, representing outputting content in the specified language Chinese
Creating the Prompt#
Next, we will create the prompt. To ensure that GPT-4 can fully understand the designed “magic,” we should take a step-by-step approach from “whole to detail” to “feed” it.
1. Set the Main Command
Please transform into a Rust expert and help me generate Rust questions according to my requirements. The questions will default to include a multiple-choice question and a coding implementation question. The output will default to Chinese unless a corresponding secondary command is specified to tell you the number of questions.
I plan to categorize the questions into three levels:
1. Work level. Work-level questions cover common features and knowledge for beginners and daily Rust code writing.
2. Professional level. Professional-level questions cover expert-level features and knowledge points in Rust.
3. Quiz type. Quiz-type questions specifically test confusing features of the Rust language.
The main commands corresponding to these three levels are:
1. work command, corresponding to work-level questions.
2. expert command, corresponding to professional-level questions.
3. quiz command, corresponding to quiz-level questions.
4. answer command, used to specify the number of questions to be answered.
2. Set the Primary Commands
Next, I will introduce primary commands, which can be combined with the main command:
1. `-tech`, indicating a primary command, representing outputting a corresponding main command level conceptual explanation of the specified content, along with examples.
2. `-type`, indicating a primary command, representing outputting corresponding main command level questions for the specified content.
3. `-idea`, indicating a primary command, representing outputting corresponding main command level project practice ideas and thoughts for reference.
4. `-crate`, indicating a primary command, representing recommending corresponding third-party crates for the specified content.
5. `-n`, indicating a primary command, representing the number of questions to be answered, along with explanations for the answers. When used with other main commands, it limits the number of generated questions.
3. Set the Secondary Commands
Next, I will introduce secondary commands, which can act on primary commands:
1. `--cn`, indicating a secondary command, representing outputting content in Chinese.
2. `--en`, indicating a secondary command, representing outputting content in English.
3. `--jp`, indicating a secondary command, representing outputting content in Japanese.
4. Adding Modification Command Definitions
The reason for designing this command system so painstakingly is to make modifying commands more convenient. Otherwise, GPT-4 would get confused.
Here is an example of modifying a command:
Modify primary command:
`-n`, indicating a primary command, representing the number of questions to be answered, along with explanations for the answers. When used with other main commands, it limits the number of generated questions.
Here is an example of adding a command:
Add main command:
explain, indicating a detailed explanation of the specified Rust code
debug, indicating helping to find code bugs and providing corrected code according to the given compiler error messages
Note: The word explain itself means to explain, so even if the main command is not set this way, GPT can recognize this word. Usually,
explain --cn
can also be recognized by GPT, and it will output in Chinese.
Usage example:
debug
fn add(a: i32, b: i32) -> i32 {
(a + b) as i64
}
error: type mismatch in return type
Let GPT Output the “Magic” System Manual#
Finally, let GPT help you organize all the main commands, primary commands, secondary commands, and their functions into a markdown table:
Please help me consolidate the main commands, primary commands, secondary commands, and their functions into a markdown table for output.
It will output the following table:
Main Command | Function |
---|---|
explain | Provide a detailed explanation of the specified Rust code |
debug | Help find code bugs and provide corrected code based on the given compiler error messages |
work | Output questions covering common features and knowledge points for Rust beginners and daily coding |
expert | Output questions covering expert-level features and knowledge points in Rust |
quiz | Output questions that specifically test confusing features of the Rust language |
answer | Specify the number of questions to be answered, along with explanations for the answers |
Primary Command | Function |
---|---|
-tech | Output a corresponding main command level conceptual explanation, along with examples |
-type | Output corresponding main command level questions |
-idea | Output corresponding main command level project practice ideas and thoughts for reference |
-crate | Limited to the main command work , recommend corresponding third-party crates |
-n | Limited to the main command answer , specify the number of questions to be answered, along with explanations |
Secondary Command | Function |
---|---|
--cn | Output content in Chinese |
--en | Output content in English |
--jp | Output content in Japanese |
Effects of Using the “Magic” System#
Now our “magic” system can be used. By combining main commands, primary commands, and secondary commands, we can achieve the desired effects.
We can use it to accomplish the following functions:
- Generate Rust questions and answers at different levels to test our knowledge points
- Specify Rust language features to generate corresponding questions
- Recommend practice projects
- Answer questions generated by ourselves
- Specify the natural language of the output content
Generate Work-Level Questions#
work
GPT-4:
Here are two work-level Rust questions, one multiple-choice question and one coding implementation question.
Multiple-choice question:
In Rust, which keyword is used to declare an immutable variable?
A. let
B. mut
C. const
D. static
Coding implementation question:
- Please write a Rust function
find_max
that takes a vector of integers as a parameter and returns the maximum value in the vector. If the vector is empty, return None. The example function signature is as follows:
fn find_max(numbers: Vec<i32>) -> Option<i32> {
// Write your code here
}
Generate Work Question Quantity#
work -n 1
GPT-4:
GPT understands that
-n
requires an explanation for the question, which can be modified through command modification.
Here is one work-level Rust question, one multiple-choice question:
Multiple-choice question:
- In Rust, which keyword is used to declare an immutable variable?
A. let B. mut C. const D. static
Answer: A. let
Explanation: In Rust, the let
keyword is used to declare an immutable variable. Immutable means that the variable's value cannot be changed after declaration. If you need to declare a mutable variable, you can use let mut
. const
and static
are used to declare constants, where const
is a constant determined at compile time, and static
is a global variable allocated at runtime.
Generate Questions Based on Specified Content#
work -type algorithm
GPT-4:
Here are two work-level Rust questions related to algorithms, one multiple-choice question and one coding implementation question.
Multiple-choice question:
- In Rust, which method is used for in-place sorting (i.e., without creating a new vector) for sorting algorithms?
A. sort B. sorted C. sort_by D. sort_unstable
Coding implementation question: 2. Please write a Rust function merge_sorted_arrays
that takes two sorted integer vectors as parameters and merges them into a new sorted vector. The example function signature is as follows:
fn merge_sorted_arrays(a: Vec<i32>, b: Vec<i32>) -> Vec<i32> {
// Write your code here
}
To prevent GPT-4 from generating the same questions, you can ask it to change the questions:
work -type trait change
Change the main command to expert
expert -type trait
GPT-4:
Here are two professional-level Rust questions related to traits, one multiple-choice question and one coding implementation question.
Multiple-choice question:
- In Rust, regarding trait objects and static dispatch, which statement is correct?
A. Trait objects implement static dispatch, which performs better than dynamic dispatch B. Static dispatch uses trait objects, which performs better than dynamic dispatch C. Static dispatch uses monomorphization, determining specific types at compile time, which performs better than dynamic dispatch D. Dynamic dispatch uses monomorphization, determining specific types at compile time, which performs better than static dispatch
Coding implementation question: 2. Please implement a trait named Drawable
that includes a method named draw
. Then, implement the Drawable
trait for the Circle
and Rectangle
structs. Finally, create a vector containing Circle
and Rectangle
, and iterate through them by calling the draw
method. The example code structure is as follows:
trait Drawable {
// Write your code here
}
struct Circle {
// Write your code here
}
struct Rectangle {
// Write your code here
}
// Implement Drawable trait for Circle and Rectangle here
fn main() {
// Create a Drawable vector here and iterate through it by calling the draw method
}
Specify to only output “coding implementation” questions:
work -n 1 -type ffi coding implementation
Here is a work-level Rust question related to FFI (Foreign Function Interface), providing you with a coding implementation question along with the answer and explanation.
Coding implementation question:
- Please use Rust's FFI feature to write a function named
rust_add
that adds two C languageint
type integers and returns the result. Please provide the corresponding C language function declaration for this function. The example code structure is as follows:
// Write your Rust code here
/*
// Provide C language function declaration here
extern "C" {
// ...
}
*/
fn main() {
// Write test code here
}
Answer:
// Rust code
#[no_mangle]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
a + b
}
/*
// C language function declaration
#include <stdint.h>
extern int32_t rust_add(int32_t a, int32_t b);
*/
fn main() {
// This cannot be tested directly; it needs to be compiled and called in a C language environment
}
Explanation: First, we define a function named rust_add
in Rust that takes two i32
type parameters and returns their sum. To allow C language to call this function, we need to use the #[no_mangle]
attribute to prevent the compiler from rewriting the function name. Then, we use the pub extern "C"
keyword to specify the ABI (Application Binary Interface) of this function in C language style.
Next, we provide the C language function declaration. Note that the int
type in C language may have different sizes on different platforms and compilers, so we use the int32_t
type in C language to ensure it matches the i32
type in Rust. This requires including the stdint.h
header file.
In the main
function, we cannot directly test this FFI function because it needs to be compiled and called in a C language environment. You can create a simple C language program, compile Rust into a dynamic or static library, link it to the C language program, and then call the rust_add
function for testing.
I’m not sure why it sometimes requires explanations and answers.
Recommended Practice Projects#
work -idea
GPT-4:
Here are some work-level project practice ideas and thoughts for your reference in Rust:
-
Command-line tool: Create a command-line tool for handling daily tasks, such as batch renaming files, downloading web resources, or parsing log files. You can use the
clap
orstructopt
library to handle command-line arguments. -
Web server: Write a simple multi-threaded web server in Rust to handle HTTP requests and provide static or dynamic content. You can use the
hyper
andtokio
libraries to implement asynchronous I/O and HTTP functionality. -
Web crawler: Write a web crawler that fetches content from specified websites and parses the required information. You can use the
reqwest
library to handle network requests and theselect.rs
library to parse HTML documents. -
Chat server and client: Create a chat server and client that allows multiple users to communicate in real-time via TCP connections. You can use the
tokio
library to implement asynchronous I/O and multi-threading functionality. -
File encryption tool: Implement a simple file encryption and decryption tool to protect users' private data. You can use the
rust-crypto
orring
library to implement encryption algorithms. -
Text editor: Develop a simple text editor that supports basic text editing functions such as opening, saving, finding, and replacing. You can use the
crossterm
ortermion
library to implement a cross-platform terminal interface.
You can specify the idea keyword:
work -idea cli gpt
GPT-4:
Here is a project practice idea and thought for creating a command-line interface (CLI) GPT tool developed in Rust for your reference:
Project Name: GPT-CLI
Project Overview: Create a command-line interface (CLI) tool that allows users to interact with the GPT model by inputting text and receiving generated text from the model. This tool can be used for various purposes, such as writing assistance, programming problem-solving, automatic email replies, etc.
Key Features:
- Text input: Allow users to input text to be used as input for the GPT model.
- GPT model integration: Integrate a GPT model (e.g., OpenAI's GPT-3 or a self-trained model) and call its API to generate text based on user input.
- Result display: Display the text results generated by the GPT model to the user.
- Save functionality: Allow users to save the generated text results to a specified file.
Library and Tool Suggestions:
- Command-line argument handling: Use the
clap
orstructopt
library to handle command-line arguments. - HTTP request library: Use the
reqwest
library to handle network requests to the GPT model API. - Asynchronous programming: Use the
tokio
orasync-std
library to implement asynchronous programming for improved performance. - Environment variable management: Use the
dotenv
library to manage sensitive information like API keys.
Development Steps:
- Design the command-line argument structure, such as input text and save file path.
- Use the
clap
orstructopt
library to parse command-line arguments. - Integrate the GPT model API, such as OpenAI GPT-3, setting up API keys and request parameters.
- Use the
reqwest
library to send HTTP requests and obtain the text results generated by the GPT model. - Process the results returned by the GPT model and display them to the user.
- Implement the functionality to save the generated text to a file.
- Test and optimize the program.
Answering Self-Generated Questions#
expert -type struct
GPT-4:
Here are two professional-level Rust questions related to structs, one multiple-choice question and one coding implementation question.
Multiple-choice question:
- In Rust, regarding the derivation of
PartialEq
andEq
traits for structs, which statement is correct?
A. All structs must implement PartialEq
and Eq
traits B. Structs only need to implement PartialEq
trait, and Eq
trait will be derived automatically C. Structs can choose to derive PartialEq
and Eq
traits, but only if all their fields implement these traits D. When deriving PartialEq
and Eq
traits for structs, there is no need to consider the traits implemented by their fields
Coding implementation question: 2. Please create a struct named Color
that contains three u8
type fields: red
, green
, and blue
. Implement the PartialEq
trait for the Color
struct to compare whether two Color
instances are equal. Two Color
instances are considered equal if the difference in their red
, green
, and blue
field values is less than or equal to 10. The example code structure is as follows:
use std::cmp::PartialEq;
struct Color {
// Write your code here
}
impl PartialEq for Color {
// Write your code here
}
fn main() {
// Create two Color instances here and compare whether they are equal
}
answer -n 2
According to your request, I will provide you with the answers and explanations for the first two questions.
Multiple-choice question answer and explanation:
- In Rust, regarding the derivation of
PartialEq
andEq
traits for structs, which statement is correct?
Answer: C. Structs can choose to derive PartialEq
and Eq
traits, but only if all their fields implement these traits.
Explanation: In Rust, structs can selectively derive PartialEq
and Eq
traits, allowing you to compare instances of structs for equality. However, the prerequisite for deriving these traits is that all fields of the struct have already implemented these traits. If any field of the struct does not implement these traits, you will not be able to derive PartialEq
and Eq
traits for that struct.
Coding implementation question answer and explanation: 2. Please create a struct named Color
that contains three u8
type fields: red
, green
, and blue
. Implement the PartialEq
trait for the Color
struct to compare whether two Color
instances are equal. Two Color
instances are considered equal if the difference in their red
, green
, and blue
field values is less than or equal to 10. The example code structure is as follows:
Answer:
use std::cmp::PartialEq;
struct Color {
red: u8,
green: u8,
blue: u8,
}
impl PartialEq for Color {
fn eq(&self, other: &Self) -> bool {
(self.red as i32 - other.red as i32).abs() <= 10 &&
(self.green as i32 - other.green as i32).abs() <= 10 &&
(self.blue as i32 - other.blue as i32).abs() <= 10
}
}
fn main() {
let color1 = Color { red: 255, green: 128, blue: 64 };
let color2 = Color { red: 250, green: 130, blue: 70 };
println!("Color1 equals Color2: {}", color1 == color2);
}
Explanation: First, we define the Color
struct and add three u8
type fields: red
, green
, and blue
. Next, we implement the PartialEq
trait for the Color
struct and define the eq
method. In the eq
method, we compare the absolute differences of the red
, green
, and blue
field values of the two Color
instances to see if they are less than or equal to 10. If the condition is met, the two Color
instances are considered equal. Finally, in the main
function, we create two Color
instances and use the ==
operator to compare whether they are equal.
Recommended Crate#
expert -crate eBPF
GPT-4:
Sure, here are the professional-level questions related to the eBPF
topic and the recommended third-party crates:
Questions:
- Please provide a detailed introduction to the principles and application scenarios of eBPF technology in Rust.
- In Rust, how to use the
libbpf-rs
crate to write efficient eBPF programs? - In Rust, how to use the
redbpf-probes
crate to implement custom eBPF event probes?
Recommended third-party crates:
libbpf-rs
: A Rust crate for writing and loading eBPF programs.redbpf-probes
: A Rust crate for writing custom eBPF event probes.
Note: The eBPF technology needs to run on a kernel that supports it. If your system does not support eBPF, you may not be able to complete this task.
Specifying the Natural Language of Output Content#
Request it to output in Japanese:
work -tech lifetime --jp
GPT-4:
以下は、ライフタイムに関連する技術概念の説明と例を日本語で提供します。
ライフタイムとは、Rust でメモリ管理や参照の安全性を担保するための概念です。ライフタイムは、コンパイル時に参照の有効性を検証し、参照されるオブジェクトが参照されている期間中に破棄されないことを保証します。
例:
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s1.len() > s2.len() {
s1
} else {
s2
}
}
fn main() {
let s1 = String::from("長い文字列");
let s2 = String::from("短い");
let result = longest(&s1, &s2);
println!("最も長い文字列は: {}", result);
}
上記の例では、longest
関数は 2 つの文字列のスライスを引数に取り、最も長いものを返します。ライフタイムパラメータ'a
は、入力参照と戻り値の参照が同じライフタイムを持つことを示しています。
longest
関数は、参照されるオブジェクトが参照されている期間中に破棄されないことを保証するために、ライフタイムを使用しています。これにより、ダングリングポインタや他のメモリ安全性に関連する問題を防止できます。
Request it to output in English:
work -tech --en lifetime
Below is an explanation and example of the technical concept of lifetimes in Rust, provided in English.
Lifetimes are a concept in Rust for managing memory and ensuring reference safety. Lifetimes are used to verify the validity of references at compile-time, ensuring that the object being referenced is not destroyed while it is still being referenced.
Example:
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s1.len() > s2.len() {
s1
} else {
s2
}
}
fn main() {
let s1 = String::from("long string");
let s2 = String::from("short");
let result = longest(&s1, &s2);
println!("The longest string is: {}", result);
}
In the example above, the longest
function takes two string slices as arguments and returns the longer one. The lifetime parameter 'a
indicates that the input references and the returned reference have the same lifetime.
The longest
function uses lifetimes to ensure that the object being referenced is not destroyed while it is still being referenced, preventing dangling pointers and other memory safety-related issues.
Conclusion#
Setting up this “magic” learning system is not difficult, but it should greatly help with daily Rust learning. Finally, I hope everyone can share their useful commands that you have expanded or noteworthy GPT-4 generated Rust questions and answers in the RustChat GitHub repository, forming a Q&A knowledge base to help more Rust learners.
Thank you for reading.