AlexZhang

AlexZhang

Create the most powerful Rust learning assistance "magic" system with ChatGPT

WechatIMG466

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:

  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.

Next, I will introduce primary commands, which can be combined with the main command in any way:

  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, limited to the main command work, representing recommending corresponding third-party crates for the specified content.
  5. -n, indicating a primary command, limited to the main command answer, representing the number of questions to be answered.

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.

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 CommandFunction
explainProvide a detailed explanation of the specified Rust code
debugHelp find code bugs and provide corrected code based on the given compiler error messages
workOutput questions covering common features and knowledge points for Rust beginners and daily coding
expertOutput questions covering expert-level features and knowledge points in Rust
quizOutput questions that specifically test confusing features of the Rust language
answerSpecify the number of questions to be answered, along with explanations for the answers
Primary CommandFunction
-techOutput a corresponding main command level conceptual explanation, along with examples
-typeOutput corresponding main command level questions
-ideaOutput corresponding main command level project practice ideas and thoughts for reference
-crateLimited to the main command work, recommend corresponding third-party crates
-nLimited to the main command answer, specify the number of questions to be answered, along with explanations
Secondary CommandFunction
--cnOutput content in Chinese
--enOutput content in English
--jpOutput 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:

  1. 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:

  1. 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:

  1. 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:

  1. 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:

  1. Please use Rust's FFI feature to write a function named rust_add that adds two C language int 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.

work -idea

GPT-4:

Here are some work-level project practice ideas and thoughts for your reference in Rust:

  1. 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 or structopt library to handle command-line arguments.

  2. 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 and tokio libraries to implement asynchronous I/O and HTTP functionality.

  3. 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 the select.rs library to parse HTML documents.

  4. 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.

  5. File encryption tool: Implement a simple file encryption and decryption tool to protect users' private data. You can use the rust-crypto or ring library to implement encryption algorithms.

  6. 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 or termion 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:

  1. Text input: Allow users to input text to be used as input for the GPT model.
  2. 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.
  3. Result display: Display the text results generated by the GPT model to the user.
  4. Save functionality: Allow users to save the generated text results to a specified file.

Library and Tool Suggestions:

  1. Command-line argument handling: Use the clap or structopt library to handle command-line arguments.
  2. HTTP request library: Use the reqwest library to handle network requests to the GPT model API.
  3. Asynchronous programming: Use the tokio or async-std library to implement asynchronous programming for improved performance.
  4. Environment variable management: Use the dotenv library to manage sensitive information like API keys.

Development Steps:

  1. Design the command-line argument structure, such as input text and save file path.
  2. Use the clap or structopt library to parse command-line arguments.
  3. Integrate the GPT model API, such as OpenAI GPT-3, setting up API keys and request parameters.
  4. Use the reqwest library to send HTTP requests and obtain the text results generated by the GPT model.
  5. Process the results returned by the GPT model and display them to the user.
  6. Implement the functionality to save the generated text to a file.
  7. 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:

  1. In Rust, regarding the derivation of PartialEq and Eq 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:

  1. In Rust, regarding the derivation of PartialEq and Eq 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.

expert -crate eBPF

GPT-4:

Sure, here are the professional-level questions related to the eBPF topic and the recommended third-party crates:

Questions:

  1. Please provide a detailed introduction to the principles and application scenarios of eBPF technology in Rust.
  2. In Rust, how to use the libbpf-rs crate to write efficient eBPF programs?
  3. 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.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.