2个版本
0.1.1 | 2022年7月9日 |
---|---|
0.1.0 | 2022年7月9日 |
#435 in 过程宏
21KB
284 行
执行evcxr
风格的Rust代码
更多evcxr
可以参考评估上下文、Jupyter 内核(针对Rust编程语言)或其支持的脚本式语法。
evcxr
风格的Rust代码示例
:dep image = "0.23"
:dep evcxr_image = "1.1"
// In a pure Rust project, the dependencies above would be specified in Cargo.toml
use evcxr_image::ImageDisplay;
image::ImageBuffer::from_fn(256, 256, |x, y| {
if (x as i32 - y as i32).abs() < 3 {
image::Rgb([0, 0, 255])
} else {
image::Rgb([0, 0, 0])
}
})
Jupyter Notebook的evcxr
内核示例
:dep execute_evcxr = { version = "0.1.2" }
use execute_evcxr::{execute_evcxr, Config};
// This way it's possible to specify the non-default values
let config = Config { verbose: false, ..Default::default() };
execute_evcxr(r#"
:dep nalgebra = "0.31.0"
:dep nalgebra_latex = { version = "0.1.6", features = ["lin_sys", "evcxr"] }
use nalgebra::{matrix, Const};
use nalgebra_latex::{
lin_sys::{
LinSys,
unknowns::SingleLetterBoldfaceVecOfUnknowns,
numbering::Numbering,
fmt::CasesLinSysFormatter,
},
fmt::EvcxrOutputFormatter,
};
use std::io::{stdout, Write};
let mut s = String::new();
let m = matrix!(
1,2,3;
4,5,6;
7,8,9;
);
let vec_of_unknowns = SingleLetterBoldfaceVecOfUnknowns::<_,{Numbering::OneBased}>::new('x', Const::<3>);
let ls = LinSys::new(m, vec_of_unknowns);
CasesLinSysFormatter::write_evcxr_output(&mut s, &ls).unwrap();
stdout().write_all(s.as_bytes()).unwrap();
"#, config);
Rust项目示例
extern crate execute_evcxr;
use execute_evcxr::{execute_evcxr, Config};
fn main() {
let config = Config { ..Config::default() };
execute_evcxr(r#"
:dep nalgebra = "0.31.0"
:dep nalgebra_latex = { version = "0.1.6", features = ["lin_sys", "evcxr"] }
use nalgebra::{matrix, Const};
use nalgebra_latex::{
lin_sys::{
LinSys,
unknowns::SingleLetterBoldfaceVecOfUnknowns,
numbering::Numbering,
fmt::CasesLinSysFormatter,
},
fmt::EvcxrOutputFormatter,
};
use std::io::{stdout, Write};
let mut s = String::new();
let m = matrix!(
1,2,3;
4,5,6;
7,8,9;
);
let vec_of_unknowns = SingleLetterBoldfaceVecOfUnknowns::<_,{Numbering::OneBased}>::new('x', Const::<3>);
let ls = LinSys::new(m, vec_of_unknowns);
CasesLinSysFormatter::write_evcxr_output(&mut s, &ls).unwrap();
stdout().write_all(s.as_bytes()).unwrap();
"#, config);
}
在撰写本文时,原始的evcxr
内核支持很多功能,但并非全部。这个crate作为一个临时的解决方案应运而生。
evcxr
风格Rust代码的注意事项
evcxr
内核支持的语法与纯Rust不同,是实现定义的。因此,同一个带有 evcxr
风格的脚本可能由 execute_evcxr
和 evcxr
本身以不同的方式执行。在出现差异的情况下,evcxr
的行为被视为正确,而 execute_evcxr
的偏差必须被视为一个错误,除非有其他说明。
关于限制
-
正如其名称所示,
execute_evcxr
并非与evcxr
一样的评估环境。它不会“返回”一个值。它通过字符串形式执行提供的脚本,而不是尝试评估它,这与evcxr
不同。 -
execute_evcxr
仅通过解析提供的脚本来完成工作。它不会分析crates依赖项的源代码。这一点将在后续文本中变得很重要。 -
由于
execute_evcxr
是一个临时解决方案,它不会尝试记忆脚本中定义了哪些宏以及它们将扩展到哪些语法实体。这一点将在后续文本中变得很重要。 -
execute_evcxr
通过解析带有evcxr
风格的Rust代码,在临时目录中构建一个 二进制crate,执行二进制crate并清理来工作。因此,它必须知道哪些语法实体(或更精确地说,“语句”)应该放在main()
函数中。这一点将在后续文本中变得很重要。 -
由于上述三个限制,开发者可能需要使用
#[expands_only_to_items]
属性来注释每个最终扩展到 “项目” 的宏调用。否则,它们将被放置在主函数中。幸运的是,最常见的宏通常不需要该属性,并且在许多情况下,即使宏在main()
中扩展到 “项目”,二进制crate仍然可以按预期工作。 -
脚本的执行速度受限于重新构建它们,包括从互联网下载依赖项。设置缓存可能是一个明智的选择。库作者尚未遇到缓存的需求。
对于库开发者
这是一个为库用户编写的README。还有一个单独的DEV-README.md,其中包含仅适用于库开发者的信息。
许可
根据您的选择,受Apache License,版本2.0或MIT许可证的许可。除非您明确说明,否则根据Apache-2.0许可证的定义,您有意提交以包含在本crate中的任何贡献,将如上双许可,没有任何附加条款或条件。
依赖关系
约1.5MB
约35K SLoC