move old files to a separate directory
This commit is contained in:
19
old_curriculum/.travis.yml
Normal file
19
old_curriculum/.travis.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
language: rust
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
cache:
|
||||
cargo: true
|
||||
|
||||
script:
|
||||
- cargo run --bin generate_readme
|
||||
- git config user.name "Carol (Nichols || Goulding)"
|
||||
- git config user.email "carol.nichols@gmail.com"
|
||||
- git commit -am "Regenerate README" && git remote add upstream "https://$GH_TOKEN@github.com/carols10cents/rustlings.git" && git push -q upstream HEAD:master > /dev/null 2>&1 || true
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
|
||||
456
old_curriculum/Cargo.lock
generated
Normal file
456
old_curriculum/Cargo.lock
generated
Normal file
@@ -0,0 +1,456 @@
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "encoding"
|
||||
version = "0.2.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-japanese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-korean"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-simpchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-singlebyte"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding-index-tradchinese"
|
||||
version = "1.20141219.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_index_tests"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "handlebars"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pest_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prlink"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/btbytes/prlink#f0536ed3b322072d65c42da2fc2a817b77d77308"
|
||||
dependencies = [
|
||||
"clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustlings"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"prlink 0.1.0 (git+https://github.com/btbytes/prlink)",
|
||||
"serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
|
||||
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
|
||||
"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
|
||||
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
|
||||
"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
|
||||
"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
|
||||
"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
|
||||
"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
|
||||
"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
|
||||
"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07af2ff31f66f39a5c8b8b8a5dc02734a453110146763e3a2323f4931a915a76"
|
||||
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
|
||||
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "56aebce561378d99a0bb578f8cb15b6114d2a1814a6c7949bbe646d968bb4fa9"
|
||||
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
|
||||
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
|
||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||
"checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
|
||||
"checksum pest_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6453faedc5c9980a3c278f28b1df33344a79cc6d4a2fd96e2b56288374dc822a"
|
||||
"checksum prlink 0.1.0 (git+https://github.com/btbytes/prlink)" = "<none>"
|
||||
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b"
|
||||
"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
|
||||
"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526"
|
||||
"checksum serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "57781ed845b8e742fc2bf306aba8e3b408fe8c366b900e3769fbc39f49eb8b39"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
|
||||
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
9
old_curriculum/Cargo.toml
Normal file
9
old_curriculum/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "rustlings"
|
||||
version = "0.1.0"
|
||||
authors = ["Carol (Nichols || Goulding) <carol.nichols@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
handlebars = "0.32.0"
|
||||
serde_json = "1.0.10"
|
||||
prlink = { git = "https://github.com/btbytes/prlink" }
|
||||
190
old_curriculum/README-template.hbs
Normal file
190
old_curriculum/README-template.hbs
Normal file
@@ -0,0 +1,190 @@
|
||||
<!--
|
||||
{{ autogenerated_notice }}
|
||||
-->
|
||||
|
||||
# rustlings
|
||||
|
||||
Small exercises to get you used to reading and writing Rust code. Includes practice reading and
|
||||
responding to compiler messages!
|
||||
|
||||
This repo is very much the smallest thing that could possibly work :)
|
||||
|
||||
## To do these exercises
|
||||
|
||||
Thanks to [btbytes'](https://twitter.com/btbytes) [prlinks](https://github.com/btbytes/prlink), you
|
||||
can now click on the links below to load the exercises in the rust playground!
|
||||
|
||||
There are infinite correct answers-- the exercises are sometimes left very open-ended. Scroll down
|
||||
in the playground to find comments that have hints.
|
||||
|
||||
If you need more help or would like to compare solutions, you can ask in [#rust-beginners on
|
||||
irc.mozilla.org](https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-beginners ), the
|
||||
[user forum](https://users.rust-lang.org/), or [the subreddit](https://reddit.com/r/rust). If an
|
||||
exercise could be improved in any way, please [create an
|
||||
issue](https://github.com/carols10cents/rustlings/issues/new) or submit a pull request!
|
||||
|
||||
### Variable bindings
|
||||
|
||||
[Relevant chapter in The Rust Programming
|
||||
Language](https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html)
|
||||
|
||||
{{ playground_link "variables/variables1.rs" }}
|
||||
{{ playground_link "variables/variables2.rs" }}
|
||||
{{ playground_link "variables/variables3.rs" }}
|
||||
{{ playground_link "variables/variables4.rs" }}
|
||||
|
||||
### Functions
|
||||
|
||||
[Relevant chapter in The Rust Programming
|
||||
Language](https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html)
|
||||
|
||||
{{ playground_link "functions/functions1.rs" }}
|
||||
{{ playground_link "functions/functions2.rs" }}
|
||||
{{ playground_link "functions/functions3.rs" }}
|
||||
{{ playground_link "functions/functions4.rs" }}
|
||||
{{ playground_link "functions/functions5.rs" }}
|
||||
|
||||
### Primitive types
|
||||
|
||||
[Relevant chapter in The Rust Programming
|
||||
Language](https://doc.rust-lang.org/book/second-edition/ch03-02-data-types.html)
|
||||
|
||||
{{ playground_link "primitive_types/primitive_types1.rs" }}
|
||||
{{ playground_link "primitive_types/primitive_types2.rs" }}
|
||||
{{ playground_link "primitive_types/primitive_types3.rs" }}
|
||||
{{ playground_link "primitive_types/primitive_types4.rs" }}
|
||||
{{ playground_link "primitive_types/primitive_types5.rs" }}
|
||||
{{ playground_link "primitive_types/primitive_types6.rs" }}
|
||||
|
||||
### Tests
|
||||
|
||||
Going out of order from the book to cover tests-- many of the following exercises will ask you to
|
||||
make tests pass!
|
||||
|
||||
[Relevant chapter in The Rust Programming
|
||||
Language](https://doc.rust-lang.org/book/second-edition/ch11-01-writing-tests.html)
|
||||
|
||||
{{ playground_link "tests/tests1.rs" }}
|
||||
{{ playground_link "tests/tests2.rs" }}
|
||||
{{ playground_link "tests/tests3.rs" }}
|
||||
{{ playground_link "tests/tests4.rs" }}
|
||||
|
||||
### If
|
||||
|
||||
[Relevant chapter in The Rust Programming
|
||||
Language](https://doc.rust-lang.org/book/second-edition/ch03-05-control-flow.html)
|
||||
|
||||
{{ playground_link "if/if1.rs" }}
|
||||
|
||||
### Strings
|
||||
|
||||
[Relevant chapter in The Rust Programming
|
||||
Language](https://doc.rust-lang.org/book/second-edition/ch08-02-strings.html)
|
||||
|
||||
{{ playground_link "strings/strings1.rs" }}
|
||||
{{ playground_link "strings/strings2.rs" }}
|
||||
{{ playground_link "strings/strings3.rs" }}
|
||||
|
||||
### Move semantics
|
||||
|
||||
These exercises are adapted from [pnkfelix]()'s [Rust
|
||||
Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- thank you Felix!!!
|
||||
|
||||
Relevant chapters in the book:
|
||||
|
||||
- [Ownership](https://doc.rust-lang.org/book/second-edition/ch04-01-what-is-ownership.html)
|
||||
- [References and borrowing](https://doc.rust-lang.org/book/second-edition/ch04-02-references-and-borrowing.html)
|
||||
|
||||
Note that the exercises in this section may look similar to each other but they are subtly
|
||||
different :)
|
||||
|
||||
{{ playground_link "move_semantics/move_semantics1.rs" }}
|
||||
{{ playground_link "move_semantics/move_semantics2.rs" }}
|
||||
{{ playground_link "move_semantics/move_semantics3.rs" }}
|
||||
{{ playground_link "move_semantics/move_semantics4.rs" }}
|
||||
|
||||
### Modules
|
||||
|
||||
[Relevant chapter in The Rust Programming
|
||||
Language](https://doc.rust-lang.org/book/second-edition/ch07-01-mod-and-the-filesystem.html)
|
||||
|
||||
{{ playground_link "modules/modules1.rs" }}
|
||||
{{ playground_link "modules/modules2.rs" }}
|
||||
|
||||
### Macros
|
||||
|
||||
Check out:
|
||||
|
||||
- [The Macros section of the first edition of the book
|
||||
book](https://doc.rust-lang.org/book/first-edition/macros.html)
|
||||
- [The Macros appendix of the second edition of the
|
||||
book](https://doc.rust-lang.org/book/second-edition/appendix-04-macros.html)
|
||||
- [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html)
|
||||
|
||||
{{ playground_link "macros/macros1.rs" }}
|
||||
{{ playground_link "macros/macros2.rs" }}
|
||||
{{ playground_link "macros/macros3.rs" }}
|
||||
{{ playground_link "macros/macros4.rs" }}
|
||||
|
||||
### Error Handling
|
||||
|
||||
The [Error
|
||||
Handling](https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html)
|
||||
and [Generics](https://doc.rust-lang.org/book/second-edition/ch10-01-syntax.html) sections are
|
||||
relevant.
|
||||
|
||||
{{ playground_link "error_handling/option1.rs" }}
|
||||
{{ playground_link "error_handling/result1.rs" }}
|
||||
{{ playground_link "error_handling/errors1.rs" }}
|
||||
{{ playground_link "error_handling/errors2.rs" }}
|
||||
{{ playground_link "error_handling/errors3.rs" }}
|
||||
{{ playground_link "error_handling/errorsn.rs" }}
|
||||
|
||||
### Standard library types
|
||||
|
||||
#### `Arc`
|
||||
|
||||
The [Concurrency](https://doc.rust-lang.org/book/second-edition/ch16-03-shared-state.html) section
|
||||
is relevant.
|
||||
|
||||
{{ playground_link "standard_library_types/arc1.rs" }}
|
||||
|
||||
#### Iterators
|
||||
|
||||
Do not adjust your monitors-- iterators 1 and 2 are indeed missing. Iterator 3 is a bit challenging
|
||||
so we're leaving space for some exercises to lead up to it!
|
||||
|
||||
Check out the [Iterators chapter of the
|
||||
book](https://doc.rust-lang.org/book/second-edition/ch13-02-iterators.html) and the [Iterator
|
||||
docs](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html).
|
||||
|
||||
{{ playground_link "standard_library_types/iterator3.rs" }}
|
||||
{{ playground_link "standard_library_types/iterators4.rs" }}
|
||||
|
||||
### Threads
|
||||
|
||||
See [the Dining Philosophers
|
||||
example](https://doc.rust-lang.org/1.4.0/book/first-edition/dining-philosophers.html) and the
|
||||
[Concurrency Chapter](https://doc.rust-lang.org/book/second-edition/ch16-01-threads.html) from the
|
||||
book.
|
||||
|
||||
{{ playground_link "threads/threads1.rs" }}
|
||||
|
||||
### Uncategorized
|
||||
|
||||
A few exercises based on things I've encountered or had trouble with getting used to.
|
||||
|
||||
{{ playground_link "ex1.rs" }}
|
||||
{{ playground_link "ex2.rs" }}
|
||||
{{ playground_link "ex3.rs" }}
|
||||
{{ playground_link "ex4.rs" }}
|
||||
{{ playground_link "ex5.rs" }}
|
||||
|
||||
## To help with this repo/TODO list
|
||||
|
||||
* File issues for problems or suggestions!
|
||||
* Contribute more exercises! Anything that took you time to get used to, or that you had trouble
|
||||
with, or that deserves practice would be a good exercise!
|
||||
* How could the process of doing these exercises work better? This is an open-ended question :) Are
|
||||
the playground links good enough? Are there ways that we could make going to the next exercise
|
||||
easier without forking the playground??
|
||||
73
old_curriculum/error_handling/errors1.rs
Normal file
73
old_curriculum/error_handling/errors1.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
// errors1.rs
|
||||
// This function refuses to generate text to be printed on a nametag if
|
||||
// you pass it an empty string. It'd be nicer if it explained what the problem
|
||||
// was, instead of just sometimes returning `None`. The 2nd test currently
|
||||
// does not compile or pass, but it illustrates the behavior we would like
|
||||
// this function to have.
|
||||
// Scroll down for hints!!!
|
||||
|
||||
pub fn generate_nametag_text(name: String) -> Option<String> {
|
||||
if name.len() > 0 {
|
||||
Some(format!("Hi! My name is {}", name))
|
||||
} else {
|
||||
// Empty names aren't allowed.
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// This test passes initially if you comment out the 2nd test.
|
||||
// You'll need to update what this test expects when you change
|
||||
// the function under test!
|
||||
#[test]
|
||||
fn generates_nametag_text_for_a_nonempty_name() {
|
||||
assert_eq!(
|
||||
generate_nametag_text("Beyoncé".into()),
|
||||
Some("Hi! My name is Beyoncé".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explains_why_generating_nametag_text_fails() {
|
||||
assert_eq!(
|
||||
generate_nametag_text("".into()),
|
||||
Err("`name` was empty; it must be nonempty.".into())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// `Err` is one of the variants of `Result`, so what the 2nd test is saying
|
||||
// is that `generate_nametag_text` should return a `Result` instead of an
|
||||
// `Option`.
|
||||
|
||||
// To make this change, you'll need to:
|
||||
// - update the return type in the function signature to be a Result that
|
||||
// could be the variants `Ok(String)` and `Err(String)`
|
||||
// - change the body of the function to return `Ok(stuff)` where it currently
|
||||
// returns `Some(stuff)`
|
||||
// - change the body of the function to return `Err(error message)` where it
|
||||
// currently returns `None`
|
||||
// - change the first test to expect `Ok(stuff)` where it currently expects
|
||||
// `Some(stuff)`.
|
||||
72
old_curriculum/error_handling/errors2.rs
Normal file
72
old_curriculum/error_handling/errors2.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
// errors2.rs
|
||||
// Say we're writing a game where you can buy items with tokens. All items cost
|
||||
// 5 tokens, and whenever you purchase items there is a processing fee of 1
|
||||
// token. A player of the game will type in how many items they want to buy,
|
||||
// and the `total_cost` function will calculate the total number of tokens.
|
||||
// Since the player typed in the quantity, though, we get it as a string-- and
|
||||
// they might have typed anything, not just numbers!
|
||||
|
||||
// Right now, this function isn't handling the error case at all (and isn't
|
||||
// handling the success case properly either). What we want to do is:
|
||||
// if we call the `parse` function on a string that is not a number, that
|
||||
// function will return a `ParseIntError`, and in that case, we want to
|
||||
// immediately return that error from our function and not try to multiply
|
||||
// and add.
|
||||
|
||||
// There are at least two ways to implement this that are both correct-- but
|
||||
// one is a lot shorter! Scroll down for hints to both ways.
|
||||
|
||||
use std::num::ParseIntError;
|
||||
|
||||
pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
|
||||
let processing_fee = 1;
|
||||
let cost_per_item = 5;
|
||||
let qty = item_quantity.parse::<i32>();
|
||||
|
||||
Ok(qty * cost_per_item + processing_fee)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn item_quantity_is_a_valid_number() {
|
||||
assert_eq!(
|
||||
total_cost("34"),
|
||||
Ok(171)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn item_quantity_is_an_invalid_number() {
|
||||
assert_eq!(
|
||||
total_cost("beep boop").unwrap_err().to_string(),
|
||||
"invalid digit found in string"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// One way to handle this is using a `match` statement on
|
||||
// `item_quantity.parse::<i32>()` where the cases are `Ok(something)` and
|
||||
// `Err(something)`. This pattern is very common in Rust, though, so there's
|
||||
// a `try!` macro that does pretty much what you would make that match statement
|
||||
// do for you! Take a look at this section of the Error Handling chapter:
|
||||
// https://doc.rust-lang.org/stable/book/error-handling.html#the-try-macro
|
||||
// and give it a `try!`
|
||||
67
old_curriculum/error_handling/errors3.rs
Normal file
67
old_curriculum/error_handling/errors3.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
// errors3.rs
|
||||
// This is a program that is trying to use a completed version of the
|
||||
// `total_cost` function from the previous exercise. It's not working though--
|
||||
// we can't call the `try!` macro in the `main()` function! Why not?
|
||||
// What should we do instead? Scroll for hints!
|
||||
|
||||
use std::num::ParseIntError;
|
||||
|
||||
fn main() {
|
||||
let mut tokens = 100;
|
||||
let pretend_user_input = "8";
|
||||
|
||||
let cost = try!(total_cost(pretend_user_input));
|
||||
|
||||
if cost > tokens {
|
||||
println!("You can't afford that many!");
|
||||
} else {
|
||||
tokens -= cost;
|
||||
println!("You now have {} tokens.", tokens);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
|
||||
let processing_fee = 1;
|
||||
let cost_per_item = 5;
|
||||
let qty = try!(item_quantity.parse::<i32>());
|
||||
|
||||
Ok(qty * cost_per_item + processing_fee)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Since the `try!` macro returns an `Err` early if the thing it's trying to
|
||||
// do fails, you can only use the `try!` macro in functions that have a
|
||||
// `Result` as their return type.
|
||||
|
||||
// The error that you get if you run this code is:
|
||||
|
||||
// ```
|
||||
// error: mismatched types:
|
||||
// expected `()`,
|
||||
// found `std::result::Result<_, _>`
|
||||
// ```
|
||||
|
||||
// which is saying that the expected return type of the `main` function is
|
||||
// the empty tuple, but we tried to return a `Result`-- and that's happening
|
||||
// in the implementation of `try!`. The `main` function never has a return type,
|
||||
// so we have to use another way of handling a `Result` within `main`.
|
||||
|
||||
// Decide what we should do if `pretend_user_input` has a string value that does
|
||||
// not parse to an integer, and implement that instead of calling the `try!`
|
||||
// macro.
|
||||
138
old_curriculum/error_handling/errorsn.rs
Normal file
138
old_curriculum/error_handling/errorsn.rs
Normal file
@@ -0,0 +1,138 @@
|
||||
// errorsn.rs
|
||||
// This is a bigger error exercise than the previous ones!
|
||||
// You can do it! :)
|
||||
//
|
||||
// Edit the `read_and_validate` function so that it compiles and
|
||||
// passes the tests... so many things could go wrong!
|
||||
//
|
||||
// - Reading from stdin could produce an io::Error
|
||||
// - Parsing the input could produce a num::ParseIntError
|
||||
// - Validating the input could produce a CreationError (defined below)
|
||||
//
|
||||
// How can we lump these errors into one general error? That is, what
|
||||
// type goes where the question marks are, and how do we return
|
||||
// that type from the body of read_and_validate?
|
||||
//
|
||||
// Scroll down for hints :)
|
||||
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
// PositiveNonzeroInteger is a struct defined below the tests.
|
||||
fn read_and_validate(b: &mut io::BufRead) -> Result<PositiveNonzeroInteger, ???> {
|
||||
let mut line = String::new();
|
||||
b.read_line(&mut line);
|
||||
let num: i64 = line.trim().parse();
|
||||
let answer = PositiveNonzeroInteger::new(num);
|
||||
answer
|
||||
}
|
||||
|
||||
// This is a test helper function that turns a &str into a BufReader.
|
||||
fn test_with_str(s: &str) -> Result<PositiveNonzeroInteger, Box<error::Error>> {
|
||||
let mut b = io::BufReader::new(s.as_bytes());
|
||||
read_and_validate(&mut b)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_success() {
|
||||
let x = test_with_str("42\n");
|
||||
assert_eq!(PositiveNonzeroInteger(42), x.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_num() {
|
||||
let x = test_with_str("eleven billion\n");
|
||||
assert!(x.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_non_positive() {
|
||||
let x = test_with_str("-40\n");
|
||||
assert!(x.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ioerror() {
|
||||
struct Broken;
|
||||
impl io::Read for Broken {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Err(io::Error::new(io::ErrorKind::BrokenPipe, "uh-oh!"))
|
||||
}
|
||||
}
|
||||
let mut b = io::BufReader::new(Broken);
|
||||
assert!(read_and_validate(&mut b).is_err());
|
||||
assert_eq!("uh-oh!", read_and_validate(&mut b).unwrap_err().to_string());
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Debug)]
|
||||
struct PositiveNonzeroInteger(u64);
|
||||
|
||||
impl PositiveNonzeroInteger {
|
||||
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
|
||||
if value == 0 {
|
||||
Err(CreationError::Zero)
|
||||
} else if value < 0 {
|
||||
Err(CreationError::Negative)
|
||||
} else {
|
||||
Ok(PositiveNonzeroInteger(value as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_positive_nonzero_integer_creation() {
|
||||
assert!(PositiveNonzeroInteger::new(10).is_ok());
|
||||
assert_eq!(Err(CreationError::Negative), PositiveNonzeroInteger::new(-10));
|
||||
assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Debug)]
|
||||
enum CreationError {
|
||||
Negative,
|
||||
Zero,
|
||||
}
|
||||
|
||||
impl fmt::Display for CreationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str((self as &error::Error).description())
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for CreationError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
CreationError::Negative => "Negative",
|
||||
CreationError::Zero => "Zero",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// First hint: To figure out what type should go where the ??? is, take a look
|
||||
// at the test helper function `test_with_str`, since it returns whatever
|
||||
// `read_and_validate` returns and`test_with_str` has its signature fully
|
||||
// specified.
|
||||
|
||||
// Next hint: There are three places in `read_and_validate` that we call a
|
||||
// function that returns a `Result` (that is, the functions might fail).
|
||||
// Wrap those calls in a `try!` macro call so that we return immediately from
|
||||
// `read_and_validate` if those function calls fail.
|
||||
|
||||
// Another hint: under the hood, the `try!` macro calls `From::from`
|
||||
// on the error value to convert it to a boxed trait object, a Box<error::Error>,
|
||||
// which is polymorphic-- that means that lots of different kinds of errors
|
||||
// can be returned from the same function because all errors act the same
|
||||
// since they all implement the `error::Error` trait.
|
||||
// Check out this section of the book:
|
||||
// https://doc.rust-lang.org/stable/book/error-handling.html#standard-library-traits-used-for-error-handling
|
||||
|
||||
// Another another hint: Note that because the `try!` macro returns
|
||||
// the *unwrapped* value in the `Ok` case, if we want to return a `Result` from
|
||||
// `read_and_validate` for *its* success case, we'll have to rewrap a value
|
||||
// that we got from the return value of a `try!` call in an `Ok`-- this will
|
||||
// look like `Ok(something)`.
|
||||
|
||||
// Another another another hint: `Result`s must be "used", that is, you'll
|
||||
// get a warning if you don't handle a `Result` that you get in your
|
||||
// function. Read more about that in the `std::result` module docs:
|
||||
// https://doc.rust-lang.org/std/result/#results-must-be-used
|
||||
45
old_curriculum/error_handling/option1.rs
Normal file
45
old_curriculum/error_handling/option1.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
// option1.rs
|
||||
// This example panics because the second time it calls `pop`, the `vec`
|
||||
// is empty, so `pop` returns `None`, and `unwrap` panics if it's called
|
||||
// on `None`. Handle this in a more graceful way than calling `unwrap`!
|
||||
// Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
let mut list = vec![3];
|
||||
|
||||
let last = list.pop().unwrap();
|
||||
println!("The last item in the list is {:?}", last);
|
||||
|
||||
let second_to_last = list.pop().unwrap();
|
||||
println!("The second-to-last item in the list is {:?}", second_to_last);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Try using a `match` statement where the arms are `Some(thing)` and `None`.
|
||||
// Or set a default value to print out if you get `None` by using the
|
||||
// function `unwrap_or`.
|
||||
// Or use an `if let` statement on the result of `pop()` to both destructure
|
||||
// a `Some` value and only print out something if we have a value!
|
||||
43
old_curriculum/error_handling/result1.rs
Normal file
43
old_curriculum/error_handling/result1.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
// result1.rs
|
||||
// Make this test pass! Scroll down for hints :)
|
||||
|
||||
#[derive(PartialEq,Debug)]
|
||||
struct PositiveNonzeroInteger(u64);
|
||||
|
||||
#[derive(PartialEq,Debug)]
|
||||
enum CreationError {
|
||||
Negative,
|
||||
Zero,
|
||||
}
|
||||
|
||||
impl PositiveNonzeroInteger {
|
||||
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
|
||||
Ok(PositiveNonzeroInteger(value as u64))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_creation() {
|
||||
assert!(PositiveNonzeroInteger::new(10).is_ok());
|
||||
assert_eq!(Err(CreationError::Negative), PositiveNonzeroInteger::new(-10));
|
||||
assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// `PositiveNonzeroInteger::new` is always creating a new instance and returning an `Ok` result.
|
||||
// It should be doing some checking, returning an `Err` result if those checks fail, and only
|
||||
// returning an `Ok` result if those checks determine that everything is... okay :)
|
||||
6
old_curriculum/ex1.rs
Normal file
6
old_curriculum/ex1.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
// ex1.rs
|
||||
// Make me compile! :)
|
||||
|
||||
fn main() {
|
||||
println();
|
||||
}
|
||||
10
old_curriculum/ex2.rs
Normal file
10
old_curriculum/ex2.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
// ex2.rs
|
||||
// Make me compile!
|
||||
|
||||
fn something() -> String {
|
||||
"hi!"
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", something());
|
||||
}
|
||||
10
old_curriculum/ex3.rs
Normal file
10
old_curriculum/ex3.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
// ex3.rs
|
||||
// Make me compile!
|
||||
|
||||
struct Foo {
|
||||
capacity: i32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", Foo { capacity: 3 });
|
||||
}
|
||||
14
old_curriculum/ex4.rs
Normal file
14
old_curriculum/ex4.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
// ex4.rs
|
||||
// Make me compile!
|
||||
|
||||
fn something() -> Result<i32, std::num::ParseIntError> {
|
||||
let x:i32 = "3".parse();
|
||||
Ok(x * 4)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match something() {
|
||||
Ok(..) => println!("You win!"),
|
||||
Err(e) => println!("Oh no something went wrong: {}", e),
|
||||
}
|
||||
}
|
||||
22
old_curriculum/ex5.rs
Normal file
22
old_curriculum/ex5.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
// ex5.rs
|
||||
// Make me compile!
|
||||
|
||||
enum Reaction<'a> {
|
||||
Sad(&'a str),
|
||||
Happy(&'a str),
|
||||
}
|
||||
|
||||
fn express(sentiment: Reaction) {
|
||||
match sentiment {
|
||||
Reaction::Sad(s) => println!(":( {}", s),
|
||||
Reaction::Happy(s) => println!(":) {}", s),
|
||||
}
|
||||
}
|
||||
|
||||
fn main () {
|
||||
let x = Reaction::Happy("It's a great day for Rust!");
|
||||
express(x);
|
||||
express(x);
|
||||
let y = Reaction::Sad("This code doesn't compile yet.");
|
||||
express(y);
|
||||
}
|
||||
44
old_curriculum/functions/functions1.rs
Normal file
44
old_curriculum/functions/functions1.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
// functions1.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
call_me();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// This main function is calling a function that it expects to exist, but the
|
||||
// function doesn't exist. It expects this function to have the name `call_me`.
|
||||
// It expects this function to not take any arguments and not return a value.
|
||||
// Sounds a lot like `main`, doesn't it?
|
||||
42
old_curriculum/functions/functions2.rs
Normal file
42
old_curriculum/functions/functions2.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
// functions2.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
call_me(3);
|
||||
}
|
||||
|
||||
fn call_me(num) {
|
||||
for i in 0..num {
|
||||
println!("Ring! Call number {}", i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Rust requires that all parts of a function's signature have type annotations,
|
||||
// but `call_me` is missing the type annotation of `num`.
|
||||
42
old_curriculum/functions/functions3.rs
Normal file
42
old_curriculum/functions/functions3.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
// functions3.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
call_me();
|
||||
}
|
||||
|
||||
fn call_me(num: i32) {
|
||||
for i in 0..num {
|
||||
println!("Ring! Call number {}", i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// This time, the function *declaration* is okay, but there's something wrong
|
||||
// with the place where we're calling the function.
|
||||
44
old_curriculum/functions/functions4.rs
Normal file
44
old_curriculum/functions/functions4.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
// functions4.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
// This store is having a sale where if the price is an even number, you get
|
||||
// 10 (money unit) off, but if it's an odd number, it's 3 (money unit) less.
|
||||
|
||||
fn main() {
|
||||
let original_price = 51;
|
||||
println!("Your sale price is {}", sale_price(original_price));
|
||||
}
|
||||
|
||||
fn sale_price(price: i32) -> {
|
||||
if is_even(price) {
|
||||
price - 10
|
||||
} else {
|
||||
price - 3
|
||||
}
|
||||
}
|
||||
|
||||
fn is_even(num: i32) -> bool {
|
||||
num % 2 == 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The error message points to line 12 and says it expects a type after the
|
||||
// `->`. This is where the function's return type should be-- take a look at
|
||||
// the `is_even` function for an example!
|
||||
44
old_curriculum/functions/functions5.rs
Normal file
44
old_curriculum/functions/functions5.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
// functions5.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
let answer = square(3);
|
||||
println!("The answer is {}", answer);
|
||||
}
|
||||
|
||||
fn square(num: i32) -> i32 {
|
||||
num * num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// This is a really common error that can be fixed by removing one character.
|
||||
// It happens because Rust distinguishes between expressions and statements: expressions return
|
||||
// a value and statements don't. We want to return a value from the `square` function, but it
|
||||
// isn't returning one right now...
|
||||
58
old_curriculum/if/if1.rs
Normal file
58
old_curriculum/if/if1.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
// if1.rs
|
||||
|
||||
pub fn bigger(a: i32, b:i32) -> i32 {
|
||||
// Complete this function to return the bigger number!
|
||||
// Do not use:
|
||||
// - return
|
||||
// - another function call
|
||||
// - additional variables
|
||||
// Scroll down for hints.
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn ten_is_bigger_than_eight() {
|
||||
assert_eq!(10, bigger(10, 8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fortytwo_is_bigger_than_thirtytwo() {
|
||||
assert_eq!(42, bigger(32, 42));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// It's possible to do this in one line if you would like!
|
||||
// Some similar examples from other languages:
|
||||
// - In C(++) this would be: `a > b ? a : b`
|
||||
// - In Python this would be: `a if a > b else b`
|
||||
// Remember in Rust that:
|
||||
// - the `if` condition does not need to be surrounded by parentheses
|
||||
// - `if`/`else` conditionals are expressions
|
||||
// - Each condition is followed by a `{}` block.
|
||||
64
old_curriculum/macros/macros1.rs
Normal file
64
old_curriculum/macros/macros1.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
// macros1.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
macro_rules! my_macro {
|
||||
() => {
|
||||
println!("Check out my macro!");
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
my_macro();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// When you call a macro, you need to add something special compared to a
|
||||
// regular function call. If you're stuck, take a look at what's inside
|
||||
// `my_macro`.
|
||||
73
old_curriculum/macros/macros2.rs
Normal file
73
old_curriculum/macros/macros2.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
// macros2.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
my_macro!();
|
||||
}
|
||||
|
||||
macro_rules! my_macro {
|
||||
() => {
|
||||
println!("Check out my macro!");
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Macros don't quite play by the same rules as the rest of Rust, in terms of
|
||||
// what's available where.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Unlike other things in Rust, the order of "where you define a macro" versus
|
||||
// "where you use it" actually matters.
|
||||
75
old_curriculum/macros/macros3.rs
Normal file
75
old_curriculum/macros/macros3.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
// macros3.rs
|
||||
// Make me compile, without taking the macro out of the module! Scroll down for hints :)
|
||||
|
||||
mod macros {
|
||||
macro_rules! my_macro {
|
||||
() => {
|
||||
println!("Check out my macro!");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
my_macro!();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// In order to use a macro outside of its module, you need to do something
|
||||
// special to the module to lift the macro out into its parent.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The same trick also works on "extern crate" statements for crates that have
|
||||
// exported macros, if you've seen any of those around.
|
||||
77
old_curriculum/macros/macros4.rs
Normal file
77
old_curriculum/macros/macros4.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
// macros4.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
macro_rules! my_macro {
|
||||
() => {
|
||||
println!("Check out my macro!");
|
||||
}
|
||||
($val:expr) => {
|
||||
println!("Look at this other macro: {}", $val);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
my_macro!();
|
||||
my_macro!(7777);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// You only need to add a single character to make this compile.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The way macros are written, it wants to see something between each
|
||||
// "macro arm", so it can separate them.
|
||||
43
old_curriculum/modules/modules1.rs
Normal file
43
old_curriculum/modules/modules1.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
// modules1.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
mod sausage_factory {
|
||||
fn make_sausage() {
|
||||
println!("sausage!");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
sausage_factory::make_sausage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Everything is private in Rust by default-- but there's a keyword we can use
|
||||
// to make something public! The compiler error should point to the thing that
|
||||
// needs to be public.
|
||||
45
old_curriculum/modules/modules2.rs
Normal file
45
old_curriculum/modules/modules2.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
// modules2.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
mod us_presidential_frontrunners {
|
||||
use self::democrats::HILLARY_CLINTON as democrat;
|
||||
use self::republicans::DONALD_TRUMP as republican;
|
||||
|
||||
mod democrats {
|
||||
pub const HILLARY_CLINTON: &'static str = "Hillary Clinton";
|
||||
pub const BERNIE_SANDERS: &'static str = "Bernie Sanders";
|
||||
}
|
||||
|
||||
mod republicans {
|
||||
pub const DONALD_TRUMP: &'static str = "Donald Trump";
|
||||
pub const JEB_BUSH: &'static str = "Jeb Bush";
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("candidates: {} and {}",
|
||||
us_presidential_frontrunners::democrat,
|
||||
us_presidential_frontrunners::republican);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The us_presidential_frontrunners module is trying to present an external
|
||||
// interface (the `democrat` and `republican` constants) that is different than
|
||||
// its internal structure (the `democrats` and `republicans` modules and
|
||||
// associated constants). It's almost there except for one keyword missing for
|
||||
// each constant.
|
||||
43
old_curriculum/move_semantics/move_semantics1.rs
Normal file
43
old_curriculum/move_semantics/move_semantics1.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
// move_semantics1.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
pub fn main() {
|
||||
let vec0 = Vec::new();
|
||||
|
||||
let vec1 = fill_vec(vec0);
|
||||
|
||||
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
|
||||
|
||||
vec1.push(88);
|
||||
|
||||
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
|
||||
|
||||
}
|
||||
|
||||
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||
let mut vec = vec;
|
||||
|
||||
vec.push(22);
|
||||
vec.push(44);
|
||||
vec.push(66);
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 11,
|
||||
// right? The fix for this is going to be adding one keyword, and the addition is NOT on line 11
|
||||
// where the error is.
|
||||
54
old_curriculum/move_semantics/move_semantics2.rs
Normal file
54
old_curriculum/move_semantics/move_semantics2.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
// move_semantics2.rs
|
||||
// Make me compile without changing line 10! Scroll down for hints :)
|
||||
|
||||
pub fn main() {
|
||||
let vec0 = Vec::new();
|
||||
|
||||
let mut vec1 = fill_vec(vec0);
|
||||
|
||||
// Do not change the following line!
|
||||
println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);
|
||||
|
||||
vec1.push(88);
|
||||
|
||||
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
|
||||
|
||||
}
|
||||
|
||||
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||
let mut vec = vec;
|
||||
|
||||
vec.push(22);
|
||||
vec.push(44);
|
||||
vec.push(66);
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// So `vec0` is being *moved* into the function `fill_vec` when we call it on
|
||||
// line 7, which means it gets dropped at the end of `fill_vec`, which means we
|
||||
// can't use `vec0` again on line 10 (or anywhere else in `main` after the
|
||||
// `fill_vec` call for that matter). We could fix this in a few ways, try them
|
||||
// all!
|
||||
// 1. Make another, separate version of the data that's in `vec0` and pass that
|
||||
// to `fill_vec` instead.
|
||||
// 2. Make `fill_vec` borrow its argument instead of taking ownership of it,
|
||||
// and then copy the data within the function in order to return an owned
|
||||
// `Vec<i32>`
|
||||
// 3. Make `fill_vec` *mutably* borrow its argument (which will need to be
|
||||
// mutable), modify it directly, then not return anything. Then you can get rid
|
||||
// of `vec1` entirely -- note that this will change what gets printed by the
|
||||
// first `println!`
|
||||
46
old_curriculum/move_semantics/move_semantics3.rs
Normal file
46
old_curriculum/move_semantics/move_semantics3.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
// move_semantics3.rs
|
||||
// Make me compile without adding new lines-- just changing existing lines!
|
||||
// (no lines with multiple semicolons necessary!)
|
||||
// Scroll down for hints :)
|
||||
|
||||
pub fn main() {
|
||||
let vec0 = Vec::new();
|
||||
|
||||
let mut vec1 = fill_vec(vec0);
|
||||
|
||||
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
|
||||
|
||||
vec1.push(88);
|
||||
|
||||
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
|
||||
|
||||
}
|
||||
|
||||
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||
vec.push(22);
|
||||
vec.push(44);
|
||||
vec.push(66);
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The difference between this one and the previous ones is that the first line
|
||||
// of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can,
|
||||
// instead of adding that line back, add `mut` in one place that will change
|
||||
// an existing binding to be a mutable binding instead of an immutable one :)
|
||||
48
old_curriculum/move_semantics/move_semantics4.rs
Normal file
48
old_curriculum/move_semantics/move_semantics4.rs
Normal file
@@ -0,0 +1,48 @@
|
||||
// move_semantics4.rs
|
||||
// Refactor this code so that instead of having `vec0` and creating the vector
|
||||
// in `fn main`, we instead create it within `fn fill_vec` and transfer the
|
||||
// freshly created vector from fill_vec to its caller. Scroll for hints!
|
||||
|
||||
pub fn main() {
|
||||
let vec0 = Vec::new();
|
||||
|
||||
let mut vec1 = fill_vec(vec0);
|
||||
|
||||
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
|
||||
|
||||
vec1.push(88);
|
||||
|
||||
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
|
||||
|
||||
}
|
||||
|
||||
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
|
||||
let mut vec = vec;
|
||||
|
||||
vec.push(22);
|
||||
vec.push(44);
|
||||
vec.push(66);
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Stop reading whenever you feel like you have enough direction :) Or try
|
||||
// doing one step and then fixing the compiler errors that result!
|
||||
// So the end goal is to:
|
||||
// - get rid of the first line in main that creates the new vector
|
||||
// - so then `vec0` doesn't exist, so we can't pass it to `fill_vec`
|
||||
// - we don't want to pass anything to `fill_vec`, so its signature should
|
||||
// reflect that it does not take any arguments
|
||||
// - since we're not creating a new vec in `main` anymore, we need to create
|
||||
// a new vec in `fill_vec`, similarly to the way we did in `main`
|
||||
17
old_curriculum/primitive_types/primitive_types1.rs
Normal file
17
old_curriculum/primitive_types/primitive_types1.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
// primitive_types1.rs
|
||||
// Fill in the rest of the line that has code missing!
|
||||
// No hints, there's no tricks, just get used to typing these :)
|
||||
|
||||
fn main() {
|
||||
// Booleans (`bool`)
|
||||
|
||||
let is_morning = true;
|
||||
if is_morning {
|
||||
println!("Good morning!");
|
||||
}
|
||||
|
||||
let // Finish the rest of this line like the example! Or make it be false!
|
||||
if is_evening {
|
||||
println!("Good evening!");
|
||||
}
|
||||
}
|
||||
27
old_curriculum/primitive_types/primitive_types2.rs
Normal file
27
old_curriculum/primitive_types/primitive_types2.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
// primitive_types2.rs
|
||||
// Fill in the rest of the line that has code missing!
|
||||
// No hints, there's no tricks, just get used to typing these :)
|
||||
|
||||
fn main() {
|
||||
// Characters (`char`)
|
||||
|
||||
let my_first_initial = 'C';
|
||||
if my_first_initial.is_alphabetic() {
|
||||
println!("Alphabetical!");
|
||||
} else if my_first_initial.is_numeric() {
|
||||
println!("Numerical!");
|
||||
} else {
|
||||
println!("Neither alphabetic nor numeric!");
|
||||
}
|
||||
|
||||
let // Finish this line like the example! What's your favorite character?
|
||||
// Try a letter, try a number, try a special character, try a character
|
||||
// from a different language than your own, try an emoji!
|
||||
if your_character.is_alphabetic() {
|
||||
println!("Alphabetical!");
|
||||
} else if your_character.is_numeric() {
|
||||
println!("Numerical!");
|
||||
} else {
|
||||
println!("Neither alphabetic nor numeric!");
|
||||
}
|
||||
}
|
||||
46
old_curriculum/primitive_types/primitive_types3.rs
Normal file
46
old_curriculum/primitive_types/primitive_types3.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
// primitive_types3.rs
|
||||
// Create an array with at least 100 elements in it where the ??? is.
|
||||
// Scroll down for hints!
|
||||
|
||||
fn main() {
|
||||
let a = ???
|
||||
|
||||
if a.len() >= 100 {
|
||||
println!("Wow, that's a big array!");
|
||||
} else {
|
||||
println!("Meh, I eat arrays like that for breakfast.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// There's a shorthand to initialize Arrays with a certain size that does not
|
||||
// require you to type in 100 items (but you certainly can if you want!)
|
||||
// Check out the Primitive Types -> Arrays section of the book:
|
||||
// https://doc.rust-lang.org/stable/book/second-edition/ch03-02-data-types.html#arrays
|
||||
// Bonus: what are some other things you could have that would return true
|
||||
// for `a.len() >= 100`?
|
||||
49
old_curriculum/primitive_types/primitive_types4.rs
Normal file
49
old_curriculum/primitive_types/primitive_types4.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
// primitive_types4.rs
|
||||
// Get a slice out of Array a where the ??? is so that the `if` statement
|
||||
// returns true. Scroll down for hints!!
|
||||
|
||||
fn main() {
|
||||
let a = [1, 2, 3, 4, 5];
|
||||
|
||||
let nice_slice = ???
|
||||
|
||||
if nice_slice == [2, 3, 4] {
|
||||
println!("Nice slice!");
|
||||
} else {
|
||||
println!("Not quite what I was expecting... I see: {:?}", nice_slice);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Take a look at the Primitive Types -> Slices section of the book:
|
||||
// http://doc.rust-lang.org/stable/book/primitive-types.html#slices
|
||||
// and use the starting and ending indices of the items in the Array
|
||||
// that you want to end up in the slice.
|
||||
|
||||
// If you're curious why the right hand of the `==` comparison does not
|
||||
// have an ampersand for a reference since the left hand side is a
|
||||
// reference, take a look at the Deref coercions chapter:
|
||||
// http://doc.rust-lang.org/stable/book/deref-coercions.html
|
||||
45
old_curriculum/primitive_types/primitive_types5.rs
Normal file
45
old_curriculum/primitive_types/primitive_types5.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
// primitive_types5.rs
|
||||
// Destructure the `cat` tuple so that the println will work.
|
||||
// Scroll down for hints!
|
||||
|
||||
fn main() {
|
||||
let cat = ("Furry McFurson", 3.5);
|
||||
let /* your pattern here */ = cat;
|
||||
|
||||
println!("{} is {} years old.", name, age);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Take a look at the Primitive Types -> Tuples section of the book:
|
||||
// http://doc.rust-lang.org/stable/book/primitive-types.html#tuples
|
||||
// Particularly the part about "destructuring lets". You'll need to
|
||||
// make a pattern to bind `name` and `age` to the appropriate parts
|
||||
// of the tuple. You can do it!!
|
||||
44
old_curriculum/primitive_types/primitive_types6.rs
Normal file
44
old_curriculum/primitive_types/primitive_types6.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
// primitive_types6.rs
|
||||
// Use a tuple index to access the second element of `numbers`.
|
||||
// You can put this right into the `println!` where the ??? is.
|
||||
// Scroll down for hints!
|
||||
|
||||
fn main() {
|
||||
let numbers = (1, 2, 3);
|
||||
println!("The second number is {}", ???);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// While you could use a destructuring `let` for the tuple here, try
|
||||
// indexing into it instead, as explained here:
|
||||
// http://doc.rust-lang.org/stable/book/primitive-types.html#tuple-indexing
|
||||
// Now you have another tool in your toolbox!
|
||||
49
old_curriculum/src/bin/generate_readme.rs
Normal file
49
old_curriculum/src/bin/generate_readme.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
// This script reads README-template.md and generates the playground links
|
||||
// from the Rust source files in the various directories.
|
||||
|
||||
// To add a new exercise, add it to the appropriate place in README-template.md
|
||||
// and then make sure to recompile this script (because the template gets
|
||||
// included at compile time and then run it to generate a new version of
|
||||
// README.md.
|
||||
|
||||
extern crate handlebars;
|
||||
extern crate prlink;
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
use handlebars::{Handlebars, Helper, RenderContext, RenderError};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let mut template_file = File::open("README-template.hbs").unwrap();
|
||||
let mut template = String::new();
|
||||
template_file.read_to_string(&mut template).unwrap();
|
||||
|
||||
let autogenerated_notice = "This file was autogenerated by the script in src/bin/generate_readme.rs.
|
||||
Please edit either the script or the template in README-template.md in
|
||||
order to make changes here rather than committing the changes directly.";
|
||||
|
||||
let mut generated_readme = File::create("README.md").unwrap();
|
||||
|
||||
let mut hbs = Handlebars::new();
|
||||
hbs.register_helper("playground_link", Box::new(playground_link_helper));
|
||||
|
||||
write!(
|
||||
generated_readme,
|
||||
"{}",
|
||||
hbs.render_template(
|
||||
&template,
|
||||
&json!({ "autogenerated_notice": autogenerated_notice }),
|
||||
).unwrap()
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
fn playground_link_helper(h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
|
||||
let filename = PathBuf::from(h.param(0).unwrap().value().as_str().unwrap());
|
||||
let link = prlink::linkify_file(&filename);
|
||||
rc.writer.write(link.into_bytes().as_ref())?;
|
||||
Ok(())
|
||||
}
|
||||
56
old_curriculum/standard_library_types/arc1.rs
Normal file
56
old_curriculum/standard_library_types/arc1.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
// arc1.rs
|
||||
// Make this code compile by filling in a value for `shared_numbers` where the
|
||||
// TODO comment is and creating an initial binding for `child_numbers`
|
||||
// somewhere. Try not to create any copies of the `numbers` Vec!
|
||||
// Scroll down for hints :)
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
fn main() {
|
||||
let numbers: Vec<_> = (0..100u32).collect();
|
||||
let shared_numbers = // TODO
|
||||
let mut joinhandles = Vec::new();
|
||||
|
||||
for offset in 0..8 {
|
||||
joinhandles.push(
|
||||
thread::spawn(move || {
|
||||
let mut i = offset;
|
||||
let mut sum = 0;
|
||||
while i < child_numbers.len() {
|
||||
sum += child_numbers[i];
|
||||
i += 5;
|
||||
}
|
||||
println!("Sum of offset {} is {}", offset, sum);
|
||||
}));
|
||||
}
|
||||
for handle in joinhandles.into_iter() {
|
||||
handle.join().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order
|
||||
// to avoid creating a copy of `numbers`, you'll need to create `child_numbers`
|
||||
// inside the loop but still in the main thread.
|
||||
|
||||
// `child_numbers` should be a clone of the Arc of the numbers instead of a
|
||||
// thread-local copy of the numbers.
|
||||
145
old_curriculum/standard_library_types/iterator3.rs
Normal file
145
old_curriculum/standard_library_types/iterator3.rs
Normal file
@@ -0,0 +1,145 @@
|
||||
// iterator3.rs
|
||||
// This is a bigger exercise than most of the others! You can do it!
|
||||
// Here is your mission, should you choose to accept it:
|
||||
// 1. Complete the divide function to get the first four tests to pass
|
||||
// 2. Uncomment the last two tests and get them to pass by filling in
|
||||
// values for `x` using `division_results`.
|
||||
// Scroll down for a minor hint for part 2, and scroll down further for
|
||||
// a major hint.
|
||||
// Have fun :-)
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum DivisionError {
|
||||
NotDivisible(NotDivisibleError),
|
||||
DivideByZero,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct NotDivisibleError {
|
||||
dividend: i32,
|
||||
divisor: i32,
|
||||
}
|
||||
|
||||
// This function should calculate `a` divided by `b` if `a` is
|
||||
// evenly divisible by b.
|
||||
// Otherwise, it should return a suitable error.
|
||||
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// Tests that verify your `divide` function implementation
|
||||
#[test]
|
||||
fn test_success() {
|
||||
assert_eq!(divide(81, 9), Ok(9));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_divisible() {
|
||||
assert_eq!(
|
||||
divide(81, 6),
|
||||
Err(DivisionError::NotDivisible(NotDivisibleError{
|
||||
dividend: 81,
|
||||
divisor: 6
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_divide_by_0() {
|
||||
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_divide_0_by_something() {
|
||||
assert_eq!(divide(0, 81), Ok(0));
|
||||
}
|
||||
|
||||
// Iterator exercises using your `divide` function
|
||||
/*
|
||||
#[test]
|
||||
fn result_with_list() {
|
||||
let numbers = vec![27, 297, 38502, 81];
|
||||
let division_results = numbers.into_iter().map(|n| divide(n, 27));
|
||||
let x //... Fill in here!
|
||||
assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_of_results() {
|
||||
let numbers = vec![27, 297, 38502, 81];
|
||||
let division_results = numbers.into_iter().map(|n| divide(n, 27));
|
||||
let x //... Fill in here!
|
||||
assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Minor hint: In each of the two cases in the match in main, you can create x with either a 'turbofish' or by hinting the type of x to the compiler. You may try both.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Major hint: Have a look at the Iter trait and at the explanation of its collect function. Especially the part about Result is interesting.
|
||||
61
old_curriculum/standard_library_types/iterators4.rs
Normal file
61
old_curriculum/standard_library_types/iterators4.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
// iterators4.rs
|
||||
|
||||
pub fn factorial(num: u64) -> u64 {
|
||||
// Complete this function to return factorial of num
|
||||
// Do not use:
|
||||
// - return
|
||||
// For extra fun don't use:
|
||||
// - imperative style loops (for, while)
|
||||
// - additional variables
|
||||
// For the most fun don't use:
|
||||
// - recursion
|
||||
// Scroll down for hints.
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn factorial_of_1() {
|
||||
assert_eq!(1, factorial(1));
|
||||
}
|
||||
#[test]
|
||||
fn factorial_of_2() {
|
||||
assert_eq!(2, factorial(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn factorial_of_4() {
|
||||
assert_eq!(24, factorial(4));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// In an imperative language you might write a for loop to iterate through
|
||||
// multiply the values into a mutable variable. Or you might write code more
|
||||
// functionally with recursion and a match clause. But you can also use ranges
|
||||
// and iterators to solve this in rust.
|
||||
46
old_curriculum/strings/strings1.rs
Normal file
46
old_curriculum/strings/strings1.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
// strings1.rs
|
||||
// Make me compile without changing the function signature! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
let answer = current_favorite_color();
|
||||
println!("My current favorite color is {}", answer);
|
||||
}
|
||||
|
||||
fn current_favorite_color() -> String {
|
||||
"blue"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The `current_favorite_color` function is currently returning a string slice with the `'static`
|
||||
// lifetime. We know this because the data of the string lives in our code itself -- it doesn't
|
||||
// come from a file or user input or another program -- so it will live as long as our program
|
||||
// lives. But it is still a string slice. There's one way to create a `String` by converting a
|
||||
// string slice covered in the Strings chapter of the book, and another way that uses the `From`
|
||||
// trait.
|
||||
44
old_curriculum/strings/strings2.rs
Normal file
44
old_curriculum/strings/strings2.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
// strings2.rs
|
||||
// Make me compile without changing the function signature! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
let word = String::from("green"); // Try not changing this line :)
|
||||
if is_a_color_word(word) {
|
||||
println!("That is a color word I know!");
|
||||
} else {
|
||||
println!("That is not a color word I know.");
|
||||
}
|
||||
}
|
||||
|
||||
fn is_a_color_word(attempt: &str) -> bool {
|
||||
attempt == "green" || attempt == "blue" || attempt == "red"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Yes, it would be really easy to fix this by just changing the value bound to `word` to be a
|
||||
// string slice instead of a `String`, wouldn't it?? There is a way to add one character to line
|
||||
// 6, though, that will coerce the `String` into a string slice.
|
||||
21
old_curriculum/strings/strings3.rs
Normal file
21
old_curriculum/strings/strings3.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
// strings3.rs
|
||||
// Ok, here are a bunch of values-- some are `Strings`, some are `&strs`. Your
|
||||
// task is to call one of these two functions on each value depending on what
|
||||
// you think each value is. That is, add either `string_slice` or `string`
|
||||
// before the parentheses on each line. If you're right, it will compile!
|
||||
|
||||
fn string_slice(arg: &str) { println!("{}", arg); }
|
||||
fn string(arg: String) { println!("{}", arg); }
|
||||
|
||||
fn main() {
|
||||
("blue");
|
||||
("red".to_string());
|
||||
(String::from("hi"));
|
||||
("rust is fun!".to_owned());
|
||||
("nice weather".into());
|
||||
(format!("Interpolation {}", "Station"));
|
||||
(&String::from("abc")[0..1]);
|
||||
(" hello there ".trim());
|
||||
("Happy Monday!".to_string().replace("Mon", "Tues"));
|
||||
("mY sHiFt KeY iS sTiCkY".to_lowercase());
|
||||
}
|
||||
49
old_curriculum/tests/tests1.rs
Normal file
49
old_curriculum/tests/tests1.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
// tests1.rs
|
||||
// Tests are important to ensure that your code does what you think it should do.
|
||||
// Tests can be run on this file with the following command:
|
||||
// rustc --test tests1.rs
|
||||
|
||||
// This test has a problem with it -- make the test compile! Make the test
|
||||
// pass! Make the test fail! Scroll down for hints :)
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn you_can_assert() {
|
||||
assert!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// You don't even need to write any code to test -- you can just test values and run that, even
|
||||
// though you wouldn't do that in real life :) `assert!` is a macro that needs an argument.
|
||||
// Depending on the value of the argument, `assert!` will do nothing (in which case the test will
|
||||
// pass) or `assert!` will panic (in which case the test will fail). So try giving different values
|
||||
// to `assert!` and see which ones compile, which ones pass, and which ones fail :)
|
||||
44
old_curriculum/tests/tests2.rs
Normal file
44
old_curriculum/tests/tests2.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
// tests2.rs
|
||||
// This test has a problem with it -- make the test compile! Make the test
|
||||
// pass! Make the test fail! Scroll down for hints :)
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn you_can_assert_eq() {
|
||||
assert_eq!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Like the previous exercise, you don't need to write any code to get this test to compile and
|
||||
// run. `assert_eq!` is a macro that takes two arguments and compares them. Try giving it two
|
||||
// values that are equal! Try giving it two arguments that are different! Try giving it two values
|
||||
// that are of different types! Try switching which argument comes first and which comes second!
|
||||
43
old_curriculum/tests/tests3.rs
Normal file
43
old_curriculum/tests/tests3.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
// tests3.rs
|
||||
// This test isn't testing our function -- make it do that in such a way that
|
||||
// the test passes. Then write a second test that tests that we get the result
|
||||
// we expect to get when we call `is_even(5)`. Scroll down for hints!
|
||||
|
||||
pub fn is_even(num: i32) -> bool {
|
||||
num % 2 == 0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn is_true_when_even() {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// You can call a function right where you're passing arguments to `assert!` -- so you could do
|
||||
// something like `assert!(having_fun())`. If you want to check that you indeed get false, you
|
||||
// can negate the result of what you're doing using `!`, like `assert!(!having_fun())`.
|
||||
19
old_curriculum/tests/tests4.rs
Normal file
19
old_curriculum/tests/tests4.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
// tests4.rs
|
||||
// This test isn't testing our function -- make it do that in such a way that
|
||||
// the test passes. Then write a second test that tests that we get the result
|
||||
// we expect to get when we call `times_two` with a negative number.
|
||||
// No hints, you can do this :)
|
||||
|
||||
pub fn times_two(num: i32) -> i32 {
|
||||
num * 2
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn returns_twice_of_positive_numbers() {
|
||||
assert_eq!(4, 4);
|
||||
}
|
||||
}
|
||||
95
old_curriculum/threads/threads1.rs
Normal file
95
old_curriculum/threads/threads1.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
// threads1.rs
|
||||
// Make this compile! Scroll down for hints :) The idea is the thread
|
||||
// spawned on line 19 is completing jobs while the main thread is
|
||||
// monitoring progress until 10 jobs are completed. If you see 6 lines
|
||||
// of "waiting..." and the program ends without timing out the playground,
|
||||
// you've got it :)
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
struct JobStatus {
|
||||
jobs_completed: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let status = Arc::new(JobStatus { jobs_completed: 0 });
|
||||
let status_shared = status.clone();
|
||||
thread::spawn(move || {
|
||||
for _ in 0..10 {
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
status_shared.jobs_completed += 1;
|
||||
}
|
||||
});
|
||||
while status.jobs_completed < 10 {
|
||||
println!("waiting... ");
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// `Arc` is an Atomic Reference Counted pointer that allows safe, shared access
|
||||
// to **immutable** data. But we want to *change* the number of `jobs_completed`
|
||||
// so we'll need to also use another type that will only allow one thread to
|
||||
// mutate the data at a time. Take a look at this section of the book:
|
||||
// https://doc.rust-lang.org/stable/book/concurrency.html#safe-shared-mutable-state
|
||||
// and keep scrolling if you'd like more hints :)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like:
|
||||
// `let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));`
|
||||
// Similar to the code in the example in the book that happens after the text
|
||||
// that says "We can use Arc<T> to fix this.". If not, give that a try! If you
|
||||
// do and would like more hints, keep scrolling!!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Make sure neither of your threads are holding onto the lock of the mutex
|
||||
// while they are sleeping, since this will prevent the other thread from
|
||||
// being allowed to get the lock. Locks are automatically released when
|
||||
// they go out of scope.
|
||||
|
||||
// Ok, so, real talk, this was actually tricky for *me* to do too. And
|
||||
// I could see a lot of different problems you might run into, so at this
|
||||
// point I'm not sure which one you've hit :) Please see a few possible
|
||||
// answers on https://github.com/carols10cents/rustlings/issues/3 --
|
||||
// mine is a little more complicated because I decided I wanted to see
|
||||
// the number of jobs currently done when I was checking the status.
|
||||
|
||||
// Please open an issue if you're still running into a problem that
|
||||
// these hints are not helping you with, or if you've looked at the sample
|
||||
// answers and don't understand why they work and yours doesn't.
|
||||
|
||||
// If you've learned from the sample solutions, I encourage you to come
|
||||
// back to this exercise and try it again in a few days to reinforce
|
||||
// what you've learned :)
|
||||
42
old_curriculum/variables/variables1.rs
Normal file
42
old_curriculum/variables/variables1.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
// variables1.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
x = 5;
|
||||
println!("x has the value {}", x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Hint: The declaration on line 5 is missing a keyword that is needed in Rust
|
||||
// to create a new variable binding.
|
||||
47
old_curriculum/variables/variables2.rs
Normal file
47
old_curriculum/variables/variables2.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
// variables2.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
let x;
|
||||
if x == 10 {
|
||||
println!("Ten!");
|
||||
} else {
|
||||
println!("Not ten!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// The compiler message is saying that Rust cannot infer the type that the
|
||||
// variable binding `x` has with what is given here.
|
||||
// What happens if you annotate line 5 with a type annotation?
|
||||
// What if you give x a value?
|
||||
// What if you do both?
|
||||
// What type should x be, anyway?
|
||||
// What if x is the same type as 10? What if it's a different type?
|
||||
43
old_curriculum/variables/variables3.rs
Normal file
43
old_curriculum/variables/variables3.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
// variables3.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
let x = 3;
|
||||
println!("Number {}", x);
|
||||
x = 5;
|
||||
println!("Number {}", x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// In Rust, variable bindings are immutable by default. But here we're trying
|
||||
// to reassign a different value to x! There's a keyword we can use to make
|
||||
// a variable binding mutable instead.
|
||||
45
old_curriculum/variables/variables4.rs
Normal file
45
old_curriculum/variables/variables4.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
// variables4.rs
|
||||
// Make me compile! Scroll down for hints :)
|
||||
|
||||
fn main() {
|
||||
let x: i32;
|
||||
println!("Number {}", x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Oops! In this exercise, we have a variable binding that we've created on
|
||||
// line 5, and we're trying to use it on line 6, but we haven't given it a
|
||||
// value. We can't print out something that isn't there; try giving x a value!
|
||||
// This is an error that can cause bugs that's very easy to make in any
|
||||
// programming language -- thankfully the Rust compiler has caught this for us!
|
||||
Reference in New Issue
Block a user