什么是条件求值的替代方法,如Rust const函数中的if或match?
我有一段代码,它根据环境名称读取config.toml文件,并为整个项目提供所有配置设置什么是条件求值的替代方法,如Rust const函数中的if或match?,rust,constants,Rust,Constants,我有一段代码,它根据环境名称读取config.toml文件,并为整个项目提供所有配置设置 const fn get_conf() -> toml::Value { let file_name = match env::var("ENVIRONMENT") { Ok(val) => val.to_lowercase(), Err(_e) => "development".to_lowercase(),
const fn get_conf() -> toml::Value {
let file_name = match env::var("ENVIRONMENT") {
Ok(val) => val.to_lowercase(),
Err(_e) => "development".to_lowercase(),
};
let content = fs::read_to_string(format!("conf/{}.toml", file_name)).unwrap();
let conf: Value = toml::from_str(content.as_str()).unwrap();
conf
}
static mut CONFIG: toml::Value = get_conf();
我得到一个错误:
错误[E0658]:`match`在`const fn中不允许出现`
-->src/lib.rs:2:21
|
2 |让文件名=匹配环境::变量(“环境”){
| _____________________^
3 | | Ok(val)=>val.to_小写(),
4 | | Err(_e)=>“development”,
5 | | };
| |_____^
|
=注:有关更多信息,请参阅第49146期
这在Rust nightly中得到了解决,但我不想在生产中使用nightly构建。在常量函数中使用匹配或if条件是否有任何解决方法?不可能使用带有稳定分支的
常量fn
。此外,您使用的不是常量fn,因此不能用于其他常量fn。我相信您的意思是,它在编译时而不是执行时检索环境变量
Fow现在一个可能的“解决方法”是,它有点笨拙但功能强大。采用该方法时,流程如下所示:
//build.rs
使用std::path::path;
使用std::env;
使用std::fs::File;
fn main(){
让path=path::new(env::var(“OUT_DIR”).unwrap().as_str()).join(“gen.rs”);
文件::创建(路径)
.expect(“gen.rs创建失败”)
.全部写(“”)
.expect(“gen文件写入失败”)
}
然后,您可以将生成的文件与直接文件一起使用,包括:
//main.rs或任何其他文件
包括!(concat!(env!(“OUT_DIR”),“/gen.rs”);
常量表达式中条件的主要替代方法是将布尔值转换为usize
s,并将其用作结果值数组的索引:
const fn demo(is_enabled: bool) -> i32 {
let choices = [
0, // false
42, // true
];
choices[is_enabled as usize]
}
这可以(痛苦地)扩展到越来越多的情况:
const fn sign(count: i32) -> i32 {
let is_pos = count > 0;
let is_zero = count == 0;
[[-1, 0], [1, 0]][is_pos as usize][is_zero as usize]
}
fn main() {
dbg!(sign(-2));
dbg!(sign(-0));
dbg!(sign(2));
}
另见:
对于您的实际用例,您应该只使用一个惰性全局值:
use once_cell::sync::Lazy; // 1.4.0
use std::{env, fs};
static mut CONFIG: Lazy<toml::Value> = Lazy::new(|| {
let file_name = match env::var("ENVIRONMENT") {
Ok(val) => val.to_lowercase(),
Err(_e) => "development".to_lowercase(),
};
let content = fs::read_to_string(format!("conf/{}.toml", file_name)).unwrap();
toml::from_str(content.as_str()).unwrap()
});
use once_cell::sync::Lazy;//1.4.0
使用std::{env,fs};
静态mut配置:Lazy=Lazy::new(| |){
让file_name=match env::var(“环境”){
Ok(val)=>val.to_小写(),
Err(_e)=>“development”。to_小写(),
};
让content=fs::read_to_string(format!(“conf/{}.toml”,文件名)).unwrap();
toml::from_str(content.as_str()).unwrap()
});
另见:
const fn
中使用
常数fn改进
您现在可以在const中使用几个核心语言特性
fn:
你好我也不能让它每晚运行:。此外,我怀疑是否可以分别读取
常量fn
中的环境变量。提供有意义的结果。您确定想要一个常量fn
,还是只想找一些东西来初始化配置
?如果是这样,lazy\u static
可能会对您有所帮助。Const函数在编译时执行,因此如果它起作用,将完全冻结您的配置,就像编译软件时一样,这看起来不像配置文件的正常使用。正如@phimuemue所说,您确定它不是您想要的lazy\u static
,这样在初始化软件时配置文件只读取一次吗?lazy\u static似乎是一个很好的解决方案,但当我运行lazy\u static时!{pub static CONFIG:Value=get_conf();},它会给我错误“宏调用中不需要此令牌的任何规则”和“match
在const fn
中是不允许的”env但是,如果没有envvar,code>将无法编译,因此要么没有要处理的故障模式,要么需要使用选项\u env代码>(但同样的问题是const fns当前无法执行条件)。代码编译良好,但在调试CLion获取配置值时“-var create:无法创建变量对象”。
if, if let, and match
while, while let, and loop
the && and || operators