Hello, friends. I hope you've had a great start to the new year. Apologies for asking a basic question.
I have two pieces of code that are quite similar, with only slight differences. However, in the second code snippet, I had to use Clone
to fix an error and make it work. While the code runs fine now, I don’t quite understand why this happens and when exactly I need to use Clone
. Additionally, I’m curious why Clone
wasn’t necessary in the first code snippet.
Code 1:
pub fn extend_hook_object_to_ast<'a>(
file_content: &str,
names: impl IntoIterator<Item = &'a str>,
allocator: &Allocator,
) -> Result<String, String> {
let mut parsed = source_to_ast(file_content, allocator)?;
if find_live_socket_node_from_ast(&parsed).is_err() {
return Err("liveSocket not found.".to_string());
}
let maybe_properties = get_properties(&mut parsed.program.body);
if let Some(properties) = maybe_properties {
let hooks_property = match find_hooks_property(properties) {
Some(prop) => prop,
None => {
let new_hooks_property = create_init_hooks(allocator);
properties.push(new_hooks_property);
get_property_by_key(properties.last_mut().unwrap(), "hooks").unwrap()
}
};
if let Expression::ObjectExpression(obj_expr) = hooks_property {
for name in names {
if !obj_expr.properties.iter().any(|x| match x {
ObjectPropertyKind::SpreadProperty(spread) => spread
.argument
.get_identifier_reference()
.map(|ref_id| ref_id.name == name)
.unwrap_or(false),
ObjectPropertyKind::ObjectProperty(normal) => normal
.value
.get_identifier_reference()
.map(|ref_id| ref_id.name == name)
.unwrap_or(false),
}) {
let new_property = create_and_import_object_into_hook(name, allocator);
obj_expr.properties.push(new_property);
}
}
}
} else {
return Err("properties not found in the AST.".to_string());
}
Ok(codegen(&parsed, false))
}
Code 2:
pub fn extend_var_object_property_by_names_to_ast<'a>(
file_content: &str,
var_name: &str,
object_names: impl IntoIterator<Item = &'a str> + Clone,
allocator: &Allocator,
) -> Result<String, String> {
let mut parsed = source_to_ast(file_content, allocator)?;
let result = parsed.program.body.iter_mut().find_map(|node| match node {
Statement::VariableDeclaration(var_decl) => var_decl
.declarations
.iter_mut()
.map(|decl| {
if decl.id.kind.get_binding_identifier().unwrap().name == var_name {
let get_init = &mut decl.init;
if let Some(Expression::ObjectExpression(obj_expr)) = get_init {
for name in object_names.clone() {
if !obj_expr.properties.iter().any(|x| match x {
ObjectPropertyKind::SpreadProperty(spread) => spread
.argument
.get_identifier_reference()
.map(|ref_id| ref_id.name == name)
.unwrap_or(false),
ObjectPropertyKind::ObjectProperty(normal) => normal
.value
.get_identifier_reference()
.map(|ref_id| ref_id.name == name)
.unwrap_or(false),
}) {
let new_property =
create_and_import_object_into_hook(name, allocator);
obj_expr.properties.push(new_property);
}
}
}
Ok(())
} else {
Err("Variable not found in javascript body".to_string())
}
})
.next(),
_ => None,
});
match result {
Some(Ok(_)) => Ok(codegen(&parsed, false)),
Some(Err(e)) => Err(e),
_ => Err("Variable not found in javascript body or javascript file is invalid".to_string()),
}
}
As you can see in the first code snippet, I used the input names: impl IntoIterator<Item = &'a str>
and called it in a for
loop without needing to use Clone
at all.
However, in the second code snippet, for the input object_names: impl IntoIterator<Item = &'a str> + Clone
, I had to explicitly use clone
in order to resolve the issue and make the code work.
Why it has this behaviour and how can use it inside code 2 without clone!
My next question is: Does using Clone here lead to higher resource consumption?
Thank you in advance