#nalgebra #latex #matrix

execute_evcxr

通过构建和执行二进制crate来执行evcxr支持的语法库

2个版本

0.1.1 2022年7月9日
0.1.0 2022年7月9日

#435 in 过程宏


用于nalgebra_latex

MIT/Apache

21KB
284

crates.io crates.io

执行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 Notebookevcxr内核示例

: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_evcxrevcxr 本身以不同的方式执行。在出现差异的情况下,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.0MIT许可证的许可。
除非您明确说明,否则根据Apache-2.0许可证的定义,您有意提交以包含在本crate中的任何贡献,将如上双许可,没有任何附加条款或条件。

依赖关系

约1.5MB
约35K SLoC