在 Rust 中处理所谓的全局变量
Dealing with so-called global variables in Rust
我们都知道使用全局变量会导致细微的错误。我需要将 Python 程序迁移到 Rust,尽可能保持算法完整。一旦我展示了 Python-Rust 等价性,将有机会调试和更改逻辑以更好地适应 Rust。这是一个使用全局变量的简单 Python 程序,后面是我不成功的 Rust 版本。
# global variable
a = 15
# function to perform addition
def add():
global a
a += 100
# function to perform subtraction
def subtract():
global a
a -= 100
# Using a global through functions
print("Initial value of a = ", a)
add()
print("a after addition = ", a)
subtract()
print("a after subtraction = ", a)
这是一个运行的 Rust 程序,但我无法获取闭包来更新所谓的全局变量。
fn fmain() {
// global variable
let mut a = 15;
// perform addition
let add = || {
let mut _name = a;
// name += 100; // the program won't compile if this is uncommented
};
call_once(add);
// perform subtraction
let subtract = || {
let mut _name = a;
// name -= 100; // the program won't compile if this is uncommented
};
call_once(subtract);
// Using a global through functions
println!("Initial value of a = {}", a);
add();
println!("a after addition = {}", a);
subtract();
println!("a after subtraction = {}", a);
}
fn main() {
fmain();
}
fn call_once<F>(f: F)
where
F: FnOnce(),
{
f();
}
我的要求:在 Rust 中重新创建 Python 逻辑。
你的 Rust 代码没有使用全局变量,a
变量是堆栈分配的。虽然 Rust 并不特别支持全局变量,但您当然可以使用它们。转换为使用实际全局变量的 Rust,您的程序将如下所示:
use lazy_static::lazy_static;
use parking_lot::Mutex; // or std::sync::Mutex
// global variable
lazy_static! {
static ref A: Mutex<u32> = Mutex::new(15);
}
// function to perform addition
fn add() {
*A.lock() += 100;
}
// function to perform subtraction
fn subtract() {
*A.lock() -= 100;
}
fn main() {
// Using a global through functions
println!("Initial value of a = {}", A.lock());
add();
println!("a after addition = {}", A.lock());
subtract();
println!("a after subtraction = {}", A.lock());
}
如果您更喜欢使用闭包,您也可以这样做,但您需要使用内部可变性来允许多个闭包捕获相同的环境。例如,您可以使用 Cell
:
use std::cell::Cell;
fn main() {
let a = Cell::new(15);
let add = || {
a.set(a.get() + 100);
};
let subtract = || {
a.set(a.get() - 100);
};
// Using a global through functions
println!("Initial value of a = {}", a.get());
add();
println!("a after addition = {}", a.get());
subtract();
println!("a after subtraction = {}", a.get());
}
无依赖性示例 enum
和 function
。编辑:根据评论中的建议改进了代码并更正了匹配臂。
use std::sync::{Arc, Mutex, Once};
static START: Once = Once::new();
static mut ARCMUT: Vec<Arc<Mutex<i32>>> = Vec::new();
// 作为枚举
enum Operation {
Add,
Subtract,
}
impl Operation {
// static change
fn result(self) -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlock = arc_clone.lock().unwrap();
match self {
Operation::Add => *unlock += 100,
Operation::Subtract => *unlock -= 100,
}
*unlock
}
// dynamic change
fn amount(self, amount: i32) -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlock = arc_clone.lock().unwrap();
match self {
Operation::Add => *unlock += amount,
Operation::Subtract => *unlock -= amount,
}
*unlock
}
}
// 作为函数
fn add() -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlcok = arc_clone.lock().unwrap();
*unlcok += 100;
*unlcok
}
//作为特征
trait OperationTrait {
fn add(self) -> Self;
fn subtract(self) -> Self;
fn return_value(self) ->i32;
}
impl OperationTrait for i32 {
fn add(mut self) -> Self {
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock += self;
self
}
fn subtract(mut self) -> Self {
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock -= self;
self
}
fn return_value(self)->Self{
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock
}
}
// fn main
fn main() {
START.call_once(|| unsafe {
ARCMUT = vec![Arc::new(Mutex::new(15))];
});
let test = Operation::Add.result();
println!("{:?}", test);
let test = Operation::Subtract.amount(100);
println!("{:?}", test);
let test = add();
println!("{:?}", test);
let test = 4000.add();
println!("{:?}", test);
}
我们都知道使用全局变量会导致细微的错误。我需要将 Python 程序迁移到 Rust,尽可能保持算法完整。一旦我展示了 Python-Rust 等价性,将有机会调试和更改逻辑以更好地适应 Rust。这是一个使用全局变量的简单 Python 程序,后面是我不成功的 Rust 版本。
# global variable
a = 15
# function to perform addition
def add():
global a
a += 100
# function to perform subtraction
def subtract():
global a
a -= 100
# Using a global through functions
print("Initial value of a = ", a)
add()
print("a after addition = ", a)
subtract()
print("a after subtraction = ", a)
这是一个运行的 Rust 程序,但我无法获取闭包来更新所谓的全局变量。
fn fmain() {
// global variable
let mut a = 15;
// perform addition
let add = || {
let mut _name = a;
// name += 100; // the program won't compile if this is uncommented
};
call_once(add);
// perform subtraction
let subtract = || {
let mut _name = a;
// name -= 100; // the program won't compile if this is uncommented
};
call_once(subtract);
// Using a global through functions
println!("Initial value of a = {}", a);
add();
println!("a after addition = {}", a);
subtract();
println!("a after subtraction = {}", a);
}
fn main() {
fmain();
}
fn call_once<F>(f: F)
where
F: FnOnce(),
{
f();
}
我的要求:在 Rust 中重新创建 Python 逻辑。
你的 Rust 代码没有使用全局变量,a
变量是堆栈分配的。虽然 Rust 并不特别支持全局变量,但您当然可以使用它们。转换为使用实际全局变量的 Rust,您的程序将如下所示:
use lazy_static::lazy_static;
use parking_lot::Mutex; // or std::sync::Mutex
// global variable
lazy_static! {
static ref A: Mutex<u32> = Mutex::new(15);
}
// function to perform addition
fn add() {
*A.lock() += 100;
}
// function to perform subtraction
fn subtract() {
*A.lock() -= 100;
}
fn main() {
// Using a global through functions
println!("Initial value of a = {}", A.lock());
add();
println!("a after addition = {}", A.lock());
subtract();
println!("a after subtraction = {}", A.lock());
}
如果您更喜欢使用闭包,您也可以这样做,但您需要使用内部可变性来允许多个闭包捕获相同的环境。例如,您可以使用 Cell
:
use std::cell::Cell;
fn main() {
let a = Cell::new(15);
let add = || {
a.set(a.get() + 100);
};
let subtract = || {
a.set(a.get() - 100);
};
// Using a global through functions
println!("Initial value of a = {}", a.get());
add();
println!("a after addition = {}", a.get());
subtract();
println!("a after subtraction = {}", a.get());
}
无依赖性示例 enum
和 function
。编辑:根据评论中的建议改进了代码并更正了匹配臂。
use std::sync::{Arc, Mutex, Once};
static START: Once = Once::new();
static mut ARCMUT: Vec<Arc<Mutex<i32>>> = Vec::new();
// 作为枚举
enum Operation {
Add,
Subtract,
}
impl Operation {
// static change
fn result(self) -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlock = arc_clone.lock().unwrap();
match self {
Operation::Add => *unlock += 100,
Operation::Subtract => *unlock -= 100,
}
*unlock
}
// dynamic change
fn amount(self, amount: i32) -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlock = arc_clone.lock().unwrap();
match self {
Operation::Add => *unlock += amount,
Operation::Subtract => *unlock -= amount,
}
*unlock
}
}
// 作为函数
fn add() -> i32 {
let mut arc_clone = unsafe { ARCMUT[0].clone() };
let mut unlcok = arc_clone.lock().unwrap();
*unlcok += 100;
*unlcok
}
//作为特征
trait OperationTrait {
fn add(self) -> Self;
fn subtract(self) -> Self;
fn return_value(self) ->i32;
}
impl OperationTrait for i32 {
fn add(mut self) -> Self {
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock += self;
self
}
fn subtract(mut self) -> Self {
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock -= self;
self
}
fn return_value(self)->Self{
let arc_clone = unsafe{ARCMUT[0].clone()};
let mut unlock = arc_clone.lock().unwrap();
*unlock
}
}
// fn main
fn main() {
START.call_once(|| unsafe {
ARCMUT = vec![Arc::new(Mutex::new(15))];
});
let test = Operation::Add.result();
println!("{:?}", test);
let test = Operation::Subtract.amount(100);
println!("{:?}", test);
let test = add();
println!("{:?}", test);
let test = 4000.add();
println!("{:?}", test);
}