-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a8f37be
Showing
9 changed files
with
425 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/target |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "macrokata" | ||
version = "0.1.0" | ||
edition = "2021" | ||
default-run = "macrokata" | ||
|
||
[[bin]] | ||
name = "macrokata" | ||
path = "src/main.rs" | ||
|
||
[[bin]] | ||
name = "01" | ||
path = "exercises/01_my_first_macro/main.rs" | ||
|
||
[[bin]] | ||
name = "01_soln" | ||
path = "exercises/01_my_first_macro/solutions/main.rs" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
clap = { version = "4.0.17", features = ["derive"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# MacroKata | ||
|
||
MacroKata is a set of exercises which you can use to learn how | ||
to write macros in rust. Unlike most exercises, not only is your goal | ||
to produce the same output with your code as with the files | ||
in solution.rs; but it should *also* be to have your expanded code be the same | ||
as `result.rs`. | ||
|
||
You should complete the kata in order, as they increase in | ||
difficulty, and depend on previous kata. | ||
|
||
## Getting Started | ||
|
||
Clone this repository: | ||
|
||
``` sh | ||
$ git clone https://www.github.com/tfpk/macrokata/ | ||
``` | ||
|
||
You will also need to install the rust "nightly" toolchain, so that we can show | ||
expanded macros. | ||
|
||
``` sh | ||
$ rustup toolchain install nightly | ||
``` | ||
|
||
Build the main binary provided with this repo: | ||
|
||
``` sh | ||
$ cargo build | ||
``` | ||
|
||
You can find the first kata (`my_first_macro`) inside `tasks/01_my_first_macro`. | ||
Read the `README.md` file, and get started by editing the `main.rs` file. | ||
|
||
To test your code, run: | ||
|
||
``` sh | ||
$ cargo run 01_my_first_macro | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Exercise 1: My First Macro | ||
|
||
Welcome to this introduction to Rust's Macro system. | ||
To complete each exercise (including this one), you should: | ||
|
||
* [ ] Read the `README.md` file, to understand what your goal is. | ||
* [ ] Try and complete the `main.rs` file. | ||
* [ ] Run the binary in this file, `cargo run 01_my_first_macro`. | ||
* [ ] Get your code to compile, run, and have the main file look the same as `result.rs` | ||
|
||
|
||
## What are Macros? | ||
|
||
Rust's macros are a way of automatically generating code before the compiler compiles it. | ||
Because the generation happens before the compiler does anything; it doesn't | ||
care about types; and it can output any Rust code you'd like. | ||
|
||
This allows you to break some of the syntax rules rust imposes on you. For example, | ||
Rust does not allow "variadic" functions -- functions with variable numbers of | ||
arguments. This makes a `println` function impossible -- it can take any number | ||
of arguments (`println!("hello")` and `println("{}", 123)`, for example). | ||
|
||
Rust gets around this rule by using a `println!` macro. Before `println!` is compiled, | ||
Rust rewrites it so it takes a single array of arguments. That way, even though | ||
it looks to you like there are multiple arguments, once it's compiled there's always | ||
just one array. | ||
|
||
Macros can range from very simple -- reducing duplicated code; to very complex, implementing the | ||
whole of HTML inside of Rust. This guide aims to build you up from the simple to the complex. | ||
|
||
As you may have guessed, you've already used them -- `println!` for example, is a macro. | ||
`vec![]` is as well. In general, macros always have a name. To run a macro, call it's name | ||
with a bang (`!`) afterwards, and then brackets (any of `()`, `[]` or `{}`) containing | ||
arguments. | ||
|
||
In other words, to run the macro `my_macro`, you'd say `my_macro!()` or `my_macro![]` or `my_macro!{}`. | ||
|
||
## How do I create one? | ||
|
||
The simplest form of macro looks like this: | ||
|
||
``` rust | ||
macro_rules! my_macro { | ||
() => { | ||
my_code(); | ||
} | ||
} | ||
``` | ||
|
||
The `macro_rules!` instructs the compiler that there is a new macro you are defining. | ||
It is followed by the name of the macro, `my_macro`. | ||
The next line lets you specify variables for your macro, but for now we'll ignore it. | ||
Any code inside the curly brackets is what Rust will replace `my_macro!()` with. | ||
|
||
So, `my_macro!()` will be replaced by `my_code();` | ||
|
||
## See it for yourself | ||
|
||
You now know everything you need to in order to complete `01_my_first_macro`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
////////// DO NOT CHANGE BELOW HERE ///////// | ||
// This function should be called by the `show_output!()` macro | ||
fn show_output() { | ||
println!("I should appear as the output.") | ||
} | ||
////////// DO NOT CHANGE ABOVE HERE ///////// | ||
|
||
// TODO: create `show_output!()` macro. | ||
|
||
////////// DO NOT CHANGE BELOW HERE ///////// | ||
|
||
fn main() { | ||
show_output!() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fn main() { | ||
show_output() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// This function should be called by the `show_output!()` macro | ||
fn show_output() { | ||
println!("I should appear as the output.") | ||
} | ||
|
||
macro_rules! show_output { | ||
() => {show_output()} | ||
} | ||
|
||
fn main() { | ||
show_output!() | ||
} |
Oops, something went wrong.