Rust Log for December Adventure of reviewing and studying Rust concepts.
12.19
-
studied measuring rust allocations, and rust range operators [a..b] https://chatgpt.com/share/676a2918-1b08-8002-97bb-1ab6881fd007
-
studied short-circuiting expressions, where the sub-expression (operand) is not necessarily evaluated https://chatgpt.com/share/676a2963-e77c-8002-9424-5a31b2f21e55
12.20
-
implemented anagram finder from leetcode https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bbdadd0c32dd60c915805e589fe2335d. clean version https://github.com/LeetCode-in-Rust/LeetCode-in-Rust?tab=readme-ov-file#udemy
-
studied Box, &dyn Debug, dynamically-sized types (DST), enum_dispatch (https://crates.io/crates/enum_dispatch)
-
studied HashMap and HashSet, as well as map.entry (for mutating hash maps)
12.21
- studied heap, stack, precedence, place, prefix operators and postfix operators, [i32] vs &[i32], https://users.rust-lang.org/t/vec-i32-vs-i32-vs-i32/122873/4?u=notplants
12.22
-
studied expressions and precedence. https://doc.rust-lang.org/reference/expressions.html
-
implemented iterator using generics https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=303bebb567a216119a9d59ae5cfa10be. based on this https://users.rust-lang.org/t/restrict-associated-type-of-trait-bound-to-make-a-difference-iterator/122878
-
studied where clause (for trait bounds, and for relationships between lifetimes)
-
studied expressions, statements, declarations and items (only declared at the root and module, by convention not normally declared within blocks)
-
studied closures, move, FnOnce, Fn and FnMut, the Copy trait
12.23
-
completed parens challenge https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=269bc9a2653083cd61e0d47eb5449a39
-
studied procedural and declarative macros. the perfect code https://doublefree.bearblog.dev/solving-advent-of-code-at-compile-time-with-rust-macros/ . https://chatgpt.com/share/676a27f5-61b4-8002-b1da-58240c60cb2c
-
studying lifetimes https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=68d0f74d70c6a07f5163175959b6f742
In Rust, a lifetime is always tied to a reference (&). Lifetimes are a way to specify how long a reference is valid, and they are not relevant for non-reference types like i32, String, or Vec
- studying static, concurrency, const, lazy_static, Mutex, Arc, RwLock, Rc, Cell, CellRef, interior mutability https://chatgpt.com/share/676a25ff-1dc0-8002-ba7b-ddf782a8c211
static is stored in its own place in memory, that is not the heap or the stack, and has a lifetime for the entire duration of the program. Sometimes referred to as “leaked heap value”.
-
attempting /home/notplants/computer/projects/lrust/LeetCode-in-Rust/src/main/rust/g0301_0400/s0322_coin_change (didnt get around to it)
-
the book, the reference, the rustonomicon https://doc.rust-lang.org/nomicon/intro.html
-
expressions and patterns are mirror opposites to each other https://h2co3.github.io/pattern/
-
the ref in static ref within lazy_static is actually a syntax for a macro. not an inherent rust thing. once_cell::sync::Lazy as a possible alternative to lazy_static https://docs.rs/once_cell/latest/once_cell/sync/struct.Lazy.html
12.25
- implemented dining philosophers https://google.github.io/comprehensive-rust/concurrency/sync-exercises/dining-philosophers.html
12.27
-
studied rust async https://m.youtube.com/watch?v=PabDPIrt9fk . 30 days of rust https://github.com/Hunterdii/30-Days-Of-Rust/blob/main/18_Asynchronous%20Programming/18_asynchronous_programming.md
-
https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md
A variable’s lifetime is how long the data it points to can be statically verified by the compiler to be valid at its current memory address.
Well yes, but a type with a ‘static lifetime is different from a type bounded by a ‘static lifetime. The latter can be dynamically allocated at run-time, can be safely and freely mutated, can be dropped, and can live for arbitrary durations.
T: ‘static includes all &‘static T however it also includes all owned types, like String, Vec, etc. The owner of some data is guaranteed that data will never get invalidated as long as the owner holds onto it, therefore the owner can safely hold onto the data indefinitely long, including up until the end of the program
from https://github.com/pretzelhammer/rust-blog/blob/master/posts/learning-rust-in-2024.md
-
completed dining philosophers with async https://google.github.io/comprehensive-rust/concurrency/async-exercises/dining-philosophers.html
-
asked a question about performance comparison between async and sync for dining philosophers
https://users.rust-lang.org/t/dining-philosophers-sync-vs-async/123152
also looked at this comparison of different async models https://users.rust-lang.org/t/all-concurrency-models-comparision-help/34886/3
-
todo: tutorial on building a runtime/executor https://ruspiro.github.io/ruspiro-async-book/03-00-build-the-runtime.html
-
todo: study this on covariance https://users.rust-lang.org/t/is-a-foo-a-a-footgun/122766/6. understand covariance. https://doc.rust-lang.org/nomicon/subtyping.html
-
todo: study this https://users.rust-lang.org/t/useful-case-for-mut-x/123135/6?u=notplants
The type F’s variance is how the subtyping of its inputs affects the subtyping of its outputs. There are three kinds of variance in Rust. Given two types Sub and Super, where Sub is a subtype of Super:
F is covariant if F<Sub> is a subtype of F<Super> (the subtype property is passed through)
F is contravariant if F<Super> is a subtype of F<Sub> (the subtype property is "inverted")
F is invariant otherwise (no subtyping relationship exists)
-
todo: spend more time with variance article to really understand it https://doc.rust-lang.org/nomicon/subtyping.html#variance
-
todo: study this https://users.rust-lang.org/t/can-two-mutable-objects-under-arc-talk-back-and-forth/123051/9?u=notplants
-
todo: study re-entrancy https://en.wikipedia.org/wiki/Reentrancy_(computing)
12.28
if ‘a contains ‘b then ‘a is a subtype of ‘b – the bigger scope is a subtype of the smaller scope
Variance is a property that type constructors have with respect to their arguments.
A type constructor in Rust is a generic type with unbound arguments
For instance Vec is a type constructor that takes a T and returns a Vec
& and &mut are type constructors that take two inputs: a lifetime, and a type to point to.
A type constructor’s variance is how the subtyping of its inputs affects the subtyping of its outputs.
‘static is a subtype of any ‘a
https://users.rust-lang.org/t/is-a-foo-a-a-footgun/122766/27?u=notplants
- verify_covariance, verify_contravariance https://users.rust-lang.org/t/contravariance-and-borrow-checking/16849?u=notplants
fn item for<'a> fn(&'a (dyn Animal + 'a)) {foo}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3188a7dba84d1c185cbf3ba876d84c7b
-
todo: try to make an example that demonstrates contravariance of functions, either using the above, or using and understanding the code in this example https://users.rust-lang.org/t/contravariance-and-borrow-checking/16849?u=notplants
-
todo: good article on variance here https://ehsanmkermani.com/2019/03/16/variance-in-rust-an-intuitive-explanation/
-
todo: try to get a better understanding of re-entrancy https://en.wikipedia.org/wiki/Reentrancy_(computing)
-
todo: get a phd in programming languages? or some other aspect of computing?
-
studied static dispatch (impl T) vs dynamic dyspatch (dyn T) https://chatgpt.com/share/6770a489-50e4-8002-96e8-eff86486b6c8 https://users.rust-lang.org/t/an-impl-trait-contained-in-a-slice-is-typed-differently/123184
12.29
- practicing with lifetimes https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e581c4c4cf315869922b1a297ead1973
1.1
-
Vec
puts its contents on the heap, while &[T] may be on the stack. from https://users.rust-lang.org/t/why-do-some-people-confound-t-with-stack-memory/123336 -
more explanation of async and Future The compiler translates the async fn into a function returning impl Future<Output = T>, where T is the return type of the async block.
-
studied support for recursion in async fn https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html#support-for-recursion-in-async-fn
-
studied compiler parallelism strategies. e.g. being able to compile a caller in parallel with its callee. using creates as the codegen limit. and other nuances. like a function exporting its metadata, that can be used by compilation by callers, before the function itself has been compiled. but also apparently sometimes the compiler does need to “look-ahead” into a function to some degree to figure out the type returned (unlike C). to see which variant of Future state machine it returns … although my understanding here is still a bit vague
cargo build --timings
can help visualized the dependency graph of compilation … so beautiful ! -
functions are contravariant but not function pointers While the type system variance rules might suggest this should work (because fn(T) -> U is contravariant with respect to T), Rust’s function pointers are invariant. This is because:
A function pointer fn(&T) must match exactly; Rust does not allow substituting one with another even if variance rules are satisfied. broken example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=68ec583c9aa22a3790f00af7280f8761 working example is still neede
- illustration of contravariance with functions https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8ba97d5ea81f30d28d1b0311a83666a2