From 32ac403da5c49b002ba420186d3122501196ff89 Mon Sep 17 00:00:00 2001 From: olivia Date: Thu, 26 Apr 2018 21:21:28 +0200 Subject: wipe readme --- README.md | 190 +------------------------------------------------------------- 1 file changed, 1 insertion(+), 189 deletions(-) diff --git a/README.md b/README.md index c6d9d97..bcd03a9 100644 --- a/README.md +++ b/README.md @@ -1,192 +1,4 @@ - - # 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) - -- ["variables1.rs"](https://play.rust-lang.org/?code=%2F%2F+variables1.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++x+%3D+5%3B%0A++++println%21%28%22x+has+the+value+%7B%7D%22%2C+x%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Hint%3A+The+declaration+on+line+5+is+missing+a+keyword+that+is+needed+in+Rust%0A%2F%2F+to+create+a+new+variable+binding.%0A) -- ["variables2.rs"](https://play.rust-lang.org/?code=%2F%2F+variables2.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+x%3B%0A++++if+x+%3D%3D+10+%7B%0A++++++++println%21%28%22Ten%21%22%29%3B%0A++++%7D+else+%7B%0A++++++++println%21%28%22Not+ten%21%22%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+The+compiler+message+is+saying+that+Rust+cannot+infer+the+type+that+the%0A%2F%2F+variable+binding+%60x%60+has+with+what+is+given+here.%0A%2F%2F+What+happens+if+you+annotate+line+5+with+a+type+annotation%3F%0A%2F%2F+What+if+you+give+x+a+value%3F%0A%2F%2F+What+if+you+do+both%3F%0A%2F%2F+What+type+should+x+be%2C+anyway%3F%0A%2F%2F+What+if+x+is+the+same+type+as+10%3F+What+if+it%27s+a+different+type%3F%0A) -- ["variables3.rs"](https://play.rust-lang.org/?code=%2F%2F+variables3.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+x+%3D+3%3B%0A++++println%21%28%22Number+%7B%7D%22%2C+x%29%3B%0A++++x+%3D+5%3B%0A++++println%21%28%22Number+%7B%7D%22%2C+x%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+In+Rust%2C+variable+bindings+are+immutable+by+default.+But+here+we%27re+trying%0A%2F%2F+to+reassign+a+different+value+to+x%21+There%27s+a+keyword+we+can+use+to+make%0A%2F%2F+a+variable+binding+mutable+instead.%0A) -- ["variables4.rs"](https://play.rust-lang.org/?code=%2F%2F+variables4.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+x%3A+i32%3B%0A++++println%21%28%22Number+%7B%7D%22%2C+x%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Oops%21+In+this+exercise%2C+we+have+a+variable+binding+that+we%27ve+created+on%0A%2F%2F+line+5%2C+and+we%27re+trying+to+use+it+on+line+6%2C+but+we+haven%27t+given+it+a%0A%2F%2F+value.+We+can%27t+print+out+something+that+isn%27t+there%3B+try+giving+x+a+value%21%0A%2F%2F+This+is+an+error+that+can+cause+bugs+that%27s+very+easy+to+make+in+any%0A%2F%2F+programming+language+--+thankfully+the+Rust+compiler+has+caught+this+for+us%21%0A) - -### Functions - -[Relevant chapter in The Rust Programming -Language](https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html) - -- ["functions1.rs"](https://play.rust-lang.org/?code=%2F%2F+functions1.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++call_me%28%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+This+main+function+is+calling+a+function+that+it+expects+to+exist%2C+but+the%0A%2F%2F+function+doesn%27t+exist.+It+expects+this+function+to+have+the+name+%60call_me%60.%0A%2F%2F+It+expects+this+function+to+not+take+any+arguments+and+not+return+a+value.%0A%2F%2F+Sounds+a+lot+like+%60main%60%2C+doesn%27t+it%3F%0A) -- ["functions2.rs"](https://play.rust-lang.org/?code=%2F%2F+functions2.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++call_me%283%29%3B%0A%7D%0A%0Afn+call_me%28num%29+%7B%0A++++for+i+in+0..num+%7B%0A++++++++println%21%28%22Ring%21+Call+number+%7B%7D%22%2C+i+%2B+1%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Rust+requires+that+all+parts+of+a+function%27s+signature+have+type+annotations%2C%0A%2F%2F+but+%60call_me%60+is+missing+the+type+annotation+of+%60num%60.%0A) -- ["functions3.rs"](https://play.rust-lang.org/?code=%2F%2F+functions3.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++call_me%28%29%3B%0A%7D%0A%0Afn+call_me%28num%3A+i32%29+%7B%0A++++for+i+in+0..num+%7B%0A++++++++println%21%28%22Ring%21+Call+number+%7B%7D%22%2C+i+%2B+1%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+This+time%2C+the+function+*declaration*+is+okay%2C+but+there%27s+something+wrong%0A%2F%2F+with+the+place+where+we%27re+calling+the+function.%0A) -- ["functions4.rs"](https://play.rust-lang.org/?code=%2F%2F+functions4.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0A%2F%2F+This+store+is+having+a+sale+where+if+the+price+is+an+even+number%2C+you+get%0A%2F%2F+10+%28money+unit%29+off%2C+but+if+it%27s+an+odd+number%2C+it%27s+3+%28money+unit%29+less.%0A%0Afn+main%28%29+%7B%0A++++let+original_price+%3D+51%3B%0A++++println%21%28%22Your+sale+price+is+%7B%7D%22%2C+sale_price%28original_price%29%29%3B%0A%7D%0A%0Afn+sale_price%28price%3A+i32%29+-%3E+%7B%0A++++if+is_even%28price%29+%7B%0A++++++++price+-+10%0A++++%7D+else+%7B%0A++++++++price+-+3%0A++++%7D%0A%7D%0A%0Afn+is_even%28num%3A+i32%29+-%3E+bool+%7B%0A++++num+%25+2+%3D%3D+0%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+The+error+message+points+to+line+12+and+says+it+expects+a+type+after+the%0A%2F%2F+%60-%3E%60.+This+is+where+the+function%27s+return+type+should+be--+take+a+look+at%0A%2F%2F+the+%60is_even%60+function+for+an+example%21%0A) -- ["functions5.rs"](https://play.rust-lang.org/?code=%2F%2F+functions5.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+answer+%3D+square%283%29%3B%0A++++println%21%28%22The+answer+is+%7B%7D%22%2C+answer%29%3B%0A%7D%0A%0Afn+square%28num%3A+i32%29+-%3E+i32+%7B%0A++++num+*+num%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+This+is+a+really+common+error+that+can+be+fixed+by+removing+one+character.%0A%2F%2F+It+happens+because+Rust+distinguishes+between+expressions+and+statements%3A+expressions+return%0A%2F%2F+a+value+and+statements+don%27t.+We+want+to+return+a+value+from+the+%60square%60+function%2C+but+it%0A%2F%2F+isn%27t+returning+one+right+now...%0A) - -### Primitive types - -[Relevant chapter in The Rust Programming -Language](https://doc.rust-lang.org/book/second-edition/ch03-02-data-types.html) - -- ["primitive_types1.rs"](https://play.rust-lang.org/?code=%2F%2F+primitive_types1.rs%0A%2F%2F+Fill+in+the+rest+of+the+line+that+has+code+missing%21%0A%2F%2F+No+hints%2C+there%27s+no+tricks%2C+just+get+used+to+typing+these+%3A%29%0A%0Afn+main%28%29+%7B%0A++++%2F%2F+Booleans+%28%60bool%60%29%0A%0A++++let+is_morning+%3D+true%3B%0A++++if+is_morning+%7B%0A++++++++println%21%28%22Good+morning%21%22%29%3B%0A++++%7D%0A%0A++++let+%2F%2F+Finish+the+rest+of+this+line+like+the+example%21+Or+make+it+be+false%21%0A++++if+is_evening+%7B%0A++++++++println%21%28%22Good+evening%21%22%29%3B%0A++++%7D%0A%7D%0A) -- ["primitive_types2.rs"](https://play.rust-lang.org/?code=%2F%2F+primitive_types2.rs%0A%2F%2F+Fill+in+the+rest+of+the+line+that+has+code+missing%21%0A%2F%2F+No+hints%2C+there%27s+no+tricks%2C+just+get+used+to+typing+these+%3A%29%0A%0Afn+main%28%29+%7B%0A++++%2F%2F+Characters+%28%60char%60%29%0A%0A++++let+my_first_initial+%3D+%27C%27%3B%0A++++if+my_first_initial.is_alphabetic%28%29+%7B%0A++++++++println%21%28%22Alphabetical%21%22%29%3B%0A++++%7D+else+if+my_first_initial.is_numeric%28%29+%7B%0A++++++++println%21%28%22Numerical%21%22%29%3B%0A++++%7D+else+%7B%0A++++++++println%21%28%22Neither+alphabetic+nor+numeric%21%22%29%3B%0A++++%7D%0A%0A++++let+%2F%2F+Finish+this+line+like+the+example%21+What%27s+your+favorite+character%3F%0A++++%2F%2F+Try+a+letter%2C+try+a+number%2C+try+a+special+character%2C+try+a+character%0A++++%2F%2F+from+a+different+language+than+your+own%2C+try+an+emoji%21%0A++++if+your_character.is_alphabetic%28%29+%7B%0A++++++++println%21%28%22Alphabetical%21%22%29%3B%0A++++%7D+else+if+your_character.is_numeric%28%29+%7B%0A++++++++println%21%28%22Numerical%21%22%29%3B%0A++++%7D+else+%7B%0A++++++++println%21%28%22Neither+alphabetic+nor+numeric%21%22%29%3B%0A++++%7D%0A%7D%0A) -- ["primitive_types3.rs"](https://play.rust-lang.org/?code=%2F%2F+primitive_types3.rs%0A%2F%2F+Create+an+array+with+at+least+100+elements+in+it+where+the+%3F%3F%3F+is.+%0A%2F%2F+Scroll+down+for+hints%21%0A%0Afn+main%28%29+%7B%0A++++let+a+%3D+%3F%3F%3F%0A%0A++++if+a.len%28%29+%3E%3D+100+%7B%0A++++++++println%21%28%22Wow%2C+that%27s+a+big+array%21%22%29%3B%0A++++%7D+else+%7B%0A++++++++println%21%28%22Meh%2C+I+eat+arrays+like+that+for+breakfast.%22%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+There%27s+a+shorthand+to+initialize+Arrays+with+a+certain+size+that+does+not+%0A%2F%2F+require+you+to+type+in+100+items+%28but+you+certainly+can+if+you+want%21%29%0A%2F%2F+Check+out+the+Primitive+Types+-%3E+Arrays+section+of+the+book%3A%0A%2F%2F+https%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Fsecond-edition%2Fch03-02-data-types.html%23arrays%0A%2F%2F+Bonus%3A+what+are+some+other+things+you+could+have+that+would+return+true%0A%2F%2F+for+%60a.len%28%29+%3E%3D+100%60%3F%0A) -- ["primitive_types4.rs"](https://play.rust-lang.org/?code=%2F%2F+primitive_types4.rs%0A%2F%2F+Get+a+slice+out+of+Array+a+where+the+%3F%3F%3F+is+so+that+the+%60if%60+statement%0A%2F%2F+returns+true.+Scroll+down+for+hints%21%21%0A%0Afn+main%28%29+%7B%0A++++let+a+%3D+%5B1%2C+2%2C+3%2C+4%2C+5%5D%3B%0A%0A++++let+nice_slice+%3D+%3F%3F%3F%0A%0A++++if+nice_slice+%3D%3D+%5B2%2C+3%2C+4%5D+%7B%0A++++++++println%21%28%22Nice+slice%21%22%29%3B%0A++++%7D+else+%7B%0A++++++++println%21%28%22Not+quite+what+I+was+expecting...+I+see%3A+%7B%3A%3F%7D%22%2C+nice_slice%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Take+a+look+at+the+Primitive+Types+-%3E+Slices+section+of+the+book%3A%0A%2F%2F+http%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Fprimitive-types.html%23slices%0A%2F%2F+and+use+the+starting+and+ending+indices+of+the+items+in+the+Array%0A%2F%2F+that+you+want+to+end+up+in+the+slice.%0A%0A%2F%2F+If+you%27re+curious+why+the+right+hand+of+the+%60%3D%3D%60+comparison+does+not%0A%2F%2F+have+an+ampersand+for+a+reference+since+the+left+hand+side+is+a%0A%2F%2F+reference%2C+take+a+look+at+the+Deref+coercions+chapter%3A%0A%2F%2F+http%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Fderef-coercions.html%0A) -- ["primitive_types5.rs"](https://play.rust-lang.org/?code=%2F%2F+primitive_types5.rs%0A%2F%2F+Destructure+the+%60cat%60+tuple+so+that+the+println+will+work.%0A%2F%2F+Scroll+down+for+hints%21%0A%0Afn+main%28%29+%7B%0A++++let+cat+%3D+%28%22Furry+McFurson%22%2C+3.5%29%3B%0A++++let+%2F*+your+pattern+here+*%2F+%3D+cat%3B%0A%0A++++println%21%28%22%7B%7D+is+%7B%7D+years+old.%22%2C+name%2C+age%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Take+a+look+at+the+Primitive+Types+-%3E+Tuples+section+of+the+book%3A%0A%2F%2F+http%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Fprimitive-types.html%23tuples%0A%2F%2F+Particularly+the+part+about+%22destructuring+lets%22.+You%27ll+need+to%0A%2F%2F+make+a+pattern+to+bind+%60name%60+and+%60age%60+to+the+appropriate+parts%0A%2F%2F+of+the+tuple.+You+can+do+it%21%21%0A) -- ["primitive_types6.rs"](https://play.rust-lang.org/?code=%2F%2F+primitive_types6.rs%0A%2F%2F+Use+a+tuple+index+to+access+the+second+element+of+%60numbers%60.%0A%2F%2F+You+can+put+this+right+into+the+%60println%21%60+where+the+%3F%3F%3F+is.%0A%2F%2F+Scroll+down+for+hints%21%0A%0Afn+main%28%29+%7B%0A++++let+numbers+%3D+%281%2C+2%2C+3%29%3B%0A++++println%21%28%22The+second+number+is+%7B%7D%22%2C+%3F%3F%3F%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+While+you+could+use+a+destructuring+%60let%60+for+the+tuple+here%2C+try+%0A%2F%2F+indexing+into+it+instead%2C+as+explained+here%3A%0A%2F%2F+http%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Fprimitive-types.html%23tuple-indexing%0A%2F%2F+Now+you+have+another+tool+in+your+toolbox%21%0A) - -### 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) - -- ["tests1.rs"](https://play.rust-lang.org/?code=%2F%2F+tests1.rs%0A%2F%2F+Tests+are+important+to+ensure+that+your+code+does+what+you+think+it+should+do.%0A%2F%2F+Tests+can+be+run+on+this+file+with+the+following+command%3A%0A%2F%2F+rustc+--test+tests1.rs%0A%0A%2F%2F+This+test+has+a+problem+with+it+--+make+the+test+compile%21+Make+the+test%0A%2F%2F+pass%21+Make+the+test+fail%21+Scroll+down+for+hints+%3A%29%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++%23%5Btest%5D%0A++++fn+you_can_assert%28%29+%7B%0A++++++++assert%21%28%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+You+don%27t+even+need+to+write+any+code+to+test+--+you+can+just+test+values+and+run+that%2C+even%0A%2F%2F+though+you+wouldn%27t+do+that+in+real+life+%3A%29+%60assert%21%60+is+a+macro+that+needs+an+argument.%0A%2F%2F+Depending+on+the+value+of+the+argument%2C+%60assert%21%60+will+do+nothing+%28in+which+case+the+test+will%0A%2F%2F+pass%29+or+%60assert%21%60+will+panic+%28in+which+case+the+test+will+fail%29.+So+try+giving+different+values%0A%2F%2F+to+%60assert%21%60+and+see+which+ones+compile%2C+which+ones+pass%2C+and+which+ones+fail+%3A%29%0A) -- ["tests2.rs"](https://play.rust-lang.org/?code=%2F%2F+tests2.rs%0A%2F%2F+This+test+has+a+problem+with+it+--+make+the+test+compile%21+Make+the+test%0A%2F%2F+pass%21+Make+the+test+fail%21+Scroll+down+for+hints+%3A%29%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++%23%5Btest%5D%0A++++fn+you_can_assert_eq%28%29+%7B%0A++++++++assert_eq%21%28%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Like+the+previous+exercise%2C+you+don%27t+need+to+write+any+code+to+get+this+test+to+compile+and%0A%2F%2F+run.+%60assert_eq%21%60+is+a+macro+that+takes+two+arguments+and+compares+them.+Try+giving+it+two%0A%2F%2F+values+that+are+equal%21+Try+giving+it+two+arguments+that+are+different%21+Try+giving+it+two+values%0A%2F%2F+that+are+of+different+types%21+Try+switching+which+argument+comes+first+and+which+comes+second%21%0A) -- ["tests3.rs"](https://play.rust-lang.org/?code=%2F%2F+tests3.rs%0A%2F%2F+This+test+isn%27t+testing+our+function+--+make+it+do+that+in+such+a+way+that%0A%2F%2F+the+test+passes.+Then+write+a+second+test+that+tests+that+we+get+the+result%0A%2F%2F+we+expect+to+get+when+we+call+%60is_even%285%29%60.+Scroll+down+for+hints%21%0A%0Apub+fn+is_even%28num%3A+i32%29+-%3E+bool+%7B%0A++++num+%25+2+%3D%3D+0%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%23%5Btest%5D%0A++++fn+is_true_when_even%28%29+%7B%0A++++++++assert%21%28false%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+You+can+call+a+function+right+where+you%27re+passing+arguments+to+%60assert%21%60+--+so+you+could+do%0A%2F%2F+something+like+%60assert%21%28having_fun%28%29%29%60.+If+you+want+to+check+that+you+indeed+get+false%2C+you%0A%2F%2F+can+negate+the+result+of+what+you%27re+doing+using+%60%21%60%2C+like+%60assert%21%28%21having_fun%28%29%29%60.%0A) -- ["tests4.rs"](https://play.rust-lang.org/?code=%2F%2F+tests4.rs%0A%2F%2F+This+test+isn%27t+testing+our+function+--+make+it+do+that+in+such+a+way+that%0A%2F%2F+the+test+passes.+Then+write+a+second+test+that+tests+that+we+get+the+result%0A%2F%2F+we+expect+to+get+when+we+call+%60times_two%60+with+a+negative+number.%0A%2F%2F+No+hints%2C+you+can+do+this+%3A%29%0A%0Apub+fn+times_two%28num%3A+i32%29+-%3E+i32+%7B%0A++++num+*+2%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%23%5Btest%5D%0A++++fn+returns_twice_of_positive_numbers%28%29+%7B%0A++++++++assert_eq%21%284%2C+4%29%3B%0A++++%7D%0A%7D%0A) - -### If - -[Relevant chapter in The Rust Programming -Language](https://doc.rust-lang.org/book/second-edition/ch03-05-control-flow.html) - -- ["if1.rs"](https://play.rust-lang.org/?code=%2F%2F+if1.rs%0A%0Apub+fn+bigger%28a%3A+i32%2C+b%3Ai32%29+-%3E+i32+%7B%0A++++%2F%2F+Complete+this+function+to+return+the+bigger+number%21%0A++++%2F%2F+Do+not+use%3A%0A++++%2F%2F+-+return%0A++++%2F%2F+-+another+function+call%0A++++%2F%2F+-+additional+variables%0A++++%2F%2F+Scroll+down+for+hints.%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%23%5Btest%5D%0A++++fn+ten_is_bigger_than_eight%28%29+%7B%0A++++++++assert_eq%21%2810%2C+bigger%2810%2C+8%29%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+fortytwo_is_bigger_than_thirtytwo%28%29+%7B%0A++++++++assert_eq%21%2842%2C+bigger%2832%2C+42%29%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+It%27s+possible+to+do+this+in+one+line+if+you+would+like%21%0A%2F%2F+Some+similar+examples+from+other+languages%3A%0A%2F%2F+-+In+C%28%2B%2B%29+this+would+be%3A+%60a+%3E+b+%3F+a+%3A+b%60%0A%2F%2F+-+In+Python+this+would+be%3A++%60a+if+a+%3E+b+else+b%60%0A%2F%2F+Remember+in+Rust+that%3A%0A%2F%2F+-+the+%60if%60+condition+does+not+need+to+be+surrounded+by+parentheses%0A%2F%2F+-+%60if%60%2F%60else%60+conditionals+are+expressions%0A%2F%2F+-+Each+condition+is+followed+by+a+%60%7B%7D%60+block.%0A) - -### Strings - -[Relevant chapter in The Rust Programming -Language](https://doc.rust-lang.org/book/second-edition/ch08-02-strings.html) - -- ["strings1.rs"](https://play.rust-lang.org/?code=%2F%2F+strings1.rs%0A%2F%2F+Make+me+compile+without+changing+the+function+signature%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+answer+%3D+current_favorite_color%28%29%3B%0A++++println%21%28%22My+current+favorite+color+is+%7B%7D%22%2C+answer%29%3B%0A%7D%0A%0Afn+current_favorite_color%28%29+-%3E+String+%7B%0A++++%22blue%22%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+The+%60current_favorite_color%60+function+is+currently+returning+a+string+slice+with+the+%60%27static%60%0A%2F%2F+lifetime.+We+know+this+because+the+data+of+the+string+lives+in+our+code+itself+--+it+doesn%27t%0A%2F%2F+come+from+a+file+or+user+input+or+another+program+--+so+it+will+live+as+long+as+our+program%0A%2F%2F+lives.+But+it+is+still+a+string+slice.+There%27s+one+way+to+create+a+%60String%60+by+converting+a%0A%2F%2F+string+slice+covered+in+the+Strings+chapter+of+the+book%2C+and+another+way+that+uses+the+%60From%60%0A%2F%2F+trait.%0A) -- ["strings2.rs"](https://play.rust-lang.org/?code=%2F%2F+strings2.rs%0A%2F%2F+Make+me+compile+without+changing+the+function+signature%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+word+%3D+String%3A%3Afrom%28%22green%22%29%3B+%2F%2F+Try+not+changing+this+line+%3A%29%0A++++if+is_a_color_word%28word%29+%7B%0A++++++++println%21%28%22That+is+a+color+word+I+know%21%22%29%3B%0A++++%7D+else+%7B%0A++++++++println%21%28%22That+is+not+a+color+word+I+know.%22%29%3B%0A++++%7D%0A%7D%0A%0Afn+is_a_color_word%28attempt%3A+%26str%29+-%3E+bool+%7B%0A++++attempt+%3D%3D+%22green%22+%7C%7C+attempt+%3D%3D+%22blue%22+%7C%7C+attempt+%3D%3D+%22red%22%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Yes%2C+it+would+be+really+easy+to+fix+this+by+just+changing+the+value+bound+to+%60word%60+to+be+a%0A%2F%2F+string+slice+instead+of+a+%60String%60%2C+wouldn%27t+it%3F%3F+There+is+a+way+to+add+one+character+to+line%0A%2F%2F+6%2C+though%2C+that+will+coerce+the+%60String%60+into+a+string+slice.%0A) -- ["strings3.rs"](https://play.rust-lang.org/?code=%2F%2F+strings3.rs%0A%2F%2F+Ok%2C+here+are+a+bunch+of+values--+some+are+%60Strings%60%2C+some+are+%60%26strs%60.+Your%0A%2F%2F+task+is+to+call+one+of+these+two+functions+on+each+value+depending+on+what%0A%2F%2F+you+think+each+value+is.+That+is%2C+add+either+%60string_slice%60+or+%60string%60%0A%2F%2F+before+the+parentheses+on+each+line.+If+you%27re+right%2C+it+will+compile%21%0A%0Afn+string_slice%28arg%3A+%26str%29+%7B+println%21%28%22%7B%7D%22%2C+arg%29%3B+%7D%0Afn+string%28arg%3A+String%29+%7B+println%21%28%22%7B%7D%22%2C+arg%29%3B+%7D%0A%0Afn+main%28%29+%7B%0A++++%28%22blue%22%29%3B%0A++++%28%22red%22.to_string%28%29%29%3B%0A++++%28String%3A%3Afrom%28%22hi%22%29%29%3B%0A++++%28%22rust+is+fun%21%22.to_owned%28%29%29%3B%0A++++%28%22nice+weather%22.into%28%29%29%3B%0A++++%28format%21%28%22Interpolation+%7B%7D%22%2C+%22Station%22%29%29%3B%0A++++%28%26String%3A%3Afrom%28%22abc%22%29%5B0..1%5D%29%3B%0A++++%28%22++hello+there+%22.trim%28%29%29%3B%0A++++%28%22Happy+Monday%21%22.to_string%28%29.replace%28%22Mon%22%2C+%22Tues%22%29%29%3B%0A++++%28%22mY+sHiFt+KeY+iS+sTiCkY%22.to_lowercase%28%29%29%3B%0A%7D%0A) - -### 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 :) - -- ["move_semantics1.rs"](https://play.rust-lang.org/?code=%2F%2F+move_semantics1.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Apub+fn+main%28%29+%7B%0A++++let+vec0+%3D+Vec%3A%3Anew%28%29%3B%0A%0A++++let+vec1+%3D+fill_vec%28vec0%29%3B%0A%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec1%22%2C+vec1.len%28%29%2C+vec1%29%3B%0A%0A++++vec1.push%2888%29%3B%0A%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec1%22%2C+vec1.len%28%29%2C+vec1%29%3B%0A%0A%7D%0A%0Afn+fill_vec%28vec%3A+Vec%3Ci32%3E%29+-%3E+Vec%3Ci32%3E+%7B%0A++++let+mut+vec+%3D+vec%3B%0A%0A++++vec.push%2822%29%3B%0A++++vec.push%2844%29%3B%0A++++vec.push%2866%29%3B%0A%0A++++vec%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+So+you%27ve+got+the+%22cannot+borrow+immutable+local+variable+%60vec1%60+as+mutable%22+error+on+line+11%2C%0A%2F%2F+right%3F+The+fix+for+this+is+going+to+be+adding+one+keyword%2C+and+the+addition+is+NOT+on+line+11%0A%2F%2F+where+the+error+is.%0A) -- ["move_semantics2.rs"](https://play.rust-lang.org/?code=%2F%2F+move_semantics2.rs%0A%2F%2F+Make+me+compile+without+changing+line+10%21+Scroll+down+for+hints+%3A%29%0A%0Apub+fn+main%28%29+%7B%0A++++let+vec0+%3D+Vec%3A%3Anew%28%29%3B%0A%0A++++let+mut+vec1+%3D+fill_vec%28vec0%29%3B%0A%0A++++%2F%2F+Do+not+change+the+following+line%21%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec0%22%2C+vec0.len%28%29%2C+vec0%29%3B%0A%0A++++vec1.push%2888%29%3B%0A%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec1%22%2C+vec1.len%28%29%2C+vec1%29%3B%0A%0A%7D%0A%0Afn+fill_vec%28vec%3A+Vec%3Ci32%3E%29+-%3E+Vec%3Ci32%3E+%7B%0A++++let+mut+vec+%3D+vec%3B%0A%0A++++vec.push%2822%29%3B%0A++++vec.push%2844%29%3B%0A++++vec.push%2866%29%3B%0A%0A++++vec%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+So+%60vec0%60+is+being+*moved*+into+the+function+%60fill_vec%60+when+we+call+it+on%0A%2F%2F+line+7%2C+which+means+it+gets+dropped+at+the+end+of+%60fill_vec%60%2C+which+means+we%0A%2F%2F+can%27t+use+%60vec0%60+again+on+line+10+%28or+anywhere+else+in+%60main%60+after+the%0A%2F%2F+%60fill_vec%60+call+for+that+matter%29.+We+could+fix+this+in+a+few+ways%2C+try+them%0A%2F%2F+all%21%0A%2F%2F+1.+Make+another%2C+separate+version+of+the+data+that%27s+in+%60vec0%60+and+pass+that%0A%2F%2F+to+%60fill_vec%60+instead.%0A%2F%2F+2.+Make+%60fill_vec%60+borrow+its+argument+instead+of+taking+ownership+of+it%2C%0A%2F%2F+and+then+copy+the+data+within+the+function+in+order+to+return+an+owned%0A%2F%2F+%60Vec%3Ci32%3E%60%0A%2F%2F+3.+Make+%60fill_vec%60+*mutably*+borrow+its+argument+%28which+will+need+to+be%0A%2F%2F+mutable%29%2C+modify+it+directly%2C+then+not+return+anything.+Then+you+can+get+rid%0A%2F%2F+of+%60vec1%60+entirely+--+note+that+this+will+change+what+gets+printed+by+the%0A%2F%2F+first+%60println%21%60%0A) -- ["move_semantics3.rs"](https://play.rust-lang.org/?code=%2F%2F+move_semantics3.rs%0A%2F%2F+Make+me+compile+without+adding+new+lines--+just+changing+existing+lines%21%0A%2F%2F+%28no+lines+with+multiple+semicolons+necessary%21%29%0A%2F%2F+Scroll+down+for+hints+%3A%29%0A%0Apub+fn+main%28%29+%7B%0A++++let+vec0+%3D+Vec%3A%3Anew%28%29%3B%0A%0A++++let+mut+vec1+%3D+fill_vec%28vec0%29%3B%0A%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec1%22%2C+vec1.len%28%29%2C+vec1%29%3B%0A%0A++++vec1.push%2888%29%3B%0A%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec1%22%2C+vec1.len%28%29%2C+vec1%29%3B%0A%0A%7D%0A%0Afn+fill_vec%28vec%3A+Vec%3Ci32%3E%29+-%3E+Vec%3Ci32%3E+%7B%0A++++vec.push%2822%29%3B%0A++++vec.push%2844%29%3B%0A++++vec.push%2866%29%3B%0A%0A++++vec%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+The+difference+between+this+one+and+the+previous+ones+is+that+the+first+line%0A%2F%2F+of+%60fn+fill_vec%60+that+had+%60let+mut+vec+%3D+vec%3B%60+is+no+longer+there.+You+can%2C%0A%2F%2F+instead+of+adding+that+line+back%2C+add+%60mut%60+in+one+place+that+will+change%0A%2F%2F+an+existing+binding+to+be+a+mutable+binding+instead+of+an+immutable+one+%3A%29%0A) -- ["move_semantics4.rs"](https://play.rust-lang.org/?code=%2F%2F+move_semantics4.rs%0A%2F%2F+Refactor+this+code+so+that+instead+of+having+%60vec0%60+and+creating+the+vector%0A%2F%2F+in+%60fn+main%60%2C+we+instead+create+it+within+%60fn+fill_vec%60+and+transfer+the%0A%2F%2F+freshly+created+vector+from+fill_vec+to+its+caller.+Scroll+for+hints%21%0A%0Apub+fn+main%28%29+%7B%0A++++let+vec0+%3D+Vec%3A%3Anew%28%29%3B%0A%0A++++let+mut+vec1+%3D+fill_vec%28vec0%29%3B%0A%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec1%22%2C+vec1.len%28%29%2C+vec1%29%3B%0A%0A++++vec1.push%2888%29%3B%0A%0A++++println%21%28%22%7B%7D+has+length+%7B%7D+content+%60%7B%3A%3F%7D%60%22%2C+%22vec1%22%2C+vec1.len%28%29%2C+vec1%29%3B%0A%0A%7D%0A%0Afn+fill_vec%28vec%3A+Vec%3Ci32%3E%29+-%3E+Vec%3Ci32%3E+%7B%0A++++let+mut+vec+%3D+vec%3B%0A%0A++++vec.push%2822%29%3B%0A++++vec.push%2844%29%3B%0A++++vec.push%2866%29%3B%0A%0A++++vec%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Stop+reading+whenever+you+feel+like+you+have+enough+direction+%3A%29+Or+try%0A%2F%2F+doing+one+step+and+then+fixing+the+compiler+errors+that+result%21%0A%2F%2F+So+the+end+goal+is+to%3A%0A%2F%2F+-+get+rid+of+the+first+line+in+main+that+creates+the+new+vector%0A%2F%2F+-+so+then+%60vec0%60+doesn%27t+exist%2C+so+we+can%27t+pass+it+to+%60fill_vec%60%0A%2F%2F+-+we+don%27t+want+to+pass+anything+to+%60fill_vec%60%2C+so+its+signature+should%0A%2F%2F+++reflect+that+it+does+not+take+any+arguments%0A%2F%2F+-+since+we%27re+not+creating+a+new+vec+in+%60main%60+anymore%2C+we+need+to+create%0A%2F%2F+++a+new+vec+in+%60fill_vec%60%2C+similarly+to+the+way+we+did+in+%60main%60%0A) - -### Modules - -[Relevant chapter in The Rust Programming -Language](https://doc.rust-lang.org/book/second-edition/ch07-01-mod-and-the-filesystem.html) - -- ["modules1.rs"](https://play.rust-lang.org/?code=%2F%2F+modules1.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Amod+sausage_factory+%7B%0A++++fn+make_sausage%28%29+%7B%0A++++++++println%21%28%22sausage%21%22%29%3B%0A++++%7D%0A%7D%0A%0Afn+main%28%29+%7B%0A++++sausage_factory%3A%3Amake_sausage%28%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Everything+is+private+in+Rust+by+default--+but+there%27s+a+keyword+we+can+use%0A%2F%2F+to+make+something+public%21+The+compiler+error+should+point+to+the+thing+that%0A%2F%2F+needs+to+be+public.%0A) -- ["modules2.rs"](https://play.rust-lang.org/?code=%2F%2F+modules2.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Amod+us_presidential_frontrunners+%7B%0A++++use+self%3A%3Ademocrats%3A%3AHILLARY_CLINTON+as+democrat%3B%0A++++use+self%3A%3Arepublicans%3A%3ADONALD_TRUMP+as+republican%3B%0A%0A++++mod+democrats+%7B%0A++++++++pub+const+HILLARY_CLINTON%3A+%26%27static+str+%3D+%22Hillary+Clinton%22%3B%0A++++++++pub+const+BERNIE_SANDERS%3A+%26%27static+str+%3D+%22Bernie+Sanders%22%3B%0A++++%7D%0A%0A++++mod+republicans+%7B%0A++++++++pub+const+DONALD_TRUMP%3A+%26%27static+str+%3D+%22Donald+Trump%22%3B%0A++++++++pub+const+JEB_BUSH%3A+%26%27static+str+%3D+%22Jeb+Bush%22%3B%0A++++%7D%0A%7D%0A%0Afn+main%28%29+%7B%0A++++println%21%28%22candidates%3A+%7B%7D+and+%7B%7D%22%2C%0A+++++++++++++us_presidential_frontrunners%3A%3Ademocrat%2C%0A+++++++++++++us_presidential_frontrunners%3A%3Arepublican%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+The+us_presidential_frontrunners+module+is+trying+to+present+an+external%0A%2F%2F+interface+%28the+%60democrat%60+and+%60republican%60+constants%29+that+is+different+than%0A%2F%2F+its+internal+structure+%28the+%60democrats%60+and+%60republicans%60+modules+and%0A%2F%2F+associated+constants%29.+It%27s+almost+there+except+for+one+keyword+missing+for%0A%2F%2F+each+constant.%0A) - -### 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) - -- ["macros1.rs"](https://play.rust-lang.org/?code=%2F%2F+macros1.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Amacro_rules%21+my_macro+%7B%0A++++%28%29+%3D%3E+%7B%0A++++++++println%21%28%22Check+out+my+macro%21%22%29%3B%0A++++%7D%3B%0A%7D%0A%0Afn+main%28%29+%7B%0A++++my_macro%28%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+When+you+call+a+macro%2C+you+need+to+add+something+special+compared+to+a%0A%2F%2F+regular+function+call.+If+you%27re+stuck%2C+take+a+look+at+what%27s+inside%0A%2F%2F+%60my_macro%60.%0A) -- ["macros2.rs"](https://play.rust-lang.org/?code=%2F%2F+macros2.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++my_macro%21%28%29%3B%0A%7D%0A%0Amacro_rules%21+my_macro+%7B%0A++++%28%29+%3D%3E+%7B%0A++++++++println%21%28%22Check+out+my+macro%21%22%29%3B%0A++++%7D%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Macros+don%27t+quite+play+by+the+same+rules+as+the+rest+of+Rust%2C+in+terms+of%0A%2F%2F+what%27s+available+where.%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Unlike+other+things+in+Rust%2C+the+order+of+%22where+you+define+a+macro%22+versus%0A%2F%2F+%22where+you+use+it%22+actually+matters.%0A) -- ["macros3.rs"](https://play.rust-lang.org/?code=%2F%2F+macros3.rs%0A%2F%2F+Make+me+compile%2C+without+taking+the+macro+out+of+the+module%21+Scroll+down+for+hints+%3A%29%0A%0Amod+macros+%7B%0A++++macro_rules%21+my_macro+%7B%0A++++++++%28%29+%3D%3E+%7B%0A++++++++++++println%21%28%22Check+out+my+macro%21%22%29%3B%0A++++++++%7D%3B%0A++++%7D%0A%7D%0A%0Afn+main%28%29+%7B%0A++++my_macro%21%28%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+In+order+to+use+a+macro+outside+of+its+module%2C+you+need+to+do+something%0A%2F%2F+special+to+the+module+to+lift+the+macro+out+into+its+parent.%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+The+same+trick+also+works+on+%22extern+crate%22+statements+for+crates+that+have%0A%2F%2F+exported+macros%2C+if+you%27ve+seen+any+of+those+around.%0A) -- ["macros4.rs"](https://play.rust-lang.org/?code=%2F%2F+macros4.rs%0A%2F%2F+Make+me+compile%21+Scroll+down+for+hints+%3A%29%0A%0Amacro_rules%21+my_macro+%7B%0A++++%28%29+%3D%3E+%7B%0A++++++++println%21%28%22Check+out+my+macro%21%22%29%3B%0A++++%7D%0A++++%28%24val%3Aexpr%29+%3D%3E+%7B%0A++++++++println%21%28%22Look+at+this+other+macro%3A+%7B%7D%22%2C+%24val%29%3B%0A++++%7D%0A%7D%0A%0Afn+main%28%29+%7B%0A++++my_macro%21%28%29%3B%0A++++my_macro%21%287777%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+You+only+need+to+add+a+single+character+to+make+this+compile.%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+The+way+macros+are+written%2C+it+wants+to+see+something+between+each%0A%2F%2F+%22macro+arm%22%2C+so+it+can+separate+them.%0A) - -### 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. - -- ["option1.rs"](https://play.rust-lang.org/?code=%2F%2F+option1.rs%0A%2F%2F+This+example+panics+because+the+second+time+it+calls+%60pop%60%2C+the+%60vec%60%0A%2F%2F+is+empty%2C+so+%60pop%60+returns+%60None%60%2C+and+%60unwrap%60+panics+if+it%27s+called%0A%2F%2F+on+%60None%60.+Handle+this+in+a+more+graceful+way+than+calling+%60unwrap%60%21%0A%2F%2F+Scroll+down+for+hints+%3A%29%0A%0Afn+main%28%29+%7B%0A++++let+mut+list+%3D+vec%21%5B3%5D%3B%0A%0A++++let+last+%3D+list.pop%28%29.unwrap%28%29%3B%0A++++println%21%28%22The+last+item+in+the+list+is+%7B%3A%3F%7D%22%2C+last%29%3B%0A%0A++++let+second_to_last+%3D+list.pop%28%29.unwrap%28%29%3B%0A++++println%21%28%22The+second-to-last+item+in+the+list+is+%7B%3A%3F%7D%22%2C+second_to_last%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Try+using+a+%60match%60+statement+where+the+arms+are+%60Some%28thing%29%60+and+%60None%60.%0A%2F%2F+Or+set+a+default+value+to+print+out+if+you+get+%60None%60+by+using+the%0A%2F%2F+function+%60unwrap_or%60.%0A%2F%2F+Or+use+an+%60if+let%60+statement+on+the+result+of+%60pop%28%29%60+to+both+destructure%0A%2F%2F+a+%60Some%60+value+and+only+print+out+something+if+we+have+a+value%21%0A) -- ["result1.rs"](https://play.rust-lang.org/?code=%2F%2F+result1.rs%0A%2F%2F+Make+this+test+pass%21+Scroll+down+for+hints+%3A%29%0A%0A%23%5Bderive%28PartialEq%2CDebug%29%5D%0Astruct+PositiveNonzeroInteger%28u64%29%3B%0A%0A%23%5Bderive%28PartialEq%2CDebug%29%5D%0Aenum+CreationError+%7B%0A++++Negative%2C%0A++++Zero%2C%0A%7D%0A%0Aimpl+PositiveNonzeroInteger+%7B%0A++++fn+new%28value%3A+i64%29+-%3E+Result%3CPositiveNonzeroInteger%2C+CreationError%3E+%7B%0A++++++++Ok%28PositiveNonzeroInteger%28value+as+u64%29%29%0A++++%7D%0A%7D%0A%0A%23%5Btest%5D%0Afn+test_creation%28%29+%7B%0A++++assert%21%28PositiveNonzeroInteger%3A%3Anew%2810%29.is_ok%28%29%29%3B%0A++++assert_eq%21%28Err%28CreationError%3A%3ANegative%29%2C+PositiveNonzeroInteger%3A%3Anew%28-10%29%29%3B%0A++++assert_eq%21%28Err%28CreationError%3A%3AZero%29%2C+PositiveNonzeroInteger%3A%3Anew%280%29%29%3B%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+%60PositiveNonzeroInteger%3A%3Anew%60+is+always+creating+a+new+instance+and+returning+an+%60Ok%60+result.%0A%2F%2F+It+should+be+doing+some+checking%2C+returning+an+%60Err%60+result+if+those+checks+fail%2C+and+only%0A%2F%2F+returning+an+%60Ok%60+result+if+those+checks+determine+that+everything+is...+okay+%3A%29%0A) -- ["errors1.rs"](https://play.rust-lang.org/?code=%2F%2F+errors1.rs%0A%2F%2F+This+function+refuses+to+generate+text+to+be+printed+on+a+nametag+if%0A%2F%2F+you+pass+it+an+empty+string.+It%27d+be+nicer+if+it+explained+what+the+problem%0A%2F%2F+was%2C+instead+of+just+sometimes+returning+%60None%60.+The+2nd+test+currently%0A%2F%2F+does+not+compile+or+pass%2C+but+it+illustrates+the+behavior+we+would+like%0A%2F%2F+this+function+to+have.%0A%2F%2F+Scroll+down+for+hints%21%21%21%0A%0Apub+fn+generate_nametag_text%28name%3A+String%29+-%3E+Option%3CString%3E+%7B%0A++++if+name.len%28%29+%3E+0+%7B%0A++++++++Some%28format%21%28%22Hi%21+My+name+is+%7B%7D%22%2C+name%29%29%0A++++%7D+else+%7B%0A++++++++%2F%2F+Empty+names+aren%27t+allowed.%0A++++++++None%0A++++%7D%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%2F%2F+This+test+passes+initially+if+you+comment+out+the+2nd+test.%0A++++%2F%2F+You%27ll+need+to+update+what+this+test+expects+when+you+change%0A++++%2F%2F+the+function+under+test%21%0A++++%23%5Btest%5D%0A++++fn+generates_nametag_text_for_a_nonempty_name%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++generate_nametag_text%28%22Beyonc%C3%A9%22.into%28%29%29%2C%0A++++++++++++Some%28%22Hi%21+My+name+is+Beyonc%C3%A9%22.into%28%29%29%0A++++++++%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+explains_why_generating_nametag_text_fails%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++generate_nametag_text%28%22%22.into%28%29%29%2C%0A++++++++++++Err%28%22%60name%60+was+empty%3B+it+must+be+nonempty.%22.into%28%29%29%0A++++++++%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+%60Err%60+is+one+of+the+variants+of+%60Result%60%2C+so+what+the+2nd+test+is+saying%0A%2F%2F+is+that+%60generate_nametag_text%60+should+return+a+%60Result%60+instead+of+an%0A%2F%2F+%60Option%60.%0A%0A%2F%2F+To+make+this+change%2C+you%27ll+need+to%3A%0A%2F%2F+-+update+the+return+type+in+the+function+signature+to+be+a+Result+that%0A%2F%2F+++could+be+the+variants+%60Ok%28String%29%60+and+%60Err%28String%29%60%0A%2F%2F+-+change+the+body+of+the+function+to+return+%60Ok%28stuff%29%60+where+it+currently%0A%2F%2F+++returns+%60Some%28stuff%29%60%0A%2F%2F+-+change+the+body+of+the+function+to+return+%60Err%28error+message%29%60+where+it%0A%2F%2F+++currently+returns+%60None%60%0A%2F%2F+-+change+the+first+test+to+expect+%60Ok%28stuff%29%60+where+it+currently+expects%0A%2F%2F+++%60Some%28stuff%29%60.%0A) -- ["errors2.rs"](https://play.rust-lang.org/?code=%2F%2F+errors2.rs%0A%2F%2F+Say+we%27re+writing+a+game+where+you+can+buy+items+with+tokens.+All+items+cost%0A%2F%2F+5+tokens%2C+and+whenever+you+purchase+items+there+is+a+processing+fee+of+1%0A%2F%2F+token.+A+player+of+the+game+will+type+in+how+many+items+they+want+to+buy%2C%0A%2F%2F+and+the+%60total_cost%60+function+will+calculate+the+total+number+of+tokens.%0A%2F%2F+Since+the+player+typed+in+the+quantity%2C+though%2C+we+get+it+as+a+string--+and%0A%2F%2F+they+might+have+typed+anything%2C+not+just+numbers%21%0A%0A%2F%2F+Right+now%2C+this+function+isn%27t+handling+the+error+case+at+all+%28and+isn%27t%0A%2F%2F+handling+the+success+case+properly+either%29.+What+we+want+to+do+is%3A%0A%2F%2F+if+we+call+the+%60parse%60+function+on+a+string+that+is+not+a+number%2C+that%0A%2F%2F+function+will+return+a+%60ParseIntError%60%2C+and+in+that+case%2C+we+want+to%0A%2F%2F+immediately+return+that+error+from+our+function+and+not+try+to+multiply%0A%2F%2F+and+add.%0A%0A%2F%2F+There+are+at+least+two+ways+to+implement+this+that+are+both+correct--+but%0A%2F%2F+one+is+a+lot+shorter%21+Scroll+down+for+hints+to+both+ways.%0A%0Ause+std%3A%3Anum%3A%3AParseIntError%3B%0A%0Apub+fn+total_cost%28item_quantity%3A+%26str%29+-%3E+Result%3Ci32%2C+ParseIntError%3E+%7B%0A++++let+processing_fee+%3D+1%3B%0A++++let+cost_per_item+%3D+5%3B%0A++++let+qty+%3D+item_quantity.parse%3A%3A%3Ci32%3E%28%29%3B%0A%0A++++Ok%28qty+*+cost_per_item+%2B+processing_fee%29%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%23%5Btest%5D%0A++++fn+item_quantity_is_a_valid_number%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++total_cost%28%2234%22%29%2C%0A++++++++++++Ok%28171%29%0A++++++++%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+item_quantity_is_an_invalid_number%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++total_cost%28%22beep+boop%22%29.unwrap_err%28%29.to_string%28%29%2C%0A++++++++++++%22invalid+digit+found+in+string%22%0A++++++++%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+One+way+to+handle+this+is+using+a+%60match%60+statement+on%0A%2F%2F+%60item_quantity.parse%3A%3A%3Ci32%3E%28%29%60+where+the+cases+are+%60Ok%28something%29%60+and%0A%2F%2F+%60Err%28something%29%60.+This+pattern+is+very+common+in+Rust%2C+though%2C+so+there%27s%0A%2F%2F+a+%60try%21%60+macro+that+does+pretty+much+what+you+would+make+that+match+statement%0A%2F%2F+do+for+you%21+Take+a+look+at+this+section+of+the+Error+Handling+chapter%3A%0A%2F%2F+https%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Ferror-handling.html%23the-try-macro%0A%2F%2F+and+give+it+a+%60try%21%60%0A) -- ["errors3.rs"](https://play.rust-lang.org/?code=%2F%2F+errors3.rs%0A%2F%2F+This+is+a+program+that+is+trying+to+use+a+completed+version+of+the%0A%2F%2F+%60total_cost%60+function+from+the+previous+exercise.+It%27s+not+working+though--%0A%2F%2F+we+can%27t+call+the+%60try%21%60+macro+in+the+%60main%28%29%60+function%21+Why+not%3F%0A%2F%2F+What+should+we+do+instead%3F+Scroll+for+hints%21%0A%0Ause+std%3A%3Anum%3A%3AParseIntError%3B%0A%0Afn+main%28%29+%7B%0A++++let+mut+tokens+%3D+100%3B%0A++++let+pretend_user_input+%3D+%228%22%3B%0A%0A++++let+cost+%3D+try%21%28total_cost%28pretend_user_input%29%29%3B%0A%0A++++if+cost+%3E+tokens+%7B%0A++++++++println%21%28%22You+can%27t+afford+that+many%21%22%29%3B%0A++++%7D+else+%7B%0A++++++++tokens+-%3D+cost%3B%0A++++++++println%21%28%22You+now+have+%7B%7D+tokens.%22%2C+tokens%29%3B%0A++++%7D%0A%7D%0A%0Apub+fn+total_cost%28item_quantity%3A+%26str%29+-%3E+Result%3Ci32%2C+ParseIntError%3E+%7B%0A++++let+processing_fee+%3D+1%3B%0A++++let+cost_per_item+%3D+5%3B%0A++++let+qty+%3D+try%21%28item_quantity.parse%3A%3A%3Ci32%3E%28%29%29%3B%0A%0A++++Ok%28qty+*+cost_per_item+%2B+processing_fee%29%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Since+the+%60try%21%60+macro+returns+an+%60Err%60+early+if+the+thing+it%27s+trying+to%0A%2F%2F+do+fails%2C+you+can+only+use+the+%60try%21%60+macro+in+functions+that+have+a%0A%2F%2F+%60Result%60+as+their+return+type.%0A%0A%2F%2F+The+error+that+you+get+if+you+run+this+code+is%3A%0A%0A%2F%2F+%60%60%60%0A%2F%2F+error%3A+mismatched+types%3A%0A%2F%2F+expected+%60%28%29%60%2C%0A%2F%2F+found+%60std%3A%3Aresult%3A%3AResult%3C_%2C+_%3E%60%0A%2F%2F+%60%60%60%0A%0A%2F%2F+which+is+saying+that+the+expected+return+type+of+the+%60main%60+function+is%0A%2F%2F+the+empty+tuple%2C+but+we+tried+to+return+a+%60Result%60--+and+that%27s+happening%0A%2F%2F+in+the+implementation+of+%60try%21%60.+The+%60main%60+function+never+has+a+return+type%2C%0A%2F%2F+so+we+have+to+use+another+way+of+handling+a+%60Result%60+within+%60main%60.%0A%0A%2F%2F+Decide+what+we+should+do+if+%60pretend_user_input%60+has+a+string+value+that+does%0A%2F%2F+not+parse+to+an+integer%2C+and+implement+that+instead+of+calling+the+%60try%21%60%0A%2F%2F+macro.%0A) -- ["errorsn.rs"](https://play.rust-lang.org/?code=%2F%2F+errorsn.rs%0A%2F%2F+This+is+a+bigger+error+exercise+than+the+previous+ones%21%0A%2F%2F+You+can+do+it%21+%3A%29%0A%2F%2F%0A%2F%2F+Edit+the+%60read_and_validate%60+function+so+that+it+compiles+and%0A%2F%2F+passes+the+tests...+so+many+things+could+go+wrong%21%0A%2F%2F%0A%2F%2F+-+Reading+from+stdin+could+produce+an+io%3A%3AError%0A%2F%2F+-+Parsing+the+input+could+produce+a+num%3A%3AParseIntError%0A%2F%2F+-+Validating+the+input+could+produce+a+CreationError+%28defined+below%29%0A%2F%2F%0A%2F%2F+How+can+we+lump+these+errors+into+one+general+error%3F+That+is%2C+what%0A%2F%2F+type+goes+where+the+question+marks+are%2C+and+how+do+we+return%0A%2F%2F+that+type+from+the+body+of+read_and_validate%3F%0A%2F%2F%0A%2F%2F+Scroll+down+for+hints+%3A%29%0A%0Ause+std%3A%3Aerror%3B%0Ause+std%3A%3Afmt%3B%0Ause+std%3A%3Aio%3B%0A%0A%2F%2F+PositiveNonzeroInteger+is+a+struct+defined+below+the+tests.%0Afn+read_and_validate%28b%3A+%26mut+io%3A%3ABufRead%29+-%3E+Result%3CPositiveNonzeroInteger%2C+%3F%3F%3F%3E+%7B%0A++++let+mut+line+%3D+String%3A%3Anew%28%29%3B%0A++++b.read_line%28%26mut+line%29%3B%0A++++let+num%3A+i64+%3D+line.trim%28%29.parse%28%29%3B%0A++++let+answer+%3D+PositiveNonzeroInteger%3A%3Anew%28num%29%3B%0A++++answer%0A%7D%0A%0A%2F%2F+This+is+a+test+helper+function+that+turns+a+%26str+into+a+BufReader.%0Afn+test_with_str%28s%3A+%26str%29+-%3E+Result%3CPositiveNonzeroInteger%2C+Box%3Cerror%3A%3AError%3E%3E+%7B%0A++++let+mut+b+%3D+io%3A%3ABufReader%3A%3Anew%28s.as_bytes%28%29%29%3B%0A++++read_and_validate%28%26mut+b%29%0A%7D%0A%0A%23%5Btest%5D%0Afn+test_success%28%29+%7B%0A++++let+x+%3D+test_with_str%28%2242%5Cn%22%29%3B%0A++++assert_eq%21%28PositiveNonzeroInteger%2842%29%2C+x.unwrap%28%29%29%3B%0A%7D%0A%0A%23%5Btest%5D%0Afn+test_not_num%28%29+%7B%0A++++let+x+%3D+test_with_str%28%22eleven+billion%5Cn%22%29%3B%0A++++assert%21%28x.is_err%28%29%29%3B%0A%7D%0A%0A%23%5Btest%5D%0Afn+test_non_positive%28%29+%7B%0A++++let+x+%3D+test_with_str%28%22-40%5Cn%22%29%3B%0A++++assert%21%28x.is_err%28%29%29%3B%0A%7D%0A%0A%23%5Btest%5D%0Afn+test_ioerror%28%29+%7B%0A++++struct+Broken%3B%0A++++impl+io%3A%3ARead+for+Broken+%7B%0A++++++++fn+read%28%26mut+self%2C+_buf%3A+%26mut+%5Bu8%5D%29+-%3E+io%3A%3AResult%3Cusize%3E+%7B%0A++++++++++++Err%28io%3A%3AError%3A%3Anew%28io%3A%3AErrorKind%3A%3ABrokenPipe%2C+%22uh-oh%21%22%29%29%0A++++++++%7D%0A++++%7D%0A++++let+mut+b+%3D+io%3A%3ABufReader%3A%3Anew%28Broken%29%3B%0A++++assert%21%28read_and_validate%28%26mut+b%29.is_err%28%29%29%3B%0A++++assert_eq%21%28%22uh-oh%21%22%2C+read_and_validate%28%26mut+b%29.unwrap_err%28%29.to_string%28%29%29%3B%0A%7D%0A%0A%23%5Bderive%28PartialEq%2CDebug%29%5D%0Astruct+PositiveNonzeroInteger%28u64%29%3B%0A%0Aimpl+PositiveNonzeroInteger+%7B%0A++++fn+new%28value%3A+i64%29+-%3E+Result%3CPositiveNonzeroInteger%2C+CreationError%3E+%7B%0A++++++++if+value+%3D%3D+0+%7B%0A++++++++++++Err%28CreationError%3A%3AZero%29%0A++++++++%7D+else+if+value+%3C+0+%7B%0A++++++++++++Err%28CreationError%3A%3ANegative%29%0A++++++++%7D+else+%7B%0A++++++++++++Ok%28PositiveNonzeroInteger%28value+as+u64%29%29%0A++++++++%7D%0A++++%7D%0A%7D%0A%0A%23%5Btest%5D%0Afn+test_positive_nonzero_integer_creation%28%29+%7B%0A++++assert%21%28PositiveNonzeroInteger%3A%3Anew%2810%29.is_ok%28%29%29%3B%0A++++assert_eq%21%28Err%28CreationError%3A%3ANegative%29%2C+PositiveNonzeroInteger%3A%3Anew%28-10%29%29%3B%0A++++assert_eq%21%28Err%28CreationError%3A%3AZero%29%2C+PositiveNonzeroInteger%3A%3Anew%280%29%29%3B%0A%7D%0A%0A%23%5Bderive%28PartialEq%2CDebug%29%5D%0Aenum+CreationError+%7B%0A++++Negative%2C%0A++++Zero%2C%0A%7D%0A%0Aimpl+fmt%3A%3ADisplay+for+CreationError+%7B%0A++++fn+fmt%28%26self%2C+f%3A+%26mut+fmt%3A%3AFormatter%29+-%3E+fmt%3A%3AResult+%7B%0A++++++++f.write_str%28%28self+as+%26error%3A%3AError%29.description%28%29%29%0A++++%7D%0A%7D%0A%0Aimpl+error%3A%3AError+for+CreationError+%7B%0A++++fn+description%28%26self%29+-%3E+%26str+%7B%0A++++++++match+*self+%7B%0A++++++++++++CreationError%3A%3ANegative+%3D%3E+%22Negative%22%2C%0A++++++++++++CreationError%3A%3AZero+%3D%3E+%22Zero%22%2C%0A++++++++%7D%0A++++%7D%0A%7D%0A%0A%2F%2F+First+hint%3A+To+figure+out+what+type+should+go+where+the+%3F%3F%3F+is%2C+take+a+look%0A%2F%2F+at+the+test+helper+function+%60test_with_str%60%2C+since+it+returns+whatever%0A%2F%2F+%60read_and_validate%60+returns+and%60test_with_str%60+has+its+signature+fully%0A%2F%2F+specified.%0A%0A%2F%2F+Next+hint%3A+There+are+three+places+in+%60read_and_validate%60+that+we+call+a%0A%2F%2F+function+that+returns+a+%60Result%60+%28that+is%2C+the+functions+might+fail%29.%0A%2F%2F+Wrap+those+calls+in+a+%60try%21%60+macro+call+so+that+we+return+immediately+from%0A%2F%2F+%60read_and_validate%60+if+those+function+calls+fail.%0A%0A%2F%2F+Another+hint%3A+under+the+hood%2C+the+%60try%21%60+macro+calls+%60From%3A%3Afrom%60%0A%2F%2F+on+the+error+value+to+convert+it+to+a+boxed+trait+object%2C+a+Box%3Cerror%3A%3AError%3E%2C%0A%2F%2F+which+is+polymorphic--+that+means+that+lots+of+different+kinds+of+errors%0A%2F%2F+can+be+returned+from+the+same+function+because+all+errors+act+the+same%0A%2F%2F+since+they+all+implement+the+%60error%3A%3AError%60+trait.%0A%2F%2F+Check+out+this+section+of+the+book%3A%0A%2F%2F+https%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Ferror-handling.html%23standard-library-traits-used-for-error-handling%0A%0A%2F%2F+Another+another+hint%3A+Note+that+because+the+%60try%21%60+macro+returns%0A%2F%2F+the+*unwrapped*+value+in+the+%60Ok%60+case%2C+if+we+want+to+return+a+%60Result%60+from%0A%2F%2F+%60read_and_validate%60+for+*its*+success+case%2C+we%27ll+have+to+rewrap+a+value%0A%2F%2F+that+we+got+from+the+return+value+of+a+%60try%21%60+call+in+an+%60Ok%60--+this+will%0A%2F%2F+look+like+%60Ok%28something%29%60.%0A%0A%2F%2F+Another+another+another+hint%3A+%60Result%60s+must+be+%22used%22%2C+that+is%2C+you%27ll%0A%2F%2F+get+a+warning+if+you+don%27t+handle+a+%60Result%60+that+you+get+in+your%0A%2F%2F+function.+Read+more+about+that+in+the+%60std%3A%3Aresult%60+module+docs%3A%0A%2F%2F+https%3A%2F%2Fdoc.rust-lang.org%2Fstd%2Fresult%2F%23results-must-be-used%0A) - -### Standard library types - -#### `Arc` - -The [Concurrency](https://doc.rust-lang.org/book/second-edition/ch16-03-shared-state.html) section -is relevant. - -- ["arc1.rs"](https://play.rust-lang.org/?code=%2F%2F+arc1.rs%0A%2F%2F+Make+this+code+compile+by+filling+in+a+value+for+%60shared_numbers%60+where+the%0A%2F%2F+TODO+comment+is+and+creating+an+initial+binding+for+%60child_numbers%60%0A%2F%2F+somewhere.+Try+not+to+create+any+copies+of+the+%60numbers%60+Vec%21%0A%2F%2F+Scroll+down+for+hints+%3A%29%0A%0Ause+std%3A%3Async%3A%3AArc%3B%0Ause+std%3A%3Athread%3B%0A%0Afn+main%28%29+%7B%0A++++let+numbers%3A+Vec%3C_%3E+%3D+%280..100u32%29.collect%28%29%3B%0A++++let+shared_numbers+%3D+%2F%2F+TODO%0A++++let+mut+joinhandles+%3D+Vec%3A%3Anew%28%29%3B%0A%0A++++for+offset+in+0..8+%7B%0A++++++++joinhandles.push%28%0A++++++++thread%3A%3Aspawn%28move+%7C%7C+%7B%0A++++++++++++let+mut+i+%3D+offset%3B%0A++++++++++++let+mut+sum+%3D+0%3B%0A++++++++++++while+i+%3C+child_numbers.len%28%29+%7B%0A++++++++++++++++sum+%2B%3D+child_numbers%5Bi%5D%3B%0A++++++++++++++++i+%2B%3D+5%3B%0A++++++++++++%7D%0A++++++++++++println%21%28%22Sum+of+offset+%7B%7D+is+%7B%7D%22%2C+offset%2C+sum%29%3B%0A++++++++%7D%29%29%3B%0A++++%7D%0A++++for+handle+in+joinhandles.into_iter%28%29+%7B%0A++++++++handle.join%28%29.unwrap%28%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Make+%60shared_numbers%60+be+an+%60Arc%60+from+the+numbers+vector.+Then%2C+in+order%0A%2F%2F+to+avoid+creating+a+copy+of+%60numbers%60%2C+you%27ll+need+to+create+%60child_numbers%60%0A%2F%2F+inside+the+loop+but+still+in+the+main+thread.%0A%0A%2F%2F+%60child_numbers%60+should+be+a+clone+of+the+Arc+of+the+numbers+instead+of+a%0A%2F%2F+thread-local+copy+of+the+numbers.%0A) - -#### 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). - -- ["iterator3.rs"](https://play.rust-lang.org/?code=%2F%2F+iterator3.rs%0A%2F%2F+This+is+a+bigger+exercise+than+most+of+the+others%21+You+can+do+it%21%0A%2F%2F+Here+is+your+mission%2C+should+you+choose+to+accept+it%3A%0A%2F%2F+1.+Complete+the+divide+function+to+get+the+first+four+tests+to+pass%0A%2F%2F+2.+Uncomment+the+last+two+tests+and+get+them+to+pass+by+filling+in%0A%2F%2F++++values+for+%60x%60+using+%60division_results%60.%0A%2F%2F+Scroll+down+for+a+minor+hint+for+part+2%2C+and+scroll+down+further+for%0A%2F%2F+a+major+hint.%0A%2F%2F+Have+fun+%3A-%29%0A%0A%23%5Bderive%28Debug%2C+PartialEq%2C+Eq%29%5D%0Apub+enum+DivisionError+%7B%0A++++NotDivisible%28NotDivisibleError%29%2C%0A++++DivideByZero%2C%0A%7D%0A%0A%23%5Bderive%28Debug%2C+PartialEq%2C+Eq%29%5D%0Apub+struct+NotDivisibleError+%7B%0A++++dividend%3A+i32%2C%0A++++divisor%3A+i32%2C%0A%7D%0A%0A%2F%2F+This+function+should+calculate+%60a%60+divided+by+%60b%60+if+%60a%60+is%0A%2F%2F+evenly+divisible+by+b.%0A%2F%2F+Otherwise%2C+it+should+return+a+suitable+error.%0Apub+fn+divide%28a%3A+i32%2C+b%3A+i32%29+-%3E+Result%3Ci32%2C+DivisionError%3E+%7B%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%2F%2F+Tests+that+verify+your+%60divide%60+function+implementation%0A++++%23%5Btest%5D%0A++++fn+test_success%28%29+%7B%0A++++++++assert_eq%21%28divide%2881%2C+9%29%2C+Ok%289%29%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+test_not_divisible%28%29+%7B%0A++++++++assert_eq%21%28%0A++++++++++++divide%2881%2C+6%29%2C%0A++++++++++++Err%28DivisionError%3A%3ANotDivisible%28NotDivisibleError%7B%0A++++++++++++++++dividend%3A+81%2C%0A++++++++++++++++divisor%3A+6%0A++++++++++++%7D%29%29%0A++++++++%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+test_divide_by_0%28%29+%7B%0A++++++++assert_eq%21%28divide%2881%2C+0%29%2C+Err%28DivisionError%3A%3ADivideByZero%29%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+test_divide_0_by_something%28%29+%7B%0A++++++++assert_eq%21%28divide%280%2C+81%29%2C+Ok%280%29%29%3B%0A++++%7D%0A%0A++++%2F%2F+Iterator+exercises+using+your+%60divide%60+function%0A++++%2F*%0A++++%23%5Btest%5D%0A++++fn+result_with_list%28%29+%7B%0A++++++++let+numbers+%3D+vec%21%5B27%2C+297%2C+38502%2C+81%5D%3B%0A++++++++let+division_results+%3D+numbers.into_iter%28%29.map%28%7Cn%7C+divide%28n%2C+27%29%29%3B%0A++++++++let+x+%2F%2F...+Fill+in+here%21%0A++++++++assert_eq%21%28format%21%28%22%7B%3A%3F%7D%22%2C+x%29%2C+%22Ok%28%5B1%2C+11%2C+1426%2C+3%5D%29%22%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+list_of_results%28%29+%7B%0A++++++++let+numbers+%3D+vec%21%5B27%2C+297%2C+38502%2C+81%5D%3B%0A++++++++let+division_results+%3D+numbers.into_iter%28%29.map%28%7Cn%7C+divide%28n%2C+27%29%29%3B%0A++++++++let+x+%2F%2F...+Fill+in+here%21%0A++++++++assert_eq%21%28format%21%28%22%7B%3A%3F%7D%22%2C+x%29%2C+%22%5BOk%281%29%2C+Ok%2811%29%2C+Ok%281426%29%2C+Ok%283%29%5D%22%29%3B%0A++++%7D%0A++++*%2F%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Minor+hint%3A+In+each+of+the+two+cases+in+the+match+in+main%2C+you+can+create+x+with+either+a+%27turbofish%27+or+by+hinting+the+type+of+x+to+the+compiler.+You+may+try+both.%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Major+hint%3A+Have+a+look+at+the+Iter+trait+and+at+the+explanation+of+its+collect+function.+Especially+the+part+about+Result+is+interesting.%0A) -- ["iterators4.rs"](https://play.rust-lang.org/?code=%2F%2F+iterators4.rs%0A%0Apub+fn+factorial%28num%3A+u64%29+-%3E+u64+%7B%0A++++%2F%2F+Complete+this+function+to+return+factorial+of+num%0A++++%2F%2F+Do+not+use%3A%0A++++%2F%2F+-+return%0A++++%2F%2F+For+extra+fun+don%27t+use%3A%0A++++%2F%2F+-+imperative+style+loops+%28for%2C+while%29%0A++++%2F%2F+-+additional+variables%0A++++%2F%2F+For+the+most+fun+don%27t+use%3A%0A++++%2F%2F+-+recursion%0A++++%2F%2F+Scroll+down+for+hints.%0A%7D%0A%0A%23%5Bcfg%28test%29%5D%0Amod+tests+%7B%0A++++use+super%3A%3A*%3B%0A%0A++++%23%5Btest%5D%0A++++fn+factorial_of_1%28%29+%7B%0A++++++++assert_eq%21%281%2C+factorial%281%29%29%3B%0A++++%7D%0A++++%23%5Btest%5D%0A++++fn+factorial_of_2%28%29+%7B%0A++++++++assert_eq%21%282%2C+factorial%282%29%29%3B%0A++++%7D%0A%0A++++%23%5Btest%5D%0A++++fn+factorial_of_4%28%29+%7B%0A++++++++assert_eq%21%2824%2C+factorial%284%29%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+In+an+imperative+language+you+might+write+a+for+loop+to+iterate+through%0A%2F%2F+multiply+the+values+into+a+mutable+variable.+Or+you+might+write+code+more%0A%2F%2F+functionally+with+recursion+and+a+match+clause.+But+you+can+also+use+ranges%0A%2F%2F+and+iterators+to+solve+this+in+rust.%0A) - -### 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. - -- ["threads1.rs"](https://play.rust-lang.org/?code=%2F%2F+threads1.rs%0A%2F%2F+Make+this+compile%21+Scroll+down+for+hints+%3A%29+The+idea+is+the+thread%0A%2F%2F+spawned+on+line+19+is+completing+jobs+while+the+main+thread+is%0A%2F%2F+monitoring+progress+until+10+jobs+are+completed.+If+you+see+6+lines%0A%2F%2F+of+%22waiting...%22+and+the+program+ends+without+timing+out+the+playground%2C%0A%2F%2F+you%27ve+got+it+%3A%29%0A%0Ause+std%3A%3Async%3A%3AArc%3B%0Ause+std%3A%3Athread%3B%0Ause+std%3A%3Atime%3A%3ADuration%3B%0A%0Astruct+JobStatus+%7B%0A++++jobs_completed%3A+u32%2C%0A%7D%0A%0Afn+main%28%29+%7B%0A++++let+status+%3D+Arc%3A%3Anew%28JobStatus+%7B+jobs_completed%3A+0+%7D%29%3B%0A++++let+status_shared+%3D+status.clone%28%29%3B%0A++++thread%3A%3Aspawn%28move+%7C%7C+%7B%0A++++++++for+_+in+0..10+%7B%0A++++++++++++thread%3A%3Asleep%28Duration%3A%3Afrom_millis%28250%29%29%3B%0A++++++++++++status_shared.jobs_completed+%2B%3D+1%3B%0A++++++++%7D%0A++++%7D%29%3B%0A++++while+status.jobs_completed+%3C+10+%7B%0A++++++++println%21%28%22waiting...+%22%29%3B%0A++++++++thread%3A%3Asleep%28Duration%3A%3Afrom_millis%28500%29%29%3B%0A++++%7D%0A%7D%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+%60Arc%60+is+an+Atomic+Reference+Counted+pointer+that+allows+safe%2C+shared+access%0A%2F%2F+to+**immutable**+data.+But+we+want+to+*change*+the+number+of+%60jobs_completed%60%0A%2F%2F+so+we%27ll+need+to+also+use+another+type+that+will+only+allow+one+thread+to%0A%2F%2F+mutate+the+data+at+a+time.+Take+a+look+at+this+section+of+the+book%3A%0A%2F%2F+https%3A%2F%2Fdoc.rust-lang.org%2Fstable%2Fbook%2Fconcurrency.html%23safe-shared-mutable-state%0A%2F%2F+and+keep+scrolling+if+you%27d+like+more+hints+%3A%29%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Do+you+now+have+an+%60Arc%60+%60Mutex%60+%60JobStatus%60+at+the+beginning+of+main%3F+Like%3A%0A%2F%2F+%60let+status+%3D+Arc%3A%3Anew%28Mutex%3A%3Anew%28JobStatus+%7B+jobs_completed%3A+0+%7D%29%29%3B%60%0A%2F%2F+Similar+to+the+code+in+the+example+in+the+book+that+happens+after+the+text%0A%2F%2F+that+says+%22We+can+use+Arc%3CT%3E+to+fix+this.%22.+If+not%2C+give+that+a+try%21+If+you%0A%2F%2F+do+and+would+like+more+hints%2C+keep+scrolling%21%21%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%2F%2F+Make+sure+neither+of+your+threads+are+holding+onto+the+lock+of+the+mutex%0A%2F%2F+while+they+are+sleeping%2C+since+this+will+prevent+the+other+thread+from%0A%2F%2F+being+allowed+to+get+the+lock.+Locks+are+automatically+released+when%0A%2F%2F+they+go+out+of+scope.%0A%0A%2F%2F+Ok%2C+so%2C+real+talk%2C+this+was+actually+tricky+for+*me*+to+do+too.+And%0A%2F%2F+I+could+see+a+lot+of+different+problems+you+might+run+into%2C+so+at+this%0A%2F%2F+point+I%27m+not+sure+which+one+you%27ve+hit+%3A%29+Please+see+a+few+possible%0A%2F%2F+answers+on+https%3A%2F%2Fgithub.com%2Fcarols10cents%2Frustlings%2Fissues%2F3+--%0A%2F%2F+mine+is+a+little+more+complicated+because+I+decided+I+wanted+to+see%0A%2F%2F+the+number+of+jobs+currently+done+when+I+was+checking+the+status.%0A%0A%2F%2F+Please+open+an+issue+if+you%27re+still+running+into+a+problem+that%0A%2F%2F+these+hints+are+not+helping+you+with%2C+or+if+you%27ve+looked+at+the+sample%0A%2F%2F+answers+and+don%27t+understand+why+they+work+and+yours+doesn%27t.%0A%0A%2F%2F+If+you%27ve+learned+from+the+sample+solutions%2C+I+encourage+you+to+come%0A%2F%2F+back+to+this+exercise+and+try+it+again+in+a+few+days+to+reinforce%0A%2F%2F+what+you%27ve+learned+%3A%29%0A) - -### Uncategorized - -A few exercises based on things I've encountered or had trouble with getting used to. - -- ["ex1.rs"](https://play.rust-lang.org/?code=%2F%2F+ex1.rs%0A%2F%2F+Make+me+compile%21+%3A%29%0A%0Afn+main%28%29+%7B%0A++++println%28%29%3B%0A%7D%0A) -- ["ex2.rs"](https://play.rust-lang.org/?code=%2F%2F+ex2.rs%0A%2F%2F+Make+me+compile%21%0A%0Afn+something%28%29+-%3E+String+%7B%0A++++%22hi%21%22%0A%7D%0A%0Afn+main%28%29+%7B%0A++++println%21%28%22%7B%7D%22%2C+something%28%29%29%3B%0A%7D%0A) -- ["ex3.rs"](https://play.rust-lang.org/?code=%2F%2F+ex3.rs%0A%2F%2F+Make+me+compile%21%0A%0Astruct+Foo+%7B%0A++++capacity%3A+i32%2C%0A%7D%0A%0Afn+main%28%29+%7B%0A++++println%21%28%22%7B%3A%3F%7D%22%2C+Foo+%7B+capacity%3A+3+%7D%29%3B%0A%7D%0A) -- ["ex4.rs"](https://play.rust-lang.org/?code=%2F%2F+ex4.rs%0A%2F%2F+Make+me+compile%21%0A%0Afn+something%28%29+-%3E+Result%3Ci32%2C+std%3A%3Anum%3A%3AParseIntError%3E+%7B%0A++++let+x%3Ai32+%3D+%223%22.parse%28%29%3B%0A++++Ok%28x+*+4%29%0A%7D%0A%0Afn+main%28%29+%7B%0A++++match+something%28%29+%7B%0A++++++++Ok%28..%29+%3D%3E+println%21%28%22You+win%21%22%29%2C%0A++++++++Err%28e%29+%3D%3E+println%21%28%22Oh+no+something+went+wrong%3A+%7B%7D%22%2C+e%29%2C%0A++++%7D%0A%7D%0A) -- ["ex5.rs"](https://play.rust-lang.org/?code=%2F%2F+ex5.rs%0A%2F%2F+Make+me+compile%21%0A%0Aenum+Reaction%3C%27a%3E+%7B%0A++++Sad%28%26%27a+str%29%2C%0A++++Happy%28%26%27a+str%29%2C%0A%7D%0A%0Afn+express%28sentiment%3A+Reaction%29+%7B%0A++++match+sentiment+%7B%0A++++++++Reaction%3A%3ASad%28s%29+%3D%3E+println%21%28%22%3A%28+%7B%7D%22%2C+s%29%2C%0A++++++++Reaction%3A%3AHappy%28s%29+%3D%3E+println%21%28%22%3A%29+%7B%7D%22%2C+s%29%2C%0A++++%7D%0A%7D%0A%0Afn+main+%28%29+%7B%0A++++let+x+%3D+Reaction%3A%3AHappy%28%22It%27s+a+great+day+for+Rust%21%22%29%3B%0A++++express%28x%29%3B%0A++++express%28x%29%3B%0A++++let+y+%3D+Reaction%3A%3ASad%28%22This+code+doesn%27t+compile+yet.%22%29%3B%0A++++express%28y%29%3B%0A%7D%0A) - -## To help with this repo/TODO list +A cool thing that is currently in development. -* 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?? -- cgit v1.2.3 From 5e89d1e888a8fafc39096afce36d02e313f349c2 Mon Sep 17 00:00:00 2001 From: olivia Date: Thu, 26 Apr 2018 21:29:11 +0200 Subject: move old files to a separate directory --- .travis.yml | 19 - Cargo.lock | 456 --------------------- Cargo.toml | 9 - README-template.hbs | 190 --------- error_handling/errors1.rs | 73 ---- error_handling/errors2.rs | 72 ---- error_handling/errors3.rs | 67 --- error_handling/errorsn.rs | 138 ------- error_handling/option1.rs | 45 -- error_handling/result1.rs | 43 -- ex1.rs | 6 - ex2.rs | 10 - ex3.rs | 10 - ex4.rs | 14 - ex5.rs | 22 - functions/functions1.rs | 44 -- functions/functions2.rs | 42 -- functions/functions3.rs | 42 -- functions/functions4.rs | 44 -- functions/functions5.rs | 44 -- if/if1.rs | 58 --- macros/macros1.rs | 64 --- macros/macros2.rs | 73 ---- macros/macros3.rs | 75 ---- macros/macros4.rs | 77 ---- modules/modules1.rs | 43 -- modules/modules2.rs | 45 -- move_semantics/move_semantics1.rs | 43 -- move_semantics/move_semantics2.rs | 54 --- move_semantics/move_semantics3.rs | 46 --- move_semantics/move_semantics4.rs | 48 --- old_curriculum/.travis.yml | 19 + old_curriculum/Cargo.lock | 456 +++++++++++++++++++++ old_curriculum/Cargo.toml | 9 + old_curriculum/README-template.hbs | 190 +++++++++ old_curriculum/error_handling/errors1.rs | 73 ++++ old_curriculum/error_handling/errors2.rs | 72 ++++ old_curriculum/error_handling/errors3.rs | 67 +++ old_curriculum/error_handling/errorsn.rs | 138 +++++++ old_curriculum/error_handling/option1.rs | 45 ++ old_curriculum/error_handling/result1.rs | 43 ++ old_curriculum/ex1.rs | 6 + old_curriculum/ex2.rs | 10 + old_curriculum/ex3.rs | 10 + old_curriculum/ex4.rs | 14 + old_curriculum/ex5.rs | 22 + old_curriculum/functions/functions1.rs | 44 ++ old_curriculum/functions/functions2.rs | 42 ++ old_curriculum/functions/functions3.rs | 42 ++ old_curriculum/functions/functions4.rs | 44 ++ old_curriculum/functions/functions5.rs | 44 ++ old_curriculum/if/if1.rs | 58 +++ old_curriculum/macros/macros1.rs | 64 +++ old_curriculum/macros/macros2.rs | 73 ++++ old_curriculum/macros/macros3.rs | 75 ++++ old_curriculum/macros/macros4.rs | 77 ++++ old_curriculum/modules/modules1.rs | 43 ++ old_curriculum/modules/modules2.rs | 45 ++ old_curriculum/move_semantics/move_semantics1.rs | 43 ++ old_curriculum/move_semantics/move_semantics2.rs | 54 +++ old_curriculum/move_semantics/move_semantics3.rs | 46 +++ old_curriculum/move_semantics/move_semantics4.rs | 48 +++ old_curriculum/primitive_types/primitive_types1.rs | 17 + old_curriculum/primitive_types/primitive_types2.rs | 27 ++ old_curriculum/primitive_types/primitive_types3.rs | 46 +++ old_curriculum/primitive_types/primitive_types4.rs | 49 +++ old_curriculum/primitive_types/primitive_types5.rs | 45 ++ old_curriculum/primitive_types/primitive_types6.rs | 44 ++ old_curriculum/src/bin/generate_readme.rs | 49 +++ old_curriculum/standard_library_types/arc1.rs | 56 +++ old_curriculum/standard_library_types/iterator3.rs | 145 +++++++ .../standard_library_types/iterators4.rs | 61 +++ old_curriculum/strings/strings1.rs | 46 +++ old_curriculum/strings/strings2.rs | 44 ++ old_curriculum/strings/strings3.rs | 21 + old_curriculum/tests/tests1.rs | 49 +++ old_curriculum/tests/tests2.rs | 44 ++ old_curriculum/tests/tests3.rs | 43 ++ old_curriculum/tests/tests4.rs | 19 + old_curriculum/threads/threads1.rs | 95 +++++ old_curriculum/variables/variables1.rs | 42 ++ old_curriculum/variables/variables2.rs | 47 +++ old_curriculum/variables/variables3.rs | 43 ++ old_curriculum/variables/variables4.rs | 45 ++ primitive_types/primitive_types1.rs | 17 - primitive_types/primitive_types2.rs | 27 -- primitive_types/primitive_types3.rs | 46 --- primitive_types/primitive_types4.rs | 49 --- primitive_types/primitive_types5.rs | 45 -- primitive_types/primitive_types6.rs | 44 -- src/bin/generate_readme.rs | 49 --- standard_library_types/arc1.rs | 56 --- standard_library_types/iterator3.rs | 145 ------- standard_library_types/iterators4.rs | 61 --- strings/strings1.rs | 46 --- strings/strings2.rs | 44 -- strings/strings3.rs | 21 - tests/tests1.rs | 49 --- tests/tests2.rs | 44 -- tests/tests3.rs | 43 -- tests/tests4.rs | 19 - threads/threads1.rs | 95 ----- variables/variables1.rs | 42 -- variables/variables2.rs | 47 --- variables/variables3.rs | 43 -- variables/variables4.rs | 45 -- 106 files changed, 3093 insertions(+), 3093 deletions(-) delete mode 100644 .travis.yml delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 README-template.hbs delete mode 100644 error_handling/errors1.rs delete mode 100644 error_handling/errors2.rs delete mode 100644 error_handling/errors3.rs delete mode 100644 error_handling/errorsn.rs delete mode 100644 error_handling/option1.rs delete mode 100644 error_handling/result1.rs delete mode 100644 ex1.rs delete mode 100644 ex2.rs delete mode 100644 ex3.rs delete mode 100644 ex4.rs delete mode 100644 ex5.rs delete mode 100644 functions/functions1.rs delete mode 100644 functions/functions2.rs delete mode 100644 functions/functions3.rs delete mode 100644 functions/functions4.rs delete mode 100644 functions/functions5.rs delete mode 100644 if/if1.rs delete mode 100644 macros/macros1.rs delete mode 100644 macros/macros2.rs delete mode 100644 macros/macros3.rs delete mode 100644 macros/macros4.rs delete mode 100644 modules/modules1.rs delete mode 100644 modules/modules2.rs delete mode 100644 move_semantics/move_semantics1.rs delete mode 100644 move_semantics/move_semantics2.rs delete mode 100644 move_semantics/move_semantics3.rs delete mode 100644 move_semantics/move_semantics4.rs create mode 100644 old_curriculum/.travis.yml create mode 100644 old_curriculum/Cargo.lock create mode 100644 old_curriculum/Cargo.toml create mode 100644 old_curriculum/README-template.hbs create mode 100644 old_curriculum/error_handling/errors1.rs create mode 100644 old_curriculum/error_handling/errors2.rs create mode 100644 old_curriculum/error_handling/errors3.rs create mode 100644 old_curriculum/error_handling/errorsn.rs create mode 100644 old_curriculum/error_handling/option1.rs create mode 100644 old_curriculum/error_handling/result1.rs create mode 100644 old_curriculum/ex1.rs create mode 100644 old_curriculum/ex2.rs create mode 100644 old_curriculum/ex3.rs create mode 100644 old_curriculum/ex4.rs create mode 100644 old_curriculum/ex5.rs create mode 100644 old_curriculum/functions/functions1.rs create mode 100644 old_curriculum/functions/functions2.rs create mode 100644 old_curriculum/functions/functions3.rs create mode 100644 old_curriculum/functions/functions4.rs create mode 100644 old_curriculum/functions/functions5.rs create mode 100644 old_curriculum/if/if1.rs create mode 100644 old_curriculum/macros/macros1.rs create mode 100644 old_curriculum/macros/macros2.rs create mode 100644 old_curriculum/macros/macros3.rs create mode 100644 old_curriculum/macros/macros4.rs create mode 100644 old_curriculum/modules/modules1.rs create mode 100644 old_curriculum/modules/modules2.rs create mode 100644 old_curriculum/move_semantics/move_semantics1.rs create mode 100644 old_curriculum/move_semantics/move_semantics2.rs create mode 100644 old_curriculum/move_semantics/move_semantics3.rs create mode 100644 old_curriculum/move_semantics/move_semantics4.rs create mode 100644 old_curriculum/primitive_types/primitive_types1.rs create mode 100644 old_curriculum/primitive_types/primitive_types2.rs create mode 100644 old_curriculum/primitive_types/primitive_types3.rs create mode 100644 old_curriculum/primitive_types/primitive_types4.rs create mode 100644 old_curriculum/primitive_types/primitive_types5.rs create mode 100644 old_curriculum/primitive_types/primitive_types6.rs create mode 100644 old_curriculum/src/bin/generate_readme.rs create mode 100644 old_curriculum/standard_library_types/arc1.rs create mode 100644 old_curriculum/standard_library_types/iterator3.rs create mode 100644 old_curriculum/standard_library_types/iterators4.rs create mode 100644 old_curriculum/strings/strings1.rs create mode 100644 old_curriculum/strings/strings2.rs create mode 100644 old_curriculum/strings/strings3.rs create mode 100644 old_curriculum/tests/tests1.rs create mode 100644 old_curriculum/tests/tests2.rs create mode 100644 old_curriculum/tests/tests3.rs create mode 100644 old_curriculum/tests/tests4.rs create mode 100644 old_curriculum/threads/threads1.rs create mode 100644 old_curriculum/variables/variables1.rs create mode 100644 old_curriculum/variables/variables2.rs create mode 100644 old_curriculum/variables/variables3.rs create mode 100644 old_curriculum/variables/variables4.rs delete mode 100644 primitive_types/primitive_types1.rs delete mode 100644 primitive_types/primitive_types2.rs delete mode 100644 primitive_types/primitive_types3.rs delete mode 100644 primitive_types/primitive_types4.rs delete mode 100644 primitive_types/primitive_types5.rs delete mode 100644 primitive_types/primitive_types6.rs delete mode 100644 src/bin/generate_readme.rs delete mode 100644 standard_library_types/arc1.rs delete mode 100644 standard_library_types/iterator3.rs delete mode 100644 standard_library_types/iterators4.rs delete mode 100644 strings/strings1.rs delete mode 100644 strings/strings2.rs delete mode 100644 strings/strings3.rs delete mode 100644 tests/tests1.rs delete mode 100644 tests/tests2.rs delete mode 100644 tests/tests3.rs delete mode 100644 tests/tests4.rs delete mode 100644 threads/threads1.rs delete mode 100644 variables/variables1.rs delete mode 100644 variables/variables2.rs delete mode 100644 variables/variables3.rs delete mode 100644 variables/variables4.rs diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 684b265..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -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 - diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 7bff901..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,456 +0,0 @@ -[[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)" = "" -"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" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index d82b8a1..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "rustlings" -version = "0.1.0" -authors = ["Carol (Nichols || Goulding) "] - -[dependencies] -handlebars = "0.32.0" -serde_json = "1.0.10" -prlink = { git = "https://github.com/btbytes/prlink" } diff --git a/README-template.hbs b/README-template.hbs deleted file mode 100644 index 5cfec7f..0000000 --- a/README-template.hbs +++ /dev/null @@ -1,190 +0,0 @@ - - -# 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?? diff --git a/error_handling/errors1.rs b/error_handling/errors1.rs deleted file mode 100644 index 14ed574..0000000 --- a/error_handling/errors1.rs +++ /dev/null @@ -1,73 +0,0 @@ -// 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 { - 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)`. diff --git a/error_handling/errors2.rs b/error_handling/errors2.rs deleted file mode 100644 index 05824c1..0000000 --- a/error_handling/errors2.rs +++ /dev/null @@ -1,72 +0,0 @@ -// 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 { - let processing_fee = 1; - let cost_per_item = 5; - let qty = item_quantity.parse::(); - - 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::()` 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!` diff --git a/error_handling/errors3.rs b/error_handling/errors3.rs deleted file mode 100644 index 9b285e0..0000000 --- a/error_handling/errors3.rs +++ /dev/null @@ -1,67 +0,0 @@ -// 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 { - let processing_fee = 1; - let cost_per_item = 5; - let qty = try!(item_quantity.parse::()); - - 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. diff --git a/error_handling/errorsn.rs b/error_handling/errorsn.rs deleted file mode 100644 index ee1179d..0000000 --- a/error_handling/errorsn.rs +++ /dev/null @@ -1,138 +0,0 @@ -// 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 { - 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> { - 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 { - 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 { - 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, -// 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 diff --git a/error_handling/option1.rs b/error_handling/option1.rs deleted file mode 100644 index 9cf0bc9..0000000 --- a/error_handling/option1.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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! diff --git a/error_handling/result1.rs b/error_handling/result1.rs deleted file mode 100644 index 851ab45..0000000 --- a/error_handling/result1.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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 { - 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 :) diff --git a/ex1.rs b/ex1.rs deleted file mode 100644 index dc5f9ca..0000000 --- a/ex1.rs +++ /dev/null @@ -1,6 +0,0 @@ -// ex1.rs -// Make me compile! :) - -fn main() { - println(); -} diff --git a/ex2.rs b/ex2.rs deleted file mode 100644 index 0fd714d..0000000 --- a/ex2.rs +++ /dev/null @@ -1,10 +0,0 @@ -// ex2.rs -// Make me compile! - -fn something() -> String { - "hi!" -} - -fn main() { - println!("{}", something()); -} diff --git a/ex3.rs b/ex3.rs deleted file mode 100644 index db27ad2..0000000 --- a/ex3.rs +++ /dev/null @@ -1,10 +0,0 @@ -// ex3.rs -// Make me compile! - -struct Foo { - capacity: i32, -} - -fn main() { - println!("{:?}", Foo { capacity: 3 }); -} diff --git a/ex4.rs b/ex4.rs deleted file mode 100644 index 362a557..0000000 --- a/ex4.rs +++ /dev/null @@ -1,14 +0,0 @@ -// ex4.rs -// Make me compile! - -fn something() -> Result { - 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), - } -} diff --git a/ex5.rs b/ex5.rs deleted file mode 100644 index 2eb8cfd..0000000 --- a/ex5.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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); -} diff --git a/functions/functions1.rs b/functions/functions1.rs deleted file mode 100644 index 396dd56..0000000 --- a/functions/functions1.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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? diff --git a/functions/functions2.rs b/functions/functions2.rs deleted file mode 100644 index 1cf95c3..0000000 --- a/functions/functions2.rs +++ /dev/null @@ -1,42 +0,0 @@ -// 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`. diff --git a/functions/functions3.rs b/functions/functions3.rs deleted file mode 100644 index b17543b..0000000 --- a/functions/functions3.rs +++ /dev/null @@ -1,42 +0,0 @@ -// 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. diff --git a/functions/functions4.rs b/functions/functions4.rs deleted file mode 100644 index 5baca0e..0000000 --- a/functions/functions4.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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! diff --git a/functions/functions5.rs b/functions/functions5.rs deleted file mode 100644 index f8fac5d..0000000 --- a/functions/functions5.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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... diff --git a/if/if1.rs b/if/if1.rs deleted file mode 100644 index 5118657..0000000 --- a/if/if1.rs +++ /dev/null @@ -1,58 +0,0 @@ -// 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. diff --git a/macros/macros1.rs b/macros/macros1.rs deleted file mode 100644 index a7c78a5..0000000 --- a/macros/macros1.rs +++ /dev/null @@ -1,64 +0,0 @@ -// 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`. diff --git a/macros/macros2.rs b/macros/macros2.rs deleted file mode 100644 index bc2e56b..0000000 --- a/macros/macros2.rs +++ /dev/null @@ -1,73 +0,0 @@ -// 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. diff --git a/macros/macros3.rs b/macros/macros3.rs deleted file mode 100644 index 84c4308..0000000 --- a/macros/macros3.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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. diff --git a/macros/macros4.rs b/macros/macros4.rs deleted file mode 100644 index d844bb0..0000000 --- a/macros/macros4.rs +++ /dev/null @@ -1,77 +0,0 @@ -// 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. diff --git a/modules/modules1.rs b/modules/modules1.rs deleted file mode 100644 index 0e092c5..0000000 --- a/modules/modules1.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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. diff --git a/modules/modules2.rs b/modules/modules2.rs deleted file mode 100644 index 164dfb0..0000000 --- a/modules/modules2.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. diff --git a/move_semantics/move_semantics1.rs b/move_semantics/move_semantics1.rs deleted file mode 100644 index 73dc0ab..0000000 --- a/move_semantics/move_semantics1.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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) -> Vec { - 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. diff --git a/move_semantics/move_semantics2.rs b/move_semantics/move_semantics2.rs deleted file mode 100644 index bc42d8e..0000000 --- a/move_semantics/move_semantics2.rs +++ /dev/null @@ -1,54 +0,0 @@ -// 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) -> Vec { - 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` -// 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!` diff --git a/move_semantics/move_semantics3.rs b/move_semantics/move_semantics3.rs deleted file mode 100644 index 7805d44..0000000 --- a/move_semantics/move_semantics3.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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) -> Vec { - 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 :) diff --git a/move_semantics/move_semantics4.rs b/move_semantics/move_semantics4.rs deleted file mode 100644 index 2b1ed8a..0000000 --- a/move_semantics/move_semantics4.rs +++ /dev/null @@ -1,48 +0,0 @@ -// 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) -> Vec { - 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` diff --git a/old_curriculum/.travis.yml b/old_curriculum/.travis.yml new file mode 100644 index 0000000..684b265 --- /dev/null +++ b/old_curriculum/.travis.yml @@ -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 + diff --git a/old_curriculum/Cargo.lock b/old_curriculum/Cargo.lock new file mode 100644 index 0000000..7bff901 --- /dev/null +++ b/old_curriculum/Cargo.lock @@ -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)" = "" +"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" diff --git a/old_curriculum/Cargo.toml b/old_curriculum/Cargo.toml new file mode 100644 index 0000000..d82b8a1 --- /dev/null +++ b/old_curriculum/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rustlings" +version = "0.1.0" +authors = ["Carol (Nichols || Goulding) "] + +[dependencies] +handlebars = "0.32.0" +serde_json = "1.0.10" +prlink = { git = "https://github.com/btbytes/prlink" } diff --git a/old_curriculum/README-template.hbs b/old_curriculum/README-template.hbs new file mode 100644 index 0000000..5cfec7f --- /dev/null +++ b/old_curriculum/README-template.hbs @@ -0,0 +1,190 @@ + + +# 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?? diff --git a/old_curriculum/error_handling/errors1.rs b/old_curriculum/error_handling/errors1.rs new file mode 100644 index 0000000..14ed574 --- /dev/null +++ b/old_curriculum/error_handling/errors1.rs @@ -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 { + 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)`. diff --git a/old_curriculum/error_handling/errors2.rs b/old_curriculum/error_handling/errors2.rs new file mode 100644 index 0000000..05824c1 --- /dev/null +++ b/old_curriculum/error_handling/errors2.rs @@ -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 { + let processing_fee = 1; + let cost_per_item = 5; + let qty = item_quantity.parse::(); + + 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::()` 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!` diff --git a/old_curriculum/error_handling/errors3.rs b/old_curriculum/error_handling/errors3.rs new file mode 100644 index 0000000..9b285e0 --- /dev/null +++ b/old_curriculum/error_handling/errors3.rs @@ -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 { + let processing_fee = 1; + let cost_per_item = 5; + let qty = try!(item_quantity.parse::()); + + 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. diff --git a/old_curriculum/error_handling/errorsn.rs b/old_curriculum/error_handling/errorsn.rs new file mode 100644 index 0000000..ee1179d --- /dev/null +++ b/old_curriculum/error_handling/errorsn.rs @@ -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 { + 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> { + 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 { + 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 { + 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, +// 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 diff --git a/old_curriculum/error_handling/option1.rs b/old_curriculum/error_handling/option1.rs new file mode 100644 index 0000000..9cf0bc9 --- /dev/null +++ b/old_curriculum/error_handling/option1.rs @@ -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! diff --git a/old_curriculum/error_handling/result1.rs b/old_curriculum/error_handling/result1.rs new file mode 100644 index 0000000..851ab45 --- /dev/null +++ b/old_curriculum/error_handling/result1.rs @@ -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 { + 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 :) diff --git a/old_curriculum/ex1.rs b/old_curriculum/ex1.rs new file mode 100644 index 0000000..dc5f9ca --- /dev/null +++ b/old_curriculum/ex1.rs @@ -0,0 +1,6 @@ +// ex1.rs +// Make me compile! :) + +fn main() { + println(); +} diff --git a/old_curriculum/ex2.rs b/old_curriculum/ex2.rs new file mode 100644 index 0000000..0fd714d --- /dev/null +++ b/old_curriculum/ex2.rs @@ -0,0 +1,10 @@ +// ex2.rs +// Make me compile! + +fn something() -> String { + "hi!" +} + +fn main() { + println!("{}", something()); +} diff --git a/old_curriculum/ex3.rs b/old_curriculum/ex3.rs new file mode 100644 index 0000000..db27ad2 --- /dev/null +++ b/old_curriculum/ex3.rs @@ -0,0 +1,10 @@ +// ex3.rs +// Make me compile! + +struct Foo { + capacity: i32, +} + +fn main() { + println!("{:?}", Foo { capacity: 3 }); +} diff --git a/old_curriculum/ex4.rs b/old_curriculum/ex4.rs new file mode 100644 index 0000000..362a557 --- /dev/null +++ b/old_curriculum/ex4.rs @@ -0,0 +1,14 @@ +// ex4.rs +// Make me compile! + +fn something() -> Result { + 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), + } +} diff --git a/old_curriculum/ex5.rs b/old_curriculum/ex5.rs new file mode 100644 index 0000000..2eb8cfd --- /dev/null +++ b/old_curriculum/ex5.rs @@ -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); +} diff --git a/old_curriculum/functions/functions1.rs b/old_curriculum/functions/functions1.rs new file mode 100644 index 0000000..396dd56 --- /dev/null +++ b/old_curriculum/functions/functions1.rs @@ -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? diff --git a/old_curriculum/functions/functions2.rs b/old_curriculum/functions/functions2.rs new file mode 100644 index 0000000..1cf95c3 --- /dev/null +++ b/old_curriculum/functions/functions2.rs @@ -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`. diff --git a/old_curriculum/functions/functions3.rs b/old_curriculum/functions/functions3.rs new file mode 100644 index 0000000..b17543b --- /dev/null +++ b/old_curriculum/functions/functions3.rs @@ -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. diff --git a/old_curriculum/functions/functions4.rs b/old_curriculum/functions/functions4.rs new file mode 100644 index 0000000..5baca0e --- /dev/null +++ b/old_curriculum/functions/functions4.rs @@ -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! diff --git a/old_curriculum/functions/functions5.rs b/old_curriculum/functions/functions5.rs new file mode 100644 index 0000000..f8fac5d --- /dev/null +++ b/old_curriculum/functions/functions5.rs @@ -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... diff --git a/old_curriculum/if/if1.rs b/old_curriculum/if/if1.rs new file mode 100644 index 0000000..5118657 --- /dev/null +++ b/old_curriculum/if/if1.rs @@ -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. diff --git a/old_curriculum/macros/macros1.rs b/old_curriculum/macros/macros1.rs new file mode 100644 index 0000000..a7c78a5 --- /dev/null +++ b/old_curriculum/macros/macros1.rs @@ -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`. diff --git a/old_curriculum/macros/macros2.rs b/old_curriculum/macros/macros2.rs new file mode 100644 index 0000000..bc2e56b --- /dev/null +++ b/old_curriculum/macros/macros2.rs @@ -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. diff --git a/old_curriculum/macros/macros3.rs b/old_curriculum/macros/macros3.rs new file mode 100644 index 0000000..84c4308 --- /dev/null +++ b/old_curriculum/macros/macros3.rs @@ -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. diff --git a/old_curriculum/macros/macros4.rs b/old_curriculum/macros/macros4.rs new file mode 100644 index 0000000..d844bb0 --- /dev/null +++ b/old_curriculum/macros/macros4.rs @@ -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. diff --git a/old_curriculum/modules/modules1.rs b/old_curriculum/modules/modules1.rs new file mode 100644 index 0000000..0e092c5 --- /dev/null +++ b/old_curriculum/modules/modules1.rs @@ -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. diff --git a/old_curriculum/modules/modules2.rs b/old_curriculum/modules/modules2.rs new file mode 100644 index 0000000..164dfb0 --- /dev/null +++ b/old_curriculum/modules/modules2.rs @@ -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. diff --git a/old_curriculum/move_semantics/move_semantics1.rs b/old_curriculum/move_semantics/move_semantics1.rs new file mode 100644 index 0000000..73dc0ab --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics1.rs @@ -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) -> Vec { + 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. diff --git a/old_curriculum/move_semantics/move_semantics2.rs b/old_curriculum/move_semantics/move_semantics2.rs new file mode 100644 index 0000000..bc42d8e --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics2.rs @@ -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) -> Vec { + 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` +// 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!` diff --git a/old_curriculum/move_semantics/move_semantics3.rs b/old_curriculum/move_semantics/move_semantics3.rs new file mode 100644 index 0000000..7805d44 --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics3.rs @@ -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) -> Vec { + 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 :) diff --git a/old_curriculum/move_semantics/move_semantics4.rs b/old_curriculum/move_semantics/move_semantics4.rs new file mode 100644 index 0000000..2b1ed8a --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics4.rs @@ -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) -> Vec { + 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` diff --git a/old_curriculum/primitive_types/primitive_types1.rs b/old_curriculum/primitive_types/primitive_types1.rs new file mode 100644 index 0000000..c3d11fe --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types1.rs @@ -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!"); + } +} diff --git a/old_curriculum/primitive_types/primitive_types2.rs b/old_curriculum/primitive_types/primitive_types2.rs new file mode 100644 index 0000000..f5c8f87 --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types2.rs @@ -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!"); + } +} diff --git a/old_curriculum/primitive_types/primitive_types3.rs b/old_curriculum/primitive_types/primitive_types3.rs new file mode 100644 index 0000000..a2f9b3b --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types3.rs @@ -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`? diff --git a/old_curriculum/primitive_types/primitive_types4.rs b/old_curriculum/primitive_types/primitive_types4.rs new file mode 100644 index 0000000..c20b63b --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types4.rs @@ -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 diff --git a/old_curriculum/primitive_types/primitive_types5.rs b/old_curriculum/primitive_types/primitive_types5.rs new file mode 100644 index 0000000..14c2fd2 --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types5.rs @@ -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!! diff --git a/old_curriculum/primitive_types/primitive_types6.rs b/old_curriculum/primitive_types/primitive_types6.rs new file mode 100644 index 0000000..d016642 --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types6.rs @@ -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! diff --git a/old_curriculum/src/bin/generate_readme.rs b/old_curriculum/src/bin/generate_readme.rs new file mode 100644 index 0000000..a502fea --- /dev/null +++ b/old_curriculum/src/bin/generate_readme.rs @@ -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(()) +} diff --git a/old_curriculum/standard_library_types/arc1.rs b/old_curriculum/standard_library_types/arc1.rs new file mode 100644 index 0000000..c744a10 --- /dev/null +++ b/old_curriculum/standard_library_types/arc1.rs @@ -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. diff --git a/old_curriculum/standard_library_types/iterator3.rs b/old_curriculum/standard_library_types/iterator3.rs new file mode 100644 index 0000000..e973ac6 --- /dev/null +++ b/old_curriculum/standard_library_types/iterator3.rs @@ -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 { +} + +#[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. diff --git a/old_curriculum/standard_library_types/iterators4.rs b/old_curriculum/standard_library_types/iterators4.rs new file mode 100644 index 0000000..13613a6 --- /dev/null +++ b/old_curriculum/standard_library_types/iterators4.rs @@ -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. diff --git a/old_curriculum/strings/strings1.rs b/old_curriculum/strings/strings1.rs new file mode 100644 index 0000000..2e5088f --- /dev/null +++ b/old_curriculum/strings/strings1.rs @@ -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. diff --git a/old_curriculum/strings/strings2.rs b/old_curriculum/strings/strings2.rs new file mode 100644 index 0000000..c77e16f --- /dev/null +++ b/old_curriculum/strings/strings2.rs @@ -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. diff --git a/old_curriculum/strings/strings3.rs b/old_curriculum/strings/strings3.rs new file mode 100644 index 0000000..b6f6a1e --- /dev/null +++ b/old_curriculum/strings/strings3.rs @@ -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()); +} diff --git a/old_curriculum/tests/tests1.rs b/old_curriculum/tests/tests1.rs new file mode 100644 index 0000000..959ed85 --- /dev/null +++ b/old_curriculum/tests/tests1.rs @@ -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 :) diff --git a/old_curriculum/tests/tests2.rs b/old_curriculum/tests/tests2.rs new file mode 100644 index 0000000..6775d61 --- /dev/null +++ b/old_curriculum/tests/tests2.rs @@ -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! diff --git a/old_curriculum/tests/tests3.rs b/old_curriculum/tests/tests3.rs new file mode 100644 index 0000000..e041f38 --- /dev/null +++ b/old_curriculum/tests/tests3.rs @@ -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())`. diff --git a/old_curriculum/tests/tests4.rs b/old_curriculum/tests/tests4.rs new file mode 100644 index 0000000..23d444a --- /dev/null +++ b/old_curriculum/tests/tests4.rs @@ -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); + } +} diff --git a/old_curriculum/threads/threads1.rs b/old_curriculum/threads/threads1.rs new file mode 100644 index 0000000..b4a5dc9 --- /dev/null +++ b/old_curriculum/threads/threads1.rs @@ -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 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 :) diff --git a/old_curriculum/variables/variables1.rs b/old_curriculum/variables/variables1.rs new file mode 100644 index 0000000..1cdd270 --- /dev/null +++ b/old_curriculum/variables/variables1.rs @@ -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. diff --git a/old_curriculum/variables/variables2.rs b/old_curriculum/variables/variables2.rs new file mode 100644 index 0000000..a0b4a37 --- /dev/null +++ b/old_curriculum/variables/variables2.rs @@ -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? diff --git a/old_curriculum/variables/variables3.rs b/old_curriculum/variables/variables3.rs new file mode 100644 index 0000000..165a277 --- /dev/null +++ b/old_curriculum/variables/variables3.rs @@ -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. diff --git a/old_curriculum/variables/variables4.rs b/old_curriculum/variables/variables4.rs new file mode 100644 index 0000000..71ebf0f --- /dev/null +++ b/old_curriculum/variables/variables4.rs @@ -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! diff --git a/primitive_types/primitive_types1.rs b/primitive_types/primitive_types1.rs deleted file mode 100644 index c3d11fe..0000000 --- a/primitive_types/primitive_types1.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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!"); - } -} diff --git a/primitive_types/primitive_types2.rs b/primitive_types/primitive_types2.rs deleted file mode 100644 index f5c8f87..0000000 --- a/primitive_types/primitive_types2.rs +++ /dev/null @@ -1,27 +0,0 @@ -// 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!"); - } -} diff --git a/primitive_types/primitive_types3.rs b/primitive_types/primitive_types3.rs deleted file mode 100644 index a2f9b3b..0000000 --- a/primitive_types/primitive_types3.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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`? diff --git a/primitive_types/primitive_types4.rs b/primitive_types/primitive_types4.rs deleted file mode 100644 index c20b63b..0000000 --- a/primitive_types/primitive_types4.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 diff --git a/primitive_types/primitive_types5.rs b/primitive_types/primitive_types5.rs deleted file mode 100644 index 14c2fd2..0000000 --- a/primitive_types/primitive_types5.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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!! diff --git a/primitive_types/primitive_types6.rs b/primitive_types/primitive_types6.rs deleted file mode 100644 index d016642..0000000 --- a/primitive_types/primitive_types6.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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! diff --git a/src/bin/generate_readme.rs b/src/bin/generate_readme.rs deleted file mode 100644 index a502fea..0000000 --- a/src/bin/generate_readme.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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(()) -} diff --git a/standard_library_types/arc1.rs b/standard_library_types/arc1.rs deleted file mode 100644 index c744a10..0000000 --- a/standard_library_types/arc1.rs +++ /dev/null @@ -1,56 +0,0 @@ -// 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. diff --git a/standard_library_types/iterator3.rs b/standard_library_types/iterator3.rs deleted file mode 100644 index e973ac6..0000000 --- a/standard_library_types/iterator3.rs +++ /dev/null @@ -1,145 +0,0 @@ -// 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 { -} - -#[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. diff --git a/standard_library_types/iterators4.rs b/standard_library_types/iterators4.rs deleted file mode 100644 index 13613a6..0000000 --- a/standard_library_types/iterators4.rs +++ /dev/null @@ -1,61 +0,0 @@ -// 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. diff --git a/strings/strings1.rs b/strings/strings1.rs deleted file mode 100644 index 2e5088f..0000000 --- a/strings/strings1.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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. diff --git a/strings/strings2.rs b/strings/strings2.rs deleted file mode 100644 index c77e16f..0000000 --- a/strings/strings2.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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. diff --git a/strings/strings3.rs b/strings/strings3.rs deleted file mode 100644 index b6f6a1e..0000000 --- a/strings/strings3.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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()); -} diff --git a/tests/tests1.rs b/tests/tests1.rs deleted file mode 100644 index 959ed85..0000000 --- a/tests/tests1.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 :) diff --git a/tests/tests2.rs b/tests/tests2.rs deleted file mode 100644 index 6775d61..0000000 --- a/tests/tests2.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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! diff --git a/tests/tests3.rs b/tests/tests3.rs deleted file mode 100644 index e041f38..0000000 --- a/tests/tests3.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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())`. diff --git a/tests/tests4.rs b/tests/tests4.rs deleted file mode 100644 index 23d444a..0000000 --- a/tests/tests4.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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); - } -} diff --git a/threads/threads1.rs b/threads/threads1.rs deleted file mode 100644 index b4a5dc9..0000000 --- a/threads/threads1.rs +++ /dev/null @@ -1,95 +0,0 @@ -// 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 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 :) diff --git a/variables/variables1.rs b/variables/variables1.rs deleted file mode 100644 index 1cdd270..0000000 --- a/variables/variables1.rs +++ /dev/null @@ -1,42 +0,0 @@ -// 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. diff --git a/variables/variables2.rs b/variables/variables2.rs deleted file mode 100644 index a0b4a37..0000000 --- a/variables/variables2.rs +++ /dev/null @@ -1,47 +0,0 @@ -// 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? diff --git a/variables/variables3.rs b/variables/variables3.rs deleted file mode 100644 index 165a277..0000000 --- a/variables/variables3.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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. diff --git a/variables/variables4.rs b/variables/variables4.rs deleted file mode 100644 index 71ebf0f..0000000 --- a/variables/variables4.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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! -- cgit v1.2.3 From 3ffefa32e156f3b8f05df798c4a3e6bd5899f30c Mon Sep 17 00:00:00 2001 From: olivia Date: Thu, 26 Apr 2018 21:41:19 +0200 Subject: init new cargo project --- .gitignore | 4 ++++ Cargo.toml | 6 ++++++ src/lib.rs | 7 +++++++ 3 files changed, 17 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore index d6c1194..798c873 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ *.swp target/ + +/target/ +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ec00628 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rustlings" +version = "0.1.0" +authors = ["olivia "] + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..31e1bb2 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} -- cgit v1.2.3 From 71482339503933d2ac94361ef34270dfa7de35ea Mon Sep 17 00:00:00 2001 From: olivia Date: Thu, 26 Apr 2018 22:14:20 +0200 Subject: add a sample --- src/lib.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 31e1bb2..9adcf56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,20 @@ +#[allow(dead_code)] +mod about_variables { + pub fn guess_this () -> i32 { + let one = 5; + let two = 7; + let three = 3; + let result = (one + two) / three; + result + } +} + #[cfg(test)] mod tests { + use super::about_variables::*; + #[test] - fn it_works() { - assert_eq!(2 + 2, 4); + fn test_complicated () { + assert_eq!(___, guess_this()); } } -- cgit v1.2.3 From d0e3a6e77001e0017443946f34a8253cb60212e8 Mon Sep 17 00:00:00 2001 From: olivia Date: Thu, 26 Apr 2018 22:15:18 +0200 Subject: make return explicit --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 9adcf56..4459509 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ mod about_variables { let two = 7; let three = 3; let result = (one + two) / three; - result + return result; } } -- cgit v1.2.3 From 8ecc1e6ff12152822add7c69d143e836010c6f8a Mon Sep 17 00:00:00 2001 From: olivia Date: Sun, 6 May 2018 17:27:03 +0200 Subject: move to another file --- src/about_variables.rs | 20 ++++++++++++++++++++ src/lib.rs | 20 -------------------- 2 files changed, 20 insertions(+), 20 deletions(-) create mode 100644 src/about_variables.rs diff --git a/src/about_variables.rs b/src/about_variables.rs new file mode 100644 index 0000000..4459509 --- /dev/null +++ b/src/about_variables.rs @@ -0,0 +1,20 @@ +#[allow(dead_code)] +mod about_variables { + pub fn guess_this () -> i32 { + let one = 5; + let two = 7; + let three = 3; + let result = (one + two) / three; + return result; + } +} + +#[cfg(test)] +mod tests { + use super::about_variables::*; + + #[test] + fn test_complicated () { + assert_eq!(___, guess_this()); + } +} diff --git a/src/lib.rs b/src/lib.rs index 4459509..e69de29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,20 +0,0 @@ -#[allow(dead_code)] -mod about_variables { - pub fn guess_this () -> i32 { - let one = 5; - let two = 7; - let three = 3; - let result = (one + two) / three; - return result; - } -} - -#[cfg(test)] -mod tests { - use super::about_variables::*; - - #[test] - fn test_complicated () { - assert_eq!(___, guess_this()); - } -} -- cgit v1.2.3 From 595a91df555fc71f3075ea78649b267665151d1d Mon Sep 17 00:00:00 2001 From: olivia Date: Sun, 6 May 2018 18:59:50 +0200 Subject: experiment --- Cargo.toml | 2 ++ src/lib.rs | 0 src/main.rs | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+) delete mode 100644 src/lib.rs create mode 100644 src/main.rs diff --git a/Cargo.toml b/Cargo.toml index ec00628..5f5c8a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,5 @@ version = "0.1.0" authors = ["olivia "] [dependencies] +quicli = "0.2.0" +ansi_term = "0.11.0" diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..abbd3b8 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,21 @@ +#[macro_use] extern crate quicli; +extern crate ansi_term; + +use quicli::prelude::*; +use ansi_term::Colour::{Red, Yellow}; + +#[derive(Debug, StructOpt)] +struct Cli { + exercise: Option, +} + +main!(|args: Cli| { + match args.exercise { + Some(e) => { + println!("selected {}", e); + } + None => { + println!("Welcome to {}", Yellow.paint("Rustlings")); + } + } +}); -- cgit v1.2.3 From 97efff760dcc032b634d3f69ebedac4ec1b301e7 Mon Sep 17 00:00:00 2001 From: olivia Date: Mon, 14 May 2018 18:41:58 +0200 Subject: use macros --- src/about_variables.rs | 26 +++++++++++++------------- src/main.rs | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/about_variables.rs b/src/about_variables.rs index 4459509..4827dcf 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -1,20 +1,20 @@ #[allow(dead_code)] -mod about_variables { - pub fn guess_this () -> i32 { - let one = 5; - let two = 7; - let three = 3; - let result = (one + two) / three; - return result; - } +pub fn guess_this () -> i32 { + let one = 5; + let two = 7; + let three = 3; + let result = (one + two) / three; + return result; } -#[cfg(test)] mod tests { - use super::about_variables::*; + use super::*; - #[test] - fn test_complicated () { - assert_eq!(___, guess_this()); + pub fn test_complicated () { + assert_eq!(1, guess_this()); } } + +pub fn exec () { + tests::test_complicated(); +} diff --git a/src/main.rs b/src/main.rs index abbd3b8..c3ca53c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,34 @@ extern crate ansi_term; use quicli::prelude::*; -use ansi_term::Colour::{Red, Yellow}; +use ansi_term::Colour::{Red, Yellow, Green}; + +macro_rules! verify { + ( $str:expr, $left:expr, $right:expr ) => { + if ($left == $right) { + println!("{} {}", Green.bold().paint("PASS"), $str); + } else { + println!("{} {}", Red.bold().paint("FAIL"), $str); + println!("\tYou submitted {}, but that's not correct!", $left); + println!("\tPlease correct your code to make this test pass!"); + } + } +} + +macro_rules! verify_easy { + ( $str:expr, $left:expr, $right:expr ) => { + if ($left == $right) { + println!("{} {}", Green.bold().paint("PASS"), $str); + } else { + println!("{} {}", Red.bold().paint("FAIL"), $str); + println!("\tExpected: {}", $right); + println!("\tGot: {}", $left); + println!("\tPlease correct your code to make this test pass!"); + } + } +} + +mod about_variables; #[derive(Debug, StructOpt)] struct Cli { @@ -10,12 +37,10 @@ struct Cli { } main!(|args: Cli| { - match args.exercise { - Some(e) => { - println!("selected {}", e); - } - None => { - println!("Welcome to {}", Yellow.paint("Rustlings")); - } + if let Some(e) = args.exercise { + println!("selected {}", e); + } else { + println!("Welcome to {}", Yellow.paint("rustlings")); + verify!("One equals one", 1, 2); } }); -- cgit v1.2.3 From 8ea1b17fd9505da92a7233d8bfd6d5f1c3d9a93e Mon Sep 17 00:00:00 2001 From: olivia Date: Mon, 14 May 2018 19:13:13 +0200 Subject: format --- src/main.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index c3ca53c..3adc6bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,12 @@ -#[macro_use] extern crate quicli; +#[macro_use] +extern crate quicli; extern crate ansi_term; +use ansi_term::Colour::{Green, Red, Yellow}; use quicli::prelude::*; -use ansi_term::Colour::{Red, Yellow, Green}; macro_rules! verify { - ( $str:expr, $left:expr, $right:expr ) => { + ($left:expr, $right:expr, $str:expr) => { if ($left == $right) { println!("{} {}", Green.bold().paint("PASS"), $str); } else { @@ -13,11 +14,11 @@ macro_rules! verify { println!("\tYou submitted {}, but that's not correct!", $left); println!("\tPlease correct your code to make this test pass!"); } - } + }; } macro_rules! verify_easy { - ( $str:expr, $left:expr, $right:expr ) => { + ($str:expr, $left:expr, $right:expr) => { if ($left == $right) { println!("{} {}", Green.bold().paint("PASS"), $str); } else { @@ -26,7 +27,7 @@ macro_rules! verify_easy { println!("\tGot: {}", $left); println!("\tPlease correct your code to make this test pass!"); } - } + }; } mod about_variables; @@ -36,11 +37,9 @@ struct Cli { exercise: Option, } -main!(|args: Cli| { - if let Some(e) = args.exercise { - println!("selected {}", e); - } else { - println!("Welcome to {}", Yellow.paint("rustlings")); - verify!("One equals one", 1, 2); - } +main!(|args: Cli| if let Some(e) = args.exercise { + println!("selected {}", e); +} else { + println!("Welcome to {}", Yellow.paint("rustlings")); + verify!(2, 1, "One equals one"); }); -- cgit v1.2.3 From d9946a91d429b2de2d0e21a2f346821f29c6ec5a Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 16 May 2018 15:23:14 +0200 Subject: make the example work --- src/about_variables.rs | 4 ++-- src/macros.rs | 31 +++++++++++++++++++++++++++++++ src/main.rs | 30 +++--------------------------- 3 files changed, 36 insertions(+), 29 deletions(-) create mode 100644 src/macros.rs diff --git a/src/about_variables.rs b/src/about_variables.rs index 4827dcf..9e64904 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -1,5 +1,5 @@ #[allow(dead_code)] -pub fn guess_this () -> i32 { +fn guess_this () -> i32 { let one = 5; let two = 7; let three = 3; @@ -11,7 +11,7 @@ mod tests { use super::*; pub fn test_complicated () { - assert_eq!(1, guess_this()); + verify!(1, guess_this(), "Complicated example"); } } diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..5c80b84 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,31 @@ +#[macro_export] +macro_rules! verify { + ($left:expr, $right:expr, $str:expr) => { + use ansi_term::Color::{Green, Red}; + + if $left == $right { + println!("{} {}", Green.bold().paint("PASS"), $str); + } else { + println!("{} {}", Red.bold().paint("FAIL"), $str); + println!("\tYou submitted {}, but that's not correct!", $left); + println!("\tPlease correct your code to make this test pass!"); + } + }; +} + +#[macro_export] +macro_rules! verify_easy { + ($str:expr, $left:expr, $right:expr) => { + use ansi_term::Color::{Green, Red}; + + if $left == $right { + println!("{} {}", Green.bold().paint("PASS"), $str); + } else { + println!("{} {}", Red.bold().paint("FAIL"), $str); + println!("\tExpected: {}", $right); + println!("\tGot: {}", $left); + println!("\tPlease correct your code to make this test pass!"); + } + }; +} + diff --git a/src/main.rs b/src/main.rs index 3adc6bd..525baa4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,34 +2,10 @@ extern crate quicli; extern crate ansi_term; -use ansi_term::Colour::{Green, Red, Yellow}; use quicli::prelude::*; +use ansi_term::Color::Yellow; -macro_rules! verify { - ($left:expr, $right:expr, $str:expr) => { - if ($left == $right) { - println!("{} {}", Green.bold().paint("PASS"), $str); - } else { - println!("{} {}", Red.bold().paint("FAIL"), $str); - println!("\tYou submitted {}, but that's not correct!", $left); - println!("\tPlease correct your code to make this test pass!"); - } - }; -} - -macro_rules! verify_easy { - ($str:expr, $left:expr, $right:expr) => { - if ($left == $right) { - println!("{} {}", Green.bold().paint("PASS"), $str); - } else { - println!("{} {}", Red.bold().paint("FAIL"), $str); - println!("\tExpected: {}", $right); - println!("\tGot: {}", $left); - println!("\tPlease correct your code to make this test pass!"); - } - }; -} - +#[macro_use] mod macros; mod about_variables; #[derive(Debug, StructOpt)] @@ -41,5 +17,5 @@ main!(|args: Cli| if let Some(e) = args.exercise { println!("selected {}", e); } else { println!("Welcome to {}", Yellow.paint("rustlings")); - verify!(2, 1, "One equals one"); + about_variables::exec(); }); -- cgit v1.2.3 From 39b3e3225ab1473eab954f8ce2458abd6e5671c7 Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 16 May 2018 15:27:52 +0200 Subject: add another example --- src/about_variables.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/about_variables.rs b/src/about_variables.rs index 9e64904..ede3479 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -1,4 +1,3 @@ -#[allow(dead_code)] fn guess_this () -> i32 { let one = 5; let two = 7; @@ -7,14 +6,24 @@ fn guess_this () -> i32 { return result; } +fn simple () -> &'static str { + let hello = "Hello World!"; + return hello; +} + mod tests { use super::*; + pub fn test_simple () { + verify!("Hello World!", simple(), "Simple example"); + } + pub fn test_complicated () { verify!(1, guess_this(), "Complicated example"); } } pub fn exec () { + tests::test_simple(); tests::test_complicated(); } -- cgit v1.2.3 From 5310dfd4065bb28337402792878627a2bc390d5e Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 16 May 2018 15:27:57 +0200 Subject: make the initial output prettier --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 525baa4..e708402 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,6 @@ struct Cli { main!(|args: Cli| if let Some(e) = args.exercise { println!("selected {}", e); } else { - println!("Welcome to {}", Yellow.paint("rustlings")); + println!("Welcome to {}!\n", Yellow.paint("Rustlings")); about_variables::exec(); }); -- cgit v1.2.3 From 89f2a986c07da3f8ecde5fdc2e2edc5ac110ef21 Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 16 May 2018 15:30:30 +0200 Subject: rustfmt --- src/about_variables.rs | 10 +++++----- src/macros.rs | 1 - src/main.rs | 5 +++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/about_variables.rs b/src/about_variables.rs index ede3479..ab2f143 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -1,4 +1,4 @@ -fn guess_this () -> i32 { +fn guess_this() -> i32 { let one = 5; let two = 7; let three = 3; @@ -6,7 +6,7 @@ fn guess_this () -> i32 { return result; } -fn simple () -> &'static str { +fn simple() -> &'static str { let hello = "Hello World!"; return hello; } @@ -14,16 +14,16 @@ fn simple () -> &'static str { mod tests { use super::*; - pub fn test_simple () { + pub fn test_simple() { verify!("Hello World!", simple(), "Simple example"); } - pub fn test_complicated () { + pub fn test_complicated() { verify!(1, guess_this(), "Complicated example"); } } -pub fn exec () { +pub fn exec() { tests::test_simple(); tests::test_complicated(); } diff --git a/src/macros.rs b/src/macros.rs index 5c80b84..4bc0871 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -28,4 +28,3 @@ macro_rules! verify_easy { } }; } - diff --git a/src/main.rs b/src/main.rs index e708402..68b8c9e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,10 +2,11 @@ extern crate quicli; extern crate ansi_term; -use quicli::prelude::*; use ansi_term::Color::Yellow; +use quicli::prelude::*; -#[macro_use] mod macros; +#[macro_use] +mod macros; mod about_variables; #[derive(Debug, StructOpt)] -- cgit v1.2.3 From 71a6041edfa14bfb66732c3b397a735e4d667ec3 Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 20:59:50 +0200 Subject: add some basic docs --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/README.md b/README.md index bcd03a9..2a51411 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,39 @@ A cool thing that is currently in development. +## How it's structured + +Ideally, like RubyKoans, all exercises can be run by executing one command, in this case +`cargo run` (most likely). This runs `src/main.rs`, which in turn runs all of the exercises. +Each exercise is contained in a Rust file called `about_.rs`. A minimal exercise looks +somewhat like this: + +```rust +fn exercise_function() { + "hello" +} + +mod tests { + use super::*; + + pub fn test() { + verify!("REPLACE ME", exercise_function(), "Function description"); + } +} + +pub fn exec() { + tests::test(); +} +``` + +Each exercise file is supposed to have one `exec` function which gets called by the `main.rs` file. +This function, in turn, calls all individual test functions. + +The tests themselves can generally be structured in whatever way is desired. Two macros are provided +for convenience. The `verify!` macro is essentially a specialized `assert_eq!`, but it doesn't panic +if the values mismatch, instead it prints out a helpful error message and keeps going. The +`verify_easy!` macro is designed as a drop-in replacement for the `verify!` macro for if the learner needs help solving the exercise. It prints the expected value, too. + +Keep in mind that this is a very early draft of how things work. Anything here might be changed +at any time, and this documentation should be updated accordingly. + -- cgit v1.2.3 From 729217da2f6307f409c5f41b79d64b92c7276e97 Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 21:03:19 +0200 Subject: add console output image --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2a51411..563ec94 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,10 @@ for convenience. The `verify!` macro is essentially a specialized `assert_eq!`, if the values mismatch, instead it prints out a helpful error message and keeps going. The `verify_easy!` macro is designed as a drop-in replacement for the `verify!` macro for if the learner needs help solving the exercise. It prints the expected value, too. +This is roughly what the console output for a simple exercise looks right now: + +![](https://i.imgur.com/gGgjvLW.png) + Keep in mind that this is a very early draft of how things work. Anything here might be changed at any time, and this documentation should be updated accordingly. -- cgit v1.2.3 From 6d5096534454ae934328f9ed634f58fae7f208f9 Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 21:22:21 +0200 Subject: port the first exercise from the old curriculum --- src/about_variables.rs | 55 +++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/about_variables.rs b/src/about_variables.rs index ab2f143..bef8049 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -1,29 +1,38 @@ -fn guess_this() -> i32 { - let one = 5; - let two = 7; - let three = 3; - let result = (one + two) / three; - return result; -} +// Welcome to Rustlings! If you're here, that means you've either successfully +// downloaded Rustlings, or are looking at this on GitHub. Either way, let me +// introduce you to one of the most basic elements of Rust: +// +// === VARIABLES === +// +// Variables are essentially little containers that hold, well, something. Think +// of them as a little cardboard box that you put stuff into. What can you put +// into a virtual cardboard box in Rust? All kinds of stuff, it turns out! +// Numbers, words, sequences, and much more. Let's start out simple, though. +// Here's our first exercise: -fn simple() -> &'static str { - let hello = "Hello World!"; - return hello; +pub fn exercise_one() { + let x = 5; + verify!(0, x, "Number assignment"); + // ^ ^ + // | | + // What's The variable + // in it itself } -mod tests { - use super::*; - - pub fn test_simple() { - verify!("Hello World!", simple(), "Simple example"); - } - - pub fn test_complicated() { - verify!(1, guess_this(), "Complicated example"); - } -} +// Did you get all that? The "let" word basically tells us that we now want to +// define a variable, and what follows it, the "x" is the name of the variable. +// Each variable has a name, like a label you put on your cardboard box so you +// don't confuse it with another, similar looking one. +// The whole "verify!" deal essentially means that Rustlings is checking if you +// solved the exercise correctly. It compares the first argument with the +// second, so in this case "0" with "x", where "x" is the _value_ of the variable +// we called "x". When you write "x", you pull out the cardboard box labelled "x" +// and take out what's inside of it. +// Speaking of which, what *is* inside of our "x" cardboard box? I don't think it's +// "0"... do you know? Replace the "0" with the value of the variable we defined. +// After that, run "cargo run" in your command line, and see if you put in the +// right answer. pub fn exec() { - tests::test_simple(); - tests::test_complicated(); + exercise_one(); } -- cgit v1.2.3 From 2f1e3bc0c7fbc4f6a692ce6315ab4c775a6f52fe Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 21:24:43 +0200 Subject: small fixes --- src/about_variables.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/about_variables.rs b/src/about_variables.rs index bef8049..6ae4124 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -16,16 +16,16 @@ pub fn exercise_one() { // ^ ^ // | | // What's The variable - // in it itself + // in it name } // Did you get all that? The "let" word basically tells us that we now want to -// define a variable, and what follows it, the "x" is the name of the variable. +// define a variable, and what follows it (the "x") is the name of the variable. // Each variable has a name, like a label you put on your cardboard box so you // don't confuse it with another, similar looking one. // The whole "verify!" deal essentially means that Rustlings is checking if you // solved the exercise correctly. It compares the first argument with the -// second, so in this case "0" with "x", where "x" is the _value_ of the variable +// second, so in this case "0" with "x", where "x" is the *value* of the variable // we called "x". When you write "x", you pull out the cardboard box labelled "x" // and take out what's inside of it. // Speaking of which, what *is* inside of our "x" cardboard box? I don't think it's -- cgit v1.2.3 From 69ff4a8b2554f4113b759a7935cb611aa13ab9ad Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 22:23:22 +0200 Subject: replace macros with more general methods --- src/about_variables.rs | 53 +++++++++++++++++++++++++------------------------- src/macros.rs | 17 +++++++++++----- src/main.rs | 36 +++++++++++++++++++++++++++++++--- 3 files changed, 72 insertions(+), 34 deletions(-) diff --git a/src/about_variables.rs b/src/about_variables.rs index 6ae4124..b4ebda0 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -1,38 +1,39 @@ -// Welcome to Rustlings! If you're here, that means you've either successfully -// downloaded Rustlings, or are looking at this on GitHub. Either way, let me -// introduce you to one of the most basic elements of Rust: -// -// === VARIABLES === -// -// Variables are essentially little containers that hold, well, something. Think -// of them as a little cardboard box that you put stuff into. What can you put -// into a virtual cardboard box in Rust? All kinds of stuff, it turns out! -// Numbers, words, sequences, and much more. Let's start out simple, though. -// Here's our first exercise: +use title; +use verify; -pub fn exercise_one() { +// Variables in Rust are defined using the "let" keyword. Like this: + +fn exercise_one() { let x = 5; - verify!(0, x, "Number assignment"); + verify(5, x); // ^ ^ // | | // What's The variable // in it name } -// Did you get all that? The "let" word basically tells us that we now want to -// define a variable, and what follows it (the "x") is the name of the variable. -// Each variable has a name, like a label you put on your cardboard box so you -// don't confuse it with another, similar looking one. -// The whole "verify!" deal essentially means that Rustlings is checking if you -// solved the exercise correctly. It compares the first argument with the -// second, so in this case "0" with "x", where "x" is the *value* of the variable -// we called "x". When you write "x", you pull out the cardboard box labelled "x" -// and take out what's inside of it. -// Speaking of which, what *is* inside of our "x" cardboard box? I don't think it's -// "0"... do you know? Replace the "0" with the value of the variable we defined. -// After that, run "cargo run" in your command line, and see if you put in the -// right answer. +// Try to replace the "0" with the value of the variable, then run +// "cargo run" and see if it was correct! + +// Here's a more complicated example: + +fn guess_me() -> &'static str { + let x = 10; + if x == 10 { + return "Ten!"; + } else { + return "Not ten!"; + } +} + +fn exercise_two() { + let result = guess_me(); + verify("REPLACE ME", result); +} pub fn exec() { + title("Variables: Exercise 1"); exercise_one(); + title("Variables: Exercise 2"); + exercise_two(); } diff --git a/src/macros.rs b/src/macros.rs index 4bc0871..22c8783 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,14 +1,21 @@ +#[macro_export] +macro_rules! title { + ($str:expr) => { + println!("{} {}", ansi_term::Color::Yellow.bold().paint("RUN"), $str); + } +} + #[macro_export] macro_rules! verify { - ($left:expr, $right:expr, $str:expr) => { + ($left:expr, $right:expr) => { use ansi_term::Color::{Green, Red}; if $left == $right { - println!("{} {}", Green.bold().paint("PASS"), $str); + println!("{} {} == {}", Green.bold().paint("PASS"), $left, $right); } else { - println!("{} {}", Red.bold().paint("FAIL"), $str); - println!("\tYou submitted {}, but that's not correct!", $left); - println!("\tPlease correct your code to make this test pass!"); + print!("{}", Red.bold().paint("FAIL")); + println!(" You submitted {}, but that's not correct!", $left); + println!(" Please correct your code to make this test pass!"); } }; } diff --git a/src/main.rs b/src/main.rs index 68b8c9e..133bdf4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,11 +2,41 @@ extern crate quicli; extern crate ansi_term; -use ansi_term::Color::Yellow; +use ansi_term::Color::{Green, Red, Yellow}; use quicli::prelude::*; +use std::fmt::Display; + +pub fn verify(left: T, right: T) { + if left == right { + println!("{} {} == {}", Green.bold().paint("PASS"), left, right); + } else { + println!( + "{} You submitted {}, but that's not correct!", + Red.bold().paint("FAIL"), + left + ); + println!(" Please correct your code to make this test pass!"); + } +} + +pub fn verify_easy(left: T, right: T) { + if left == right { + println!("{} {} == {}", Green.bold().paint("PASS"), left, right); + } else { + println!( + "{} You submitted {}, but that's not correct!", + Red.bold().paint("FAIL"), + left + ); + println!(" Expected: {}", right); + println!(" Please correct your code to make this test pass!"); + } +} + +pub fn title(s: &str) { + println!("{} {}", Yellow.bold().paint("RUN"), s); +} -#[macro_use] -mod macros; mod about_variables; #[derive(Debug, StructOpt)] -- cgit v1.2.3 From 4eca18050f21b3bc69477118845903ec61283d4f Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 22:26:09 +0200 Subject: put it in a separate file --- src/about_variables.rs | 3 +-- src/macros.rs | 37 ------------------------------------- src/main.rs | 35 ++--------------------------------- 3 files changed, 3 insertions(+), 72 deletions(-) delete mode 100644 src/macros.rs diff --git a/src/about_variables.rs b/src/about_variables.rs index b4ebda0..1587dc0 100644 --- a/src/about_variables.rs +++ b/src/about_variables.rs @@ -1,5 +1,4 @@ -use title; -use verify; +use helpers::*; // Variables in Rust are defined using the "let" keyword. Like this: diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index 22c8783..0000000 --- a/src/macros.rs +++ /dev/null @@ -1,37 +0,0 @@ -#[macro_export] -macro_rules! title { - ($str:expr) => { - println!("{} {}", ansi_term::Color::Yellow.bold().paint("RUN"), $str); - } -} - -#[macro_export] -macro_rules! verify { - ($left:expr, $right:expr) => { - use ansi_term::Color::{Green, Red}; - - if $left == $right { - println!("{} {} == {}", Green.bold().paint("PASS"), $left, $right); - } else { - print!("{}", Red.bold().paint("FAIL")); - println!(" You submitted {}, but that's not correct!", $left); - println!(" Please correct your code to make this test pass!"); - } - }; -} - -#[macro_export] -macro_rules! verify_easy { - ($str:expr, $left:expr, $right:expr) => { - use ansi_term::Color::{Green, Red}; - - if $left == $right { - println!("{} {}", Green.bold().paint("PASS"), $str); - } else { - println!("{} {}", Red.bold().paint("FAIL"), $str); - println!("\tExpected: {}", $right); - println!("\tGot: {}", $left); - println!("\tPlease correct your code to make this test pass!"); - } - }; -} diff --git a/src/main.rs b/src/main.rs index 133bdf4..02f0227 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,41 +2,10 @@ extern crate quicli; extern crate ansi_term; -use ansi_term::Color::{Green, Red, Yellow}; +use ansi_term::Color::Yellow; use quicli::prelude::*; -use std::fmt::Display; - -pub fn verify(left: T, right: T) { - if left == right { - println!("{} {} == {}", Green.bold().paint("PASS"), left, right); - } else { - println!( - "{} You submitted {}, but that's not correct!", - Red.bold().paint("FAIL"), - left - ); - println!(" Please correct your code to make this test pass!"); - } -} - -pub fn verify_easy(left: T, right: T) { - if left == right { - println!("{} {} == {}", Green.bold().paint("PASS"), left, right); - } else { - println!( - "{} You submitted {}, but that's not correct!", - Red.bold().paint("FAIL"), - left - ); - println!(" Expected: {}", right); - println!(" Please correct your code to make this test pass!"); - } -} - -pub fn title(s: &str) { - println!("{} {}", Yellow.bold().paint("RUN"), s); -} +mod helpers; mod about_variables; #[derive(Debug, StructOpt)] -- cgit v1.2.3 From 54f58cd726eeb7acc2ebb1491729444aab367e87 Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 22:27:51 +0200 Subject: update docs --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 563ec94..4ddaae5 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ pub fn exec() { Each exercise file is supposed to have one `exec` function which gets called by the `main.rs` file. This function, in turn, calls all individual test functions. -The tests themselves can generally be structured in whatever way is desired. Two macros are provided -for convenience. The `verify!` macro is essentially a specialized `assert_eq!`, but it doesn't panic +The tests themselves can generally be structured in whatever way is desired, there doesn't have to be a "tests" module, for example. Two macros are provided +for convenience. The `verify` helper function is essentially a specialized `assert_eq!`, but it doesn't panic if the values mismatch, instead it prints out a helpful error message and keeps going. The -`verify_easy!` macro is designed as a drop-in replacement for the `verify!` macro for if the learner needs help solving the exercise. It prints the expected value, too. +`verify_easy` function is designed as a drop-in replacement for the `verify` function for if the learner needs help solving the exercise. It prints the expected value, too. This is roughly what the console output for a simple exercise looks right now: -- cgit v1.2.3 From 850a13e9133fedb2fce27884902e0aab94da9692 Mon Sep 17 00:00:00 2001 From: olivia Date: Tue, 22 May 2018 22:28:13 +0200 Subject: oh, commit this --- src/helpers.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/helpers.rs diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..e0b560b --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,33 @@ +use ansi_term::Color::{Green, Red, Yellow}; +use std::fmt::Display; + +pub fn verify(left: T, right: T) { + if left == right { + println!("{} {} == {}", Green.bold().paint("PASS"), left, right); + } else { + println!( + "{} You submitted {}, but that's not correct!", + Red.bold().paint("FAIL"), + left + ); + println!(" Please correct your code to make this test pass!"); + } +} + +pub fn verify_easy(left: T, right: T) { + if left == right { + println!("{} {} == {}", Green.bold().paint("PASS"), left, right); + } else { + println!( + "{} You submitted {}, but that's not correct!", + Red.bold().paint("FAIL"), + left + ); + println!(" Expected: {}", right); + println!(" Please correct your code to make this test pass!"); + } +} + +pub fn title(s: &str) { + println!("{} {}", Yellow.bold().paint("RUN"), s); +} -- cgit v1.2.3 From f7846af7ac388652a6f80a2bbce926ba8f053062 Mon Sep 17 00:00:00 2001 From: olivia Date: Fri, 9 Nov 2018 20:31:14 +0100 Subject: right let's try this one again --- .DS_Store | Bin 0 -> 6148 bytes Cargo.toml | 5 +- README.md | 41 -- exercises/error_handling/errors1.rs | 73 ++++ exercises/error_handling/errors2.rs | 72 ++++ exercises/error_handling/errors3.rs | 62 +++ exercises/error_handling/errorsn.rs | 138 +++++++ exercises/error_handling/option1.rs | 45 ++ exercises/error_handling/result1.rs | 43 ++ exercises/ex1.rs | 6 + exercises/ex2.rs | 10 + exercises/ex3.rs | 10 + exercises/ex4.rs | 14 + exercises/ex5.rs | 22 + exercises/functions/functions1.rs | 44 ++ exercises/functions/functions2.rs | 42 ++ exercises/functions/functions3.rs | 42 ++ exercises/functions/functions4.rs | 44 ++ exercises/functions/functions5.rs | 47 +++ exercises/if/if1.rs | 58 +++ exercises/macros/macros1.rs | 64 +++ exercises/macros/macros2.rs | 73 ++++ exercises/macros/macros3.rs | 75 ++++ exercises/macros/macros4.rs | 77 ++++ exercises/modules/modules1.rs | 43 ++ exercises/modules/modules2.rs | 45 ++ exercises/move_semantics/move_semantics1.rs | 43 ++ exercises/move_semantics/move_semantics2.rs | 54 +++ exercises/move_semantics/move_semantics3.rs | 46 +++ exercises/move_semantics/move_semantics4.rs | 48 +++ exercises/primitive_types/primitive_types1.rs | 17 + exercises/primitive_types/primitive_types2.rs | 27 ++ exercises/primitive_types/primitive_types3.rs | 47 +++ exercises/primitive_types/primitive_types4.rs | 49 +++ exercises/primitive_types/primitive_types5.rs | 45 ++ exercises/primitive_types/primitive_types6.rs | 45 ++ exercises/standard_library_types/arc1.rs | 56 +++ exercises/standard_library_types/iterator3.rs | 147 +++++++ exercises/standard_library_types/iterators4.rs | 61 +++ exercises/strings/strings1.rs | 46 +++ exercises/strings/strings2.rs | 44 ++ exercises/strings/strings3.rs | 21 + exercises/tests/tests1.rs | 49 +++ exercises/tests/tests2.rs | 44 ++ exercises/tests/tests3.rs | 43 ++ exercises/tests/tests4.rs | 19 + exercises/threads/threads1.rs | 95 +++++ exercises/variables/variables1.rs | 42 ++ exercises/variables/variables2.rs | 47 +++ exercises/variables/variables3.rs | 43 ++ exercises/variables/variables4.rs | 45 ++ old_curriculum/.travis.yml | 19 - old_curriculum/Cargo.lock | 456 --------------------- old_curriculum/Cargo.toml | 9 - old_curriculum/README-template.hbs | 190 --------- old_curriculum/error_handling/errors1.rs | 73 ---- old_curriculum/error_handling/errors2.rs | 72 ---- old_curriculum/error_handling/errors3.rs | 67 --- old_curriculum/error_handling/errorsn.rs | 138 ------- old_curriculum/error_handling/option1.rs | 45 -- old_curriculum/error_handling/result1.rs | 43 -- old_curriculum/ex1.rs | 6 - old_curriculum/ex2.rs | 10 - old_curriculum/ex3.rs | 10 - old_curriculum/ex4.rs | 14 - old_curriculum/ex5.rs | 22 - old_curriculum/functions/functions1.rs | 44 -- old_curriculum/functions/functions2.rs | 42 -- old_curriculum/functions/functions3.rs | 42 -- old_curriculum/functions/functions4.rs | 44 -- old_curriculum/functions/functions5.rs | 44 -- old_curriculum/if/if1.rs | 58 --- old_curriculum/macros/macros1.rs | 64 --- old_curriculum/macros/macros2.rs | 73 ---- old_curriculum/macros/macros3.rs | 75 ---- old_curriculum/macros/macros4.rs | 77 ---- old_curriculum/modules/modules1.rs | 43 -- old_curriculum/modules/modules2.rs | 45 -- old_curriculum/move_semantics/move_semantics1.rs | 43 -- old_curriculum/move_semantics/move_semantics2.rs | 54 --- old_curriculum/move_semantics/move_semantics3.rs | 46 --- old_curriculum/move_semantics/move_semantics4.rs | 48 --- old_curriculum/primitive_types/primitive_types1.rs | 17 - old_curriculum/primitive_types/primitive_types2.rs | 27 -- old_curriculum/primitive_types/primitive_types3.rs | 46 --- old_curriculum/primitive_types/primitive_types4.rs | 49 --- old_curriculum/primitive_types/primitive_types5.rs | 45 -- old_curriculum/primitive_types/primitive_types6.rs | 44 -- old_curriculum/src/bin/generate_readme.rs | 49 --- old_curriculum/standard_library_types/arc1.rs | 56 --- old_curriculum/standard_library_types/iterator3.rs | 145 ------- .../standard_library_types/iterators4.rs | 61 --- old_curriculum/strings/strings1.rs | 46 --- old_curriculum/strings/strings2.rs | 44 -- old_curriculum/strings/strings3.rs | 21 - old_curriculum/tests/tests1.rs | 49 --- old_curriculum/tests/tests2.rs | 44 -- old_curriculum/tests/tests3.rs | 43 -- old_curriculum/tests/tests4.rs | 19 - old_curriculum/threads/threads1.rs | 95 ----- old_curriculum/variables/variables1.rs | 42 -- old_curriculum/variables/variables2.rs | 47 --- old_curriculum/variables/variables3.rs | 43 -- old_curriculum/variables/variables4.rs | 45 -- src/about_variables.rs | 38 -- src/helpers.rs | 33 -- src/main.rs | 55 ++- 107 files changed, 2414 insertions(+), 3223 deletions(-) create mode 100644 .DS_Store create mode 100755 exercises/error_handling/errors1.rs create mode 100755 exercises/error_handling/errors2.rs create mode 100755 exercises/error_handling/errors3.rs create mode 100755 exercises/error_handling/errorsn.rs create mode 100755 exercises/error_handling/option1.rs create mode 100755 exercises/error_handling/result1.rs create mode 100755 exercises/ex1.rs create mode 100755 exercises/ex2.rs create mode 100755 exercises/ex3.rs create mode 100755 exercises/ex4.rs create mode 100755 exercises/ex5.rs create mode 100755 exercises/functions/functions1.rs create mode 100755 exercises/functions/functions2.rs create mode 100755 exercises/functions/functions3.rs create mode 100755 exercises/functions/functions4.rs create mode 100755 exercises/functions/functions5.rs create mode 100755 exercises/if/if1.rs create mode 100755 exercises/macros/macros1.rs create mode 100755 exercises/macros/macros2.rs create mode 100755 exercises/macros/macros3.rs create mode 100755 exercises/macros/macros4.rs create mode 100755 exercises/modules/modules1.rs create mode 100755 exercises/modules/modules2.rs create mode 100755 exercises/move_semantics/move_semantics1.rs create mode 100755 exercises/move_semantics/move_semantics2.rs create mode 100755 exercises/move_semantics/move_semantics3.rs create mode 100755 exercises/move_semantics/move_semantics4.rs create mode 100755 exercises/primitive_types/primitive_types1.rs create mode 100755 exercises/primitive_types/primitive_types2.rs create mode 100755 exercises/primitive_types/primitive_types3.rs create mode 100755 exercises/primitive_types/primitive_types4.rs create mode 100755 exercises/primitive_types/primitive_types5.rs create mode 100755 exercises/primitive_types/primitive_types6.rs create mode 100755 exercises/standard_library_types/arc1.rs create mode 100755 exercises/standard_library_types/iterator3.rs create mode 100755 exercises/standard_library_types/iterators4.rs create mode 100755 exercises/strings/strings1.rs create mode 100755 exercises/strings/strings2.rs create mode 100755 exercises/strings/strings3.rs create mode 100755 exercises/tests/tests1.rs create mode 100755 exercises/tests/tests2.rs create mode 100755 exercises/tests/tests3.rs create mode 100755 exercises/tests/tests4.rs create mode 100755 exercises/threads/threads1.rs create mode 100755 exercises/variables/variables1.rs create mode 100755 exercises/variables/variables2.rs create mode 100755 exercises/variables/variables3.rs create mode 100755 exercises/variables/variables4.rs delete mode 100644 old_curriculum/.travis.yml delete mode 100644 old_curriculum/Cargo.lock delete mode 100644 old_curriculum/Cargo.toml delete mode 100644 old_curriculum/README-template.hbs delete mode 100644 old_curriculum/error_handling/errors1.rs delete mode 100644 old_curriculum/error_handling/errors2.rs delete mode 100644 old_curriculum/error_handling/errors3.rs delete mode 100644 old_curriculum/error_handling/errorsn.rs delete mode 100644 old_curriculum/error_handling/option1.rs delete mode 100644 old_curriculum/error_handling/result1.rs delete mode 100644 old_curriculum/ex1.rs delete mode 100644 old_curriculum/ex2.rs delete mode 100644 old_curriculum/ex3.rs delete mode 100644 old_curriculum/ex4.rs delete mode 100644 old_curriculum/ex5.rs delete mode 100644 old_curriculum/functions/functions1.rs delete mode 100644 old_curriculum/functions/functions2.rs delete mode 100644 old_curriculum/functions/functions3.rs delete mode 100644 old_curriculum/functions/functions4.rs delete mode 100644 old_curriculum/functions/functions5.rs delete mode 100644 old_curriculum/if/if1.rs delete mode 100644 old_curriculum/macros/macros1.rs delete mode 100644 old_curriculum/macros/macros2.rs delete mode 100644 old_curriculum/macros/macros3.rs delete mode 100644 old_curriculum/macros/macros4.rs delete mode 100644 old_curriculum/modules/modules1.rs delete mode 100644 old_curriculum/modules/modules2.rs delete mode 100644 old_curriculum/move_semantics/move_semantics1.rs delete mode 100644 old_curriculum/move_semantics/move_semantics2.rs delete mode 100644 old_curriculum/move_semantics/move_semantics3.rs delete mode 100644 old_curriculum/move_semantics/move_semantics4.rs delete mode 100644 old_curriculum/primitive_types/primitive_types1.rs delete mode 100644 old_curriculum/primitive_types/primitive_types2.rs delete mode 100644 old_curriculum/primitive_types/primitive_types3.rs delete mode 100644 old_curriculum/primitive_types/primitive_types4.rs delete mode 100644 old_curriculum/primitive_types/primitive_types5.rs delete mode 100644 old_curriculum/primitive_types/primitive_types6.rs delete mode 100644 old_curriculum/src/bin/generate_readme.rs delete mode 100644 old_curriculum/standard_library_types/arc1.rs delete mode 100644 old_curriculum/standard_library_types/iterator3.rs delete mode 100644 old_curriculum/standard_library_types/iterators4.rs delete mode 100644 old_curriculum/strings/strings1.rs delete mode 100644 old_curriculum/strings/strings2.rs delete mode 100644 old_curriculum/strings/strings3.rs delete mode 100644 old_curriculum/tests/tests1.rs delete mode 100644 old_curriculum/tests/tests2.rs delete mode 100644 old_curriculum/tests/tests3.rs delete mode 100644 old_curriculum/tests/tests4.rs delete mode 100644 old_curriculum/threads/threads1.rs delete mode 100644 old_curriculum/variables/variables1.rs delete mode 100644 old_curriculum/variables/variables2.rs delete mode 100644 old_curriculum/variables/variables3.rs delete mode 100644 old_curriculum/variables/variables4.rs delete mode 100644 src/about_variables.rs delete mode 100644 src/helpers.rs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..956be3c Binary files /dev/null and b/.DS_Store differ diff --git a/Cargo.toml b/Cargo.toml index 5f5c8a9..bf4195d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,6 @@ version = "0.1.0" authors = ["olivia "] [dependencies] -quicli = "0.2.0" -ansi_term = "0.11.0" +clap = "2.32.0" +indicatif = "0.9.0" +console = "0.6.2" diff --git a/README.md b/README.md index 4ddaae5..8049c22 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,3 @@ # rustlings A cool thing that is currently in development. - -## How it's structured - -Ideally, like RubyKoans, all exercises can be run by executing one command, in this case -`cargo run` (most likely). This runs `src/main.rs`, which in turn runs all of the exercises. -Each exercise is contained in a Rust file called `about_.rs`. A minimal exercise looks -somewhat like this: - -```rust -fn exercise_function() { - "hello" -} - -mod tests { - use super::*; - - pub fn test() { - verify!("REPLACE ME", exercise_function(), "Function description"); - } -} - -pub fn exec() { - tests::test(); -} -``` - -Each exercise file is supposed to have one `exec` function which gets called by the `main.rs` file. -This function, in turn, calls all individual test functions. - -The tests themselves can generally be structured in whatever way is desired, there doesn't have to be a "tests" module, for example. Two macros are provided -for convenience. The `verify` helper function is essentially a specialized `assert_eq!`, but it doesn't panic -if the values mismatch, instead it prints out a helpful error message and keeps going. The -`verify_easy` function is designed as a drop-in replacement for the `verify` function for if the learner needs help solving the exercise. It prints the expected value, too. - -This is roughly what the console output for a simple exercise looks right now: - -![](https://i.imgur.com/gGgjvLW.png) - -Keep in mind that this is a very early draft of how things work. Anything here might be changed -at any time, and this documentation should be updated accordingly. - diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs new file mode 100755 index 0000000..14ed574 --- /dev/null +++ b/exercises/error_handling/errors1.rs @@ -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 { + 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)`. diff --git a/exercises/error_handling/errors2.rs b/exercises/error_handling/errors2.rs new file mode 100755 index 0000000..15c21c8 --- /dev/null +++ b/exercises/error_handling/errors2.rs @@ -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 { + let processing_fee = 1; + let cost_per_item = 5; + let qty = item_quantity.parse::(); + + 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::()` where the cases are `Ok(something)` and +// `Err(something)`. This pattern is very common in Rust, though, so there's +// a `?` operator 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/second-edition/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator +// and give it a try! diff --git a/exercises/error_handling/errors3.rs b/exercises/error_handling/errors3.rs new file mode 100755 index 0000000..9c29af5 --- /dev/null +++ b/exercises/error_handling/errors3.rs @@ -0,0 +1,62 @@ +// 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 use the `?` operator 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 = 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 { + let processing_fee = 1; + let cost_per_item = 5; + let qty = item_quantity.parse::()?; + + Ok(qty * cost_per_item + processing_fee) +} + + + + + + + + + + + + + + + + + + +// Since the `?` operator returns an `Err` early if the thing it's trying to +// do fails, you can only use the `?` operator in functions that have a +// `Result` as their return type. + +// Hence the error that you get if you run this code is: + +// ``` +// error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`) +// ``` + +// 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 using the `?` +// operator. diff --git a/exercises/error_handling/errorsn.rs b/exercises/error_handling/errorsn.rs new file mode 100755 index 0000000..15c6cd5 --- /dev/null +++ b/exercises/error_handling/errorsn.rs @@ -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 { + 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> { + 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 { + 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 { + 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). +// Apply the `?` operator on those calls so that we return immediately from +// `read_and_validate` if those function calls fail. + +// Another hint: under the hood, the `?` operator calls `From::from` +// on the error value to convert it to a boxed trait object, a Box, +// 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/second-edition/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator + +// Another another hint: Note that because the `?` operator 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 `?`ed 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 diff --git a/exercises/error_handling/option1.rs b/exercises/error_handling/option1.rs new file mode 100755 index 0000000..9cf0bc9 --- /dev/null +++ b/exercises/error_handling/option1.rs @@ -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! diff --git a/exercises/error_handling/result1.rs b/exercises/error_handling/result1.rs new file mode 100755 index 0000000..851ab45 --- /dev/null +++ b/exercises/error_handling/result1.rs @@ -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 { + 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 :) diff --git a/exercises/ex1.rs b/exercises/ex1.rs new file mode 100755 index 0000000..dc5f9ca --- /dev/null +++ b/exercises/ex1.rs @@ -0,0 +1,6 @@ +// ex1.rs +// Make me compile! :) + +fn main() { + println(); +} diff --git a/exercises/ex2.rs b/exercises/ex2.rs new file mode 100755 index 0000000..0fd714d --- /dev/null +++ b/exercises/ex2.rs @@ -0,0 +1,10 @@ +// ex2.rs +// Make me compile! + +fn something() -> String { + "hi!" +} + +fn main() { + println!("{}", something()); +} diff --git a/exercises/ex3.rs b/exercises/ex3.rs new file mode 100755 index 0000000..db27ad2 --- /dev/null +++ b/exercises/ex3.rs @@ -0,0 +1,10 @@ +// ex3.rs +// Make me compile! + +struct Foo { + capacity: i32, +} + +fn main() { + println!("{:?}", Foo { capacity: 3 }); +} diff --git a/exercises/ex4.rs b/exercises/ex4.rs new file mode 100755 index 0000000..362a557 --- /dev/null +++ b/exercises/ex4.rs @@ -0,0 +1,14 @@ +// ex4.rs +// Make me compile! + +fn something() -> Result { + 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), + } +} diff --git a/exercises/ex5.rs b/exercises/ex5.rs new file mode 100755 index 0000000..2eb8cfd --- /dev/null +++ b/exercises/ex5.rs @@ -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); +} diff --git a/exercises/functions/functions1.rs b/exercises/functions/functions1.rs new file mode 100755 index 0000000..396dd56 --- /dev/null +++ b/exercises/functions/functions1.rs @@ -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? diff --git a/exercises/functions/functions2.rs b/exercises/functions/functions2.rs new file mode 100755 index 0000000..1cf95c3 --- /dev/null +++ b/exercises/functions/functions2.rs @@ -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`. diff --git a/exercises/functions/functions3.rs b/exercises/functions/functions3.rs new file mode 100755 index 0000000..b17543b --- /dev/null +++ b/exercises/functions/functions3.rs @@ -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. diff --git a/exercises/functions/functions4.rs b/exercises/functions/functions4.rs new file mode 100755 index 0000000..5baca0e --- /dev/null +++ b/exercises/functions/functions4.rs @@ -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! diff --git a/exercises/functions/functions5.rs b/exercises/functions/functions5.rs new file mode 100755 index 0000000..d3ff002 --- /dev/null +++ b/exercises/functions/functions5.rs @@ -0,0 +1,47 @@ +// 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 based on its operand, and statements simply return a () type which behaves just like `void` in C/C++ language. +// We want to return a value of `i32` type from the `square` function, but it is returning a `()` type... +// They are not the same. There are two solutions: +// 1. Add a `return` ahead of `num * num;` +// 2. remove `;`, make it to be `num * num` diff --git a/exercises/if/if1.rs b/exercises/if/if1.rs new file mode 100755 index 0000000..5118657 --- /dev/null +++ b/exercises/if/if1.rs @@ -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. diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs new file mode 100755 index 0000000..a7c78a5 --- /dev/null +++ b/exercises/macros/macros1.rs @@ -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`. diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs new file mode 100755 index 0000000..bc2e56b --- /dev/null +++ b/exercises/macros/macros2.rs @@ -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. diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs new file mode 100755 index 0000000..84c4308 --- /dev/null +++ b/exercises/macros/macros3.rs @@ -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. diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs new file mode 100755 index 0000000..d844bb0 --- /dev/null +++ b/exercises/macros/macros4.rs @@ -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. diff --git a/exercises/modules/modules1.rs b/exercises/modules/modules1.rs new file mode 100755 index 0000000..0e092c5 --- /dev/null +++ b/exercises/modules/modules1.rs @@ -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. diff --git a/exercises/modules/modules2.rs b/exercises/modules/modules2.rs new file mode 100755 index 0000000..164dfb0 --- /dev/null +++ b/exercises/modules/modules2.rs @@ -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. diff --git a/exercises/move_semantics/move_semantics1.rs b/exercises/move_semantics/move_semantics1.rs new file mode 100755 index 0000000..37038ec --- /dev/null +++ b/exercises/move_semantics/move_semantics1.rs @@ -0,0 +1,43 @@ +// move_semantics1.rs +// Make me compile! Scroll down for hints :) + +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) -> Vec { + 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. diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs new file mode 100755 index 0000000..b50e349 --- /dev/null +++ b/exercises/move_semantics/move_semantics2.rs @@ -0,0 +1,54 @@ +// move_semantics2.rs +// Make me compile without changing line 10! Scroll down for hints :) + +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) -> Vec { + 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` +// 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!` diff --git a/exercises/move_semantics/move_semantics3.rs b/exercises/move_semantics/move_semantics3.rs new file mode 100755 index 0000000..8e7b0ad --- /dev/null +++ b/exercises/move_semantics/move_semantics3.rs @@ -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 :) + +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) -> Vec { + 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 :) diff --git a/exercises/move_semantics/move_semantics4.rs b/exercises/move_semantics/move_semantics4.rs new file mode 100755 index 0000000..903a330 --- /dev/null +++ b/exercises/move_semantics/move_semantics4.rs @@ -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! + +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) -> Vec { + 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` diff --git a/exercises/primitive_types/primitive_types1.rs b/exercises/primitive_types/primitive_types1.rs new file mode 100755 index 0000000..c3d11fe --- /dev/null +++ b/exercises/primitive_types/primitive_types1.rs @@ -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!"); + } +} diff --git a/exercises/primitive_types/primitive_types2.rs b/exercises/primitive_types/primitive_types2.rs new file mode 100755 index 0000000..f5c8f87 --- /dev/null +++ b/exercises/primitive_types/primitive_types2.rs @@ -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!"); + } +} diff --git a/exercises/primitive_types/primitive_types3.rs b/exercises/primitive_types/primitive_types3.rs new file mode 100755 index 0000000..7ce2226 --- /dev/null +++ b/exercises/primitive_types/primitive_types3.rs @@ -0,0 +1,47 @@ +// 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!). +// For example, you can do: +// let array = ["Are we there yet?"; 10]; + +// Bonus: what are some other things you could have that would return true +// for `a.len() >= 100`? diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs new file mode 100755 index 0000000..7dc9e47 --- /dev/null +++ b/exercises/primitive_types/primitive_types4.rs @@ -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 Understanding Ownership -> Slices -> Other Slices section of the book: +// https://doc.rust-lang.org/stable/book/second-edition/ch04-03-slices.html#other-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 section of the book: +// https://doc.rust-lang.org/stable/book/second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods diff --git a/exercises/primitive_types/primitive_types5.rs b/exercises/primitive_types/primitive_types5.rs new file mode 100755 index 0000000..4045e78 --- /dev/null +++ b/exercises/primitive_types/primitive_types5.rs @@ -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 Data Types -> The Tuple Type section of the book: +// https://doc.rust-lang.org/stable/book/second-edition/ch03-02-data-types.html#the-tuple-type +// Particularly the part about destructuring (second to last example in the section). +// You'll need to make a pattern to bind `name` and `age` to the appropriate parts +// of the tuple. You can do it!! diff --git a/exercises/primitive_types/primitive_types6.rs b/exercises/primitive_types/primitive_types6.rs new file mode 100755 index 0000000..439a56b --- /dev/null +++ b/exercises/primitive_types/primitive_types6.rs @@ -0,0 +1,45 @@ +// 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 in the last example of the +// Data Types -> The Tuple Type section of the book: +// https://doc.rust-lang.org/stable/book/second-edition/ch03-02-data-types.html#the-tuple-type +// Now you have another tool in your toolbox! diff --git a/exercises/standard_library_types/arc1.rs b/exercises/standard_library_types/arc1.rs new file mode 100755 index 0000000..c744a10 --- /dev/null +++ b/exercises/standard_library_types/arc1.rs @@ -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. diff --git a/exercises/standard_library_types/iterator3.rs b/exercises/standard_library_types/iterator3.rs new file mode 100755 index 0000000..1d2e135 --- /dev/null +++ b/exercises/standard_library_types/iterator3.rs @@ -0,0 +1,147 @@ +// 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 { +} + +#[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. diff --git a/exercises/standard_library_types/iterators4.rs b/exercises/standard_library_types/iterators4.rs new file mode 100755 index 0000000..13613a6 --- /dev/null +++ b/exercises/standard_library_types/iterators4.rs @@ -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. diff --git a/exercises/strings/strings1.rs b/exercises/strings/strings1.rs new file mode 100755 index 0000000..2e5088f --- /dev/null +++ b/exercises/strings/strings1.rs @@ -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. diff --git a/exercises/strings/strings2.rs b/exercises/strings/strings2.rs new file mode 100755 index 0000000..c77e16f --- /dev/null +++ b/exercises/strings/strings2.rs @@ -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. diff --git a/exercises/strings/strings3.rs b/exercises/strings/strings3.rs new file mode 100755 index 0000000..b6f6a1e --- /dev/null +++ b/exercises/strings/strings3.rs @@ -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()); +} diff --git a/exercises/tests/tests1.rs b/exercises/tests/tests1.rs new file mode 100755 index 0000000..959ed85 --- /dev/null +++ b/exercises/tests/tests1.rs @@ -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 :) diff --git a/exercises/tests/tests2.rs b/exercises/tests/tests2.rs new file mode 100755 index 0000000..6775d61 --- /dev/null +++ b/exercises/tests/tests2.rs @@ -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! diff --git a/exercises/tests/tests3.rs b/exercises/tests/tests3.rs new file mode 100755 index 0000000..e041f38 --- /dev/null +++ b/exercises/tests/tests3.rs @@ -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())`. diff --git a/exercises/tests/tests4.rs b/exercises/tests/tests4.rs new file mode 100755 index 0000000..23d444a --- /dev/null +++ b/exercises/tests/tests4.rs @@ -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); + } +} diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs new file mode 100755 index 0000000..4f9aa89 --- /dev/null +++ b/exercises/threads/threads1.rs @@ -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/second-edition/ch16-03-shared-state.html#atomic-reference-counting-with-arct +// 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 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 :) diff --git a/exercises/variables/variables1.rs b/exercises/variables/variables1.rs new file mode 100755 index 0000000..1cdd270 --- /dev/null +++ b/exercises/variables/variables1.rs @@ -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. diff --git a/exercises/variables/variables2.rs b/exercises/variables/variables2.rs new file mode 100755 index 0000000..a0b4a37 --- /dev/null +++ b/exercises/variables/variables2.rs @@ -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? diff --git a/exercises/variables/variables3.rs b/exercises/variables/variables3.rs new file mode 100755 index 0000000..165a277 --- /dev/null +++ b/exercises/variables/variables3.rs @@ -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. diff --git a/exercises/variables/variables4.rs b/exercises/variables/variables4.rs new file mode 100755 index 0000000..71ebf0f --- /dev/null +++ b/exercises/variables/variables4.rs @@ -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! diff --git a/old_curriculum/.travis.yml b/old_curriculum/.travis.yml deleted file mode 100644 index 684b265..0000000 --- a/old_curriculum/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -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 - diff --git a/old_curriculum/Cargo.lock b/old_curriculum/Cargo.lock deleted file mode 100644 index 7bff901..0000000 --- a/old_curriculum/Cargo.lock +++ /dev/null @@ -1,456 +0,0 @@ -[[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)" = "" -"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" diff --git a/old_curriculum/Cargo.toml b/old_curriculum/Cargo.toml deleted file mode 100644 index d82b8a1..0000000 --- a/old_curriculum/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "rustlings" -version = "0.1.0" -authors = ["Carol (Nichols || Goulding) "] - -[dependencies] -handlebars = "0.32.0" -serde_json = "1.0.10" -prlink = { git = "https://github.com/btbytes/prlink" } diff --git a/old_curriculum/README-template.hbs b/old_curriculum/README-template.hbs deleted file mode 100644 index 5cfec7f..0000000 --- a/old_curriculum/README-template.hbs +++ /dev/null @@ -1,190 +0,0 @@ - - -# 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?? diff --git a/old_curriculum/error_handling/errors1.rs b/old_curriculum/error_handling/errors1.rs deleted file mode 100644 index 14ed574..0000000 --- a/old_curriculum/error_handling/errors1.rs +++ /dev/null @@ -1,73 +0,0 @@ -// 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 { - 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)`. diff --git a/old_curriculum/error_handling/errors2.rs b/old_curriculum/error_handling/errors2.rs deleted file mode 100644 index 05824c1..0000000 --- a/old_curriculum/error_handling/errors2.rs +++ /dev/null @@ -1,72 +0,0 @@ -// 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 { - let processing_fee = 1; - let cost_per_item = 5; - let qty = item_quantity.parse::(); - - 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::()` 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!` diff --git a/old_curriculum/error_handling/errors3.rs b/old_curriculum/error_handling/errors3.rs deleted file mode 100644 index 9b285e0..0000000 --- a/old_curriculum/error_handling/errors3.rs +++ /dev/null @@ -1,67 +0,0 @@ -// 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 { - let processing_fee = 1; - let cost_per_item = 5; - let qty = try!(item_quantity.parse::()); - - 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. diff --git a/old_curriculum/error_handling/errorsn.rs b/old_curriculum/error_handling/errorsn.rs deleted file mode 100644 index ee1179d..0000000 --- a/old_curriculum/error_handling/errorsn.rs +++ /dev/null @@ -1,138 +0,0 @@ -// 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 { - 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> { - 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 { - 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 { - 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, -// 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 diff --git a/old_curriculum/error_handling/option1.rs b/old_curriculum/error_handling/option1.rs deleted file mode 100644 index 9cf0bc9..0000000 --- a/old_curriculum/error_handling/option1.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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! diff --git a/old_curriculum/error_handling/result1.rs b/old_curriculum/error_handling/result1.rs deleted file mode 100644 index 851ab45..0000000 --- a/old_curriculum/error_handling/result1.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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 { - 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 :) diff --git a/old_curriculum/ex1.rs b/old_curriculum/ex1.rs deleted file mode 100644 index dc5f9ca..0000000 --- a/old_curriculum/ex1.rs +++ /dev/null @@ -1,6 +0,0 @@ -// ex1.rs -// Make me compile! :) - -fn main() { - println(); -} diff --git a/old_curriculum/ex2.rs b/old_curriculum/ex2.rs deleted file mode 100644 index 0fd714d..0000000 --- a/old_curriculum/ex2.rs +++ /dev/null @@ -1,10 +0,0 @@ -// ex2.rs -// Make me compile! - -fn something() -> String { - "hi!" -} - -fn main() { - println!("{}", something()); -} diff --git a/old_curriculum/ex3.rs b/old_curriculum/ex3.rs deleted file mode 100644 index db27ad2..0000000 --- a/old_curriculum/ex3.rs +++ /dev/null @@ -1,10 +0,0 @@ -// ex3.rs -// Make me compile! - -struct Foo { - capacity: i32, -} - -fn main() { - println!("{:?}", Foo { capacity: 3 }); -} diff --git a/old_curriculum/ex4.rs b/old_curriculum/ex4.rs deleted file mode 100644 index 362a557..0000000 --- a/old_curriculum/ex4.rs +++ /dev/null @@ -1,14 +0,0 @@ -// ex4.rs -// Make me compile! - -fn something() -> Result { - 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), - } -} diff --git a/old_curriculum/ex5.rs b/old_curriculum/ex5.rs deleted file mode 100644 index 2eb8cfd..0000000 --- a/old_curriculum/ex5.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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); -} diff --git a/old_curriculum/functions/functions1.rs b/old_curriculum/functions/functions1.rs deleted file mode 100644 index 396dd56..0000000 --- a/old_curriculum/functions/functions1.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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? diff --git a/old_curriculum/functions/functions2.rs b/old_curriculum/functions/functions2.rs deleted file mode 100644 index 1cf95c3..0000000 --- a/old_curriculum/functions/functions2.rs +++ /dev/null @@ -1,42 +0,0 @@ -// 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`. diff --git a/old_curriculum/functions/functions3.rs b/old_curriculum/functions/functions3.rs deleted file mode 100644 index b17543b..0000000 --- a/old_curriculum/functions/functions3.rs +++ /dev/null @@ -1,42 +0,0 @@ -// 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. diff --git a/old_curriculum/functions/functions4.rs b/old_curriculum/functions/functions4.rs deleted file mode 100644 index 5baca0e..0000000 --- a/old_curriculum/functions/functions4.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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! diff --git a/old_curriculum/functions/functions5.rs b/old_curriculum/functions/functions5.rs deleted file mode 100644 index f8fac5d..0000000 --- a/old_curriculum/functions/functions5.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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... diff --git a/old_curriculum/if/if1.rs b/old_curriculum/if/if1.rs deleted file mode 100644 index 5118657..0000000 --- a/old_curriculum/if/if1.rs +++ /dev/null @@ -1,58 +0,0 @@ -// 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. diff --git a/old_curriculum/macros/macros1.rs b/old_curriculum/macros/macros1.rs deleted file mode 100644 index a7c78a5..0000000 --- a/old_curriculum/macros/macros1.rs +++ /dev/null @@ -1,64 +0,0 @@ -// 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`. diff --git a/old_curriculum/macros/macros2.rs b/old_curriculum/macros/macros2.rs deleted file mode 100644 index bc2e56b..0000000 --- a/old_curriculum/macros/macros2.rs +++ /dev/null @@ -1,73 +0,0 @@ -// 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. diff --git a/old_curriculum/macros/macros3.rs b/old_curriculum/macros/macros3.rs deleted file mode 100644 index 84c4308..0000000 --- a/old_curriculum/macros/macros3.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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. diff --git a/old_curriculum/macros/macros4.rs b/old_curriculum/macros/macros4.rs deleted file mode 100644 index d844bb0..0000000 --- a/old_curriculum/macros/macros4.rs +++ /dev/null @@ -1,77 +0,0 @@ -// 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. diff --git a/old_curriculum/modules/modules1.rs b/old_curriculum/modules/modules1.rs deleted file mode 100644 index 0e092c5..0000000 --- a/old_curriculum/modules/modules1.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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. diff --git a/old_curriculum/modules/modules2.rs b/old_curriculum/modules/modules2.rs deleted file mode 100644 index 164dfb0..0000000 --- a/old_curriculum/modules/modules2.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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. diff --git a/old_curriculum/move_semantics/move_semantics1.rs b/old_curriculum/move_semantics/move_semantics1.rs deleted file mode 100644 index 73dc0ab..0000000 --- a/old_curriculum/move_semantics/move_semantics1.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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) -> Vec { - 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. diff --git a/old_curriculum/move_semantics/move_semantics2.rs b/old_curriculum/move_semantics/move_semantics2.rs deleted file mode 100644 index bc42d8e..0000000 --- a/old_curriculum/move_semantics/move_semantics2.rs +++ /dev/null @@ -1,54 +0,0 @@ -// 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) -> Vec { - 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` -// 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!` diff --git a/old_curriculum/move_semantics/move_semantics3.rs b/old_curriculum/move_semantics/move_semantics3.rs deleted file mode 100644 index 7805d44..0000000 --- a/old_curriculum/move_semantics/move_semantics3.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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) -> Vec { - 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 :) diff --git a/old_curriculum/move_semantics/move_semantics4.rs b/old_curriculum/move_semantics/move_semantics4.rs deleted file mode 100644 index 2b1ed8a..0000000 --- a/old_curriculum/move_semantics/move_semantics4.rs +++ /dev/null @@ -1,48 +0,0 @@ -// 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) -> Vec { - 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` diff --git a/old_curriculum/primitive_types/primitive_types1.rs b/old_curriculum/primitive_types/primitive_types1.rs deleted file mode 100644 index c3d11fe..0000000 --- a/old_curriculum/primitive_types/primitive_types1.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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!"); - } -} diff --git a/old_curriculum/primitive_types/primitive_types2.rs b/old_curriculum/primitive_types/primitive_types2.rs deleted file mode 100644 index f5c8f87..0000000 --- a/old_curriculum/primitive_types/primitive_types2.rs +++ /dev/null @@ -1,27 +0,0 @@ -// 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!"); - } -} diff --git a/old_curriculum/primitive_types/primitive_types3.rs b/old_curriculum/primitive_types/primitive_types3.rs deleted file mode 100644 index a2f9b3b..0000000 --- a/old_curriculum/primitive_types/primitive_types3.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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`? diff --git a/old_curriculum/primitive_types/primitive_types4.rs b/old_curriculum/primitive_types/primitive_types4.rs deleted file mode 100644 index c20b63b..0000000 --- a/old_curriculum/primitive_types/primitive_types4.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 diff --git a/old_curriculum/primitive_types/primitive_types5.rs b/old_curriculum/primitive_types/primitive_types5.rs deleted file mode 100644 index 14c2fd2..0000000 --- a/old_curriculum/primitive_types/primitive_types5.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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!! diff --git a/old_curriculum/primitive_types/primitive_types6.rs b/old_curriculum/primitive_types/primitive_types6.rs deleted file mode 100644 index d016642..0000000 --- a/old_curriculum/primitive_types/primitive_types6.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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! diff --git a/old_curriculum/src/bin/generate_readme.rs b/old_curriculum/src/bin/generate_readme.rs deleted file mode 100644 index a502fea..0000000 --- a/old_curriculum/src/bin/generate_readme.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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(()) -} diff --git a/old_curriculum/standard_library_types/arc1.rs b/old_curriculum/standard_library_types/arc1.rs deleted file mode 100644 index c744a10..0000000 --- a/old_curriculum/standard_library_types/arc1.rs +++ /dev/null @@ -1,56 +0,0 @@ -// 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. diff --git a/old_curriculum/standard_library_types/iterator3.rs b/old_curriculum/standard_library_types/iterator3.rs deleted file mode 100644 index e973ac6..0000000 --- a/old_curriculum/standard_library_types/iterator3.rs +++ /dev/null @@ -1,145 +0,0 @@ -// 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 { -} - -#[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. diff --git a/old_curriculum/standard_library_types/iterators4.rs b/old_curriculum/standard_library_types/iterators4.rs deleted file mode 100644 index 13613a6..0000000 --- a/old_curriculum/standard_library_types/iterators4.rs +++ /dev/null @@ -1,61 +0,0 @@ -// 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. diff --git a/old_curriculum/strings/strings1.rs b/old_curriculum/strings/strings1.rs deleted file mode 100644 index 2e5088f..0000000 --- a/old_curriculum/strings/strings1.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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. diff --git a/old_curriculum/strings/strings2.rs b/old_curriculum/strings/strings2.rs deleted file mode 100644 index c77e16f..0000000 --- a/old_curriculum/strings/strings2.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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. diff --git a/old_curriculum/strings/strings3.rs b/old_curriculum/strings/strings3.rs deleted file mode 100644 index b6f6a1e..0000000 --- a/old_curriculum/strings/strings3.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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()); -} diff --git a/old_curriculum/tests/tests1.rs b/old_curriculum/tests/tests1.rs deleted file mode 100644 index 959ed85..0000000 --- a/old_curriculum/tests/tests1.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 :) diff --git a/old_curriculum/tests/tests2.rs b/old_curriculum/tests/tests2.rs deleted file mode 100644 index 6775d61..0000000 --- a/old_curriculum/tests/tests2.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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! diff --git a/old_curriculum/tests/tests3.rs b/old_curriculum/tests/tests3.rs deleted file mode 100644 index e041f38..0000000 --- a/old_curriculum/tests/tests3.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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())`. diff --git a/old_curriculum/tests/tests4.rs b/old_curriculum/tests/tests4.rs deleted file mode 100644 index 23d444a..0000000 --- a/old_curriculum/tests/tests4.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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); - } -} diff --git a/old_curriculum/threads/threads1.rs b/old_curriculum/threads/threads1.rs deleted file mode 100644 index b4a5dc9..0000000 --- a/old_curriculum/threads/threads1.rs +++ /dev/null @@ -1,95 +0,0 @@ -// 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 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 :) diff --git a/old_curriculum/variables/variables1.rs b/old_curriculum/variables/variables1.rs deleted file mode 100644 index 1cdd270..0000000 --- a/old_curriculum/variables/variables1.rs +++ /dev/null @@ -1,42 +0,0 @@ -// 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. diff --git a/old_curriculum/variables/variables2.rs b/old_curriculum/variables/variables2.rs deleted file mode 100644 index a0b4a37..0000000 --- a/old_curriculum/variables/variables2.rs +++ /dev/null @@ -1,47 +0,0 @@ -// 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? diff --git a/old_curriculum/variables/variables3.rs b/old_curriculum/variables/variables3.rs deleted file mode 100644 index 165a277..0000000 --- a/old_curriculum/variables/variables3.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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. diff --git a/old_curriculum/variables/variables4.rs b/old_curriculum/variables/variables4.rs deleted file mode 100644 index 71ebf0f..0000000 --- a/old_curriculum/variables/variables4.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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! diff --git a/src/about_variables.rs b/src/about_variables.rs deleted file mode 100644 index 1587dc0..0000000 --- a/src/about_variables.rs +++ /dev/null @@ -1,38 +0,0 @@ -use helpers::*; - -// Variables in Rust are defined using the "let" keyword. Like this: - -fn exercise_one() { - let x = 5; - verify(5, x); - // ^ ^ - // | | - // What's The variable - // in it name -} - -// Try to replace the "0" with the value of the variable, then run -// "cargo run" and see if it was correct! - -// Here's a more complicated example: - -fn guess_me() -> &'static str { - let x = 10; - if x == 10 { - return "Ten!"; - } else { - return "Not ten!"; - } -} - -fn exercise_two() { - let result = guess_me(); - verify("REPLACE ME", result); -} - -pub fn exec() { - title("Variables: Exercise 1"); - exercise_one(); - title("Variables: Exercise 2"); - exercise_two(); -} diff --git a/src/helpers.rs b/src/helpers.rs deleted file mode 100644 index e0b560b..0000000 --- a/src/helpers.rs +++ /dev/null @@ -1,33 +0,0 @@ -use ansi_term::Color::{Green, Red, Yellow}; -use std::fmt::Display; - -pub fn verify(left: T, right: T) { - if left == right { - println!("{} {} == {}", Green.bold().paint("PASS"), left, right); - } else { - println!( - "{} You submitted {}, but that's not correct!", - Red.bold().paint("FAIL"), - left - ); - println!(" Please correct your code to make this test pass!"); - } -} - -pub fn verify_easy(left: T, right: T) { - if left == right { - println!("{} {} == {}", Green.bold().paint("PASS"), left, right); - } else { - println!( - "{} You submitted {}, but that's not correct!", - Red.bold().paint("FAIL"), - left - ); - println!(" Expected: {}", right); - println!(" Please correct your code to make this test pass!"); - } -} - -pub fn title(s: &str) { - println!("{} {}", Yellow.bold().paint("RUN"), s); -} diff --git a/src/main.rs b/src/main.rs index 02f0227..cf2eddd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,44 @@ #[macro_use] -extern crate quicli; -extern crate ansi_term; +extern crate clap; +extern crate indicatif; +extern crate console; -use ansi_term::Color::Yellow; -use quicli::prelude::*; +use clap::{App, SubCommand}; +use indicatif::{ProgressBar}; +use console::{style, Emoji}; +use std::process::Command; -mod helpers; -mod about_variables; - -#[derive(Debug, StructOpt)] -struct Cli { - exercise: Option, +fn main() { + let matches = App::new("r2") + .version(crate_version!()) + .author("Olivia Hugger") + .about("Test") + .subcommand(SubCommand::with_name("verify").alias("v")) + .get_matches(); + + if let Some(_) = matches.subcommand_matches("verify") { + execute("exercises/ex1.rs"); + execute("exercises/ex2.rs"); + execute("exercises/ex3.rs"); + execute("exercises/ex4.rs"); + execute("exercises/ex5.rs"); + } } -main!(|args: Cli| if let Some(e) = args.exercise { - println!("selected {}", e); -} else { - println!("Welcome to {}!\n", Yellow.paint("Rustlings")); - about_variables::exec(); -}); +fn execute(filename: &str) { + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Compiling {}...", filename).as_str()); + bar.enable_steady_tick(100); + let compilecmd = Command::new("rustc") + .args(&[filename, "-o", "temp"]) + .output() + .expect("fail"); + bar.finish_and_clear(); + if compilecmd.status.success() { + println!("{} Successfully compiled {}!", Emoji("✅", "✓"), style(filename).italic()); + } else { + println!("{} Compilation of {} failed! Compiler error message:\n", Emoji("⚠️ ", "!"), style(filename).italic()); + println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); + std::process::exit(1); + } +} -- cgit v1.2.3 From 18a1447a65406ce587cf12c98e03e09d86f4e2bc Mon Sep 17 00:00:00 2001 From: olivia Date: Fri, 9 Nov 2018 22:31:54 +0100 Subject: add the whole curriculum --- src/main.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index cf2eddd..a144e3a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use clap::{App, SubCommand}; use indicatif::{ProgressBar}; use console::{style, Emoji}; use std::process::Command; +use std::fs::remove_file; fn main() { let matches = App::new("r2") @@ -17,15 +18,64 @@ fn main() { .get_matches(); if let Some(_) = matches.subcommand_matches("verify") { - execute("exercises/ex1.rs"); - execute("exercises/ex2.rs"); - execute("exercises/ex3.rs"); - execute("exercises/ex4.rs"); - execute("exercises/ex5.rs"); + compile_only("exercises/ex1.rs"); + compile_only("exercises/ex2.rs"); + compile_only("exercises/ex3.rs"); + compile_only("exercises/ex4.rs"); + compile_only("exercises/ex5.rs"); + + compile_only("exercises/variables/variables1.rs"); + compile_only("exercises/variables/variables2.rs"); + compile_only("exercises/variables/variables3.rs"); + compile_only("exercises/variables/variables4.rs"); + + compile_only("exercises/functions/functions1.rs"); + compile_only("exercises/functions/functions2.rs"); + compile_only("exercises/functions/functions3.rs"); + compile_only("exercises/functions/functions4.rs"); + compile_only("exercises/functions/functions5.rs"); + + compile_only("exercises/primitive_types/primitive_types1.rs"); + compile_only("exercises/primitive_types/primitive_types2.rs"); + compile_only("exercises/primitive_types/primitive_types3.rs"); + compile_only("exercises/primitive_types/primitive_types4.rs"); + compile_only("exercises/primitive_types/primitive_types5.rs"); + compile_only("exercises/primitive_types/primitive_types6.rs"); + + test("exercises/tests/tests1.rs"); + test("exercises/tests/tests2.rs"); + test("exercises/tests/tests3.rs"); + test("exercises/tests/tests4.rs"); + + test("exercises/if/if1.rs"); + + compile_only("exercises/strings/strings1.rs"); + compile_only("exercises/strings/strings2.rs"); + compile_only("exercises/strings/strings3.rs"); + + compile_only("exercises/move_semantics/move_semantics1.rs"); + compile_only("exercises/move_semantics/move_semantics2.rs"); + compile_only("exercises/move_semantics/move_semantics3.rs"); + compile_only("exercises/move_semantics/move_semantics4.rs"); + + compile_only("exercises/modules/modules1.rs"); + compile_only("exercises/modules/modules2.rs"); + + compile_only("exercises/macros/macros1.rs"); + compile_only("exercises/macros/macros2.rs"); + compile_only("exercises/macros/macros3.rs"); + compile_only("exercises/macros/macros4.rs"); + + test("exercises/error_handling/errors1.rs"); + test("exercises/error_handling/errors2.rs"); + test("exercises/error_handling/errors3.rs"); + test("exercises/error_handling/errorsn.rs"); + compile_only("exercises/error_handling/option1.rs"); + test("exercises/error_handling/result1.rs"); } } -fn execute(filename: &str) { +fn compile_only(filename: &str) { let bar = ProgressBar::new_spinner(); bar.set_message(format!("Compiling {}...", filename).as_str()); bar.enable_steady_tick(100); @@ -36,9 +86,35 @@ fn execute(filename: &str) { bar.finish_and_clear(); if compilecmd.status.success() { println!("{} Successfully compiled {}!", Emoji("✅", "✓"), style(filename).italic()); + clean().unwrap(); } else { println!("{} Compilation of {} failed! Compiler error message:\n", Emoji("⚠️ ", "!"), style(filename).italic()); println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); + clean().unwrap(); std::process::exit(1); } } + +fn test(filename: &str) { + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Testing {}...", filename).as_str()); + bar.enable_steady_tick(100); + let testcmd = Command::new("rustc") + .args(&["--test", filename, "-o", "temp"]) + .output() + .expect("fail"); + bar.finish_and_clear(); + if testcmd.status.success() { + println!("{} Successfully tested {}!", Emoji("✅", "✓"), style(filename).italic()); + clean().unwrap(); + } else { + println!("{} Testing of {} failed! Please try again.", Emoji("⚠️ ", "!"), style(filename).italic()); + clean().unwrap(); + std::process::exit(1); + } +} + +fn clean() -> Result<(), std::io::Error> { + remove_file("temp")?; + Ok(()) +} -- cgit v1.2.3 From b3c52803e97a5bef5fbe1e26ce4f8ba9b9d26b7d Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 14 Nov 2018 19:23:16 +0100 Subject: color output messages --- .gitignore | 2 -- src/main.rs | 12 ++++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 798c873..6aac0d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ *.swp target/ - -/target/ **/*.rs.bk Cargo.lock diff --git a/src/main.rs b/src/main.rs index a144e3a..509e055 100644 --- a/src/main.rs +++ b/src/main.rs @@ -85,10 +85,12 @@ fn compile_only(filename: &str) { .expect("fail"); bar.finish_and_clear(); if compilecmd.status.success() { - println!("{} Successfully compiled {}!", Emoji("✅", "✓"), style(filename).italic()); + let formatstr = format!("{} Successfully compiled {}!", Emoji("✅", "✓"), filename); + println!("{}", style(formatstr).green()); clean().unwrap(); } else { - println!("{} Compilation of {} failed! Compiler error message:\n", Emoji("⚠️ ", "!"), style(filename).italic()); + let formatstr = format!("{} Compilation of {} failed! Compiler error message:\n", Emoji("⚠️ ", "!"), filename); + println!("{}", style(formatstr).red()); println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); clean().unwrap(); std::process::exit(1); @@ -105,10 +107,12 @@ fn test(filename: &str) { .expect("fail"); bar.finish_and_clear(); if testcmd.status.success() { - println!("{} Successfully tested {}!", Emoji("✅", "✓"), style(filename).italic()); + let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename); + println!("{}", style(formatstr).green()); clean().unwrap(); } else { - println!("{} Testing of {} failed! Please try again.", Emoji("⚠️ ", "!"), style(filename).italic()); + let formatstr = format!("{} Testing of {} failed! Please try again.", Emoji("⚠️ ", "!"), filename); + println!("{}", style(formatstr).red()); clean().unwrap(); std::process::exit(1); } -- cgit v1.2.3 From 2216b3a3ab2938a968ad89362c673609ee4e68eb Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 14 Nov 2018 19:24:11 +0100 Subject: remove and ignore .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes .gitignore | 1 + 2 files changed, 1 insertion(+) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 956be3c..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore index 6aac0d4..61e30e2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ target/ **/*.rs.bk Cargo.lock +.DS_Store -- cgit v1.2.3 From 6cc16edff0ee30bc4cc482724f3a3579ec65fa6d Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 14 Nov 2018 20:04:48 +0100 Subject: add a fancy ascii header --- src/main.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main.rs b/src/main.rs index 509e055..af0860d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,13 @@ fn main() { .about("Test") .subcommand(SubCommand::with_name("verify").alias("v")) .get_matches(); + + println!(r#" _ _ _ "#); + println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); + println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); + println!(r#" | | | |_| \__ \ |_| | | | | | (_| \__ \ "#); + println!(r#" |_| \__,_|___/\__|_|_|_| |_|\__, |___/ "#); + println!(r#" |___/ "#); if let Some(_) = matches.subcommand_matches("verify") { compile_only("exercises/ex1.rs"); -- cgit v1.2.3 From b8789f09e012e7635d2e618179d4e085456393f1 Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 14 Nov 2018 20:08:38 +0100 Subject: add empty line after ascii --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index af0860d..0bb2fc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,6 +23,7 @@ fn main() { println!(r#" | | | |_| \__ \ |_| | | | | | (_| \__ \ "#); println!(r#" |_| \__,_|___/\__|_|_|_| |_|\__, |___/ "#); println!(r#" |___/ "#); + println!(""); if let Some(_) = matches.subcommand_matches("verify") { compile_only("exercises/ex1.rs"); -- cgit v1.2.3 From 6baac88574f8a0774d536db9998c51176620e51b Mon Sep 17 00:00:00 2001 From: olivia Date: Wed, 14 Nov 2018 20:12:20 +0100 Subject: fmt --- src/main.rs | 235 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 124 insertions(+), 111 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0bb2fc0..8e7172c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,129 +1,142 @@ #[macro_use] extern crate clap; -extern crate indicatif; extern crate console; +extern crate indicatif; use clap::{App, SubCommand}; -use indicatif::{ProgressBar}; use console::{style, Emoji}; -use std::process::Command; +use indicatif::ProgressBar; use std::fs::remove_file; +use std::process::Command; fn main() { - let matches = App::new("r2") - .version(crate_version!()) - .author("Olivia Hugger") - .about("Test") - .subcommand(SubCommand::with_name("verify").alias("v")) - .get_matches(); - - println!(r#" _ _ _ "#); - println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); - println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); - println!(r#" | | | |_| \__ \ |_| | | | | | (_| \__ \ "#); - println!(r#" |_| \__,_|___/\__|_|_|_| |_|\__, |___/ "#); - println!(r#" |___/ "#); - println!(""); - - if let Some(_) = matches.subcommand_matches("verify") { - compile_only("exercises/ex1.rs"); - compile_only("exercises/ex2.rs"); - compile_only("exercises/ex3.rs"); - compile_only("exercises/ex4.rs"); - compile_only("exercises/ex5.rs"); - - compile_only("exercises/variables/variables1.rs"); - compile_only("exercises/variables/variables2.rs"); - compile_only("exercises/variables/variables3.rs"); - compile_only("exercises/variables/variables4.rs"); - - compile_only("exercises/functions/functions1.rs"); - compile_only("exercises/functions/functions2.rs"); - compile_only("exercises/functions/functions3.rs"); - compile_only("exercises/functions/functions4.rs"); - compile_only("exercises/functions/functions5.rs"); - - compile_only("exercises/primitive_types/primitive_types1.rs"); - compile_only("exercises/primitive_types/primitive_types2.rs"); - compile_only("exercises/primitive_types/primitive_types3.rs"); - compile_only("exercises/primitive_types/primitive_types4.rs"); - compile_only("exercises/primitive_types/primitive_types5.rs"); - compile_only("exercises/primitive_types/primitive_types6.rs"); - - test("exercises/tests/tests1.rs"); - test("exercises/tests/tests2.rs"); - test("exercises/tests/tests3.rs"); - test("exercises/tests/tests4.rs"); - - test("exercises/if/if1.rs"); - - compile_only("exercises/strings/strings1.rs"); - compile_only("exercises/strings/strings2.rs"); - compile_only("exercises/strings/strings3.rs"); - - compile_only("exercises/move_semantics/move_semantics1.rs"); - compile_only("exercises/move_semantics/move_semantics2.rs"); - compile_only("exercises/move_semantics/move_semantics3.rs"); - compile_only("exercises/move_semantics/move_semantics4.rs"); - - compile_only("exercises/modules/modules1.rs"); - compile_only("exercises/modules/modules2.rs"); - - compile_only("exercises/macros/macros1.rs"); - compile_only("exercises/macros/macros2.rs"); - compile_only("exercises/macros/macros3.rs"); - compile_only("exercises/macros/macros4.rs"); - - test("exercises/error_handling/errors1.rs"); - test("exercises/error_handling/errors2.rs"); - test("exercises/error_handling/errors3.rs"); - test("exercises/error_handling/errorsn.rs"); - compile_only("exercises/error_handling/option1.rs"); - test("exercises/error_handling/result1.rs"); - } + let matches = App::new("r2") + .version(crate_version!()) + .author("Olivia Hugger") + .about("Test") + .subcommand(SubCommand::with_name("verify").alias("v")) + .subcommand(SubCommand::with_name("run").alias("r")) + .get_matches(); + + println!(r#" _ _ _ "#); + println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); + println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); + println!(r#" | | | |_| \__ \ |_| | | | | | (_| \__ \ "#); + println!(r#" |_| \__,_|___/\__|_|_|_| |_|\__, |___/ "#); + println!(r#" |___/ "#); + println!(""); + + if let Some(_) = matches.subcommand_matches("verify") { + compile_only("exercises/ex1.rs"); + compile_only("exercises/ex2.rs"); + compile_only("exercises/ex3.rs"); + compile_only("exercises/ex4.rs"); + compile_only("exercises/ex5.rs"); + + compile_only("exercises/variables/variables1.rs"); + compile_only("exercises/variables/variables2.rs"); + compile_only("exercises/variables/variables3.rs"); + compile_only("exercises/variables/variables4.rs"); + + compile_only("exercises/functions/functions1.rs"); + compile_only("exercises/functions/functions2.rs"); + compile_only("exercises/functions/functions3.rs"); + compile_only("exercises/functions/functions4.rs"); + compile_only("exercises/functions/functions5.rs"); + + compile_only("exercises/primitive_types/primitive_types1.rs"); + compile_only("exercises/primitive_types/primitive_types2.rs"); + compile_only("exercises/primitive_types/primitive_types3.rs"); + compile_only("exercises/primitive_types/primitive_types4.rs"); + compile_only("exercises/primitive_types/primitive_types5.rs"); + compile_only("exercises/primitive_types/primitive_types6.rs"); + + test("exercises/tests/tests1.rs"); + test("exercises/tests/tests2.rs"); + test("exercises/tests/tests3.rs"); + test("exercises/tests/tests4.rs"); + + test("exercises/if/if1.rs"); + + compile_only("exercises/strings/strings1.rs"); + compile_only("exercises/strings/strings2.rs"); + compile_only("exercises/strings/strings3.rs"); + + compile_only("exercises/move_semantics/move_semantics1.rs"); + compile_only("exercises/move_semantics/move_semantics2.rs"); + compile_only("exercises/move_semantics/move_semantics3.rs"); + compile_only("exercises/move_semantics/move_semantics4.rs"); + + compile_only("exercises/modules/modules1.rs"); + compile_only("exercises/modules/modules2.rs"); + + compile_only("exercises/macros/macros1.rs"); + compile_only("exercises/macros/macros2.rs"); + compile_only("exercises/macros/macros3.rs"); + compile_only("exercises/macros/macros4.rs"); + + test("exercises/error_handling/errors1.rs"); + test("exercises/error_handling/errors2.rs"); + test("exercises/error_handling/errors3.rs"); + test("exercises/error_handling/errorsn.rs"); + compile_only("exercises/error_handling/option1.rs"); + test("exercises/error_handling/result1.rs"); + } } fn compile_only(filename: &str) { - let bar = ProgressBar::new_spinner(); - bar.set_message(format!("Compiling {}...", filename).as_str()); - bar.enable_steady_tick(100); - let compilecmd = Command::new("rustc") - .args(&[filename, "-o", "temp"]) - .output() - .expect("fail"); - bar.finish_and_clear(); - if compilecmd.status.success() { - let formatstr = format!("{} Successfully compiled {}!", Emoji("✅", "✓"), filename); - println!("{}", style(formatstr).green()); - clean().unwrap(); - } else { - let formatstr = format!("{} Compilation of {} failed! Compiler error message:\n", Emoji("⚠️ ", "!"), filename); - println!("{}", style(formatstr).red()); - println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); - clean().unwrap(); - std::process::exit(1); - } + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Compiling {}...", filename).as_str()); + bar.enable_steady_tick(100); + let compilecmd = Command::new("rustc") + .args(&[filename, "-o", "temp"]) + .output() + .expect("fail"); + bar.finish_and_clear(); + if compilecmd.status.success() { + let formatstr = format!( + "{} Successfully compiled {}!", + Emoji("✅", "✓"), + filename + ); + println!("{}", style(formatstr).green()); + clean().unwrap(); + } else { + let formatstr = format!( + "{} Compilation of {} failed! Compiler error message:\n", + Emoji("⚠️ ", "!"), + filename + ); + println!("{}", style(formatstr).red()); + println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); + clean().unwrap(); + std::process::exit(1); + } } fn test(filename: &str) { - let bar = ProgressBar::new_spinner(); - bar.set_message(format!("Testing {}...", filename).as_str()); - bar.enable_steady_tick(100); - let testcmd = Command::new("rustc") - .args(&["--test", filename, "-o", "temp"]) - .output() - .expect("fail"); - bar.finish_and_clear(); - if testcmd.status.success() { - let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename); - println!("{}", style(formatstr).green()); - clean().unwrap(); - } else { - let formatstr = format!("{} Testing of {} failed! Please try again.", Emoji("⚠️ ", "!"), filename); - println!("{}", style(formatstr).red()); - clean().unwrap(); - std::process::exit(1); - } + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Testing {}...", filename).as_str()); + bar.enable_steady_tick(100); + let testcmd = Command::new("rustc") + .args(&["--test", filename, "-o", "temp"]) + .output() + .expect("fail"); + bar.finish_and_clear(); + if testcmd.status.success() { + let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename); + println!("{}", style(formatstr).green()); + clean().unwrap(); + } else { + let formatstr = format!( + "{} Testing of {} failed! Please try again.", + Emoji("⚠️ ", "!"), + filename + ); + println!("{}", style(formatstr).red()); + clean().unwrap(); + std::process::exit(1); + } } fn clean() -> Result<(), std::io::Error> { -- cgit v1.2.3 From e0ee5f1d7fd706705f169074356280ea8b245d69 Mon Sep 17 00:00:00 2001 From: olivia Date: Fri, 23 Nov 2018 15:18:43 +0100 Subject: implement run command --- src/main.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8e7172c..1a085ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ extern crate clap; extern crate console; extern crate indicatif; -use clap::{App, SubCommand}; +use clap::{App, Arg, SubCommand}; use console::{style, Emoji}; use indicatif::ProgressBar; use std::fs::remove_file; @@ -15,8 +15,11 @@ fn main() { .author("Olivia Hugger") .about("Test") .subcommand(SubCommand::with_name("verify").alias("v")) - .subcommand(SubCommand::with_name("run").alias("r")) - .get_matches(); + .subcommand( + SubCommand::with_name("run") + .alias("r") + .arg(Arg::with_name("file").required(true).index(1)), + ).get_matches(); println!(r#" _ _ _ "#); println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); @@ -26,6 +29,51 @@ fn main() { println!(r#" |___/ "#); println!(""); + if let Some(matches) = matches.subcommand_matches("run") { + if let Some(filename) = matches.value_of("file") { + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Compiling {}...", filename).as_str()); + bar.enable_steady_tick(100); + let compilecmd = Command::new("rustc") + .args(&[filename, "-o", "temp"]) + .output() + .expect("fail"); + bar.set_message(format!("Running {}...", filename).as_str()); + if compilecmd.status.success() { + let runcmd = Command::new("./temp").output().expect("fail"); + bar.finish_and_clear(); + + if runcmd.status.success() { + println!("{}", String::from_utf8_lossy(&runcmd.stdout)); + let formatstr = + format!("{} Successfully ran {}", Emoji("✅", "✓"), filename); + println!("{}", style(formatstr).green()); + clean().unwrap(); + } else { + println!("{}", String::from_utf8_lossy(&runcmd.stdout)); + println!("{}", String::from_utf8_lossy(&runcmd.stderr)); + + let formatstr = + format!("{} Ran {} with errors", Emoji("⚠️ ", "!"), filename); + println!("{}", style(formatstr).red()); + clean().unwrap(); + } + } else { + bar.finish_and_clear(); + let formatstr = format!( + "{} Compilation of {} failed! Compiler error message:\n", + Emoji("⚠️ ", "!"), + filename + ); + println!("{}", style(formatstr).red()); + println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); + clean().unwrap(); + } + } else { + panic!("Please supply a filename!"); + } + } + if let Some(_) = matches.subcommand_matches("verify") { compile_only("exercises/ex1.rs"); compile_only("exercises/ex2.rs"); -- cgit v1.2.3 From f18590f0a1006b526e7e79089e06e8f10de688da Mon Sep 17 00:00:00 2001 From: Erik Vesteraas Date: Mon, 26 Nov 2018 10:54:08 +0100 Subject: Add color=always to rustc options --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 1a085ef..9d5c150 100644 --- a/src/main.rs +++ b/src/main.rs @@ -137,7 +137,7 @@ fn compile_only(filename: &str) { bar.set_message(format!("Compiling {}...", filename).as_str()); bar.enable_steady_tick(100); let compilecmd = Command::new("rustc") - .args(&[filename, "-o", "temp"]) + .args(&[filename, "-o", "temp", "--color", "always"]) .output() .expect("fail"); bar.finish_and_clear(); -- cgit v1.2.3 From 1d495ff7b9c0a9d638576558d409533e80ba2330 Mon Sep 17 00:00:00 2001 From: olivia Date: Mon, 26 Nov 2018 11:10:38 +0100 Subject: add markdown output for default command --- Cargo.toml | 1 + default_out.md | 4 ++++ src/main.rs | 22 +++++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 default_out.md diff --git a/Cargo.toml b/Cargo.toml index bf4195d..5ac31cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ authors = ["olivia "] clap = "2.32.0" indicatif = "0.9.0" console = "0.6.2" +syntect = "3.0.2" diff --git a/default_out.md b/default_out.md new file mode 100644 index 0000000..7cbdffc --- /dev/null +++ b/default_out.md @@ -0,0 +1,4 @@ +## Welcome to Rustlings! + +To get started, run `rustlings verify` in order to get the first exercise. +Make sure to have your editor open! \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1a085ef..e84dff7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,15 +2,21 @@ extern crate clap; extern crate console; extern crate indicatif; +extern crate syntect; use clap::{App, Arg, SubCommand}; use console::{style, Emoji}; use indicatif::ProgressBar; +use syntect::easy::HighlightFile; +use syntect::parsing::SyntaxSet; +use syntect::highlighting::{ThemeSet, Style}; +use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings}; use std::fs::remove_file; +use std::io::BufRead; use std::process::Command; fn main() { - let matches = App::new("r2") + let matches = App::new("rustlings") .version(crate_version!()) .author("Olivia Hugger") .about("Test") @@ -21,6 +27,9 @@ fn main() { .arg(Arg::with_name("file").required(true).index(1)), ).get_matches(); + let ss = SyntaxSet::load_defaults_newlines(); + let ts = ThemeSet::load_defaults(); + println!(r#" _ _ _ "#); println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); @@ -130,6 +139,17 @@ fn main() { compile_only("exercises/error_handling/option1.rs"); test("exercises/error_handling/result1.rs"); } + + if let None = matches.subcommand_name() { + let mut highlighter = HighlightFile::new("default_out.md", &ss, &ts.themes["Solarized (dark)"]).unwrap(); + for maybe_line in highlighter.reader.lines() { + let line = maybe_line.unwrap(); + let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line, &ss); + println!("{}", as_24_bit_terminal_escaped(®ions[..], true)); + } + } + + println!("\x1b[0m"); } fn compile_only(filename: &str) { -- cgit v1.2.3 From a4b4350b70a4af46abf9d3d27bef1459a9b58521 Mon Sep 17 00:00:00 2001 From: olivia Date: Mon, 26 Nov 2018 11:29:39 +0100 Subject: switch theme to base16 eighties --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 71e2925..685618d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,7 +141,7 @@ fn main() { } if let None = matches.subcommand_name() { - let mut highlighter = HighlightFile::new("default_out.md", &ss, &ts.themes["Solarized (dark)"]).unwrap(); + let mut highlighter = HighlightFile::new("default_out.md", &ss, &ts.themes["base16-eighties.dark"]).unwrap(); for maybe_line in highlighter.reader.lines() { let line = maybe_line.unwrap(); let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line, &ss); -- cgit v1.2.3 From c5c32f4add2654f18aff5d9b6d5cf62d8fa47048 Mon Sep 17 00:00:00 2001 From: delet0r Date: Mon, 26 Nov 2018 12:27:14 +0100 Subject: README for CLI only version This README mentions READMEs for every exercise topic, those haven't been added yet. --- README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8049c22..dfd48f6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,24 @@ # rustlings -A cool thing that is currently in development. +Greetings and welcome to rustlings. This project contains small exercises get you used to reading and writing code. This includes reading and responding to compiler messages! + +## How to get started +To use rustlings you have to have [rust](https://www.rust-lang.org/) installed on your machine. +If you already have it, you can clone the repo to your local environment with: +``` bash +git clone https://github.com/rustlings/rustlings.git +``` +To run rustlings you can either use `cargo run ` or you can install rustlings on your machine +by running `cargo install --path ` +(NOTE: for rustling to function you have to be in the directory of the repo). + +## Doing exercises +The execises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. For every topic there is an additional README file with some reasources to get you started on the topic. We really recommend, that you have a look at them before you start. + +Your task is simple every exercise contains an error you have to solve, in order to make it compile. + +Running rustlings with the subcommand `verify` will compile every exercise in the recommended order. It will stop at the first exercise that didn't compile and show you the error to be solved. + +If you want to run a single erxercise you can use the subcommand `run `. + +When you struggle to solve the error, there is usually a tip at the bottom of the each exercise. \ No newline at end of file -- cgit v1.2.3 From 9d16d6b63d9a399d9e7d65a7aa7993ba94253e40 Mon Sep 17 00:00:00 2001 From: Erik Vesteraas Date: Mon, 26 Nov 2018 12:41:39 +0100 Subject: Add watch mode, and don't panic on clean failure --- Cargo.toml | 1 + src/main.rs | 170 ++++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 103 insertions(+), 68 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5ac31cd..c1f81fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,4 @@ clap = "2.32.0" indicatif = "0.9.0" console = "0.6.2" syntect = "3.0.2" +notify = "4.0.0" diff --git a/src/main.rs b/src/main.rs index 685618d..3cdd0b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate clap; extern crate console; extern crate indicatif; extern crate syntect; +extern crate notify; use clap::{App, Arg, SubCommand}; use console::{style, Emoji}; @@ -14,6 +15,11 @@ use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings}; use std::fs::remove_file; use std::io::BufRead; use std::process::Command; +use std::fs::read_to_string; +use std::sync::mpsc::channel; +use std::time::Duration; +use notify::DebouncedEvent; +use notify::{RecommendedWatcher, Watcher, RecursiveMode}; fn main() { let matches = App::new("rustlings") @@ -21,6 +27,7 @@ fn main() { .author("Olivia Hugger") .about("Test") .subcommand(SubCommand::with_name("verify").alias("v")) + .subcommand(SubCommand::with_name("watch").alias("w")) .subcommand( SubCommand::with_name("run") .alias("r") @@ -57,7 +64,7 @@ fn main() { let formatstr = format!("{} Successfully ran {}", Emoji("✅", "✓"), filename); println!("{}", style(formatstr).green()); - clean().unwrap(); + clean(); } else { println!("{}", String::from_utf8_lossy(&runcmd.stdout)); println!("{}", String::from_utf8_lossy(&runcmd.stderr)); @@ -65,7 +72,7 @@ fn main() { let formatstr = format!("{} Ran {} with errors", Emoji("⚠️ ", "!"), filename); println!("{}", style(formatstr).red()); - clean().unwrap(); + clean(); } } else { bar.finish_and_clear(); @@ -76,7 +83,7 @@ fn main() { ); println!("{}", style(formatstr).red()); println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); - clean().unwrap(); + clean(); } } else { panic!("Please supply a filename!"); @@ -84,60 +91,14 @@ fn main() { } if let Some(_) = matches.subcommand_matches("verify") { - compile_only("exercises/ex1.rs"); - compile_only("exercises/ex2.rs"); - compile_only("exercises/ex3.rs"); - compile_only("exercises/ex4.rs"); - compile_only("exercises/ex5.rs"); - - compile_only("exercises/variables/variables1.rs"); - compile_only("exercises/variables/variables2.rs"); - compile_only("exercises/variables/variables3.rs"); - compile_only("exercises/variables/variables4.rs"); - - compile_only("exercises/functions/functions1.rs"); - compile_only("exercises/functions/functions2.rs"); - compile_only("exercises/functions/functions3.rs"); - compile_only("exercises/functions/functions4.rs"); - compile_only("exercises/functions/functions5.rs"); - - compile_only("exercises/primitive_types/primitive_types1.rs"); - compile_only("exercises/primitive_types/primitive_types2.rs"); - compile_only("exercises/primitive_types/primitive_types3.rs"); - compile_only("exercises/primitive_types/primitive_types4.rs"); - compile_only("exercises/primitive_types/primitive_types5.rs"); - compile_only("exercises/primitive_types/primitive_types6.rs"); - - test("exercises/tests/tests1.rs"); - test("exercises/tests/tests2.rs"); - test("exercises/tests/tests3.rs"); - test("exercises/tests/tests4.rs"); - - test("exercises/if/if1.rs"); - - compile_only("exercises/strings/strings1.rs"); - compile_only("exercises/strings/strings2.rs"); - compile_only("exercises/strings/strings3.rs"); - - compile_only("exercises/move_semantics/move_semantics1.rs"); - compile_only("exercises/move_semantics/move_semantics2.rs"); - compile_only("exercises/move_semantics/move_semantics3.rs"); - compile_only("exercises/move_semantics/move_semantics4.rs"); - - compile_only("exercises/modules/modules1.rs"); - compile_only("exercises/modules/modules2.rs"); - - compile_only("exercises/macros/macros1.rs"); - compile_only("exercises/macros/macros2.rs"); - compile_only("exercises/macros/macros3.rs"); - compile_only("exercises/macros/macros4.rs"); - - test("exercises/error_handling/errors1.rs"); - test("exercises/error_handling/errors2.rs"); - test("exercises/error_handling/errors3.rs"); - test("exercises/error_handling/errorsn.rs"); - compile_only("exercises/error_handling/option1.rs"); - test("exercises/error_handling/result1.rs"); + match verify() { + Ok(_) => {} + Err(_) => std::process::exit(1), + } + } + + if let Some(_) = matches.subcommand_matches("watch") { + watch().unwrap(); } if let None = matches.subcommand_name() { @@ -152,7 +113,79 @@ fn main() { println!("\x1b[0m"); } -fn compile_only(filename: &str) { +fn watch() -> notify::Result<()> { + let (tx, rx) = channel(); + + let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?; + watcher.watch("./exercises", RecursiveMode::Recursive)?; + + let _ignored = verify(); + + loop { + match rx.recv() { + Ok(event) => { + match event { + DebouncedEvent::Chmod(_) + | DebouncedEvent::Write(_) => { + let _ignored = verify(); + } + _ => {} + } + }, + Err(e) => println!("watch error: {:?}", e), + } + } +} + +fn verify() -> Result<(), ()> { + compile_only("exercises/ex1.rs")?; + compile_only("exercises/ex2.rs")?; + compile_only("exercises/ex3.rs")?; + compile_only("exercises/ex4.rs")?; + compile_only("exercises/ex5.rs")?; + compile_only("exercises/variables/variables1.rs")?; + compile_only("exercises/variables/variables2.rs")?; + compile_only("exercises/variables/variables3.rs")?; + compile_only("exercises/variables/variables4.rs")?; + compile_only("exercises/functions/functions1.rs")?; + compile_only("exercises/functions/functions2.rs")?; + compile_only("exercises/functions/functions3.rs")?; + compile_only("exercises/functions/functions4.rs")?; + compile_only("exercises/functions/functions5.rs")?; + compile_only("exercises/primitive_types/primitive_types1.rs")?; + compile_only("exercises/primitive_types/primitive_types2.rs")?; + compile_only("exercises/primitive_types/primitive_types3.rs")?; + compile_only("exercises/primitive_types/primitive_types4.rs")?; + compile_only("exercises/primitive_types/primitive_types5.rs")?; + compile_only("exercises/primitive_types/primitive_types6.rs")?; + test("exercises/tests/tests1.rs")?; + test("exercises/tests/tests2.rs")?; + test("exercises/tests/tests3.rs")?; + test("exercises/tests/tests4.rs")?; + test("exercises/if/if1.rs")?; + compile_only("exercises/strings/strings1.rs")?; + compile_only("exercises/strings/strings2.rs")?; + compile_only("exercises/strings/strings3.rs")?; + compile_only("exercises/move_semantics/move_semantics1.rs")?; + compile_only("exercises/move_semantics/move_semantics2.rs")?; + compile_only("exercises/move_semantics/move_semantics3.rs")?; + compile_only("exercises/move_semantics/move_semantics4.rs")?; + compile_only("exercises/modules/modules1.rs")?; + compile_only("exercises/modules/modules2.rs")?; + compile_only("exercises/macros/macros1.rs")?; + compile_only("exercises/macros/macros2.rs")?; + compile_only("exercises/macros/macros3.rs")?; + compile_only("exercises/macros/macros4.rs")?; + test("exercises/error_handling/errors1.rs")?; + test("exercises/error_handling/errors2.rs")?; + test("exercises/error_handling/errors3.rs")?; + test("exercises/error_handling/errorsn.rs")?; + compile_only("exercises/error_handling/option1.rs")?; + test("exercises/error_handling/result1.rs")?; + Ok(()) +} + +fn compile_only(filename: &str) -> Result<(), ()> { let bar = ProgressBar::new_spinner(); bar.set_message(format!("Compiling {}...", filename).as_str()); bar.enable_steady_tick(100); @@ -168,7 +201,8 @@ fn compile_only(filename: &str) { filename ); println!("{}", style(formatstr).green()); - clean().unwrap(); + clean(); + Ok(()) } else { let formatstr = format!( "{} Compilation of {} failed! Compiler error message:\n", @@ -177,12 +211,12 @@ fn compile_only(filename: &str) { ); println!("{}", style(formatstr).red()); println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); - clean().unwrap(); - std::process::exit(1); + clean(); + Err(()) } } -fn test(filename: &str) { +fn test(filename: &str) -> Result<(), ()> { let bar = ProgressBar::new_spinner(); bar.set_message(format!("Testing {}...", filename).as_str()); bar.enable_steady_tick(100); @@ -194,7 +228,8 @@ fn test(filename: &str) { if testcmd.status.success() { let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename); println!("{}", style(formatstr).green()); - clean().unwrap(); + clean(); + Ok(()) } else { let formatstr = format!( "{} Testing of {} failed! Please try again.", @@ -202,12 +237,11 @@ fn test(filename: &str) { filename ); println!("{}", style(formatstr).red()); - clean().unwrap(); - std::process::exit(1); + clean(); + Err(()) } } -fn clean() -> Result<(), std::io::Error> { - remove_file("temp")?; - Ok(()) +fn clean() { + let _ignored = remove_file("temp"); } -- cgit v1.2.3 From 7f5ab6e1dc95f0d858babc2492d7607ae00c2ebd Mon Sep 17 00:00:00 2001 From: Erik Vesteraas Date: Mon, 26 Nov 2018 15:07:34 +0100 Subject: Continue work on new readme. - Be more explicit re terminal commands - Copy over "Need help?" section - General wording --- README.md | 51 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index dfd48f6..a015b8f 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,51 @@ Greetings and welcome to rustlings. This project contains small exercises get you used to reading and writing code. This includes reading and responding to compiler messages! ## How to get started -To use rustlings you have to have [rust](https://www.rust-lang.org/) installed on your machine. -If you already have it, you can clone the repo to your local environment with: -``` bash + +To use rustlings you need to have a [Rust](https://www.rust-lang.org/) toolchain installed. To install it go to [rustup.rs](https://rustup.rs/). + +Once Rust is installed, clone the rustlings repository and enter the resulting directory: + +```bash git clone https://github.com/rustlings/rustlings.git +cd rustlings +``` + +Once in the directory you can install rustlings on your machine and run exercises: + +```bash +cargo install --path . +rustlings ``` -To run rustlings you can either use `cargo run ` or you can install rustlings on your machine -by running `cargo install --path ` -(NOTE: for rustling to function you have to be in the directory of the repo). + +Or run rustlings directly with cargo, without installing it: + +```bash +cargo run +``` + +If you choose to not install rustlings, just replace `rustlings` with `cargo run` in the rest of this text. ## Doing exercises -The execises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. For every topic there is an additional README file with some reasources to get you started on the topic. We really recommend, that you have a look at them before you start. -Your task is simple every exercise contains an error you have to solve, in order to make it compile. +The execises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. + +For every topic there is an additional README file with some resources to get you started on the topic. We really recommend, that you have a look at them before you start. + +Your task is simple. Every exercise contains an error you have to solve, in order to make it compile. + +Running `rustlings verify` will compile every exercise in the recommended order. It will stop at the first exercise that didn't compile and show you the error to be solved. + +`rustlings watch` will rerun this verification every time you save an exercise. + +To compile and run a single exercise you can use `rustlings run `. -Running rustlings with the subcommand `verify` will compile every exercise in the recommended order. It will stop at the first exercise that didn't compile and show you the error to be solved. +In case you get stuck, there is usually a hint at the bottom of each exercise. -If you want to run a single erxercise you can use the subcommand `run `. +### Need help? -When you struggle to solve the error, there is usually a tip at the bottom of the each exercise. \ No newline at end of file +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! -- cgit v1.2.3 From 0973e600566baa0071cfd050bdfbf62a3e72b43e Mon Sep 17 00:00:00 2001 From: delet0r Date: Mon, 26 Nov 2018 16:43:42 +0100 Subject: Created sub READMEs for CLI only version Sub READMEs contain the relevant resources from the main README of the web version. All second edition Rust Book links were updated to the 2018 edition. Fixed to typos in main README.md. --- README.md | 8 ++++---- exercises/error_handling/README.md | 5 +++++ exercises/functions/REAMDE.md | 1 + exercises/if/REAMDE.md | 1 + exercises/macros/README.md | 2 ++ exercises/modules/README.md | 1 + exercises/move_semantics/README.md | 7 +++++++ exercises/primitive_types/README.md | 0 exercises/standard_library_types/README.md | 1 + exercises/strings/REAMDE.md | 0 exercises/tests/README.md | 3 +++ exercises/threads/README.md | 1 + exercises/variables/README.md | 0 13 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 exercises/error_handling/README.md create mode 100644 exercises/functions/REAMDE.md create mode 100644 exercises/if/REAMDE.md create mode 100644 exercises/macros/README.md create mode 100644 exercises/modules/README.md create mode 100644 exercises/move_semantics/README.md create mode 100644 exercises/primitive_types/README.md create mode 100644 exercises/standard_library_types/README.md create mode 100644 exercises/strings/REAMDE.md create mode 100644 exercises/tests/README.md create mode 100644 exercises/threads/README.md create mode 100644 exercises/variables/README.md diff --git a/README.md b/README.md index dfd48f6..849848f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # rustlings -Greetings and welcome to rustlings. This project contains small exercises get you used to reading and writing code. This includes reading and responding to compiler messages! +Greetings and welcome to rustlings. This project contains small exercises to get you used to reading and writing code. This includes reading and responding to compiler messages! ## How to get started To use rustlings you have to have [rust](https://www.rust-lang.org/) installed on your machine. @@ -13,12 +13,12 @@ by running `cargo install --path ` (NOTE: for rustling to function you have to be in the directory of the repo). ## Doing exercises -The execises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. For every topic there is an additional README file with some reasources to get you started on the topic. We really recommend, that you have a look at them before you start. +The exercises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. For every topic there is an additional README file with some resources to get you started on the topic. We really recommend, that you have a look at them before you start. Your task is simple every exercise contains an error you have to solve, in order to make it compile. Running rustlings with the subcommand `verify` will compile every exercise in the recommended order. It will stop at the first exercise that didn't compile and show you the error to be solved. -If you want to run a single erxercise you can use the subcommand `run `. +If you want to run a single exercise, you can use the subcommand `run `. -When you struggle to solve the error, there is usually a tip at the bottom of the each exercise. \ No newline at end of file +When you struggle to solve the error, there is usually a tip at the bottom of each exercise. \ No newline at end of file diff --git a/exercises/error_handling/README.md b/exercises/error_handling/README.md new file mode 100644 index 0000000..b5895d7 --- /dev/null +++ b/exercises/error_handling/README.md @@ -0,0 +1,5 @@ +For this exercise check out the chapters: +- [Error Handling](https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html) +- [Generics](https://doc.rust-lang.org/book/second-edition/ch10-01-syntax.html) + +of the Rust Book. \ No newline at end of file diff --git a/exercises/functions/REAMDE.md b/exercises/functions/REAMDE.md new file mode 100644 index 0000000..12bbc05 --- /dev/null +++ b/exercises/functions/REAMDE.md @@ -0,0 +1 @@ +For this exercise check out the chapter [Functions](https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/if/REAMDE.md b/exercises/if/REAMDE.md new file mode 100644 index 0000000..ce68a43 --- /dev/null +++ b/exercises/if/REAMDE.md @@ -0,0 +1 @@ +For this exercise check out the chapter [If](https://doc.rust-lang.org/book/second-edition/ch03-05-control-flow.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/macros/README.md b/exercises/macros/README.md new file mode 100644 index 0000000..9af0071 --- /dev/null +++ b/exercises/macros/README.md @@ -0,0 +1,2 @@ +For this exercise check out the section [Macros](https://doc.rust-lang.org/book/first-edition/macros.html) and the chapter +[Macros Appendix](https://doc.rust-lang.org/book/2018-edition/appendix-04-macros.html) of the Rust Book and [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html). diff --git a/exercises/modules/README.md b/exercises/modules/README.md new file mode 100644 index 0000000..61edccb --- /dev/null +++ b/exercises/modules/README.md @@ -0,0 +1 @@ +For this exercise check out the [Modules](https://doc.rust-lang.org/book/second-edition/ch07-01-mod-and-the-filesystem.html) chapter of the Rust Book. \ No newline at end of file diff --git a/exercises/move_semantics/README.md b/exercises/move_semantics/README.md new file mode 100644 index 0000000..d9c6c65 --- /dev/null +++ b/exercises/move_semantics/README.md @@ -0,0 +1,7 @@ +These exercises are adapted from [pnkfelix](https://github.com/rustlings/rustlings/blob/master)'s [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- Thank you Felix!!! + +For this exercise check out the chapters: +- [Ownership](https://doc.rust-lang.org/book/second-edition/ch04-01-what-is-ownership.html) +- [Reference and borrowing](https://doc.rust-lang.org/book/second-edition/ch04-02-references-and-borrowing.ht) + +of the Rust Book. \ No newline at end of file diff --git a/exercises/primitive_types/README.md b/exercises/primitive_types/README.md new file mode 100644 index 0000000..e69de29 diff --git a/exercises/standard_library_types/README.md b/exercises/standard_library_types/README.md new file mode 100644 index 0000000..ef4ba45 --- /dev/null +++ b/exercises/standard_library_types/README.md @@ -0,0 +1 @@ +For this exercise check out the chapter [Shared-State Concurrency](https://doc.rust-lang.org/book/second-edition/ch16-03-shared-state.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/strings/REAMDE.md b/exercises/strings/REAMDE.md new file mode 100644 index 0000000..e69de29 diff --git a/exercises/tests/README.md b/exercises/tests/README.md new file mode 100644 index 0000000..9919995 --- /dev/null +++ b/exercises/tests/README.md @@ -0,0 +1,3 @@ +Going out of order from the book to cover tests -- many of the following exercises will ask you to make tests pass! + +For this exercise check out the section [How to Write Tests](https://doc.rust-lang.org/book/second-edition/ch11-01-writing-tests.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/threads/README.md b/exercises/threads/README.md new file mode 100644 index 0000000..6e7d789 --- /dev/null +++ b/exercises/threads/README.md @@ -0,0 +1 @@ +For this exercise check out the [Dining Philosophers example](https://doc.rust-lang.org/1.4.0/book/dining-philosophers.html) and the chapter [Concurrency](https://doc.rust-lang.org/book/second-edition/ch16-01-threads.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/variables/README.md b/exercises/variables/README.md new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3 From b0c9b33978ca6ae1eff3658c7c6d0bfe48926d23 Mon Sep 17 00:00:00 2001 From: delet0r Date: Tue, 27 Nov 2018 10:54:01 +0100 Subject: Changed Rust Book versions in links to 2018 Forgot to add changes to last commit. --- exercises/error_handling/README.md | 6 +++--- exercises/functions/REAMDE.md | 2 +- exercises/if/REAMDE.md | 2 +- exercises/macros/README.md | 2 +- exercises/modules/README.md | 2 +- exercises/move_semantics/README.md | 4 ++-- exercises/primitive_types/README.md | 1 + exercises/standard_library_types/README.md | 6 +++++- exercises/strings/REAMDE.md | 1 + exercises/tests/README.md | 2 +- exercises/threads/README.md | 2 +- exercises/variables/README.md | 1 + 12 files changed, 19 insertions(+), 12 deletions(-) diff --git a/exercises/error_handling/README.md b/exercises/error_handling/README.md index b5895d7..2a53803 100644 --- a/exercises/error_handling/README.md +++ b/exercises/error_handling/README.md @@ -1,5 +1,5 @@ -For this exercise check out the chapters: -- [Error Handling](https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html) -- [Generics](https://doc.rust-lang.org/book/second-edition/ch10-01-syntax.html) +For this exercise check out the sections: +- [Error Handling](https://doc.rust-lang.org/book/2018-edition/ch09-02-recoverable-errors-with-result.html) +- [Generics](https://doc.rust-lang.org/book/2018-edition/ch10-01-syntax.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/functions/REAMDE.md b/exercises/functions/REAMDE.md index 12bbc05..70555a1 100644 --- a/exercises/functions/REAMDE.md +++ b/exercises/functions/REAMDE.md @@ -1 +1 @@ -For this exercise check out the chapter [Functions](https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html) of the Rust Book. \ No newline at end of file +For this exercise check out the chapter [Functions](https://doc.rust-lang.org/book/2018-edition/ch03-03-how-functions-work.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/if/REAMDE.md b/exercises/if/REAMDE.md index ce68a43..1061462 100644 --- a/exercises/if/REAMDE.md +++ b/exercises/if/REAMDE.md @@ -1 +1 @@ -For this exercise check out the chapter [If](https://doc.rust-lang.org/book/second-edition/ch03-05-control-flow.html) of the Rust Book. \ No newline at end of file +For this exercise check out the chapter [If](https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html?highlight=control,fl#control-flow) of the Rust Book. \ No newline at end of file diff --git a/exercises/macros/README.md b/exercises/macros/README.md index 9af0071..87851c5 100644 --- a/exercises/macros/README.md +++ b/exercises/macros/README.md @@ -1,2 +1,2 @@ -For this exercise check out the section [Macros](https://doc.rust-lang.org/book/first-edition/macros.html) and the chapter +For this exercise check out the section [Macros](https://doc.rust-lang.org/book/2018-edition/macros.html) and the chapter [Macros Appendix](https://doc.rust-lang.org/book/2018-edition/appendix-04-macros.html) of the Rust Book and [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html). diff --git a/exercises/modules/README.md b/exercises/modules/README.md index 61edccb..7a0232f 100644 --- a/exercises/modules/README.md +++ b/exercises/modules/README.md @@ -1 +1 @@ -For this exercise check out the [Modules](https://doc.rust-lang.org/book/second-edition/ch07-01-mod-and-the-filesystem.html) chapter of the Rust Book. \ No newline at end of file +For this exercise check out the [Modules](https://doc.rust-lang.org/book/2018-edition/ch07-01-mod-and-the-filesystem.html) chapter of the Rust Book. \ No newline at end of file diff --git a/exercises/move_semantics/README.md b/exercises/move_semantics/README.md index d9c6c65..c8095bf 100644 --- a/exercises/move_semantics/README.md +++ b/exercises/move_semantics/README.md @@ -1,7 +1,7 @@ These exercises are adapted from [pnkfelix](https://github.com/rustlings/rustlings/blob/master)'s [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- Thank you Felix!!! For this exercise check out the chapters: -- [Ownership](https://doc.rust-lang.org/book/second-edition/ch04-01-what-is-ownership.html) -- [Reference and borrowing](https://doc.rust-lang.org/book/second-edition/ch04-02-references-and-borrowing.ht) +- [Ownership](https://doc.rust-lang.org/book/2018-edition/ch04-01-what-is-ownership.html) +- [Reference and borrowing](https://doc.rust-lang.org/book/2018-edition/ch04-02-references-and-borrowing.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/primitive_types/README.md b/exercises/primitive_types/README.md index e69de29..e4f3181 100644 --- a/exercises/primitive_types/README.md +++ b/exercises/primitive_types/README.md @@ -0,0 +1 @@ +For this exercise check out the chapter [Data Types](https://doc.rust-lang.org/book/2018-edition/ch03-02-data-types.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/standard_library_types/README.md b/exercises/standard_library_types/README.md index ef4ba45..46d2ff2 100644 --- a/exercises/standard_library_types/README.md +++ b/exercises/standard_library_types/README.md @@ -1 +1,5 @@ -For this exercise check out the chapter [Shared-State Concurrency](https://doc.rust-lang.org/book/second-edition/ch16-03-shared-state.html) of the Rust Book. \ No newline at end of file +For the Arc exercise check out the chapter [Shared-State Concurrency](https://doc.rust-lang.org/book/2018-edition/ch16-03-shared-state.html) of the Rust Book. + +For the Iterator exercise check out the chapters [Iterator](https://doc.rust-lang.org/book/2018-edition/ch13-02-iterators.html) of the Rust Book and the [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.htmlj). +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! + diff --git a/exercises/strings/REAMDE.md b/exercises/strings/REAMDE.md index e69de29..76b74d7 100644 --- a/exercises/strings/REAMDE.md +++ b/exercises/strings/REAMDE.md @@ -0,0 +1 @@ +For this exercise check out the chapter [Strings](https://doc.rust-lang.org/book/2018-edition/ch08-02-strings.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/tests/README.md b/exercises/tests/README.md index 9919995..8683ba8 100644 --- a/exercises/tests/README.md +++ b/exercises/tests/README.md @@ -1,3 +1,3 @@ Going out of order from the book to cover tests -- many of the following exercises will ask you to make tests pass! -For this exercise check out the section [How to Write Tests](https://doc.rust-lang.org/book/second-edition/ch11-01-writing-tests.html) of the Rust Book. \ No newline at end of file +For this exercise check out the section [How to Write Tests](https://doc.rust-lang.org/book/2018-edition/ch11-01-writing-tests.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/threads/README.md b/exercises/threads/README.md index 6e7d789..90581fa 100644 --- a/exercises/threads/README.md +++ b/exercises/threads/README.md @@ -1 +1 @@ -For this exercise check out the [Dining Philosophers example](https://doc.rust-lang.org/1.4.0/book/dining-philosophers.html) and the chapter [Concurrency](https://doc.rust-lang.org/book/second-edition/ch16-01-threads.html) of the Rust Book. \ No newline at end of file +For this exercise check out the [Dining Philosophers example](https://doc.rust-lang.org/1.4.0/book/dining-philosophers.html) and the chapter [Concurrency](https://doc.rust-lang.org/book/2018-edition/ch16-01-threads.html) of the Rust Book. \ No newline at end of file diff --git a/exercises/variables/README.md b/exercises/variables/README.md index e69de29..574c162 100644 --- a/exercises/variables/README.md +++ b/exercises/variables/README.md @@ -0,0 +1 @@ +For this exercise checkout the section [Variables and Mutability](https://doc.rust-lang.org/book/2018-edition/ch03-01-variables-and-mutability.html) of the Rust Book. \ No newline at end of file -- cgit v1.2.3 From a0d21020dfd442c93d057a00627ec66fa72317eb Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:07:19 +0100 Subject: update for rust 2018 --- Cargo.toml | 1 + src/main.rs | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c1f81fd..5fe7438 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "rustlings" version = "0.1.0" authors = ["olivia "] +edition = "2018" [dependencies] clap = "2.32.0" diff --git a/src/main.rs b/src/main.rs index 3cdd0b4..7187c03 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,13 @@ -#[macro_use] -extern crate clap; -extern crate console; -extern crate indicatif; -extern crate syntect; -extern crate notify; - -use clap::{App, Arg, SubCommand}; +use clap::{App, Arg, SubCommand, crate_version}; use console::{style, Emoji}; use indicatif::ProgressBar; use syntect::easy::HighlightFile; use syntect::parsing::SyntaxSet; use syntect::highlighting::{ThemeSet, Style}; -use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings}; +use syntect::util::{as_24_bit_terminal_escaped}; use std::fs::remove_file; use std::io::BufRead; use std::process::Command; -use std::fs::read_to_string; use std::sync::mpsc::channel; use std::time::Duration; use notify::DebouncedEvent; -- cgit v1.2.3 From 3ffd43bc2a66ac0d340b8b7a6dc8df55cb3cdb0c Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:08:15 +0100 Subject: remove 2018 specification for cargo fix --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5fe7438..c1f81fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ name = "rustlings" version = "0.1.0" authors = ["olivia "] -edition = "2018" [dependencies] clap = "2.32.0" -- cgit v1.2.3 From ad26a6d0e61393643a8ad1b99812631d53c7c789 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:08:48 +0100 Subject: revert --- src/main.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7187c03..3cdd0b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,21 @@ -use clap::{App, Arg, SubCommand, crate_version}; +#[macro_use] +extern crate clap; +extern crate console; +extern crate indicatif; +extern crate syntect; +extern crate notify; + +use clap::{App, Arg, SubCommand}; use console::{style, Emoji}; use indicatif::ProgressBar; use syntect::easy::HighlightFile; use syntect::parsing::SyntaxSet; use syntect::highlighting::{ThemeSet, Style}; -use syntect::util::{as_24_bit_terminal_escaped}; +use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings}; use std::fs::remove_file; use std::io::BufRead; use std::process::Command; +use std::fs::read_to_string; use std::sync::mpsc::channel; use std::time::Duration; use notify::DebouncedEvent; -- cgit v1.2.3 From 679508b278643f5ce3796cafb512a03df61939c7 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:09:49 +0100 Subject: ah well it was worth a try --- Cargo.toml | 1 + src/main.rs | 12 ++---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c1f81fd..5fe7438 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "rustlings" version = "0.1.0" authors = ["olivia "] +edition = "2018" [dependencies] clap = "2.32.0" diff --git a/src/main.rs b/src/main.rs index 3cdd0b4..7187c03 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,13 @@ -#[macro_use] -extern crate clap; -extern crate console; -extern crate indicatif; -extern crate syntect; -extern crate notify; - -use clap::{App, Arg, SubCommand}; +use clap::{App, Arg, SubCommand, crate_version}; use console::{style, Emoji}; use indicatif::ProgressBar; use syntect::easy::HighlightFile; use syntect::parsing::SyntaxSet; use syntect::highlighting::{ThemeSet, Style}; -use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings}; +use syntect::util::{as_24_bit_terminal_escaped}; use std::fs::remove_file; use std::io::BufRead; use std::process::Command; -use std::fs::read_to_string; use std::sync::mpsc::channel; use std::time::Duration; use notify::DebouncedEvent; -- cgit v1.2.3 From a388bb3798e2595c47924c6e4128f10e00cfc705 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:33:43 +0100 Subject: split codebase --- src/main.rs | 162 +++------------------------------------------------------- src/run.rs | 49 ++++++++++++++++++ src/util.rs | 5 ++ src/verify.rs | 109 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 155 deletions(-) create mode 100644 src/run.rs create mode 100644 src/util.rs create mode 100644 src/verify.rs diff --git a/src/main.rs b/src/main.rs index 7187c03..0fc0692 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,19 @@ use clap::{App, Arg, SubCommand, crate_version}; -use console::{style, Emoji}; -use indicatif::ProgressBar; use syntect::easy::HighlightFile; use syntect::parsing::SyntaxSet; use syntect::highlighting::{ThemeSet, Style}; use syntect::util::{as_24_bit_terminal_escaped}; -use std::fs::remove_file; use std::io::BufRead; -use std::process::Command; use std::sync::mpsc::channel; use std::time::Duration; use notify::DebouncedEvent; use notify::{RecommendedWatcher, Watcher, RecursiveMode}; +use crate::verify::verify; +use crate::run::run; + +mod run; +mod verify; +mod util; fn main() { let matches = App::new("rustlings") @@ -38,48 +40,7 @@ fn main() { println!(""); if let Some(matches) = matches.subcommand_matches("run") { - if let Some(filename) = matches.value_of("file") { - let bar = ProgressBar::new_spinner(); - bar.set_message(format!("Compiling {}...", filename).as_str()); - bar.enable_steady_tick(100); - let compilecmd = Command::new("rustc") - .args(&[filename, "-o", "temp"]) - .output() - .expect("fail"); - bar.set_message(format!("Running {}...", filename).as_str()); - if compilecmd.status.success() { - let runcmd = Command::new("./temp").output().expect("fail"); - bar.finish_and_clear(); - - if runcmd.status.success() { - println!("{}", String::from_utf8_lossy(&runcmd.stdout)); - let formatstr = - format!("{} Successfully ran {}", Emoji("✅", "✓"), filename); - println!("{}", style(formatstr).green()); - clean(); - } else { - println!("{}", String::from_utf8_lossy(&runcmd.stdout)); - println!("{}", String::from_utf8_lossy(&runcmd.stderr)); - - let formatstr = - format!("{} Ran {} with errors", Emoji("⚠️ ", "!"), filename); - println!("{}", style(formatstr).red()); - clean(); - } - } else { - bar.finish_and_clear(); - let formatstr = format!( - "{} Compilation of {} failed! Compiler error message:\n", - Emoji("⚠️ ", "!"), - filename - ); - println!("{}", style(formatstr).red()); - println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); - clean(); - } - } else { - panic!("Please supply a filename!"); - } + run(matches.clone()); } if let Some(_) = matches.subcommand_matches("verify") { @@ -128,112 +89,3 @@ fn watch() -> notify::Result<()> { } } } - -fn verify() -> Result<(), ()> { - compile_only("exercises/ex1.rs")?; - compile_only("exercises/ex2.rs")?; - compile_only("exercises/ex3.rs")?; - compile_only("exercises/ex4.rs")?; - compile_only("exercises/ex5.rs")?; - compile_only("exercises/variables/variables1.rs")?; - compile_only("exercises/variables/variables2.rs")?; - compile_only("exercises/variables/variables3.rs")?; - compile_only("exercises/variables/variables4.rs")?; - compile_only("exercises/functions/functions1.rs")?; - compile_only("exercises/functions/functions2.rs")?; - compile_only("exercises/functions/functions3.rs")?; - compile_only("exercises/functions/functions4.rs")?; - compile_only("exercises/functions/functions5.rs")?; - compile_only("exercises/primitive_types/primitive_types1.rs")?; - compile_only("exercises/primitive_types/primitive_types2.rs")?; - compile_only("exercises/primitive_types/primitive_types3.rs")?; - compile_only("exercises/primitive_types/primitive_types4.rs")?; - compile_only("exercises/primitive_types/primitive_types5.rs")?; - compile_only("exercises/primitive_types/primitive_types6.rs")?; - test("exercises/tests/tests1.rs")?; - test("exercises/tests/tests2.rs")?; - test("exercises/tests/tests3.rs")?; - test("exercises/tests/tests4.rs")?; - test("exercises/if/if1.rs")?; - compile_only("exercises/strings/strings1.rs")?; - compile_only("exercises/strings/strings2.rs")?; - compile_only("exercises/strings/strings3.rs")?; - compile_only("exercises/move_semantics/move_semantics1.rs")?; - compile_only("exercises/move_semantics/move_semantics2.rs")?; - compile_only("exercises/move_semantics/move_semantics3.rs")?; - compile_only("exercises/move_semantics/move_semantics4.rs")?; - compile_only("exercises/modules/modules1.rs")?; - compile_only("exercises/modules/modules2.rs")?; - compile_only("exercises/macros/macros1.rs")?; - compile_only("exercises/macros/macros2.rs")?; - compile_only("exercises/macros/macros3.rs")?; - compile_only("exercises/macros/macros4.rs")?; - test("exercises/error_handling/errors1.rs")?; - test("exercises/error_handling/errors2.rs")?; - test("exercises/error_handling/errors3.rs")?; - test("exercises/error_handling/errorsn.rs")?; - compile_only("exercises/error_handling/option1.rs")?; - test("exercises/error_handling/result1.rs")?; - Ok(()) -} - -fn compile_only(filename: &str) -> Result<(), ()> { - let bar = ProgressBar::new_spinner(); - bar.set_message(format!("Compiling {}...", filename).as_str()); - bar.enable_steady_tick(100); - let compilecmd = Command::new("rustc") - .args(&[filename, "-o", "temp", "--color", "always"]) - .output() - .expect("fail"); - bar.finish_and_clear(); - if compilecmd.status.success() { - let formatstr = format!( - "{} Successfully compiled {}!", - Emoji("✅", "✓"), - filename - ); - println!("{}", style(formatstr).green()); - clean(); - Ok(()) - } else { - let formatstr = format!( - "{} Compilation of {} failed! Compiler error message:\n", - Emoji("⚠️ ", "!"), - filename - ); - println!("{}", style(formatstr).red()); - println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); - clean(); - Err(()) - } -} - -fn test(filename: &str) -> Result<(), ()> { - let bar = ProgressBar::new_spinner(); - bar.set_message(format!("Testing {}...", filename).as_str()); - bar.enable_steady_tick(100); - let testcmd = Command::new("rustc") - .args(&["--test", filename, "-o", "temp"]) - .output() - .expect("fail"); - bar.finish_and_clear(); - if testcmd.status.success() { - let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename); - println!("{}", style(formatstr).green()); - clean(); - Ok(()) - } else { - let formatstr = format!( - "{} Testing of {} failed! Please try again.", - Emoji("⚠️ ", "!"), - filename - ); - println!("{}", style(formatstr).red()); - clean(); - Err(()) - } -} - -fn clean() { - let _ignored = remove_file("temp"); -} diff --git a/src/run.rs b/src/run.rs new file mode 100644 index 0000000..9605370 --- /dev/null +++ b/src/run.rs @@ -0,0 +1,49 @@ +use console::{style, Emoji}; +use indicatif::ProgressBar; +use std::process::Command; +use crate::util::clean; + +pub fn run(matches: clap::ArgMatches) { + if let Some(filename) = matches.value_of("file") { + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Compiling {}...", filename).as_str()); + bar.enable_steady_tick(100); + let compilecmd = Command::new("rustc") + .args(&[filename, "-o", "temp"]) + .output() + .expect("fail"); + bar.set_message(format!("Running {}...", filename).as_str()); + if compilecmd.status.success() { + let runcmd = Command::new("./temp").output().expect("fail"); + bar.finish_and_clear(); + + if runcmd.status.success() { + println!("{}", String::from_utf8_lossy(&runcmd.stdout)); + let formatstr = + format!("{} Successfully ran {}", Emoji("✅", "✓"), filename); + println!("{}", style(formatstr).green()); + clean(); + } else { + println!("{}", String::from_utf8_lossy(&runcmd.stdout)); + println!("{}", String::from_utf8_lossy(&runcmd.stderr)); + + let formatstr = + format!("{} Ran {} with errors", Emoji("⚠️ ", "!"), filename); + println!("{}", style(formatstr).red()); + clean(); + } + } else { + bar.finish_and_clear(); + let formatstr = format!( + "{} Compilation of {} failed! Compiler error message:\n", + Emoji("⚠️ ", "!"), + filename + ); + println!("{}", style(formatstr).red()); + println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); + clean(); + } + } else { + panic!("Please supply a filename!"); + } +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..37a2028 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,5 @@ +use std::fs::remove_file; + +pub fn clean() { + let _ignored = remove_file("temp"); +} diff --git a/src/verify.rs b/src/verify.rs new file mode 100644 index 0000000..e4a1d2a --- /dev/null +++ b/src/verify.rs @@ -0,0 +1,109 @@ +use console::{style, Emoji}; +use indicatif::ProgressBar; +use std::process::Command; +use crate::util::clean; + +pub fn verify() -> Result<(), ()> { + compile_only("exercises/ex1.rs")?; + compile_only("exercises/ex2.rs")?; + compile_only("exercises/ex3.rs")?; + compile_only("exercises/ex4.rs")?; + compile_only("exercises/ex5.rs")?; + compile_only("exercises/variables/variables1.rs")?; + compile_only("exercises/variables/variables2.rs")?; + compile_only("exercises/variables/variables3.rs")?; + compile_only("exercises/variables/variables4.rs")?; + compile_only("exercises/functions/functions1.rs")?; + compile_only("exercises/functions/functions2.rs")?; + compile_only("exercises/functions/functions3.rs")?; + compile_only("exercises/functions/functions4.rs")?; + compile_only("exercises/functions/functions5.rs")?; + compile_only("exercises/primitive_types/primitive_types1.rs")?; + compile_only("exercises/primitive_types/primitive_types2.rs")?; + compile_only("exercises/primitive_types/primitive_types3.rs")?; + compile_only("exercises/primitive_types/primitive_types4.rs")?; + compile_only("exercises/primitive_types/primitive_types5.rs")?; + compile_only("exercises/primitive_types/primitive_types6.rs")?; + test("exercises/tests/tests1.rs")?; + test("exercises/tests/tests2.rs")?; + test("exercises/tests/tests3.rs")?; + test("exercises/tests/tests4.rs")?; + test("exercises/if/if1.rs")?; + compile_only("exercises/strings/strings1.rs")?; + compile_only("exercises/strings/strings2.rs")?; + compile_only("exercises/strings/strings3.rs")?; + compile_only("exercises/move_semantics/move_semantics1.rs")?; + compile_only("exercises/move_semantics/move_semantics2.rs")?; + compile_only("exercises/move_semantics/move_semantics3.rs")?; + compile_only("exercises/move_semantics/move_semantics4.rs")?; + compile_only("exercises/modules/modules1.rs")?; + compile_only("exercises/modules/modules2.rs")?; + compile_only("exercises/macros/macros1.rs")?; + compile_only("exercises/macros/macros2.rs")?; + compile_only("exercises/macros/macros3.rs")?; + compile_only("exercises/macros/macros4.rs")?; + test("exercises/error_handling/errors1.rs")?; + test("exercises/error_handling/errors2.rs")?; + test("exercises/error_handling/errors3.rs")?; + test("exercises/error_handling/errorsn.rs")?; + compile_only("exercises/error_handling/option1.rs")?; + test("exercises/error_handling/result1.rs")?; + Ok(()) +} + +fn compile_only(filename: &str) -> Result<(), ()> { + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Compiling {}...", filename).as_str()); + bar.enable_steady_tick(100); + let compilecmd = Command::new("rustc") + .args(&[filename, "-o", "temp", "--color", "always"]) + .output() + .expect("fail"); + bar.finish_and_clear(); + if compilecmd.status.success() { + let formatstr = format!( + "{} Successfully compiled {}!", + Emoji("✅", "✓"), + filename + ); + println!("{}", style(formatstr).green()); + clean(); + Ok(()) + } else { + let formatstr = format!( + "{} Compilation of {} failed! Compiler error message:\n", + Emoji("⚠️ ", "!"), + filename + ); + println!("{}", style(formatstr).red()); + println!("{}", String::from_utf8_lossy(&compilecmd.stderr)); + clean(); + Err(()) + } +} + +fn test(filename: &str) -> Result<(), ()> { + let bar = ProgressBar::new_spinner(); + bar.set_message(format!("Testing {}...", filename).as_str()); + bar.enable_steady_tick(100); + let testcmd = Command::new("rustc") + .args(&["--test", filename, "-o", "temp"]) + .output() + .expect("fail"); + bar.finish_and_clear(); + if testcmd.status.success() { + let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename); + println!("{}", style(formatstr).green()); + clean(); + Ok(()) + } else { + let formatstr = format!( + "{} Testing of {} failed! Please try again.", + Emoji("⚠️ ", "!"), + filename + ); + println!("{}", style(formatstr).red()); + clean(); + Err(()) + } +} -- cgit v1.2.3 From e03a98cbf6491dcf36e8a96fda20764bc1e1748e Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:33:58 +0100 Subject: rustfmt --- src/main.rs | 39 +++++++++++++++++++-------------------- src/run.rs | 12 +++++------- src/verify.rs | 2 +- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0fc0692..c229e0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,19 @@ -use clap::{App, Arg, SubCommand, crate_version}; -use syntect::easy::HighlightFile; -use syntect::parsing::SyntaxSet; -use syntect::highlighting::{ThemeSet, Style}; -use syntect::util::{as_24_bit_terminal_escaped}; +use crate::run::run; +use crate::verify::verify; +use clap::{crate_version, App, Arg, SubCommand}; +use notify::DebouncedEvent; +use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use std::io::BufRead; use std::sync::mpsc::channel; use std::time::Duration; -use notify::DebouncedEvent; -use notify::{RecommendedWatcher, Watcher, RecursiveMode}; -use crate::verify::verify; -use crate::run::run; +use syntect::easy::HighlightFile; +use syntect::highlighting::{Style, ThemeSet}; +use syntect::parsing::SyntaxSet; +use syntect::util::as_24_bit_terminal_escaped; mod run; -mod verify; mod util; +mod verify; fn main() { let matches = App::new("rustlings") @@ -26,11 +26,12 @@ fn main() { SubCommand::with_name("run") .alias("r") .arg(Arg::with_name("file").required(true).index(1)), - ).get_matches(); + ) + .get_matches(); let ss = SyntaxSet::load_defaults_newlines(); let ts = ThemeSet::load_defaults(); - + println!(r#" _ _ _ "#); println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); @@ -55,7 +56,8 @@ fn main() { } if let None = matches.subcommand_name() { - let mut highlighter = HighlightFile::new("default_out.md", &ss, &ts.themes["base16-eighties.dark"]).unwrap(); + let mut highlighter = + HighlightFile::new("default_out.md", &ss, &ts.themes["base16-eighties.dark"]).unwrap(); for maybe_line in highlighter.reader.lines() { let line = maybe_line.unwrap(); let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line, &ss); @@ -76,14 +78,11 @@ fn watch() -> notify::Result<()> { loop { match rx.recv() { - Ok(event) => { - match event { - DebouncedEvent::Chmod(_) - | DebouncedEvent::Write(_) => { - let _ignored = verify(); - } - _ => {} + Ok(event) => match event { + DebouncedEvent::Chmod(_) | DebouncedEvent::Write(_) => { + let _ignored = verify(); } + _ => {} }, Err(e) => println!("watch error: {:?}", e), } diff --git a/src/run.rs b/src/run.rs index 9605370..093d1e4 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,7 +1,7 @@ +use crate::util::clean; use console::{style, Emoji}; use indicatif::ProgressBar; use std::process::Command; -use crate::util::clean; pub fn run(matches: clap::ArgMatches) { if let Some(filename) = matches.value_of("file") { @@ -16,19 +16,17 @@ pub fn run(matches: clap::ArgMatches) { if compilecmd.status.success() { let runcmd = Command::new("./temp").output().expect("fail"); bar.finish_and_clear(); - + if runcmd.status.success() { println!("{}", String::from_utf8_lossy(&runcmd.stdout)); - let formatstr = - format!("{} Successfully ran {}", Emoji("✅", "✓"), filename); + let formatstr = format!("{} Successfully ran {}", Emoji("✅", "✓"), filename); println!("{}", style(formatstr).green()); clean(); } else { println!("{}", String::from_utf8_lossy(&runcmd.stdout)); println!("{}", String::from_utf8_lossy(&runcmd.stderr)); - - let formatstr = - format!("{} Ran {} with errors", Emoji("⚠️ ", "!"), filename); + + let formatstr = format!("{} Ran {} with errors", Emoji("⚠️ ", "!"), filename); println!("{}", style(formatstr).red()); clean(); } diff --git a/src/verify.rs b/src/verify.rs index e4a1d2a..4da1562 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,7 +1,7 @@ +use crate::util::clean; use console::{style, Emoji}; use indicatif::ProgressBar; use std::process::Command; -use crate::util::clean; pub fn verify() -> Result<(), ()> { compile_only("exercises/ex1.rs")?; -- cgit v1.2.3 From 7fa2f87c8b47dbb79d4c6e41bdd095e6962270fa Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:44:55 +0100 Subject: make the default output a bit nicer --- default_out.md | 2 -- src/main.rs | 18 +++++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/default_out.md b/default_out.md index 7cbdffc..e221d78 100644 --- a/default_out.md +++ b/default_out.md @@ -1,4 +1,2 @@ -## Welcome to Rustlings! - To get started, run `rustlings verify` in order to get the first exercise. Make sure to have your editor open! \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c229e0b..779e4b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,13 +32,17 @@ fn main() { let ss = SyntaxSet::load_defaults_newlines(); let ts = ThemeSet::load_defaults(); - println!(r#" _ _ _ "#); - println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); - println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); - println!(r#" | | | |_| \__ \ |_| | | | | | (_| \__ \ "#); - println!(r#" |_| \__,_|___/\__|_|_|_| |_|\__, |___/ "#); - println!(r#" |___/ "#); - println!(""); + if None == matches.subcommand_name() { + println!(""); + println!(r#" welcome to... "#); + println!(r#" _ _ _ "#); + println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#); + println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#); + println!(r#" | | | |_| \__ \ |_| | | | | | (_| \__ \ "#); + println!(r#" |_| \__,_|___/\__|_|_|_| |_|\__, |___/ "#); + println!(r#" |___/ "#); + println!(""); + } if let Some(matches) = matches.subcommand_matches("run") { run(matches.clone()); -- cgit v1.2.3 From 6fb82fd63472f7acd91f185204eb6f96d56c4b31 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 20:54:12 +0100 Subject: make default out substantially more helpful --- default_out.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/default_out.md b/default_out.md index e221d78..3e00c10 100644 --- a/default_out.md +++ b/default_out.md @@ -1,2 +1,20 @@ +Thanks for installing `rustlings`! + +## Is this your first time? + +Let's make sure you're up to speed: +- You have Rust installed, preferably via `rustup` +- You have `~/.cargo/bin` added to your PATH variable +- You have cloned this repository (https://github.com/rustlings/rustlings) +- You have installed Rust language support for your editor +- You have locally installed the `rustlings` command by running: + +```sh +cargo install --path . +``` + +If you've done all of this (or even most of it), congrats! You're ready +to start working with Rust. + To get started, run `rustlings verify` in order to get the first exercise. Make sure to have your editor open! \ No newline at end of file -- cgit v1.2.3 From 7907dedda664810b3d6087d13ffc505f6cb87159 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 21:02:47 +0100 Subject: clean up readme --- README.md | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 2c86cfd..76ced0e 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,37 @@ # rustlings -Greetings and welcome to rustlings. This project contains small exercises to get you used to reading and writing code. This includes reading and responding to compiler messages! +Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages! -## How to get started +Alternatively, for a first-time Rust learner, there's several other resources: -To use rustlings you need to have a [Rust](https://www.rust-lang.org/) toolchain installed. To install it go to [rustup.rs](https://rustup.rs/). +- [The Book](https://doc.rust-lang.org/book/index.html) - The most comprehensive resource for learning Rust, but a bit theoretical sometimes +- [Rust By Example](https://doc.rust-lang.org/rust-by-example/index.html) - Learn Rust by solving little exercises! It's almost like `rustlings`, but online -Once Rust is installed, clone the rustlings repository and enter the resulting directory: +## Getting Started + +To use `rustlings` you need to have [Rust](https://www.rust-lang.org/) installed on your computer. To install Rust, go to [rustup.rs](https://rustup.rs/). + +Once Rust is installed, clone the `rustlings` repository and enter the resulting directory: ```bash git clone https://github.com/rustlings/rustlings.git cd rustlings ``` -Once in the directory you can install rustlings on your machine and run exercises: +Once in the directory you can install `rustlings` on your machine and run the introduction: ```bash cargo install --path . -rustlings -``` - -Or run rustlings directly with cargo, without installing it: - -```bash -cargo run +rustlings ``` -If you choose to not install rustlings, just replace `rustlings` with `cargo run` in the rest of this text. +If you choose to not install the `rustlings` command, just replace `rustlings` with `cargo run` in the rest of this text. ## Doing exercises -The exercises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. For every topic there is an additional README file with some resources to get you started on the topic. We really recommend, that you have a look at them before you start. - -For every topic there is an additional README file with some resources to get you started on the topic. We really recommend, that you have a look at them before you start. - -Your task is simple. Every exercise contains an error you have to solve, in order to make it compile. +The exercises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. For every topic there is an additional README file with some resources to get you started on the topic. We really recommend that you have a look at them before you start. -Running `rustlings verify` will compile every exercise in the recommended order. It will stop at the first exercise that didn't compile and show you the error to be solved. +Your task is simple. Every exercise contains an error you have to solve in order to make it compile. Running `rustlings verify` will compile every exercise in the recommended order. It will stop at the first exercise that didn't compile and show you the error to be solved. `rustlings watch` will rerun this verification every time you save an exercise. -- cgit v1.2.3 From 2b31ae1afe2bcb399422a47664367535e30568da Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 21:11:09 +0100 Subject: add "logo" --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76ced0e..a1db31b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# rustlings +# ![crab pet](http://i.imgur.com/LbZJgmm.gif) Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages! -- cgit v1.2.3 From 3e0c25d24d67ee68ca7b256f7150043a09e6abb6 Mon Sep 17 00:00:00 2001 From: lynn <819880950@qq.com> Date: Wed, 9 Jan 2019 21:13:39 +0100 Subject: Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a1db31b..2072e40 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# ![crab pet](http://i.imgur.com/LbZJgmm.gif) +![crab pet](http://i.imgur.com/LbZJgmm.gif) + +# rustlings Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages! -- cgit v1.2.3 From ed89ada148907a6b05b8a2357267931e3c3b6c8f Mon Sep 17 00:00:00 2001 From: lynn <819880950@qq.com> Date: Wed, 9 Jan 2019 21:17:02 +0100 Subject: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2072e40..f6ba239 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![crab pet](http://i.imgur.com/LbZJgmm.gif) -# rustlings +# rustlings 🦀❤️ Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages! -- cgit v1.2.3 From b90f642029568dc4260601693f2e13cd41637048 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 21:26:12 +0100 Subject: remove the ex*.rs files --- ex6.rs | 47 ----------------------------------------------- exercises/ex1.rs | 6 ------ exercises/ex2.rs | 10 ---------- exercises/ex3.rs | 10 ---------- exercises/ex4.rs | 14 -------------- exercises/ex5.rs | 22 ---------------------- src/verify.rs | 5 ----- 7 files changed, 114 deletions(-) delete mode 100644 ex6.rs delete mode 100755 exercises/ex1.rs delete mode 100755 exercises/ex2.rs delete mode 100755 exercises/ex3.rs delete mode 100755 exercises/ex4.rs delete mode 100755 exercises/ex5.rs diff --git a/ex6.rs b/ex6.rs deleted file mode 100644 index 33e589d..0000000 --- a/ex6.rs +++ /dev/null @@ -1,47 +0,0 @@ -// ex6.rs -// Make me compile! Scroll down for hints :) - -fn main() { - let robot_name = Some(String::from("Bors")); - - match robot_name { - Some(name) => println!("Found a name: {}", name), - None => (), - } - - println!("robot_name is: {:?}", robot_name); -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Hint: The following two statements are equivalent: -// let x = &y; -// let ref x = y; diff --git a/exercises/ex1.rs b/exercises/ex1.rs deleted file mode 100755 index dc5f9ca..0000000 --- a/exercises/ex1.rs +++ /dev/null @@ -1,6 +0,0 @@ -// ex1.rs -// Make me compile! :) - -fn main() { - println(); -} diff --git a/exercises/ex2.rs b/exercises/ex2.rs deleted file mode 100755 index 0fd714d..0000000 --- a/exercises/ex2.rs +++ /dev/null @@ -1,10 +0,0 @@ -// ex2.rs -// Make me compile! - -fn something() -> String { - "hi!" -} - -fn main() { - println!("{}", something()); -} diff --git a/exercises/ex3.rs b/exercises/ex3.rs deleted file mode 100755 index db27ad2..0000000 --- a/exercises/ex3.rs +++ /dev/null @@ -1,10 +0,0 @@ -// ex3.rs -// Make me compile! - -struct Foo { - capacity: i32, -} - -fn main() { - println!("{:?}", Foo { capacity: 3 }); -} diff --git a/exercises/ex4.rs b/exercises/ex4.rs deleted file mode 100755 index 362a557..0000000 --- a/exercises/ex4.rs +++ /dev/null @@ -1,14 +0,0 @@ -// ex4.rs -// Make me compile! - -fn something() -> Result { - 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), - } -} diff --git a/exercises/ex5.rs b/exercises/ex5.rs deleted file mode 100755 index 2eb8cfd..0000000 --- a/exercises/ex5.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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); -} diff --git a/src/verify.rs b/src/verify.rs index 4da1562..b396dc0 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -4,11 +4,6 @@ use indicatif::ProgressBar; use std::process::Command; pub fn verify() -> Result<(), ()> { - compile_only("exercises/ex1.rs")?; - compile_only("exercises/ex2.rs")?; - compile_only("exercises/ex3.rs")?; - compile_only("exercises/ex4.rs")?; - compile_only("exercises/ex5.rs")?; compile_only("exercises/variables/variables1.rs")?; compile_only("exercises/variables/variables2.rs")?; compile_only("exercises/variables/variables3.rs")?; -- cgit v1.2.3 From 17e12433cbe0174fe93196a43953af95ccb71dae Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 21:47:50 +0100 Subject: add a test --- exercises/test1.rs | 15 +++++++++++++++ src/verify.rs | 1 + 2 files changed, 16 insertions(+) create mode 100644 exercises/test1.rs diff --git a/exercises/test1.rs b/exercises/test1.rs new file mode 100644 index 0000000..6d7a2e8 --- /dev/null +++ b/exercises/test1.rs @@ -0,0 +1,15 @@ +// test1.rs +// Make me compile! Scroll down for hints :) + +fn something() -> [f32; 120] { + ??? +} + +fn something_else() -> String { + ??? +} + +fn main() { + println!("This array is {} items long, and it should be 120", something().len()); + println!("This function returns a string: {}", something_else()); +} diff --git a/src/verify.rs b/src/verify.rs index b396dc0..5e5108c 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -19,6 +19,7 @@ pub fn verify() -> Result<(), ()> { compile_only("exercises/primitive_types/primitive_types4.rs")?; compile_only("exercises/primitive_types/primitive_types5.rs")?; compile_only("exercises/primitive_types/primitive_types6.rs")?; + compile_only("exercises/test1.rs")?; test("exercises/tests/tests1.rs")?; test("exercises/tests/tests2.rs")?; test("exercises/tests/tests3.rs")?; -- cgit v1.2.3 From 141db7795b23d066a2b7c798d16c96ff53aa5a52 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 9 Jan 2019 22:04:08 +0100 Subject: add --test run flag --- src/main.rs | 3 ++- src/run.rs | 8 ++++++++ src/verify.rs | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 779e4b9..b74cda7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,8 @@ fn main() { .subcommand( SubCommand::with_name("run") .alias("r") - .arg(Arg::with_name("file").required(true).index(1)), + .arg(Arg::with_name("file").required(true).index(1)) + .arg(Arg::with_name("test").short("t").long("test")), ) .get_matches(); diff --git a/src/run.rs b/src/run.rs index 093d1e4..809b79d 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,10 +1,18 @@ use crate::util::clean; +use crate::verify::test; use console::{style, Emoji}; use indicatif::ProgressBar; use std::process::Command; pub fn run(matches: clap::ArgMatches) { if let Some(filename) = matches.value_of("file") { + if matches.is_present("test") { + match test(filename) { + Ok(_) => (), + Err(_) => (), + } + std::process::exit(0); + } let bar = ProgressBar::new_spinner(); bar.set_message(format!("Compiling {}...", filename).as_str()); bar.enable_steady_tick(100); diff --git a/src/verify.rs b/src/verify.rs index 5e5108c..c5f3266 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -78,7 +78,7 @@ fn compile_only(filename: &str) -> Result<(), ()> { } } -fn test(filename: &str) -> Result<(), ()> { +pub fn test(filename: &str) -> Result<(), ()> { let bar = ProgressBar::new_spinner(); bar.set_message(format!("Testing {}...", filename).as_str()); bar.enable_steady_tick(100); -- cgit v1.2.3 From dc1f3b79f8b528659e39057ac733d07e1051bc4d Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 23 Jan 2019 20:48:01 +0100 Subject: add tests; refactor exercise links --- exercises/if/if1.rs | 1 + exercises/primitive_types/primitive_types4.rs | 4 ++-- exercises/primitive_types/primitive_types5.rs | 2 +- exercises/primitive_types/primitive_types6.rs | 2 +- exercises/strings/strings3.rs | 21 --------------------- exercises/test1.rs | 25 +++++++++++++++---------- exercises/test2.rs | 22 ++++++++++++++++++++++ exercises/test3.rs | 24 ++++++++++++++++++++++++ exercises/test4.rs | 12 ++++++++++++ exercises/tests/tests1.rs | 2 +- exercises/tests/tests3.rs | 4 ++-- exercises/tests/tests4.rs | 19 ------------------- src/verify.rs | 17 +++++++++-------- 13 files changed, 90 insertions(+), 65 deletions(-) delete mode 100755 exercises/strings/strings3.rs create mode 100755 exercises/test2.rs create mode 100755 exercises/test3.rs create mode 100644 exercises/test4.rs delete mode 100755 exercises/tests/tests4.rs diff --git a/exercises/if/if1.rs b/exercises/if/if1.rs index 5118657..6dd64c0 100755 --- a/exercises/if/if1.rs +++ b/exercises/if/if1.rs @@ -9,6 +9,7 @@ pub fn bigger(a: i32, b:i32) -> i32 { // Scroll down for hints. } +// Don't mind this for now :) #[cfg(test)] mod tests { use super::*; diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs index 7dc9e47..1147cf7 100755 --- a/exercises/primitive_types/primitive_types4.rs +++ b/exercises/primitive_types/primitive_types4.rs @@ -39,11 +39,11 @@ fn main() { // Take a look at the Understanding Ownership -> Slices -> Other Slices section of the book: -// https://doc.rust-lang.org/stable/book/second-edition/ch04-03-slices.html#other-slices +// https://doc.rust-lang.org/book/ch04-03-slices.html // 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 section of the book: -// https://doc.rust-lang.org/stable/book/second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods +// https://doc.rust-lang.org/book/ch15-02-deref.html diff --git a/exercises/primitive_types/primitive_types5.rs b/exercises/primitive_types/primitive_types5.rs index 4045e78..ae849b4 100755 --- a/exercises/primitive_types/primitive_types5.rs +++ b/exercises/primitive_types/primitive_types5.rs @@ -39,7 +39,7 @@ fn main() { // Take a look at the Data Types -> The Tuple Type section of the book: -// https://doc.rust-lang.org/stable/book/second-edition/ch03-02-data-types.html#the-tuple-type +// https://doc.rust-lang.org/stable/book/ch03-02-data-types.html#the-tuple-type // Particularly the part about destructuring (second to last example in the section). // You'll need to make a pattern to bind `name` and `age` to the appropriate parts // of the tuple. You can do it!! diff --git a/exercises/primitive_types/primitive_types6.rs b/exercises/primitive_types/primitive_types6.rs index 439a56b..634e56b 100755 --- a/exercises/primitive_types/primitive_types6.rs +++ b/exercises/primitive_types/primitive_types6.rs @@ -41,5 +41,5 @@ fn main() { // While you could use a destructuring `let` for the tuple here, try // indexing into it instead, as explained in the last example of the // Data Types -> The Tuple Type section of the book: -// https://doc.rust-lang.org/stable/book/second-edition/ch03-02-data-types.html#the-tuple-type +// https://doc.rust-lang.org/stable/book/ch03-02-data-types.html#the-tuple-type // Now you have another tool in your toolbox! diff --git a/exercises/strings/strings3.rs b/exercises/strings/strings3.rs deleted file mode 100755 index b6f6a1e..0000000 --- a/exercises/strings/strings3.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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()); -} diff --git a/exercises/test1.rs b/exercises/test1.rs index 6d7a2e8..f52513d 100644 --- a/exercises/test1.rs +++ b/exercises/test1.rs @@ -1,15 +1,20 @@ // test1.rs -// Make me compile! Scroll down for hints :) +// This is a test for the following sections: +// - Variables +// - Functions -fn something() -> [f32; 120] { - ??? -} - -fn something_else() -> String { - ??? -} +// Mary is buying apples. One apple usually costs 2 dollars, but if you buy +// more than 40 at once, each apple only costs 1! Write a function that calculates +// the price of an order of apples given the order amount. fn main() { - println!("This array is {} items long, and it should be 120", something().len()); - println!("This function returns a string: {}", something_else()); + let price1 = calculateprice(55); + let price2 = calculateprice(40); + + // Don't modify this! + if price1 == 55 && price2 == 80 { + println!("Good job!"); + } else { + panic!("Uh oh! Wrong price!"); + } } diff --git a/exercises/test2.rs b/exercises/test2.rs new file mode 100755 index 0000000..249abbc --- /dev/null +++ b/exercises/test2.rs @@ -0,0 +1,22 @@ +// test2.rs +// This is a test for the following sections: +// - Tests + +// 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); + } +} diff --git a/exercises/test3.rs b/exercises/test3.rs new file mode 100755 index 0000000..e94b069 --- /dev/null +++ b/exercises/test3.rs @@ -0,0 +1,24 @@ +// strings3.rs +// This is a test for the following sections: +// - Strings + +// 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()); +} diff --git a/exercises/test4.rs b/exercises/test4.rs new file mode 100644 index 0000000..e50f1b0 --- /dev/null +++ b/exercises/test4.rs @@ -0,0 +1,12 @@ +// test4.rs +// This test covers the sections: +// - Modules +// - Macros + +// Write a macro that passes the test! No hints this time, you can do it! + +fn main() { + if my_macro!("world!") != "Hello world!" { + panic!("Oh no! Wrong output!"); + } +} diff --git a/exercises/tests/tests1.rs b/exercises/tests/tests1.rs index 959ed85..b11221f 100755 --- a/exercises/tests/tests1.rs +++ b/exercises/tests/tests1.rs @@ -1,7 +1,7 @@ // 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 +// rustlings run --test exercises/tests/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 :) diff --git a/exercises/tests/tests3.rs b/exercises/tests/tests3.rs index e041f38..e10d2aa 100755 --- a/exercises/tests/tests3.rs +++ b/exercises/tests/tests3.rs @@ -1,6 +1,6 @@ // 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 +// the test passes. Then write a second test that tests whether 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 { @@ -13,7 +13,7 @@ mod tests { #[test] fn is_true_when_even() { - assert!(false); + assert!(); } } diff --git a/exercises/tests/tests4.rs b/exercises/tests/tests4.rs deleted file mode 100755 index 23d444a..0000000 --- a/exercises/tests/tests4.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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); - } -} diff --git a/src/verify.rs b/src/verify.rs index c5f3266..9aa3a4b 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -8,36 +8,37 @@ pub fn verify() -> Result<(), ()> { compile_only("exercises/variables/variables2.rs")?; compile_only("exercises/variables/variables3.rs")?; compile_only("exercises/variables/variables4.rs")?; + test("exercises/if/if1.rs")?; compile_only("exercises/functions/functions1.rs")?; compile_only("exercises/functions/functions2.rs")?; compile_only("exercises/functions/functions3.rs")?; compile_only("exercises/functions/functions4.rs")?; compile_only("exercises/functions/functions5.rs")?; + compile_only("exercises/test1.rs")?; compile_only("exercises/primitive_types/primitive_types1.rs")?; compile_only("exercises/primitive_types/primitive_types2.rs")?; compile_only("exercises/primitive_types/primitive_types3.rs")?; compile_only("exercises/primitive_types/primitive_types4.rs")?; compile_only("exercises/primitive_types/primitive_types5.rs")?; compile_only("exercises/primitive_types/primitive_types6.rs")?; - compile_only("exercises/test1.rs")?; test("exercises/tests/tests1.rs")?; test("exercises/tests/tests2.rs")?; test("exercises/tests/tests3.rs")?; - test("exercises/tests/tests4.rs")?; - test("exercises/if/if1.rs")?; + test("exercises/test2.rs")?; compile_only("exercises/strings/strings1.rs")?; compile_only("exercises/strings/strings2.rs")?; - compile_only("exercises/strings/strings3.rs")?; - compile_only("exercises/move_semantics/move_semantics1.rs")?; - compile_only("exercises/move_semantics/move_semantics2.rs")?; - compile_only("exercises/move_semantics/move_semantics3.rs")?; - compile_only("exercises/move_semantics/move_semantics4.rs")?; + compile_only("exercises/test3.rs")?; compile_only("exercises/modules/modules1.rs")?; compile_only("exercises/modules/modules2.rs")?; compile_only("exercises/macros/macros1.rs")?; compile_only("exercises/macros/macros2.rs")?; compile_only("exercises/macros/macros3.rs")?; compile_only("exercises/macros/macros4.rs")?; + compile_only("exercises/test4.rs")?; + compile_only("exercises/move_semantics/move_semantics1.rs")?; + compile_only("exercises/move_semantics/move_semantics2.rs")?; + compile_only("exercises/move_semantics/move_semantics3.rs")?; + compile_only("exercises/move_semantics/move_semantics4.rs")?; test("exercises/error_handling/errors1.rs")?; test("exercises/error_handling/errors2.rs")?; test("exercises/error_handling/errors3.rs")?; -- cgit v1.2.3 From a49a22071ab0c675e43e03ab9c08b0153d8f9c74 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 23 Jan 2019 21:02:06 +0100 Subject: redo the section readmes --- exercises/functions/REAMDE.md | 8 +++++++- exercises/if/README.md | 7 +++++++ exercises/if/REAMDE.md | 1 - exercises/macros/README.md | 12 ++++++++++-- exercises/modules/README.md | 8 +++++++- exercises/move_semantics/README.md | 13 ++++++++----- exercises/primitive_types/README.md | 9 ++++++++- exercises/strings/REAMDE.md | 10 +++++++++- exercises/tests/README.md | 6 +++++- exercises/variables/README.md | 8 +++++++- 10 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 exercises/if/README.md delete mode 100644 exercises/if/REAMDE.md diff --git a/exercises/functions/REAMDE.md b/exercises/functions/REAMDE.md index 70555a1..c40755b 100644 --- a/exercises/functions/REAMDE.md +++ b/exercises/functions/REAMDE.md @@ -1 +1,7 @@ -For this exercise check out the chapter [Functions](https://doc.rust-lang.org/book/2018-edition/ch03-03-how-functions-work.html) of the Rust Book. \ No newline at end of file +### Functions + +Here, you'll learn how to write functions and how Rust's compiler can trace things way back. + +#### Book Sections + +- [How Functions Work](https://doc.rust-lang.org/stable/book/ch03-03-how-functions-work.html) diff --git a/exercises/if/README.md b/exercises/if/README.md new file mode 100644 index 0000000..996ac93 --- /dev/null +++ b/exercises/if/README.md @@ -0,0 +1,7 @@ +### If + +`if`, the most basic type of control flow, is what you'll learn here. + +#### Book Sections + +- [Control Flow - if expressions](https://doc.rust-lang.org/stable/book/ch03-05-control-flow.html#if-expressions) diff --git a/exercises/if/REAMDE.md b/exercises/if/REAMDE.md deleted file mode 100644 index 1061462..0000000 --- a/exercises/if/REAMDE.md +++ /dev/null @@ -1 +0,0 @@ -For this exercise check out the chapter [If](https://doc.rust-lang.org/book/2018-edition/ch03-05-control-flow.html?highlight=control,fl#control-flow) of the Rust Book. \ No newline at end of file diff --git a/exercises/macros/README.md b/exercises/macros/README.md index 87851c5..b8f8e42 100644 --- a/exercises/macros/README.md +++ b/exercises/macros/README.md @@ -1,2 +1,10 @@ -For this exercise check out the section [Macros](https://doc.rust-lang.org/book/2018-edition/macros.html) and the chapter -[Macros Appendix](https://doc.rust-lang.org/book/2018-edition/appendix-04-macros.html) of the Rust Book and [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html). +### Macros + +Rust's macro system is very powerful, but also kind of difficult to wrap your +head around. We're not going to teach you how to write your own fully-featured +modules, instead we'll show you how to use and create them. + +#### Book Sections + +- [Macros](https://doc.rust-lang.org/stable/book/ch19-06-macros.html) +- [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html) diff --git a/exercises/modules/README.md b/exercises/modules/README.md index 7a0232f..7a58d90 100644 --- a/exercises/modules/README.md +++ b/exercises/modules/README.md @@ -1 +1,7 @@ -For this exercise check out the [Modules](https://doc.rust-lang.org/book/2018-edition/ch07-01-mod-and-the-filesystem.html) chapter of the Rust Book. \ No newline at end of file +### Modules + +In this section we'll give you an introduction to Rust's module system. + +#### Book Sections + +- [The Module System](https://doc.rust-lang.org/stable/book/ch07-02-modules-and-use-to-control-scope-and-privacy.html) diff --git a/exercises/move_semantics/README.md b/exercises/move_semantics/README.md index c8095bf..1b9cab7 100644 --- a/exercises/move_semantics/README.md +++ b/exercises/move_semantics/README.md @@ -1,7 +1,10 @@ -These exercises are adapted from [pnkfelix](https://github.com/rustlings/rustlings/blob/master)'s [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- Thank you Felix!!! +### Move Semantics -For this exercise check out the chapters: -- [Ownership](https://doc.rust-lang.org/book/2018-edition/ch04-01-what-is-ownership.html) -- [Reference and borrowing](https://doc.rust-lang.org/book/2018-edition/ch04-02-references-and-borrowing.html) +These exercises are adapted from [pnkfelix](https://github.com/pnkfelix)'s [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- Thank you Felix!!! -of the Rust Book. \ No newline at end of file +#### Book Sections + +For this section, the book links are especially important. + +- [Ownership](https://doc.rust-lang.org/stable/book/ch04-01-what-is-ownership.html) +- [Reference and borrowing](https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html) diff --git a/exercises/primitive_types/README.md b/exercises/primitive_types/README.md index e4f3181..b53394a 100644 --- a/exercises/primitive_types/README.md +++ b/exercises/primitive_types/README.md @@ -1 +1,8 @@ -For this exercise check out the chapter [Data Types](https://doc.rust-lang.org/book/2018-edition/ch03-02-data-types.html) of the Rust Book. \ No newline at end of file +### Primitive Types + +Rust has a couple of basic types that are directly implemented into the +compiler. In this section, we'll go through the most important ones. + +#### Book Sections + +- [Data Types](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html) diff --git a/exercises/strings/REAMDE.md b/exercises/strings/REAMDE.md index 76b74d7..b79ac06 100644 --- a/exercises/strings/REAMDE.md +++ b/exercises/strings/REAMDE.md @@ -1 +1,9 @@ -For this exercise check out the chapter [Strings](https://doc.rust-lang.org/book/2018-edition/ch08-02-strings.html) of the Rust Book. \ No newline at end of file +### Strings + +Rust has two string types, a string slice (`&str`) and an owned string (`String`). +We're not going to dictate when you should use which one, but we'll show you how +to identify and create them, as well as use them. + +#### Book Sections + +- [Strings](https://doc.rust-lang.org/stable/book/ch08-02-strings.html) diff --git a/exercises/tests/README.md b/exercises/tests/README.md index 8683ba8..243b913 100644 --- a/exercises/tests/README.md +++ b/exercises/tests/README.md @@ -1,3 +1,7 @@ +### Tests + Going out of order from the book to cover tests -- many of the following exercises will ask you to make tests pass! -For this exercise check out the section [How to Write Tests](https://doc.rust-lang.org/book/2018-edition/ch11-01-writing-tests.html) of the Rust Book. \ No newline at end of file +#### Book Sections + +- [Writing Tests](https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html) diff --git a/exercises/variables/README.md b/exercises/variables/README.md index 574c162..6ae26cb 100644 --- a/exercises/variables/README.md +++ b/exercises/variables/README.md @@ -1 +1,7 @@ -For this exercise checkout the section [Variables and Mutability](https://doc.rust-lang.org/book/2018-edition/ch03-01-variables-and-mutability.html) of the Rust Book. \ No newline at end of file +### Variables + +Here you'll learn about simple variables. + +#### Book Sections + +- [Variables and Mutability](https://doc.rust-lang.org/stable/book/ch03-01-variables-and-mutability.html) -- cgit v1.2.3 From 63c50a34535c8b0214e33146b31464316be6bf06 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 23 Jan 2019 21:36:08 +0100 Subject: complete readme --- README.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f6ba239..0c15aa8 100644 --- a/README.md +++ b/README.md @@ -33,18 +33,83 @@ If you choose to not install the `rustlings` command, just replace `rustlings` w The exercises are sorted by topic and can be found in the subdirectory `rustlings/exercises/`. For every topic there is an additional README file with some resources to get you started on the topic. We really recommend that you have a look at them before you start. -Your task is simple. Every exercise contains an error you have to solve in order to make it compile. Running `rustlings verify` will compile every exercise in the recommended order. It will stop at the first exercise that didn't compile and show you the error to be solved. +The task is simple. Most exercises contain an error that keep it from compiling, and it's up to you to fix it! Some exercises are also ran as tests, but rustlings handles them all the same. To run the exercises in the recommended order, execute: -`rustlings watch` will rerun this verification every time you save an exercise. +```bash +rustlings verify +``` + +This will try to verify the completion of every exercise in a predetermined order (what we think is best for newcomers). If you don't want to rerun `verify` every time you change a file, you can run: + +```bash +rustlings watch +``` + +This will do the same as verify, but won't quit after running and instead automatically rerun as soon as you change a file in the `exercises/` directory. + +In case you want to go by your own order, or want to only verify a single exercise, you can run: -To compile and run a single exercise you can use `rustlings run `. +```bash +rustlings run exercises/path/to/exercise.rs +``` + +Or if it's a `#[test]`: + +```bash +rustlings run --test exercises/path/to/exercise_with_test.rs +``` In case you get stuck, there is usually a hint at the bottom of each exercise. -### Need help? +## Testing yourself + +After every couple of sections, there will be a test that'll test your knowledge on a bunch of sections at once. These tests are found in `exercises/testN.rs`. + +## Completion + +Rustlings isn't done; there are a couple of sections that are very experimental and don't have proper documentation. These include: + +- Errors (`exercises/errors/`) +- Option (`exercises/option/`) +- Result (`exercises/result/`) +- Move Semantics (could still be improved, `exercises/move_semantics/`) + +Additionally, we could use exercises on a couple of topics: + +- Structs +- Better ownership stuff +- `impl` +- ??? probably more + +If you are interested in improving or adding new ones, please feel free to contribute! Read on for more information :) + +## Contributing + +### Adding an exercise + +First step is to add the exercise! Call it `exercises/yourTopic/yourTopicN.rs`, make sure to +put in some helpful links, and link to sections of the book in `exercises/yourTopic/README.md`. + +Then, you'll want to make sure it gets verified when you run `rustlings verify`. Open `src/verify.rs` and +put your exercise somewhere in there: + +```diff + ... + compile_only("exercises/functions5.rs")?; ++ compile_only("exercises/yourTopic/yourTopicN.rs")?; + compile_only("exercises/test1.rs")?; + ... +``` + +That's all! + +### Working on the source code + +`rustlings` is basically a glorified `rustc` wrapper. Therefore the source code +isn't really that complicated since the bulk of the work is done by `rustc`. +`src/main.rs` contains a simple `clap` CLI that loads from `src/verify.rs` and `src/run.rs`. + +## Credits + +`rustlings` was originally written by [Carol](https://github.com/carols10cents)! -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! -- cgit v1.2.3 From 8cff8de4931f5c4b259431433d731ecc45d7604d Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 23 Jan 2019 21:43:32 +0100 Subject: add more detailed command help --- src/main.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index b74cda7..8f9ccea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,15 +18,16 @@ mod verify; fn main() { let matches = App::new("rustlings") .version(crate_version!()) - .author("Olivia Hugger") - .about("Test") - .subcommand(SubCommand::with_name("verify").alias("v")) - .subcommand(SubCommand::with_name("watch").alias("w")) + .author("Olivia Hugger, Carol Nichols") + .about("Rustlings is a collection of small exercises to get you used to writing and reading Rust code") + .subcommand(SubCommand::with_name("verify").alias("v").about("Verifies all exercises according to the recommended order")) + .subcommand(SubCommand::with_name("watch").alias("w").about("Reruns `verify` when files were edited")) .subcommand( SubCommand::with_name("run") .alias("r") + .about("Runs/Tests a single exercise") .arg(Arg::with_name("file").required(true).index(1)) - .arg(Arg::with_name("test").short("t").long("test")), + .arg(Arg::with_name("test").short("t").long("test").help("Run the file as a test")), ) .get_matches(); -- cgit v1.2.3 From f447adef8fba193dab8c27d8342e96fba63a6753 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 23 Jan 2019 21:51:53 +0100 Subject: minor readme change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c15aa8..ec3ac36 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Greetings and welcome to `rustlings`. This project contains small exercises to g Alternatively, for a first-time Rust learner, there's several other resources: -- [The Book](https://doc.rust-lang.org/book/index.html) - The most comprehensive resource for learning Rust, but a bit theoretical sometimes +- [The Book](https://doc.rust-lang.org/book/index.html) - The most comprehensive resource for learning Rust, but a bit theoretical sometimes. You will be using this along with Rustlings! - [Rust By Example](https://doc.rust-lang.org/rust-by-example/index.html) - Learn Rust by solving little exercises! It's almost like `rustlings`, but online ## Getting Started -- cgit v1.2.3 From 05f65d67aece9008d19b2bd5533a18b8b6fcf82c Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 23 Jan 2019 21:56:05 +0100 Subject: thematically refactor modules2 --- exercises/modules/modules2.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/exercises/modules/modules2.rs b/exercises/modules/modules2.rs index 164dfb0..d5946e5 100755 --- a/exercises/modules/modules2.rs +++ b/exercises/modules/modules2.rs @@ -1,25 +1,25 @@ // 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 delicious_snacks { + use self::fruits::PEAR as fruit; + use self::veggies::CUCUMBER as veggie; - mod democrats { - pub const HILLARY_CLINTON: &'static str = "Hillary Clinton"; - pub const BERNIE_SANDERS: &'static str = "Bernie Sanders"; + mod fruits { + pub const PEAR: &'static str = "Pear"; + pub const APPLE: &'static str = "Apple"; } - mod republicans { - pub const DONALD_TRUMP: &'static str = "Donald Trump"; - pub const JEB_BUSH: &'static str = "Jeb Bush"; + mod veggies { + pub const CUCUMBER: &'static str = "Cucumber"; + pub const CARROT: &'static str = "Carrot"; } } fn main() { - println!("candidates: {} and {}", - us_presidential_frontrunners::democrat, - us_presidential_frontrunners::republican); + println!("favorite snacks: {} and {}", + delicious_snacks::fruit, + delicious_snacks::veggie); } @@ -38,8 +38,8 @@ fn main() { -// 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 +// The delicious_snacks module is trying to present an external +// interface (the `fruit` and `veggie` constants) that is different than +// its internal structure (the `fruits` and `veggies` modules and // associated constants). It's almost there except for one keyword missing for // each constant. -- cgit v1.2.3 From 531f8fe6ff835bb8b464fcdabc5fec84f9ff35a5 Mon Sep 17 00:00:00 2001 From: liv Date: Wed, 23 Jan 2019 21:57:24 +0100 Subject: update cargo.toml authors --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5fe7438..e6a2a16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustlings" version = "0.1.0" -authors = ["olivia "] +authors = ["olivia <819880950@qq.com>", "Carol (Nichols || Goulding) Date: Wed, 23 Jan 2019 22:00:38 +0100 Subject: update readme with reference to the old version --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ec3ac36..762ae6b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages! +_...looking for the old, web-based version of Rustlings? Try [here](https://github.com/rustlings/rustlings/tree/rustlings-1)_ + Alternatively, for a first-time Rust learner, there's several other resources: - [The Book](https://doc.rust-lang.org/book/index.html) - The most comprehensive resource for learning Rust, but a bit theoretical sometimes. You will be using this along with Rustlings! -- cgit v1.2.3