Is there a way to do a for loop that is neither iterative nor linear? - for-loop

Can I write a Rust for loop equivalent to this C code:
for(int i = 2; i <= 128; i=i*i){
//do something
}
I'm only seeing things like
for i in 0..128 { /* do something */ }
or
let v = vec![0, 1, 2, /* ... */ ];
for i in v.iter() { /* do something */ }
Should I just use a while loop?

You can always create a custom iterator that does whatever unique sequence you need:
struct Doubling {
current: u64,
max: u64,
}
impl Iterator for Doubling {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if self.current > self.max {
None
} else {
let v = Some(self.current);
self.current *= 2;
v
}
}
}
fn main() {
let iter = Doubling { current: 2, max: 128 };
let values: Vec<_> = iter.collect();
println!("{:?}", values);
}
It's important to recognize that this logic (like the original C!) has nasty edge cases when the value is doubled beyond the size of the type.
In this particular case, you can also recognize that you have an exponential series:
fn main() {
let iter = (1..8).map(|p| 2i32.pow(p));
let values: Vec<_> = iter.collect();
println!("{:?}", values);
}
If you want to get really experimental, check out Lazy sequence generation in Rust. Adapted here:
#![feature(generators, generator_trait, conservative_impl_trait)]
use std::ops::{Generator, GeneratorState};
fn doubling(mut start: u64, max: u64) -> impl Iterator<Item = u64> {
GeneratorIteratorAdapter(move || {
while start <= max {
yield start;
start *= 2;
}
})
}
fn main() {
let iter = doubling(2, 128);
let sum: Vec<_> = iter.collect();
println!("{:?}", sum);
}
/* copy-pasta */
struct GeneratorIteratorAdapter<G>(G);
impl<G> Iterator for GeneratorIteratorAdapter<G>
where
G: Generator<Return = ()>,
{
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
match self.0.resume() {
GeneratorState::Yielded(x) => Some(x),
GeneratorState::Complete(_) => None,
}
}
}

can I write a for loop equivalent to this C code:
That specifically, yes:
extern crate itertools;
for i in itertools::iterate(2, |&i| i*i).take_while(|&i| i <= 128) {
// do something
}
But in general, no. There is no single, direct equivalent to all possible uses of C's for loop. If there's no way to write it using iterators then yes, you need to use a more general loop form:
{
let mut i = 2;
while i <= 128 {
// do something
i = i*i;
}
}

Related

Building clean and flexible binary trees in Rust

