Hello, I'm adding lifetime sugar to my sugar collections. But I'm confused which one is the most cleaner, easier to read, clear separation, doesn't convolute the code once there are many of them. I would like to hear your opinion
I realize that the tree structure contributes to the confusion after there are deep hierarchy type, like Result<Vec<HashMap<String, HashMap<String, i32>>>, Error. Thus combined with lifetime looks more convoluted. So what if it becomes linear flat, like Result<_, Error> | Vec | HashMap<String, _> | HashMap<String, _> | i32
Vec | i32 means Vec has i32
HashMap<String, _> | i32 means the _ is i32
Now updated the code, what do you think if the lifetime sugar combined with linear flat type like this?
Here is the list
NOTE :
- pseudocode, not the detail implementation
- it is to show what it looks like if in the case that needs multiple lifetime with nested (multi reference)
- what it looks like in case there is deep tree type
- what it looks like if combined with generic
- Scope = variable is dropped after this name. R! = macro of lifetime + reference (&'). Type is the last
#[fn(
scope : config, user, table
type :
T
U = Allocator + MyTrait
)]
fn proses_data(
cfg: R!(config, str),
user: R!(user, R!(config, str)),
table: R!(data,
HashMap<
R1!(config, str),
R1!(config, T)
>
),
complex: Result<_, Error> | R!(user, HashMap<String, _>) | R!(MaybeUninit<_>) | [_; 100] | U) -> R!(user, str) {
*user
}
- Declare scope name, and call them with / (breadcrumb). Lifetime on left, type on right
#[fn]
scope<config, user, data>
fn proses_data<T, U: Allocator + MyTrait>(
cfg: /config &str,
user: /user/config &&str,
table: /data &HashMap(/config &str, /config T),
complex: Result(_, Error) | /user &HashMap(String, _) | &MaybeUninit(_) | [_; 100] | U,
) -> /user str {
*user
}
- Almost same like before, except it is grouped with [..]
#[fn]
fn proses_data<T, U: Allocator + MyTrait>(
cfg: [config] &str,
user: [user, config] &&str,
table: [data] &HashMap<[config] &str, [config] T>,
complex: Result(_, Error) | [user] &HashMap(String, _) | &MaybeUninit(_) | [_; 100] | U,
) -> [user] &str {
*user
}
- Type remain clean, lifetime is defined in lifetime clause similar to where clause
#[fn]
fn proses_data<T, U: Allocator + MyTrait>(
cfg: &str,
user: &&str,
table: &HashMap<&str, T>,
complex: Result(_, Error) | &HashMap(String, _) | &MaybeUninit(_) | [_; 100] | U,
) -> &str
lifetime
cfg: config,
user: user config,
table: data<config, config>,
complex: Result<_, _> | user<_, _> | _ | _ | _,
return: user
{
*user
}
- Declare scope and the relationship cleanly at the top. Generic type on the last. Use scope with #, lifetime on the left, type on the right, every type with # means it's reference.
#[fn(
scope : config, user, table
type :
T
U = Allocator + MyTrait
)]
fn proses_data(
cfg: config#str,
user: user#config#str,
table: data#HashMap(config#str, config#T),
complex: Result(_, Error) | user#HashMap(String, _) | MaybeUninit | [_; 100] | U,
) -> user#str {
*user
}
Each of them represent this :
fn proses<'config, 'user, 'table, T, U>(
cfg: &'config str,
user: &'user &'config str,
table: &'data HashMap<&'config str, &'config T>,
complex: Result<Vec<HashMap<String, MaybeUninit<[U; 100]>>>, Error>) -> &'user str
where
U: Allocator + MyTrait
{
*user
}
I am also looking for a way to build extension to make can write Rust without ; similar like those in Typescript, Kotlin, Swift, Golang
I have idea like this
cargo-auto -> rewrite code with auto insert ; to different folder -> compile that one
But I am looking the method without rewriting if possible to prevent duplicated target folder. And does not trigger Rust analyzer IDE inline error show
Is there any?