You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note that both of these methods can be called with `&self` rather than `&mut self`.
13
13
14
-
# Motivation
14
+
##Motivation
15
15
16
-
Appending to a vector with a shared reference sounds unconventional, and it is. However, if we consider our vector as a bag of or a container of things rather than having a collective meaning; then, appending element or elements to the end of the vector:
17
-
* does not mutate any of already added elements, and hence,
18
-
***it is not different than creating a new element in the scope**.
16
+
Appending to a vector with a shared reference sounds unconventional, and it is.
19
17
20
-
# Safety
18
+
From another perspective, however, appending an element to the end of the vector does not mutate any of already added elements or change their positions. It can be argued that *it is not different than creating a new element within the scope*. This statement will be clear with the following example.
19
+
20
+
The challenge is to define a type-safe, recursive and expressive expression builder. In our toy example, an expression can either be a symbol, or addition or subtraction of two expressions. The final desired ergonomic solution is as follows:
21
+
22
+
```rust ignore
23
+
letscope=Scope::default();
24
+
25
+
// instantiate some symbols
26
+
letx=scope.symbol("x");
27
+
lety=scope.symbol("y");
28
+
assert_eq!(&x.to_string(), "x");
29
+
assert_eq!(&y.to_string(), "y");
30
+
31
+
// apply binary operations to create new symbols
32
+
letp=x+y;
33
+
assert_eq!(&p.to_string(), "x + y");
34
+
35
+
letq=x-y;
36
+
assert_eq!(&q.to_string(), "x - y");
37
+
38
+
// and further binary operations
39
+
lett=p+q;
40
+
assert_eq!(&t.to_string(), "x + y + x - y");
41
+
42
+
// we only use 'scope' to create symbols
43
+
// but in the background, all expressions are collected in our scope
This at first seemed **impossible in safe rust** for way too many reasons. However, it is conveniently possible using an `ImpVec`. You may run the example in [expressions.rs](https://github.com/orxfun/orx-imp-vec/blob/main/examples/expressions.rs) by `cargo run --example expressions`, or see the details of the implementation below.
It is natural to expect that appending elements to a vector does not affect already added elements. However, this is usually not the case due to underlying memory management. For instance, `std::vec::Vec` may move already added elements to different memory locations to maintain the contagious layout of the vector.
23
203
@@ -37,10 +217,10 @@ vec.push(4);
37
217
// assert_eq!(ref_to_first, &0);
38
218
```
39
219
40
-
This beloved feature of the borrow checker of rust is not required and used for `imp_push` and `imp_extend_from_slice` methods of `ImpVec` since these methods do not require a `&mut self` reference. Therefore, the following code compiles and runs perfectly safely.
220
+
This beloved feature of the borrow checker of rust is not required for `imp_push` and `imp_extend_from_slice` methods of `ImpVec` since these methods do not require a `&mut self` reference. Therefore, the following code compiles and runs perfectly safely.
0 commit comments