I'm using binary trees to create a simple computation graph. I understand that linked lists are a pain in Rust, but it's a very convenient data structure for what I'm doing. I tried using Box and Rc<RefCell> for the children nodes, but it didn't work out how I wanted, so I used unsafe:
use std::ops::{Add, Mul};
#[derive(Debug, Copy, Clone)]
struct MyStruct {
value: i32,
lchild: Option<*mut MyStruct>,
rchild: Option<*mut MyStruct>,
}
impl MyStruct {
unsafe fn print_tree(&mut self, set_to_zero: bool) {
if set_to_zero {
self.value = 0;
}
println!("{:?}", self);
let mut nodes = vec![self.lchild, self.rchild];
while nodes.len() > 0 {
let child;
match nodes.pop() {
Some(popped_child) => child = popped_child.unwrap(),
None => continue,
}
if set_to_zero {
(*child).value = 0;
}
println!("{:?}", *child);
if !(*child).lchild.is_none() {
nodes.push((*child).lchild);
}
if !(*child).rchild.is_none() {
nodes.push((*child).rchild);
}
}
println!("");
}
}
impl Add for MyStruct {
type Output = Self;
fn add(self, other: Self) -> MyStruct {
MyStruct{
value: self.value + other.value,
lchild: Some(&self as *const _ as *mut _),
rchild: Some(&other as *const _ as *mut _),
}
}
}
impl Mul for MyStruct {
type Output = Self;
fn mul(self, other: Self) -> Self {
MyStruct{
value: self.value * other.value,
lchild: Some(&self as *const _ as *mut _),
rchild: Some(&other as *const _ as *mut _),
}
}
}
fn main() {
let mut tree: MyStruct;
{
let a = MyStruct{ value: 10, lchild: None, rchild: None };
let b = MyStruct{ value: 20, lchild: None, rchild: None };
let c = a + b;
println!("c.value: {}", c.value); // 30
let mut d = a + b;
println!("d.value: {}", d.value); // 30
d.value = 40;
println!("d.value: {}", d.value); // 40
let mut e = c * d;
println!("e.value: {}", e.value); // 1200
unsafe {
e.print_tree(false); // correct values
e.print_tree(true); // all zeros
e.print_tree(false); // all zeros, everything is set correctly
}
tree = e;
}
unsafe { tree.print_tree(false); } // same here, only zeros
}
Link to the playground
I honestly don't mind that much using unsafe, but is there a safe way doing it? How bad is the use of unsafe here?
You can just box both of the children, since you have a unidirectional tree:
use std::ops::{Add, Mul};
use std::fmt;
#[derive(Clone)]
struct MyStruct {
value: i32,
lchild: Option<Box<MyStruct>>,
rchild: Option<Box<MyStruct>>,
}
impl fmt::Debug for MyStruct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("MyStruct")
.field("value", &self.value)
.field("lchild", &self.lchild.as_deref())
.field("rchild", &self.rchild.as_deref())
.finish()
}
}
impl MyStruct {
fn print_tree(&mut self, set_to_zero: bool) {
if set_to_zero {
self.value = 0;
}
println!("MyStruct {{ value: {:?}, lchild: {:?}, rchild: {:?} }}", self.value, &self.lchild as *const _, &self.rchild as *const _);
if let Some(child) = &mut self.lchild {
child.print_tree(set_to_zero);
}
if let Some(child) = &mut self.rchild {
child.print_tree(set_to_zero);
}
}
}
impl Add for MyStruct {
type Output = Self;
fn add(self, other: Self) -> MyStruct {
MyStruct {
value: self.value + other.value,
lchild: Some(Box::new(self)),
rchild: Some(Box::new(other)),
}
}
}
impl Mul for MyStruct {
type Output = Self;
fn mul(self, other: Self) -> Self {
MyStruct {
value: self.value * other.value,
lchild: Some(Box::new(self)),
rchild: Some(Box::new(other)),
}
}
}
fn main() {
let tree = {
let a = MyStruct {
value: 10,
lchild: None,
rchild: None,
};
let b = MyStruct {
value: 20,
lchild: None,
rchild: None,
};
let c = a.clone() + b.clone();
println!("c.value: {}", c.value); // 30
let mut d = a.clone() + b.clone();
println!("d.value: {}", d.value); // 30
d.value = 40;
println!("d.value: {}", d.value); // 40
let mut e = c * d;
println!("e.value: {}", e.value); // 1200
println!("");
e.print_tree(false); // correct values
println!("");
e.print_tree(true); // all zeros
println!("");
e.print_tree(false); // all zeros, everything is set correctly
println!("");
e
};
dbg!(tree);
}
I implemented Debug manually and reimplemented print_tree recursively. I don't know if there is a way to implement print_tree as mutable like that without recursion, but it's certainly possible if you take &self instead (removing the set_to_zero stuff).
playground
Edit: Turns out it is possible to mutably iterate over the tree values without recursion. The following code is derived from the playground in this comment by #Shepmaster.
impl MyStruct {
fn zero_tree(&mut self) {
let mut node_stack = vec![self];
let mut value_stack = vec![];
// collect mutable references to each value
while let Some(MyStruct { value, lchild, rchild }) = node_stack.pop() {
value_stack.push(value);
if let Some(child) = lchild {
node_stack.push(child);
}
if let Some(child) = rchild {
node_stack.push(child);
}
}
// iterate over mutable references to values
for value in value_stack {
*value = 0;
}
}
}

strange process names when trying to get a PID in rust with the Windows api

