diff --git a/.gitignore b/.gitignore index 5ec1830..c3719fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ +**/target +**/*.rs.bk **/.cargo/* diff --git a/branches/Cargo.lock b/branches/Cargo.lock new file mode 100644 index 0000000..4ca0c2d --- /dev/null +++ b/branches/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "branches" +version = "0.1.0" + diff --git a/branches/Cargo.toml b/branches/Cargo.toml new file mode 100644 index 0000000..55d1a68 --- /dev/null +++ b/branches/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "branches" +version = "0.1.0" +authors = ["Georg Hopp "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/branches/src/main.rs b/branches/src/main.rs new file mode 100644 index 0000000..a654126 --- /dev/null +++ b/branches/src/main.rs @@ -0,0 +1,31 @@ +// +// Control Flow Examples +// +// Georg Hopp +// +// Copyright © 2019 Georg Hopp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +fn main() { + let condition = true; + let number = if condition { + 5 + } else { + 6 + }; + + println!("The value of number is: {}", number); +} diff --git a/functions/Cargo.lock b/functions/Cargo.lock new file mode 100644 index 0000000..88287d1 --- /dev/null +++ b/functions/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "functions" +version = "0.1.0" + diff --git a/functions/Cargo.toml b/functions/Cargo.toml new file mode 100644 index 0000000..51f41d9 --- /dev/null +++ b/functions/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "functions" +version = "0.1.0" +authors = ["Georg Hopp "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/functions/src/main.rs b/functions/src/main.rs new file mode 100644 index 0000000..c078135 --- /dev/null +++ b/functions/src/main.rs @@ -0,0 +1,12 @@ +fn main() { + another_function(5, add_five(6)); +} + +fn another_function(x: i32, y: i32) { + println!("The value of x id: {}", x); + println!("The value of y id: {}", y); +} + +fn add_five(x: i32) -> i32 { + x + 5 +} diff --git a/guessing_game/.gitignore b/guessing_game/.gitignore deleted file mode 100644 index 53eaa21..0000000 --- a/guessing_game/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -**/*.rs.bk diff --git a/hello/.gitignore b/hello/.gitignore deleted file mode 100644 index 53eaa21..0000000 --- a/hello/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -**/*.rs.bk diff --git a/loops/Cargo.lock b/loops/Cargo.lock new file mode 100644 index 0000000..9942b36 --- /dev/null +++ b/loops/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "loops" +version = "0.1.0" + diff --git a/loops/Cargo.toml b/loops/Cargo.toml new file mode 100644 index 0000000..6efd743 --- /dev/null +++ b/loops/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "loops" +version = "0.1.0" +authors = ["Georg Hopp "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/loops/src/main.rs b/loops/src/main.rs new file mode 100644 index 0000000..2f6063d --- /dev/null +++ b/loops/src/main.rs @@ -0,0 +1,64 @@ +// +// Loops examples. +// +// Georg Hopp +// +// Copyright © 2019 Georg Hopp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +fn main() { + // It seams that to use loops this way you absolutely need a mutable. + // If I build it with a normal type and try to shadow it within the loop + // the outer variable is always used as input for the shadow, thus it is + // always the same.... that really sucks. + let mut counter = 0; + + let result = loop { + counter = counter + 1; + if counter == 10 { + break counter * 2; + } + }; + + println!("The result is {}", result); + + // The same is true with «while» ... which again sucks. + let mut number = 3; + + while number != 0 { + println!("{}!", number); + number = number - 1; + } + + println!("LIFTOFF!!!"); + + // apart from beeing frustrated about the above facts... lets continue. + let a = [10, 20, 30, 40, 50]; + let mut index = 0; + + while index < 5 { + println!("the value is: {}", a[index]); + index = index + 1; + } + + for element in a.iter() { + println!("the value is still: {}", element); + } + + for number in (1..4).rev() { + println!("for {}!", number); + } +} diff --git a/ownership/Cargo.lock b/ownership/Cargo.lock new file mode 100644 index 0000000..2aa4918 --- /dev/null +++ b/ownership/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "ownership" +version = "0.1.0" + diff --git a/ownership/Cargo.toml b/ownership/Cargo.toml new file mode 100644 index 0000000..d3b1aec --- /dev/null +++ b/ownership/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "ownership" +version = "0.1.0" +authors = ["Georg Hopp "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/ownership/src/main.rs b/ownership/src/main.rs new file mode 100644 index 0000000..cabc748 --- /dev/null +++ b/ownership/src/main.rs @@ -0,0 +1,183 @@ +// +// Examples related to ownership, also introducing String. +// +// Georg Hopp +// +// Copyright © 2019 Georg Hopp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +fn main() { + concat(); + move_variable(); + clone_variable(); + + let s = String::from("hello"); // s comes into scope + + take_ownership(s); // s's value moves into the function + // … and so is no longer valid here. + let x = 5; // x comes into scope + + makes_copy(x); // the scalar value has the Copy trait and + // lives on the stack and thus is still + // valid here. + + let _s1 = gives_ownership(); // move the return value into _s1 + let s2 = String::from("hello"); // s2 comes into scope + let _s3 = takes_and_gives(s2); // s2 is moved into function, which in + // turn moves the return value into _s3. + + let s1 = String::from("hello"); // s1 comes into scope. + let len = calculate_length(&s1); // A reference to s1 is given to a + // calculate_length which effectively is + // not s1 itself but another pointer to + // s1… which is the reason that we still + // can use it below. + let _another_s = &s1; // again only a reference which does not + // take ownership, thus s1 can still be + // used below. + println!("The length of '{}' is {}.", s1, len); + + // Passing values as reference to a function is called borrowing. A + // borrowed value can't be changed. + change(&s1); + + // but we can force this… which is probably not the best of ideas most + // of the time… + let mut s_mut = String::from("hello"); + change_mutable(&mut s_mut); + + // but you can have only one mutable reference of a value in a single + // scope. The following would fail with: + // cannot borrow `s_mut` as mutable more than once at a time second + // mutable borrow occurs here + // let r1 = &mut s_mut; + // let r2 = &mut s_mut; + // println!("{}, {}", r1, r2); + + // We also can't have an immutable reference while we have a mutable one. + // Look on Page 98 for an explanation. + + // The scope of references is not the whole block they are introduced in + // but goes only until their last usage. Thus if you first have an + // immutable reference but never use it after a mutable reference is + // declared, that would be ok… At all this is kind of confusing and very + // Mozzilaish. :D + + // Now we demonstrate string slices… + let s4 = String::from("hello world"); + let s_slice = first_word(&s4); + + // working with an mutable reference like with s4.clear() will not + // compile at this point because we already have and use later on an + // immutable reference. + + println!("The slice was: {}", s_slice); + + // not that string literals are slices. They are immutable references of + // the programs TEXT segment. Thats the reason why they are immutable. + + // Thus try generic_first_word… + println!("First word on literal: {}", generic_first_word("hello world")); + println!("First word on String: {}", generic_first_word(&s4[..])); +} // x and s go out of scope but nothing happens for s because this function + // has no longer the ownership of s. + // s3 goes out of scope and is dropped. s2 was moved and s1 is dropped. + +fn concat() { + let mut s = String::from("hello"); + s.push_str(", world!"); + println!("{}", s); +} + +fn move_variable() { + let s1 = String::from("hello"); + let s2 = s1; // does not copy data but only the String structure. + // when using s1 below we get an error that a moved value was borrowed. + println!("{}, world!", s2); +} + +fn clone_variable() { + let s1 = String::from("hello"); + let s2 = s1.clone(); + // this time both are valid. + println!("s1 = {}, s2 = {}", s1, s2) +} + +fn take_ownership(some_string: String) { // some_string comes into scope + println!("{}", some_string); +} // some_string goes out of scope and «drop» is called, thus memory freed. + +fn makes_copy(some_integer: i32) { // some integer comes into scope + println!("{}", some_integer); +} // Here, some_integer goes out of scope but because it was a copy and on the + // stack nothing special happens… beside that stack space is freed. + +fn gives_ownership() -> String { // this will move the return value into the + // calling function. + let some_string = String::from("hello"); // some_string comes into scope + some_string +} + +fn takes_and_gives(a_string: String) -> String { // a_string comes into scope + a_string // and is returned and moved + // to the calling function. +} // a_string goes out of scope but nothing happens as it is moved. + +fn calculate_length(s: &String) -> usize { // s comes into scope. It is a + // reference. References do not + // take ownership of the underlying + // value which is the String in + // main. + s.len() +} // Here s goes out of scope but because it has no ownership of the String + // nothing happens. + +fn change(_some_string: &String) { + // the following would give this error: + // `_some_string` is a `&` reference, so the data it refers to cannot be + // borrowed as mutable + // _some_string.push_str(", world!"); +} + +fn change_mutable(some_string: &mut String) { + some_string.push_str(", world"); +} + +fn first_word(s: &String) -> &str { + let bytes = s.as_bytes(); + + for (i, &item) in bytes.iter().enumerate() { + if item == b' ' { + return &s[..i]; + } + } + + &s[..] +} + +// To make first_word work on either string literals (which are in fact string +// slices, s.o.) one would write first_word like this… +fn generic_first_word(s: &str) -> &str { + let bytes = s.as_bytes(); + + for (i, &item) in bytes.iter().enumerate() { + if item == b' ' { + return &s[..i]; + } + } + + &s[..] +} diff --git a/variables/Cargo.lock b/variables/Cargo.lock new file mode 100644 index 0000000..2d62cbe --- /dev/null +++ b/variables/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "variables" +version = "0.1.0" + diff --git a/variables/Cargo.toml b/variables/Cargo.toml new file mode 100644 index 0000000..0c349db --- /dev/null +++ b/variables/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "variables" +version = "0.1.0" +authors = ["Georg Hopp "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/variables/src/main.rs b/variables/src/main.rs new file mode 100644 index 0000000..c4e4a19 --- /dev/null +++ b/variables/src/main.rs @@ -0,0 +1,6 @@ +fn main() { + let mut x = 5; + println!("The value of x is: {}", x); + x = 6; + println!("The value of x is: {}", x); +}