使用extendr:Rust克隆R字符串后原变量仍被修改的原因
问题原因与解决办法
原因
你调用Strings::clone()后原R变量s仍被修改,核心问题在于extendr的clone()是对R字符向量的浅拷贝:它仅复制了向量的容器结构,但没有创建元素的独立副本。加上R的字符向量底层依赖全局字符串池的指针,用set_elt修改克隆对象时,会意外绕过R的写时复制机制,导致原向量的元素指针被修改。
解决方案
不要依赖clone(),手动构建全新的字符向量,彻底脱离原向量的引用:
#[extendr] fn strings_elt(x: Strings) -> Strings { x.iter() .enumerate() .map(|(i, s)| { if i == 0 { // 替换第一个元素为AAA "AAA".into() } else { // 保留其他元素(NA则返回NA_STRING) s.cloned().unwrap_or_else(|| NA_STRING.into()) } }) .collect() }
验证效果
运行修改后的代码:
library(rextendr) rust_source(code = ' #[extendr] fn strings_elt(x: Strings) -> Strings { x.iter() .enumerate() .map(|(i, s)| { if i == 0 { "AAA".into() } else { s.cloned().unwrap_or_else(|| NA_STRING.into()) } }) .collect() } ') s <- c("aaa", NA, "bbb") s1 <- strings_elt(s) s1 # 输出:"AAA" NA "bbb" s # 输出:"aaa" NA "bbb" 原变量未被修改
内容的提问来源于stack exchange,提问作者GL_Li
相关产品推荐
相关产品推荐