Hello my goal is to create a rust function which takes a process name as string and returns a PID.
I came up with this function:
pub unsafe fn get_proc_id(proc_name: String) -> u32 {
let mut proc_id: u32 = 0;
let mut h_snap = windows::Win32::System::Diagnostics::ToolHelp::CreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS,
0,
);
let h_snap = match h_snap {
Ok(t) => t,
Err(e) => panic!("eror {}", e),
};
let mut proc_entry: PROCESSENTRY32 = PROCESSENTRY32 {
..PROCESSENTRY32::default()
};
proc_entry.dwSize = std::mem::size_of::<PROCESSENTRY32>() as u32;
let entry_ptr = &mut proc_entry as *mut PROCESSENTRY32;
if windows::Win32::System::Diagnostics::ToolHelp::Process32First(h_snap, entry_ptr).as_bool() {
loop {
let mut proc_exe_string: String = String::new();
if proc_exe_string.eq(&proc_name) {
proc_id = proc_entry.th32ProcessID;
break;
}
for e in proc_entry.szExeFile {
if e.0 != 0 {
proc_exe_string.push(e.0 as char)
}
}
println!("{}", proc_exe_string);
if !Process32Next(h_snap, entry_ptr).as_bool() {
break;
}
}
}
CloseHandle(h_snap);
return proc_id; }
The function prints some strange process names. for example I'm looking for "ac_client.exe" however the function shows this process as ac_client.exeexe.exeee and this is similar for most process names. some other examples:
chrome.exexeexe.exeee
Discord.exer.exee.exee

What's the idiomatic replacement for glsl output parameters in wgsl?

In glsl and hlsl, I can define a function like this:
float voronoi(vec2 x, out int2 cell) {
cell = ...
return ...
}
However, it doesn't seem like this is possible in wgsl.
What's the intended replacement for this? I guess I could define a VoronoiResult struct, but it seems overly boilerplate heavy:
struct VoronoiResult {
cell: vec2<i32>;
distance: f32;
};
fn voronoi(x: vec2<f32>) -> VoronoiResult {
// ...
var ret: VoronoiResult;
ret.distance = distance;
ret.cell = cell;
return ret;
}
The equivalent would be to use a pointer argument:
fn voronoi(x: vec2<f32>, cell: ptr<function, vec2<i32>>) -> f32 {
*cell = vec2(1, 2);
return 1.f;
}
#compute #workgroup_size(1)
fn main() {
var a: vec2<i32>;
var f = voronoi(vec2(1.f, 1.f), &a);
}
This produces the HLSL:
float voronoi(float2 x, inout int2 cell) {
cell = int2(1, 2);
return 1.0f;
}
[numthreads(1, 1, 1)]
void main() {
int2 a = int2(0, 0);
float f = voronoi((1.0f).xx, a);
return;
}
You can also make the struct version shorter by using the struct initializer:
struct Out {
cell: vec2<i32>,
val: f32,
}
fn voronoi(x: vec2<f32>) -> Out {
return Out(vec2(1, 2), 1.f);
}
#compute #workgroup_size(1)
fn main() {
var f = voronoi(vec2(1.f, 1.f));
}

Idiomatic way to create static iterable collection of named structs?

What is the idiomatic way to create static iterable collection of named structs? I have n instances of a struct, where n is known at compile time and is less than 20. I would like to be able to iterate over all the entries and also be able to refer to each entry by a name instead of an index. All the data is known at compile time.
I could use an array or enum, along with hand written constants which map the labels to indexes; but this seems finicky.
fn common_behaviour(x: f64) {
print!("{}", x);
}
const ADD: usize = 0;
const SUBTRACT: usize = 1;
fn main () {
let mut foos: [f64; 2] = [0.0; 2];
foos[ADD] = 4.0;
foos[SUBTRACT] = 2.0;
for foo in &foos {
common_behaviour(*foo);
}
foos[ADD] += 1.0;
foos[SUBTRACT] -= 1.0;
}
Alternatively, I could just pay the performance cost and use a HashMap as the hashing overhead might not actually matter that much, but this seems suboptimal as well.
Perhaps, I could refactor my code to use function pointers instead special casing the different special cases.
fn common_behaviour(x: f64) {
print!("{}", x);
}
fn add(x: f64) -> f64 {
x + 1.0
}
fn subtract(x: f64) -> f64 {
x - 1.0
}
struct Foo {
data: f64,
special: fn(f64) -> f64
}
impl Foo {
fn new(data: f64, special: fn(f64) -> f64) -> Foo {
Foo { data, special }
}
}
fn main() {
let mut foos = [Foo::new(4.0, add), Foo::new(2.0, subtract)];
for foo in &mut foos {
common_behaviour(foo.data);
foo.data = (foo.special)(foo.data);
}
}
What is most idiomatic way to handle this situation?
Looking at:
fn main() {
let mut foos = [Foo::new(4.0, add), Foo::new(2.0, subtract)];
for foo in &mut foos {
common_behaviour(foo.data);
foo.data = (foo.special)(foo.data);
}
}
I see a Command Pattern struggling to emerge, and Rust is great at expressing this pattern, thanks to enum:
enum Foo {
Add(f64),
Sub(f64),
}
impl Foo {
fn apply(&mut self) {
match self {
Foo::Add(x) => {
Self::common(*x);
*x += 1.0;
},
Foo::Sub(x) => {
Self::common(*x);
*x -= 1.0;
},
}
}
fn common(x: f64) {
print!("{}", x);
}
}
And your example becomes:
fn main() {
let mut foos = [Foo::Add(4.0), Foo::Sub(2.0)];
for foo in &mut foos {
foo.apply();
}
}

How do I check if a slice is sorted?

How do I check if a slice is sorted?
Assuming a function that accepts a slice of i32, is there an idiomatic Rust way of checking if the slice is sorted?
fn is_sorted(data: &[i32]) -> bool {
// ...
}
Would it be possible to generalize the above method so that it would accept an iterator?
fn is_sorted<I>(iter: I)
where
I: Iterator,
I::Item: Ord,
{
// ...
}
I'd grab pairs of elements and assert they are all in ascending (or descending, depending on what you mean by "sorted") order:
fn is_sorted<T>(data: &[T]) -> bool
where
T: Ord,
{
data.windows(2).all(|w| w[0] <= w[1])
}
fn main() {
assert!(is_sorted::<u8>(&[]));
assert!(is_sorted(&[1]));
assert!(is_sorted(&[1, 2, 3]));
assert!(is_sorted(&[1, 1, 1]));
assert!(!is_sorted(&[1, 3, 2]));
assert!(!is_sorted(&[3, 2, 1]));
}
Ditto for generic iterators:
extern crate itertools; // 0.7.8
use itertools::Itertools;
fn is_sorted<I>(data: I) -> bool
where
I: IntoIterator,
I::Item: Ord + Clone,
{
data.into_iter().tuple_windows().all(|(a, b)| a <= b)
}
fn main() {
assert!(is_sorted(&[] as &[u8]));
assert!(is_sorted(&[1]));
assert!(is_sorted(&[1, 2, 3]));
assert!(is_sorted(&[1, 1, 1]));
assert!(!is_sorted(&[1, 3, 2]));
assert!(!is_sorted(&[3, 2, 1]));
}
See also:
Are there equivalents to slice::chunks/windows for iterators to loop over pairs, triplets etc?
In nightly Rust, there are unstable methods to accomplish this:
slice::is_sorted
slice::is_sorted_by
slice::is_sorted_by_key
Iterator::is_sorted
Iterator::is_sorted_by
Iterator::is_sorted_by_key
It is not necessary to have Clone for an iterator is_sorted implementation. Here is a no-dependency Rust implementation of is_sorted:
fn is_sorted<I>(data: I) -> bool
where
I: IntoIterator,
I::Item: Ord,
{
let mut it = data.into_iter();
match it.next() {
None => true,
Some(first) => it.scan(first, |state, next| {
let cmp = *state <= next;
*state = next;
Some(cmp)
}).all(|b| b),
}
}
One more using try_fold():
pub fn is_sorted<T: IntoIterator>(t: T) -> bool
where
<T as IntoIterator>::Item: std::cmp::PartialOrd,
{
let mut iter = t.into_iter();
if let Some(first) = iter.next() {
iter.try_fold(first, |previous, current| {
if previous > current {
Err(())
} else {
Ok(current)
}
})
.is_ok()
} else {
true
}
}

Resources